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