Determining Muscle Forces From MOCO Solution
- Brodie Klosowski
- Posts: 6
- Joined: Sun Sep 10, 2023 8:00 pm
Determining Muscle Forces From MOCO Solution
Hello,
I am trying to make sense of the outputted muscle forces from a tracking simulation I have run. As an example I will use the left soleus muscle.
My main question is, what does the value of /forceset/soleus_l represent? Is it the percentage of the maximum possible muscle force for that muscle or is it the actual force value in Newtons? I would imagine it would be the percentage of the maximum muscle force due to its magnitude and similarity to the activation but would like confirmation before continuing. Also I do not believe it is an issue with my simulation as I checked a solution provided in the Moco examples and it showed a similar trend. Image for reference:
Cheers in Advance
I am trying to make sense of the outputted muscle forces from a tracking simulation I have run. As an example I will use the left soleus muscle.
My main question is, what does the value of /forceset/soleus_l represent? Is it the percentage of the maximum possible muscle force for that muscle or is it the actual force value in Newtons? I would imagine it would be the percentage of the maximum muscle force due to its magnitude and similarity to the activation but would like confirmation before continuing. Also I do not believe it is an issue with my simulation as I checked a solution provided in the Moco examples and it showed a similar trend. Image for reference:
Cheers in Advance
- Pasha van Bijlert
- Posts: 227
- Joined: Sun May 10, 2020 3:15 am
Re: Determining Muscle Forces From MOCO Solution
Hi Brodie,
Moco automatically adds a controller to each muscle when you run an optimization. It computes the control inputs (i.e., muscle excitation signals) or whatever problem you've defined. These are normalized (so between 0 &1, or perhaps bounded between 0.00001 & 1 or similar). Control input (or muscle excitations) result a change in muscle activation (or muscle active state) via 1st order dynamics. You can actually see this in your graph - the muscle's activation basically follows the excitatory input, but is slightly delayed and slightly smoother. Activate state is also bounded between 0 - 1. You can think of these both as percentages.
A Hill-type muscle's force depends on active state, length, and contraction velocity. What you're after is the output "normalized tendon force" (since force in the tendon should be equal to force in the muscle fiber, if the muscle is equilibriated). This will also be bounded between 0 - 1, where 1 represents maximal isometric force (F_max) in Newtons. So you need to plot each muscle's normalized tendon force multiplied by its F_max.
Cheers,
Pasha
Moco automatically adds a controller to each muscle when you run an optimization. It computes the control inputs (i.e., muscle excitation signals) or whatever problem you've defined. These are normalized (so between 0 &1, or perhaps bounded between 0.00001 & 1 or similar). Control input (or muscle excitations) result a change in muscle activation (or muscle active state) via 1st order dynamics. You can actually see this in your graph - the muscle's activation basically follows the excitatory input, but is slightly delayed and slightly smoother. Activate state is also bounded between 0 - 1. You can think of these both as percentages.
A Hill-type muscle's force depends on active state, length, and contraction velocity. What you're after is the output "normalized tendon force" (since force in the tendon should be equal to force in the muscle fiber, if the muscle is equilibriated). This will also be bounded between 0 - 1, where 1 represents maximal isometric force (F_max) in Newtons. So you need to plot each muscle's normalized tendon force multiplied by its F_max.
Cheers,
Pasha
- Brodie Klosowski
- Posts: 6
- Joined: Sun Sep 10, 2023 8:00 pm
Re: Determining Muscle Forces From MOCO Solution
Hi Pasha,
Thanks for the reply.
How would I go about finding the normalised tendon force? Would I need to change something in my simulation code in order for it to be included in the output?
Cheers in advance,
Brodie
Thanks for the reply.
How would I go about finding the normalised tendon force? Would I need to change something in my simulation code in order for it to be included in the output?
Cheers in advance,
Brodie
- Ross Miller
- Posts: 375
- Joined: Tue Sep 22, 2009 2:02 pm
Re: Determining Muscle Forces From MOCO Solution
Hi Brodie,
The solution matrix/file from a Moco solution (.sto file) includes the time-varying values of the model's states and controls. If the normalized_tendon_force variables Pasha mentioned are not in your simulation's solution, it probably means your model has rigid tendons, which means the tendon forces are not state variables (the forces are uniquely determined by muscle activations and joint kinematics).
There is surely a post-hoc analysis (e.g. "MuscleAnalysis" class, I would guess) that can compute the various fiber/tendon forces, but for those forces to be state variables in the solution, the tendons need to be set as non-rigid.
Hope this helps!
Ross
The solution matrix/file from a Moco solution (.sto file) includes the time-varying values of the model's states and controls. If the normalized_tendon_force variables Pasha mentioned are not in your simulation's solution, it probably means your model has rigid tendons, which means the tendon forces are not state variables (the forces are uniquely determined by muscle activations and joint kinematics).
There is surely a post-hoc analysis (e.g. "MuscleAnalysis" class, I would guess) that can compute the various fiber/tendon forces, but for those forces to be state variables in the solution, the tendons need to be set as non-rigid.
Hope this helps!
Ross
- Brodie Klosowski
- Posts: 6
- Joined: Sun Sep 10, 2023 8:00 pm
Re: Determining Muscle Forces From MOCO Solution
Hello,
Wouldn't using this muscle analysis tool defeat the purpose of trying to find the muscle forces from the tracking simulation? Or am I misunderstanding this.
It just seems odd that almost every example simulation code I have seen uses the operator "ModOpIgnoreTendonCompliance" when doing this supposedly removes the ability to get the muscle forces from the simulation output.
Cheers
Wouldn't using this muscle analysis tool defeat the purpose of trying to find the muscle forces from the tracking simulation? Or am I misunderstanding this.
It just seems odd that almost every example simulation code I have seen uses the operator "ModOpIgnoreTendonCompliance" when doing this supposedly removes the ability to get the muscle forces from the simulation output.
Cheers
- Nicholas Bianco
- Posts: 1050
- Joined: Thu Oct 04, 2012 8:09 pm
Re: Determining Muscle Forces From MOCO Solution
Hi Brodie,
You can use MocoStudy::analyze() to compute muscle forces from a MocoSolution. You need to provide the second argument "outputPaths", which is a list of paths to Outputs in the model for which you want to compute values. You can find the list of Muscle Outputs here. The Output path format is as follows: "/path/to/my_component|output_name".
Best,
Nick
You can use MocoStudy::analyze() to compute muscle forces from a MocoSolution. You need to provide the second argument "outputPaths", which is a list of paths to Outputs in the model for which you want to compute values. You can find the list of Muscle Outputs here. The Output path format is as follows: "/path/to/my_component|output_name".
Best,
Nick
- Brodie Klosowski
- Posts: 6
- Joined: Sun Sep 10, 2023 8:00 pm
Re: Determining Muscle Forces From MOCO Solution
Hi Nicholas,
Thank you for that, this is what I am looking for I believe. Is there any chance you could please provide some formatting assistance for me?
I am using MATLAB for this project and I cannot find an example of how to use "MocoStudy::analyze()". I Have tried multiple set ups but whenever I try to use "analyze" MATLAB thinks I am trying to use the analyze function from the radio frequency (RF) toolbox which makes me think I am formatting it wrong. For refference, the code I have tried is:
clc; clear all; close all;
% Import Libraries
import org.opensim.modeling.*;
% Set up moco trajectory from Moco Solution .sto output
tracking_solution = 'gait_solution_single_stride.sto';
traj = MocoTrajectory(tracking_solution);
% Create Moco Study and problem
study = MocoStudy();
study.setName('muscle_force_collection');
problem = study.updProblem();
% Create and assign model processor to problem
modelProcessor = ModelProcessor('subject_walk_onlyNecessaryMarkers.osim');
problem.setModelProcessor(modelProcessor);
% Use study.analyze to find tendon forces
muscle_force = study.analyze(traj, '/forceset/vaslat_r/tendon_force');
%% Attempt at getting all tendon forces
all_muscle_forces = problem.analyze(traj, '.*tendon_force');
I have checked that my MATLAB path is to OpenSim yet I still get this error:
Would greatly appreciate some help on this and thank you in advance.
Brodie
Thank you for that, this is what I am looking for I believe. Is there any chance you could please provide some formatting assistance for me?
I am using MATLAB for this project and I cannot find an example of how to use "MocoStudy::analyze()". I Have tried multiple set ups but whenever I try to use "analyze" MATLAB thinks I am trying to use the analyze function from the radio frequency (RF) toolbox which makes me think I am formatting it wrong. For refference, the code I have tried is:
clc; clear all; close all;
% Import Libraries
import org.opensim.modeling.*;
% Set up moco trajectory from Moco Solution .sto output
tracking_solution = 'gait_solution_single_stride.sto';
traj = MocoTrajectory(tracking_solution);
% Create Moco Study and problem
study = MocoStudy();
study.setName('muscle_force_collection');
problem = study.updProblem();
% Create and assign model processor to problem
modelProcessor = ModelProcessor('subject_walk_onlyNecessaryMarkers.osim');
problem.setModelProcessor(modelProcessor);
% Use study.analyze to find tendon forces
muscle_force = study.analyze(traj, '/forceset/vaslat_r/tendon_force');
%% Attempt at getting all tendon forces
all_muscle_forces = problem.analyze(traj, '.*tendon_force');
I have checked that my MATLAB path is to OpenSim yet I still get this error:
Would greatly appreciate some help on this and thank you in advance.
Brodie
- Nicholas Bianco
- Posts: 1050
- Joined: Thu Oct 04, 2012 8:09 pm
Re: Determining Muscle Forces From MOCO Solution
Hi Brodie,
The correct format in Matlab would be as follows:
The "outputPaths" argument takes a vector or paths; here we need StdVectorString(), our Matlab interface's version of the C++ std::vector<std::string> type. Also note the use of the vertical bar character in the output path.
Best,
Nick
The correct format in Matlab would be as follows:
Code: Select all
study = MocoStudy();
% your study configuration here
solution = study.solve();
outputPaths = StdVectorString();
outputPaths.add('/forceset/vaslat_r|tendon_force');
outputs = study.analyze(solution, outputPaths);
Best,
Nick
- Brodie Klosowski
- Posts: 6
- Joined: Sun Sep 10, 2023 8:00 pm
Re: Determining Muscle Forces From MOCO Solution
Hi Nicholas,
Thank you again. Just to clarify, do I need to change my original simulation (with all the set up, bounds, etc) to a MocoStudy instead of a MocoTrack and run it again in order to get these outputs? Or can I just set up a simple moco study (similar to what I did above) and use the solution I already have?
Cheers,
Brodie
Thank you again. Just to clarify, do I need to change my original simulation (with all the set up, bounds, etc) to a MocoStudy instead of a MocoTrack and run it again in order to get these outputs? Or can I just set up a simple moco study (similar to what I did above) and use the solution I already have?
Cheers,
Brodie
- Nicholas Bianco
- Posts: 1050
- Joined: Thu Oct 04, 2012 8:09 pm
Re: Determining Muscle Forces From MOCO Solution
Hi Brodie,
MocoTrack is just a tool for configuring a MocoStudy for tracking optimization problems. You can access the internally configured MocoStudy using "initialize":
Best,
Nick
MocoTrack is just a tool for configuring a MocoStudy for tracking optimization problems. You can access the internally configured MocoStudy using "initialize":
Code: Select all
track = MocoTrack();
% your tracking problem configuration
study = track.initialize();
solution = study.solve();
outputPaths = StdVectorString();
outputPaths.add('/forceset/vaslat_r|tendon_force');
outputs = study.analyze(solution, outputPaths);
Nick