opensim-core icon indicating copy to clipboard operation
opensim-core copied to clipboard

MATLAB MarkersReference crash when accessing marker values

Open cvhammond opened this issue 3 years ago • 5 comments

I'm updating our NMSM Pipeline project to HEAD and found the following issue that crashes MATLAB.

fileName = 'simple_arm.trc';

import org.opensim.modeling.*
markerNames = ["r_humerus1", "r_humerus2", "r_humerus3", "r_radius1", "r_radius2", "r_radius3"];
markerWeightSet = SetMarkerWeights();
for i=1:length(markerNames)
    markerWeightSet.cloneAndAppend(MarkerWeight(markerNames(i), 1.0));
end
markersReference = MarkersReference(fileName, markerWeightSet);

markersReference.get_marker_weights(1)

simple_arm.txt I'm using this file for a very simple .trc file (rename .txt to .trc). The trc file works as expected in OpenSim GUI.

cvhammond avatar Jun 15 '22 00:06 cvhammond

For the record, this same API is exercised and tested in C++ here https://github.com/opensim-org/opensim-core/blob/2ef5732554db5671356b0d04364cbcbd4a4e5de8/OpenSim/Simulation/Test/testInverseKinematicsSolver.cpp#L171 but I'll dig into it further

aymanhab avatar Jun 15 '22 21:06 aymanhab

It is a bit hard to see why this line get_marker_weights(1) have ever worked in the past considering the signature of the method SetMarkerWeights get_marker_weights(int i) While ideally we don't crash, the expected API call sequence is to get reference to the Set using get_marker_weights() then call get(i) to retrieve the ith element. I'll leave this issue open as we shouldn't crash but otherwise this seems to be an unexpected use of the API that has been there since 4.0. If I missed something about the context please let me know @CVHammond

aymanhab avatar Jun 16 '22 00:06 aymanhab

Hmm, this is an interesting scenario. So I tried the script above in my 4.0 environment and it runs, albeit as you pointed out, perhaps as an unintended addition to the MATLAB API. The line that actually crashed the project in 4.4 beta but not in 4.0 is ikSolver.getNumMarkersInUse(). I thought involving the InverseKinematicsSolver object could obfuscate the bug. Here is a test case that most closely demonstrates the functionality that we have implemented and works in 4.0. If you have a better way to achieve the end goal of ikSolver.computeCurrentMarkerError(i) I'm all ears.

fileName = 'simple_arm.trc';
modelFileName = "simple_arm.osim";

import org.opensim.modeling.*
model = Model(modelFileName);
state = model.initSystem();
markerNames = ["r_humerus1", "r_humerus2", "r_humerus3", "r_radius1", ...
    "r_radius2", "r_radius3"];
markerWeightSet = SetMarkerWeights();
for i=1:length(markerNames)
    markerWeightSet.cloneAndAppend(MarkerWeight(markerNames(i), 1.0));
end
% markersReference = MarkersReference(fileName, markerWeightSet); % 4.4 beta
markersReference = MarkersReference(fileName); % 4.0
markersReference.setMarkerWeightSet(markerWeightSet); % 4.0

ikSolver = InverseKinematicsSolver(model, markersReference, ...
    SimTKArrayCoordinateReference());

ikSolver.assemble(state);
error = zeros(1, ikSolver.getNumMarkersInUse());
for i=0:ikSolver.getNumMarkersInUse()-1
    error(i+1) = ikSolver.computeCurrentMarkerError(i);
end

cvhammond avatar Jun 16 '22 22:06 cvhammond

@CVHammond I'm trying to build a test case to exercise your code but missing the 'simple_arm.osim' model file. This is important since the marker names in trc file must match the names in the model. Please attach the model file here or send it by email. Thank you

aymanhab avatar Jun 20 '22 16:06 aymanhab

Oops, sorry I didn't include it. GitHub doesn't let me submit .osim files, so here is the model as a .txt simple_arm.txt @aymanhab

cvhammond avatar Jun 20 '22 18:06 cvhammond