OpenSim Moco  0.2.0
exampleMocoTrack.cpp

This is an example using the MocoTrack tool with a complex model to track walking.

/* -------------------------------------------------------------------------- *
* OpenSim Moco: exampleMocoTrack.cpp *
* -------------------------------------------------------------------------- *
* Copyright (c) 2019 Stanford University and the Authors *
* *
* Author(s): Nicholas Bianco *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain a *
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* -------------------------------------------------------------------------- */
#include <Moco/osimMoco.h>
#include <Actuators/CoordinateActuator.h>
using namespace OpenSim;
void torqueDrivenMarkerTracking() {
// Create and name an instance of the MocoTrack tool.
MocoTrack track;
track.setName("torque_driven_marker_tracking");
// Construct a ModelProcessor and add it to the tool. ModelProcessors
// accept a base model and allow you to easily modify the model by appending
// ModelOperators. Operations are performed in the order that they are
// appended to the model. In C++, you may use the pipe operator '|' to
// append ModelOperators.
track.setModel(
// Create the base Model by passing in the model file.
ModelProcessor("subject_walk_armless.osim") |
// Add ground reaction external loads in lieu of a ground-contact
// model.
ModOpAddExternalLoads("grf_walk.xml") |
// Remove all the muscles in the model's ForceSet.
// Add CoordinateActuators to the model degrees-of-freedom. This
// ignores the pelvis coordinates which already have residual
// CoordinateActuators.
// Use this convenience function to set the MocoTrack markers reference
// directly from a TRC file. By default, the markers data is filtered at
// 6 Hz and if in millimeters, converted to meters.
track.setMarkersReferenceFromTRC("marker_trajectories.trc");
// There is marker data in the 'marker_trajectories.trc' associated with
// model markers that no longer exists (i.e. markers on the arms). Set this
// flag to avoid an exception from being thrown.
track.set_allow_unused_references(true);
// Increase the global marker tracking weight, which is the weight
// associated with the internal MocoMarkerTrackingGoal term.
track.set_markers_global_tracking_weight(10);
// Increase the tracking weights for individual markers in the data set
// placed on bony landmarks compared to markers located on soft tissue.
MocoWeightSet markerWeights;
markerWeights.cloneAndAppend({"R.ASIS", 20});
markerWeights.cloneAndAppend({"L.ASIS", 20});
markerWeights.cloneAndAppend({"R.PSIS", 20});
markerWeights.cloneAndAppend({"L.PSIS", 20});
markerWeights.cloneAndAppend({"R.Knee", 10});
markerWeights.cloneAndAppend({"R.Ankle", 10});
markerWeights.cloneAndAppend({"R.Heel", 10});
markerWeights.cloneAndAppend({"R.MT5", 5});
markerWeights.cloneAndAppend({"R.Toe", 2});
markerWeights.cloneAndAppend({"L.Knee", 10});
markerWeights.cloneAndAppend({"L.Ankle", 10});
markerWeights.cloneAndAppend({"L.Heel", 10});
markerWeights.cloneAndAppend({"L.MT5", 5});
markerWeights.cloneAndAppend({"L.Toe", 2});
track.set_markers_weight_set(markerWeights);
// Initial time, final time, and mesh interval. The number of mesh points
// used to discretize the problem is computed internally using these values.
track.set_initial_time(0.81);
track.set_final_time(1.65);
track.set_mesh_interval(0.05);
// Solve! The boolean argument indicates to visualize the solution.
MocoSolution solution = track.solve(true);
}
void muscleDrivenStateTracking() {
// Create and name an instance of the MocoTrack tool.
MocoTrack track;
track.setName("muscle_driven_state_tracking");
// Construct a ModelProcessor and set it on the tool. The default
// muscles in the model are replaced with optimization-friendly
// DeGrooteFregly2016Muscles, and adjustments are made to the default muscle
// parameters.
ModelProcessor modelProcessor =
ModelProcessor("subject_walk_armless.osim") |
ModOpAddExternalLoads("grf_walk.xml") |
// Only valid for DeGrooteFregly2016Muscles.
// Only valid for DeGrooteFregly2016Muscles.
track.setModel(modelProcessor);
// Construct a TableProcessor of the coordinate data and pass it to the
// tracking tool. TableProcessors can be used in the same way as
// ModelProcessors by appending TableOperators to modify the base table.
// A TableProcessor with no operators, as we have here, simply returns the
// base table.
track.setStatesReference(TableProcessor("coordinates.sto"));
track.set_states_global_tracking_weight(10);
// This setting allows extra data columns contained in the states
// reference that don't correspond to model coordinates.
track.set_allow_unused_references(true);
// Since there is only coordinate position data the states references, this
// setting is enabled to fill in the missing coordinate speed data using
// the derivative of splined position data.
track.set_track_reference_position_derivatives(true);
// Initial time, final time, and mesh interval.
track.set_initial_time(0.81);
track.set_final_time(1.65);
track.set_mesh_interval(0.08);
// Instead of calling solve(), call initialize() to receive a pre-configured
// MocoStudy object based on the settings above. Use this to customize the
// problem beyond the MocoTrack interface.
MocoStudy study = track.initialize();
// Get a reference to the MocoControlGoal that is added to every MocoTrack
// problem by default.
MocoProblem& problem = study.updProblem();
MocoControlGoal& effort =
dynamic_cast<MocoControlGoal&>(problem.updGoal("control_effort"));
// Put a large weight on the pelvis CoordinateActuators, which act as the
// residual, or 'hand-of-god', forces which we would like to keep as small
// as possible.
Model model = modelProcessor.process();
for (const auto& coordAct : model.getComponentList<CoordinateActuator>()) {
auto coordPath = coordAct.getAbsolutePathString();
if (coordPath.find("pelvis") != std::string::npos) {
effort.setWeightForControl(coordPath, 10);
}
}
// Solve and visualize.
MocoSolution solution = study.solve();
study.visualize(solution);
}
int main() {
// Solve the torque-driven marker tracking problem.
// This problem takes a few minutes to solve.
torqueDrivenMarkerTracking();
// Solve the muscle-driven state tracking problem.
// This problem could take an hour or more to solve, depending on the
// number of processor cores available for parallelization. With 12 cores,
// it takes around 25 minutes.
muscleDrivenStateTracking();
return EXIT_SUCCESS;
}
OpenSim::ModOpIgnoreTendonCompliance
Turn off tendon compliance for all muscles in the model.
Definition: ModelOperators.h:56
OpenSim::MocoStudy::solve
MocoSolution solve() const
Solve the provided MocoProblem using the provided MocoSolver, and obtain the solution to the problem.
OpenSim::ModOpReplaceMusclesWithDeGrooteFregly2016
Invoke DeGrooteFregly2016Muscle::replaceMuscles() on the model.
Definition: ModelOperators.h:29
OpenSim::ModelProcessor::process
Model process(const std::string &relativeToDirectory={}) const
Process and obtain the model.
Definition: ModelProcessor.h:109
OpenSim::MocoTrack
Definition: MocoTrack.h:157
OpenSim::ModOpAddExternalLoads
Add external loads (e.g., ground reaction forces) to the model from a XML file.
Definition: ModelOperators.h:256
OpenSim::ModelProcessor
This class describes a workflow for processing a Model using ModelOperators.
Definition: ModelProcessor.h:47
OpenSim::MocoStudy::updProblem
MocoProblem & updProblem()
If using this method in C++, make sure to include the "&" in the return type; otherwise,...
OpenSim::ModOpScaleActiveFiberForceCurveWidthDGF
Scale the active fiber force curve width for all DeGrooteFregly2016Muscles in the model.
Definition: ModelOperators.h:138
OpenSim::MocoStudy::visualize
void visualize(const MocoTrajectory &it) const
Interactively visualize a trajectory using the simbody-visualizer.
OpenSim::MocoStudy
The top-level class for solving a custom optimal control problem.
Definition: MocoStudy.h:71
OpenSim
The utilities in this file are categorized as follows:
Definition: About.h:24
OpenSim::ModOpRemoveMuscles
Remove all muscles contained in the model's ForceSet.
Definition: ModelOperators.h:206
OpenSim::MocoTrack::setStatesReference
void setStatesReference(TableProcessor states)
Set the states reference TableProcessor.
Definition: MocoTrack.h:242
OpenSim::MocoSolution
Return type for MocoStudy::solve().
Definition: MocoTrajectory.h:740
OpenSim::MocoProblem
A description of an optimal control problem, backed by OpenSim Models.
Definition: MocoProblem.h:424
OpenSim::ModOpIgnorePassiveFiberForcesDGF
Turn off passive fiber forces for all DeGrooteFregly2016Muscles in the model.
Definition: ModelOperators.h:122
OpenSim::MocoControlGoal
Minimize the sum of the absolute value of the controls raised to a given exponent,...
Definition: MocoControlGoal.h:53
OpenSim::MocoProblem::updGoal
MocoGoal & updGoal(const std::string &name)
Returns a reference to the goal with name "name" in phase 0.
OpenSim::MocoTrack::setMarkersReferenceFromTRC
void setMarkersReferenceFromTRC(const std::string &filename, double lowpassFilterFreq=6.0)
Set the markers reference directly from a TRC file.
Definition: MocoTrack.h:256
OpenSim::MocoWeightSet
A container for Moco weights.
Definition: MocoWeightSet.h:56
OpenSim::TableProcessor
This class describes a workflow for processing a table using TableOperators.
Definition: TableProcessor.h:47
OpenSim::MocoControlGoal::setWeightForControl
void setWeightForControl(const std::string &controlName, const double &weight)
Set the weight to use for the term in the cost associated with controlName (the name or path of the c...
OpenSim::ModOpAddReserves
Add reserve actuators to the model using ModelFactory::createReserveActuators.
Definition: ModelOperators.h:218