API 4.4.1-2022-10-19-2c4045e59
For MATLAB, Python, Java, and C++ users
exampleMocoTrack.py

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

1# -------------------------------------------------------------------------- #
2# OpenSim Moco: exampleMocoTrack.py #
3# -------------------------------------------------------------------------- #
4# Copyright (c) 2019 Stanford University and the Authors #
5# #
6# Author(s): Nicholas Bianco #
7# #
8# Licensed under the Apache License, Version 2.0 (the "License") you may #
9# not use this file except in compliance with the License. You may obtain a #
10# copy of the License at http://www.apache.org/licenses/LICENSE-2.0 #
11# #
12# Unless required by applicable law or agreed to in writing, software #
13# distributed under the License is distributed on an "AS IS" BASIS, #
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15# See the License for the specific language governing permissions and #
16# limitations under the License. #
17# -------------------------------------------------------------------------- #
18
19# This example features two different tracking problems solved using the
20# MocoTrack tool.
21# - The first problem demonstrates the basic usage of the tool interface
22# to solve a torque-driven marker tracking problem.
23# - The second problem shows how to customize a muscle-driven state tracking
24# problem using more advanced features of the tool interface.
25#
26# See the README.txt next to this file for more information.
27
28import os
29import opensim as osim
30
31def torqueDrivenMarkerTracking():
32
33 # Create and name an instance of the MocoTrack tool.
34 track = osim.MocoTrack()
35 track.setName("torque_driven_marker_tracking")
36
37 # Construct a ModelProcessor and add it to the tool. ModelProcessors
38 # accept a base model and allow you to easily modify the model by appending
39 # ModelOperators. Operations are performed in the order that they are
40 # appended to the model.
41 # Create the base Model by passing in the model file.
42 modelProcessor = osim.ModelProcessor("subject_walk_armless.osim")
43 # Add ground reaction external loads in lieu of a ground-contact model.
44 modelProcessor.append(osim.ModOpAddExternalLoads("grf_walk.xml"))
45 # Remove all the muscles in the model's ForceSet.
46 modelProcessor.append(osim.ModOpRemoveMuscles())
47 # Add CoordinateActuators to the model degrees-of-freedom. This ignores the
48 # pelvis coordinates which already have residual CoordinateActuators.
49 modelProcessor.append(osim.ModOpAddReserves(250))
50 track.setModel(modelProcessor)
51
52 # Use this convenience function to set the MocoTrack markers reference
53 # directly from a TRC file. By default, the markers data is filtered at
54 # 6 Hz and if in millimeters, converted to meters.
55 track.setMarkersReferenceFromTRC("marker_trajectories.trc")
56
57 # There is marker data in the 'marker_trajectories.trc' associated with
58 # model markers that no longer exists (i.e. markers on the arms). Set this
59 # flag to avoid an exception from being thrown.
60 track.set_allow_unused_references(True)
61
62 # Increase the global marker tracking weight, which is the weight
63 # associated with the internal MocoMarkerTrackingCost term.
64 track.set_markers_global_tracking_weight(10)
65
66 # Increase the tracking weights for individual markers in the data set
67 # placed on bony landmarks compared to markers located on soft tissue.
68 markerWeights = osim.MocoWeightSet()
69 markerWeights.cloneAndAppend(osim.MocoWeight("R.ASIS", 20))
70 markerWeights.cloneAndAppend(osim.MocoWeight("L.ASIS", 20))
71 markerWeights.cloneAndAppend(osim.MocoWeight("R.PSIS", 20))
72 markerWeights.cloneAndAppend(osim.MocoWeight("L.PSIS", 20))
73 markerWeights.cloneAndAppend(osim.MocoWeight("R.Knee", 10))
74 markerWeights.cloneAndAppend(osim.MocoWeight("R.Ankle", 10))
75 markerWeights.cloneAndAppend(osim.MocoWeight("R.Heel", 10))
76 markerWeights.cloneAndAppend(osim.MocoWeight("R.MT5", 5))
77 markerWeights.cloneAndAppend(osim.MocoWeight("R.Toe", 2))
78 markerWeights.cloneAndAppend(osim.MocoWeight("L.Knee", 10))
79 markerWeights.cloneAndAppend(osim.MocoWeight("L.Ankle", 10))
80 markerWeights.cloneAndAppend(osim.MocoWeight("L.Heel", 10))
81 markerWeights.cloneAndAppend(osim.MocoWeight("L.MT5", 5))
82 markerWeights.cloneAndAppend(osim.MocoWeight("L.Toe", 2))
83 track.set_markers_weight_set(markerWeights)
84
85 # Initial time, final time, and mesh interval. The number of mesh points
86 # used to discretize the problem is computed internally using these values.
87 track.set_initial_time(0.81)
88 track.set_final_time(1.65)
89 track.set_mesh_interval(0.05)
90
91 # Solve! Use track.solve() to skip visualizing.
92 solution = track.solveAndVisualize()
93
94def muscleDrivenStateTracking():
95
96 # Create and name an instance of the MocoTrack tool.
97 track = osim.MocoTrack()
98 track.setName("muscle_driven_state_tracking")
99
100 # Construct a ModelProcessor and set it on the tool. The default
101 # muscles in the model are replaced with optimization-friendly
102 # DeGrooteFregly2016Muscles, and adjustments are made to the default muscle
103 # parameters.
104 modelProcessor = osim.ModelProcessor("subject_walk_armless.osim")
105 modelProcessor.append(osim.ModOpAddExternalLoads("grf_walk.xml"))
106 modelProcessor.append(osim.ModOpIgnoreTendonCompliance())
107 modelProcessor.append(osim.ModOpReplaceMusclesWithDeGrooteFregly2016())
108 # Only valid for DeGrooteFregly2016Muscles.
109 modelProcessor.append(osim.ModOpIgnorePassiveFiberForcesDGF())
110 # Only valid for DeGrooteFregly2016Muscles.
111 modelProcessor.append(osim.ModOpScaleActiveFiberForceCurveWidthDGF(1.5))
112 track.setModel(modelProcessor)
113
114 # Construct a TableProcessor of the coordinate data and pass it to the
115 # tracking tool. TableProcessors can be used in the same way as
116 # ModelProcessors by appending TableOperators to modify the base table.
117 # A TableProcessor with no operators, as we have here, simply returns the
118 # base table.
119 track.setStatesReference(osim.TableProcessor("coordinates.sto"))
120 track.set_states_global_tracking_weight(10)
121
122 # This setting allows extra data columns contained in the states
123 # reference that don't correspond to model coordinates.
124 track.set_allow_unused_references(True)
125
126 # Since there is only coordinate position data in the states references,
127 # this setting is enabled to fill in the missing coordinate speed data using
128 # the derivative of splined position data.
129 track.set_track_reference_position_derivatives(True)
130
131 # Initial time, final time, and mesh interval.
132 track.set_initial_time(0.81)
133 track.set_final_time(1.65)
134 track.set_mesh_interval(0.08)
135
136 # Instead of calling solve(), call initialize() to receive a pre-configured
137 # MocoStudy object based on the settings above. Use this to customize the
138 # problem beyond the MocoTrack interface.
139 study = track.initialize()
140
141 # Get a reference to the MocoControlCost that is added to every MocoTrack
142 # problem by default.
143 problem = study.updProblem()
144 effort = osim.MocoControlGoal.safeDownCast(problem.updGoal("control_effort"))
145
146 # Put a large weight on the pelvis CoordinateActuators, which act as the
147 # residual, or 'hand-of-god', forces which we would like to keep as small
148 # as possible.
149 model = modelProcessor.process()
150 model.initSystem()
151 forceSet = model.getForceSet()
152 for i in range(forceSet.getSize()):
153 forcePath = forceSet.get(i).getAbsolutePathString()
154 if 'pelvis' in str(forcePath):
155 effort.setWeightForControl(forcePath, 10)
156
157 # Solve and visualize.
158 solution = study.solve()
159 study.visualize(solution)
160
161# Solve the torque-driven marker tracking problem.
162# This problem takes a few minutes to solve.
163torqueDrivenMarkerTracking()
164
165# Solve the muscle-driven state tracking problem.
166# This problem could take an hour or more to solve, depending on the number of
167# processor cores available for parallelization. With 12 cores, it takes around
168# 25 minutes.
169muscleDrivenStateTracking()