Moco goals for average speed in cycling model

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
Ana de Sousa
Posts: 58
Joined: Thu Apr 07, 2016 4:21 pm

Moco goals for average speed in cycling model

Post by Ana de Sousa » Wed Nov 22, 2023 7:09 am

Hello! (I've posted this in the OpenSim forum, but someone suggested I post it here).

I'm currently working on a project involving a human model (with joint torques) connected to a crank, capable of pedalling from position 0 to 360 degrees. I can successfully predict pedal motion using MocoFinalTimeGoal as the target goal.

Now, I want to explore a different target: average crank speed, rather than optimising minimal time.

I would like some help with that! I considered the following options:

MocoAverageSpeedGoal
The documentation mentions it requires the average speed to match a desired value, calculated as the displacement of the system's COM divided by the phase duration. It seems designed for walking with the COM as a translational displacement. Is that correct? I'm unsure about its fit for my cycling model, where the COM ideally stays in the same position at the start and end. On this topic, I have another question: how is the phase duration defined in Moco?

MocoAngularVelocityTrackingGoal
It focuses on tracking speed rather than achieving a specific average speed. I'm specifically interested in predicting the final speed, not tracking a movement yet.

MocoGoal
It seems more oriented towards initial and final constraints rather than average speed.

Custom goal?
I have no idea where to begin and would greatly appreciate any insights or ideas that might help.

Any other option
I'm open to exploring any suggestions given here. Thanks a lot!


Thank you in advance for your time and assistance.

User avatar
Aaron Fox
Posts: 271
Joined: Sun Aug 06, 2017 10:54 pm

Re: Moco goals for average speed in cycling model

Post by Aaron Fox » Wed Nov 22, 2023 3:57 pm

Hi Ana,

Interesting problem and perhaps difficult to find a solution with the current suite of Moco goals. I think your assessment of the goals you outlined are accurate and that they won't help with this problem.

The only solution I can think of right now is to use one of the more generic goals (e.g. MocoOutputGoal) and find a way to fit this into the idea of the output representing crank speed in some way. For example, if you attached a marker to the crank (or foot) in the model, the marker would have outputs of position and velocity. You could focus on the velocity of the marker, and the MocoOutputGoal can be set so that the norm of the vector is minimised (not sure whether that vector would represent crank speed though given the marker output is linear velocity). Basically I'm suggesting that the velocity of a marker attached to the crank could be used as an output goal in the problem.

You'll note that this output goal is minimised, which is obviously not what you want in achieving fast crank speed. I think that you can set the weight of the goal to a negative value - which then inverts the output and hence it would become a maximise goal.

Hope that helps.

Aaron

User avatar
Carlos Gonçalves
Posts: 127
Joined: Wed Jun 08, 2016 4:56 am

Re: Moco goals for average speed in cycling model

Post by Carlos Gonçalves » Wed Nov 22, 2023 5:50 pm

Hello Ana and Aaron, hello everyone.

I could add some thoughts to the question; maybe it will lead to a good discussion and test.

From my experience, there are options in tracking and prediction scenarios:

Tracking goals: MocoStateTrackingGoal & MocoAngularVelocityTrackingGoal
Since they were designed for tracking, we need to be a little creative. For both, we need a guess or reference to the crank's velocity. The idea is that a constant crank speed equal to your desired average speed can be used as a tracking variable for the optimizer. Since the goal will be integrated into the whole simulation time. In the end, the result should have an average angular velocity close to what you have chosen. Maybe an impossible reference value will lead to the maximum angular average speed that the model can generate.

MocoOutputGoal
The MocoOutputGoal is different from the MocoOutputFinalGoal so that it will integrate the value of the output (crank's angular velocity) during the whole simulation time. Using a negative goal's weight, the optimizer will maximize the output.

In any of those options, adding a MocoControlGoal (weight ~= 0.01) is good so the solution can converge easier.

What do you think?

Best regards

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

Re: Moco goals for average speed in cycling model

Post by Nicholas Bianco » Thu Nov 23, 2023 10:45 am

Hi Ana,

I have an idea: if your model has a coordinate for the bicycle crank, then you should have state variable for the speed (i.e., something like "/jointset/crank/crank_angle/speed"). You could then use a MocoStateTrackingGoal to track a constant reference value for the crank. speed. Finally, you can add a MocoScaleFactor to the goal (via "addScaleFactor()") to scale the constant crank speed reference up or down (within bounds of your choosing). If you set the constant reference speed to 1, then the scale factor effectively becomes the crank speed that you want to optimize.

Enforcing a constant crank speed is a bit different than enforcing an average crank speed, but hopefully this is still a useful approach.

Best,
Nick

User avatar
Ross Miller
Posts: 371
Joined: Tue Sep 22, 2009 2:02 pm

Re: Moco goals for average speed in cycling model

Post by Ross Miller » Fri Nov 24, 2023 4:39 am

I don't know of a way to enforce a constant speed (i.e. the instantaneous speed of some coordinate is always the same value). I think in the original Chow & Jacobson (1971) paper they prescribed the motion of the pelvis somehow, but not sure how that was done or if Moco can do a similar thing.

https://doi.org/10.1016/0025-5564(71)90062-9

If the simulation is of steady-state pedaling over an integer number of cycles, using MocoPeriodicityGoal and MocoTrack.set_final_time (if doing a tracking problem) seems like an easy way to enforce average speed.

Ross

User avatar
Ana de Sousa
Posts: 58
Joined: Thu Apr 07, 2016 4:21 pm

Re: Moco goals for average speed in cycling model

Post by Ana de Sousa » Fri Nov 24, 2023 10:09 am

Hi everyone! First off, I want to express my gratitude for all the valuable suggestions and comments. It's been a good learning experience, and I genuinely appreciate the help.

I'd like to share some follow-up thoughts and questions regarding your suggestions, and I'll delve into work over the coming weeks

Aaron: MocoOutputGoal
This is a very interesting approach! However, given that I already have the states of the crank (position and angular speed), I'm leaning towards using them rather than creating a new marker.
On a related note, I have a quick question for another application: Do you know any examples where a marker is added to a model via coding?

Carlos and Nicholas: MocoStateTrackingGoal
I initially hesitated with this approach, thinking it might be a bit like taking shortcuts, but not really, it is a valid solution, indeed. I'll explore MocoStateTrackingGoal, especially since I have the speed state of the crank, as Nicholas pointed out. I can create a reference trajectory with a constant value and ask the optimiser to minimise it. Since it's already solving for just the initial and final states (0 and 360 degrees), it shouldn't pose a problem for the optimiser.

I do have a couple of follow-up (possibly naive) questions for you guys, if you don't mind:
1) Carlos, I'm not entirely clear on your distinction between MocoOutputFinalGoal and MocoOutputGoal. Could you provide a bit more explanation?
2) Nicholas, is there a significant difference between using MocoScaleFactor-addScaleFactor and simply adding a different constant value as a reference?
3) Could you guys share an easy example of a problem involving tracking just one state?

Ross: Pelvis tracking
Tracking the pelvis is an interesting approach. But I forgot to mention that the system remains stationary in my model.

Once again, thanks a bunch for your insights!

User avatar
Ross Miller
Posts: 371
Joined: Tue Sep 22, 2009 2:02 pm

Re: Moco goals for average speed in cycling model

Post by Ross Miller » Fri Nov 24, 2023 12:26 pm

Hi Ana,

I wasn't suggested to track the pelvis motion. Assuming the crank angle is a state in the model, you can use a periodicity constraint combined with a prescribed final time to prescribe the average speed of the crank (360 degrees / Tfinal).

Ross

User avatar
Aaron Fox
Posts: 271
Joined: Sun Aug 06, 2017 10:54 pm

Re: Moco goals for average speed in cycling model

Post by Aaron Fox » Sun Nov 26, 2023 4:22 pm

Hi Ana,

I didn't realise you had the crank info as a state, which does make things easier. You could track it as others have suggested, or even bound it to a final value that achieves the speed you want (if that's the idea).

As far as adding markers to a model, I don't have any specific examples - but it should be fairly intuitive if you have an understanding of how to use OpenSim classes/functions in your code. It's fairly simple in creating the marker, changing its parameters and then appending it to the models markerset.

Aaron

User avatar
Carlos Gonçalves
Posts: 127
Joined: Wed Jun 08, 2016 4:56 am

Re: Moco goals for average speed in cycling model

Post by Carlos Gonçalves » Mon Nov 27, 2023 6:01 am

Hello Ana and everyone,

Ana, what I mentioned about MocoOutputGoal and MocoOutputFinalGoal are messages from my future self to a current version in multiverse. I already took my suffering figuring it out myself.

When using MocoOutputFinalGoal, the cost is measured in the final So it is good if you want to simulate just that. There is a post about my quest here viewtopicPhpbb.php?f=1815&t=15134&p=0&s ... fa895d014a, where Nick, Ross and Ton helped a lot in my simulations of jump.

Using MocoOutputGoal, the cost is integrated/sum in the whole time. That's why it could benefit following your average constant value.

Here is some code that could help:

Code: Select all

meanVelocity= osim.MocoOutputGoal('cranck_velocity')
meanVelocity.setOutputPath('/bodyset/cranck|angular_velocity')
meanVelocity.setWeight( yourCostWeight)  
#meanVelocity.setOutputIndex(1)  # Align with the axis of the Vector 
meanVelocity.setExponent(3)  # keep height signed (1 is the default value)
meanVelocity.setDivideByDisplacement(False) # should be false because the bike is stationary
problem.addGoal(meanVelocity)

Ross suggestion is great! If you add the periodic goal, the simulation could be shorter and you will have the "steady state result" for the system. The simulation would already start with some cranck velocity and the simulation will and in the full cycle of the cranck.

That is something to explore later. Just to keep in mind that you need to provide enough time and "state final bound" to cranck position, otherwise it will never reach some velocity starting from zero.

User avatar
Ana de Sousa
Posts: 58
Joined: Thu Apr 07, 2016 4:21 pm

Re: Moco goals for average speed in cycling model

Post by Ana de Sousa » Mon Nov 27, 2023 7:32 am

Hi everyone,

First, I appreciate all the insights! I'm conducting tests based on your comments, and I'll make sure to respond to each of you ASAP.

Meanwhile, I've encountered another challenge that might have a quicker solution, can you help me out?

I'm working on introducing resistance to the crank. Currently, the crank operates as a freewheel, and my attempt to incorporate resistance involved using the prescribedForce() function. Here's a snippet of the code:

Code: Select all


# Create a ConstantForce
prescribed_force = osim.PrescribedForce()
prescribed_force.setBodyName('/bodyset/crank')
prescribed_force.setPointFunctions(osim.Constant(0),
                                   osim.Constant(0),
                                   osim.Constant(0))

# Create a constant force function
constant_force = osim.Constant(force_value)

# Set the constant force function for all components (x, y, z)
prescribed_force.setTorqueFunctions(constant_force, constant_force, constant_force)

# Add the force to the model
model.addForce(prescribed_force)

However, I'm uncertain about where to apply this force in terms of axes (x, y, z). For my initial attempt, I added it to all axes, but I'm not entirely clear on what that means.

When inspecting the model in the GUI, I can see the PrescribedForce, click on TorqueFunctions, and see the Constant with the value "force_value" as I defined in the code, so it looks like the code works. Moreover, I tested the model in the GUI with the forwardDynamics, and the crank cycles, so the force seems to be there.

Then, I isolated the crank model (without the human), added an actuator to the crank, and asked Moco to solve the problem of moving the crank from 0 to 180 in the shortest time. However, introducing the prescribedForce doesn't seem to impact the actuator values even with a force value of 1000.

I'm puzzled about what might be happening here. Any help is greatly appreciated.

Thank you in advance!

POST REPLY