1 #ifndef OPENSIM_MODEL_H_
2 #define OPENSIM_MODEL_H_
3 /* -------------------------------------------------------------------------- *
4  *                             OpenSim:  Model.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): Frank C. Anderson, Peter Loan, Ayman Habib, 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 // INCLUDES
27 #include <string>
28 #include <OpenSim/Simulation/osimSimulationDLL.h>
29 #include <OpenSim/Common/Units.h>
30 #include <OpenSim/Common/ModelDisplayHints.h>
31 #include <OpenSim/Simulation/AssemblySolver.h>
32 #include <OpenSim/Simulation/Model/AnalysisSet.h>
33 #include <OpenSim/Simulation/Model/BodySet.h>
34 #include <OpenSim/Simulation/Model/ComponentSet.h>
35 #include <OpenSim/Simulation/Model/ContactGeometrySet.h>
36 #include <OpenSim/Simulation/Model/ControllerSet.h>
37 #include <OpenSim/Simulation/Model/CoordinateSet.h>
38 #include <OpenSim/Simulation/Model/ForceSet.h>
39 #include <OpenSim/Simulation/Model/Ground.h>
40 #include <OpenSim/Simulation/Model/JointSet.h>
41 #include <OpenSim/Simulation/Model/MarkerSet.h>
42 #include <OpenSim/Simulation/Model/ModelComponent.h>
43 #include <OpenSim/Simulation/Model/ModelVisualPreferences.h>
44 #include <OpenSim/Simulation/Model/ModelVisualizer.h>
45 #include <OpenSim/Simulation/Model/ProbeSet.h>
46 #include <OpenSim/Simulation/SimbodyEngine/SimbodyEngine.h>
47 
48 #include "simbody/internal/Force_Gravity.h"
49 #include "simbody/internal/GeneralContactSubsystem.h"
50 
51 
52 namespace OpenSim {
53 
54 class Actuator;
55 class Analysis;
56 class Body;
57 class Constraint;
58 class ConstraintSet;
59 class ContactGeometry;
60 class Controller;
61 class CoordinateSet;
62 class Force;
63 class Frame;
64 class Muscle;
65 class Storage;
66 class ScaleSet;
67 
68 #ifdef SWIG
69     #ifdef OSIMSIMULATION_API
70         #undef OSIMSIMULATION_API
71         #define OSIMSIMULATION_API
72     #endif
73 #endif
74 
75 //==============================================================================
76 /// Model  Exceptions
77 //==============================================================================
78 class ModelHasNoSystem : public Exception {
79 public:
ModelHasNoSystem(const std::string & file,size_t line,const std::string & func,const std::string & modelName)80     ModelHasNoSystem(const std::string& file, size_t line,
81             const std::string& func,
82             const std::string& modelName) :
83                 OpenSim::Exception(file, line, func) {
84         std::string msg = "You must first call initSystem() on your Model";
85         if (!modelName.empty()) {
86             msg += " '" + modelName + "'";
87         }
88         msg += ".";
89         addMessage(msg);
90     }
91 };
92 
93 class PhysicalOffsetFramesFormLoop : public Exception {
94 public:
PhysicalOffsetFramesFormLoop(const std::string & file,size_t line,const std::string & func,const Object & obj,const std::string & frameName)95     PhysicalOffsetFramesFormLoop(const std::string& file,
96         size_t line,
97         const std::string& func,
98         const Object& obj,
99         const std::string& frameName) :
100         Exception(file, line, func, obj) {
101         std::string msg =
102             "PhysicalOffsetFrames are not permitted to form loops.\n'" +
103             frameName + "' already part of a branch of PhysicalOffsetFrames.";
104         addMessage(msg);
105     }
106 };
107 
108 class JointFramesHaveSameBaseFrame : public Exception {
109 public:
JointFramesHaveSameBaseFrame(const std::string & file,size_t line,const std::string & func,const std::string & thisName,const std::string & parentName,const std::string & childName,const std::string & baseName)110     JointFramesHaveSameBaseFrame(const std::string& file,
111         size_t line,
112         const std::string& func,
113         const std::string& thisName,
114         const std::string& parentName,
115         const std::string& childName,
116         const std::string& baseName) :
117         Exception(file, line, func) {
118         std::string msg = "Joint '" + thisName +
119             "' cannot connect parent frame '" +
120             parentName + "' to child frame '" + childName + "'.\n" +
121             "Parent and child frames have the same base frame '" +
122             baseName + "'.";
123         addMessage(msg);
124     }
125 };
126 
127 
128 
129 //==============================================================================
130 //                                  MODEL
131 //==============================================================================
132 /** A concrete class that specifies the interface to a musculoskeletal model.
133 You can read this in from an XML file or create it programmatically, and
134 modify it via the API.
135 
136 A Model contains ModelComponents, and is itself a ModelComponent so must
137 satisfy the ModelComponent interface, as well as the Object interface from
138 which ModelComponent derives. This allows a Model to allocate "global"
139 resources using ModelComponent resource-allocation facilities.
140 
141 Computation using a Model is done by creating a computational representation
142 of the Model, called a System (SimTK::System), using Simbody. Creation of the
143 System is initiated by a call to the Model's initSystem() method. The System and
144 related objects are maintained in a runtime section of the Model object. You
145 can also ask a Model to provide visualization using the setUseVisualizer()
146 method, in which case it will allocate and maintain a ModelVisualizer.
147 
148 @authors Frank Anderson, Peter Loan, Ayman Habib, Ajay Seth, Michael Sherman
149 @see ModelComponent, ModelVisualizer, SimTK::System
150 **/
151 
152 class OSIMSIMULATION_API Model  : public ModelComponent {
153 // Note, a concrete object typically employs the OpenSim_DECLARE_CONCRETE_OBJECT
154 // macro, but, for Model we do not want its clone() method to be auto-generated.
155 // Instead, we want to override and customize it and so we employ the subset of
156 // macros that OpenSim_DECLARE_CONCRETE_OBJECT calls, excluding one that
157 // implements clone() and getConcreteClassName(), which are implemented below.
158 OpenSim_OBJECT_ANY_DEFS(Model, ModelComponent);
159 OpenSim_OBJECT_NONTEMPLATE_DEFS(Model, ModelComponent);
160 
161 public:
162 //==============================================================================
163 // PROPERTIES
164 //==============================================================================
165     OpenSim_DECLARE_PROPERTY(credits, std::string,
166         "Credits (e.g., model author names) associated with the model.");
167 
168     OpenSim_DECLARE_PROPERTY(publications, std::string,
169         "Publications and references associated with the model.");
170 
171     OpenSim_DECLARE_PROPERTY(length_units, std::string,
172         "Units for all lengths.");
173 
174     OpenSim_DECLARE_PROPERTY(force_units, std::string,
175         "Units for all forces.");
176 
177     OpenSim_DECLARE_PROPERTY(assembly_accuracy, double,
178     "Specify how accurate the resulting configuration of a model assembly "
179     "should be. This translates to the number of significant digits in the "
180     "resulting coordinate values. Therefore, if you require initial conditions "
181     "accurate to four significant digits, use a minimum of 1e-4 as the accuracy."
182     "The default setting is 1e-9 as to satisfy the most stringent requirements by "
183     "default. NOTE: Failure for a model to satisfy the assembly accuracy often "
184     "indicates inconsistency in the constraints. For example, the feet are welded "
185     "at locations measured to five significant digits while the model lacks dofs "
186     "to change stance width, in which case it cannot achieve 1e-9 accuracy." );
187 
188     OpenSim_DECLARE_PROPERTY(gravity, SimTK::Vec3,
189         "Acceleration due to gravity, expressed in ground.");
190 
191     OpenSim_DECLARE_PROPERTY(ground, Ground,
192         "The model's ground reference frame.");
193 
194     OpenSim_DECLARE_UNNAMED_PROPERTY(BodySet,
195         "List of bodies that make up this model.");
196 
197     OpenSim_DECLARE_UNNAMED_PROPERTY(JointSet,
198         "List of joints that connect the bodies.");
199 
200     OpenSim_DECLARE_UNNAMED_PROPERTY(ConstraintSet,
201         "Constraints in the model.");
202 
203     OpenSim_DECLARE_UNNAMED_PROPERTY(MarkerSet,
204         "Markers in the model.");
205 
206     OpenSim_DECLARE_UNNAMED_PROPERTY(ForceSet,
207         "Forces in the model (includes Actuators).");
208 
209     OpenSim_DECLARE_UNNAMED_PROPERTY(ControllerSet,
210         "Controllers that provide the control inputs for Actuators.");
211 
212     OpenSim_DECLARE_UNNAMED_PROPERTY(ContactGeometrySet,
213         "Geometry to be used in contact forces.");
214 
215     OpenSim_DECLARE_UNNAMED_PROPERTY(ProbeSet,
216         "Probes in the model.");
217 
218     OpenSim_DECLARE_UNNAMED_PROPERTY(ComponentSet,
219         "Additional components in the model.");
220 
221     OpenSim_DECLARE_UNNAMED_PROPERTY(ModelVisualPreferences,
222         "Visual preferences for this model.");
223 
224 //==============================================================================
225 // OUTPUTS
226 //==============================================================================
227     OpenSim_DECLARE_OUTPUT(com_position, SimTK::Vec3,
228             calcMassCenterPosition, SimTK::Stage::Position);
229 
230     OpenSim_DECLARE_OUTPUT(com_velocity, SimTK::Vec3,
231             calcMassCenterVelocity, SimTK::Stage::Velocity);
232 
233     OpenSim_DECLARE_OUTPUT(com_acceleration, SimTK::Vec3,
234             calcMassCenterAcceleration, SimTK::Stage::Acceleration);
235 
236     OpenSim_DECLARE_OUTPUT(kinetic_energy, double,
237             calcKineticEnergy, SimTK::Stage::Position);
238 
239     OpenSim_DECLARE_OUTPUT(potential_energy, double,
240         calcPotentialEnergy, SimTK::Stage::Velocity);
241 
242 
243 //=============================================================================
244 // METHODS
245 //=============================================================================
246     //--------------------------------------------------------------------------
247     // CONSTRUCTION AND DESTRUCTION
248     //--------------------------------------------------------------------------
249 public:
250 
251     /** Default constructor creates a %Model containing only the Ground frame
252     and a set of default properties. */
253     Model();
254 
255     /** Constructor from an OpenSim XML model file.
256     NOTE: The Model is read in (deserialized) from the model file, which means
257     the properties of the Model and its components are filled in from values in
258     the file. In order to evaluate the validity of the properties (e.g. Inertia
259     tensors, availability of Mesh files, ...) and to identify properties as
260     subcomponents of the Model, one must invoke Model::finalizeFromProperties()
261     first. Model::initSystem() invokes finalizeFromProperties() on its way to
262     creating the System and initializing the State.
263 
264     @param filename     Name of a file containing an OpenSim model in XML
265                         format; suffix is typically ".osim".
266     **/
267     explicit Model(const std::string& filename) SWIG_DECLARE_EXCEPTION;
268 
269     /** Satisfy all connections (Sockets and Inputs) in the model, using this
270      * model as the root Component. This is a convenience form of
271      * Component::finalizeConnections() that uses this model as root.
272      */
finalizeConnections()273     void finalizeConnections() { finalizeConnections(*this); }
274     // Allow overloading.
275    using Component::finalizeConnections;
276 
277     /**
278      * Perform some set up functions that happen after the
279      * object has been deserialized. TODO: this method is
280      * not yet designed to be called after a model has been
281      * copied.
282      */
283     void setup() SWIG_DECLARE_EXCEPTION;
284 
285     /**
286      * Perform some clean up functions that are normally done
287      * from the destructor however this gives the GUI a way to
288      * proactively do the cleaning without waiting for garbage
289      * collection to do the actual cleanup.
290      */
291     void cleanup();
292 
293     /** Model clone() override that invokes finalizeFromProperties()
294         on a default copy constructed Model, prior to returning the Model. */
295     Model* clone() const override;
296 
getConcreteClassName()297     const std::string& getConcreteClassName() const override
298     {   return getClassName(); }
299 
300     //--------------------------------------------------------------------------
301     // VISUALIZATION
302     //--------------------------------------------------------------------------
303     /** @name                     Visualization
304     Methods in this group affect visualization of this Model, which may be
305     through the OpenSim GUI or through the use of a ModelVisualizer which can
306     provide limited run-time display and user interaction capability for an
307     OpenSim API-based program. If you enable visualization at the API level,
308     the %Model will create a ModelVisualizer that you can use to control
309     display and user interaction. In turn, the ModelVisualizer makes use of a
310     Simbody SimTK::Visualizer; for advanced features you can ask the
311     ModelVisualizer to give you direct access to the SimTK::Visualizer; consult
312     Simbody documentation for more details. **/
313     /**@{**/
314 
315     /** Get read only access to the ModelDisplayHints object stored with this
316     %Model. These should be checked whenever display geometry is being
317     generated. **/
getDisplayHints()318     const ModelDisplayHints& getDisplayHints() const {
319         return get_ModelVisualPreferences().get_ModelDisplayHints();}
320     /** Get writable access to the ModelDisplayHints object stored with this
321     %Model. The GUI or ModelVisualizer can update these as a result of user
322     requests, or an OpenSim API program can set them programmatically. **/
updDisplayHints()323     ModelDisplayHints& updDisplayHints() {
324         return upd_ModelVisualPreferences().upd_ModelDisplayHints(); }
325 
326     /** Request or suppress visualization of this %Model. This flag is checked
327     during initSystem() and if set causes the %Model to allocate a
328     ModelVisualizer that provides visualization and interaction with the %Model
329     as it is executing. The default is no visualization.
330     @see getModelVisualizer() **/
setUseVisualizer(bool visualize)331     void setUseVisualizer(bool visualize) {_useVisualizer=visualize;}
332     /** Return the current setting of the "use visualizer" flag, which will
333     take effect at the next call to initSystem() on this %Model. **/
getUseVisualizer()334     bool getUseVisualizer() const {return _useVisualizer;}
335 
336     /** Test whether a ModelVisualizer has been created for this Model. Even
337     if visualization has been requested there will be no visualizer present
338     until initSystem() has been successfully invoked. Use this method prior
339     to calling getVisualizer() or updVisualizer() to avoid an
340     unpleasant exception. **/
hasVisualizer()341     bool hasVisualizer() const {return _modelViz != nullptr;}
342 
343     /** Obtain read-only access to the ModelVisualizer. This will throw an
344     exception if visualization was not requested or initSystem() not yet
345     called.
346     @return A const reference to the allocated ModelVisualizer. **/
getVisualizer()347     const ModelVisualizer& getVisualizer() const {
348         if (!hasVisualizer())
349             throw Exception("Model::getVisualizer(): no visualizer present.");
350         return *_modelViz;
351     }
352     /** Obtain writable access to the ModelVisualizer. This will throw an
353     exception if visualization was not requested or initSystem() not yet
354     called. Writable access to the ModelVisualizer requires that you have
355     writable access to this containing Model.
356     @return A non-const reference to the allocated ModelVisualizer. **/
updVisualizer()357     ModelVisualizer& updVisualizer() {
358         if (!hasVisualizer())
359             throw Exception("Model::updVisualizer(): no visualizer present.");
360         return *_modelViz;
361     }
362     /**@}**/
363 
364     /** After the %Model and its components have been constructed, call this to
365     interconnect the components and then create the Simbody
366     MultibodySystem needed to represent the %Model computationally. The
367     extendConnectToModel() method of each contained ModelComponent will be invoked,
368     and then their addToSystem() methods are invoked.
369     The resulting MultibodySystem is maintained internally by the %Model. After
370     this call, you may obtain a writable reference to the System using
371     updMultibodySystem() which you can use to make any additions you want. Then
372     when the System is complete, call initializeState() to finalize it and
373     obtain an initial State. **/
374     void buildSystem();
375 
376     /** After buildSystem() has been called, and any additional modifications
377     to the Simbody MultibodySystem have been made, call this method to finalize
378     the MultibodySystem (by calling its realizeTopology() method), obtain an
379     initial state, and assemble it so that position constraints are
380     satisfied. The initStateFromProperties() method of each contained
381     ModelComponent will be invoked. A reference to the writable internally-
382     maintained model State is returned (note that this does not affect the
383     system's default state (which is part of the model and hence read only).
384     The model's state can be reset to the system's default state at any time
385     by re-executing initializeState(). **/
386     SimTK::State& initializeState();
387 
388 
389     /** Convenience method that invokes buildSystem() and then
390     initializeState(). This returns a reference to the writable internally-
391     maintained model State. Note that this does not affect the
392     system's default state (which is part of the model and hence read-only). **/
initSystem()393     SimTK::State& initSystem() SWIG_DECLARE_EXCEPTION {
394         buildSystem();
395         return initializeState();
396     }
397 
398 
399     /** Convenience method that returns a reference to the model's 'working'
400     state. This is just returning the reference that was returned by
401     initSystem() and initializeState() -- note that either of these methods
402     must be called prior to getWorkingState(), otherwise an empty state will
403     be returned. **/
404     const SimTK::State& getWorkingState() const;
405     SimTK::State& updWorkingState();
406 
407     /**
408      * This is called after the Model is fully created but before starting a simulation.
409      * It ONLY initializes the computational system used to simulate the model and
410      * addToSystem() has been called already. This method should only be used if
411      * if additional SimTK::System components are being added using the SimTK API
412      * and the programmer is certain that the model's system has been created.
413      */
initStateWithoutRecreatingSystem(SimTK::State & state)414     void initStateWithoutRecreatingSystem(SimTK::State& state) const { initStateFromProperties(state); };
415 
416     /**
417      * Mark the computational system as invalid.  This should be called whenever a property
418      * of the model is modified.  Once this has been called, no calculations can be done until
419      * initSystem() is called again.
420      */
421     void invalidateSystem();
422 
423     /** Check that the underlying computational system representing the model is valid.
424         That is, is the system ready for performing calculations. */
425     bool isValidSystem() const;
426 
427     /**
428      * Create a storage (statesStorage) that has same label order as model's states
429      * with values populated from originalStorage. Use the default state value if
430      * a state is unspecified in the originalStorage. If warnUnspecifiedStates is
431      * true then a warning is printed that includes the default value used for
432      * the state value unspecified in originalStorage. The input originalStorage
433      * must be in meters or radians for Coordinate values and their speeds
434      * (m/s, rad/s) otherwise an Exception is thrown.
435      */
436     void formStateStorage(const Storage& originalStorage,
437                           Storage& statesStorage,
438                           bool warnUnspecifiedStates = true) const;
439 
440     void formQStorage(const Storage& originalStorage, Storage& qStorage);
441 
442     /**
443      * Update the AssemblySolver to the latest coordinate locking/constraints
444      */
445     void updateAssemblyConditions(SimTK::State& s);
446     /**
447      * Find the kinematic state of the model that satisfies constraints and coordinate goals
448      * If assemble is being called due to a coordinate set value, provide the option
449      * to weight that coordinate value more heavily if specified.
450      */
451     void assemble(SimTK::State& state, const Coordinate *coord = NULL, double weight = 10);
452 
453 
454     /**
455      * Update the state of all Muscles so they are in equilibrium.
456      */
457     void equilibrateMuscles(SimTK::State& state);
458 
459     //--------------------------------------------------------------------------
460     /**@name       Access to the Simbody System and components
461 
462     Methods in this section provide advanced users access to the underlying
463     Simbody System and associated subcomponents that are constructed and
464     maintained by this %Model. Note that these are not available until after
465     initSystem() has been invoked on this %Model. Be very careful if you
466     call any of the upd() methods since modifying a System after the %Model
467     creates it can require reinitialization.
468     @see initStateWithoutRecreatingSystem() **/
469     /**@{**/
470 
471     /** Get read-only access to the internal Simbody MultibodySystem that was
472     created by this %Model at the last initSystem() call. **/
getMultibodySystem()473     const SimTK::MultibodySystem& getMultibodySystem() const {return getSystem(); }
474     /** (Advanced) Get writable access to the internal Simbody MultibodySystem
475     that was created by this %Model at the last initSystem() call. Be careful
476     if you make modifications to the System because that will invalidate
477     initialization already performed by the Model.
478     @see initStateWithoutRecreatingSystem() **/
updMultibodySystem()479     SimTK::MultibodySystem& updMultibodySystem() const {return updSystem(); }
480 
481     /** Get read-only access to the internal DefaultSystemSubsystem allocated
482     by this %Model's Simbody MultibodySystem. **/
getDefaultSubsystem()483     const SimTK::DefaultSystemSubsystem& getDefaultSubsystem() const
484     {   return getMultibodySystem().getDefaultSubsystem(); }
485     /** (Advanced) Get writable access to the internal DefaultSystemSubsystem
486     allocated by this %Model's Simbody MultibodySystem. **/
updDefaultSubsystem()487     SimTK::DefaultSystemSubsystem& updDefaultSubsystem()
488     {   return updMultibodySystem().updDefaultSubsystem(); }
489 
490     /** Get read-only access to the internal SimbodyMatterSubsystem allocated
491     by this %Model. **/
getMatterSubsystem()492     const SimTK::SimbodyMatterSubsystem& getMatterSubsystem() const
493     {   return _system->getMatterSubsystem(); }
494     /** (Advanced) Get writable access to the internal SimbodyMatterSubsystem
495     allocated by this %Model. **/
updMatterSubsystem()496     SimTK::SimbodyMatterSubsystem& updMatterSubsystem()
497     {   return _system->updMatterSubsystem(); }
498 
499     /** Get read-only access to the Simbody Force::Gravity element that was
500     allocated by this %Model. **/
getGravityForce()501     const SimTK::Force::Gravity& getGravityForce() const
502     {   return *_gravityForce; }
503     /** (Advanced) Get writable access to the Simbody Force::Gravity element
504     that was allocated by this %Model. **/
updGravityForce()505     SimTK::Force::Gravity& updGravityForce()
506     {   return *_gravityForce; }
507 
508     /** Get read-only access to the internal Simbody GeneralForceSubsystem
509     allocated by this %Model. **/
getForceSubsystem()510     const SimTK::GeneralForceSubsystem& getForceSubsystem() const
511     {   return *_forceSubsystem; }
512     /** (Advanced) Get writable access to the internal Simbody
513     GeneralForceSubsystem allocated by this %Model. **/
updForceSubsystem()514     SimTK::GeneralForceSubsystem& updForceSubsystem()
515     {   return *_forceSubsystem; }
516 
517     /**@}**/
518 
519     /**@name  Realize the Simbody System and State to Computational Stage
520     Methods in this section enable advanced and scripting users access to
521     realize the Simbody MultibodySystem and the provided state to a desired
522     computational (realization) Stage.
523     Note that these are not accessible until after initSystem() has been
524     invoked on this %Model. **/
525     /**@{**/
526 
527     /** Perform computations that depend only on time and earlier stages. **/
528     void realizeTime(const SimTK::State& state) const;
529     /** Perform computations that depend only on position-level state
530     variables and computations performed in earlier stages (including time). **/
531     void realizePosition(const SimTK::State& state) const;
532     /** Perform computations that depend only on velocity-level state
533     variables and computations performed in earlier stages (including position,
534     and time). **/
535     void realizeVelocity(const SimTK::State& state) const;
536     /** Perform computations (typically forces) that may depend on
537     dynamics-stage state variables, and on computations performed in earlier
538     stages (including velocity, position, and time), but not on other forces,
539     accelerations, constraint multipliers, or reaction forces. **/
540     void realizeDynamics(const SimTK::State& state) const;
541     /** Perform computations that may depend on applied forces. **/
542     void realizeAcceleration(const SimTK::State& state) const;
543     /** Perform computations that may depend on anything but are only used
544     for reporting and cannot affect subsequent simulation behavior. **/
545     void realizeReport(const SimTK::State& state) const;
546 
547     /**@}**/
548 
549     /** @name Adding components to the Model
550      * Model takes ownership of the ModelComponent and adds it to a specialized
551      * (typed) Set within the model. Model will maintain Components added using
552      * these methods in separate %Sets of the corresponding type and they will
553      * serialize as part of type specific %Sets. These sets can be useful for
554      * uniquely identifying components that share the same name, but are of
555      * different types since they  live in different %Sets. For example, using
556      * addBody(toesBody) and addJoint(toesJoint) will have unique paths:
557      * "/bodyset/toes" and "/jointset/toes", respectively, even when they have
558      * the same name, "toes".
559      * @note these are legacy methods and remain as a convenience alternative to
560      * using Component::addComponent().
561      * In contrast, components added using addComponent() are not stored in the
562      * model's %Sets but live in a flat components list (which is also serialized).
563      * Component provides access via getComponentList<%SpecificType> or
564      * getComponent<%SpecificType> to get any subcomponent, including those that
565      * are contained in Model's %Sets. In this case, either a Body or a Joint has
566      * the pathname "/toes" but both cannot share the same name and will throw
567      * SubcomponentsWithDuplicateName.
568      * Future versions of OpenSim are likely to deprecate the use of Sets and
569      * these methods, because they cannot support new Component types without
570      * modifying the API (for more add####() methods), whereas
571      * getComponentList<%SpecificType>() and getComponent<%SpecificType> will
572      * generalize: they do not have these limitations and are applicable for
573      * adding to any Component not just Model.
574      */
575     // @{
576     void addModelComponent(ModelComponent* adoptee);
577     void addBody(Body *adoptee);
578     void addJoint(Joint *adoptee);
579     void addConstraint(Constraint *adoptee);
580     void addForce(Force *adoptee);
581     void addProbe(Probe *adoptee);
582     void addContactGeometry(ContactGeometry *adoptee);
583     void addMarker(Marker *adoptee);
584     // @}
585 
586     /** remove passed in Probe from model **/
587     void removeProbe(Probe *probe);
588 
589     /**
590      * Get the XML file name used to construct the model.
591      *
592      * @return XML file name string.
593      */
getInputFileName()594     const std::string& getInputFileName() const { return _fileName; }
595 
596     /**
597      * %Set the XML file name used to construct the model.
598      *
599      * @param fileName The XML file name.
600      */
setInputFileName(const std::string & fileName)601     void setInputFileName(const std::string& fileName) { _fileName = fileName; }
602 
603     /**
604      * Get the credits (e.g., model author names) associated with the model.
605      *
606      * @return Credits string.
607      */
getCredits()608     const std::string& getCredits() const { return get_credits(); }
609 
610     /**
611      * %Set the credits (e.g., model author names) associated with the model.
612      *
613      * @param aCredits The string of credits.
614      */
setAuthors(const std::string & aCredits)615     void setAuthors(const std::string& aCredits) { upd_credits() = aCredits; }
616 
617     /**
618      * Get the publications associated with the model.
619      *
620      * @return Publications string.
621      */
getPublications()622     const std::string& getPublications() const { return get_publications(); }
623 
624     /**
625      * %Set the publications associated with the model.
626      *
627      * @param aPublications The string of publications.
628      */
setPublications(const std::string & aPublications)629     void setPublications(const std::string& aPublications) { upd_publications() = aPublications; }
630 
631     /**
632      * Get the length units associated with the model.
633      *
634      * @return Length units.
635      */
getLengthUnits()636     const Units& getLengthUnits() const { return _lengthUnits; }
637 
638     /**
639      * Get the force units associated with the model.
640      *
641      * @return Force units
642      */
getForceUnits()643     const Units& getForceUnits() const { return _forceUnits; }
644 
645     /**
646      * Get the gravity vector in the global frame.
647      *
648      * @return The XYZ gravity vector in the global frame.
649      */
650     SimTK::Vec3 getGravity() const;
651 
652     /**
653      * %Set the gravity vector in the global frame.
654      *
655      * @param aGrav The XYZ gravity vector
656      * @return Whether or not the gravity vector was successfully set.
657      */
658     bool setGravity(const SimTK::Vec3& aGrav);
659 
660     /**
661      * Get the number of markers in the model.
662      * @return Number of markers.
663      */
664     int getNumMarkers() const;
665 
666     /**
667      * Get the number of ContactGeometries in the model.
668      * @return Number of ContactGeometries.
669      */
670     int getNumContactGeometries() const;
671 
672     /**
673      * Get the total number of bodies in the model.
674      * @return Number of bodies.
675      */
676     int getNumBodies() const;
677 
678     /**
679     * Get the total number of joints in the model.
680     * @return Number of joints.
681     */
682     int getNumJoints() const;
683 
684     /**
685      * Get the total number of coordinates in the model.
686      * @return Number of coordinates.
687      */
688     int getNumCoordinates() const;
689 
690     /**
691     * Get the total number of speeds in the model.
692     * @return Number of speeds.
693     */
694     int getNumSpeeds() const;
695 
696     /**
697     * Get the total number of constraints in the model.
698     * @return Number of constraints.
699     */
700     int getNumConstraints() const;
701 
702     /**
703      * Get the total number of probes in the model.
704      * @return Number of probes.
705      */
706     int getNumProbes() const;
707 
708     /**
709      * Get the subset of Forces in the model which are actuators
710      * @return The set of Actuators
711      */
712     const Set<Actuator>& getActuators() const;
713     Set<Actuator>& updActuators();
714 
715     /**
716      * Get the subset of Forces in the model which are muscles
717      * @return The set of Muscles
718      */
719     const Set<Muscle>& getMuscles() const;
720     Set<Muscle>& updMuscles();
721 
getForceSet()722     const ForceSet& getForceSet() const { return get_ForceSet(); };
updForceSet()723     ForceSet& updForceSet() { return upd_ForceSet(); };
724 
725     /**
726      * Get the subset of Probes in the model
727      * @return The set of Probes
728      */
getProbeSet()729     const ProbeSet& getProbeSet() const { return get_ProbeSet(); };
updProbeSet()730     ProbeSet& updProbeSet() { return upd_ProbeSet(); };
731 
732     /**
733      * Get the subst of misc ModelComponents in the model
734      * @return The set of misc ModelComponents
735      */
getMiscModelComponentSet()736     const ComponentSet& getMiscModelComponentSet() const
737     {   return get_ComponentSet(); };
updMiscModelComponentSet()738     ComponentSet& updMiscModelComponentSet()
739     {   return upd_ComponentSet(); };
740 
741     /**
742      * Get the number of analyses in the model.
743      * @return The number of analyses.
744      */
745     int getNumAnalyses() const;
746 
747     /**
748      * Get the number of controls for this the model.
749      * Only valid once underlying system for the model has been created.
750      * Throws an exception if called before Model::initSystem()
751      * @return number of controls corresponding to all the actuators in the model
752      */
753     int getNumControls() const;
754 
755     /** Writable access to the default values for controls. These values are used for
756         control value during a simulation unless updated, for example, by a Controller */
updDefaultControls()757     SimTK::Vector& updDefaultControls() const { return _defaultControls; }
setDefaultControls(const SimTK::Vector & controls)758     void setDefaultControls(const SimTK::Vector& controls) const
759     {   _defaultControls = controls; }
getDefaultControls()760     const SimTK::Vector& getDefaultControls() const { return _defaultControls; };
761 
762     /**
763      * Update the controls for this the model at a given state.
764      * Only callable once underlying system for the model has been created.
765      * Throws an exception if called before Model::initSystem()
766      * This call invalidates the dynamics of the model and invalidates the
767      * value of the controls until they are marked as valid when the update
768      * is completed (@see markControlsAsValid)
769      * @param[in]   s         System state at which to apply the controls
770      * @return      writable controls Vector
771      */
772     SimTK::Vector& updControls(const SimTK::State& s) const;
773 
774     /**
775      * Mark controls as valid after an update at a given state.
776      * Indicates that controls are valid for use at the dynamics stage.
777      * If the stage is Velocity or lower the controls will remain invalid.
778      * @param[in]   s         System state in which the controls are updated
779      */
780     void markControlsAsValid(const SimTK::State& s) const;
781 
782     /**
783      * Alternatively, set the controls on the model at a given state.
784      * Note, this method will invalidate the dynamics of the model,
785      * but will mark the controls as valid. (E.g. controllers will not be invoked)
786      * @param[in]   s         System state at which to apply the controls
787      * @param[in]   controls  The complete Vector of controls to be applied
788      */
789     void setControls(const SimTK::State& s, const SimTK::Vector& controls) const;
790 
791     /** Const access to controls does not invalidate dynamics */
792     const SimTK::Vector& getControls(const SimTK::State &s) const;
793 
794     /** Compute the controls for the model.
795     Calls down to the Controllers to make their contributions to the controls.
796 
797     @param[in]   state       System state from which Controllers should draw
798                              when computing their control outputs.
799     @param[out]  controls    The complete vector of controls into which
800                              individual controller contributions should be
801                              added. **/
802     void computeControls(const SimTK::State& state, SimTK::Vector& controls) const;
803 
804     /**
805      * Get a flag indicating if the model needs controls to operate its actuators
806      */
807     bool isControlled() const;
808     void storeControls( const SimTK::State& s, int step );
809     void printControlStorage(const std::string& fileName ) const;
810     TimeSeriesTable getControlsTable() const;
811     const ControllerSet& getControllerSet() const;
812     ControllerSet& updControllerSet();
813     bool getAllControllersEnabled() const;
814     void setAllControllersEnabled( bool enabled );
815 
816     void applyDefaultConfiguration(SimTK::State& s );
817 
818 
819     /**
820      * Get the model's dynamics engine
821      *
822      * @return Reference to the Simbody dynamics engine
823      */
getSimbodyEngine()824     const SimbodyEngine& getSimbodyEngine() const { return _simbodyEngine; }
updSimbodyEngine()825     SimbodyEngine& updSimbodyEngine() { return _simbodyEngine; }
826 
827     //--------------------------------------------------------------------------
828     // Subsystem computations
829     //--------------------------------------------------------------------------
830     void computeStateVariableDerivatives(const SimTK::State &s) const override;
831     double getTotalMass(const SimTK::State &s) const;
832     SimTK::Inertia getInertiaAboutMassCenter(const SimTK::State &s) const;
833     SimTK::Vec3 calcMassCenterPosition(const SimTK::State &s) const;
834     SimTK::Vec3 calcMassCenterVelocity(const SimTK::State &s) const;
835     SimTK::Vec3 calcMassCenterAcceleration(const SimTK::State &s) const;
836     /** return the total Kinetic Energy for the underlying system.*/
calcKineticEnergy(const SimTK::State & s)837     double calcKineticEnergy(const SimTK::State &s) const {
838         return getMultibodySystem().calcKineticEnergy(s);
839     }
840     /** return the total Potential Energy for the underlying system.*/
calcPotentialEnergy(const SimTK::State & s)841     double calcPotentialEnergy(const SimTK::State &s) const {
842         return getMultibodySystem().calcPotentialEnergy(s);
843     }
844 
845     int getNumMuscleStates() const;
846     int getNumProbeStates() const;
847 
848     //--------------------------------------------------------------------------
849     // SETS
850     //--------------------------------------------------------------------------
851     //
852     //--------------------------------------------------------------------------
853     // COORDINATES
854     //--------------------------------------------------------------------------
updCoordinateSet()855     CoordinateSet& updCoordinateSet() {
856        return _coordinateSet;
857     }
getCoordinateSet()858     const CoordinateSet& getCoordinateSet() const {
859        return _coordinateSet;
860     }
861 
862     /** Obtain a list of Model's Coordinates in the order they appear in the
863         MultibodySystem after Model::initSystem() has been called.
864         Coordinates in the CoordinateSet do not have a predefined order. In
865         some instances it is helpful to get the coordinates in order of
866         generalized coordinates in the Multibody Tree as defined in the
867         underlying MultibodySystem. For example, computing the generalized
868         forces from the System, yields a vector of generalized forces
869         in order of the Multibody Tree and now that can be attributed to
870         corresponding generalized Coordinates of the Model.
871         Throws if the MultibodySystem is not valid. */
872     std::vector<SimTK::ReferencePtr<const Coordinate>>
873         getCoordinatesInMultibodyTreeOrder() const;
874 
875     /** Get a warning message if any Coordinates have a MotionType that is NOT
876         consistent with its previous user-specified value that existed in
877         Model files prior to OpenSim 4.0 */
878     std::string getWarningMesssageForMotionTypeInconsistency() const;
879 
updBodySet()880     BodySet& updBodySet() { return upd_BodySet(); }
getBodySet()881     const BodySet& getBodySet() const { return get_BodySet(); }
882 
883     JointSet& updJointSet();
884     const JointSet& getJointSet() const;
885 
updAnalysisSet()886     AnalysisSet& updAnalysisSet() {return _analysisSet; }
getAnalysisSet()887     const AnalysisSet& getAnalysisSet() const {return _analysisSet; }
888 
updContactGeometrySet()889     ContactGeometrySet& updContactGeometrySet() { return upd_ContactGeometrySet(); }
getContactGeometrySet()890     const ContactGeometrySet& getContactGeometrySet() const { return get_ContactGeometrySet(); }
891 
892     /** Get a const reference to the Ground reference frame */
893     const Ground& getGround() const;
894     /** Get a writable reference to the Ground reference frame */
895     Ground& updGround();
896 
897     //--------------------------------------------------------------------------
898     // CONSTRAINTS
899     //--------------------------------------------------------------------------
updConstraintSet()900     ConstraintSet& updConstraintSet() { return upd_ConstraintSet(); }
getConstraintSet()901     const ConstraintSet& getConstraintSet() const { return get_ConstraintSet(); }
902 
903     //--------------------------------------------------------------------------
904     // MARKERS
905     //--------------------------------------------------------------------------
updMarkerSet()906     MarkerSet& updMarkerSet() { return upd_MarkerSet(); }
getMarkerSet()907     const MarkerSet& getMarkerSet() const { return get_MarkerSet(); }
908 
909     void writeMarkerFile(const std::string& aFileName);
910 
911     /**
912     * Update the markers in the model by appending the ones in the
913     * passed-in marker set. If the marker of the same name exists
914     * in the model, then replace it.
915     *
916     * @param newMarkerSet the set of markers used to update the model's set.
917     */
918     void updateMarkerSet(MarkerSet& newMarkerSet);
919     int deleteUnusedMarkers(const Array<std::string>& aMarkerNames);
920 
921     /**
922      * Add an Analysis to the %Model.
923      *
924      * @param adoptee pointer to the Analysis to add
925      */
926     void addAnalysis(Analysis *adoptee);
927     /** Add a Controller to the %Model. **/
928     void addController(Controller *adoptee);
929 
930     /**
931      * Remove an Analysis from the %Model.
932      *
933      * @param analysis  Pointer to the analysis to remove.
934      * @param deleteIt  Whether the removed object should be deleted.
935      */
936     void removeAnalysis(Analysis* analysis, bool deleteIt=true);
937     /** Remove a Controller from the %Model. **/
938     void removeController(Controller *aController);
939 
940     //--------------------------------------------------------------------------
941     // DERIVATIVES
942     //--------------------------------------------------------------------------
943     //--------------------------------------------------------------------------
944     // OPERATIONS
945     //--------------------------------------------------------------------------
946 
947     /**
948      * Scale the model.
949      *
950      * @param state      State containing parameter values that might be
951      *                   modified here.
952      * @param scaleSet   The set of XYZ scale factors for the bodies.
953      * @param preserveMassDist
954      *                   Whether the masses of the bodies should be scaled by
955      *                   the scale factors. If `false`, body masses will be
956      *                   adjusted only if `finalMass` has been specified; if
957      *                   `true`, body masses will be scaled by the product of
958      *                   the body's scale factors (and then a second time if
959      *                   `finalMass` has been specified). Inertias are always
960      *                   updated to reflect changes in body dimensions.
961      * @param finalMass  The total mass that the scaled model should have.
962      * @returns          Whether or not scaling was successful.
963      */
964     bool scale(SimTK::State&    state,
965                const ScaleSet&  scaleSet,
966                bool             preserveMassDist,
967                double           finalMass = -1.0);
968 
969     //--------------------------------------------------------------------------
970     // PRINT
971     //--------------------------------------------------------------------------
972 
973     /**
974      * Print some basic information about the model.
975      *
976      * @param aOStream Output stream.
977      */
978     void printBasicInfo(std::ostream& aOStream = std::cout) const;
979 
980     /**
981      * Print detailed information about the model.
982      *
983      * @param s        the system State.
984      * @param aOStream Output stream.
985      */
986     void printDetailedInfo(const SimTK::State& s,
987                            std::ostream& aOStream = std::cout) const;
988 
989     /**
990      * Model relinquishes ownership of all components such as: Bodies, Constraints, Forces,
991      * ContactGeometry and so on. That means the freeing of the memory of these objects is up
992      * to the caller. This only affects components stored in the Model's Sets,
993      * and does not affect those added via Component::addComponent().
994      */
995     void disownAllComponents();
996     /**
997      * Convenience function to turn on/off overriding the force for all actuators
998      */
999     void overrideAllActuators( SimTK::State& s, bool flag);
1000 
1001     /**
1002      * Get a log of errors/warnings encountered when loading/constructing the model
1003      */
getValidationLog()1004     const std::string& getValidationLog() const { return _validationLog; };
1005     /** Append to the Model's validation log without affecting is current contents */
1006     void appendToValidationLog(const std::string& note);
clearValidationLog()1007     void clearValidationLog() { _validationLog = ""; };
1008 
1009     /**
1010      * Utility to get a reference to an Object based on its name and type
1011      * throws an exception if the object was not found.
1012      * names are case sensitive
1013      * @param typeString the type of object being looked up (Body, Force, Constraint, Coordinate, Joint, Marker, Controller, Frame)
1014      * @param nameString the name of the object being looked up
1015      * @return reference to the object if found or throws an exception.
1016      */
1017     const Object& getObjectByTypeAndName(const std::string& typeString, const std::string& nameString) SWIG_DECLARE_EXCEPTION;
1018 
1019     //--------------------------------------------------------------------------
1020     /**@name            Implementation of Object interface
1021 
1022     These methods are %Model's implementation of virtual methods defined in
1023     the Object class from which %Model derives (indirectly through
1024     ModelComponent). **/
1025     /**@{**/
1026 
1027     /** Destructor. */
~Model()1028     ~Model() override {
1029         // Must ensure the System is deleted after the subsystem handles,
1030         // otherwise the subsystem handles are "dangling."
1031         _contactSubsystem.reset();
1032         _forceSubsystem.reset();
1033         _gravityForce.reset();
1034         _matter.reset();
1035     }
1036 
1037     /** Override of the default implementation to account for versioning. */
1038     void updateFromXMLNode(SimTK::Xml::Element& aNode,
1039                            int versionNumber = -1) override;
1040     /**@}**/
1041 
1042     //--------------------------------------------------------------------------
1043     /**@name         Implementation of Component interface
1044 
1045     These methods are %Model's implementation of virtual methods defined in
1046     the Component class from which %Model derives. **/
1047     /**@{**/
1048     void extendFinalizeFromProperties() override;
1049 
1050     void extendConnectToModel(Model& model)  override;
1051     void extendAddToSystem(SimTK::MultibodySystem& system) const override;
1052     void extendInitStateFromProperties(SimTK::State& state) const override;
1053     /**@}**/
1054 
1055     /**
1056      * Given a State, set all default values for this Model to match those
1057      * found in the State.
1058      */
1059     void extendSetPropertiesFromState(const SimTK::State& state) override;
1060 
1061     //--------------------------------------------------------------------------
1062     /**@name         Implementation of ModelComponent interface
1063 
1064     These methods are %Model's implementation of virtual methods defined in
1065     the ModelComponent class from which %Model derives. **/
1066     /**@{**/
1067     void generateDecorations
1068        (bool                                        fixed,
1069         const ModelDisplayHints&                    hints,
1070         const SimTK::State&                         state,
1071         SimTK::Array_<SimTK::DecorativeGeometry>&   appendToThis) const
1072                                                                 override;
1073     /**@}**/
1074 
1075     //--------------------------------------------------------------------------
1076 
1077 private:
1078     // %Set the values of all data members to an appropriate "null" value.
1079     void setNull();
1080 
1081     // Construct the properties of a Model.
1082     void constructProperties();
1083     void setDefaultProperties();
1084 
1085     // Utility to build a connected graph (tree) of the multibody system
1086     void createMultibodyTree();
1087 
1088     void createMultibodySystem();
1089 
1090     void createAssemblySolver(const SimTK::State& s);
1091 
1092     // To provide access to private _modelComponents member.
1093     friend class Component;
1094 
1095 //==============================================================================
1096 // DATA MEMBERS
1097 //==============================================================================
1098 private:
1099     //--------------------------------------------------------------------------
1100     //                              MODELING
1101     //--------------------------------------------------------------------------
1102     // These data members are concerned with the structure and contents of the
1103     // model and must be given values prior to initiating computation.
1104 
1105     // Name of file from which the model was constructed, if any, otherwise
1106     // set to "Unassigned".
1107     std::string _fileName;
1108 
1109     // Private place to save some deserialization/error checking info in case
1110     // needed later.
1111     std::string _validationLog;
1112 
1113 
1114     //Units for length
1115     Units _lengthUnits;
1116     //Units for forces
1117     Units _forceUnits;
1118 
1119     // Other Model data structures that are derived from the properties
1120     // or added programmatically.
1121 
1122     // Set containing the analyses in this model.
1123     AnalysisSet     _analysisSet;
1124 
1125     // Set containing the generalized coordinates in this model.
1126     CoordinateSet   _coordinateSet;
1127 
1128     SimTK::MultibodyGraphMaker _multibodyTree;
1129 
1130     // This object just provides an alternate interface to the computational
1131     // SimTK::MultibodySystem. It is constructed just knowing the Model and
1132     // then forwards requests through the Model at runtime.
1133     SimbodyEngine _simbodyEngine;
1134 
1135     // This is the internal 'writable' state of the model.
1136     // _workingState will be set to the system default state when
1137     // initializeState() or initSystem() is called.
1138     SimTK::State _workingState;
1139 
1140 
1141     //--------------------------------------------------------------------------
1142     //                              RUN TIME
1143     //--------------------------------------------------------------------------
1144 
1145     // If this flag is set when initSystem() is called, we'll allocate
1146     // a ModelVisualizer for display.
1147     bool _useVisualizer;
1148 
1149     // Global flag used to disable all Controllers.
1150     bool _allControllersEnabled;
1151 
1152 
1153     //                      SIMBODY MULTIBODY SYSTEM
1154     // We dynamically allocate these because they are not available at
1155     // construction.
1156     // The model owns the MultibodySystem, but the
1157     // subsystems and force elements are owned by the MultibodySystem. However,
1158     // that memory management happens through Simbody's handles. It's fine for
1159     // us to manage the heap memory for the handles.
1160 
1161     SimTK::ResetOnCopy<std::unique_ptr<SimTK::SimbodyMatterSubsystem>>
1162         _matter;
1163     SimTK::ResetOnCopy<std::unique_ptr<SimTK::Force::Gravity>>
1164         _gravityForce;
1165     SimTK::ResetOnCopy<std::unique_ptr<SimTK::GeneralForceSubsystem>>
1166         _forceSubsystem;
1167     SimTK::ResetOnCopy<std::unique_ptr<SimTK::GeneralContactSubsystem>>
1168         _contactSubsystem;
1169 
1170     // We place this after the subsystems so that during copy construction and
1171     // copy assignment, the subsystem handles are copied first. If the system
1172     // is copied first, the handles end up "dangling."
1173     SimTK::ResetOnCopy<std::unique_ptr<SimTK::MultibodySystem>> _system;
1174 
1175     // System-dependent objects.
1176 
1177     // Assembly solver used for satisfying constraints and other configuration
1178     // goals. This object is owned by the Model, and should not be copied
1179     // when the Model is copied.
1180     SimTK::ResetOnCopy<std::unique_ptr<AssemblySolver>> _assemblySolver;
1181 
1182     // Model controls as a shared pool (Vector) of individual Actuator controls
1183     SimTK::MeasureIndex   _modelControlsIndex;
1184     // Default values pooled from Actuators upon system creation.
1185     mutable SimTK::Vector _defaultControls;
1186 
1187 
1188     //                          VISUALIZATION
1189     // Anyone generating display geometry from this Model should consult this
1190     // object to pick up user preferences. Its contents may be modified by the
1191     // current user interface (GUI or ModelVisualizer) or programmatically.
1192     ModelDisplayHints   _displayHints;
1193 
1194     // If visualization has been requested at the API level, we'll allocate
1195     // a ModelVisualizer. The Model owns this object, but it should not be
1196     // copied.
1197     SimTK::ResetOnCopy<std::unique_ptr<ModelVisualizer>> _modelViz;
1198 
1199 //==============================================================================
1200 };  // END of class Model
1201 //==============================================================================
1202 
1203 
1204 //==============================================================================
1205 } // end of namespace OpenSim
1206 
1207 #endif // OPENSIM_MODEL_H_
1208 
1209