OpenSim Moco
0.1.0-preprint
Solve optimal control problems with OpenSim models
|
This muscle model was published in De Groote et al.
2016. The parameters of the active force-length and force-velocity curves have been slightly modified from what was published to ensure the curves go through key points:
The fiber damping helps with numerically solving for fiber velocity at low activations or with low force-length multipliers, and is likely to be more useful with explicit fiber dynamics than implicit fiber dynamics (when support for fiber dynamics is added).
This class supports tendon compliance dynamics in both explicit and implicit form. Both forms of the dynamics use normalized tendon force as the state variable (rather than the typical fiber length state). The explicit form is handled through the usual Component dynamics interface. The implicit form introduces an additional discrete and cache SimTK::State variable for the derivative of normalized tendon force and muscle-tendon equilibrium residual respectively. The implicit form is only for use with solvers that support implicit dynamics (i.e. Moco) and cannot be used to perform a time-stepping forward simulation with Manager; use explicit mode for time-stepping.
The documentation for Muscle::MuscleLengthInfo states that the optimalFiberLength of a muscle is also its resting length, but this is not true for this muscle: there is a non-zero passive fiber force at the optimal fiber length.
In the Muscle class, setIgnoreTendonCompliance() and setIngoreActivationDynamics() control modeling options, meaning these settings could theoretically be changed. However, for this class, the modeling option is ignored and the values of the ignore_tendon_compliance and ignore_activation_dynamics properties are used directly.
De Groote, F., Kinney, A. L., Rao, A. V., & Fregly, B. J. (2016). Evaluation of Direct Collocation Optimal Control Problem Formulations for Solving the Muscle Redundancy Problem. Annals of Biomedical Engineering, 44(10), 1–15. http://doi.org/10.1007/s10439-016-1591-9
#include <Moco/Moco/Components/DeGrooteFregly2016Muscle.h>
Public Member Functions | |
OpenSim_DECLARE_PROPERTY (activation_time_constant, double, "Smaller value means activation can change more rapidly (units: " "seconds).") | |
OpenSim_DECLARE_PROPERTY (deactivation_time_constant, double, "Smaller value means activation can decrease more rapidly " "(units: seconds).") | |
OpenSim_DECLARE_PROPERTY (default_activation, double, "Value of activation in the default state returned by " "initSystem().") | |
OpenSim_DECLARE_PROPERTY (default_normalized_tendon_force, double, "Value of normalized tendon force in the default state returned by " "initSystem().") | |
OpenSim_DECLARE_PROPERTY (active_force_width_scale, double, "Scale factor for the width of the active force-length curve. " "Larger values make the curve wider. " "(default: 1.0).") | |
OpenSim_DECLARE_PROPERTY (fiber_damping, double, "The linear damping of the fiber (default: 0.01).") | |
OpenSim_DECLARE_PROPERTY (tendon_strain_at_one_norm_force, double, "Tendon strain at a tension of 1 normalized force.") | |
OpenSim_DECLARE_PROPERTY (ignore_passive_fiber_force, bool, "Make the passive fiber force 0 (default: false).") | |
OpenSim_DECLARE_PROPERTY (tendon_compliance_dynamics_mode, std::string, "The dynamics method used to enforce tendon compliance dynamics. " "Options: 'explicit' or 'implicit'. Default: 'explicit'. ") | |
OpenSim_DECLARE_OUTPUT (implicitresidual_normalized_tendon_force, double, getImplicitResidualNormalizedTendonForce, SimTK::Stage::Dynamics) | |
OpenSim_DECLARE_OUTPUT (implicitenabled_normalized_tendon_force, bool, getImplicitEnabledNormalizedTendonForce, SimTK::Stage::Model) | |
OpenSim_DECLARE_OUTPUT (statebounds_normalized_tendon_force, SimTK::Vec2, getBoundsNormalizedTendonForce, SimTK::Stage::Model) | |
Set methods. | |
If ignore_tendon_compliance is true, this sets nothing. | |
void | setNormalizedTendonForce (SimTK::State &s, double normTendonForce) const |
Muscle interface | |
double | getActivation (const SimTK::State &s) const override |
If ignore_activation_dynamics is true, this gets excitation instead. | |
void | setActivation (SimTK::State &s, double activation) const override |
If ignore_activation_dynamics is true, this sets excitation instead. | |
void | computeInitialFiberEquilibrium (SimTK::State &s) const override |
Fiber velocity is assumed to be 0. | |
double | calcInextensibleTendonActiveFiberForce (SimTK::State &, double) const override |
void | calcMuscleLengthInfo (const SimTK::State &s, MuscleLengthInfo &mli) const override |
void | calcFiberVelocityInfo (const SimTK::State &s, FiberVelocityInfo &fvi) const override |
void | calcMuscleDynamicsInfo (const SimTK::State &s, MuscleDynamicsInfo &mdi) const override |
void | calcMusclePotentialEnergyInfo (const SimTK::State &s, MusclePotentialEnergyInfo &mpei) const override |
Get methods. | |
bool | getImplicitEnabledNormalizedTendonForce (const SimTK::State &) const |
We don't need the state, but the state parameter is a requirement of Output functions. | |
double | getImplicitResidualNormalizedTendonForce (const SimTK::State &s) const |
Compute the muscle-tendon force equilibrium residual value when using implicit contraction dynamics with normalized tendon force as the state. | |
double | getNormalizedTendonForce (const SimTK::State &s) const |
If ignore_tendon_compliance is true, this gets normalized fiber force along the tendon instead. | |
double | getNormalizedTendonForceDerivative (const SimTK::State &s) const |
If integration_mode is 'implicit', this gets the discrete variable tendon force derivative value. More... | |
double | getEquilibriumResidual (const SimTK::State &s) const |
The residual (i.e. More... | |
double | getLinearizedEquilibriumResidualDerivative (const SimTK::State &s) const |
The residual (i.e. More... | |
SimTK::Vec2 | getBoundsNormalizedTendonForce (const SimTK::State &) const |
The first element of the Vec2 is the lower bound, and the second is the upper bound. More... | |
static std::string | getActivationStateName () |
static std::string | getNormalizedTendonForceStateName () |
static std::string | getImplicitDynamicsDerivativeName () |
static std::string | getImplicitDynamicsResidualName () |
static double | getMinNormalizedTendonForce () |
static double | getMaxNormalizedTendonForce () |
Calculation methods. | |
These functions compute the values of normalized/dimensionless curves, their derivatives and integrals, and other quantities of the muscle. These do not depend on a SimTK::State. | |
SimTK::Real | calcActiveForceLengthMultiplier (const SimTK::Real &normFiberLength) const |
The active force-length curve is the sum of 3 Gaussian-like curves. More... | |
SimTK::Real | calcActiveForceLengthMultiplierDerivative (const SimTK::Real &normFiberLength) const |
The derivative of the active force-length curve with respect to normalized fiber length. More... | |
SimTK::Real | calcPassiveForceMultiplier (const SimTK::Real &normFiberLength) const |
This is the passive force-length curve. More... | |
SimTK::Real | calcPassiveForceMultiplierDerivative (const SimTK::Real &normFiberLength) const |
This is the derivative of the passive force-length curve with respect to the normalized fiber length. | |
SimTK::Real | calcPassiveForceMultiplierIntegral (const SimTK::Real &normFiberLength) const |
This is the integral of the passive force-length curve with respect to the normalized fiber length. | |
SimTK::Real | calcTendonForceMultiplier (const SimTK::Real &normTendonLength) const |
The normalized tendon force as a function of normalized tendon length. More... | |
SimTK::Real | calcTendonForceMultiplierDerivative (const SimTK::Real &normTendonLength) const |
This is the derivative of the tendon-force length curve with respect to normalized tendon length. | |
SimTK::Real | calcTendonForceMultiplierIntegral (const SimTK::Real &normTendonLength) const |
This is the integral of the tendon-force length curve with respect to normalized tendon length. | |
SimTK::Real | calcTendonForceLengthInverseCurve (const SimTK::Real &normTendonForce) const |
This is the inverse of the tendon force-length curve, and returns the normalized tendon length as a function of the normalized tendon force. | |
SimTK::Real | calcTendonForceLengthInverseCurveDerivative (const SimTK::Real &derivNormTendonForce, const SimTK::Real &normTendonLength) const |
This is the derivative of the inverse tendon-force length. More... | |
void | calcFiberForce (const SimTK::Real &activation, const SimTK::Real &activeForceLengthMultiplier, const SimTK::Real &forceVelocityMultiplier, const SimTK::Real &normPassiveFiberForce, const SimTK::Real &normFiberVelocity, SimTK::Real &activeFiberForce, SimTK::Real &conPassiveFiberForce, SimTK::Real &nonConPassiveFiberForce, SimTK::Real &totalFiberForce) const |
This computes both the total fiber force and the individual components of fiber force (active, conservative passive, and non-conservative passive). More... | |
SimTK::Real | calcFiberStiffness (const SimTK::Real &activation, const SimTK::Real &normFiberLength, const SimTK::Real &fiberVelocityMultiplier) const |
The stiffness of the fiber in the direction of the fiber. More... | |
SimTK::Real | calcTendonStiffness (const SimTK::Real &normTendonLength) const |
The stiffness of the tendon in the direction of the tendon. More... | |
SimTK::Real | calcMuscleStiffness (const SimTK::Real &tendonStiffness, const SimTK::Real &fiberStiffnessAlongTendon) const |
The stiffness of the whole musculotendon unit in the direction of the tendon. More... | |
SimTK::Real | calcPartialPennationAnglePartialFiberLength (const SimTK::Real &fiberLength) const |
The derivative of pennation angle with respect to fiber length. More... | |
SimTK::Real | calcPartialFiberForceAlongTendonPartialFiberLength (const SimTK::Real &fiberForce, const SimTK::Real &fiberStiffness, const SimTK::Real &sinPennationAngle, const SimTK::Real &cosPennationAngle, const SimTK::Real &partialPennationAnglePartialFiberLength) const |
The derivative of the fiber force along the tendon with respect to fiber length. More... | |
SimTK::Real | calcFiberStiffnessAlongTendon (const SimTK::Real &fiberLength, const SimTK::Real &partialFiberForceAlongTendonPartialFiberLength, const SimTK::Real &sinPennationAngle, const SimTK::Real &cosPennationAngle, const SimTK::Real &partialPennationAnglePartialFiberLength) const |
The derivative of the fiber force along the tendon with respect to the fiber length along the tendon. More... | |
SimTK::Real | calcPartialTendonLengthPartialFiberLength (const SimTK::Real &fiberLength, const SimTK::Real &sinPennationAngle, const SimTK::Real &cosPennationAngle, const SimTK::Real &partialPennationAnglePartialFiberLength) const |
SimTK::Real | calcPartialTendonForcePartialFiberLength (const SimTK::Real &tendonStiffness, const SimTK::Real &fiberLength, const SimTK::Real &sinPennationAngle, const SimTK::Real &cosPennationAngle) const |
SimTK::Real | calcEquilibriumResidual (const SimTK::Real &tendonForce, const SimTK::Real &fiberForceAlongTendon) const |
The residual (i.e. More... | |
SimTK::Real | calcLinearizedEquilibriumResidualDerivative (const SimTK::Real muscleTendonVelocity, const SimTK::Real &fiberVelocityAlongTendon, const SimTK::Real &tendonStiffness, const SimTK::Real &fiberStiffnessAlongTendon) const |
The residual (i.e. More... | |
static SimTK::Real | calcForceVelocityMultiplier (const SimTK::Real &normFiberVelocity) |
The parameters of this curve are not modifiable, so this function is static. More... | |
static SimTK::Real | calcForceVelocityInverseCurve (const SimTK::Real &forceVelocityMult) |
This is the inverse of the force-velocity multiplier function, and returns the normalized fiber velocity (in [-1, 1]) as a function of the force-velocity multiplier. | |
Utilities | |
Given a residual lambda function and domain initial guess to the left and right of a root, use bisection to find a root value. | |
SimTK::Real | solveBisection (std::function< SimTK::Real(const SimTK::Real &)> calcResidual, SimTK::Real left, SimTK::Real right, const SimTK::Real &xTolerance=1e-6, const SimTK::Real &yTolerance=1e-6, int maxIterations=1000) const |
DataTable | exportFiberLengthCurvesToTable (const SimTK::Vector &normFiberLengths=SimTK::Vector()) const |
Export the active force-length multiplier and passive force multiplier curves to a DataTable. More... | |
DataTable | exportFiberVelocityMultiplierToTable (const SimTK::Vector &normFiberVelocities=SimTK::Vector()) const |
Export the fiber force-velocity multiplier curve to a DataTable. More... | |
DataTable | exportTendonForceMultiplierToTable (const SimTK::Vector &normTendonLengths=SimTK::Vector()) const |
Export the fiber tendon force multiplier curve to a DataTable. More... | |
void | printCurvesToSTOFiles (const std::string &directory=".") const |
Print the muscle curves to STO files. More... | |
static void | replaceMuscles (Model &model, bool allowUnsupportedMuscles=false) |
Replace muscles of other types in the model with muscles of this type. More... | |
|
inline |
The active force-length curve is the sum of 3 Gaussian-like curves.
The width of the curve can be adjusted via the active_force_width_scale property.
|
inline |
The derivative of the active force-length curve with respect to normalized fiber length.
This curve is based on the derivative of the Gaussian-like curve used in calcActiveForceLengthMultiplier(). The active_force_width_scale property also affects the value of the derivative curve.
|
inline |
The residual (i.e.
error) in the muscle-tendon equilibrium equation: residual = tendonForce - fiberForce * cosPennationAngle
|
inline |
This computes both the total fiber force and the individual components of fiber force (active, conservative passive, and non-conservative passive).
|
inline |
The stiffness of the fiber in the direction of the fiber.
This includes both active and passive force contributions to stiffness from the muscle fiber.
|
inline |
The derivative of the fiber force along the tendon with respect to the fiber length along the tendon.
|
inlinestatic |
The parameters of this curve are not modifiable, so this function is static.
Domain: [-1, 1] Range: [0, 1.794]
|
inline |
The residual (i.e.
error) in the time derivative of the linearized muscle-tendon equilibrium equation (Millard et al. 2013, equation A6): residual = fiberStiffnessAlongTendon * fiberVelocityAlongTendon - tendonStiffness * (muscleTendonVelocity - fiberVelocityAlongTendon)
|
inline |
The stiffness of the whole musculotendon unit in the direction of the tendon.
|
inline |
The derivative of the fiber force along the tendon with respect to fiber length.
|
inline |
The derivative of pennation angle with respect to fiber length.
|
inline |
This is the passive force-length curve.
The curve becomes negative below the minNormFiberLength.
|
inline |
This is the derivative of the inverse tendon-force length.
Given the derivative of normalized tendon force and normalized tendon length, this returns normalized tendon velocity.
|
inline |
The normalized tendon force as a function of normalized tendon length.
Note that this curve does not go through (1, 0); when normTendonLength=1, this function returns a slightly negative number.
|
inline |
The stiffness of the tendon in the direction of the tendon.
DataTable OpenSim::DeGrooteFregly2016Muscle::exportFiberLengthCurvesToTable | ( | const SimTK::Vector & | normFiberLengths = SimTK::Vector() | ) | const |
Export the active force-length multiplier and passive force multiplier curves to a DataTable.
If the normFiberLengths argument is omitted, we use createVectorLinspace(200, minNormFiberLength, maxNormFiberLength).
DataTable OpenSim::DeGrooteFregly2016Muscle::exportFiberVelocityMultiplierToTable | ( | const SimTK::Vector & | normFiberVelocities = SimTK::Vector() | ) | const |
Export the fiber force-velocity multiplier curve to a DataTable.
If the normFiberVelocities argument is omitted, we use createVectorLinspace(200, -1.1, 1.1).
DataTable OpenSim::DeGrooteFregly2016Muscle::exportTendonForceMultiplierToTable | ( | const SimTK::Vector & | normTendonLengths = SimTK::Vector() | ) | const |
Export the fiber tendon force multiplier curve to a DataTable.
If the normFiberVelocities argument is omitted, we use createVectorLinspace(200, 0.95, 1 + <strain at 1 norm force>)
|
inline |
The first element of the Vec2 is the lower bound, and the second is the upper bound.
We don't need the state, but the state parameter is a requirement of Output functions.
|
inline |
The residual (i.e.
error) in the muscle-tendon equilibrium equation: residual = tendonForce - fiberForce * cosPennationAngle
|
inline |
The residual (i.e.
error) in the time derivative of the linearized muscle-tendon equilibrium equation (Millard et al. 2013, equation A6): residual = fiberStiffnessAlongTendon * fiberVelocityAlongTendon - tendonStiffness * (muscleTendonVelocity - fiberVelocityAlongTendon)
|
inline |
If integration_mode is 'implicit', this gets the discrete variable tendon force derivative value.
If integration_mode is 'explicit', this gets the value returned by getStateVariableDerivativeValue() for the 'normalized_tendon_force' state. If ignore_tendon_compliance is false, this returns zero.
void OpenSim::DeGrooteFregly2016Muscle::printCurvesToSTOFiles | ( | const std::string & | directory = "." | ) | const |
Print the muscle curves to STO files.
The files will be named as <muscle-name>_<curve_type>.sto
.
directory | The directory to which the data files should be written. Do NOT include the filename. By default, the files are printed to the current working directory. |
|
static |
Replace muscles of other types in the model with muscles of this type.
Currently, only Millard2012EquilibriumMuscles and Thelen2003Muscles are replaced. If the model has muscles of other types, an exception is thrown unless allowUnsupportedMuscles is true. Since the DeGrooteFregly2016Muscle implements tendon compliance dynamics with normalized tendon force as the state variable, this function ignores the 'default_fiber_length' property in replaced muscles.