How To Get the Torque at Specific Positions?

Provide easy-to-use, extensible software for modeling, simulating, controlling, and analyzing the neuromusculoskeletal system.
POST REPLY
User avatar
Jenna Li
Posts: 3
Joined: Tue Jun 04, 2024 3:54 pm

How To Get the Torque at Specific Positions?

Post by Jenna Li » Fri Jul 05, 2024 2:23 pm

We have a model, and we are trying to get an approximation of how difficult certain poses are. We are trying to get the torque at different positions in python. Does anyone have any sample scripts or pointers on how to do that?

Tags:

User avatar
Mohammadreza Rezaie
Posts: 377
Joined: Fri Nov 24, 2017 12:48 am

Re: How To Get the Torque at Specific Positions?

Post by Mohammadreza Rezaie » Sat Jul 06, 2024 2:28 am

We are trying to get the torque at different positions in python.
Hi, if I'm not mistaken, InverseDynamicsSolver could help. This requires accelerations; after updating the coordinates' value and speed, call realizeVelocity, prepare a vector of accelerations in multibody tree order, and solve it. The general form should be something like this (you can also use a loop to solve it at each time frame):

Code: Select all

import opensim as osim
import numpy as np

model = osim.Model('./input/scaled.osim')
state = model.initSystem()
IDSolver = osim.InverseDynamicsSolver(model)

for coordinate in model.getCoordinateSet():
    coordinate.setValue(state, 1) # test in radians
    coordinate.setSpeedValue(state, 1) # test in radians/s

model.realizeVelocity(state)

# # accelerations vector must be in multibody tree order:
# CTree = model.getCoordinateNamesInMultibodyTreeOrder()
# CTree = [CTree.getElt(i) for i in range(CTree.size())]
n = state.getNU()
uDot = osim.Vector(np.ones(n)) # test in radians/s^2

IDSolver.solve(state, uDot).to_numpy()
(use your real values instead of the ones)

Hope this helps.
-Mohammadreza

User avatar
Jenna Li
Posts: 3
Joined: Tue Jun 04, 2024 3:54 pm

Re: How To Get the Torque at Specific Positions?

Post by Jenna Li » Tue Jul 09, 2024 5:39 am

Thank you so much for the response! I tried using InverseDynamicsSolver but got very strange values as output. the values (below) are very large, and don't seem to match up with what I think the torque should be.

here's my code:

Code: Select all

def get_torque_values(model, state, pos=None, coord_names = ["elv_angle", "shoulder_elv", "shoulder_rot", "elbow_flexion", "pro_sup", "deviation", "flexion"]):

    inverse_dynamics_solver = osim.InverseDynamicsSolver(model)
    coords = model.getCoordinateSet()
    to_keep_index = []

    for i in range(coords.getSize()):
        coord = coords.get(i)
        coord.setSpeedValue(state,0)
        if coord.getName() in coord_names:
            to_keep_index.append(i)
            if pos is not None:
                coord.setValue(state,pos[coords.get(i).getName()])
                coord.setSpeedValue(state,0)

    model.realizeVelocity(state)
    udot = osim.Vector(model.getNumSpeeds(), 0.0)
    torque_values = inverse_dynamics_solver.solve(state,udot)
    relevant_torque_values = [torque_values[to_keep_index[i]] for i in range(len(to_keep_index))]

    return relevant_torque_values

def test_torque_values(model_path, joint_names=["elv_angle", "shoulder_elv", "shoulder_rot", "elbow_flexion", "pro_sup", "deviation", "flexion"]):
    model = osim.Model(model_path)
    state = model.initSystem()

    default = get_torque_values(model,state)
    testCoord = model.getCoordinateSet().get("shoulder_elv")
    testCoord.setValue(state,3.14/2)
    raised = get_torque_values(model,state)
    # testCoord = model.getCoordinateSet().get("elbow_flexion")
    testCoord.setValue(state,3.14)
    high = get_torque_values(model,state)
    print('range max: ',testCoord.getRangeMax())

    print(default)
    print(default[1])
    print(raised[1])
    print(high[1])

test_torque_values(model_path)
here is what test_torque_values printed out:
[-525.8879515086584, 1759.1103165292966, -315.1703446028086, 0.07566166921931483, 58.50165393582534, -16.38013139804234, 9.067275629231764]
1759.1103165292966
2049.6546823307117
2066.793696377007

shoulder_elv ranges from zero to pi. When at shoulder_elv is at pi/2, the arm is parallel with the ground in opensim creator. To me it seems that the highest torque on this joint should be when the arm is held parallel to the ground, but the values don't reflect that. Also, I don't understand why the values are so large.

User avatar
Jenna Li
Posts: 3
Joined: Tue Jun 04, 2024 3:54 pm

Re: How To Get the Torque at Specific Positions?

Post by Jenna Li » Tue Jul 09, 2024 7:03 am

Also I am hoping to use InverseDynamicTools to get the torque values through a motion from a motion sto file. On the API it says:
"As an additional service, the InverseDynamicsTool can provide an equivalent body force (torque and force) applied to the joint frame. Since generalized forces include scaling (due to units conversion as well as coupling between translations and rotations, for example) they are not necessarily joint torques or forces. "
https://simtk.org/api_docs/opensim/api_ ... l#details

If I am interpreting this correctly, the run() function of InverseDynamicsTool returns the generalized forces, and I need to use some other function to get the torque? I am wondering how I can get the torque and force? I don't see functions listed in the api that would allow me to do so.

POST REPLY