API  4.5.1
For C++ developers
Moco User Guide


Getting started

To learn how to download, install, and run your first Moco example, see the following page:

MocoTools

Moco provides easy-to-use tools for solving for muscle activity that can achieve an observed motion. See the following pages:

These tools derive from the MocoTool class.

Solving custom optimal control problems

If the MocoTools do not satisfy your needs, you can create and solve your own custom optimal control problem using the MocoStudy class.

MocoStudy: custom optimal control problems

Choosing a Model

Moco supports most OpenSim models, including those with kinematic constraints, auxiliary (muscle) dynamics, and passive force components.

Moco does not support models with SimTK::Measures, such as Probes. Some Measures rely on time-stepping forward integration, which does not occur with Moco. This prevents using, for example, the metabolics probes with Moco. See Bhargava2004SmoothedMuscleMetabolics for a metabolics model that is compatible with Moco.

Some model components are supported through Moco but may hinder the solvers from converging quickly. Any components with discontinuous functions can cause issues for the derivative-based optimization algorithms used by Moco. We suggest replacing your model's muscles with DeGrooteFregly2016Muscles and replacing your contact forces with SmoothSphereHalfSpaceForces. These components are designed for use with direct collocation.

Using Controllers with Moco

Moco supports a subset of OpenSim's Controllers. Without a controller, a MocoProblem will contain one control for each ScalarActuator in the model. When a Controller is added to the model, there is no longer necessarily a one-to-one correspondence between model actuators and controls in the optimal control problem.

The following Controllers are currently supported by Moco:

"Model-controlled" versus "OCP-controlled" actuators

By default, if you add a Controller to your model, Moco will not add optimal control variables for the ScalarActuators (i.e., "Model-controlled" actuators) that the Controller controls to the MocoProblem.

Currently, you cannot add controls from the optimal control problem on top of the control values from the Controller. However, control values from multiple Controllers are additive, since this is the behavior in OpenSim.

Controls associated with "Model-controlled" actuators will not be included the MocoSolution (i.e., the solution controls will match the controls listed in the MocoProblem). Therefore, the solution from a MocoStudy that includes a model Controller can be used as an initial guess for a subsequent problem with the same model, just like any other MocoStudy. The utility method MocoTrajectory::generateControlsFromModelControllers() can be used to populate a MocoTrajectory (or MocoSolution) with the controls defined by Controllers in the model, which may be useful for post-hoc analyses and is required for certain utility functions (e.g., MocoUtilities::analyzeMocoTrajectory()).

Configuring a MocoProblem with Controllers

Unless explicitly defined otherwise, MocoGoals will use the control values computed from the underlying Model. These controls will be the combination of the controls from the optimal control problem and the controls computed by any Controllers in the model.

Relevant MocoGoals and MocoPathConstraints have the option to ignore the controls computed by model Controllers if you wish to only use the controls from the optimal control problem in a cost function term or constraint (e.g., MocoControlGoal::setIgnoreControlledActuators and MocoControlBoundConstraint::setIgnoreControlledActuators).

The setting MocoPhase::setBoundActivationFromExcitation() applies to all muscles in the MocoProblem, whether they are controlled by a Controller or not.

InputController support

Certain problems may require a controller that defines actuator controls based on a higher-level control signal from the optimizer. For example, controlling muscles using muscle synergies requires a controller that accepts synergy excitation controls as input and maps them to muscle excitation signals. The synergy excitations would be OCP controls and the synergy controller would use synergy weight vectors to convert them to muscle excitation values.

To support these types of problems, Moco provides InputController, an intermediate abstract class derived from Controller that provides a list Input for mapping scalar control signals from another component to actuator controls. Concrete implementations provide the method getInputControlLabels() which defines the number, order, and labels of Input controls for the InputController. SynergyController is an example of a concrete implementation of InputController that supports the muscle synergy example described above.

Moco adds OCP controls to the MocoProblem for each "Input control" defined by a InputController in the model. The names for Input control variables use the format "<InputController_path>/<Input_control_label>". For example, "/controllerset/synergy_controller/synergy_excitation_0".

Moco separates the notion of a "control", or control variables associated with model actuators, and "Input controls", control variables associated with Inputs to InputControllers. The bounds for an Input control variable can be set using MocoProblem::setInputControlInfo() or MocoProblem::setInputControlInfoPattern(). MocoTrajectory provides get (e.g., getInputControl(), getInputControlNames()), set (e.g., setInputControl()), and utility (e.g., exportToInputControlsTable()) methods for accessing or modifying Input controls. MocoSolutions will include Input controls associated with a solved MocoProblem, and the Input controls trajectory can be accessed via MocoTrajectory::getInputControlsTrajectory(). Finally, the method MocoTrajectory::generateControlsFromModelControllers() also supports Input controls: the Input control trajectories are used to compute the associated model control trajectories via the InputControllers in the model.

MocoGoals and MocoPathConstraints that rely on control variables now also support Input control variables. See MocoControlGoal, MocoControlTrackingGoal, MocoPeriodicityGoal, and MocoControlBoundConstraint for details on how each handle Input control variables.

The following InputControllers are currently supported by Moco:

Defining a custom goal or cost

Moco allows you to compose your cost from multiple existing cost terms. This gives you flexibility and means that you usually do not need to write your cost yourself, even if it has many terms. Moco's existing costs are usually well-tested and work well with Moco's solvers, so we encourage you to use them if possible. In the case that you want to create your own custom cost term, you can derive from MocoGoal in C++. See exampleSlidingMassAdvanced.cpp and exampleMocoCustomEffortGoal.cpp.

If you do not want to write C++ code, you can prototype your cost in MATLAB and we can help convert it to C++. See the Matlab example examplePrototypeCustomGoal.m for more information.

In the future, Moco could allow you to define custom cost terms in Python. If this is of interest to you, please let the Moco developers know (on GitHub).

Sealed solutions or trajectories

Moco uses the MocoTrajectory and MocoSolution classes to hold initial guesses and solutions to optimal control problems. Solving a problem (MocoStudy::solve()) returns a MocoSolution. If the solver failed to converge, the solution will be sealed (MocoTrajectory::isSealed()), which means that you cannot do anything with the it (read, edit, or write) until you call MocoTrajectory::unseal(). The sealing forces you to acknowledge that the solver failed.

Utilities

OpenSim and Moco contain utilities for creating models, modifying models, working with data, and postprocessing results.

  1. ModelFactory: Create standard models and modify existing models.
  2. ModelProcessor: Create a workflow of operations to perform on a model.
  3. TableProcessor: Create a workflow of operations to perform on a table.
  4. Moco Utilities, including visualizing and analyzing a MocoTrajectory.
  5. plot_trajectory.py: Plot a MocoTrajectory with the Python Matplotlib plotting library.
  6. report.py: Generate a detailed PDF report about a MocoTrajectory and any reference data (part of the opensim Python package).

Frequently Asked Questions

See Moco frequently asked questions.

Cheat sheet

This short PDF shows common Moco commands, and makes for a nice desk-side companion.