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