opensim-org / opensim-core

SimTK OpenSim C++ libraries and command-line applications, and Java/Python wrapping.
https://opensim.stanford.edu
Apache License 2.0
758 stars 308 forks source link

computing jacobian: matlab and c++ api difference #3735

Closed EmanueleFeola closed 3 months ago

EmanueleFeola commented 3 months ago

My goal is to compute the jacobian of the model. Using matlab's api, it works as expected, but I'm having some trouble making it work using c++ api. Do you have any idea what I'm doing wrong? Here it follows both the matlab and the c++ code I'm testing, and some debug information at the end. Thank you in advance for any suggestion.

Using matlab it works correctly:

model = Model("model.osim");
state = model.initSystem(); 
model.realizePosition(state);

force_position_vector = [0, 0, 0];
simbody_position_vector = Vec3.createFromMat(force_position_vector);
simbody_jacobian = Matrix();

smss = model.getMatterSubsystem();
smss.calcStationJacobian(state, 4, simbody_position_vector, simbody_jacobian);
jacob = simbody_jacobian.getAsMat; % correct output

If I use c++ api, an exception is raised (Access violation reading location 0x0000000000000000):

Model* model = new Model("model.osim");
State& state = model->initSystem();
model->realizePosition(state);

SimbodyMatterSubsystem smss = model->getMatterSubsystem();
Matrix JS;
smss.calcStationJacobian(state, MobilizedBodyIndex(4), Vec3(0), JS); // exception (Access violation reading location 0x0000000000000000.)

Debugging I found the following info. The model is loaded correctly, since model->printBasicInfo(); prints the correct number of joints (4) and bodies (4).

If I loop through the body set (model->getBodySet()) I can print the bodies names, but if I try to access their mobilizedbody another excpetion is thrown.

If I loop through the joint set, I can print the joints names but I can't access their child frames (joints[i].getChildFrame()) without raising another exception.

state.getNQ() and state.getNU() return the correct number. model->getNumBodies(); returns the correct number of bodies smss->getNumBodies(); returns 0, as if the model was not initialized correctly

EmanueleFeola commented 3 months ago

Solved by Michael Sherman on the Opensim forum.

The solution is the following: you need to get a reference to the existing SimbodyMatterSubsystem rather than a copy const SimbodyMatterSubsystem& smss = model->getMatterSubsystem();