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

This is an example that uses the MocoInverse tool and EMG data to create an EMG-driven simulation of walking. 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 exampleEMGTracking_helpers as helpers
4import os
5import numpy as np
6
7
10
11# Part 1a: Load a 19 degree-of-freedom model with 18 lower-limb,
12# sagittal-plane muscles and a torque-actuated torso. This includes a set of
13# ground reaction forces applied to the model via ExternalLoads, which is
14# necessary for the muscle redundancy problem. See the function definition
15# at the bottom of this file to see how the model is loaded and constructed.
16model = helpers.getWalkingModel()
17
18# Part 1b: Create the MocoInverse tool and set the Model.
19
20
21# Part 1c: Create a TableProcessor using the coordinates file from inverse
22# kinematics.
23
24
25# Part 1d: Set the kinematics reference for MocoInverse using the
26# TableProcessor we just created.
27
28
29# Part 1e: Provide the solver settings: initial and final time, the mesh
30# interval, and the constraint and convergence tolerances.
31inverse.set_initial_time( )
32inverse.set_final_time( )
33inverse.set_mesh_interval( )
34inverse.set_constraint_tolerance( )
35inverse.set_convergence_tolerance( )
36
37if not os.path.isfile('effortSolution.sto'):
38 # Part 1f: Solve the problem!
39
40
41
46emgReference = osim.TimeSeriesTable('emg.sto')
47helpers.compareSolutionToEMG(emgReference, 'effortSolution.sto')
48
49
52
53# Part 3a: Call initialize() to get access to the MocoStudy contained within
54# the MocoInverse instance. This will allow us to make additional
55# modifications to the problem not provided by MocoInverse.
56
57
58# Part 3b: Create a MocoControlTrackingGoal, set its weight, and provide
59# the EMG data as the tracking reference. We also need to specify the
60# reference labels for the four muscles whose EMG we will track.
61tracking =
62tracking.setWeight( )
63tracking.setReference( )
64tracking.setReferenceLabel('/forceset/gasmed_l', 'gastrocnemius')
65tracking.setReferenceLabel('/forceset/tibant_l', 'tibialis_anterior')
66tracking.setReferenceLabel('/forceset/bfsh_l', 'biceps_femoris')
67tracking.setReferenceLabel( )
68
69# Part 3c: The EMG signals in the tracking are all normalized to have
70# a maximum value of 1, but the magnitudes of the excitations from the
71# effort minimization solution suggest that these signals should be
72# rescaled. Use addScaleFactor() to add a MocoParameter to the problem that
73# will scale the reference data for the muscles in the tracking cost.
74tracking.addScaleFactor('gastroc_factor', '/forceset/gasmed_l', [0.01, 1.0])
75tracking.addScaleFactor('tibant_factor', '/forceset/tibant_l', [0.01, 1.0])
76tracking.addScaleFactor('bifem_factor', '/forceset/bfsh_l', [0.01, 1.0])
77tracking.addScaleFactor( )
78
79# Part 3d: Add the tracking goal to the problem.
80
81
82# Part 3e: Update the MocoCasADiSolver with the updated MocoProblem using
83# resetProblem().
84solver = osim.MocoCasADiSolver.safeDownCast(study.updSolver())
85solver.resetProblem(problem)
86
87# Part 3f: Tell MocoCasADiSolver that the MocoParameters we added to the
88# problem via addScaleFactor() above do not require initSystem() calls on
89# the model. This provides a large speed-up.
90
91
92if not os.path.isfile('trackingSolution.sto'):
93 # Part 3g: Solve the problem!
94
95
96
97# Part 3h: Get the values of the optimized scale factors.
98trackingSolution = osim.MocoTrajectory('trackingSolution.sto')
99gastroc_factor = trackingSolution.getParameter('gastroc_factor')
100tibant_factor = trackingSolution.getParameter('tibant_factor')
101bifem_factor = trackingSolution.getParameter('bifem_factor')
102gluteus_factor =
103
104
106print('\nOptimized scale factor values:')
107print('------------------------------')
108print('gastrocnemius = ' + str(gastroc_factor))
109print('tibialis anterior = ' + str(tibant_factor))
110print('biceps femoris short head = ' + str(bifem_factor))
111print('gluteus = ' + str(gluteus_factor))
112
113# Part 4b: Re-scale the reference data using the optimized scale factors.
114gastroc = emgReference.updDependentColumn('gastrocnemius')
115tibant = emgReference.updDependentColumn('tibialis_anterior')
116bifem = emgReference.updDependentColumn('biceps_femoris')
117gluteus = emgReference.updDependentColumn('gluteus')
118for t in np.arange(emgReference.getNumRows()):
119 t = int(t) # Convert to Python built-in int type for indexing
120 gastroc[t] = gastroc_factor * gastroc[t]
121 tibant[t] = tibant_factor * tibant[t]
122 bifem[t] = bifem_factor * bifem[t]
123 gluteus[t] = gluteus_factor * gluteus[t]
124
125# Part 4c: Generate the plots. Compare results to the effort minimization
126# solution.
127helpers.compareSolutionToEMG(emgReference, 'effortSolution.sto',
128 'trackingSolution.sto')