tldr: I'm trying to use setExternalLoads to apply an external load but cannot get it to work.
I am trying to perform a forward dynamic batch process which uses different experimental data in each iteration. Normally when applying an external load in a forward dynamics simulation I would create an ExternalLoad.xml file and add it to the forward tool using the setExternalLoadsFileName() command. I have run a single simulation in this way and it works.
As I am performing a batch process I was hoping to avoid creating and loading a new ExternalLoad.xml file for each iteration by defining the external loads within the MatLab code and adding it directly to the forward tool using the setExternalLoads() command. However I have not been able to get this to work. It has not been applying any external loads. I have compared the results from the simulations using the setExternalLoads() command to simulations without any external loads so the only force present is the body weights and the results (from point kinematics measuring the motion of the bodies and the body kinematics) are identical.
I have check that the external load is correct by printing it out as an .xml file and applying it using the setExternalLoadsFileName() command, the simulation runs and applied the external load. I clear the external load, external force, forward tool, model, point kinematics, and body kinematics on each iteration and have placed initSystem after applying the external loads (as suggested here viewtopicPhpbb.php?f=91&t=4025&p=0&star ... a0191b8fc8 for inverse dynamics).
Below is the code for the batch process, this is part of a larger code which prepares the experimental data and specifies some file paths (such as path2mot), I am confident paths are not the problem as the code runs and outputs all the files to the correct places. Appologies for the length of the code but not knowing where the problem is I wanted to share it all:
Code: Select all
for i= 1:no_data_set
%% ===================== Call files and folders ======================== %%
% ----------- Specify results file for current iteration
data_set_no = sprintf('_%d',i);
results_folder_current = append(results_folder_base, data_set_no); % create a name for folder which will contain results for current iteration
mkdir([path2mot results_folder_4_batch results_folder_current{1}]) % create folder for results of current iteration
% ----------- Load relevant .mot file
file_no = sprintf('_%d',i);
CurrentMotFile = [path2mot results_folder_4_batch NameNoExt file_no '.mot']; % path to .mot file
[~, CurrentMotFileName, extension] = fileparts(CurrentMotFile); % Create the storage object from the input .mot file
CurrentMotStor = STOFileAdapter().read(CurrentMotFile);
% get labels from mot file
MotTableLabels = CurrentMotStor.getColumnLabels;
forceslabels = cell(CurrentMotStor.getNumColumns(),1);
for i = 0 : CurrentMotStor.getNumColumns() -1
forceslabels{i+1,1} = char(MotTableLabels.get(i));
end
%% ========================== OpenSim Model ============================ %%
% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %
% Load a model
% path to model defined outside of loop
myModel = Model(path2model);
% initiate model
myModel.initSystem();
% ------------------ Get various model components ---------------------- %
% ------------------------- Bodies
bodySet = myModel.getBodySet();
nBodies = bodySet.getSize;
% ------------------------- Joints
jointSet = myModel.getJointSet();
nJoints = jointSet.getSize;
% ------------------------- Muscles
muscSet = myModel.getMuscles();
nMuscles = muscSet.getSize;
% nameMusc = myModel.getStateVariableNames();
% ------------------------- Ground
gnd = myModel.getGround();
% ------------------------- Actuators
actSet = myModel.getActuators();
nact = actSet.getSize;
% ------------------------- Forces
forceSet = myModel.getForceSet();
%
%% ===================== Set External Loads ======================== %%
% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %
% define application of external loads
LowpassFilt = -1;
% ---------------- External force
%
% externalforce placed within externalload,
extforce = ExternalForce();
extforce.setName(CurrentMotFileName);
% Identify force and point columns
forceIDIndex = find( contains(forceslabels,'_vx'));
pointIDIndex = find( contains(forceslabels,'_px'));
%
extforce.set_applied_to_body('top_pot');
extforce.set_force_expressed_in_body('ground');
extforce.set_point_expressed_in_body('ground');
extforce.set_force_identifier(strrep(forceslabels{forceIDIndex},'x',''));
extforce.set_point_identifier(strrep(forceslabels{pointIDIndex},'x',''));
%
% ---------------- External load
%
extload = ExternalLoads();
extload.setName(CurrentMotFileName);
extload.setDataFileName(CurrentMotFile); % provide path to .mot file
extload.cloneAndAppend(extforce); % add the external force to the external load
extload.setLowpassCutoffFrequencyForLoadKinematics(LowpassFilt);
% Create external load xml file
extLoadsXml = [CurrentMotFileName '_' 'external_loads.xml'];
% Print the external load xml file
extload.print([path2mot results_folder_4_batch results_folder_current{1} '\' extLoadsXml]); % must go into an already existing folder
%
%
%% ------------- Set-up of ForwardTool through Matlab -------------- %%
%
% setup options
errorTol = 1.0000000000000001e-05;
maxIntergratorSteps = 20000;
minStepSize = 1e-08;
maxStepSize = 1;
outputPrecision = 8;
timeStart = 0;
timeEnd = 1.24;
% Apply to forward tool
ft = ForwardTool();
ft.setName(['set-up_' CurrentMotFileName]); % name of forward tool
ft.setModel(myModel); % model
ft.setModelFilename([char(myModel.getName) '_' CurrentMotFileName]); % name model
ft.setReplaceForceSet(0) % specified force sets are appended
% apply set up options
ft.setStartTime(timeStart);
ft.setFinalTime(timeEnd);
ft.setErrorTolerance(errorTol);
ft.setMaximumNumberOfSteps(maxIntergratorSteps);
ft.setMinDT(minStepSize);
ft.setMaxDT(maxStepSize);
ft.setOutputPrecision(outputPrecision);
ft.setSolveForEquilibrium(0); % very important when muscles are involved
% set the external load of the current loop, this should make no
% difference as there are no muscles in the model, simulations have
% shown this is the case
ft.setExternalLoads(extload);
% specify output directory
ft.setResultsDir([path2mot results_folder_4_batch results_folder_current{1}]) % folder for results, it will be automatically created MotFilePath results_folder_4_batch
% print out .xml file of forward tool
FT_SetUp_Xml = [CurrentMotFileName '_' 'SetUp.xml'];
ft.print([path2mot results_folder_4_batch results_folder_current{1} '\' FT_SetUp_Xml]); % Write this Object into an XML file of the given name
%
% ----------------
%
%% ---------------------- Prepare Analysis ------------------------- %%
% Necessary to define the analysis
%
% ------------------------- Add point kinematics analysis
%
% Add analysis for a point in L3
pk1 = PointKinematics();
myModel.addAnalysis(pk1);
pk1.setInDegrees(1)
pk1.setBody(bodySet.get(1));
pk1.setRelativeToBody(gnd)
pk1.setPointName('centre_of_DIC_point_L3')
pk1.setPoint(Vec3(-0.0395074751100576,0.0471332730104978,0.00651529708770742));
% Add analysis for a point in L2
pk2 = PointKinematics();
myModel.addAnalysis(pk2);
pk2.setInDegrees(1)
pk2.setBody(bodySet.get(2));
pk2.setRelativeToBody(gnd)
pk2.setPointName('centre_of_DIC_point_L2')
pk2.setPoint(Vec3(-0.0436541829436566,0.0862211168263703,0.0112360325795324));
%
% ------------------------- Add body kinematics
bk = BodyKinematics();
bk.setModel(myModel)
bk.setInDegrees(1)
bk.setExpressResultsInLocalFrame(1);
myModel.addAnalysis(bk);
%
% --------------------------- Run simulation ---------------------------- %
%
myModel.initSystem();
ft.run();
clear myModel extload extforce ft pk1 pk2 bk
end