Tracking IK instead of states
Tracking IK instead of states
Hi there,
I am wondering if I can use an IK/.mot file instead of states/.sto file as a tracking goal?
Thanks
I am wondering if I can use an IK/.mot file instead of states/.sto file as a tracking goal?
Thanks
- Ross Miller
- Posts: 375
- Joined: Tue Sep 22, 2009 2:02 pm
Re: Tracking IK instead of states
Hi Grace,
For kinematics, MocoTrack can track marker coordinates and/or "processed" kinematic data, e.g. joint angles.
Anecdotally, I've had better results (more consistent convergence) tracking processed data. It also avoids the step of having to match your model's marker set to your data, which can be laborious if the model doesn't already have a marker set or if you data's set doesn't match the model's.
Ross
For kinematics, MocoTrack can track marker coordinates and/or "processed" kinematic data, e.g. joint angles.
Anecdotally, I've had better results (more consistent convergence) tracking processed data. It also avoids the step of having to match your model's marker set to your data, which can be laborious if the model doesn't already have a marker set or if you data's set doesn't match the model's.
Ross
Re: Tracking IK instead of states
Hi Grace,
Agree with Ross - I've found tracking the 'processed' kinematic data to work better. I think I can see one issue you might have been querying, in that IK results come in the .mot format and report the data as 'coordinates' rather than 'states'. I wrote a brief Python function into some of my pipelines that converted an IK .mot file to a states .sto file - so it may be helpful to see this process:
Aaron
Agree with Ross - I've found tracking the 'processed' kinematic data to work better. I think I can see one issue you might have been querying, in that IK results come in the .mot format and report the data as 'coordinates' rather than 'states'. I wrote a brief Python function into some of my pipelines that converted an IK .mot file to a states .sto file - so it may be helpful to see this process:
Code: Select all
def kinematicsToStates(kinematicsFileName = None, osimModelFileName = None,
outputFileName = 'coordinates.sto',
inDegrees = True, outDegrees = False):
# Convenience function for converting IK results to a states storage.
#
# Input: kinematicsFileName - file containing kinematic data. Header should only be coordinates name, rather than path to state
# osimModelFileName - opensim model filename that corresponds to kinematic data
# outputFileName - optional filename to output to (defaults to coordinates.sto)
# inDegrees - set to true if kinematics file is in degrees (defaults to True)
# outDegrees - set to true if desired output is in degrees (defaults to False)
if kinematicsFileName is None:
raise ValueError('Filename for kinematics is required')
if osimModelFileName is None:
raise ValueError('OpenSim model filename is required')
#Load in the kinematic data
kinematicsStorage = osim.Storage(kinematicsFileName)
#Create a copy of the kinematics data to alter the column labels in
statesStorage = osim.Storage(kinematicsFileName)
#Resample the data points linearly to avoid any later issues with matching
#time points. Use a time stamp for 250 Hz
kinematicsStorage.resampleLinear(1/250)
statesStorage.resampleLinear(1/250)
#Get the column headers for the storage file
angleNames = kinematicsStorage.getColumnLabels()
#Get the corresponding full paths from the model to rename the
#angles in the kinematics file
kinematicModel = osim.Model(osimModelFileName)
for ii in range(0,angleNames.getSize()):
currAngle = angleNames.get(ii)
if currAngle != 'time':
#Get full path to coordinate
fullPath = kinematicModel.updCoordinateSet().get(currAngle).getAbsolutePathString()+'/value'
#Set angle name appropriately using full path
angleNames.set(ii,fullPath)
#Set the states storage object to have the updated column labels
statesStorage.setColumnLabels(angleNames)
#Appropriately set output in degrees or radians
if inDegrees and not outDegrees:
#Convert degrees values to radians for consistency with the current
#file label (defaults back to inDegrees=no). Radians seem to work
#better with the Moco process as well.
kinematicModel.initSystem()
kinematicModel.getSimbodyEngine().convertDegreesToRadians(statesStorage)
elif inDegrees and outDegrees:
#Change the storage label back to specifying indegrees=yes
statesStorage.setInDegrees(True)
elif not inDegrees and outDegrees:
#Convert radians to degrees
kinematicModel.initSystem()
kinematicModel.getSimbodyEngine().convertRadiansToDegrees(statesStorage)
#Reset labeling for degrees
statesStorage.setInDegrees(True)
#Write the states storage object to file
statesStorage.printToXML(outputFileName)
Re: Tracking IK instead of states
Thanks Aaron and Ross that is very helpful! I will try out the code and try to convert it for use in MATLAB.
Cheers,
Grace
Cheers,
Grace
Re: Tracking IK instead of states
Hi again,
I have converted your code for use in MATLAB - see below. However when I write the file the first line of data is indented which I think is causing an issue when I try to solve a MocoInverse problem. I am getting the error :
Thanks
I have converted your code for use in MATLAB - see below. However when I write the file the first line of data is indented which I think is causing an issue when I try to solve a MocoInverse problem. I am getting the error :
Is there a workaround for this? Or would this error be due to some other issue?Java exception occurred:
java.lang.RuntimeException: SimTK Exception thrown at FactorQTZ.cpp:325:
Bad call to Simbody API method FactorQTZ::factor(): Can't factor a matrix that has a zero dimension -- got 8 X 0.
(Required condition 'mat.nelt() > 0' was not met.)
at org.opensim.modeling.opensimMocoJNI.MocoInverse_solve(Native Method)
at org.opensim.modeling.MocoInverse.solve(MocoInverse.java:451)
Thanks
Code: Select all
function ConvertIKtoSTO(kinematicsFileName, osimModelFileName, ...
outputFileName, inDegrees , outDegrees )
% Convenience function for converting IK results to a states storage.
%
% Input: kinematicsFileName - file containing kinematic data. Header should only be coordinates name, rather than path to state
% osimModelFileName - opensim model filename that corresponds to kinematic data
% outputFileName - optional filename to output to (defaults to coordinates.sto)
% inDegrees - set to true if kinematics file is in degrees (defaults to True)
% outDegrees - set to true if desired output is in degrees (defaults to False)
import org.opensim.modeling.*;
%Load in the kinematic data
kinematicsStorage = Storage(kinematicsFileName);
%Create a copy of the kinematics data to alter the column labels in
statesStorage = Storage(kinematicsFileName);
%Resample the data points linearly to avoid any later issues with matching
%time points. Use a time stamp for 250 Hz
kinematicsStorage.resampleLinear(1/250)
statesStorage.resampleLinear(1/250)
%Get the column headers for the storage file
angleNames = kinematicsStorage.getColumnLabels();
%Get the corresponding full paths from the model to rename the
%angles in the kinematics file
kinematicModel = Model(osimModelFileName);
for ii=1:size(angleNames.getSize(),1)
currAngle = angleNames.get(ii);
if currAngle ~= 'time'
%Get full path to coordinate
fullPath = [char(kinematicModel.updCoordinateSet().get(currAngle).getAbsolutePathString()) '/value'];
%Set angle name appropriately using full path
angleNames.set(ii,fullPath)
end
end
%Set the states storage object to have the updated column labels
statesStorage.setColumnLabels(angleNames)
%Appropriately set output in degrees or radians
if inDegrees ==1 && outDegrees~=1
%Convert degrees values to radians for consistency with the current
%file label (defaults back to inDegrees=no). Radians seem to work
%better with the Moco process as well.
kinematicModel.initSystem()
kinematicModel.getSimbodyEngine().convertDegreesToRadians(statesStorage)
elseif inDegrees ==1 && outDegrees ==1
%Change the storage label back to specifying indegrees=yes
statesStorage.setInDegrees(true)
elseif inDegrees ~=1 && outDegrees ~=1
%Convert radians to degrees
kinematicModel.initSystem()
kinematicModel.getSimbodyEngine().convertRadiansToDegrees(statesStorage)
%Reset labeling for degrees
statesStorage.setInDegrees(True)
end
%Write the states storage object to file
statesStorage.print(outputFileName)
end
- Evan Dooley
- Posts: 25
- Joined: Fri Sep 27, 2019 8:36 am
Re: Tracking IK instead of states
Hi Grace,
I also am working on setting up a MocoInverse problem and have been running into issues. I got a similar error you have shown trying to put this together.
Even with this adjustment I am still getting the same error when I run inverse.solve().
Any chance you have figured out how to debug this error? I am guessing that my model is creating a singularity, but I am unsure how I can go about tracking this down in Moco.
Thanks for sharing your work so far.
Best,
Evan
I also am working on setting up a MocoInverse problem and have been running into issues. I got a similar error you have shown trying to put this together.
I tried using the code you put up to convert my MOT file and when I ran it initially it only updated the column name for the first coordinate. I modified the loop to this section and now it converts my MOT file to one similar to the "coorditnates.sto" given in the 3Dwalking example.Error using MocoInverse_TorqueDrive_CoordTrack_v02 (line 109)
Java exception occurred:
java.lang.RuntimeException: SimTK Exception thrown at FactorQTZ.cpp:325:
Bad call to Simbody API method FactorQTZ::factor(): Can't factor a matrix that has a zero dimension -- got 4 X 0.
(Required condition 'mat.nelt() > 0' was not met.)
at org.opensim.modeling.opensimMocoJNI.MocoInverse_solve(Native Method)
at org.opensim.modeling.MocoInverse.solve(MocoInverse.java:451)
Code: Select all
for ii=1:angleNames.getSize()-1 % time col was skipped
currAngle = angleNames.get(ii);
%Get full path to coordinate
fullPath = [char(kinematicModel.updCoordinateSet().get(currAngle).getAbsolutePathString()) '/value'];
%Set angle name appropriately using full path
angleNames.set(ii,fullPath)
end
Any chance you have figured out how to debug this error? I am guessing that my model is creating a singularity, but I am unsure how I can go about tracking this down in Moco.
Thanks for sharing your work so far.
Best,
Evan
- Nicholas Bianco
- Posts: 1078
- Joined: Thu Oct 04, 2012 8:09 pm
Re: Tracking IK instead of states
Hi Grace and Evan,
Have you made any modifications to this model for your MocoInverse problems (e.g., changed joint definitions or modified kinematic constraints)? This error seems model specific, not related to Moco.
-Nick
Have you made any modifications to this model for your MocoInverse problems (e.g., changed joint definitions or modified kinematic constraints)? This error seems model specific, not related to Moco.
-Nick
- Evan Dooley
- Posts: 25
- Joined: Fri Sep 27, 2019 8:36 am
Re: Tracking IK instead of states
Hello,
I have not changed the joint definitions, but I think it is a model specific thing.
I believe it is due to the subtalar joints still being locked in the model I was trying to simulate. Reading more on the forum this seems to cause various issues, so I tried unlocking these joints.
After releasing the subtalar joints, Moco attempts to solve.
(at the moment it fails, but I'm still digging into that)
Thanks for your quick response Nick!
-Evan
I have not changed the joint definitions, but I think it is a model specific thing.
I believe it is due to the subtalar joints still being locked in the model I was trying to simulate. Reading more on the forum this seems to cause various issues, so I tried unlocking these joints.
After releasing the subtalar joints, Moco attempts to solve.
(at the moment it fails, but I'm still digging into that)
Thanks for your quick response Nick!
-Evan
- Nicholas Bianco
- Posts: 1078
- Joined: Thu Oct 04, 2012 8:09 pm
Re: Tracking IK instead of states
Hi Evan,
You're welcome! The recommended practice for locked joints (if you wish to ignore them in your simulations), is to replace these joints with a WeldJoint. Moco has a ModelOperator called ModOpReplaceJointsWithWelds that you can use to do this.
-Nick
You're welcome! The recommended practice for locked joints (if you wish to ignore them in your simulations), is to replace these joints with a WeldJoint. Moco has a ModelOperator called ModOpReplaceJointsWithWelds that you can use to do this.
-Nick
- Evan Dooley
- Posts: 25
- Joined: Fri Sep 27, 2019 8:36 am
Re: Tracking IK instead of states
Awesome!
I have made a note and will give that function a try.
For completeness, my simulation was not converging because I had the max/min forces on the controllers set way too low. I opened them up to -inf to +inf and Moco quickly converged to a reasonable solution.
Thanks for the tips!
Best,
Evan
I have made a note and will give that function a try.
For completeness, my simulation was not converging because I had the max/min forces on the controllers set way too low. I opened them up to -inf to +inf and Moco quickly converged to a reasonable solution.
Thanks for the tips!
Best,
Evan