Performing Inverse Dynamics via Matlab API
- David John Saxby
- Posts: 83
- Joined: Mon May 09, 2011 8:39 pm
Performing Inverse Dynamics via Matlab API
Hi All,
I'm working on Matlab scripts which will use the API to setup and run ID for x number of trials in v3.0.1.
I use a setupID.xml template, which functionally empty (model and file are unassigned), with the exception of the external loads xml file, which I have to generic templates based on a left or right foot strike. Which external loads file is passed to tool is to be controlled by some separate logic regarding foot markers to force plate COP distance.
All is good except I cannot seem to get/set the values in the external loads xml file.
In the InverseDynamicsTool, there are methods such as:
idTool.getExternalLoads().setExternalLoadsModelKinematicsFileName(motionFile);
idTool.getExternalLoads().setDataFileName(grfMOTfile);
I use these, but when I pause the script after printing the setup file the external force file is unmodified.
It may also be interesting that I am set the model name:
% Load the model
model = Model(modelFile);
% Instantiate the model
state = model.initSystem();
% Tell Tool to use the loaded model
idTool.setModel(model);
And when I verify the model is being pointed to in the printed setup file it remains unmodified.
Do I have the correct approach in trying to modify generic IDsetup and external loads xml via the ID tool? Is there a constructor method which would allow me to work on the external loads file directly? Any suspicions about why I'm not printing the xml with names I specify?
Many thanks for any suggestions of where to look.
David
I'm working on Matlab scripts which will use the API to setup and run ID for x number of trials in v3.0.1.
I use a setupID.xml template, which functionally empty (model and file are unassigned), with the exception of the external loads xml file, which I have to generic templates based on a left or right foot strike. Which external loads file is passed to tool is to be controlled by some separate logic regarding foot markers to force plate COP distance.
All is good except I cannot seem to get/set the values in the external loads xml file.
In the InverseDynamicsTool, there are methods such as:
idTool.getExternalLoads().setExternalLoadsModelKinematicsFileName(motionFile);
idTool.getExternalLoads().setDataFileName(grfMOTfile);
I use these, but when I pause the script after printing the setup file the external force file is unmodified.
It may also be interesting that I am set the model name:
% Load the model
model = Model(modelFile);
% Instantiate the model
state = model.initSystem();
% Tell Tool to use the loaded model
idTool.setModel(model);
And when I verify the model is being pointed to in the printed setup file it remains unmodified.
Do I have the correct approach in trying to modify generic IDsetup and external loads xml via the ID tool? Is there a constructor method which would allow me to work on the external loads file directly? Any suspicions about why I'm not printing the xml with names I specify?
Many thanks for any suggestions of where to look.
David
- Ayman Habib
- Posts: 2248
- Joined: Fri Apr 01, 2005 12:24 pm
Re: Performing Inverse Dynamics via Matlab API
Hi David,
If the functionality works (seems like it's using the correct model and external loads) then it could be a bug with the "properties" not being updated or not written because the code doesn't know they have been changed. Generally going through API calls may not modify properties as a side effect, for example setting the model will not set the model file_name property (as the passed in model may not have a file associated with it to begin with).
If you need an interface that affects the properties directly and you're not finding it please let us know.
Best regards,
-Ayman
If the functionality works (seems like it's using the correct model and external loads) then it could be a bug with the "properties" not being updated or not written because the code doesn't know they have been changed. Generally going through API calls may not modify properties as a side effect, for example setting the model will not set the model file_name property (as the passed in model may not have a file associated with it to begin with).
If you need an interface that affects the properties directly and you're not finding it please let us know.
Best regards,
-Ayman
- David John Saxby
- Posts: 83
- Joined: Mon May 09, 2011 8:39 pm
Re: Performing Inverse Dynamics via Matlab API
Hi Ayman,
Generally yes, it would be quite useful to be able to modify these properties of the external loads file through the API. I tried via matlab parsing, but as you pointed out quite rightly this messes us the xml file and then it is not handled by the API or GUI.
So trying to avoid manually changing input files in the xml or gui, I need to be able to control the source file for the loads, the matching model kinematics, and also potentially the assignment of the loads to bodies in the model, as my trials vary in foot and plate striking. I have logic to determine what is happening, but I'm stuck as to how to apply these settings via the API.
Regarding the models, I've also noticed this in the analysis tool. I load a generic muscle analysis xml which doesn't have a model associated with it, with the plan to set this explicitly in the API, but no setModel method exists for AnalyzeTool. Would it be sufficient to instantiate the model of interest, and then apply the AnalyzeTool? Would the tool then use the current instance of the model, plus whatever analysis specified in the generic template?
David
Generally yes, it would be quite useful to be able to modify these properties of the external loads file through the API. I tried via matlab parsing, but as you pointed out quite rightly this messes us the xml file and then it is not handled by the API or GUI.
So trying to avoid manually changing input files in the xml or gui, I need to be able to control the source file for the loads, the matching model kinematics, and also potentially the assignment of the loads to bodies in the model, as my trials vary in foot and plate striking. I have logic to determine what is happening, but I'm stuck as to how to apply these settings via the API.
Regarding the models, I've also noticed this in the analysis tool. I load a generic muscle analysis xml which doesn't have a model associated with it, with the plan to set this explicitly in the API, but no setModel method exists for AnalyzeTool. Would it be sufficient to instantiate the model of interest, and then apply the AnalyzeTool? Would the tool then use the current instance of the model, plus whatever analysis specified in the generic template?
David
- Ayman Habib
- Posts: 2248
- Joined: Fri Apr 01, 2005 12:24 pm
Re: Performing Inverse Dynamics via Matlab API
Hi David,
Regarding the AnalyzeTool question, the answer is yes, if you instantiate it from a file then call setModel then you should be fine and the Analyses specified in the file will be executed.
For the first part related to specifying ExternalLoads, I'd create an ExternalLoads object programmatically, add ExternalForce(s) to it then write it to a file, and then call setExternalLoadsFileName() on the InverseDynamicsTool with the name of the file you created.
Please let me know how that goes.
Best regards,
-Ayman
Regarding the AnalyzeTool question, the answer is yes, if you instantiate it from a file then call setModel then you should be fine and the Analyses specified in the file will be executed.
For the first part related to specifying ExternalLoads, I'd create an ExternalLoads object programmatically, add ExternalForce(s) to it then write it to a file, and then call setExternalLoadsFileName() on the InverseDynamicsTool with the name of the file you created.
Please let me know how that goes.
Best regards,
-Ayman
- David John Saxby
- Posts: 83
- Joined: Mon May 09, 2011 8:39 pm
Re: Performing Inverse Dynamics via Matlab API
Hi Ayman,
Thanks a lot!
I'll give it a go and report back on the forum how it went.
David
Thanks a lot!
I'll give it a go and report back on the forum how it went.
David
- David John Saxby
- Posts: 83
- Joined: Mon May 09, 2011 8:39 pm
Re: Performing Inverse Dynamics via Matlab API
Hi Ayman,
Your suggestions worked very well.
For ID:
I looked at the source code for DynamicsTool to understand the construction of external loads by ExternalLoads constructor. Once made, I set the ID tool's external loads to the new file created. Works!
On an unrelated note, have you guys had any bugs reported on 3.0.1's ID solutions. I have very reasonable kinematics and normative GRFs, but my id moments are off by about a factor of 10. Forces and kinematics are synchronized, the forces applied to the correct bodies, and the shape of the torques looks normal for gait, but again the magnitudes are preposterous.
For MuscleAnalysis:
It worked as you suggested. Model is instantiated from a file: model = Model(ModelFile);
Then to analyzeToool.setModel(model), applied the current instance of the model. Tool executes.
David
Your suggestions worked very well.
For ID:
I looked at the source code for DynamicsTool to understand the construction of external loads by ExternalLoads constructor. Once made, I set the ID tool's external loads to the new file created. Works!
On an unrelated note, have you guys had any bugs reported on 3.0.1's ID solutions. I have very reasonable kinematics and normative GRFs, but my id moments are off by about a factor of 10. Forces and kinematics are synchronized, the forces applied to the correct bodies, and the shape of the torques looks normal for gait, but again the magnitudes are preposterous.
For MuscleAnalysis:
It worked as you suggested. Model is instantiated from a file: model = Model(ModelFile);
Then to analyzeToool.setModel(model), applied the current instance of the model. Tool executes.
David
- Ayman Habib
- Posts: 2248
- Joined: Fri Apr 01, 2005 12:24 pm
Re: Performing Inverse Dynamics via Matlab API
Hi David,
Thanks for reporting back to the forum on your progress. I'm sure many users will benefit from this.
For differences in ID results, I'm not aware of any changes in 3.0.1 that would change ID results relative to version 3.0 directly. We made a fix in the scaleTool so that "preserve mass distribution" flag is handled correctly. This has the potential to change ID results downstream but only if you rerun the whole pipeline including scaling. Please let us know how to reproduce the different results in version 3.0 vs. 3.0.1 and we'll take a look. If needed please feel free to file a bug report and attach all the necessary model/setup and data files.
Best regards,
-Ayman
Thanks for reporting back to the forum on your progress. I'm sure many users will benefit from this.
For differences in ID results, I'm not aware of any changes in 3.0.1 that would change ID results relative to version 3.0 directly. We made a fix in the scaleTool so that "preserve mass distribution" flag is handled correctly. This has the potential to change ID results downstream but only if you rerun the whole pipeline including scaling. Please let us know how to reproduce the different results in version 3.0 vs. 3.0.1 and we'll take a look. If needed please feel free to file a bug report and attach all the necessary model/setup and data files.
Best regards,
-Ayman
- Günter Schneider
- Posts: 29
- Joined: Thu Jul 26, 2012 6:08 am
Re: Performing Inverse Dynamics via Matlab API
aymanh wrote:Hi David,
...
For the first part related to specifying ExternalLoads, I'd create an ExternalLoads object programmatically, add ExternalForce(s) to it then write it to a file, and then call setExternalLoadsFileName() on the InverseDynamicsTool with the name of the file you created. ...
Best regards,
-Ayman
Hi David, hi Ayman!saxbyd wrote:Hi Ayman,
Your suggestions worked very well.
For ID:
I looked at the source code for DynamicsTool to understand the construction of external loads by ExternalLoads constructor. Once made, I set the ID tool's external loads to the new file created. Works!
..
David
I`ve got the same problem with my MATLAB script for ID. I need to add a specific external load file (that i created via matlab) to every single ID-simulation run!
I'm not really familiar with the ExternalLoads constructor or the source code, and the next problem i found is that matlab reports that ther is no method called "setExternalLoadsFileName" for class"org.opensim.modeling.InverseDanymicsTool" !?!?
Can you help me with that!?! THX a lot in advance and have a nice monday morning
Best regards
Günter
Edit: @David: is there a chance to get a look into your script for the part you add the external load files !?!?
Re: Performing Inverse Dynamics via Matlab API
Inverse Dynamics considers all the applied loads on the model, not just external forces. If you have muscles in your model, you must exclude them if their state is not well defined. The IDTool can exclude them for you if you identify them by name or group, see:
This is the main cause for seeing large unexplainable forces in ID, since the muscle states will be at their default values which can lead to unreasonable forces. The ID setup file we provide excludes Muscles by default so that might be why you had not realized that they were being ignored by ID previously.
Code: Select all
DynamicsTool::setExcludedForces(const Array<std::string>& )
This is the main cause for seeing large unexplainable forces in ID, since the muscle states will be at their default values which can lead to unreasonable forces. The ID setup file we provide excludes Muscles by default so that might be why you had not realized that they were being ignored by ID previously.
- David John Saxby
- Posts: 83
- Joined: Mon May 09, 2011 8:39 pm
Re: Performing Inverse Dynamics via Matlab API
Hi Gunter,
That is fairly weird regarding the method problem.
% Apply the generic xml to the constructor
idTool = InverseDynamicsTool(genericSetupForID);
% instantiate, set model, time, etc...
% Create an external loads object
extLoadsObject = ExternalLoads(model,activeExternalForceFile);
% Set the grf filename
extLoadsObject.setDataFileName(fullpathGRFFile);
% Set the model external loads file
extLoadsObject.setExternalLoadsModelKinematicsFileName(fullpathIKfile);
% Create name for a subject specific external loads xml
extLoadsXml = [data.Name '_' 'external_loads.xml'];
% Print the external load xml file
extLoadsObject.print([subjectDir '\' extLoadsXml]);
That is a snippet from my code and it works no problem from v3.0-3.1.
Hopefully that works for you too. Also check that your template xml which you feed to the constructor is correct. The safest way is make a blank one in the GUI and operate on that rather than creating one in matlab.
DJS
That is fairly weird regarding the method problem.
% Apply the generic xml to the constructor
idTool = InverseDynamicsTool(genericSetupForID);
% instantiate, set model, time, etc...
% Create an external loads object
extLoadsObject = ExternalLoads(model,activeExternalForceFile);
% Set the grf filename
extLoadsObject.setDataFileName(fullpathGRFFile);
% Set the model external loads file
extLoadsObject.setExternalLoadsModelKinematicsFileName(fullpathIKfile);
% Create name for a subject specific external loads xml
extLoadsXml = [data.Name '_' 'external_loads.xml'];
% Print the external load xml file
extLoadsObject.print([subjectDir '\' extLoadsXml]);
That is a snippet from my code and it works no problem from v3.0-3.1.
Hopefully that works for you too. Also check that your template xml which you feed to the constructor is correct. The safest way is make a blank one in the GUI and operate on that rather than creating one in matlab.
DJS