1 /* -------------------------------------------------------------------------- *
2 * OpenSim: FirstOrderMuscleActivationDynamics.cpp *
3 * -------------------------------------------------------------------------- *
4 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. *
5 * See http://opensim.stanford.edu and the NOTICE file for more information. *
6 * OpenSim is developed at Stanford University and supported by the US *
7 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA *
8 * through the Warrior Web program. *
9 * *
10 * Copyright (c) 2005-2017 Stanford University and the Authors *
11 * Author(s): Thomas Uchida, Matthew Millard, Ajay Seth *
12 * *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may *
14 * not use this file except in compliance with the License. You may obtain a *
15 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
16 * *
17 * Unless required by applicable law or agreed to in writing, software *
18 * distributed under the License is distributed on an "AS IS" BASIS, *
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
20 * See the License for the specific language governing permissions and *
21 * limitations under the License. *
22 * -------------------------------------------------------------------------- */
23
24 #include "FirstOrderMuscleActivationDynamics.h"
25
26 using namespace std;
27 using namespace OpenSim;
28 using namespace SimTK;
29
30 const std::string FirstOrderMuscleActivationDynamics::
31 STATE_NAME_ACTIVATION = "activation";
32
33 //==============================================================================
34 // CONSTRUCTORS
35 //==============================================================================
FirstOrderMuscleActivationDynamics()36 FirstOrderMuscleActivationDynamics::FirstOrderMuscleActivationDynamics() :
37 MuscleActivationDynamics()
38 {
39 setNull();
40 constructProperties();
41 setName("default_FirstOrderMuscleActivationDynamics");
42 }
43
44 FirstOrderMuscleActivationDynamics::
FirstOrderMuscleActivationDynamics(const std::string & name,ExcitationGetter * getter)45 FirstOrderMuscleActivationDynamics(const std::string& name,
46 ExcitationGetter* getter) :
47 MuscleActivationDynamics(name, getter)
48 {
49 setNull();
50 constructProperties();
51 }
52
53 //==============================================================================
54 // ACCESSORS AND MUTATORS
55 //==============================================================================
getActivationTimeConstant() const56 double FirstOrderMuscleActivationDynamics::getActivationTimeConstant() const
57 { return get_activation_time_constant(); }
getDeactivationTimeConstant() const58 double FirstOrderMuscleActivationDynamics::getDeactivationTimeConstant() const
59 { return get_deactivation_time_constant(); }
60
61 void FirstOrderMuscleActivationDynamics::
setActivationTimeConstant(double activationTimeConstant)62 setActivationTimeConstant(double activationTimeConstant)
63 {
64 set_activation_time_constant(max(SimTK::SignificantReal,
65 activationTimeConstant));
66 }
67
68 void FirstOrderMuscleActivationDynamics::
setDeactivationTimeConstant(double deactivationTimeConstant)69 setDeactivationTimeConstant(double deactivationTimeConstant)
70 {
71 set_deactivation_time_constant(max(SimTK::SignificantReal,
72 deactivationTimeConstant));
73 }
74
75 //==============================================================================
76 // MODELCOMPONENT INTERFACE REQUIREMENTS
77 //==============================================================================
78 void FirstOrderMuscleActivationDynamics::
extendAddToSystem(SimTK::MultibodySystem & system) const79 extendAddToSystem(SimTK::MultibodySystem& system) const
80 {
81 Super::extendAddToSystem(system);
82 addStateVariable(STATE_NAME_ACTIVATION, SimTK::Stage::Dynamics);
83 }
84
85 void FirstOrderMuscleActivationDynamics::
extendInitStateFromProperties(SimTK::State & s) const86 extendInitStateFromProperties(SimTK::State& s) const
87 {
88 Super::extendInitStateFromProperties(s);
89 setActivation(s, getDefaultActivation());
90 }
91
92 void FirstOrderMuscleActivationDynamics::
extendSetPropertiesFromState(const SimTK::State & s)93 extendSetPropertiesFromState(const SimTK::State& s)
94 {
95 Super::extendSetPropertiesFromState(s);
96 setDefaultActivation(getActivation(s));
97 }
98
99 void FirstOrderMuscleActivationDynamics::
computeStateVariableDerivatives(const SimTK::State & s) const100 computeStateVariableDerivatives(const SimTK::State& s) const
101 {
102 double adot =
103 calcActivationDerivative(getExcitation(s), getActivation(s));
104
105 setStateVariableDerivativeValue(s, STATE_NAME_ACTIVATION, adot);
106 }
107
108 //==============================================================================
109 // STATE-DEPENDENT METHODS
110 //==============================================================================
111 double FirstOrderMuscleActivationDynamics::
getActivation(const SimTK::State & s) const112 getActivation(const SimTK::State& s) const
113 {
114 return clampToValidInterval(getStateVariableValue(s, STATE_NAME_ACTIVATION));
115 }
116
setActivation(SimTK::State & s,double activation) const117 void FirstOrderMuscleActivationDynamics::setActivation(SimTK::State& s,
118 double activation) const
119 {
120 setStateVariableValue(s, STATE_NAME_ACTIVATION,
121 clampToValidInterval(activation));
122 }
123
124 //==============================================================================
125 // PRIVATE METHODS
126 //==============================================================================
setNull()127 void FirstOrderMuscleActivationDynamics::setNull()
128 {
129 setAuthors("Thomas Uchida, Matthew Millard, Ajay Seth");
130 }
131
constructProperties()132 void FirstOrderMuscleActivationDynamics::constructProperties()
133 {
134 constructProperty_activation_time_constant(0.010);
135 constructProperty_deactivation_time_constant(0.040);
136 }
137
138 double FirstOrderMuscleActivationDynamics::
calcActivationDerivative(double excitation,double activation) const139 calcActivationDerivative(double excitation, double activation) const
140 {
141 excitation = clampToValidInterval(excitation);
142 activation = clampToValidInterval(activation);
143 double tau = (excitation > activation)
144 ? getActivationTimeConstant() * (0.5 + 1.5*activation)
145 : getDeactivationTimeConstant() / (0.5 + 1.5*activation);
146 return (excitation-activation)/tau;
147 }
148