This is an example using the MocoInverse tool with a complex model to prescribe walking. This example also shows how to track electromyography data.
#include <OpenSim/Actuators/ModelOperators.h>
#include <OpenSim/Common/Adapters.h>
#include <OpenSim/Moco/osimMoco.h>
void solveMocoInverse() {
inverse.
setName(
"example3DWalking_MocoInverse");
modelProcessor.
append(ModOpAddExternalLoads(
"grf_walk.xml"));
modelProcessor.
append(ModOpIgnoreTendonCompliance());
modelProcessor.
append(ModOpReplacePathsWithFunctionBasedPaths(
"subject_walk_scaled_FunctionBasedPathSet.xml"));
modelProcessor.
append(ModOpAddReserves(1.0));
"example3DWalking_MocoInverse_solution.sto");
}
void solveMocoInverseWithEMG() {
inverse.
setName(
"example3DWalking_MocoInverseWithEMG");
modelProcessor.append(ModOpAddExternalLoads("grf_walk.xml"));
modelProcessor.append(ModOpIgnoreTendonCompliance());
modelProcessor.append(ModOpReplacePathsWithFunctionBasedPaths(
"subject_walk_scaled_FunctionBasedPathSet.xml"));
modelProcessor.append(ModOpAddReserves(1.0));
controlsRef.updDependentColumn("soleus") *= 0.77;
controlsRef.updDependentColumn("gastrocnemius") *= 0.87;
controlsRef.updDependentColumn("tibialis_anterior") *= 0.37;
tracking->setReference(controlsRef);
tracking->setReferenceLabel("/forceset/soleus_r", "soleus");
tracking->setReferenceLabel("/forceset/gasmed_r", "gastrocnemius");
tracking->setReferenceLabel("/forceset/gaslat_r", "gastrocnemius");
tracking->setReferenceLabel("/forceset/tibant_r", "tibialis_anterior");
solution.
write(
"example3DWalking_MocoInverseWithEMG_solution.sto");
controlsRef.removeColumn("medial_hamstrings");
controlsRef.removeColumn("biceps_femoris");
controlsRef.removeColumn("vastus_lateralis");
controlsRef.removeColumn("vastus_medius");
controlsRef.removeColumn("rectus_femoris");
controlsRef.removeColumn("gluteus_maximus");
controlsRef.removeColumn("gluteus_medius");
controlsRef.setColumnLabels({"/forceset/soleus_r", "/forceset/gasmed_r",
"/forceset/tibant_r"});
controlsRef.appendColumn("/forceset/gaslat_r",
controlsRef.getDependentColumn("/forceset/gasmed_r"));
}
void solveMocoInverseWithSynergies(int numSynergies = 5) {
modelProcessor.append(ModOpAddExternalLoads("grf_walk.xml"));
modelProcessor.append(ModOpIgnoreTendonCompliance());
modelProcessor.append(ModOpIgnoreActivationDynamics());
modelProcessor.append(ModOpReplacePathsWithFunctionBasedPaths(
"subject_walk_scaled_FunctionBasedPathSet.xml"));
modelProcessor.append(ModOpAddReserves(1.0));
Model model = modelProcessor.process();
MocoTrajectory prevSolution(
"example3DWalking_MocoInverse_solution.sto");
std::vector<std::string> leftControlNames;
std::vector<std::string> rightControlNames;
const auto& name = muscle.getName();
if (name.compare(name.length() - 2, 2, "_l") == 0) {
leftControlNames.push_back(muscle.getAbsolutePathString());
} else if (name.compare(name.length() - 2, 2, "_r") == 0) {
rightControlNames.push_back(muscle.getAbsolutePathString());
}
}
for (const auto& name : leftControlNames) {
}
for (const auto& name : rightControlNames) {
}
int maxIterations = 100;
double tolerance = 1e-6;
SimTK::Matrix Wl;
SimTK::Matrix Hl;
maxIterations, tolerance, Wl, Hl);
SimTK::Matrix Wr;
SimTK::Matrix Hr;
maxIterations, tolerance, Wr, Hr);
leftController->setName("synergy_controller_left_leg");
for (const auto& name : leftControlNames) {
}
for (int i = 0; i < numSynergies; ++i) {
leftController->addSynergyVector(Hl.row(i).transpose().getAsVector());
}
rightController->setName("synergy_controller_right_leg");
for (const auto& name : rightControlNames) {
}
for (int i = 0; i < numSynergies; ++i) {
rightController->addSynergyVector(Hr.row(i).transpose().getAsVector());
}
inverse.
setName(
"example3DWalking_MocoInverseWithSynergies");
problem.
updGoal(
"excitation_effort"));
for (int i = 0; i < numSynergies; ++i) {
std::string nameLeft = fmt::format("/controllerset/"
"synergy_controller_left_leg/synergy_excitation_{}", i);
effort.setWeightForControl(nameLeft, 10);
std::string nameRight = fmt::format("/controllerset/"
"synergy_controller_right_leg/synergy_excitation_{}", i);
effort.setWeightForControl(nameRight, 10);
}
solution.
write(fmt::format(
"example3DWalking_MocoInverseWith{}Synergies_" "solution.sto", numSynergies));
}
int main() {
solveMocoInverse();
solveMocoInverseWithEMG();
int numSynergies = 5;
solveMocoInverseWithSynergies(numSynergies);
return EXIT_SUCCESS;
}