Page 1 of 1

Get joint moment in a simulation

Posted: Fri Mar 02, 2018 4:38 am
by tgeijten
I need to find the joint moment of a specific degree of freedom (i.e. the generalized force of a coordinate) of a simulation using the OpenSim API. I know it should be easy, but I've been looking at the docs for hours and can't seem to figure it out :?

Can anyone help me out?

Re: Get joint moment in a simulation

Posted: Sat Mar 03, 2018 3:36 am
by mitkof6
Hi,

You can run the InverseDynamicsTool and then read the results that are stored in .sto file. To use the ID tool I have the following C++ code

Code: Select all

/**
* \brief Performs inverse dynamics given a IK motion and externally applied
* forces. Results are stored in the provided result directory as
* subjectName_id.sto.
*/
class OactivePipeline_API InverseDynamicsModule {
public:
    struct Parameters {
        std::string subjectName;
        OpenSim::Model model;
        std::string inverseKinematicsMotion;
        std::string groundReactionXMLTemplate;
        std::string groundReactionForces;
        std::string resultsDir;
    };
    InverseDynamicsModule(Parameters& parameters);
    void run();
private:
    Parameters parameters;
};

InverseDynamicsModule::InverseDynamicsModule(Parameters& parameters)
    : parameters(parameters) {
}

void InverseDynamicsModule::run() {
    string tempExternalLoadsXML = parameters.resultsDir +
        parameters.subjectName + "_external_loads.xml";
    // prepare external loads
    ExternalLoads externalLoads(parameters.model,
                                parameters.groundReactionXMLTemplate);
    // update template
    externalLoads.setExternalLoadsModelKinematicsFileName(
        parameters.inverseKinematicsMotion);
    externalLoads.setDataFileName(parameters.groundReactionForces);
    externalLoads.setLowpassCutoffFrequencyForLoadKinematics(6);
    externalLoads.print(tempExternalLoadsXML);

    // ID tool
    InverseDynamicsTool id;
    id.setModel(parameters.model);
    Storage motion(parameters.inverseKinematicsMotion);
    id.setStartTime(motion.getFirstTime());
    id.setEndTime(motion.getLastTime());
    id.setCoordinatesFileName(parameters.inverseKinematicsMotion);
    // let createExternalLoads handle the creation of the external loads (internally)
    id.setExternalLoadsFileName(tempExternalLoadsXML);
    id.setOutputGenForceFileName(parameters.subjectName + "_id.sto");
    id.setResultsDir(parameters.resultsDir);
    // if muscles are not excluded then the results are wrong (very high)
    Array<string> forcesToExclude;
    forcesToExclude.append("Muscles");
    id.setExcludedForces(forcesToExclude);
    id.setLowpassCutoffFrequency(6);
    id.run();
}

and in order to call

Code: Select all

    // perform ID
    InverseDynamicsModule::Parameters idParameters{
    	"subject01_walk1",
    	model,
    	subjectDir + "results_cpp/subject01_walk1_ik.mot" ,
    	subjectDir + "subject01_walk1_grf.xml",
    	subjectDir + "subject01_walk1_grf.mot",
    	subjectDir + "results_cpp/"
    };
    InverseDynamicsModule id(idParameters);
    id.run();
Best

Re: Get joint moment in a simulation

Posted: Sat Mar 03, 2018 6:40 am
by tgeijten
Hi Dimitar,

Thanks for the quick reply! However, I'm looking to find the joint moments in a FORWARD simulation (I'm sorry I wasn't clear about this in my initial post). Any idea how to extract those from an OpenSim::Model instance?

Re: Get joint moment in a simulation

Posted: Sat Mar 03, 2018 11:39 am
by mitkof6
Hi,

If you mean a forward dynamics settings you can't get the generalized forces because they are the input to your model. If your model is actuated by the muscles then you may want to compute τ = R * fm (τ: generalized forces, R: muscle moment arm, fm: muscle forces). Is this what you want?

Re: Get joint moment in a simulation

Posted: Mon Mar 05, 2018 3:55 am
by tgeijten
Thanks again! What I need is indeed the generalized forces of the model, but these are not only generated by muscles, but also by contact forces, coordinate limit forces, etc. During forward dynamics simulation, OpenSim / Simbody computes these forces and adds them together before computing the accelerations and integrating the results.

So during the SimTK::Stage::Acceleration stage, all the generalized forces should be available. Instead of recomputing them, I simply wish to extract them from the Simbody subsystem. I'm fairly certain this is possible, I simply can't seem to find the proper API call. I hope this makes sense?

Re: Get joint moment in a simulation

Posted: Mon Mar 05, 2018 8:24 am
by mitkof6
This is a bit tricky. Here is a code (OpenSim v4.0) that I used to calculate the total forces (muscles are excluded).

https://github.com/mitkof6/task-space/b ... el.cpp#L99

You will have to change this line:

https://github.com/mitkof6/task-space/b ... el.cpp#L59

so that the muscle contribution is accounted. Furthermore, I have used a different convention of the model dynamics (as compared to Simbody). For more details:

https://github.com/mitkof6/task-space/b ... Model.h#L7

https://simbody.github.io/simbody-3.6-d ... ml#details

Hope this helps

Re: Get joint moment in a simulation

Posted: Mon Mar 12, 2018 3:10 am
by tgeijten
Thank you, this is indeed what I was looking for!

I must say it's a lot more intricate than I expected -- especially since Simbody already computes the same generalized forces internally :? Would it make sense to post a separate feature request for Simbody on that?

Anyway, thanks again for the great support!