Classes to use MOT file in MATLAB to move model and analyse actuators
Posted: Tue Aug 22, 2023 7:28 am
Dear experts,
I am not able to understand the methods and classes to use a MOT file (generated from MoCap data applied to an OpenSim model) to a different model (same base model, but with different actuators etc.). I tried to have the MOT file into a STO object, and access the data as StateVectors etc., but could not find how to do the same. I have ended up treating the MOT file as a txt file and then iterating over the coordinates and setting values. Could someone please help me with how to use some OpenSim API functions/classes instead of using nested loops (code below).
Secondly, just to improve my understanding - as I was looking to just assign the coordinate values to the bodies to see how the body was moving (and potentially how cable actuators would behave), I did not need muscles etc. However, even after removing the muscles, if I don't use the following line: model.equilibrateMuscles(state)
I get the following error (why would that be ?)
Error:
Regards,
Rejin
Code:
I am not able to understand the methods and classes to use a MOT file (generated from MoCap data applied to an OpenSim model) to a different model (same base model, but with different actuators etc.). I tried to have the MOT file into a STO object, and access the data as StateVectors etc., but could not find how to do the same. I have ended up treating the MOT file as a txt file and then iterating over the coordinates and setting values. Could someone please help me with how to use some OpenSim API functions/classes instead of using nested loops (code below).
Secondly, just to improve my understanding - as I was looking to just assign the coordinate values to the bodies to see how the body was moving (and potentially how cable actuators would behave), I did not need muscles etc. However, even after removing the muscles, if I don't use the following line: model.equilibrateMuscles(state)
I get the following error (why would that be ?)
Error:
Code: Select all
Error using torsoStabiliserOpenSimSimulation
Java exception occurred:
java.lang.RuntimeException: SimTK Exception thrown at State.cpp:974:
Error detected by Simbody method getCacheEntry: State Cache entry was out of date at Stage Time.
This entry depends on version 1 of Stage Instance but was last updated at version 0.
(Required condition 'version == m_dependsOnVersionWhenLastComputed' was not met.)
at org.opensim.modeling.opensimSimulationJNI.Point_calcDistanceBetween__SWIG_1(Native Method)
at org.opensim.modeling.Point.calcDistanceBetween(Point.java:153)
Regards,
Rejin
Code:
Code: Select all
clc
clear
%% Initialization
% import Opensim classes
org.opensim.modeling.opensimCommon.GetVersion()
import org.opensim.modeling.*
basefilename = 'Model_9x10_Wheelchair_2';
modfilename = strcat(basefilename, ...
datestr(now,'_ddmmyy_HHMM'),'.osim');
% Load model and get model components
model = Model(strcat(basefilename,'.osim'));
% Load MOT file
motData = readtable('Limit01_9x10.mot','FileType','text');
timeVec = motData.time;
coordinateDataMatrix = motData{:,2:end};
% Initialize the sytem
state = model.initSystem();
bodySet = model.getBodySet();
numBodies = bodySet.getSize();
coordinateSet = model.getCoordinateSet();
numCoordinates = coordinateSet.getSize();
forceSet = model.getForceSet();
numForces = forceSet.getSize();
markerSet = model.getMarkerSet();
numMarkers = markerSet.getSize();
%% Get relevant marker info
for i = 1:numMarkers
tempMarker = markerSet.get(i-1);
tempMarkerName(i) = tempMarker.getName();
fprintf("Marker Name: %i: %s \n",i-1,tempMarkerName(i));
if strcmp(tempMarkerName(i),'T2_4')
T2_4_Marker = tempMarker;
T2_4_Marker.set_fixed(true);
T2_4_MarkerLoc = tempMarker.get_location();
elseif strcmp(tempMarkerName(i),'T2_8')
T2_8_Marker = tempMarker;
T2_8_Marker.set_fixed(true);
T2_8_MarkerLoc = tempMarker.get_location();
elseif strcmp(tempMarkerName(i),'wheelchair1')
wheelchair1Marker = tempMarker;
wheelchair1Marker.set_fixed(true);
wheelchair1MarkerLoc = tempMarker.get_location();
elseif strcmp(tempMarkerName(i),'wheelchair3')
wheelchair3Marker = tempMarker;
wheelchair3Marker.set_fixed(true);
wheelchair3MarkerLoc = tempMarker.get_location();
end
end
scapula_R = model.getBodySet().get('scapula_R');
scapula_L = model.getBodySet().get('scapula_L');
ground = model.getGround();
pathSpring1_restingLength = wheelchair1Marker.calcDistanceBetween(state,scapula_L,T2_8_Marker.get_location());
fprintf('Path Spring 1 Resting Length:%.04f \n',pathSpring1_restingLength)
pathSpring2_restingLength = wheelchair3Marker.calcDistanceBetween(state,scapula_R,T2_4_Marker.get_location());
fprintf('Path Spring 2 Resting Length:%.04f \n',pathSpring2_restingLength)
%% Remove all muscles
% Get the MuscleSet
muscleSet = model.getMuscles();
% Number of muscles in the model
numMuscles = muscleSet.getSize();
% Iterate through all the muscles and remove them
for i = numMuscles+1:-1:1 % Start from the last muscle; OpenSim uses 0-indexing
% Remove the muscle from the model
model.updForceSet().remove(i-1);
end
%% Add Actuator between markers
% syringe actuator specs
% L_ser = 0.015; L_syr = 0.018; k_ser = 400; gearing = 1/2.25;
% get syringe actuator force as a function of displacement (x)
% syringeActuatorFunc = @(x) syringeActuator_simplified2(x,[L_ser L_syr k_ser gearing]);
% d = linspace(0,(L_ser+L_syr)*gearing,1000);
% syringeActForce = syringeActuatorFunc(d);
% plot(d,syringeActForce)
% Create Path Actuator between selected marker locations
actuator1 = PathSpring();
actuator1.setName('Actuator1');
% Set the location of the first point in the tibia frame. These numbers
% were determined from placing a marker on the desired location in the GUI.
actuator1.getGeometryPath().appendNewPathPoint('wheelchairLoc1',ground,wheelchair1MarkerLoc);
% Set the locaton of the second point in the Calcn frame
actuator1.getGeometryPath().appendNewPathPoint('scapulaL_Loc', scapula_L,T2_8_MarkerLoc);
% Create Path Actuator between selected marker locations
actuator2 = PathSpring();
actuator2.setName('Actuator2');
% Set the location of the first point in the tibia frame. These numbers
% were determined from placing a marker on the desired location in the GUI.
actuator2.getGeometryPath().appendNewPathPoint('wheelchairLoc3',ground,wheelchair3MarkerLoc);
% Set the locaton of the second point in the Calcn frame
actuator2.getGeometryPath().appendNewPathPoint('scapulaR_Loc', scapula_R,T2_4_MarkerLoc);
% actuator1 - Path Spring Characteristics
actuator1.setStiffness(0);
actuator1.setDissipation(0);
actuator1.setRestingLength(pathSpring1_restingLength);
% actuator2 - Path Spring Characteristics
actuator2.setStiffness(0);
actuator2.setDissipation(0);
actuator2.setRestingLength(pathSpring2_restingLength);
% Add the force to the model
model.addForce(actuator1);
model.addForce(actuator2);
model.finalizeConnections();
% print model - save as new file
model.print(modfilename)
%% Traverse MOT File kinematics
% get number of timesteps
numTimesteps = length(timeVec);
model.setUseVisualizer(false);
% Re-initialise system
state = model.initSystem();
% iterate over time
for i = 1:numTimesteps
% iterate over model coordinates
for j = 1:numCoordinates
currCoord = coordinateSet.get(j-1);
currCoord.setValue(state,coordinateDataMatrix(i,j),false);
end
% model.equilibrateMuscles(state);
L_pathSpring1_a(i) = wheelchair1Marker.calcDistanceBetween(state,scapula_L,T2_8_Marker.get_location());
L_pathSpring1_b(i) = actuator1.getLength(state);
L_pathSpring2_a(i) = wheelchair3Marker.calcDistanceBetween(state,scapula_R,T2_4_Marker.get_location());
L_pathSpring2_b(i) = actuator2.getLength(state);
% fprintf('Time: %03f \n',timeVec(i))
fprintf('Time: %03f Path Spring 1 Length: %.04f %.04f Path Spring 2 Length: %.04f %.04f \n',...
timeVec(i),L_pathSpring1_a(i),L_pathSpring1_b(i),...
L_pathSpring2_a(i),L_pathSpring2_b(i));
end
%% Save Data
save('ModelOpenSim_wActuators.mat')