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

This is an example that predicts a squat-to-stand movement and optimizes the stiffness of an assistive passive device. This example is used in hands-on workshops, and accordingly has blanks that users must fill in. See exampleSquatToStand_answers.m for a completed version.

1
3import opensim as osim
4import exampleSquatToStand_helpers as helpers
5import mocoPlotTrajectory as plot
6import os
7import numpy as np
8torqueDrivenModel = helpers.getTorqueDrivenModel()
9muscleDrivenModel = helpers.getMuscleDrivenModel()
10
11
13
14
15# Part 1b: Initialize the problem and set the model.
16
17
18# Part 1c: Set bounds on the problem.
19#
20# problem.setTimeBounds(initial_bounds, final_bounds)
21# problem.setStateInfo(path, trajectory_bounds, inital_bounds, final_bounds)
22#
23# All *_bounds arguments can be set to a range, [lower upper], or to a
24# single value (equal lower and upper bounds). Empty brackets, [], indicate
25# using default bounds (if they exist). You may set multiple state infos at
26# once using setStateInfoPattern():
27#
28# problem.setStateInfoPattern(pattern, trajectory_bounds, inital_bounds, ...
29# final_bounds)
30#
31# This function supports regular expressions in the 'pattern' argument;
32# use '.*' to match any substring of the state/control path
33# For example, the following will set all coordinate value state infos:
34#
35# problem.setStateInfoPattern('/path/to/states/.*/value', ...)
36
37# Time bounds
38problem.setTimeBounds( )
39
40# Position bounds: the model should start in a squat and finish
41# standing up.
42problem.setStateInfo('/jointset/hip_r/hip_flexion_r/value', )
43problem.setStateInfo('/jointset/knee_r/knee_angle_r/value', )
44problem.setStateInfo('/jointset/ankle_r/ankle_angle_r/value', )
45
46# Velocity bounds: all model coordinates should start and end at rest.
47problem.setStateInfoPattern('/jointset/.*/speed', )
48
49# Part 1d: Add a MocoControlCost to the problem.
50
51
52# Part 1e: Configure the solver.
53
54
55if not os.path.isfile('predictSolution.sto'):
56 # Part 1f: Solve! Write the solution to file, and visualize.
57
58
59
63
64
65# Part 2b: Add a MocoStateTrackingCost to the problem using the states
66# from the predictive problem (via the TableProcessor we just created).
67# Enable the setAllowUnusedReferences() setting to ignore the controls in
68# the predictive solution.
69
70
71# Part 2c: Reduce the control cost weight so it now acts as a regularization
72# term.
73
74
75# Part 2d: Set the initial guess using the predictive problem solution.
76# Tighten convergence tolerance to ensure smooth controls.
77
78
79if not os.path.isfile('trackingSolution.sto'):
80 # Part 2e: Solve! Write the solution to file, and visualize.
81
82
83
85plot.mocoPlotTrajectory('predictSolution.sto', 'trackingSolution.sto',
86 'predict', 'track')
87
88
90
91
92# Part 4a: Provide the model via a ModelProcessor. Similar to the TableProcessor,
93# you can add operators to modify the base model.
94
95
96# Part 4b: Set the reference kinematics using the same TableProcessor we used
97# in the tracking problem.
98
99
100# Part 4c: Set the time range, mesh interval, and convergence tolerance.
101inverse.set_initial_time( )
102inverse.set_final_time( )
103inverse.set_mesh_interval( )
104inverse.set_convergence_tolerance( )
105inverse.set_constraint_tolerance( )
106
107# Allow extra (unused) columns in the kinematics and minimize activations.
108inverse.set_kinematics_allow_extra_columns(True)
109inverse.set_minimize_sum_squared_activations(True)
110
111# Append additional outputs path for quantities that are calculated
112# post-hoc using the inverse problem solution.
113inverse.append_output_paths('.*normalized_fiber_length')
114inverse.append_output_paths('.*passive_force_multiplier')
115
116# Part 4d: Solve! Write the MocoSolution to file.
117
118
119# Part 4e: Get the outputs we calculated from the inverse solution.
120
121
122
125
126
127# Part 5b: Create a ModelProcessor similar to the previous one, using the same
128# reserve actuator strength so we can compare muscle activity accurately.
129
130
131# Part 5c: Solve! Write solution.
132
133
134
135print('Cost without device: ', solution.getObjective())
136print('Cost with device: ', deviceSolution.getObjective())
137
138# This is a convenience function provided for you. See below for the
139# implementation.
140helpers.compareInverseSolutions(inverseSolution, inverseDeviceSolution)