This example optimizes the motion of a point mass actuated by a single muscle and shows you how to use the AnalyzeTool and a metabolic probe with a MocoSolution.
#include <OpenSim/Analyses/MuscleAnalysis.h>
#include <OpenSim/Analyses/ProbeReporter.h>
#include <OpenSim/Common/STOFileAdapter.h>
#include <OpenSim/Moco/osimMoco.h>
#include <OpenSim/Simulation/SimbodyEngine/PinJoint.h>
#include <OpenSim/Tools/AnalyzeTool.h>
Model createHangingMuscleModel(
bool ignoreActivationDynamics,
bool ignoreTendonCompliance) {
auto* body =
new Body(
"body", 0.5, SimTK::Vec3(0), SimTK::Inertia(0));
actu->setName("muscle");
actu->set_max_isometric_force(30.0);
actu->set_optimal_fiber_length(0.10);
actu->set_tendon_slack_length(0.05);
actu->set_tendon_strain_at_one_norm_force(0.10);
actu->set_ignore_activation_dynamics(ignoreActivationDynamics);
actu->set_ignore_tendon_compliance(ignoreTendonCompliance);
actu->set_fiber_damping(0.01);
actu->set_tendon_compliance_dynamics_mode("implicit");
actu->set_max_contraction_velocity(10);
actu->set_pennation_angle_at_optimal(0.10);
actu->addNewPathPoint(
"origin", model.
updGround(), SimTK::Vec3(0));
actu->addNewPathPoint("insertion", *body, SimTK::Vec3(0));
{
probe->setName("metabolics");
probe->addMuscle("muscle", 0.5);
}
{
probe->setName("activation_maintenance_rate");
probe->set_activation_maintenance_rate_on(true);
probe->set_shortening_rate_on(false);
probe->set_basal_rate_on(false);
probe->set_mechanical_work_rate_on(false);
probe->addMuscle("muscle", 0.5);
}
{
probe->setName("shortening_rate");
probe->set_activation_maintenance_rate_on(false);
probe->set_shortening_rate_on(true);
probe->set_basal_rate_on(false);
probe->set_mechanical_work_rate_on(false);
probe->addMuscle("muscle", 0.5);
}
{
probe->setName("basal_rate");
probe->set_activation_maintenance_rate_on(false);
probe->set_shortening_rate_on(false);
probe->set_basal_rate_on(true);
probe->set_mechanical_work_rate_on(false);
probe->addMuscle("muscle", 0.5);
}
{
probe->setName("mechanical_work_rate");
probe->set_activation_maintenance_rate_on(false);
probe->set_shortening_rate_on(false);
probe->set_basal_rate_on(false);
probe->set_mechanical_work_rate_on(true);
probe->addMuscle("muscle", 0.5);
}
body->attachGeometry(
new Sphere(0.05));
return model;
}
int main() {
const bool ignoreActivationDynamics = false;
const bool ignoreTendonCompliance = false;
Model model = createHangingMuscleModel(ignoreActivationDynamics,
ignoreTendonCompliance);
model.
print(
"hanging_muscle.osim");
problem.
setStateInfo(
"/joint/height/value", {0.14, 0.16}, 0.15, 0.14);
if (!ignoreActivationDynamics) {
initial_activation->
setName(
"initial_activation");
}
if (!ignoreTendonCompliance) {
auto* initial_equilibrium =
initial_equilibrium->
setName(
"initial_velocity_equilibrium");
initial_equilibrium->setMode("cost");
initial_equilibrium->setWeight(0.001);
}
solver.set_num_mesh_intervals(50);
solver.set_multibody_dynamics_mode("implicit");
solver.set_optim_convergence_tolerance(1e-4);
solver.set_optim_constraint_tolerance(1e-4);
"exampleHangingMuscle_states.sto");
"exampleHangingMuscle_controls.sto");
{
analyze.setModelFilename(
"hanging_muscle.osim");
analyze.setStatesFileName(
"exampleHangingMuscle_states.sto");
analyze.updControllerSet().adoptAndAppend(
analyze.print(
"exampleHangingMuscle_AnalyzeTool_setup.xml");
}
return EXIT_SUCCESS;
}