This example conducts a 2-D prediction of walking, employing a MocoPerodicityGoal.
#include <OpenSim/Common/STOFileAdapter.h>
#include <OpenSim/Moco/osimMoco.h>
double stateTrackingWeight = 1,
double GRFTrackingWeight = 1) {
using SimTK::Pi;
for (
const auto& coord : model.getComponentList<
Coordinate>()) {
symmetryGoal->addStatePair({coord.getStateVariableNames()[0],
std::regex_replace(coord.getStateVariableNames()[0],
std::regex("_r"), "_l")});
symmetryGoal->addStatePair({coord.getStateVariableNames()[1],
std::regex_replace(coord.getStateVariableNames()[1],
std::regex("_r"), "_l")});
}
symmetryGoal->addStatePair({coord.getStateVariableNames()[0],
std::regex_replace(coord.getStateVariableNames()[0],
std::regex("_l"), "_r")});
symmetryGoal->addStatePair({coord.getStateVariableNames()[1],
std::regex_replace(coord.getStateVariableNames()[1],
std::regex("_l"), "_r")});
}
symmetryGoal->addStatePair({coord.getStateVariableNames()[0],
coord.getStateVariableNames()[0]});
symmetryGoal->addStatePair({coord.getStateVariableNames()[1],
coord.getStateVariableNames()[1]});
}
}
symmetryGoal->addStatePair({"/jointset/groundPelvis/pelvis_tx/speed"});
symmetryGoal->addControlPair({"/lumbarAct"});
for (
const auto& muscle : model.getComponentList<
Muscle>()) {
symmetryGoal->addStatePair({muscle.getStateVariableNames()[0],
std::regex_replace(muscle.getStateVariableNames()[0],
std::regex("_r"), "_l")});
}
symmetryGoal->addStatePair({muscle.getStateVariableNames()[0],
std::regex_replace(muscle.getStateVariableNames()[0],
std::regex("_l"), "_r")});
}
}
if (GRFTrackingWeight != 0) {
"contact", GRFTrackingWeight);
contactTracking->addContactGroup(
{"contactHeel_r", "contactFront_r"},"Right_GRF");
contactTracking->addContactGroup(
{"contactHeel_l", "contactFront_l"}, "Left_GRF");
contactTracking->setProjection("plane");
contactTracking->setProjectionVector(SimTK::Vec3(0, 0, 1));
}
problem.
setStateInfo(
"/jointset/groundPelvis/pelvis_tilt/value",
{-20 * Pi / 180, -10 * Pi / 180});
problem.
setStateInfo(
"/jointset/groundPelvis/pelvis_tx/value", {0, 1});
"/jointset/groundPelvis/pelvis_ty/value", {0.75, 1.25});
{-10 * Pi / 180, 60 * Pi / 180});
{-10 * Pi / 180, 60 * Pi / 180});
"/jointset/knee_l/knee_angle_l/value", {-50 * Pi / 180, 0});
"/jointset/knee_r/knee_angle_r/value", {-50 * Pi / 180, 0});
problem.
setStateInfo(
"/jointset/ankle_l/ankle_angle_l/value",
{-15 * Pi / 180, 25 * Pi / 180});
problem.
setStateInfo(
"/jointset/ankle_r/ankle_angle_r/value",
{-15 * Pi / 180, 25 * Pi / 180});
problem.
setStateInfo(
"/jointset/lumbar/lumbar/value", {0, 20 * Pi / 180});
full.write("gaitTracking_solution_fullcycle.sto");
std::vector<std::string> contact_r;
std::vector<std::string> contact_l;
contact_r.push_back("contactHeel_r");
contact_r.push_back("contactFront_r");
contact_l.push_back("contactHeel_l");
contact_l.push_back("contactFront_l");
model, full, contact_r, contact_l);
"gaitTracking_solutionGRF_fullcycle.sto");
return solution;
}
void gaitPrediction(
const MocoSolution& gaitTrackingSolution) {
using SimTK::Pi;
for (
const auto& coord : model.getComponentList<
Coordinate>()) {
symmetryGoal->addStatePair({coord.getStateVariableNames()[0],
std::regex_replace(coord.getStateVariableNames()[0],
std::regex("_r"), "_l")});
symmetryGoal->addStatePair({coord.getStateVariableNames()[1],
std::regex_replace(coord.getStateVariableNames()[1],
std::regex("_r"), "_l")});
}
symmetryGoal->addStatePair({coord.getStateVariableNames()[0],
std::regex_replace(coord.getStateVariableNames()[0],
std::regex("_l"), "_r")});
symmetryGoal->addStatePair({coord.getStateVariableNames()[1],
std::regex_replace(coord.getStateVariableNames()[1],
std::regex("_l"), "_r")});
}
symmetryGoal->addStatePair({coord.getStateVariableNames()[0],
coord.getStateVariableNames()[0]});
symmetryGoal->addStatePair({coord.getStateVariableNames()[1],
coord.getStateVariableNames()[1]});
}
}
symmetryGoal->addStatePair({"/jointset/groundPelvis/pelvis_tx/speed"});
symmetryGoal->addControlPair({"/lumbarAct"});
for (
const auto& muscle : model.getComponentList<
Muscle>()) {
symmetryGoal->addStatePair({muscle.getStateVariableNames()[0],
std::regex_replace(muscle.getStateVariableNames()[0],
std::regex("_r"), "_l")});
}
symmetryGoal->addStatePair({muscle.getStateVariableNames()[0],
std::regex_replace(muscle.getStateVariableNames()[0],
std::regex("_l"), "_r")});
}
}
effortGoal->setDivideByDisplacement(true);
problem.
setStateInfo(
"/jointset/groundPelvis/pelvis_tilt/value",
{-20 * Pi / 180, -10 * Pi / 180});
problem.
setStateInfo(
"/jointset/groundPelvis/pelvis_tx/value", {0, 1});
"/jointset/groundPelvis/pelvis_ty/value", {0.75, 1.25});
{-10 * Pi / 180, 60 * Pi / 180});
{-10 * Pi / 180, 60 * Pi / 180});
"/jointset/knee_l/knee_angle_l/value", {-50 * Pi / 180, 0});
"/jointset/knee_r/knee_angle_r/value", {-50 * Pi / 180, 0});
problem.
setStateInfo(
"/jointset/ankle_l/ankle_angle_l/value",
{-15 * Pi / 180, 25 * Pi / 180});
problem.
setStateInfo(
"/jointset/ankle_r/ankle_angle_r/value",
{-15 * Pi / 180, 25 * Pi / 180});
problem.
setStateInfo(
"/jointset/lumbar/lumbar/value", {0, 20 * Pi / 180});
solver.set_verbosity(2);
solver.set_optim_solver("ipopt");
solver.set_optim_convergence_tolerance(1e-4);
solver.set_optim_constraint_tolerance(1e-4);
solver.set_optim_max_iterations(1000);
solver.setGuess(gaitTrackingSolution);
full.write("gaitPrediction_solution_fullcycle.sto");
std::vector<std::string> contact_r;
std::vector<std::string> contact_l;
contact_r.push_back("contactHeel_r");
contact_r.push_back("contactFront_r");
contact_l.push_back("contactHeel_l");
contact_l.push_back("contactFront_l");
model, full, contact_r, contact_l);
"gaitPrediction_solutionGRF_fullcycle.sto");
}
int main() {
try {
gaitPrediction(gaitTrackingSolution);
} catch (const std::exception& e) { std::cout << e.what() << std::endl; }
return EXIT_SUCCESS;
}