ClutchedPathSpring in gait simulation using Moco
- Nathan Pickle
- Posts: 12
- Joined: Wed Jan 09, 2013 11:10 am
ClutchedPathSpring in gait simulation using Moco
I'm attempting to use ClutchedPathSpring components to represent an exosuit in a Moco simulation (2D, tracking, half gait cycle with periodicity constraints), and am getting some results I don't fully understand. I've attached a few examples that illustrate the issue I'm seeing.
I started by setting up a simple test case (SimpleLegExample in the attached files) to check that Moco would be able to handle the ClutchedPathSpring. In that example, the knee joint attempts to track a specified trajectory while an external torque is also applied to the knee joint. With the ClutchedPathSpring stiffness set to 500 N/m, Moco appeared to generate a reasonable control signal for the ClutchedPathSpring, and the knee tracked the desired trajectory reasonably well also. I took this as confirmation that the ClutchedPathSpring was compatible with Moco and moved on to setting up gait simulations.
However, when I added ClutchedPathSpring components to my gait simulation, the gait was noticeably altered from the no-exo simulations. The initial posture is altered, and the model "hops" at toe off. I thought this may be due to the force being generated by the ClutchedPathSpring, but even setting stiffness to a very small value (e.g., 0.1 N/m as in the attached example) the gait solution is significantly altered. The Moco setups in the attached GaitNoExo and GaitWithExo examples are identical except for the addition of two ClutchedPathSpring components in the GaitWithExo example. The other difference of note is that the MocoControlGoal weights on the exosuit components are set to 10. The optimization failed to converge with those weights set to 1.
I have tried a number of different settings in Moco (changing weights, changing solver settings, changing ClutchedPathSpring parameters, etc), but have been unable to find a setting that meaningfully influences the Moco solution. My expectation is that because the ClutchedPathSpring generates so little force, Moco should produce a solution that is nearly identical to the no-exo simulation.
My hunch is that the ClutchedPathSpring is somehow causing problems for the solver, but I've run out of ideas for how to isolate the root cause. Any suggestions are welcome!
I started by setting up a simple test case (SimpleLegExample in the attached files) to check that Moco would be able to handle the ClutchedPathSpring. In that example, the knee joint attempts to track a specified trajectory while an external torque is also applied to the knee joint. With the ClutchedPathSpring stiffness set to 500 N/m, Moco appeared to generate a reasonable control signal for the ClutchedPathSpring, and the knee tracked the desired trajectory reasonably well also. I took this as confirmation that the ClutchedPathSpring was compatible with Moco and moved on to setting up gait simulations.
However, when I added ClutchedPathSpring components to my gait simulation, the gait was noticeably altered from the no-exo simulations. The initial posture is altered, and the model "hops" at toe off. I thought this may be due to the force being generated by the ClutchedPathSpring, but even setting stiffness to a very small value (e.g., 0.1 N/m as in the attached example) the gait solution is significantly altered. The Moco setups in the attached GaitNoExo and GaitWithExo examples are identical except for the addition of two ClutchedPathSpring components in the GaitWithExo example. The other difference of note is that the MocoControlGoal weights on the exosuit components are set to 10. The optimization failed to converge with those weights set to 1.
I have tried a number of different settings in Moco (changing weights, changing solver settings, changing ClutchedPathSpring parameters, etc), but have been unable to find a setting that meaningfully influences the Moco solution. My expectation is that because the ClutchedPathSpring generates so little force, Moco should produce a solution that is nearly identical to the no-exo simulation.
My hunch is that the ClutchedPathSpring is somehow causing problems for the solver, but I've run out of ideas for how to isolate the root cause. Any suggestions are welcome!
- Attachments
-
- ClutchedPathSpring Examples.zip
- (646.76 KiB) Downloaded 57 times
- Nathan Pickle
- Posts: 12
- Joined: Wed Jan 09, 2013 11:10 am
Re: ClutchedPathSpring in gait simulation using Moco
I've attached a couple of videos showing the "hop" motion I referred to in my previous post. The files are zipped mp4s.
- Attachments
-
- Exosuit.zip
- (253.64 KiB) Downloaded 79 times
-
- NoExosuit.zip
- (290.58 KiB) Downloaded 67 times
- Ross Miller
- Posts: 375
- Joined: Tue Sep 22, 2009 2:02 pm
Re: ClutchedPathSpring in gait simulation using Moco
Hi Nathan,
I didn't know about this actuator (ClutchedPathSpring), looks interesting!
The second video doesn't look particularly strange to me, although I agree 0.1 N/m shouldn't have an appreciable effect on the gait. Is everything else identical between the models, e.g. is the actuator massless? How big is the dissipation constant? I couldn't find the default value in the documentation.
The description of ClutchedPathSpring sounds like the dynamics are discontinuous (stiffness abruptly becomes k at u=1 and abruptly becomes 0 at u=0), which might be the cause of the convergence issue. What does the control signal for that actuator look like?
Ross
I didn't know about this actuator (ClutchedPathSpring), looks interesting!
The second video doesn't look particularly strange to me, although I agree 0.1 N/m shouldn't have an appreciable effect on the gait. Is everything else identical between the models, e.g. is the actuator massless? How big is the dissipation constant? I couldn't find the default value in the documentation.
The description of ClutchedPathSpring sounds like the dynamics are discontinuous (stiffness abruptly becomes k at u=1 and abruptly becomes 0 at u=0), which might be the cause of the convergence issue. What does the control signal for that actuator look like?
Ross
- Nathan Pickle
- Posts: 12
- Joined: Wed Jan 09, 2013 11:10 am
Re: ClutchedPathSpring in gait simulation using Moco
Hi Ross - thanks for your thoughts.
The ClutchedPathSpring components are massless, so that shouldn't be an issue. The default dissipation is 0.3, but I lowered it to 0.01 for this example.
You are correct about the dynamics being discontinuous, though there are some nuances. If the control input u is greater than zero, the clutch is engaged and the spring stretches, producing force. However, the spring tension is scaled by the control signal value (see code snippet below). In practice, this means that if you set the control to u=1.0 and apply a force F, the spring will stretch to length L. However, if you set the control to u=0.5 and apply the same force F, the spring will stretch to length 2L. I think this may "soften" the discontinuity a bit, though I'm not certain about that.
In my gait simulaiton, Moco does produce controls very near zero, though in writing this reply I noticed that they are above what OpenSim defines as "zero", so the clutch is still engaged throughout the simulation. I am going to try modifying the threshold at which the clutch engages and see if that changes the results at all.
The ClutchedPathSpring components are massless, so that shouldn't be an issue. The default dissipation is 0.3, but I lowered it to 0.01 for this example.
You are correct about the dynamics being discontinuous, though there are some nuances. If the control input u is greater than zero, the clutch is engaged and the spring stretches, producing force. However, the spring tension is scaled by the control signal value (see code snippet below). In practice, this means that if you set the control to u=1.0 and apply a force F, the spring will stretch to length L. However, if you set the control to u=0.5 and apply the same force F, the spring will stretch to length 2L. I think this may "soften" the discontinuity a bit, though I'm not certain about that.
Code: Select all
double ClutchedPathSpring::computeActuation(const SimTK::State& s) const
{
// clamp or cap the control input to [0, 1]
double control = SimTK::clamp(0.0, getControl(s), 1.0);
double tension = control *
(getStiffness()*getStretch(s) * //elastic force
(1+getDissipation()*getLengtheningSpeed(s))); //dissipation
setActuation(s, tension);
return tension;
}
- Ross Miller
- Posts: 375
- Joined: Tue Sep 22, 2009 2:02 pm
Re: ClutchedPathSpring in gait simulation using Moco
Hi Nathan,
I want to try out this actuator as a model of a prosthetic knee. How did you define the geometry of the spring? As a "path spring" I assume you define the coordinates of the path somewhere (similar to a muscle in OpenSim) but I don't seen anything like that in the ClutchedPathSpring documentation:
https://simtk.org/api_docs/opensim/api_ ... pring.html
EDIT: Never mind, I figured the geometry part out! Now however I'm getting an error when I initialize the MocoStudy with the model that has the ClutchedPathSpring (named "prosthetic_knee_r" in my model):
Any ideas?
Ross
I want to try out this actuator as a model of a prosthetic knee. How did you define the geometry of the spring? As a "path spring" I assume you define the coordinates of the path somewhere (similar to a muscle in OpenSim) but I don't seen anything like that in the ClutchedPathSpring documentation:
https://simtk.org/api_docs/opensim/api_ ... pring.html
EDIT: Never mind, I figured the geometry part out! Now however I'm getting an error when I initialize the MocoStudy with the model that has the ClutchedPathSpring (named "prosthetic_knee_r" in my model):
Code: Select all
java.lang.RuntimeException: No info available for state '/forceset/prosthetic_knee_r/stretch'.
Ross
- Nathan Pickle
- Posts: 12
- Joined: Wed Jan 09, 2013 11:10 am
Re: ClutchedPathSpring in gait simulation using Moco
Hi Ross,
Sorry for the delay, just saw your post. You may have figured this out already, but you'll need to add state info (e.g., max and min) for the "stretch" state of the ClutchedPathSpring. Stretch is the change in length of the spring from it's resting length, so you can set it accordingly. I typically used:
So the bounds are 0 and 1, and the initial value is 0.
As a general update on this topic - I was able to solve the issue I was having by creating a customized version of the PathSpring class. A key difference between PathSpring and ClutchedPathSpring is that the PathSpring is a passive model component, whereas ClutchedPathSpring is an actuator. I achieved the desired behavior by adding properties to the spring component that allow me to specify a time range during which the spring produces force. Outside of that time range it just produces zero force. It's a bit of a hack, but it's working for my use case.
Sorry for the delay, just saw your post. You may have figured this out already, but you'll need to add state info (e.g., max and min) for the "stretch" state of the ClutchedPathSpring. Stretch is the change in length of the spring from it's resting length, so you can set it accordingly. I typically used:
Code: Select all
problem.setStateInfo(stateName, [0,1],0)
So the bounds are 0 and 1, and the initial value is 0.
As a general update on this topic - I was able to solve the issue I was having by creating a customized version of the PathSpring class. A key difference between PathSpring and ClutchedPathSpring is that the PathSpring is a passive model component, whereas ClutchedPathSpring is an actuator. I achieved the desired behavior by adding properties to the spring component that allow me to specify a time range during which the spring produces force. Outside of that time range it just produces zero force. It's a bit of a hack, but it's working for my use case.
- Ross Miller
- Posts: 375
- Joined: Tue Sep 22, 2009 2:02 pm
Re: ClutchedPathSpring in gait simulation using Moco
Thanks Nathan. My issue seems to be that I'm using MocoTrack to create the MocoStudy, and when I initialize that study to create the study and the problem, it needs the info for the stretch state, but I ca'nt find a way to specify that info within MocoTrack before doing the initialization.
I think I need to switch to MocoStateTrackingGoal but that's not working well (converging) for me yet.
Ross
I think I need to switch to MocoStateTrackingGoal but that's not working well (converging) for me yet.
Ross
- Nathan Pickle
- Posts: 12
- Joined: Wed Jan 09, 2013 11:10 am
Re: ClutchedPathSpring in gait simulation using Moco
Oh yes, I remember now I ran into that also. I actually brought that up with the dev team: https://github.com/opensim-org/opensim-core/issues/3154
I started trying to add the stretch stateInfo, and ended up basically recreating MocoTrack in Python so I could insert the stateInfo at the right place in the configuration process. It wasn't too bad - there was just the one function mentioned in that Github issue that isn't accessible through the Python API.
I started trying to add the stretch stateInfo, and ended up basically recreating MocoTrack in Python so I could insert the stateInfo at the right place in the configuration process. It wasn't too bad - there was just the one function mentioned in that Github issue that isn't accessible through the Python API.
- Nicholas Bianco
- Posts: 1044
- Joined: Thu Oct 04, 2012 8:09 pm
Re: ClutchedPathSpring in gait simulation using Moco
Hey guys,
If you still want to use the "initialize()" approach with MocoTrack, you should be able to update the problem this and give the solver the updated problem via "resetProblem()":
I agree though, that the "initialize()" approach (for MocoTrack and MocoInverse) still isn't ideal for many use cases, and I'm trying to think of ways to improve it.
-NIck
If you still want to use the "initialize()" approach with MocoTrack, you should be able to update the problem this and give the solver the updated problem via "resetProblem()":
Code: Select all
study = track.initialize();
problem = study.updProblem();
problem.setStateInfo('/forceset/prosthetic_knee_r/stretch', [0,1], 0);
solver = MocoCasADiSolver.safeDownCast(study.updSolver());
solver.resetProblem(problem);
-NIck
- Ross Miller
- Posts: 375
- Joined: Tue Sep 22, 2009 2:02 pm
Re: ClutchedPathSpring in gait simulation using Moco
Hi Nick,
My issue is that I can't do the first line of code in your example [study = track.initialize()] when the model has a ClutchedPathSpring actuator in it. The error about the lack of state info for the stretch variable occurs on that first line of code. I think this was also Nathan's issue. It seems like I need a way to specify the state info for the stretch variable with the setup of the MocoTrack tool and there doesn't seem to a way to do that.
I have it working (I think) now using MocoStateTrackingGoal instead of MocoTrack.
The problem seems unique to ClutchedPathSpring, or at least I haven't found other actuators with this problem. Other non-muscle actuators e.g. ActivationCoordinateActuator work fine with MocoTrack in my experience.
Ross
My issue is that I can't do the first line of code in your example [study = track.initialize()] when the model has a ClutchedPathSpring actuator in it. The error about the lack of state info for the stretch variable occurs on that first line of code. I think this was also Nathan's issue. It seems like I need a way to specify the state info for the stretch variable with the setup of the MocoTrack tool and there doesn't seem to a way to do that.
I have it working (I think) now using MocoStateTrackingGoal instead of MocoTrack.
The problem seems unique to ClutchedPathSpring, or at least I haven't found other actuators with this problem. Other non-muscle actuators e.g. ActivationCoordinateActuator work fine with MocoTrack in my experience.
Ross