opensim-org / opensim-models

SimTK OpenSim models (.osim) and related example files that are distributed with OpenSim.
opensim.stanford.edu
57 stars 43 forks source link

Patellofemoral range in Rajagopal model #178

Open mrrezaie opened 1 month ago

mrrezaie commented 1 month ago

Hi @nickbianco,

In the Rajagopal2016.osim model, the walker_knee joint is ranged between 0 and 2.0944 Radians, and the patellofemoral joint, which is constrained as a function of knee motion, is defined to be in [-99999, -99999] range. Accordingly, OpenSim Moco uses this huge range for patellofemoral joint bound, while its actual range is [0, 2.0944]. This range can be confirmed by:

model = osim.Model('Rajagopal2016.osim')
state = model.initSystem()
knee = model.getCoordinateSet().get('knee_angle_r')
patellofemoral = model.getCoordinateSet().get('knee_angle_r_beta')
angles = osim.createVectorLinspace(10, knee.getRangeMin(), knee.getRangeMax())
for i in range( angles.size()):
    angle = angles.get(i)
    knee.setValue(state, angle)
    model.realizePosition(state)
    PFA = patellofemoral.getValue(state)
    print(f'knee: {round(angle,4)}, patellofemoral: {round(PFA,4)}')
knee: 0.0,    patellofemoral: 0.0
knee: 0.2327, patellofemoral: 0.2327
knee: 0.4654, patellofemoral: 0.4654
knee: 0.6981, patellofemoral: 0.6981
knee: 0.9308, patellofemoral: 0.9308
knee: 1.1636, patellofemoral: 1.1636
knee: 1.3963, patellofemoral: 1.3963
knee: 1.629,  patellofemoral: 1.629
knee: 1.8617, patellofemoral: 1.8617
knee: 2.0944, patellofemoral: 2.0944

I just tested this new range for the bound of the patellofemoral joint in OpenSim MocoTrack, i.e. [0, 2.0944] (exactly the same as the knee), and the convergence time of a torque-driven marker tracking simulation reduced from 00:10:19 (535 iter) to 00:06:53 (347 iter) (4 threads). So, adjusting this range in the official model, as well as in the Moco examples, could be beneficial.

Thank you in advance.

nickbianco commented 1 month ago

Hi @mrrezaie, thanks for pointing this out. I usually reduce the range on this coordinate manually via setStateInfo(). We could consider reducing the range in the model, but we should check how that would affect other analyses outside of Moco.

mrrezaie commented 1 month ago

I just did some IK and ID tests on Rajagopal2015 model and its associated running data, and the curves perfectly overlapped: ik id2 I'm also curious to know why the original developers of the model used such a huge range of motion for that!!!

tkuchida commented 1 month ago

I'm also curious to know why the original developers of the model used such a huge range of motion for that!!!

I don't think the model was designed with this use case in mind. The range entered for the patellofemoral joint is immaterial if it's constrained to be equal to the knee joint angle in OpenSim. If possible, could the problem in Moco be simplified so that the knee joint and patellofemoral joint share a single state variable? (I presume what happens now is that both angles are design variables and are enforced by a constraint to be equal?)

nickbianco commented 1 month ago

If possible, could the problem in Moco be simplified so that the knee joint and patellofemoral joint share a single state variable?

In this case that might be possible, but in general such simplifications would be tricky or not possible. Currently, we enforce kinematic constraints directly in Moco.

I just did some IK and ID tests on Rajagopal2015 model and its associated running data, and the curves perfectly overlapped:

My point wasn't that these curves wouldn't overlap with a narrowing range for the patella coordinate, but rather is there any value in allow dependent coordinates to have wider ranges than their "expected" ranges during simulation. During forward integration, Simbody corrects coordinates that do not lie on the constraint manifold using a projection, during which the coordinate might lie outside of its bounds. However, I doubt the coordinate bounds are enforced during integration or coordinate projection anyway.