rbdlsim/3rdparty/rbdl/addons/muscle/MuscleFunctionFactory.h

833 lines
30 KiB
C
Raw Permalink Normal View History

2020-10-03 22:55:14 +02:00
#ifndef MUSCLEFUNCTIONFACTORY_H_
#define MUSCLEFUNCTIONFACTORY_H_
/* -------------------------------------------------------------------------- *
* OpenSim: SmoothSegmentedFunctionFactory.h *
* -------------------------------------------------------------------------- *
* The OpenSim API is a toolkit for musculoskeletal modeling and simulation. *
* See http://opensim.stanford.edu and the NOTICE file for more information. *
* OpenSim is developed at Stanford University and supported by the US *
* National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA *
* through the Warrior Web program. *
* *
* Copyright (c) 2005-2012 Stanford University and the Authors *
* Author(s): Matthew Millard *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain a *
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* -------------------------------------------------------------------------- */
/*
Update:
This is a port of the original code so that it will work with
the multibody code RBDL written by Martin Felis.
Author:
Matthew Millard
Date:
Nov 2015
*/
#include "../geometry/SmoothSegmentedFunction.h"
#include "../geometry/SegmentedQuinticBezierToolkit.h"
#include <cstdio>
#include <iostream>
#include <fstream>
#include <cmath>
/**
This is a class that acts as a user friendly wrapper to QuinticBezerCurveSet
to build specific kinds of physiologically plausible muscle curves using C2
continuous sets of quintic Bezier curves. This class has been written there did
not exist a set of curves describing muscle characteristics that was:
1. Physiologically Accurate
2. Continuous to the second derivative
3. Parameterized in a physically meaningful manner
For example, the curves employed by Thelen (Thelen DG(2003). Adjustment of
Muscle Mechanics Model Parameters to Simulate Dynamic Contractions in Older
Adults. ASME Journal of Biomechanical Engineering (125).) are parameterized in a
physically meaningful manner, making them easy to use. However there are
many shortcomings of these curves:
1. The tendon and parallel element are not C2 continuous, making them slow to
simulate and likely not physiologically accurate.
2. The active force length curve approaches does not achieve its minimum value
at a normalized fiber length of 0.5, and 1.5.
3. The force velocity curve is not C2 continuous at the origin. As it is
written in the paper the curve is impossible to use with an equilibrium model
because it is not invertible. In addition the force-velocity curve actually
increases in stiffness as activation drops - a very undesirable property given
that many muscles are inactive at any one time.
The muscle curves used in the literature until 2012 have been hugely influenced
by Thelen's work, and thus similar comments can easily be applied to just about
every other musculoskeletal simulation.
Another example is from Miller (Miller,RH(2011).Optimal Control of
Human Running. PhD Thesis). On pg 149 a physiolgically plausible force velocity
curve is specified that gives the user the ability to change the concentric
curvature to be consistent with a slow or a fast twitch musle. This curve is
not C2 continuous at the origin, but even worse, it contains singularities in
its parameter space. Since these parameters do not have a physical
interpretation this model is difficult to use without accidentically creating a
curve with a singularity.
With this motivation I set out to develop a class that could generate muscle
characteristic curves with the following properties:
1. Physiologically Accurate
2. Continuous to the second derivative
3. Parameterized in a physically meaningful manner
4. Monotonicity for monotonic curves
5. Computationally efficient
These goals were surprisingly time consuming achieve, but these goals have been
achieved using sets of C2 continuous quintic Bezier curves. The resulting
muscle curve functions in this class take parameters that would be intuitive to
biomechanists who simulate human musculoskeletal systems, and returns a
SmoothSegmentedFunction which is capable of evaluating the value, and
derivatives of the desired function (or actually relation as
the case may be).
Each curve is made up of one or more C2 quintic Bezier curves x(u),
and y(u), with linearily extrapolated ends as shown in the figure below. These
quintic curves span 2 points, and achieve the desired derivative at its end
points. The degree of curviness can be varied from 0 to 1 (0, 0.75 and 1.0 are
shown in the figure in grey, blue and black respectively), and will make the
curve approximate a line when set to 0 (grey), and approximate a curve that
hugs the intersection of the lines that are defined by the end points locations
and the slopes at the end of each curve segment (red lines). Although you do
not need to set all of this information directly, for some of the curves it is
useful to know that both the slope and the curviness parameter may need to be
altered to achieve the desired shape.
\image html fig_GeometryAddon_quinticCornerSections.png
<B>Computational Cost Details</B>
All computational costs assume the following operation costs:
\verbatim
Operation Type : #flops
*,+,-,=,Boolean Op : 1
/ : 10
sqrt: 20
trig: 40
\endverbatim
These relative weightings will vary processor to processor, and so any of
the quoted computational costs are approximate.
<B> RBDL Port Notes </B>
The port of this code from OpenSim has been accompanied by a few changes:
1. The 'calcIntegral' method has been removed. Why? This function
relied on having access to a variable-step error controlled
integrator. There is no such integrator built into RBDL. Rather
than add a dependency (by using Boost perhaps) this functionality
has been removed.
2. The function name .printMuscleCurveToFile(...) has been changed
to .printCurveToFile().
@author Matt Millard
@version 0.0
*/
namespace RigidBodyDynamics {
namespace Addons {
namespace Muscle{
class MuscleFunctionFactory
{
public:
// friend class SmoothSegmentedFunction;
/**
This is a function that will produce a C2 (continuous to the second
derivative) active force length curve.
@param lce0 Normalized fiber length at the left-most shoulder of the
active force-length curve. The value of the active force
length curve for lce < lce0 will be equal to the value
set in shoulderVal. Normally lce0 is approximately 0.5
@param lce1 Normalized fiber length at the transition point between
the ascending limb and the plateau region of the active
force length curve.
@param lce2 Normalized fiber length at the maximum active force length
curve value of 1. Normally lce2 is by definition 1.
@param lce3 Normalized fiber length of the at the right most shoulder
of the active-force length curve. The value of the active
force length curve for lce > lce2 will be equal to the
value of shoulderVal. Normally lce3 is approximately 1.5
@param minActiveForceLengthValue
The minimum value of the active force length
curve. A physiological non-equibrium muscle model
would have this value set to 0. An equilibrium
muscle model would have a non-zero lower bound on
this value of 0.1 typically. shoulderVal must be
greater than, or equal to 0.
@param plateauSlope The slope of the plateau of the active force
length curve between lce1 and lce2. This parameter
can vary depending on the muscle model, but a
value of 0.8616 is a good place to start.
@param curviness The dimensionless 'curviness' parameter that
can vary between 0 (a line) to 1 (a smooth, but
sharply bent elbow). A value of 0 will yield an active
force length curve that is composed of slightly curved
line segments. A value of 1 will yield an active force
length curve that is smoothly rounded.
@param curveName The name of the muscle this curve applies to. This
curve name should have the name of the muscle and the
curve in it (e.g. "bicep_fiberActiveForceLengthCurve")
sothat if this curve ever causes an exception, a
userfriendly error message can be displayed to the
end user to help them debug their model.
@param smoothSegmentedFunctionToUpdate
A SmoothSegmentedFunction object that will be erased and filled with
the coefficients that are defined by this curve.
\b aborts \b
if these conditions aren't met
-0 < lce0 < lce1 < lce2 < lce3
-shoulderVal >= 0
-0 <= plateauSlope < (1/(lce3-lce2))
-0 <= curviness <= 1
\image html fig_MuscleAddon_MuscleFunctionFactory_falCurve.png
<B>Conditions:</B>
<B>Computational Costs</B>
\verbatim
~20,500 flops
\endverbatim
<B>Example:</B>
@code
double lce0 = 0.5;
double lce1 = 0.75;
double lce2 = 1;
double lce3 = 1.5;
double shoulderVal = 0.1;
double plateauSlope = 0.75;
double curviness = 0.9;
SmoothSegmentedFunction fiberfalCurve = SmoothSegmentedFunction();
MuscleFunctionFactory::
createFiberActiveForceLengthCurve(lce0, lce1, lce2, lce3,
shoulderVal, plateauSlope, curviness,"test", fiberfalCurve);
fiberfalCurve.printCurveToFile();
@endcode
*/
static void createFiberActiveForceLengthCurve(
double lce0,
double lce1,
double lce2,
double lce3,
double minActiveForceLengthValue,
double plateauSlope,
double curviness,
const std::string& curveName,
RigidBodyDynamics::Addons::Geometry
::SmoothSegmentedFunction&
smoothSegmentedFunctionToUpdate);
/**
This function will generate a C2 continous (continuous to the second
derivative) force velocity curve of a single muscle fiber. The main
function of this element is to model the amount the force enhancement or
attenuation that is associated with contracting at a particular velocity.
@param fmaxE The normalized maximum force the fiber can generate when
is being stretched. This value is reported to range
between 1.1 and 1.8 in the literature, though all values
are above 1.
@param dydxC The slope of the fv(dlce(t)/dt) curve at the maximum
normalized concentric contraction velocity. Although
physiologically the value of dydxC at the maximum
concentric contracton velocity is by definition 0, a value
of 0 is often used. If you are using an equilbrium type
model this term must be positive and greater than zero so
that the fv curve can be inverted.
<br /><br />
Minimum Value: 0
Maximum Value: dydxC < 1
<br /><br />
@param dydxNearC The slope of the force velocity curve as it approaches
the maximum concentric (shortening) contraction velocity.
<br /><br />
Minimum Value: > dydxC
Maximum Value: dydxNearC < 1
<br /><br />
@param dydxIso The slope of the fv curve when dlce(t)/dt = 0.
<br /><br />
Minimim Value: dydxIso > 1.0
Maximum Value: dydxIso < Inf
@param dydxE The analogous term of dydxC parameter but for the
eccentric portion of the force-velocity curve. As with
the dydxC term, the physiologically accurate value for
this parameter is 0, though a value of 0 is rarely used
in muscle models. If you are using an equilbrium type
model this term must be positive and greater than zero
so that the fv curve can be inverted.
<br /><br />
Minimum Value: 0
Maximum Value: dydxC < (fmaxE-1).
<br /><br />
As with the dydxC term,
the size of this term also affects the stiffness of the
integration problem for equilibrium-type muscle models:
the closer to zero this term is, the stiffer the model
will be (but only when (dlce(t)/dt)/vmax approaches 1.
@param dydxNearE The slope of the force velocity curve as it approaches
the maximum eccentric (lengthening) contraction velocity.
<br /><br />
Minimum Value: > dydxE
Maximum Value: dydxNearE < (fmaxE-1)
<br /><br />
@param concCurviness The dimensionless 'curviness' parameter that
can vary between 0 (a line) to 1 (a smooth, but
sharply bent elbow). This parameter affects only
the concentric side of the fv curve.
@param eccCurviness The dimensionless 'curviness' parameter that
can vary between 0 (a line) to 1 (a smooth, but
sharply bent elbow). This parameter affects only
the eccentric side of the fv curve.
@param curveName The name of the muscle this curve applies to. This
curve name should have the name of the muscle and the
curve in it (e.g. "bicep_fiberForceVelocityCurve")
sothat if this curve ever causes an exception, a
userfriendly error message can be displayed to the
end user to help them debug their model.
@param smoothSegmentedFunctionToUpdate
A SmoothSegmentedFunction object that will be erased and filled with
the coefficients that are defined by this curve.
\b aborts \b
unless these conditions are met
-0 <= dydxC < 1
-dydxC < dydxNearC < 1
-1 < dydxIso
-dydxE < (fmaxE-1)
-dydxE < dydxNearC < (fmaxE-1)
-0<= concCurviness <=0
-0 <= eccCurviness <= 0
\image html fig_MuscleAddon_MuscleFunctionFactory_fvCurve.png
<B>Computational Costs</B>
\verbatim
~8,200 flops
\endverbatim
<B>Example:</B>
@code
double fmaxE = 1.8;
double dydxC = 0.1;
double dydxNearC = 0.25;
double dydxE = 0.1;
double dydxNearE = 0.15;
double dydxIso= 5;
double concCurviness = 0.1;
double eccCurviness = 0.75;
SmoothSegmentedFunction fiberFVCurve = SmoothSegmentedFunction();
MuscleFunctionFactory::
createFiberForceVelocityCurve(fmaxE,
dydxC, dydxNearC, dydxIso, dydxE, dydxNearE,
concCurviness, eccCurviness,"test", fiberFVCurve);
fiberFVCurve.printCurveToFile();
@endcode
*/
static void createFiberForceVelocityCurve(
double fmaxE,
double dydxC,
double dydxNearC,
double dydxIso,
double dydxE,
double dydxNearE,
double concCurviness,
double eccCurviness,
const std::string& curveName,
RigidBodyDynamics::Addons::Geometry::
SmoothSegmentedFunction&
smoothSegmentedFunctionToUpdate);
/**
This function will generate a C2 continuous (continuous to the 2nd
derivative) inverse curve that the function
createFiberForceVelocityCurve generates. The inverse force velocity
curve is required by every equilibrium muscle model in order to compute
the derivative of fiber velocity. To generate the inverse force velocity
curve simply call this function with EXACTLY the same parameter values
that you used to generate the force velocity curve. See the parameter
descriptions for createFiberForceVelocityCurve, as the parameters for
the inverse function are identical. The curve name should be different,
however, because this is an inverse curve
(e.g. "bicep_fiberForceVelocityInverseCurve")
\image html fig_MuscleAddon_MuscleFunctionFactory_fvInvCurve.png
*/
static void createFiberForceVelocityInverseCurve(
double fmaxE,
double dydxC,
double dydxNearC,
double dydxIso,
double dydxE,
double dydxNearE,
double concCurviness,
double eccCurviness,
const std::string& muscleName,
RigidBodyDynamics::Addons::Geometry::
SmoothSegmentedFunction&
smoothSegmentedFunctionToUpdate);
/**
This element will generate a C2 continuous (continuous to the 2nd
derivative) compressive force profile curve as a function of pennation.
A muscle model with this element usually places this element parallel to
the fiber.The main function of this element is to prevent the fiber from
achieving a pennation angle of pi/2 radians. This type of element is
necessary for a parallelogram pennated equilibrium muscle models because
without it, the muscle model can deform to the point where a pennation
angle of pi/2 radians is reached, which causes a singularity in the
model.
@param phi0 The pennation angle at which the compressive force element
starts to engage . When the pennation angle is greater than
phi0, the compressive element is generating a force. When the
pennation angle is less than phi0, the compressive element
generates no force.
@param kiso This is the maximum stiffness of the compressive element,
which occurs when the fiber is pennated by 90 degrees
@param curviness The dimensionless 'curviness' parameter that
can vary between 0 (a line) to 1 (a smooth, but
sharply bent elbow)
@param curveName The name of the muscle this curve applies to. This
curve name should have the name of the muscle and the
curve in it
(e.g. "bicep_fiberCompressiveForcePennationCurve")
sothat if this curve ever causes an exception, a
userfriendly error message can be displayed to the
end user to help them debug their model.
@param smoothSegmentedFunctionToUpdate
A SmoothSegmentedFunction object that will be erased and filled with
the coefficients that are defined by this curve.
\b aborts \b
unless the following conditions are met
-0 < phi0 < SimTK::Pi/2
-kiso > 1/(SimTK::Pi/2-phi0)
-0 <= curviness <= 1
\image html fig_MuscleAddon_MuscleFunctionFactory_fcphiCurve.png
<B>Computational Costs</B>
\verbatim
~4,100 flops
\endverbatim
<B>Example:</B>
@code
double phi0 = (SimTK::Pi/2)*(8.0/9.0);
double kiso = 8.389863790885878;
double c = 0.0;
SmoothSegmentedFunction fiberCEPhiCurve = SmoothSegmentedFunction();
MuscleFunctionFactory::
createFiberCompressiveForcePennationCurve(phi0,kiso,c,"test",fiberCEPhiCurve);
fiberCEPhiCurve.printCurveToFile();
@endcode
*/
static void createFiberCompressiveForcePennationCurve(
double phi0,
double kiso,
double curviness,
const std::string& curveName,
RigidBodyDynamics::Addons::Geometry::
SmoothSegmentedFunction&
smoothSegmentedFunctionToUpdate);
/**
This element will generate a C2 continuous (continuous to the 2nd
derivative) compressive force profile curve as a function of
cos(pennation).
A muscle model with this element usually places this element in line
with the tendon. The main function of this element is to prevent the
fiber from achieving a pennation angle of pi/2 radians. This type of
element is necessary for a parallelogram pennated muscle models because
without it, the muscle model can deform to the point where a pennation
angle of pi/2 radians is reached, which causes a singularity in the
model.
@param cosPhi0 The cosine of the pennation angle at which the
compressive force element starts to engage. When the
cos of the pennation angle is greater than cosPhi0, the
compressive element generates no force. When cos of the
pennation angle is less than cosPhi0, the compressive
element generates a compressive force.
@param kiso This is the maximum stiffness of the compressive element,
which occurs when cosPhi is zero. This parameter must be
negative
cos
@param curviness The dimensionless 'curviness' parameter that
can vary between 0 (a line) to 1 (a smooth, but
sharply bent elbow)
@param curveName The name of the muscle this curve applies to. This
curve name should have the name of the muscle and the
curve in it
(e.g. "bicep_fiberCompressiveForceCosPennationCurve")
sothat if this curve ever causes an exception, a
userfriendly error message can be displayed to the
end user to help them debug their model.
@param smoothSegmentedFunctionToUpdate
A SmoothSegmentedFunction object that will be erased and filled with
the coefficients that are defined by this curve.
\b aborts \b
unless the following conditions are met:
-0 < cosPhi0
-kiso > 1/(cosPhi0)
-0 <= curviness <= 1
\image html fig_MuscleAddon_MuscleFunctionFactory_fcCosPhiCurve.png
<B>Computational Costs</B>
\verbatim
~4,100 flops
\endverbatim
<B>Example:</B>
@code
double cosPhi0 = cos( (80.0/90.0)*SimTK::Pi/2);
double kiso = -1.2/(cosPhi0);
double c = 0.5;
SmoothSegmentedFunction fiberCECosPhiCurve = MuscleFunctionFactory::
createFiberCompressiveForceCosPennationCurve(cosPhi0,kiso,c,"test");
fiberCEPhiCurve.printCurveToFile();
@endcode
*/
static void createFiberCompressiveForceCosPennationCurve(
double cosPhi0,
double kiso,
double curviness,
const std::string& curveName,
RigidBodyDynamics::Addons::Geometry::
SmoothSegmentedFunction&
smoothSegmentedFunctionToUpdate);
/**
This element will generate a C2 continous (continuous to the second
derivative) curve that models a compressive force profile that is a
function of fiber length. The main function of
this element is to prevent the fiber from achieving an unrealistically
short length. This type of element is necessary for equilibrium-type
muscle models because of the editing that is done to the active force
length curve that endows an equilibrium model fiber with the ability to
to generate force when a physiological fiber cannot.
@param l0 The normalized fiber length at which the compressive element
starts to engage. When the fiber is shorter than l0, the
compressive element is generating a force. When the fiber
length is longer than l0, the compressive element generates
no force.
@param kiso This is the maximum stiffness of the compressive element,
which occurs when the fiber has a length of 0, under a load
of 1 maximum isometric unit of force.
@param curviness The dimensionless 'curviness' parameter that
can vary between 0 (a line) to 1 (a smooth, but
sharply bent elbow)
@param curveName The name of the muscle this curve applies to. This
curve name should have the name of the muscle and the
curve in it
(e.g. "bicep_fiberCompressiveForceLengthCurve")
sothat if this curve ever causes an exception, a
userfriendly error message can be displayed to the
end user to help them debug their model.
@param smoothSegmentedFunctionToUpdate
A SmoothSegmentedFunction object that will be erased and filled with
the coefficients that are defined by this curve.
\b aborts \b
unless the following conditions are met
-e0 > 0
-kiso > 1/(e0)
-0 <= curviness <= 1
\image html fig_MuscleAddon_MuscleFunctionFactory_fpeCurve.png
<B>Computational Costs</B>
\verbatim
~4,100 flops
\endverbatim
<B>Example:</B>
@code
double lmax = 0.6;
double kiso = -8.389863790885878;
double c = 0.1;//0.0;
SmoothSegmentedFunction fiberCECurve = MuscleFunctionFactory::
createFiberCompressiveForceLengthCurve(lmax,kiso,c,"test");
fiberCECurve.printCurveToFile();
@endcode
*/
static void createFiberCompressiveForceLengthCurve(
double l0,
double kiso,
double curviness,
const std::string& curveName,
RigidBodyDynamics::Addons::Geometry::
SmoothSegmentedFunction&
smoothSegmentedFunctionToUpdate);
/**
This function will generate a C2 continuous curve that fits a fiber's
tensile force length curve.
@param eZero The fiber strain at which the fiber begins to develop force.
Thus an e0 of 0.0 means that the fiber will start to develop
passive force when it has a normalized length of 1.0. Note
that e0 can be postive or negative.
@param eIso The fiber strain at which the fiber develops 1 unit of
normalized force (1 maximum isometric force). Note that the
'1' is left off. Thus an e0 of 0.6 means that the fiber
will develop an 1 normalized force unit when it is strained
by 60% of its resting length, or to a normalized length of
1.6
@param kLow The normalized stiffness (or slope) of the fiber curve
close to the location where the force-length curve
approaches a normalized force of 0. This is usually
chosen to be a small, but non-zero fraction of kIso
(kLow = 0.025 kIso is typical).
@param kIso The normalized stiffness (or slope) of the fiber curve
when the fiber is strained by eIso (or has a length of
1+eIso) under a load of 1 maximum isometric unit of force.
@param curviness The dimensionless 'curviness' parameter that
can vary between 0 (a line) to 1 (a smooth, but
sharply bent elbow)
@param curveName The name of the muscle this curve applies to. This
curve name should have the name of the muscle and the
curve in it (e.g. "bicep_fiberForceLengthCurve")
sothat if this curve ever causes an exception, a
userfriendly error message can be displayed to the
end user to help them debug their model.
@param smoothSegmentedFunctionToUpdate
A SmoothSegmentedFunction object that will be erased and filled with
the coefficients that are defined by this curve.
\b aborts \b
unless the following conditions are met
-eIso > eZero
-kIso > 1/(eIso-eZero)
-0 < kLow < kIso
-0 <= curviness <= 1
\image html fig_MuscleAddon_MuscleFunctionFactory_fcLengthCurve.png
<B>Computational Costs</B>
\verbatim
~4,100 flops
\endverbatim
<B>Example:</B>
@code
double eIso = 0.6;
double eZero = 0.0;
double kIso = 4.0/(eIso-eZero);
double kNearZero = 0.025*kIso
double c = 0.5;
SmoothSegmentedFunction fiberFLCurve
= MuscleFunctionFactory::
createFiberForceLengthCurve(eZero, eIso,
kLow, kIso, c,"test");
fiberFLCurve.printCurveToFile();
@endcode
*/
static void createFiberForceLengthCurve(
double eZero,
double eIso,
double kLow,
double kIso,
double curviness,
const std::string& curveName,
RigidBodyDynamics::Addons::Geometry::
SmoothSegmentedFunction&
smoothSegmentedFunctionToUpdate);
/**
Will generate a C2 continous (continuous to the second derivative)
curve in a MuscleFunctionObject object that fits a tendon's tensile
force length curve.
@param eIso The tendon strain at which the tendon develops 1 unit
of normalized force (1 maximum isometric force). Note that
the'1' is left off. Thus an e0 of 0.04 means that the tendon
will develop an 1 normalized force unit when it is strained
by 4% of its resting length, at a normalized length of
1.04
@param kIso The normalized stiffness (or slope) of the tendon
curve when the tendon is strained by e0
(or has a length of 1+e0) under a load of 1 maximum
isometric unit of force.
@param fToe The normalized force at which the tendon smoothly
transitions from the curved low stiffness region to
the linear stiffness region.
@param curviness The dimensionless 'curviness' parameter that
can vary between 0 (a line) to 1 (a smooth, but
sharply bent elbow)
@param curveName The name of the muscle this curve applies to. This
curve name should have the name of the muscle and the
curve in it (e.g. "bicep_tendonForceLengthCurve")
sothat if this curve ever causes an exception, a
userfriendly error message can be displayed to the
end user to help them debug their model.
@param smoothSegmentedFunctionToUpdate
A SmoothSegmentedFunction object that will be erased and filled with
the coefficients that are defined by this curve.
\b aborts \b
unless the following conditions are met:
-0 < fToe < 1
-e0 > 0
-kiso > 1/e0
-0 <= curviness <= 1
\image html fig_MuscleAddon_MuscleFunctionFactory_fseCurve.png
<B>Computational Costs</B>
\verbatim
~4,100 flops
\endverbatim
<B>Example:</B>
@code
double e0 = 0.04;
double kiso = 42.79679348815859;
double fToe = 1.0/3.0
double c = 0.75;
SmoothSegmentedFunction* tendonCurve = MuscleFunctionFactory::
createTendonForceLengthCurve(
e0,kiso,fToe,c,"test");
tendonCurve.printCurveToFile();
@endcode
*/
static void createTendonForceLengthCurve(double eIso,
double kIso,
double fToe,
double curviness,
const std::string& curveName,
RigidBodyDynamics::Addons::Geometry::
SmoothSegmentedFunction&
smoothSegmentedFunctionToUpdate);
};
}
}
}
#endif //MUSCLEFUNCTIONFACTORY_H_