opensim-moco
opensim-moco copied to clipboard
Decouple control signals and actuators for synergies and speed.
Suggested by B.J. To support synergies
@nickbianco suggested a constraint-based approach. Thinking about this more: we could have a path constraint synergyControls = W * actuatorControls
, use actuatorControls
to actuate the system, and use synergyControls
in the cost function.
Why would you use synergyControls
in the cost function? Doesn't it make more sense to minimize your motor controls?
Otherwise, the synergy controls aren't used for anything.
@antoinefalisse that is a good question. I think we should try minimizing both and see what happens. We'll at least need synergies in a regularization cost term.
Currently, controls in the direct collocation problem are tied 1-to-1 with (scalar) actuators in the model. There are three reasons to decouple the direct collocation controls from the actuators in the model: to support synergies and other such controllers, to allow users to include multiple Controllers in their model (for reflexes, etc.), and to speed up goals that depend only on controls.
MocoPhases should allow users to allocate vectors of controls, provided with a name, and should provide the option to automatically create a named control for each enabled ScalarActuator in the model.
Right now, some goals rely on the coupling through createControlNamesFromModel()
; we should move this to a service provided by the base Goal/MocoProblemRep that are based on controls, rather than actuators.
To speed up goals, we should provide a way for goals to be evaluated using the raw controls directly rather than going through the model.
See branch preprint_DiscreteController
.
If there are no user-defined actuators, bounds will apply only directly to the DC controls. If there are additional actuators, we must ensure the actuators' max control is not exceeded, so we need additional internal path constraints. These will be somewhat redundant, but we need to ensure that the sum of all controls contributed by all controls does not exceed what the actuator can handle. Or, alternatively, it's not a bound but the Controller/Actuator class just lets the control saturate (using clamp). I'm not sure yet where the clamping belongs.
@carmichaelong , you might have insight on where generic control clamping belongs.
I definitely thought about this a lot, but all I ever ended up realizing was it was depended on the user's application. Could always just do a clamp step right before injecting a final value into a controller/actuator (assuming you have a step that adds them up separately), but it seems like that might cause some issues for a synergy constraints?
The ControllerSet (or the Model?) sums up the controls from all Controllers. The I don't know what people do when synergies lead an individual's muscle activation to exceed 1.
The central place to do the clamping would be somewhere here: https://github.com/opensim-org/opensim-core/blob/654e20e3f092eaf18aba3ca904cc502e20e7bb68/OpenSim/Simulation/Model/Model.cpp#L1878-L1909
I guess I agree that it depends on the application.
As a separate note, when Moco fully decouples controls and actuators, we may need to create a Controller that users can add to a Model that allows users to conduct forward simulations using the controls from Moco. Maybe ControlSetController can handle this; a MocoSolution could produce the required controller.
Oh you meant including core side as well. A (possibly) relevant discussion about this type of thing can be found in https://github.com/opensim-org/opensim-core/issues/2035.