Maximize Velocity of a Body Segment

OpenSim Moco is a software toolkit to solve optimal control problems with musculoskeletal models defined in OpenSim using the direct collocation method.
User avatar
Tylan Templin
Posts: 40
Joined: Mon Jan 15, 2018 10:55 am

Maximize Velocity of a Body Segment

Post by Tylan Templin » Tue Jan 04, 2022 3:49 pm

Hi everyone,

I would like to use Moco to maximize the velocity of a certain body segment using MocoOutputGoal.

I am currently adding this as a goal to a tracking simulation with the following lines of code:

Code: Select all

study = track.initialize()
problem = study.updProblem()

bodySet = model.getBodySet()
hand = bodySet.get('hand_r')
hand_vel = hand.getOutput('velocity')
outputGoal = osim.MocoOutputGoal("hand_vel",1)
outputGoal.setOutputPath(hand_vel.getPathName())
problem.addGoal(outputGoal)

solution = study.solve()
     
When I run it I get an error message saying:
"RuntimeError: std::exception in 'OpenSim::MocoSolution OpenSim::MocoStudy::solve() const': Bad dynamic_cast!"

However, if I do not add the MocoOutputGoal it runs just fine.

Any suggestions for how to fix this?

In addition, is it possible to specify a direction of velocity to maximize (i.e. the x component)?

Thanks!

Ty

User avatar
Pasha van Bijlert
Posts: 214
Joined: Sun May 10, 2020 3:15 am

Re: Maximize Velocity of a Body Segment

Post by Pasha van Bijlert » Wed Jan 05, 2022 2:36 am

Hi Tylan,

About your error: MocoOutputGoal accepts a scalar (or double) output, which means that it doesn't accept outputs which are represented as vectors. Body inherits its outputs (including velocity) from Frame, where you can see that Velocity is output as a SpatialVec (two 3-element vectors representing angular and linear velocity). I don't think using non-scalar outputs as goals is currently supported.
Cheers,
Pasha

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

Re: Maximize Velocity of a Body Segment

Post by Ross Miller » Wed Jan 05, 2022 5:10 am

Hi Tylan,

Even if you manage to get this working (I think Pasha is correct concerning SpatialVec), I think MocoOutputGoal attempts to minimize (not maximize) the specified quantity.

It doesn't square the output or anything like that, so you could maybe trick Moco into maximization by setting up the problem such that a "good" solution has velocities in the negative direction.

Alternatively, setting the problem up as a tracking problem with an impossibly-fast target velocity may work.

I haven't tried either of those things, just speculating!

Ross

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

Re: Maximize Velocity of a Body Segment

Post by Aaron Fox » Sun Jan 09, 2022 3:43 pm

Hi Tylan,

Just to add a basic point on top of what Ross mentions, it's been Mentioned by Nick/Chris that giving a goal that minimises a negative weight will result it in maximising the property - which might help in this situation.

Aaron

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

Re: Maximize Velocity of a Body Segment

Post by Nicholas Bianco » Mon Jan 10, 2022 12:09 pm

Setting a negative weight should work, but I actually like Ross' suggesting to using a tracking goal with a very large reference velocity. I have a hunch this might work well.

User avatar
Tylan Templin
Posts: 40
Joined: Mon Jan 15, 2018 10:55 am

Re: Maximize Velocity of a Body Segment

Post by Tylan Templin » Mon Jan 10, 2022 1:19 pm

Thank you for the helpful suggestions! I have a couple of follow up questions:

1. Thank you Pasha for pointing me to the outputs of Frame. I am now using 'linear_velocity' which is a Vec3 instead of a SpatialVec. This still doesn't eliminate the problem of being a non-scalar, but does get one step closer. Is there a way to select a specific component of the Output (i.e. the 'X' component) and then negate that value as a workaround for maximization? I have tried:

Code: Select all

hand_vel = hand.getOutput('linear_velocity')
hand_vel_x_neg = hand_vel.get(0)*-1
But get an error "AttributeError: 'AbstractOutput' object has no attribute 'get' "

2. With the alternative approach, I am unsure how to setup the tracking goal to have an excessively large hand velocity. I know you can set the end state of a particular degree of freedom in the model using something like:

Code: Select all

problem.setStateInfo('/jointset/hand_r/wrist_flex_r/speed', [0, 10000], 0 , 10000)

But that would only "maximize" wrist flexion speed not necessarily the linear velocity of the hand. Can you do something similar with a body rather than a joint? Any other thoughts or suggestions for how to approach the problem?

Thanks again!

Ty

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

Re: Maximize Velocity of a Body Segment

Post by Nicholas Bianco » Tue Jan 11, 2022 12:04 pm

Hi Tylan,

With the current implementation of MocoOutputGoal, you won't be able to minimize/maximum the 'linear_velocity' output since, as you've noted, it's a Vec3 type. We're hoping to add support for Vector types soon.

The setStateInfo() interface can only set bounds and boundary constraints, so if the model can't reach that max speed, the problem will fail. Rather, you can use MocoStateTrackingGoal, and provide a trajectory with a constant, large speed across the entire time range for the coordinate you want to maximum speed for. You could also use MocoTranslationTrackingGoal to specify a Vec3 position trajectory for a body segment; since that requires position trajectory, to maximum speed, you would need to provide a position trajectory with a large slope with an intercept at the body's known initial position.

User avatar
Tylan Templin
Posts: 40
Joined: Mon Jan 15, 2018 10:55 am

Re: Maximize Velocity of a Body Segment

Post by Tylan Templin » Tue Jan 11, 2022 3:22 pm

Thanks Nick!

I believe I would need to use MocoTranslationTrackingGoal since I am trying to maximize the velocity of a body instead of a specific coordinate. However, it seems that to do so I would have to provide a guess for the trajectory for the entire motion. I would like to avoid this so I don't have to make any assumptions about the best way to achieve maximum velocity at the end of the movement. For example, a linear fit wouldn't really be ideal because it is possible that even negative velocities early in the motion would help produce maximum velocity at the end of the motion.

Is there any way in Moco to maximize the end velocity of a body segment? Or would I need a custom goal to do so?

Best,

Ty

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

Re: Maximize Velocity of a Body Segment

Post by Nicholas Bianco » Thu Jan 13, 2022 3:35 pm

Hey Tylan,

Sorry, but I think that's the best option I can come up with for now. As you suggest, you would need a new goal to specifically minimize/maximum the final velocity of a body segment in the way you're looking for.

We're aiming for new updates to MocoOutputGoal and add new MocoGoals in the near future that could be more suited to what you're trying to do.

Best,
Nick

User avatar
Tylan Templin
Posts: 40
Joined: Mon Jan 15, 2018 10:55 am

Re: Maximize Velocity of a Body Segment

Post by Tylan Templin » Fri Mar 04, 2022 3:45 pm

Hi everyone,

I am now trying to write a custom goal for this objective and I have been able to do so by modifying the example in
"opensim-moco-0.4.0-win\Resources\Code\CPP\Plugins\exampleMocoCustomEffortGoal" with the help from this forum post: viewtopicPhpbb.php?f=1815&t=12844&p=0&s ... 4ba939e34c.

However, doing so maximizes the integral of the hand velocity over the entire motion. This is a good first step but my intention is to maximize the maximum hand velocity (which may not necessarily be at the end of the motion).

In the "MocoCustomEffortGoal.cpp" file lines 35-37 are:

Code: Select all

void MocoCustomEffortGoal::calcGoalImpl(
        const GoalInput& input, SimTK::Vector& cost) const {
    cost[0] = input.integral;
}
I would like be be able to do something along the lines of:

Code: Select all

void MocoCustomEffortGoal::calcGoalImpl(
        const GoalInput& input, SimTK::Vector& cost) const {
    //cost[0] = input.integral;
      cost[0] = input.max_element; //where this line returns the max element in the integrand rather than integrating it
}
This seems like it should be relatively straightforward but I am not entirely sure how to do it. Would appreciate any suggestions!

Thanks!

Ty

POST REPLY