Low Muscle Activation
Posted: Wed Nov 02, 2022 9:10 am
Hi All!
I have been working on improving my Moco Inverse solution for walking/running trials, however I continue to get very low muscle activations (primarily < 0.2). I am using implicit tendon dynamics, and have lowered my reserves as much as possible while still allowing the model to run (100). In addition I have set constraint and convergence tolerances to 1e-03 and 1e-02 respectively based on information I have found on the forum. My residuals are all small, on the order or 10^-5. I did a comparison of the running activations to experimental EMG data collected in lab. The comparison normalized both the MocoInverse activations and the experimental EMG activations peak values to 1 which caused them to align pretty well. However, the walking activations do not match EMG data as well and are quite a bit smaller. I have attached the MocoInverse Walking and Running solutions.
Code is listed below:
Thanks!
Molly
I have been working on improving my Moco Inverse solution for walking/running trials, however I continue to get very low muscle activations (primarily < 0.2). I am using implicit tendon dynamics, and have lowered my reserves as much as possible while still allowing the model to run (100). In addition I have set constraint and convergence tolerances to 1e-03 and 1e-02 respectively based on information I have found on the forum. My residuals are all small, on the order or 10^-5. I did a comparison of the running activations to experimental EMG data collected in lab. The comparison normalized both the MocoInverse activations and the experimental EMG activations peak values to 1 which caused them to align pretty well. However, the walking activations do not match EMG data as well and are quite a bit smaller. I have attached the MocoInverse Walking and Running solutions.
Code is listed below:
Code: Select all
% function solveMocoInverse()
import org.opensim.modeling.*;
% Construct the MocoInverse tool.
inverse = MocoInverse();
% Construct a ModelProcessor and set it on the tool. The default
% muscles in the model are replaced with optimization-friendly
% DeGrooteFregly2016Muscles, and adjustments are made to the default muscle
% parameters.
modelProcessor = ModelProcessor('DDH09_SS_0Wlk01_postRRA.osim');
modelProcessor.append(ModOpAddExternalLoads('DDH09_0Wlk01_RRA_GRF.xml'));
modelProcessor.append(ModOpReplaceMusclesWithDeGrooteFregly2016());
% Only valid for DeGrooteFregly2016Muscles.
modelProcessor.append(ModOpIgnorePassiveFiberForcesDGF());
% modelProcessor.append(ModOpIgnoreTendonCompliance());
modelProcessor.append(ModOpUseImplicitTendonComplianceDynamicsDGF());
% Only valid for DeGrooteFregly2016Muscles.
modelProcessor.append(ModOpScaleActiveFiberForceCurveWidthDGF(1.5));
modelProcessor.append(ModOpAddReserves(100, 1));
jointNames = StdVectorString();
jointNames.add('mtp_l');
jointNames.add('mtp_r');
modelProcessor.append(ModOpReplaceJointsWithWelds(jointNames));
inverse.setModel(modelProcessor);
% Construct a TableProcessor of the coordinate data and pass it to the
% inverse tool. TableProcessors can be used in the same way as
% ModelProcessors by appending TableOperators to modify the base table.
% A TableProcessor with no operators, as we have here, simply returns the
% base table.
inverse.setKinematics(TableProcessor('DDH09_SS_0Wlk01_states.sto'));
% inverse.append_output_paths('.*fiber_length');
% Initial time, final time, and mesh interval.
inverse.set_initial_time(3.38);
inverse.set_final_time(4.349);
inverse.set_mesh_interval(0.02);
% By default, Moco gives an error if the kinematics contains extra columns.
% Here, we tell Moco to allow (and ignore) those extra columns.
inverse.set_kinematics_allow_extra_columns(true);
inverse.set_minimize_sum_squared_activations(true);
inverse.set_constraint_tolerance(1e-03);
inverse.set_convergence_tolerance(1e-02);
% Solve the problem and write the solution to a Storage file.
solution = inverse.solve();
solution.getMocoSolution().write('MocoInverse_0Wlk01_solution.sto');
% Generate a report with plots for the solution trajectory.
model = modelProcessor.process();
report = osimMocoTrajectoryReport(model, ...
'MocoInverse_0Wlk01_solution.sto', 'bilateral', true);
% The report is saved to the working directory.
reportFilepath = report.generate();
open(reportFilepath);
Molly