Page 1 of 1

API computation of muscle moment arms of the scapulothoracic model

Posted: Mon May 30, 2022 6:38 am
by gudrun
Dear Opensim community,

I am working with a colleague on the scapulothoracic model (Seth et al., 2019) and we would like to automatize the computation of muscle moment arms (MMA) over time for several motion trials. We use the MATLAB API. To do that, we would like to wrote a for loop that set the model in the position indicated by the k line of an input IK file, then compute the MMA of the muscles of the model in that position, and continue the loop.

However, before starting the code, we checked the feasibility with the angular values of the first line of our IK file. We set manually the values, realize the position and then display the values of the same degrees of freedom for verification (like in the following code). Because of the AC constraint of the model, the displayed values for sternoclavicular and scapulothoracic joints are different from the values we entered (to ensure the contact between scapula and clavicle, some positions are not achievable by the model). But, these values are from an IK file, so the model should be able to achieve it.

Code: Select all

import org.opensim.modeling.*

%% Import plugin scapulothoracic joint
Model.LoadOpenSimLibrary('C:\OpenSim 4.1\plugins\ScapulothoracicJointPlugin40_WinX64');

%% setup files
model = Model('path\model.osim');
state = model.initSystem(); 
model.initSystem();

%% change joint values
model.getJointSet().get('sternoclavicular').get_coordinates(0).setValue(state, 0.1723);
model.getJointSet().get('sternoclavicular').get_coordinates(1).setValue(state, 0.1323); 
model.getJointSet().get('scapulothoracic').get_coordinates(0).setValue(state, 0.6005); 
model.getJointSet().get('scapulothoracic').get_coordinates(1).setValue(state, 0.0385); 
model.getJointSet().get('scapulothoracic').get_coordinates(2).setValue(state, 0.3747); 
model.getJointSet().get('scapulothoracic').get_coordinates(3).setValue(state, -0.0470); 
model.getJointSet().get('GlenoHumeral').get_coordinates(0).setValue(state, 0.5133);

%% applied new position
model.realizePosition(state);

%% Verification 
disp(model.getJointSet().get('sternoclavicular').get_coordinates(0).getValue(state));
disp(model.getJointSet().get('sternoclavicular').get_coordinates(1).getValue(state));
disp(model.getJointSet().get('scapulothoracic').get_coordinates(0).getValue(state));
disp(model.getJointSet().get('scapulothoracic').get_coordinates(1).getValue(state));
disp(model.getJointSet().get('scapulothoracic').get_coordinates(2).getValue(state));
disp(model.getJointSet().get('scapulothoracic').get_coordinates(3).getValue(state));
disp(model.getJointSet().get('GlenoHumeral').get_coordinates(0).getValue(state));

%% Verification - plot MMA
clav_prot = model.getJointSet().get('sternoclavicular').get_coordinates(0);
model.getMuscles().get('TrapeziusClavicle_S').computeMomentArm(state,clav_prot);


Then, we tried to use the model without AC constraint: using the same IK file, we unlock the constraint by adding this line

Code: Select all

 model.getConstraintSet().get('AC').set_isEnforced(0); 
before

Code: Select all

 state = model.initSystem();
. Now the DoF values respect the IK file, but the computed MMA are completely different from the values we plotted with the GUI for the model with the constraint (some are even zero, probably because the skeletal chain is now open).

Did we make a mistake somewhere? Is there a way to fix this? Or should we change the method of computing MMA?

Many thanks in advance,
Best regards,

Alicia Blasi-Toccacceli

Re: API computation of muscle moment arms of the scapulothoracic model

Posted: Mon May 30, 2022 10:55 am
by tkuchida
It looks like you are using the Coordinate::setValue() method with the default third argument. Please see the documentation here: https://simtk.org/api_docs/opensim/api_ ... f2e88d7c42. You should pass "False" for the third argument when setting all Coordinates except the last one so that you don't project the model onto the constraint manifold after each Coordinate is set (i.e. when the model is in an "intermediate" configuration). Alternatively, you can use "False" as the third argument for all setValue() calls and then call Model::assemble() when all Coordinates have been set.