API  4.5
For C++ developers
exampleIMUTracking.py

This is an example that uses a squat-to-stand motion to create synthetic accelerometer data, and then creates a tracking simulation to track the synthetic accelerometer signals. 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 
2 import opensim as osim
3 import exampleIMUTracking_helpers as helpers
4 # Add the directory above to access mocoPlotTrajectory.py
5 import sys
6 sys.path.insert(1, '../')
7 import mocoPlotTrajectory as plot
8 import numpy as np
9 import os
10 
11 
15 model = helpers.getTorqueDrivenSquatToStandModel()
16 
17 # Part 1b: Add frames to the model that will represent our IMU locations.
18 # The function addIMUFrame() adds a PhysicalOffsetFrame to a body at a
19 # specified location and orientation. Each frame is added at the path:
20 #
21 # /bodyset/<body_name>/<body_name>_imu_offset
22 #
23 helpers.addIMUFrame(model, 'torso',
24  osim.Vec3(0.08, 0.3, 0), osim.Vec3(0, 0.5*np.pi, 0.5*np.pi))
25 helpers.addIMUFrame(model, 'femur_r',
26  osim.Vec3(0, -0.2, 0.05), osim.Vec3(0, 0, 0.5*np.pi))
27 helpers.addIMUFrame(model, 'tibia_r', osim.Vec3(0, -0.2, 0.05),
28  osim.Vec3(0, 0, 0.5*np.pi))
29 
30 # Part 1c: Add IMU components to the model using the PhysicalOffsetFrames
31 # we just added to the model. We'll use the helper function addModelIMUs()
32 # included with OpenSenseUtilities.
33 imuFramePaths = osim.StdVectorString()
34 imuFramePaths.append( )
35 imuFramePaths.append( )
36 imuFramePaths.append( )
37 osim.OpenSenseUtilities().addModelIMUs(model, imuFramePaths)
38 model.initSystem()
39 
40 
44 
45 # Part 2a: Create a new MocoStudy.
46 
47 
48 # Part 2b: Initialize the problem and set the model.
49 
50 
51 # Part 2c: Set bounds on the problem.
52 #
53 # problem.setTimeBounds(initial_bounds, final_bounds)
54 # problem.setStateInfo(path, trajectory_bounds, inital_bounds, final_bounds)
55 #
56 # All *_bounds arguments can be set to a range, [lower upper], or to a
57 # single value (equal lower and upper bounds). Empty brackets, [], indicate
58 # using default bounds (if they exist). You may set multiple state infos at
59 # once using setStateInfoPattern():
60 #
61 # problem.setStateInfoPattern(pattern, trajectory_bounds, inital_bounds, ...
62 # final_bounds)
63 #
64 # This function supports regular expressions in the 'pattern' argument;
65 # use '.*' to match any substring of the state/control path
66 # For example, the following will set all coordinate value state infos:
67 #
68 # problem.setStateInfoPattern('/path/to/states/.*/value', ...)
69 
70 # Time bounds
71 problem.setTimeBounds( )
72 
73 # Position bounds: the model should start in a squat and finish
74 # standing up.
75 problem.setStateInfo('/jointset/hip_r/hip_flexion_r/value', )
76 problem.setStateInfo('/jointset/knee_r/knee_angle_r/value', )
77 problem.setStateInfo('/jointset/ankle_r/ankle_angle_r/value', )
78 
79 # Velocity bounds: all model coordinates should start and end at rest.
80 problem.setStateInfoPattern('/jointset/.*/speed', )
81 
82 # Part 2d: Add a MocoControlGoal to the problem.
83 
84 
85 # Part 2e: Configure the solver.
86 solver = study.initCasADiSolver()
87 solver.set_num_mesh_intervals( )
88 solver.set_optim_constraint_tolerance( )
89 solver.set_optim_convergence_tolerance( )
90 
91 if not os.path.isfile('predictSolution.sto'):
92  # Part 2f: Solve! Write the solution to file, and visualize.
93 
94 
95 
96 
101 
102 # Part 3a: Load the prediction solution.
103 
104 
105 # Part 3b: Compute the accelerometer signals using the analyzeVec3() free
106 # function included with SimulationUtilities. These free functions can be
107 # accessed in scripting by using the 'opensimSimulation' prefix.
108 outputPaths = osim.StdVectorString()
109 outputPaths.append( )
110 accelerometerSignals = osim.analyzeVec3(model,
111  predictSolution.exportToStatesTable(),
112  predictSolution.exportToControlsTable(),
113  outputPaths)
114 
115 # Part 3c: Update the column labels of the accelerometer signals to match
116 # the offset frame paths. This is necessary for the tracking goal we'll add
117 # to the problem in Part 4.
118 accelerometerSignals.setColumnLabels(imuFramePaths)
119 
120 # Part 3d: Plot the synthetic acceleration signals.
121 helpers.plotAccelerationSignals(accelerometerSignals)
122 
123 
130 tracking =
131 tracking.setFramePaths( )
132 tracking.setAccelerationReference( )
133 tracking.setGravityOffset( )
134 tracking.setExpressAccelerationsInTrackingFrames( )
135 problem.addGoal( )
136 
137 # Part 4b: Reduce the control cost weight so that the tracking term will
138 # dominate.
139 
140 
141 if not os.path.isfile('trackingSolution.sto'):
142  # Part 4c: Solve! Write the solution to file, and visualize.
143 
144 
145 
146 
149 plot.mocoPlotTrajectory('predictSolution.sto', 'trackingSolution.sto',
150  'predict', 'track')
151 
152 # Part 5b: Compare accelerations from tracking solution to the reference
153 # accelerations.
154 trackingSolution = osim.MocoTrajectory('trackingSolution.sto')
155 accelerometerSignalsTracking = osim.analyzeVec3(model,
156  trackingSolution.exportToStatesTable(),
157  trackingSolution.exportToControlsTable(),
158  outputPaths)
159 accelerometerSignalsTracking.setColumnLabels(imuFramePaths)
160 helpers.plotAccelerationSignals(accelerometerSignals,
161  accelerometerSignalsTracking)