API  4.5
For C++ developers
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 
3 import opensim as osim
4 import exampleSquatToStand_helpers as helpers
5 import mocoPlotTrajectory as plot
6 import os
7 import numpy as np
8 torqueDrivenModel = helpers.getTorqueDrivenModel()
9 muscleDrivenModel = 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
38 problem.setTimeBounds( )
39 
40 # Position bounds: the model should start in a squat and finish
41 # standing up.
42 problem.setStateInfo('/jointset/hip_r/hip_flexion_r/value', )
43 problem.setStateInfo('/jointset/knee_r/knee_angle_r/value', )
44 problem.setStateInfo('/jointset/ankle_r/ankle_angle_r/value', )
45 
46 # Velocity bounds: all model coordinates should start and end at rest.
47 problem.setStateInfoPattern('/jointset/.*/speed', )
48 
49 # Part 1d: Add a MocoControlCost to the problem.
50 
51 
52 # Part 1e: Configure the solver.
53 
54 
55 if 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 
79 if not os.path.isfile('trackingSolution.sto'):
80  # Part 2e: Solve! Write the solution to file, and visualize.
81 
82 
83 
85 plot.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.
101 inverse.set_initial_time( )
102 inverse.set_final_time( )
103 inverse.set_mesh_interval( )
104 inverse.set_convergence_tolerance( )
105 inverse.set_constraint_tolerance( )
106 
107 # Allow extra (unused) columns in the kinematics and minimize activations.
108 inverse.set_kinematics_allow_extra_columns(True)
109 inverse.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.
113 inverse.append_output_paths('.*normalized_fiber_length')
114 inverse.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 
135 print('Cost without device: ', solution.getObjective())
136 print('Cost with device: ', deviceSolution.getObjective())
137 
138 # This is a convenience function provided for you. See below for the
139 # implementation.
140 helpers.compareInverseSolutions(inverseSolution, inverseDeviceSolution)