1 #ifndef OPENSIM_UMBERGER2010_METABOLIC_POWER_PROBE_H_
2 #define OPENSIM_UMBERGER2010_METABOLIC_POWER_PROBE_H_
3 /* -------------------------------------------------------------------------- *
4  *               OpenSim:  Umberger2010MuscleMetabolicsProbe.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): Tim Dorn                                                        *
14  * Contributor(s): Thomas Uchida                                              *
15  *                                                                            *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
17  * not use this file except in compliance with the License. You may obtain a  *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
19  *                                                                            *
20  * Unless required by applicable law or agreed to in writing, software        *
21  * distributed under the License is distributed on an "AS IS" BASIS,          *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
23  * See the License for the specific language governing permissions and        *
24  * limitations under the License.                                             *
25  * -------------------------------------------------------------------------- */
26 
27 #include "Probe.h"
28 #include <OpenSim/Common/Set.h>
29 
30 namespace OpenSim {
31 
32 class Model;
33 class Muscle;
34 
35 // Helper classes defined below.
36 class Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter;
37 class Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameterSet;
38 
39 //=============================================================================
40 //             MUSCLE METABOLIC POWER PROBE (Umberger, et al., 2010)
41 //=============================================================================
42 
43 /**
44  * %Umberger2010MuscleMetabolicsProbe is a Probe ModelComponent for computing
45  * the net metabolic energy rate of a set of Muscles in the model during a
46  * simulation.
47  *
48  * <h1>%Umberger2010MuscleMetabolicsProbe Theory</h1>
49  *
50  * The discussion here is based on the following papers:
51  *
52  * <a href="http://dx.doi.org/10.1371/journal.pone.0150378">
53  * Uchida, T. K., Hicks, J. L., Dembia, C. L., Delp, S. L. (2016). Stretching
54  * your energetic budget: how tendon compliance affects the metabolic cost of
55  * running. PLOS ONE 11(3), e0150378.</a>
56  *
57  * <a href="http://www.ncbi.nlm.nih.gov/pubmed/20356877">
58  * Umberger, B. R. (2010). Stance and swing phase costs in human walking.
59  * J R Soc Interface 7, 1329-40.</a>
60  *
61  * <a href="http://www.ncbi.nlm.nih.gov/pubmed/12745424">
62  * Umberger, B. R., Gerritsen, K. G. and Martin, P. E. (2003).
63  * A model of human muscle energy expenditure.
64  * Comput Methods Biomech Biomed Engin 6, 99-111.</a>
65  *
66  * <I>Note that the equations below that describe the particular implementation
67  * of %Umberger2010MuscleMetabolicsProbe may slightly differ from the equations
68  * described in the representative publications above. Note also that we define
69  * positive muscle velocity to indicate lengthening (eccentric contraction) and
70  * negative muscle velocity to indicate shortening (concentric contraction).</I>
71  *
72  *
73  * %Muscle metabolic power (or rate of metabolic energy consumption) is equal to
74  * the rate at which heat is liberated plus the rate at which work is done:\n
75  * <B>Edot = Bdot + sumOfAllMuscles(Adot + Mdot + Sdot + Wdot).</B>
76  *
77  * - Bdot is the basal heat rate (W).
78  * - Adot is the activation heat rate (W).
79  * - Mdot is the maintenance heat rate (W).
80  * - Sdot is the shortening heat rate (W).
81  * - Wdot is the mechanical work rate (W).
82  *
83  *
84  * This probe also uses muscle parameters stored in the MetabolicMuscle object for each muscle.
85  * The full set of all MetabolicMuscles (MetabolicMuscleSet) is a property of this probe:
86  *
87  * - m = The mass of the muscle (kg).
88  * - r = Ratio of slow-twitch fibers in the muscle (between 0 and 1).
89  *
90  * The recruitment model described by Bhargava et al. (2004) is used to set the
91  * slow-twitch fiber ratio used in the calculations below. The ratio specified
92  * by the user indicates the composition of the muscle; this value is used only
93  * at full excitation (i.e., when all fibers are recruited). As excitation
94  * decreases from 1 to 0, the proportion of recruited fibers that are
95  * slow-twitch fibers increases from r to 1. See
96  * <a href="http://www.ncbi.nlm.nih.gov/pubmed/14672571">Bhargava, L.J., Pandy,
97  * M.G., Anderson, F.C. (2004) A phenomenological model for estimating metabolic
98  * energy consumption in muscle contraction. J Biomech 37:81-88</a> and Uchida
99  * et al. (2016). To assume a constant ratio of slow- and fast-twitch fiber
100  * recruitment, set the 'use_Bhargava_recruitment_model' property to false.
101  *
102  *
103  *
104  * <H2><B> BASAL HEAT RATE (W) </B></H2>
105  * If <I>basal_rate_on</I> is set to true, then Bdot is calculated as follows:\n
106  * <B>Bdot = basal_coefficient * (m_body^basal_exponent) </B>
107  *     - m_body = mass of the entire model
108  *     - basal_coefficient and basal_exponent are defined by their respective properties.\n
109  * <I>Note that this quantity is muscle independent. Rather it is calculated on a whole body level.</I>
110  *
111  *
112  * <H2><B> ACTIVATION & MAINTENANCE HEAT RATE (W) </B></H2>
113  * If <I>activation_maintenance_rate_on</I> is set to true, then Adot+Mdot is calculated as follows:\n
114  * <B>Adot+Mdot = [128*(1-r) + 25] * A^0.6 * S                                         </B>,  <I> l_CE <= l_CE_opt </I>\n
115  * <B>Adot+Mdot = (0.4*[128*(1-r) + 25] + 0.6*[128*(1-r) + 25]*F_CE_iso) * A^0.6 * S   </B>,  <I> l_CE >  l_CE_opt </I>
116  *     - <B>A = u          </B>,    u >  a
117  *     - <B>A = (u+a)/2    </B>,    u <= a
118  *
119  *     - m = The mass of the muscle (kg).
120  *     - l_CE = muscle fiber length at the current time.
121  *     - l_CE_opt = optimal fiber length of the muscle.
122  *     - F_CE_iso = normalized contractile element force-length curve.
123  *     - u = muscle excitation at the current time.
124  *     - a = muscle activation at the current time.
125  *     - S = aerobic/anaerobic scaling factor, defined by the 'aerobic_factor' property (i.e. usually 1.0 for primarily anaerobic activities, 1.5 for primarily aerobic activities).
126  *
127  *
128  * <H2><B> SHORTENING HEAT RATE (W) </B></H2>
129  * If <I>shortening_rate_on</I> is set to true, then Sdot is calculated as follows:\n
130  * <B>Sdot = m * (-[(alphaS_slow * v_CE_norm * r) + (alphaS_fast * v_CE_norm * (1-r))] * A^2 * S)           </B>,   <I>l_CE <= l_CE_opt   &   v_CE >= 0 (concentric / isometric contraction)</I>\n
131  * <B>Sdot = m * (-[(alphaS_slow * v_CE_norm * r) + (alphaS_fast * v_CE_norm * (1-r))] * A^2 * S * F_iso)   </B>,   <I>l_CE >  l_CE_opt   &   v_CE >= 0 (concentric / isometric contraction)</I>\n
132  * <B>Sdot = m * (alphaL * v_CE_norm * A * S)              </B>,   <I>l_CE <= l_CE_opt   &   v_CE <  0 (eccentric contraction)</I>\n
133  * <B>Sdot = m * (alphaL * v_CE_norm * A * S * F_CE_iso)   </B>,   <I>l_CE >  l_CE_opt   &   v_CE <  0 (eccentric contraction)</I>
134  *     - <B>A = u          </B>,    <I>u >  a </I>
135  *     - <B>A = (u+a)/2    </B>,    <I>u <= a </I>
136  *
137  *     - <B>alphaS_fast = 153 / v_CE_max          </B>
138  *     - <B>alphaS_slow = 100 / (v_CE_max / 2.5)  </B>
139  *     - <B>alphaL = 4.0 * alphaS_slow </B>
140  *
141  *     - m = The mass of the muscle (kg).
142  *     - l_CE = muscle fiber length at the current time.
143  *     - l_CE_opt = optimal fiber length of the muscle.
144  *     - F_CE_iso = force that would be developed by the contractile element of muscle under isometric conditions with the current activation and fiber length.
145  *     - v_CE = muscle fiber velocity at the current time.
146  *     - v_CE_max = maximum shortening velocity of the muscle.
147  *     - v_CE_norm = normalized muscle fiber velocity (defined for this model as v_CE/l_CE_opt).
148  *               Note that this is a different metric to the typical normalized_muscle_fiber_velocity of v_CE/v_CE_max.
149  *     - S = aerobic/anaerobic scaling factor, defined by the 'aerobic_factor' property (i.e. usually 1.0 for primarily anaerobic activities, 1.5 for primarily aerobic activities).
150  *
151  *
152  * <H2><B> MECHANICAL WORK RATE (W) </B></H2>
153  * If <I>mechanical_work_rate_on</I> is set to true, then Wdot is calculated as follows:\n
154  * <B>Wdot = -(F_CE * v_CE)           </B>
155  *     - v_CE = muscle fiber velocity at the current time.
156  *     - F_CE = force developed by the contractile element of muscle at the current time.\n
157  *
158  * If we draw a control volume around the fiber, the first law of thermodynamics
159  * suggests that negative mechanical work should be included in Wdot. As such,
160  * we revert back to the model described in Umberger et al. (2003) by default.
161  * To exclude negative mechanical work from Wdot and use a coefficient of 0.3
162  * (rather than 4.0) to calculate alpha_L, set the
163  * 'include_negative_mechanical_work' property to false.
164  *
165  * During eccentric contraction, the magnitude of the (negative) mechanical work
166  * rate can exceed that of the total (positive) heat rate, resulting in a flow
167  * of energy into the fiber. Experiments indicate that the chemical processes
168  * involved in fiber contraction cannot be reversed, and most of the energy that
169  * is absorbed during eccentric contraction (in increased cross-bridge
170  * potentials, for example) is eventually converted into heat. Thus, we increase
171  * Sdot (if necessary) to ensure Edot > 0 for each muscle. See
172  * <a href="http://www.ncbi.nlm.nih.gov/pubmed/9409483">Constable, J.K.,
173  * Barclay, C.J., Gibbs, C.L. (1997) Energetics of lengthening in mouse and toad
174  * skeletal muscles. J Physiol 505:205-215</a> and Uchida et al. (2016). To
175  * allow muscles to have negative total power, set the
176  * 'forbid_negative_total_power' property to false.
177  *
178  *
179  * Note that if enforce_minimum_heat_rate_per_muscle == true AND
180  * activation_maintenance_rate_on == shortening_rate_on == true, then the total heat
181  * rate (AMdot + Sdot) will be capped to a minimum value of 1.0 W/kg (Umberger(2003), page 104).
182  *
183  *
184  *
185  *
186  * <H1>Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter</H1>
187  *
188  * Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter is an Object class that
189  * holds the metabolic parameters required to calculate metabolic power for a single muscle.
190  *
191  * <H2><B> Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter Properties </B></H2>
192  *
193  * REQUIRED PROPERTIES
194  * - <B>specific_tension</B> = The specific tension of the muscle (Pascals (N/m^2)).
195  * - <B>density</B> = The density of the muscle (kg/m^3).
196  * - <B>ratio_slow_twitch_fibers</B> = Ratio of slow twitch fibers in the muscle (must be between 0 and 1).
197  *
198  * OPTIONAL PROPERTIES
199  * - <B>use_provided_muscle_mass</B> = An optional flag that allows the user to
200  *      explicitly specify a muscle mass. If set to true, the 'provided_muscle_mass'
201  *      property must be specified. The default setting is false, in which case, the
202  *      muscle mass is calculated from the following formula:
203  *          m = (Fmax/specific_tension)*density*Lm_opt, where
204  *              specific_tension and density are properties defined above
205  *                  (note that their default values are set based on mammalian muscle,
206  *                  0.25e6 N/m^2 and 1059.7 kg/m^3, respectively);
207  *              Fmax and Lm_opt are the maximum isometric force and optimal
208  *                  fiber length, respectively, of the muscle.
209  *
210  * - <B>provided_muscle_mass</B> = The user specified muscle mass (kg).
211  *
212  *
213  * @author Tim Dorn
214  */
215 
216 class OSIMSIMULATION_API Umberger2010MuscleMetabolicsProbe : public Probe {
217 OpenSim_DECLARE_CONCRETE_OBJECT(Umberger2010MuscleMetabolicsProbe, Probe);
218 public:
219 //==============================================================================
220 // PROPERTIES
221 //==============================================================================
222     /** Enabled by default. **/
223     OpenSim_DECLARE_PROPERTY(activation_maintenance_rate_on,
224         bool,
225         "Specify whether activation & maintenance heat rate is to be calculated (true/false).");
226 
227     /** Enabled by default. **/
228     OpenSim_DECLARE_PROPERTY(shortening_rate_on,
229         bool,
230         "Specify whether shortening heat rate is to be calculated (true/false).");
231 
232     /** Enabled by default. **/
233     OpenSim_DECLARE_PROPERTY(basal_rate_on,
234         bool,
235         "Specify whether basal heat rate is to be calculated (true/false).");
236 
237     /** Enabled by default. **/
238     OpenSim_DECLARE_PROPERTY(mechanical_work_rate_on,
239         bool,
240         "Specify whether mechanical work rate is to be calculated (true/false).");
241 
242     /** Enabled by default. **/
243     OpenSim_DECLARE_PROPERTY(enforce_minimum_heat_rate_per_muscle,
244         bool,
245         "Specify whether the total heat rate for a muscle will be clamped to a "
246         "minimum value of 1.0 W/kg (true/false).");
247 
248     /** Default value = 1.5. **/
249     OpenSim_DECLARE_PROPERTY(aerobic_factor,
250         double,
251         "Aerobic scale factor (S=1.0 for primarily anaerobic conditions and S=1.5 "
252         "for primarily aerobic conditions. See Umberger et al., (2003).");
253 
254     /** Default value = 1.2. **/
255     OpenSim_DECLARE_PROPERTY(basal_coefficient,
256         double,
257         "Basal metabolic coefficient.");
258 
259     /** Default value = 1.0. **/
260     OpenSim_DECLARE_PROPERTY(basal_exponent,
261         double,
262         "Basal metabolic exponent.");
263 
264     /** Default value = 1.0. **/
265     OpenSim_DECLARE_PROPERTY(muscle_effort_scaling_factor,
266         double,
267         "Scale the excitation and activation values used by the probe to "
268         "compensate for solutions with excessive coactivation (e.g., when a "
269         "suboptimal tracking strategy is used).");
270 
271     /** Enabled by default. **/
272     OpenSim_DECLARE_PROPERTY(use_Bhargava_recruitment_model,
273         bool,
274         "Specify whether the recruitment model described by Bhargava et al. "
275         "(2004) will used to determine the slow-twitch fiber ratio "
276         "(true/false). Disable to use the model as published in Umberger "
277         "(2010).");
278 
279     /** Enabled by default. **/
280     OpenSim_DECLARE_PROPERTY(include_negative_mechanical_work,
281         bool,
282         "Specify whether negative mechanical work will be included in Wdot and "
283         "a coefficient of 4.0 will be used to calculate alpha_L (true/false). "
284         "Disable to use the model as published in Umberger (2010).");
285 
286     /** Enabled by default. **/
287     OpenSim_DECLARE_PROPERTY(forbid_negative_total_power,
288         bool,
289         "Specify whether the total power for each muscle must remain positive "
290         "(true/false). Disable to use the model as published in Umberger "
291         "(2010).");
292 
293     /** Default value = true **/
294     OpenSim_DECLARE_PROPERTY(report_total_metabolics_only,
295         bool,
296         "If set to false, the individual muscle metabolics, basal rate, and "
297         "total summation will be reported. If set to true, only the total "
298         "summation will be reported.");
299 
300     OpenSim_DECLARE_UNNAMED_PROPERTY(
301         Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameterSet,
302         "A set containing, for each muscle, the parameters "
303         "required to calculate muscle metabolic power.");
304 
305 //=============================================================================
306 // PUBLIC METHODS
307 //=============================================================================
308     /** MuscleMap typedef */
309     typedef std::map
310        <std::string,
311         Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter*>
312         MuscleMap;
313 
314     //--------------------------------------------------------------------------
315     // Constructor(s) and Setup
316     //--------------------------------------------------------------------------
317     /** Default constructor */
318     Umberger2010MuscleMetabolicsProbe();
319 
320     /** Convenience constructor */
321     Umberger2010MuscleMetabolicsProbe(
322         const bool activation_maintenance_rate_on,
323         const bool shortening_rate_on,
324         const bool basal_rate_on,
325         const bool work_rate_on);
326 
327 
328     //-----------------------------------------------------------------------------
329     // Computation
330     //-----------------------------------------------------------------------------
331     /** Compute muscle metabolic power. */
332     virtual SimTK::Vector computeProbeInputs(const SimTK::State& state) const override;
333 
334     /** Returns the number of probe inputs in the vector returned by computeProbeInputs(). */
335     int getNumProbeInputs() const override;
336 
337     /** Returns the column labels of the probe values for reporting.
338         Currently uses the Probe name as the column label, so be sure
339         to name your probe appropriately!  */
340     virtual OpenSim::Array<std::string> getProbeOutputLabels() const override;
341 
342 
343     //-----------------------------------------------------------------------------
344     /** @name     Umberger2010MuscleMetabolicsProbe Interface
345     These accessor methods are to be used when setting up a new muscle
346     metabolic analysis from the API. The basic operation is as follows:
347     @code
348     Umberger2010MuscleMetabolicsProbe* myProbe new Umberger2010MuscleMetabolicsProbe(...);
349     model.addProbe(myProbe);
350     myProbe->addMuscle("muscleName1", ... );
351     myProbe->addMuscle("muscleName2", ... );
352     myProbe->addMuscle("muscleName3", ... );
353     myProbe->useProvidedMass("muscleName1", 1.2);         // muscle1 mass = 1.2 kg
354     myProbe->useCalculatedMass("muscleName2");            // muscle2 mass is based on muscle properties (below)
355     myProbe->setDensity("muscleName2", 1100.0);           // muscle2 density is 1100 kg/m^3
356     myProbe->setSpecificTension("muscleName2", 0.26e6);   // muscle2 specific tension is 0.26e6 Pa
357     myProbe->removeMuscle("muscleName3");
358     myProbe->setOperation("integrate")           // See OpenSim::Probe for other operations
359     @endcode
360     @note It is important to first add the metabolic probe to the model before
361     calling any other methods that may modify its properties. This is because
362     some methods (e.g. addMuscle() or useCalculatedMass) may require information
363     about the muscles to successfully execute, and this information can only be
364     obtained if the metabolic probe is already 'connected' to the model.
365     */
366     /** Get the number of muscles being analyzed in the metabolic analysis. */
367     const int getNumMetabolicMuscles() const;
368 
369     /** Add a muscle and its parameters so that it can be included in the metabolic analysis. */
370     void addMuscle(const std::string& muscleName,
371         double ratio_slow_twitch_fibers);
372 
373     /** Add a muscle and its parameters so that it can be included in the metabolic analysis. */
374     void addMuscle(const std::string& muscleName,
375         double ratio_slow_twitch_fibers,
376         double muscle_mass);
377 
378     /** Remove a muscle from the metabolic analysis. */
379     void removeMuscle(const std::string& muscleName);
380 
381     /** %Set an existing muscle to use a provided muscle mass. */
382     void useProvidedMass(const std::string& muscleName, double providedMass);
383 
384     /** %Set an existing muscle to calculate its own mass. */
385     void useCalculatedMass(const std::string& muscleName);
386 
387     /** Get whether the muscle mass is being explicitly provided.
388         True means that it is using the property 'provided_muscle_mass'
389         False means that the muscle mass is being calculated from muscle properties. */
390     bool isUsingProvidedMass(const std::string& muscleName);
391 
392     /** Get the muscle mass used in the metabolic analysis. The value
393         returned will depend on if the muscle mass is explicitly provided
394         (i.e. isUsingProvidedMass = true), or if it is being automatically
395         calculated from muscle data already present in the model
396         (i.e. isUsingProvidedMass = true). */
397     const double getMuscleMass(const std::string& muscleName) const;
398 
399     /** Get the ratio of slow twitch fibers for an existing muscle. */
400     const double getRatioSlowTwitchFibers(const std::string& muscleName) const;
401 
402     /** %Set the ratio of slow twitch fibers for an existing muscle. */
403     void setRatioSlowTwitchFibers(const std::string& muscleName, const double& ratio);
404 
405     /** Get the density for an existing muscle (kg/m^3). */
406     const double getDensity(const std::string& muscleName) const;
407 
408     /** %Set the density for an existing muscle (kg/m^3). */
409     void setDensity(const std::string& muscleName, const double& density);
410 
411     /** Get the specific tension for an existing muscle (Pascals (N/m^2)). */
412     const double getSpecificTension(const std::string& muscleName) const;
413 
414     /** %Set the specific tension for an existing muscle (Pascals (N/m^2)). */
415     void setSpecificTension(const std::string& muscleName, const double& specificTension);
416 
417 
418 
419 //==============================================================================
420 // PRIVATE
421 //==============================================================================
422 private:
423     //--------------------------------------------------------------------------
424     // Data
425     //--------------------------------------------------------------------------
426     MuscleMap _muscleMap;
427 
428     //--------------------------------------------------------------------------
429     // ModelComponent Interface
430     //--------------------------------------------------------------------------
431     void extendConnectToModel(Model& aModel) override;
432     void connectIndividualMetabolicMuscle
433        (Model& aModel,
434         Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter& mm);
435 
436     void setNull();
437     void constructProperties();
438 
439 
440     //--------------------------------------------------------------------------
441     // MetabolicMuscleParameter Private Interface
442     //--------------------------------------------------------------------------
443     // Get const MetabolicMuscleParameter from the MuscleMap using a string accessor.
444     const Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter*
445         getMetabolicParameters(const std::string& muscleName) const;
446 
447     // Get writable MetabolicMuscleParameter from the MuscleMap using a string accessor.
448     Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter*
449         updMetabolicParameters(const std::string& muscleName);
450 
451 public:
452 
453 
454 //=============================================================================
455 };  // END of class Umberger2010MuscleMetabolicsProbe
456 //=============================================================================
457 
458 //==============================================================================
459 //          Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter
460 //==============================================================================
461 
462 /**
463  * Documentation for this class has been provided with the documentation for the
464  * Umberger2010MuscleMetabolicsProbe class.
465  *
466  * @see Umberger2010MuscleMetabolicsProbe
467  */
468 
469 class OSIMSIMULATION_API
470     Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter
471     : public Object
472 {
473     OpenSim_DECLARE_CONCRETE_OBJECT(
474         Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter, Object);
475 public:
476 //==============================================================================
477 // PROPERTIES
478 //==============================================================================
479     OpenSim_DECLARE_PROPERTY(specific_tension, double,
480         "The specific tension of the muscle (Pascals (N/m^2)).");
481 
482     OpenSim_DECLARE_PROPERTY(density, double,
483         "The density of the muscle (kg/m^3).");
484 
485     OpenSim_DECLARE_PROPERTY(ratio_slow_twitch_fibers, double,
486         "Ratio of slow twitch fibers in the muscle (must be between 0 and 1).");
487 
488     OpenSim_DECLARE_PROPERTY(use_provided_muscle_mass, bool,
489         "An optional flag that allows the user to explicitly specify a muscle mass. "
490         "If set to true, the <provided_muscle_mass> property must be specified.");
491 
492     OpenSim_DECLARE_PROPERTY(provided_muscle_mass, double,
493         "The user specified muscle mass (kg).");
494 
495     //=============================================================================
496     // METHODS
497     //=============================================================================
498     //--------------------------------------------------------------------------
499     // Constructor(s)
500     //--------------------------------------------------------------------------
501     Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter();
502 
503     Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter(
504         const std::string& muscleName,
505         double ratio_slow_twitch_fibers,
506         double muscle_mass = SimTK::NaN);
507 
508     //--------------------------------------------------------------------------
509     // Muscle mass
510     //--------------------------------------------------------------------------
getMuscleMass()511     const double& getMuscleMass() const      { return _muscMass; }
512     void setMuscleMass();
513 
514     //--------------------------------------------------------------------------
515     // Internal muscle pointer
516     //--------------------------------------------------------------------------
getMuscle()517     const Muscle* getMuscle() const         { return _musc.get(); }
setMuscle(Muscle * m)518     void setMuscle(Muscle* m)               { _musc = m; }
519 
520 
521     //--------------------------------------------------------------------------
522     // Object interface
523     //--------------------------------------------------------------------------
524 private:
525     void setNull();
526     void constructProperties();
527 
528     //=============================================================================
529     // DATA
530     //=============================================================================
531     // These private member variables are set by the probe that owns this
532     // MetabolicMuscleParameter
533     SimTK::ReferencePtr<Muscle> _musc;  // Internal pointer to the muscle that corresponds
534                             // to these parameters.
535     double _muscMass;       // The mass of the muscle (depends on if
536                             // <use_provided_muscle_mass> is true or false.
537 
538 //=============================================================================
539 };  // END of class MetabolicMuscleParameter
540 //=============================================================================
541 
542 
543 
544 //==============================================================================
545 //                          MetabolicMuscleParameterSet
546 //==============================================================================
547 /**
548  * MetabolicMuscleParameterSet is an internal container class containing the set
549  * of MetabolicMuscleParameters for each muscle that is probed.
550  */
551 class OSIMSIMULATION_API
552     Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameterSet
553     : public Set<Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter>
554 {
555     OpenSim_DECLARE_CONCRETE_OBJECT(
556         Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameterSet,
557         Set<Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameter>);
558 
559 public:
Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameterSet()560     Umberger2010MuscleMetabolicsProbe_MetabolicMuscleParameterSet()
561     {  }
562 
563 //=============================================================================
564 };  // END of class MetabolicMuscleParameterSet
565 //=============================================================================
566 
567 
568 }; //namespace
569 //=============================================================================
570 //=============================================================================
571 
572 
573 #endif // #ifndef OPENSIM_UMBERGER2010_METABOLIC_POWER_PROBE_H_
574