1 #ifndef OPENSIM_FIRST_ORDER_MUSCLE_ACTIVATION_DYNAMICS_H_
2 #define OPENSIM_FIRST_ORDER_MUSCLE_ACTIVATION_DYNAMICS_H_
3 /* -------------------------------------------------------------------------- *
4  *               OpenSim:  FirstOrderMuscleActivationDynamics.h               *
5  * -------------------------------------------------------------------------- *
6  * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
7  * See http://opensim.stanford.edu and the NOTICE file for more information.  *
8  * OpenSim is developed at Stanford University and supported by the US        *
9  * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
10  * through the Warrior Web program.                                           *
11  *                                                                            *
12  * Copyright (c) 2005-2017 Stanford University and the Authors                *
13  * Author(s): Thomas Uchida, Matthew Millard, Ajay Seth                       *
14  *                                                                            *
15  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
16  * not use this file except in compliance with the License. You may obtain a  *
17  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
18  *                                                                            *
19  * Unless required by applicable law or agreed to in writing, software        *
20  * distributed under the License is distributed on an "AS IS" BASIS,          *
21  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
22  * See the License for the specific language governing permissions and        *
23  * limitations under the License.                                             *
24  * -------------------------------------------------------------------------- */
25 
26 #include <OpenSim/Actuators/osimActuatorsDLL.h>
27 #include <OpenSim/Actuators/MuscleActivationDynamics.h>
28 
29 namespace OpenSim {
30 /** Computes muscle activation using a modified version of the first-order
31     dynamic models used by Thelen (2003) and Winters (1995). The time derivative
32     of activation (\f$da/dt\f$) is calculated as follows:
33     \f[ \frac{da}{dt} = \frac{u-a}{\tau(u,a)} \f]
34     where \f$u\f$ is excitation, \f$a\f$ is activation, and \f$\tau(u,a)\f$ is
35     an excitation- and activation-dependent time constant:
36     \f[ \tau(u,a) = \tau_{\rm{act}} (0.5 + 1.5a) \quad {\rm{if}}\ u > a \f]
37     \f[ \tau(u,a) = \tau_{\rm{deact}} / (0.5 + 1.5a) \quad {\rm{otherwise}} \f]
38     Typical values for activation (\f$\tau_{\rm{act}}\f$) and deactivation
39     (\f$\tau_{\rm{deact}}\f$) time constants are 10 ms and 40 ms, respectively.
40 
41     Three properties are inherited from the base MuscleActivationDynamics class:
42     \c minimum_activation, \c maximum_activation, and \c default_activation.
43     Note that equilibrium muscle models typically have a numerical singularity
44     in their state equations when activation is zero, so care should be taken
45     when setting \c minimum_activation to zero. Minimum activation values
46     between 0.01 and 0.1 are typically used with equilibrium muscle models.
47 
48     <b>Properties</b>
49     \li \c activation_time_constant: Activation time constant (in seconds).
50     \li \c deactivation_time_constant: Deactivation time constant (in seconds).
51 
52     <b>Conditions</b>
53     \verbatim
54     activation_time_constant > 0
55     deactivation_time_constant > 0
56     \endverbatim
57 
58     <b>Default %Property Values</b>
59     \verbatim
60     activation_time_constant ...... 0.010
61     deactivation_time_constant .... 0.040
62     minimum_activation ............ 0.01
63     maximum_activation ............ 1
64     default_activation ............ 0.5
65     \endverbatim
66 
67     <b>References</b>
68     \li Thelen, D.G. (2003) Adjustment of muscle mechanics model parameters to
69         simulate dynamic contractions in older adults. ASME Journal of
70         Biomechanical Engineering 125(1):70--77.
71     \li Winters, J.M. (1995) An improved muscle-reflex actuator for use in
72         large-scale neuromusculoskeletal models. Annals of Biomedical
73         Engineering 23(4):359--374.
74 
75     @author Thomas Uchida, Matthew Millard, Ajay Seth
76 **/
77 
78 class OSIMACTUATORS_API FirstOrderMuscleActivationDynamics :
79     public MuscleActivationDynamics {
80     OpenSim_DECLARE_CONCRETE_OBJECT(FirstOrderMuscleActivationDynamics,
81                                     MuscleActivationDynamics);
82 public:
83 
84 //==============================================================================
85 // PROPERTIES
86 //==============================================================================
87     OpenSim_DECLARE_PROPERTY(activation_time_constant, double,
88         "Activation time constant (in seconds)");
89     OpenSim_DECLARE_PROPERTY(deactivation_time_constant, double,
90         "Deactivation time constant (in seconds)");
91 
92 //==============================================================================
93 // PUBLIC METHODS
94 //==============================================================================
95     /** @name Constructors **/
96     //@{
97 
98     /** Creates a first-order activation dynamic model with the default property
99         values and assigns it a default name. An %ExcitationGetter must be
100         created for obtaining muscle excitation. **/
101     FirstOrderMuscleActivationDynamics();
102 
103     /** Creates a first-order activation dynamic model with the default property
104         values, the specified name, and the specified %ExcitationGetter. Takes
105         ownership of the %ExcitationGetter object. **/
106     FirstOrderMuscleActivationDynamics(const std::string& name,
107                                        ExcitationGetter* getter);
108     //@}
109 
110     //--------------------------------------------------------------------------
111     // ACCESSORS AND MUTATORS
112     //--------------------------------------------------------------------------
113     /** @name Accessors and Mutators **/
114     //@{
115 
116     /** Get the activation time constant. **/
117     double getActivationTimeConstant() const;
118     /** %Set the activation time constant to a value greater than zero. **/
119     void setActivationTimeConstant(double activationTimeConstant);
120 
121     /** Get the deactivation time constant. **/
122     double getDeactivationTimeConstant() const;
123     /** %Set the deactivation time constant to a value greater than zero. **/
124     void setDeactivationTimeConstant(double deactivationTimeConstant);
125 
126     //@}
127 
128     //--------------------------------------------------------------------------
129     // MODELCOMPONENT INTERFACE REQUIREMENTS
130     //--------------------------------------------------------------------------
131     /** @name ModelComponent Interface Requirements **/
132     //@{
133 
134     /** Adds activation to the state. **/
135     void extendAddToSystem(SimTK::MultibodySystem& system) const override;
136 
137     /** Initializes the activation state variable to \c default_activation. **/
138     void extendInitStateFromProperties(SimTK::State& s) const override;
139 
140     /** Sets \c default_activation to the current value of the activation state
141         variable. **/
142     void extendSetPropertiesFromState(const SimTK::State& s) override;
143 
144     /** Calculates the time derivative of activation using a first-order dynamic
145         model. Respects the lower bound on activation while preserving the
146         expected steady-state value. **/
147     void computeStateVariableDerivatives(const SimTK::State& s) const override;
148 
149     //@}
150 
151     //--------------------------------------------------------------------------
152     // STATE-DEPENDENT METHODS
153     //--------------------------------------------------------------------------
154     /** Get the current activation from the state. **/
155     double getActivation(const SimTK::State& s) const override;
156 
157     /** %Set activation state variable to the value provided. **/
158     void setActivation(SimTK::State& s, double activation) const override;
159 
160 //==============================================================================
161 // PRIVATE METHODS
162 //==============================================================================
163 private:
164     void setNull();
165     void constructProperties();
166 
167     /** Implementation of a first-order activation dynamic model that respects
168         the lower bound on activation while preserving the expected steady-state
169         value. **/
170     double calcActivationDerivative(double excitation, double activation) const;
171 
172     static const std::string STATE_NAME_ACTIVATION;
173 
174 }; // end of class FirstOrderMuscleActivationDynamics
175 }  // end of namespace OpenSim
176 
177 #endif //OPENSIM_FIRST_ORDER_MUSCLE_ACTIVATION_DYNAMICS_H_
178