API 4.4.1-2022-10-19-2c4045e59
For MATLAB, Python, Java, and C++ users
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
2import opensim as osim
3import exampleIMUTracking_helpers as helpers
4# Add the directory above to access mocoPlotTrajectory.py
5import sys
6sys.path.insert(1, '../')
7import mocoPlotTrajectory as plot
8import numpy as np
9import os
10
11
15model = 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#
23helpers.addIMUFrame(model, 'torso',
24 osim.Vec3(0.08, 0.3, 0), osim.Vec3(0, 0.5*np.pi, 0.5*np.pi))
25helpers.addIMUFrame(model, 'femur_r',
26 osim.Vec3(0, -0.2, 0.05), osim.Vec3(0, 0, 0.5*np.pi))
27helpers.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.
33imuFramePaths = osim.StdVectorString()
34imuFramePaths.append( )
35imuFramePaths.append( )
36imuFramePaths.append( )
37osim.OpenSenseUtilities().addModelIMUs(model, imuFramePaths)
38model.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
71problem.setTimeBounds( )
72
73# Position bounds: the model should start in a squat and finish
74# standing up.
75problem.setStateInfo('/jointset/hip_r/hip_flexion_r/value', )
76problem.setStateInfo('/jointset/knee_r/knee_angle_r/value', )
77problem.setStateInfo('/jointset/ankle_r/ankle_angle_r/value', )
78
79# Velocity bounds: all model coordinates should start and end at rest.
80problem.setStateInfoPattern('/jointset/.*/speed', )
81
82# Part 2d: Add a MocoControlGoal to the problem.
83
84
85# Part 2e: Configure the solver.
86solver = study.initCasADiSolver()
87solver.set_num_mesh_intervals( )
88solver.set_optim_constraint_tolerance( )
89solver.set_optim_convergence_tolerance( )
90
91if 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.
108outputPaths = osim.StdVectorString()
109outputPaths.append( )
110accelerometerSignals = 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.
118accelerometerSignals.setColumnLabels(imuFramePaths)
119
120# Part 3d: Plot the synthetic acceleration signals.
121helpers.plotAccelerationSignals(accelerometerSignals)
122
123
130tracking =
131tracking.setFramePaths( )
132tracking.setAccelerationReference( )
133tracking.setGravityOffset( )
134tracking.setExpressAccelerationsInTrackingFrames( )
135problem.addGoal( )
136
137# Part 4b: Reduce the control cost weight so that the tracking term will
138# dominate.
139
140
141if not os.path.isfile('trackingSolution.sto'):
142 # Part 4c: Solve! Write the solution to file, and visualize.
143
144
145
146
149plot.mocoPlotTrajectory('predictSolution.sto', 'trackingSolution.sto',
150 'predict', 'track')
151
152# Part 5b: Compare accelerations from tracking solution to the reference
153# accelerations.
154trackingSolution = osim.MocoTrajectory('trackingSolution.sto')
155accelerometerSignalsTracking = osim.analyzeVec3(model,
156 trackingSolution.exportToStatesTable(),
157 trackingSolution.exportToControlsTable(),
158 outputPaths)
159accelerometerSignalsTracking.setColumnLabels(imuFramePaths)
160helpers.plotAccelerationSignals(accelerometerSignals,
161 accelerometerSignalsTracking)