1 /* -------------------------------------------------------------------------- *
2  *            OpenSim:  ActivationFiberLengthMuscle_Deprecated.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): Peter Loan, 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 //==============================================================================
25 // INCLUDES
26 //==============================================================================
27 #include "ActivationFiberLengthMuscle_Deprecated.h"
28 #include "Model.h"
29 
30 using namespace std;
31 using namespace OpenSim;
32 using SimTK::Vec3;
33 
34 //==============================================================================
35 // STATICS
36 //==============================================================================
37 
38 const int ActivationFiberLengthMuscle_Deprecated::STATE_ACTIVATION = 0;
39 const int ActivationFiberLengthMuscle_Deprecated::STATE_FIBER_LENGTH = 1;
40 
41 const string ActivationFiberLengthMuscle_Deprecated::STATE_ACTIVATION_NAME = "activation";
42 const string ActivationFiberLengthMuscle_Deprecated::STATE_FIBER_LENGTH_NAME = "fiber_length";
43 
44 
45 //==============================================================================
46 // CONSTRUCTOR(S) AND DESTRUCTOR
47 //==============================================================================
48 // Uses default (compiler-generated) destructor, copy constructor, copy
49 // assignment operator.
50 
51 //_____________________________________________________________________________
52 // Default constructor.
ActivationFiberLengthMuscle_Deprecated()53 ActivationFiberLengthMuscle_Deprecated::ActivationFiberLengthMuscle_Deprecated()
54 {
55     setNull();
56     constructProperties();
57 }
58 
59 //==============================================================================
60 // CONSTRUCTION METHODS
61 //==============================================================================
62 //_____________________________________________________________________________
63 // Set the data members of this ActivationFiberLengthMuscle_Deprecated to
64 // their null values.
setNull()65 void ActivationFiberLengthMuscle_Deprecated::setNull()
66 {
67     _defaultActivation = 0;
68     _defaultFiberLength = 0;
69 }
70 
71 //_____________________________________________________________________________
72 // Allocate and initialize properties. (There aren't any here.)
constructProperties()73 void ActivationFiberLengthMuscle_Deprecated::constructProperties()
74 {
75 }
76 
77 //_____________________________________________________________________________
78 /**
79  * allocate and initialize the SimTK state for this actuator.
80  */
extendAddToSystem(SimTK::MultibodySystem & system) const81  void ActivationFiberLengthMuscle_Deprecated::extendAddToSystem(SimTK::MultibodySystem& system) const
82 {
83     Super::extendAddToSystem(system);
84     const string& className = getConcreteClassName();
85     const string& suffix = " flag is not currently implemented.";
86 
87     if(get_ignore_activation_dynamics()){
88         string errMsg = className + "::ignore_activation_dynamics" + suffix;
89         throw Exception(errMsg);
90     }
91 
92     if(get_ignore_tendon_compliance()){
93         string errMsg = className + "::ignore_tendon_compliance" + suffix;
94         throw Exception(errMsg);
95     }
96 
97     addStateVariable(STATE_ACTIVATION_NAME);
98     addStateVariable(STATE_FIBER_LENGTH_NAME);
99 
100     // Cache the computed active and passive muscle force
101     // note the total muscle force is the tendon force and is already a cached variable of the actuator
102     addCacheVariable<double>("activeForce", 0.0, SimTK::Stage::Velocity);
103     addCacheVariable<double>("passiveForce", 0.0, SimTK::Stage::Velocity);
104  }
105 
extendInitStateFromProperties(SimTK::State & s) const106  void ActivationFiberLengthMuscle_Deprecated::extendInitStateFromProperties( SimTK::State& s) const
107 {
108     Super::extendInitStateFromProperties(s);
109 
110     setActivation(s, _defaultActivation);
111     setFiberLength(s, _defaultFiberLength);
112 }
113 
extendSetPropertiesFromState(const SimTK::State & state)114 void ActivationFiberLengthMuscle_Deprecated::extendSetPropertiesFromState(const SimTK::State& state)
115 {
116     Super::extendSetPropertiesFromState(state);
117 
118     _defaultActivation = getActivation(state);
119     _defaultFiberLength = getFiberLength(state);
120 }
121 
getDefaultActivation() const122 double ActivationFiberLengthMuscle_Deprecated::getDefaultActivation() const {
123     return _defaultActivation;
124 }
setDefaultActivation(double activation)125 void ActivationFiberLengthMuscle_Deprecated::setDefaultActivation(double activation) {
126     _defaultActivation = activation;
127 }
getDefaultFiberLength() const128 double ActivationFiberLengthMuscle_Deprecated::getDefaultFiberLength() const {
129     return _defaultFiberLength;
130 }
setDefaultFiberLength(double length)131 void ActivationFiberLengthMuscle_Deprecated::setDefaultFiberLength(double length) {
132     _defaultFiberLength = length;
133 }
134 
135 
136 // STATES
137 //_____________________________________________________________________________
138 /**
139  * Set the derivative of an actuator state, specified by index
140  *
141  * @param aStateName The name of the state to set.
142  * @param aValue The value to set the state to.
143  */
setStateVariableDeriv(const SimTK::State & s,const std::string & aStateName,double aValue) const144 void ActivationFiberLengthMuscle_Deprecated::setStateVariableDeriv(const SimTK::State& s, const std::string &aStateName, double aValue) const
145 {
146     double& cacheVariable = updCacheVariableValue<double>(s, aStateName + "_deriv");
147     cacheVariable = aValue;
148     markCacheVariableValid(s, aStateName + "_deriv");
149 }
150 
151 //_____________________________________________________________________________
152 /**
153  * Get the derivative of an actuator state, by index.
154  *
155  * @param aStateName the name of the state to get.
156  * @return The value of the state.
157  */
getStateVariableDeriv(const SimTK::State & s,const std::string & aStateName) const158 double ActivationFiberLengthMuscle_Deprecated::getStateVariableDeriv(const SimTK::State& s, const std::string &aStateName) const
159 {
160     return getCacheVariableValue<double>(s, aStateName + "_deriv");
161 }
162 
163 //_____________________________________________________________________________
164 /**
165  * Compute the derivatives of the muscle states.
166  *
167  * @param s  system state
168  */
169 void ActivationFiberLengthMuscle_Deprecated::
computeStateVariableDerivatives(const SimTK::State & s) const170     computeStateVariableDerivatives(const SimTK::State &s) const
171 {
172     double adot = 0;
173     double ldot = 0;
174     if (appliesForce(s)) {
175         adot = getActivationDeriv(s);
176         ldot = getFiberVelocity(s);
177     }
178 
179     setStateVariableDerivativeValue(s, STATE_ACTIVATION_NAME, adot);
180     setStateVariableDerivativeValue(s, STATE_FIBER_LENGTH_NAME, ldot);
181 }
182 
183 //==============================================================================
184 // GET
185 //==============================================================================
186 //-----------------------------------------------------------------------------
187 // LENGTH
188 //-----------------------------------------------------------------------------
getFiberLength(const SimTK::State & s) const189 double ActivationFiberLengthMuscle_Deprecated::getFiberLength(const SimTK::State& s) const {
190     return getStateVariableValue(s, STATE_FIBER_LENGTH_NAME);
191 }
setFiberLength(SimTK::State & s,double fiberLength) const192 void ActivationFiberLengthMuscle_Deprecated::setFiberLength(SimTK::State& s, double fiberLength) const {
193     setStateVariableValue(s, STATE_FIBER_LENGTH_NAME, fiberLength);
194 }
getFiberLengthDeriv(const SimTK::State & s) const195 double ActivationFiberLengthMuscle_Deprecated::getFiberLengthDeriv(const SimTK::State& s) const {
196     return getStateVariableDeriv(s, STATE_FIBER_LENGTH_NAME);
197 }
setFiberLengthDeriv(const SimTK::State & s,double fiberLengthDeriv) const198 void ActivationFiberLengthMuscle_Deprecated::setFiberLengthDeriv(const SimTK::State& s, double fiberLengthDeriv) const {
199     setStateVariableDeriv(s, STATE_FIBER_LENGTH_NAME, fiberLengthDeriv);
200 }
201 //_____________________________________________________________________________
202 /**
203  * Get the normalized length of the muscle fiber(s).  This is the current
204  * fiber length(s) divided by the optimal fiber length.
205  *
206  * @param Current length of the muscle fiber(s).
207  */
getNormalizedFiberLength(const SimTK::State & s) const208 double ActivationFiberLengthMuscle_Deprecated::getNormalizedFiberLength(const SimTK::State& s) const
209 {
210     return getFiberLength(s) / getOptimalFiberLength();
211 }
212 //_____________________________________________________________________________
213 /**
214  * Get the length of the muscle fiber(s) along the tendon. This method
215  * accounts for the pennation angle.
216  *
217  * @return Current length of the muscle fiber(s) along the direction of
218  * the tendon.
219  */
getFiberLengthAlongTendon(const SimTK::State & s) const220 double ActivationFiberLengthMuscle_Deprecated::getFiberLengthAlongTendon(const SimTK::State& s) const
221 {
222     return getFiberLength(s) * cos(getPennationAngle(s));
223 }
224 //_____________________________________________________________________________
225 /**
226  * Get the length of the tendon.
227  *
228  * @return Current length of the tendon.
229  */
getTendonLength(const SimTK::State & s) const230 double ActivationFiberLengthMuscle_Deprecated::getTendonLength(const SimTK::State& s) const
231 {
232     return getLength(s) - getFiberLengthAlongTendon(s);
233 }
234 
235 //-----------------------------------------------------------------------------
236 // FORCE
237 //-----------------------------------------------------------------------------
238 //_____________________________________________________________________________
239 /**
240  * Compute the force generated by the muscle fibers. This accounts for
241  * pennation angle. That is, the fiber force is computed by dividing the
242  * actuator force by the cosine of the pennation angle.
243  *
244  * @return Force in the muscle fibers.
245  */
getFiberForce(const SimTK::State & s) const246 double ActivationFiberLengthMuscle_Deprecated::getFiberForce(const SimTK::State& s) const
247 {
248     double force;
249     double cos_penang = cos(getPennationAngle(s));
250     if(fabs(cos_penang) < SimTK::Zero) {
251         force = SimTK::NaN;
252     } else {
253         force = getActuation(s) / cos_penang;
254     }
255 
256     return force;
257 }
258 //_____________________________________________________________________________
259 /**
260  * Get the active force generated by the muscle fibers.
261  *
262  * @return Current active force of the muscle fibers.
263  */
getActiveFiberForce(const SimTK::State & s) const264 double ActivationFiberLengthMuscle_Deprecated::getActiveFiberForce(const SimTK::State& s) const
265 {
266     return getFiberForce(s) - getPassiveFiberForce(s);
267 }
268 /**
269  * Get the passive force generated by the muscle fibers.
270  *
271  * @param Current passive force of the muscle fiber(s).
272  */
getPassiveFiberForce(const SimTK::State & s) const273 double ActivationFiberLengthMuscle_Deprecated::getPassiveFiberForce(const SimTK::State& s) const
274 {
275     return getPassiveForce(s);
276 }
277 //_____________________________________________________________________________
278 /**
279  * Get the active force generated by the muscle fibers along the direction
280  * of the tendon.
281  *
282  * @return Current active force of the muscle fibers along tendon.
283  */
getActiveFiberForceAlongTendon(const SimTK::State & s) const284 double ActivationFiberLengthMuscle_Deprecated::getActiveFiberForceAlongTendon(const SimTK::State& s) const
285 {
286     return getActiveFiberForce(s) * cos(getPennationAngle(s));
287 }
288 //_____________________________________________________________________________
289 /**
290  * Get the passive force generated by the muscle fibers along the direction
291  * of the tendon.
292  *
293  * @return Current passive force of the muscle fibers along tendon.
294  */
getPassiveFiberForceAlongTendon(const SimTK::State & s) const295 double ActivationFiberLengthMuscle_Deprecated::getPassiveFiberForceAlongTendon(const SimTK::State& s) const
296 {
297     return getPassiveFiberForce(s) * cos(getPennationAngle(s));
298 }
getPassiveForce(const SimTK::State & s) const299 double ActivationFiberLengthMuscle_Deprecated::getPassiveForce( const SimTK::State& s) const {
300     return getCacheVariableValue<double>(s, "passiveForce");
301 }
setPassiveForce(const SimTK::State & s,double force) const302 void ActivationFiberLengthMuscle_Deprecated::setPassiveForce(const SimTK::State& s, double force ) const {
303     setCacheVariableValue<double>(s, "passiveForce", force);
304 }
305 
getTendonForce(const SimTK::State & s) const306 double ActivationFiberLengthMuscle_Deprecated::getTendonForce(const SimTK::State& s) const {
307     return getActuation(s);
308 }
setTendonForce(const SimTK::State & s,double force) const309 void ActivationFiberLengthMuscle_Deprecated::setTendonForce(const SimTK::State& s, double force) const {
310     setActuation(s, force);
311 }
getActivation(const SimTK::State & s) const312 double ActivationFiberLengthMuscle_Deprecated::getActivation(const SimTK::State& s) const {
313     return getStateVariableValue(s, STATE_ACTIVATION_NAME);
314 }
setActivation(SimTK::State & s,double activation) const315 void ActivationFiberLengthMuscle_Deprecated::setActivation(SimTK::State& s, double activation) const {
316     setStateVariableValue(s, STATE_ACTIVATION_NAME, activation);
317 }
getActivationDeriv(const SimTK::State & s) const318 double ActivationFiberLengthMuscle_Deprecated::getActivationDeriv(const SimTK::State& s) const {
319     return getStateVariableDeriv(s, STATE_ACTIVATION_NAME);
320 }
setActivationDeriv(const SimTK::State & s,double activationDeriv) const321 void ActivationFiberLengthMuscle_Deprecated::setActivationDeriv(const SimTK::State& s, double activationDeriv) const {
322     setStateVariableDeriv(s, STATE_ACTIVATION_NAME, activationDeriv);
323 }
324 //_____________________________________________________________________________
325 //**
326 // * get the excitation value for this ActivationFiberLengthMuscle_Deprecated
327 // */
getExcitation(const SimTK::State & s) const328 double ActivationFiberLengthMuscle_Deprecated::getExcitation( const SimTK::State& s) const {
329     return( getControl(s) );
330 }
331 //_____________________________________________________________________________
332 /**
333  * Get the stress in this actuator.  It is calculated as the force divided
334  * by the maximum isometric force (which is proportional to its area).
335  */
getStress(const SimTK::State & s) const336 double ActivationFiberLengthMuscle_Deprecated::getStress(const SimTK::State& s) const
337 {
338     return getActuation(s) / get_max_isometric_force();
339 }
340 
341 //==============================================================================
342 // SCALING
343 //==============================================================================
344 void ActivationFiberLengthMuscle_Deprecated::
extendPostScale(const SimTK::State & s,const ScaleSet & scaleSet)345 extendPostScale(const SimTK::State& s, const ScaleSet& scaleSet)
346 {
347     Super::extendPostScale(s, scaleSet);
348 
349     GeometryPath& path = upd_GeometryPath();
350     if (path.getPreScaleLength(s) > 0.0)
351     {
352         double scaleFactor = path.getLength(s) / path.getPreScaleLength(s);
353         upd_optimal_fiber_length() *= scaleFactor;
354         upd_tendon_slack_length() *= scaleFactor;
355 
356         // Clear the pre-scale length that was stored in the GeometryPath.
357         path.setPreScaleLength(s, 0.0);
358     }
359 }
360 
361 //--------------------------------------------------------------------------
362 // COMPUTATIONS
363 //--------------------------------------------------------------------------
364 
365 //==============================================================================
366 // FORCE APPLICATION
367 //==============================================================================
368 //_____________________________________________________________________________
369 /**
370  * Apply the muscle's force at its points of attachment to the bodies.
371  */
computeForce(const SimTK::State & s,SimTK::Vector_<SimTK::SpatialVec> & bodyForces,SimTK::Vector & generalizedForces) const372 void ActivationFiberLengthMuscle_Deprecated::computeForce(const SimTK::State& s,
373                               SimTK::Vector_<SimTK::SpatialVec>& bodyForces,
374                               SimTK::Vector& generalizedForces) const
375 {
376     Super::computeForce(s, bodyForces, generalizedForces);
377 
378     if (isActuationOverridden(s)) {
379         // Also define the state derivatives, since realize acceleration will
380         // ask for muscle derivatives, which will be integrated
381         // in the case the force is being overridden, the states aren't being used
382         // but a valid derivative cache entry is still required
383         setStateVariableDeriv(s, STATE_ACTIVATION_NAME, 0.0);
384         setStateVariableDeriv(s, STATE_FIBER_LENGTH_NAME, 0.0);
385     }
386 }
387 
388 //_____________________________________________________________________________
389 /**
390  * Compute the equilibrium states.  This method computes a fiber length
391  * for the muscle that is consistent with the muscle's activation level.
392  */
computeInitialFiberEquilibrium(SimTK::State & s) const393 void ActivationFiberLengthMuscle_Deprecated::computeInitialFiberEquilibrium(SimTK::State& s) const
394 {
395     /*double force = */computeIsometricForce(s, getActivation(s));
396 
397     //cout<<getName()<<": isometric force = "<<force<<endl;
398     //cout<<getName()<<": fiber length = "<<getFiberLength(s)<<endl;
399 }
400 
401 
402 double ActivationFiberLengthMuscle_Deprecated::
calcInextensibleTendonActiveFiberForce(SimTK::State & s,double aActivation) const403     calcInextensibleTendonActiveFiberForce(SimTK::State& s, double aActivation) const
404 {
405     double isometricForce = computeIsometricForce(s, aActivation);
406 
407     const double &optimalFiberLength = get_optimal_fiber_length();
408     const double &pennationAngleAtOptimal = get_pennation_angle_at_optimal();
409     const double &maxContractionVelocity = get_max_contraction_velocity();
410 
411     //double normalizedLength = getFiberLength(s) / optimalFiberLength;
412     double normalizedVelocity = -cos(pennationAngleAtOptimal) * getLengtheningSpeed(s) / (maxContractionVelocity * optimalFiberLength);
413     double normalizedForceVelocity = evaluateForceLengthVelocityCurve(1.0,1.0,normalizedVelocity);
414 
415     return isometricForce * normalizedForceVelocity;
416 }
417 
418 //==============================================================================
419 // GENERIC NORMALIZED FORCE-LENGTH-VELOCITY PROPERTIES
420 //==============================================================================
421 //_____________________________________________________________________________
422 /**
423  * Evaluate the normalized force-length-velocity curve for the Muscle_Deprecated.
424  * A simple generic implementation is used here.  Derived classes should
425  * override this method for more precise evaluation of the
426  * force-length-velocity curve.
427  *
428  * @param aActivation Activation level of the Muscle_Deprecated.  1.0 is full activation;
429  * 0.0 is no activation.
430  * @param aNormalizedLength Normalized length of the Muscle_Deprecated fibers.  1.0 indicates
431  * the Muscle_Deprecated fibers are at their optimal length.  Lnorm = L / Lo.
432  * @param aNormalizedVelocity Normalized shortening velocity of the Muscle_Deprecated fibers.
433  * Positive values indicate concentric contraction (shortening); negative values
434  * indicate eccentric contraction (lengthening).  Normalized velocity is
435  * the fiber shortening velocity divided by the maximum shortening velocity times
436  * the optimal fiber length.  Vnorm = V / (Vmax*Lo).
437  * @return Force normalized by the optimal force.
438  */
evaluateForceLengthVelocityCurve(double aActivation,double aNormalizedLength,double aNormalizedVelocity) const439 double ActivationFiberLengthMuscle_Deprecated::evaluateForceLengthVelocityCurve(double aActivation, double aNormalizedLength, double aNormalizedVelocity) const
440 {
441     // force-length
442     double fLength = exp(-17.33 * fabs(pow(aNormalizedLength-1.0,3)));
443 
444     // force-velocity
445     double fVelocity = 1.8  -  1.8 / (1.0 + exp( (0.04 - aNormalizedVelocity)/0.18) );
446 
447     return aActivation * fLength * fVelocity;
448 }
449 
450 
451 //_____________________________________________________________________________
452 /**
453  * Utility function to calculate the current pennation angle in a
454  * Muscle_Deprecated. Pennation angle increases as Muscle_Deprecated fibers shorten. The implicit
455  * modeling assumption is that Muscle_Deprecateds have constant width.
456  *
457  * @param aFiberLength Current fiber length of Muscle_Deprecated.
458  * @param aOptimalFiberLength Optimal fiber length of Muscle_Deprecated.
459  * @param aInitialPennationAngle Pennation angle at optimal fiber length (in radians).
460  * @return Current pennation angle (in radians).
461  */
calcPennation(double aFiberLength,double aOptimalFiberLength,double aInitialPennationAngle) const462 double ActivationFiberLengthMuscle_Deprecated::calcPennation( double aFiberLength, double aOptimalFiberLength,
463                                                 double aInitialPennationAngle) const
464 {
465     if (aFiberLength < SimTK::Eps)
466         return 0.0;
467 
468    double value = aOptimalFiberLength * sin(aInitialPennationAngle) / aFiberLength;
469 
470    if ( SimTK::isNaN(value)  )
471        return 0.0;
472    else if (value <= 0.0 )
473       return 0.0;
474    else if (value >= 1.0)
475         return SimTK_PI/2.0;
476    else
477       return asin(value);
478 }
479 
480 //==============================================================================
481 // CALCULATIONS
482 //==============================================================================
483 /* calculate muscle's position related values such fiber and tendon lengths,
484     normalized lengths, pennation angle, etc... */
calcMuscleLengthInfo(const SimTK::State & s,MuscleLengthInfo & mli) const485 void ActivationFiberLengthMuscle_Deprecated::calcMuscleLengthInfo(const SimTK::State& s, MuscleLengthInfo& mli) const
486 {
487     double norm_muscle_tendon_length = getLength(s) / getOptimalFiberLength();
488 
489     mli.fiberLength = getStateVariableValue(s, STATE_FIBER_LENGTH_NAME);
490 
491     mli.pennationAngle = calcPennation(mli.fiberLength, getOptimalFiberLength(), getPennationAngleAtOptimalFiberLength());
492 
493     mli.cosPennationAngle = cos(mli.pennationAngle);
494     mli.tendonLength = getLength(s)-mli.fiberLength*mli.cosPennationAngle;
495 
496     mli.normFiberLength = mli.fiberLength/getOptimalFiberLength();
497     mli.normTendonLength = norm_muscle_tendon_length - mli.normFiberLength * mli.cosPennationAngle;
498     mli.tendonStrain = (mli.tendonLength/getTendonSlackLength()-1.0);
499 
500     mli.fiberActiveForceLengthMultiplier = calcActiveForce(s, mli.normFiberLength);
501     mli.fiberPassiveForceLengthMultiplier = calcPassiveForce(s, mli.normFiberLength);
502 }
503 
504 /* calculate muscle's velocity related values such fiber and tendon velocities,
505     normalized velocities, pennation angular velocity, etc... */
calcFiberVelocityInfo(const SimTK::State & s,FiberVelocityInfo & fvi) const506 void ActivationFiberLengthMuscle_Deprecated::calcFiberVelocityInfo(const SimTK::State& s, FiberVelocityInfo& fvi) const
507 {
508     fvi.fiberVelocity = getFiberLengthDeriv(s);
509     fvi.normFiberVelocity = fvi.fiberVelocity/(getOptimalFiberLength()*getMaxContractionVelocity());
510 }
511 
512 /* calculate muscle's active and passive force-length, force-velocity,
513     tendon force, relationships and their related values */
calcMuscleDynamicsInfo(const SimTK::State & s,MuscleDynamicsInfo & mdi) const514 void ActivationFiberLengthMuscle_Deprecated::calcMuscleDynamicsInfo(const SimTK::State& s, MuscleDynamicsInfo& mdi) const
515 {
516     const MuscleLengthInfo &mli = getMuscleLengthInfo(s);
517     const double &maxIsometricForce = getMaxIsometricForce();
518 
519     double tendonForce = getActuation(s);
520     mdi.normTendonForce = tendonForce/maxIsometricForce;
521 
522     mdi.passiveFiberForce = mli.fiberPassiveForceLengthMultiplier * maxIsometricForce;
523 
524     mdi.activation = getStateVariableValue(s, STATE_ACTIVATION_NAME);
525 
526     mdi.activeFiberForce =  tendonForce/mli.cosPennationAngle - mdi.passiveFiberForce;
527 }
528