Version discrepancy causing unexpected result

OpenSim Moco is a software toolkit to solve optimal control problems with musculoskeletal models defined in OpenSim using the direct collocation method.
POST REPLY
User avatar
Alexandre Peres
Posts: 4
Joined: Tue May 09, 2023 6:15 am

Version discrepancy causing unexpected result

Post by Alexandre Peres » Wed Apr 03, 2024 1:33 am

Hey everyone,

I've just started working with MOCO in OpenSim, and I'm running into an issue with a colleague's example. My colleague is using OpenSim version 4.4 and opensim-moco-4.4.1-py311np123 package.
When I tried to run her example, I encountered the following error messages:

Code: Select all

 solver = helpers.configure_solver(study, config)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 solver = study.initCasADiSolver()
          ^^^^^^^^^^^^^^^^^^^^^^^^
 return _moco.MocoStudy_initCasADiSolver(self)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

RuntimeError: std::exception in 'OpenSim::MocoCasADiSolver & OpenSim::MocoStudy::initCasADiSolver()': Coordinate '/jointset/ground_pelvis/pelvis_tilt' is locked, but Moco does not support locked coordinates. Consider replacing the joint for this coordinate with a WeldJoint instead.
Thrown at MocoProblemRep.cpp:93 in initialize().

Process finished with exit code 1
I tried unlocking the locked coordinates, and while MOCO ran and converged to a solution, it was not as expected. For instance, the ankles are supposed to be locked during movement, but they are not.

Now, I'm considering two possible solutions:
  • Package Version Issue: I attempted to install the same package as my colleague (opensim-moco-4.4.1-py311np123 package), but when I run osim.GetVersionAndDate(), I get "version 4.5-2023-11-26-efcdfd3eb, build date 23:19:12 Nov 28 2023", which is unexpected. Could this version discrepancy be causing the issue?
  • Joint Type Change: Should I follow the error message's recommendation to change the PinJoints to WeldJoints? This solution would alter the model, potentially leading to different solutions.
Any advice on the best approach moving forward would be greatly appreciated!

User avatar
Nicholas Bianco
Posts: 972
Joined: Thu Oct 04, 2012 8:09 pm

Re: Version discrepancy causing unexpected result

Post by Nicholas Bianco » Wed Apr 03, 2024 10:03 am

Hi Alexandre,

We explicitly disallow locked coordinates in Moco due to a bug that leads to NaNs when using them in simulation.
Package Version Issue: I attempted to install the same package as my colleague (opensim-moco-4.4.1-py311np123 package), but when I run osim.GetVersionAndDate(), I get "version 4.5-2023-11-26-efcdfd3eb, build date 23:19:12 Nov 28 2023", which is unexpected. Could this version discrepancy be causing the issue?
This python package was probably built after 4.4.1 was released, which means it might contain changes added after 4.4.1. But we can still get it to work for your needs.
Joint Type Change: Should I follow the error message's recommendation to change the PinJoints to WeldJoints? This solution would alter the model, potentially leading to different solutions.
Yes, I recommend doing this. If the joint coordinate was intended to be locked, replacing it with a WeldJoint will yield functionally the same model, even if constructed slightly differently. Also, it's more efficient to weld the joint since the weld will remove both the coordinate and the kinematic constraint (the "lock") associated with the joint which Moco would otherwise have to enforce.

The situation is a little different for joints that have multiple coordinates (e.g., the hip joint). You can't weld these joints since that would remove all coordinates. Rather, you should remove the coordinates from the joint that you would like to exclude. I realize this is less convenient and perhaps a locked coordinate would be useful here. I am hoping to look into the locked joint issues in the near future.

Best,
Nick

User avatar
Alexandre Peres
Posts: 4
Joined: Tue May 09, 2023 6:15 am

Re: Version discrepancy causing unexpected result

Post by Alexandre Peres » Thu Apr 11, 2024 5:36 am

Hey Nick, thank you for your advice.
For the past few days I've been working on replacing the locked joints with WeldJoints and my first atempt, as shown bellow, was to simply create new WeldJoints with the same names as the PinJoints and CustomJoints I wanted to replace and hope that it would overwrite them.

Code: Select all

    # Pelvis WeldJoint
    ground = osim.PhysicalFrame.safeDownCast(model.getComponent('ground'))
    pelvis = osim.PhysicalFrame.safeDownCast(model.getComponent('bodyset/pelvis'))

    pelvis_weld_joint = osim.WeldJoint("ground_pelvis",
                                        ground,
                                        osim.Vec3(pelvis_x, pelvis_y, 0),
                                        osim.Vec3(0, 0, pelvis_tilt),
                                        pelvis,
                                        osim.Vec3(0, 0, 0),
                                        osim.Vec3(0, 0, 0))

And the error message was the following:
RuntimeError: std::exception in 'void OpenSim::Model::finalizeConnections()': Failed to convert a pointer from a SimTK::MultibodyGraphMaker to the desired type. This is a known bug that can happen when trying to assemble models that have incorrect topologies (see opensim-core issue #3299). You might need to change/fix your model's topology, or post a comment on that issue.
Thrown at Model.cpp:85 in MultibodyGraphMakerPtrCast().
My next approach was to use the replaceJointWithWeldJoint function, but as you mentioned on your reply, when it comes to joints with multiple coordinates, it just removes them. So the next step was to find a way to edit the existing PhysicalOffsetFrames since now there were no coordinates and here is the solution I came with to solve this problem:

Code: Select all

    #Changing a locked CustomJoint into a WeldJoint
    osim.ModelFactory.replaceJointWithWeldJoint(model, "ground_pelvis")
    
    # Setting position for pelvis WeldJoint according to config file (substitutes the need for coordinates)
    frame = model.updJointSet().get("ground_pelvis").upd_frames(0)
    frame.set_translation(osim.Vec3(pelvis_x, pelvis_y, 0.0))
    frame.set_orientation(osim.Vec3(0.0, 0.0, pelvis_tilt))
Hopefully this helps people with similar problems in the future.
Best wishes,
Alex Peres

User avatar
Nicholas Bianco
Posts: 972
Joined: Thu Oct 04, 2012 8:09 pm

Re: Version discrepancy causing unexpected result

Post by Nicholas Bianco » Fri Apr 12, 2024 10:02 am

Hi Alex,

My recommendation would be to weld joints that can be welded (i.e., all coordinates are locked), and for the others, modify the joint definition to remove the coordinates you want to exclude. In the latter case, you're probably only dealing with CustomJoints (e.g., the hip joint).

As the name suggest, CustomJoints allow you to select the number of coordinates in the joint definition and how the interact with the spatial transform that determines the joint motion. For a hip joint, typically the three coordinates are each assigned to one simple rotation in the spatial transform, so you could simply remove the coordinates from the joint that you want to "lock". You can refer to the CustomJoint documentation for more information.

Best,
Nick

POST REPLY