1 #ifndef OPENSIM_COMPONENT_H_
2 #define OPENSIM_COMPONENT_H_
3 /* -------------------------------------------------------------------------- *
4  *                             OpenSim: Component.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): 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 /** @file
27  * This file defines the abstract Component class, which is used to add
28  * computational components to the underlying SimTK::System (MultibodySystem).
29  * It specifies the interface that components must satisfy in order to be part
30  * of the system and provides a series of helper methods for adding variables
31  * (state, discrete, cache, ...) to the underlying system. As such,
32  * Component handles all of the bookkeeping for variable indices and
33  * provides convenience access via variable names. Furthermore, a component
34  * embodies constructs of inputs, outputs and connections that are useful in
35  * composing computational systems.
36  *
37  * A component may contain one or more underlying Simbody multibody system
38  * elements (MobilizedBody, Constraint, Force, or Measure) which are part of
39  * a SimTK::Subsystem. A SimTK::Subsystem is where new variables are
40  * allocated. A Component, by default, uses the System's DefaultSubsystem.
41  * for allocating new variables.
42  */
43 
44 // INCLUDES
45 #include <OpenSim/Common/osimCommonDLL.h>
46 #include "OpenSim/Common/Object.h"
47 #include "OpenSim/Common/ComponentSocket.h"
48 #include "OpenSim/Common/ComponentOutput.h"
49 #include "OpenSim/Common/Array.h"
50 #include "ComponentList.h"
51 #include "ComponentPath.h"
52 #include <functional>
53 
54 #include "simbody/internal/MultibodySystem.h"
55 
56 namespace OpenSim {
57 
58 class Model;
59 class ModelDisplayHints;
60 
61 //==============================================================================
62 /// Component Exceptions
63 //==============================================================================
64 class ComponentHasNoName : public Exception {
65 public:
ComponentHasNoName(const std::string & file,size_t line,const std::string & func,const std::string & componentConcreteClassName)66     ComponentHasNoName(const std::string& file,
67         size_t line,
68         const std::string& func,
69         const std::string& componentConcreteClassName) :
70         Exception(file, line, func) {
71         std::string msg = componentConcreteClassName;
72         msg += " was constructed with no name.\n";
73         msg += "Please assign a valid name and try again.";
74         addMessage(msg);
75     }
76 };
77 
78 class InvalidComponentName : public Exception {
79 public:
InvalidComponentName(const std::string & file,size_t line,const std::string & func,const std::string & thisName,const std::string & invalidChars,const std::string & componentConcreteClassName)80     InvalidComponentName(const std::string& file,
81         size_t line,
82         const std::string& func,
83         const std::string& thisName,
84         const std::string& invalidChars,
85         const std::string& componentConcreteClassName) :
86         Exception(file, line, func) {
87         std::string msg = "Component '" + thisName + "' of type " +
88             componentConcreteClassName + " contains invalid characters of: '" +
89             invalidChars + "'.";
90         addMessage(msg);
91     }
92 };
93 
94 class ComponentNotFoundOnSpecifiedPath : public ComponentNotFound {
95 public:
ComponentNotFoundOnSpecifiedPath(const std::string & file,size_t line,const std::string & func,const std::string & toFindName,const std::string & toFindClassName,const std::string & thisName)96     ComponentNotFoundOnSpecifiedPath(const std::string& file,
97         size_t line,
98         const std::string& func,
99         const std::string& toFindName,
100         const std::string& toFindClassName,
101         const std::string& thisName) :
102         ComponentNotFound(file, line, func) {
103         std::string msg = "Component '" + thisName;
104         msg += "' could not find '" + toFindName;
105         msg += "' of type " + toFindClassName + ". ";
106         msg += "Make sure a component exists at this path and that it is of ";
107         msg += "the correct type.";
108         addMessage(msg);
109     }
110 };
111 
112 class ComponentIsAnOrphan : public Exception {
113 public:
ComponentIsAnOrphan(const std::string & file,size_t line,const std::string & func,const std::string & thisName,const std::string & componentConcreteClassName)114     ComponentIsAnOrphan(const std::string& file,
115         size_t line,
116         const std::string& func,
117         const std::string& thisName,
118         const std::string& componentConcreteClassName) :
119         Exception(file, line, func) {
120         std::string msg = "Component '" + thisName + "' of type " +
121             componentConcreteClassName + " has no owner and is not the root.\n" +
122             "Verify that finalizeFromProperties() has been invoked on the " +
123             "root Component or that this Component is not a clone, which has " +
124             "not been added to another Component.";
125         addMessage(msg);
126     }
127 };
128 
129 class SubcomponentsWithDuplicateName : public Exception {
130 public:
SubcomponentsWithDuplicateName(const std::string & file,size_t line,const std::string & func,const std::string & thisName,const std::string & duplicateName)131     SubcomponentsWithDuplicateName(const std::string& file,
132         size_t line,
133         const std::string& func,
134         const std::string& thisName,
135         const std::string& duplicateName) :
136         Exception(file, line, func) {
137         std::string msg = "Component '" + thisName + "' has subcomponents " +
138             "with duplicate name '" + duplicateName + "'. "
139             "Please supply unique names for immediate subcomponents.";
140         addMessage(msg);
141     }
142 };
143 
144 class ComponentIsRootWithNoSubcomponents : public Exception {
145 public:
ComponentIsRootWithNoSubcomponents(const std::string & file,size_t line,const std::string & func,const std::string & thisName,const std::string & componentConcreteClassName)146     ComponentIsRootWithNoSubcomponents(const std::string& file,
147         size_t line,
148         const std::string& func,
149         const std::string& thisName,
150         const std::string& componentConcreteClassName) :
151         Exception(file, line, func) {
152         std::string msg = "Component '" + thisName + "' of type " +
153             componentConcreteClassName + " is the root but has no " +
154             "subcomponents listed.\n" +
155             "Verify that finalizeFromProperties() was called on this "
156             "Component to identify its subcomponents.";
157         addMessage(msg);
158     }
159 };
160 
161 class ComponentAlreadyPartOfOwnershipTree : public Exception {
162 public:
ComponentAlreadyPartOfOwnershipTree(const std::string & file,size_t line,const std::string & func,const std::string & compName,const std::string & thisName)163     ComponentAlreadyPartOfOwnershipTree(const std::string& file,
164                                         size_t line,
165                                         const std::string& func,
166                                         const std::string& compName,
167                                         const std::string& thisName) :
168         Exception(file, line, func) {
169         std::string msg = "Component '" + compName;
170         msg += "' already owned by tree to which '" + thisName;
171         msg += "' belongs. Clone the component to adopt a fresh copy.";
172         addMessage(msg);
173     }
174 };
175 
176 class ComponentHasNoSystem : public Exception {
177 public:
ComponentHasNoSystem(const std::string & file,size_t line,const std::string & func,const Object & obj)178     ComponentHasNoSystem(const std::string& file,
179                          size_t line,
180                          const std::string& func,
181                          const Object& obj) :
182         Exception(file, line, func, obj) {
183         std::string msg = "Component has no underlying System.\n";
184         msg += "You must call initSystem() on the top-level Component ";
185         msg += "(i.e. Model) first.";
186         addMessage(msg);
187     }
188 };
189 
190 class SocketNotFound : public Exception {
191 public:
SocketNotFound(const std::string & file,size_t line,const std::string & func,const Object & obj,const std::string & socketName)192     SocketNotFound(const std::string& file,
193                    size_t line,
194                    const std::string& func,
195                    const Object& obj,
196                    const std::string& socketName) :
197         Exception(file, line, func, obj) {
198         std::string msg = "no Socket '" + socketName;
199         msg += "' found for this Component.";
200         addMessage(msg);
201     }
202 };
203 
204 class InputNotFound : public Exception {
205 public:
InputNotFound(const std::string & file,size_t line,const std::string & func,const Object & obj,const std::string & inputName)206     InputNotFound(const std::string& file,
207                   size_t line,
208                   const std::string& func,
209                   const Object& obj,
210                   const std::string& inputName) :
211         Exception(file, line, func, obj) {
212         std::string msg = "no Input '" + inputName;
213         msg += "' found for this Component.";
214         addMessage(msg);
215     }
216 };
217 
218 class OutputNotFound : public Exception {
219 public:
OutputNotFound(const std::string & file,size_t line,const std::string & func,const Object & obj,const std::string & outputName)220     OutputNotFound(const std::string& file,
221                    size_t line,
222                    const std::string& func,
223                    const Object& obj,
224                    const std::string& outputName) :
225         Exception(file, line, func, obj) {
226         std::string msg = "no Output '" + outputName;
227         msg += "' found for this Component.";
228         addMessage(msg);
229     }
230 };
231 
232 //==============================================================================
233 //                            OPENSIM COMPONENT
234 //==============================================================================
235 /**
236  * The abstract Component class defines the interface used to add computational
237  * elements to the underlying SimTK::System (MultibodySystem). It specifies
238  * the interface that components must satisfy in order to be part of the system
239  * and provides a series of helper methods for adding variables
240  * (state, discrete, cache, ...) to the underlying system. As such, Component
241  * handles all of the bookkeeping of system indices and provides convenience
242  * access to variable values (incl. derivatives) via their names as strings.
243  *
244  * ### System and State
245  *
246  * The MultibodySystem and its State are defined by Simbody (ref ...). Briefly,
247  * a System represents the mathematical equations that specify the behavior
248  * of a computational model. The State is a collection of all the variables
249  * that uniquely define the unknowns in the system equations. Consider a single
250  * differential equation as a system, while a single set of variable values that
251  * satisfy the equation is a state of that system. These could be values for
252  * joint coordinates, their speeds, as well other variables that govern
253  * the system dynamics (e.g. muscle activation and fiber-length variables
254  * that dictate muscle force). These variables are called continuous state
255  * variables in Simbody, but are more simply referred to as <em>StateVariables</em>
256  * in OpenSim. Component provides services to define and access its
257  * StateVariables and specify their dynamics (derivatives with respect to time)
258  * that are automatically and simultaneously integrated with the MultibodySystem
259  * dynamics. Common operations to integrate, take the max or min, or to delay a
260  * signal, etc. require internal variables to perform their calculations and
261  * these are also held in the State. Simbody provides the infrastructure to
262  * ensure that calculations are kept up-to-date with the state variable values.
263  *
264  * There are other types of "State" variables such as a flag (or options) that
265  * enables a component to be disabled or for a muscle force to be overridden and
266  * and these are identified as <em>ModelingOptions</em> since they may change
267  * the modeled dynamics of the component. Component provides services
268  * that enable developers of components to define additional ModelingOptions.
269  *
270  * ### Discrete variables
271  *
272  * Often a component requires input from an outside source (precomputed data
273  * from a file, another program, or interaction from a user) in which case these
274  * variables do not have dynamics (differential eqns.) known to the component,
275  * but are necessary to describe the dynamical "state" of the system. An example,
276  * is a throttle component (a "controller" that provides an actuator, e.g. a
277  * motor, with a control signal like a voltage or current) which it gets as direct
278  * input from the user (via a joystick, key press, etc..). The throttle controls
279  * the motor torque output and therefore the behavior of the model. The input by
280  * the user to the throttle the motor (the controls) is necessary to specify the
281  * model dynamics at any instant and therefore are considered part of the State.
282  * In OpenSim they are simply referred to as DiscreteVariables. The Component
283  * provides services to enable developers of components to define and access its
284  * DiscreteVariables.
285  *
286  * ### Cache variables
287  *
288  * Fast and efficient simulations also require computationally expensive
289  * calculations to be performed only when necessary. Often the result of an
290  * expensive calculation can be reused many times over, while the variables it
291  * is dependent on remain fixed. The concept of holding onto these values is
292  * called caching and the variables that hold these values are call
293  * <em>CacheVariables</em>. It is important to note, that cache variables are
294  * not state variables. Cache variables can always be recomputed exactly
295  * from the State. OpenSim uses the Simbody infrastructure to manage cache
296  * variables and their validity. Component provides a simplified interface to
297  * define and access CacheVariables.
298  *
299  * ### Stages
300  *
301  * Many modeling and simulation codes put the onus on users and component
302  * creators to manage the validity of cache variables, which is likely to lead
303  * to undetectable errors where cache values are stale (calculated based on past
304  * state variable values). Simbody, on the other hand, provides a more strict
305  * infrastructure to make it easy to exploit the efficiencies of caching while
306  * reducing the risks of validity errors. To do this, Simbody employs the concept
307  * of computational stages to "realize" (or compute) a model's system to a
308  * particular stage requires cached quantities up to and including the stage to
309  * to computed/specified. Simbody utilizes nine realization stages
310  * (<tt>SimTK::Stage::</tt>)
311  *
312  * -# \c Topology       finalize System with "slots" for most variables (above)
313  * -# \c %Model         specify modeling choices
314  * -# \c Instance       specify modifiable model parameters
315  * -# \c Time           compute time dependent quantities
316  * -# \c Position       compute position dependent quantities
317  * -# \c Velocity       compute velocity dependent quantities
318  * -# \c Dynamics       compute system applied forces and dependent quantities
319  * -# \c Acceleration   compute system accelerations and all other derivatives
320  * -# \c Report         compute quantities for reporting/output
321  *
322  * The Component interface is automatically invoked by the System and its
323  * realizations. Component users and most developers need not concern themselves
324  * with \c Topology, \c %Model or \c Instance stages. That interaction is managed
325  * by Component when component creators implement extendAddToSystem() and use the
326  * services provided by Component. Component creators do need to determine and
327  * specify stage dependencies for Discrete and CacheVariables that they add to
328  * their components. For example, the throttle controller reads its value from
329  * user input and it is valid for all calculations as long as time does not
330  * change. If the simulation (via numerical integration) steps forward (or
331  * backward for a trial step) and updates the state, the control from a previous
332  * state (time) should be invalid and an error generated for trying to access
333  * the DiscreteVariable for the control value. To do this one specifies the
334  * "invalidates" stage (e.g. <tt>SimTK::Stage::Time</tt>) for a DiscreteVariable
335  * when the variable is added to the Component. A subsequent change to that
336  * variable will invalidate all state cache entries at that stage or higher. For
337  * example, if a DiscreteVariable is declared to invalidate <tt>Stage::Position</tt>
338  * then changing it will invalidate cache entries that depend on positions,
339  * velocities, forces, and accelerations.
340  *
341  * Similar principles apply to CacheVariables, which requires a "dependsOn" stage to
342  * be specified when a CacheVariable is added to the component. In this case,
343  * the cache variable "shadows" the State (unlike a DiscreteVariable, which is a
344  * part of the State) holding already-computed state-dependent values so that
345  * they do not need to be recomputed until the state changes.
346  * Accessing the CacheVariable in a State whose current stage is lower than
347  * that CacheVariable's specified dependsOn stage will trigger an exception.
348  * It is up to the component to update the value of the cache variable.
349  * Component provides methods to check if the cache is valid, update its value
350  * and then to mark it as valid.
351  *
352  * ### The interface of this class
353  *
354  * The primary responsibility of a Component is to add its computational
355  * representation(s) to the underlying SimTK::System by implementing
356  * extendAddToSystem().
357  *
358  * Additional methods provide support for adding modeling options, state and
359  * cache variables.
360  *
361  * Public methods enable access to component variables via their names.
362  *
363  * ### Subcomponents
364  *
365  * A %Component can have any number of %Components within it; we call these
366  * subcomponents. Subcomponents can also contain their own subcomponents as
367  * well. There are three categories of subcomponents, which vary in whether
368  * they are *configurable* and *fixed in number*:
369  *
370  * - **property subcomponents** Any Property in a Component that is of type
371  *   Component is a subcomponent. This includes list properties and Set%s. This
372  *   is the most common category of subcomponent, and its distinguishing
373  *   feature is that these subcomponents are *configurable* by the user of this
374  *   component. These subcomponents appear in the XML for this component, and
375  *   can be modified in XML or through the API. They are also not fixed in
376  *   number; users can add more property subcomponents to an existing
377  *   component (though it is possible to enforce a fixed number by using
378  *   one-value properties or limiting the size of a list property). The bodies,
379  *   joints, forces, etc. in a Model's BodySet, JointSet, ForceSet, etc. are
380  *   all examples of property subcomponents. This category of subcomponent is
381  *   the most similar to what was available pre-v4.0.
382  * - **member subcomponents** These are *not* configurable by the user of this
383  *   Component, and can only be modified by this Component. You can
384  *   still access member subcomponents through the API, but only the component
385  *   containing the subcomponents can modify them. Any Component class can have
386  *   any number of member subcomponents, but this number is *fixed* for every
387  *   instance of the component.
388  * - **adopted subcomponents** These are *not* configurable (does not appear in
389  *   XML) and *not* fixed in number. For example, a component can decide,
390  *   based on other aspects of the model, that it needs to create a new
391  *   subcomponent. This can be done using adopted subcomponents.
392  *
393  * Also, any specific Component can end up in any of these three categories.
394  * That is, if you have a MySpecialForce Component, any other Component can
395  * have it as a property subcomponent, a member subcomponent, or as an adopted
396  * subcomponent.
397  *
398  * @author Ajay Seth, Michael Sherman, Chris Dembia
399  */
400 class OSIMCOMMON_API Component : public Object {
401 OpenSim_DECLARE_ABSTRACT_OBJECT(Component, Object);
402 
403 protected:
404 //==============================================================================
405 // PROPERTIES
406 //==============================================================================
407 
408     OpenSim_DECLARE_LIST_PROPERTY(components, Component,
409         "List of components that this component owns and serializes.");
410 
411 public:
412 //==============================================================================
413 // METHODS
414 //==============================================================================
415     /** Default constructor **/
416     Component();
417 
418     /** Construct Component from an XML file. **/
419     Component(const std::string& aFileName,
420         bool aUpdateFromXMLNode = true) SWIG_DECLARE_EXCEPTION;
421 
422     /** Construct Component from a specific node in an XML document. **/
423     explicit Component(SimTK::Xml::Element& aNode);
424 
425     /** Use default copy constructor and assignment operator. */
426     Component(const Component&) = default;
427     Component& operator=(const Component&) = default;
428 
429     /** Destructor is virtual to allow concrete Component to cleanup. **/
430     virtual ~Component() = default;
431 
432     /** @name Component Structural Interface
433     The structural interface ensures that deserialization, resolution of
434     inter-connections, and handling of dependencies are performed systematically
435     and prior to system creation, followed by allocation of necessary System
436     resources. These methods can be extended by virtual methods that form the
437     Component Extension Interface (e.g. #extendFinalizeFromProperties)
438     that can be implemented by subclasses of Components.
439 
440     Component ensures that the corresponding calls are propagated to all of its
441     subcomponents.*/
442 
443     ///@{
444 
445     /** Define a Component's internal data members and structure according to
446         its properties. This includes its subcomponents as part of the component
447         ownership tree and identifies its owner (if present) in the tree.
448         finalizeFromProperties propagates to all of the component's subcomponents
449         prior to invoking the virtual extendFinalizeFromProperties() on itself.
450         Note that if the Component has already been added to a System (result of
451         addToSystem(); e.g., Model::initSystem()) when finalizeFromProperties()
452         is called, then finalizeFromProperties() disassociates the component from
453         that System.*/
454     void finalizeFromProperties();
455 
456     /** Satisfy the Component's connections specified by its Sockets and Inputs.
457         Locate Components and their Outputs to satisfy the connections in an
458         aggregate Component (e.g. Model), which is the root of a tree of
459         Components. */
460     void finalizeConnections(Component& root);
461 
462     /** Disconnect/clear this Component from its aggregate component. Empties
463         all component's sockets and sets them as disconnected.*/
464     void clearConnections();
465 
466     /** Have the Component add itself to the underlying computational System */
467     void addToSystem(SimTK::MultibodySystem& system) const;
468 
469     /** Initialize Component's state variable values from its properties */
470     void initStateFromProperties(SimTK::State& state) const;
471 
472     /** %Set Component's properties given a state. */
473     void setPropertiesFromState(const SimTK::State& state);
474 
475     // End of Component Structural Interface (public non-virtual).
476     ///@}
477 
478     /** Optional method for generating arbitrary display geometry that reflects
479     this %Component at the specified \a state. This will be called once to
480     obtain ground- and body-fixed geometry (with \a fixed=\c true), and then
481     once per frame (with \a fixed=\c false) to generate on-the-fly geometry such
482     as rubber band lines, force arrows, labels, or debugging aids.
483 
484     Please note that there is a precondition that the state passed in to
485     generateDecorations be realized to Stage::Position. If your component can
486     visualize quantities realized at Velocity, Dynamics or Acceleration stages,
487     then you must check that the stage has been realized before using/requesting
488     stage dependent values. It is forbidden to realize the model to a higher
489     stage within generateDecorations, because this can trigger costly side-
490     effects such as evaluating all model forces even when performing a purely
491     kinematic study.
492 
493     If you override this method, be sure to invoke the base class method first,
494     using code like this:
495     @code
496     void MyComponent::generateDecorations
497        (bool                                        fixed,
498         const ModelDisplayHints&                    hints,
499         const SimTK::State&                         state,
500         SimTK::Array_<SimTK::DecorativeGeometry>&   appendToThis) const
501     {
502         // invoke parent class method
503         Super::generateDecorations(fixed,hints,state,appendToThis);
504         // ... your code goes here
505         // can render velocity dependent quanities if stage is Velocity or higher
506         if(state.getSystemStage() >= Stage::Velocity) {
507             // draw velocity vector for model COM
508         }
509         // can render computed forces if stage is Dynamics or higher
510         if(state.getSystemStage() >= Stage::Dynamics) {
511             // change the length of a force arrow based on the force in N
512         }
513     }
514     @endcode
515 
516     @param[in]      fixed
517         If \c true, generate only geometry that is fixed to a PhysicalFrame,
518         configuration, and velocity. Otherwise generate only such dependent
519         geometry.
520     @param[in]      hints
521         See documentation for ModelDisplayHints; you may want to alter the
522         geometry you generate depending on what you find there. For example,
523         you can determine whether the user wants to see debug geometry.
524     @param[in]      state
525         The State for which geometry should be produced. See below for more
526         information.
527     @param[in,out]  appendToThis
528         %Array to which generated geometry should be \e appended via the
529         \c push_back() method.
530 
531     When called with \a fixed=\c true only modeling options and parameters
532     (Instance variables) should affect geometry; time, position, and velocity
533     should not. In that case OpenSim will already have realized the \a state
534     through Instance stage. When called with \a fixed=\c false, you may
535     consult any relevant value in \a state. However, to avoid unnecessary
536     computation, OpenSim guarantees only that \a state will have been realized
537     through Position stage; if you need anything higher than that (reaction
538     forces, for example) you should make sure the \a state is realized through
539     Acceleration stage. **/
generateDecorations(bool fixed,const ModelDisplayHints & hints,const SimTK::State & state,SimTK::Array_<SimTK::DecorativeGeometry> & appendToThis)540     virtual void generateDecorations
541             (bool                                       fixed,
542             const ModelDisplayHints&                    hints,
543             const SimTK::State&                         state,
544             SimTK::Array_<SimTK::DecorativeGeometry>&   appendToThis) const {};
545 
546     /**
547      * Get the underlying MultibodySystem that this component is connected to.
548      * Make sure you have called Model::initSystem() prior to accessing the System.
549      * Throws an Exception if the System has not been created or the Component
550      * has not added itself to the System.
551      * @see hasSystem().  */
552     const SimTK::MultibodySystem& getSystem() const;
553 
554     /**
555     * Check if this component has an underlying MultibodySystem.
556     * Returns false if the System has not been created OR if this
557     * Component has not added itself to the System.  */
hasSystem()558     bool hasSystem() const { return !_system.empty(); }
559 
560     /** Does the provided component already exist anywhere in the ownership
561      * tree (not just subcomponents of this component)? */
562     bool isComponentInOwnershipTree(const Component* component) const;
563 
564     /**
565     * Add a Component (as a subcomponent) of this component.
566     * This component takes ownership of the subcomponent and it will be
567     * serialized (appear in XML) as part of this component. Specifically,
568     * it will appear in the `<components>` list for this Component.
569     * If the subcomponent is already owned by this component or exists
570     * in the same hierarchy (tree) as this component, an Exception
571     * is thrown.
572     * @note addComponent is intended to replace existing addBody(), addJoint,
573     *       ... on Model or the requirement for specific add###() methods to
574     *       subcomponents to a Component.
575     *
576     * Typical usage is:
577     @code
578         // Start with an empty Model (which is a Component)
579         Model myModel;
580         // Create any Component type on the heap
581         Body* newBody = new Body();
582         // Customize the Component by setting its properties
583         newBody->setName("newBody");
584         newBody->setMass(10.0);
585         newBody->setMassCenter(SimTK::Vec3(0));
586         // ...
587         // Now add it to your model, which will take ownership of it
588         myModel.addComponent(newBody);
589         //
590         // Keep creating and adding new components, like Joints, Forces, etc..
591     @endcode
592     *
593     * @throws ComponentAlreadyPartOfOwnershipTree
594     * @param subcomponent is the Component to be added. */
595     void addComponent(Component* subcomponent);
596 
597     /**
598      * Get an iterator through the underlying subcomponents that this component is
599      * composed of. The hierarchy of Components/subComponents forms a tree.
600      * The order of the Components is that of tree preorder traversal so that a
601      * component is traversed before its subcomponents.
602      *
603      * @code{.cpp}
604      * for (const auto& muscle : model.getComponentList<Muscle>()) {
605      *     muscle.get_max_isometric_force();
606      * }
607      * @endcode
608      *
609      * The returned ComponentList does not permit modifying any components; if
610      * you want to modify the components, see updComponentList().
611      *
612      * @tparam T A subclass of Component (e.g., Body, Muscle).
613      */
614     template <typename T = Component>
getComponentList()615     ComponentList<const T> getComponentList() const {
616         static_assert(std::is_base_of<Component, T>::value,
617                 "Template argument must be Component or a derived class.");
618         initComponentTreeTraversal(*this);
619         return ComponentList<const T>(*this);
620     }
621 
622     /** Similar to getComponentList(), except the resulting list allows one to
623     modify the components. For example, you could use this method to change
624     the max isometric force of all muscles:
625 
626     @code{.cpp}
627     for (auto& muscle : model.updComponentList<Muscle>()) {
628         muscle.set_max_isometric_force(...);
629     }
630     @endcode
631 
632     @note Do NOT use this method to add (or remove) (sub)components from any
633     component. The tree structure of the components should not be altered
634     through this ComponentList.
635 
636     @tparam T A subclass of Component (e.g., Body, Muscle). */
637     template <typename T = Component>
updComponentList()638     ComponentList<T> updComponentList() {
639         static_assert(std::is_base_of<Component, T>::value,
640                 "Template argument must be Component or a derived class.");
641         initComponentTreeTraversal(*this);
642         clearObjectIsUpToDateWithProperties();
643         return ComponentList<T>(*this);
644     }
645 
646     /**
647      * Uses getComponentList<T>() to count the number of underlying
648      * subcomponents of the specified type.
649      *
650      * @tparam T A subclass of Component (e.g., Body, Muscle).
651      */
652     template <typename T = Component>
countNumComponents()653     unsigned countNumComponents() const {
654         unsigned count = 0u;
655         const auto compList = getComponentList<T>();
656         auto it = compList.begin();
657         while (it != compList.end()) {
658             ++count;
659             ++it;
660         }
661         return count;
662     }
663 
664     /** Class that permits iterating over components/subcomponents (but does
665      * not actually contain the components themselves). */
666     template <typename T>
667     friend class ComponentList;
668     /** Class to iterate over ComponentList returned by getComponentList(). */
669     template <typename T>
670     friend class ComponentListIterator;
671 
672 
673     /** Get the complete (absolute) pathname for this Component to its ancestral
674      * Component, which is the root of the tree to which this Component belongs.
675      * For example: a Coordinate Component would have an absolute path name
676      * like: `/arm26/elbow_r/flexion`. Accessing a Component by its
677      * absolutePathName from root is guaranteed to be unique. The
678      * absolutePathName is generated on-the-fly by traversing the ownership tree
679      * and, therefore, calling this method is not "free". */
680     std::string getAbsolutePathString() const;
681 
682     /** Return a ComponentPath of the absolute path of this Component.
683      * Note that this has more overhead than calling `getName()` because
684      * it traverses up the tree to generate the absolute pathname (and its
685      * computational cost is thus a function of depth). Consider other
686      * options if this is repeatedly called and efficiency is important.
687      * For instance, `getAbsolutePathString()` is faster if you only
688      * need the path as a string. */
689     ComponentPath getAbsolutePath() const;
690 
691     /** Get the relative path of this Component with respect to another
692      * Component, as a string. */
693     std::string getRelativePathString(const Component& wrt) const;
694 
695     /** Get the relative path of this Component with respect to another
696      * Component. */
697     ComponentPath getRelativePath(const Component& wrt) const;
698 
699     /** Query if there is a component (of any type) at the specified
700      * path name. For example,
701      * @code
702      * bool exists = model.hasComponent("right_elbow/elbow_flexion");
703      * @endcode
704      * checks if `model` has a subcomponent "right_elbow," which has a
705      * subcomponent "elbow_flexion." */
hasComponent(const std::string & pathname)706     bool hasComponent(const std::string& pathname) const {
707         return hasComponent<Component>(pathname);
708     }
709 
710     /** Query if there is a component of a given type at the specified
711      * path name. For example,
712      * @code
713      * bool exists = model.hasComponent<Coordinate>("right_elbow/elbow_flexion");
714      * @endcode
715      * checks if `model` has a subcomponent "right_elbow," which has a
716      * subcomponent "elbow_flexion," and that "elbow_flexion" is of type
717      * Coordinate. This method cannot be used from scripting; see the
718      * non-templatized hasComponent(). */
719     template <class C = Component>
hasComponent(const std::string & pathname)720     bool hasComponent(const std::string& pathname) const {
721         static_assert(std::is_base_of<Component, C>::value,
722             "Template parameter 'C' must be derived from Component.");
723         const C* comp = this->template traversePathToComponent<C>({pathname});
724         return comp != nullptr;
725     }
726 
727     /**
728      * Get a unique subcomponent of this Component by its path name and type 'C'.
729      * Throws ComponentNotFoundOnSpecifiedPath exception if the component at
730      * that path name location does not exist OR it is not of the correct type.
731      * For example,
732      * @code
733      *    auto& coord = model.getComponent<Coordinate>("right_elbow/elbow_flexion");
734      * @endcode
735      * returns coord which is a Coordinate named "elbow_flexion" from a Joint
736      * named "right_elbow" given it is a child of the Component (Model) model.
737      * If unsure of a Component's path or whether or not it exists in the model,
738      * use printComponentsMatching() or hasComponent().
739      *
740      * This template function cannot be used in Python/Java/MATLAB; see the
741      * non-templatized getComponent().
742      *
743      * @param  pathname        a pathname of a Component of interest
744      * @return const reference to component of type C at
745      * @throws ComponentNotFoundOnSpecifiedPath if no component exists
746      */
747     template <class C = Component>
getComponent(const std::string & pathname)748     const C& getComponent(const std::string& pathname) const {
749         return getComponent<C>(ComponentPath(pathname));
750     }
751     template <class C = Component>
getComponent(const ComponentPath & pathname)752     const C& getComponent(const ComponentPath& pathname) const {
753         static_assert(std::is_base_of<Component, C>::value,
754             "Template parameter 'CompType' must be derived from Component.");
755 
756         const C* comp = this->template traversePathToComponent<C>(pathname);
757         if (comp) {
758             return *comp;
759         }
760 
761         // Only error cases remain
762         OPENSIM_THROW(ComponentNotFoundOnSpecifiedPath, pathname.toString(),
763                                                        C::getClassName(),
764                                                        getName());
765     }
766 
767     /** Similar to the templatized getComponent(), except this returns the
768      * component as the generic Component type. This can be used in
769      * Python/Java/MATLAB. Here is an example of using this in MATLAB:
770      * @code
771      * coord = model.getComponent('right_elbow/elbow_flexion')
772      * coord.getNumConnectees() % okay; this is a Component method.
773      * coord.getDefaultClamped() % inaccessible; method on Coordinate.
774      * Coordinate.safeDownCast(coord).getDefaultClamped() % now accessible.
775      * @endcode
776      *
777      * %Exception: in Python, you will get the concrete type (in most cases):
778      * @code{.py}
779      * coord = model.getComponent('right_elbow/elbow_flexion')
780      * coord.getDefaultClamped() # works; no downcasting necessary.
781      * @endcode
782      */
getComponent(const std::string & pathname)783     const Component& getComponent(const std::string& pathname) const {
784         return getComponent<Component>(pathname);
785     }
786 
787     /** Get a writable reference to a subcomponent. Use this method
788     * to edit the properties and connections of the subcomponent.
789     * Note: the method will mark this Component as out-of-date with
790     * its properties and will require finalizeFromProperties() to be
791     * invoked directly or indirectly (by finalizeConnections() or
792     * Model::initSystem())
793     * @param name       the pathname of the Component of interest
794     * @return Component the component of interest
795     * @throws ComponentNotFoundOnSpecifiedPath if no component exists
796     * @see getComponent()
797     */
798     template <class C = Component>
updComponent(const std::string & name)799     C& updComponent(const std::string& name) {
800         return updComponent<C>(ComponentPath(name));
801     }
802     template <class C = Component>
updComponent(const ComponentPath & name)803     C& updComponent(const ComponentPath& name) {
804         clearObjectIsUpToDateWithProperties();
805         return *const_cast<C*>(&(this->template getComponent<C>(name)));
806     }
807 
808     /** Similar to the templatized updComponent(), except this returns the
809      * component as the generic Component type. As with the non-templatized
810      * getComponent(), though, this will give the concrete type in Python in
811      * most cases.
812      * @see getComponent()
813      */
updComponent(const std::string & pathname)814     Component& updComponent(const std::string& pathname) {
815         return updComponent<Component>(pathname);
816     }
817 
818 
819     /** Print a list to the console of all components whose absolute path name
820      * contains the given string. You might use this if (a) you know the name
821      * of a component in your model but don't know its absolute path, (b) if
822      * you want to find all components with a given name, or (c) to get a list
823      * of all components on the right leg of a model (if all components on the
824      * right side have "_r" in their name).
825      *
826      * A function call like:
827      * @code{.cpp}
828      * unsigned num = comp.printComponentsMatching("rotation");
829      * @endcode
830      * may produce output like:
831      * @verbatim
832      * /leg_model/right_hip/rotation
833      * /leg_model/left_hip/rotation
834      * @endverbatim
835      *
836      * @returns The number of matches. */
837     unsigned printComponentsMatching(const std::string& substring) const;
838 
839     /**
840      * Get the number of "continuous" state variables maintained by the
841      * Component and its subcomponents.
842      * @throws ComponentHasNoSystem if this Component has not been added to a
843      *         System (i.e., if initSystem has not been called)
844      */
845     int getNumStateVariables() const;
846 
847     /**
848      * Get the names of "continuous" state variables maintained by the Component
849      * and its subcomponents.
850      * @throws ComponentHasNoSystem if this Component has not been added to a
851      *         System (i.e., if initSystem has not been called)
852      */
853     Array<std::string> getStateVariableNames() const;
854 
855 
856     /** @name Component Socket Access methods
857         Access Sockets of this component by name. */
858     //@{
859     /** Get the number of Sockets in this Component. */
getNumSockets()860     int getNumSockets() const {
861         return int(_socketsTable.size());
862     }
863 
864     /** Collect and return the names of the sockets in this component. You
865      * can use this to iterate through the sockets:
866      * @code
867      * for (std::string name : comp.getSocketNames()) {
868      *     const AbstractSocket& socket = getSocket(name);
869      * }
870      * @endcode */
getSocketNames()871     std::vector<std::string> getSocketNames() {
872         std::vector<std::string> names;
873         for (const auto& it : _socketsTable) {
874             names.push_back(it.first);
875         }
876         return names;
877     }
878 
879     /**
880     * Get the "connectee" object that the Component's Socket
881     * is bound to. Guaranteed to be valid only after the Component
882     * has been connected (that is connect() has been invoked).
883     * If the Socket has not been connected, an exception is thrown.
884     *
885     * This method is for getting the concrete connectee object, and is not
886     * available in scripting. If you want generic access to the connectee as an
887     * Object, use the non-templated version.
888     *
889     * @tparam T         the type of the Connectee (e.g., PhysicalFrame).
890     * @param name       the name of the socket
891     * @return T         const reference to object that satisfies
892     *                   the Socket
893     *
894     * Example:
895     * @code
896     * const PhysicalFrame& frame = joint.getConnectee<PhysicalFrame>("parent_frame");
897     * frame.getMobilizedBody();
898     * @endcode
899     */
900     template<typename T>
getConnectee(const std::string & name)901     const T& getConnectee(const std::string& name) const {
902         // get the Socket and check if it is connected.
903         const Socket<T>& socket = getSocket<T>(name);
904         OPENSIM_THROW_IF_FRMOBJ(!socket.isConnected(), Exception,
905                 "Socket '" + name + "' not connected.");
906         return socket.getConnectee();
907     }
908 
909     /** Get the connectee as an Object. This means you will not have
910     * access to the methods on the concrete connectee. This is the method you
911     * must use in MATLAB to access the connectee.
912     *
913     * Example:
914     * @code{.cpp}
915     * const Object& obj = joint.getConnectee("parent_frame");
916     * obj.getName(); // method on Object works.
917     * obj.getMobilizedBody(); // error: not available.
918     * @endcode
919     *
920     * In MATLAB, if you want the concrete type, you need to downcast the
921     * Object. Here is an example where you know the "parent_frame" is a Body:
922     * @code
923     * f = joint.getConnectee('parent_frame');
924     * m = Body.safeDownCast(f).getMass();
925     * @endcode
926     *
927     * Exception: in Python, you will get the concrete type (in most cases):
928     * @code{.py}
929     * f = joint.getConnectee("parent_frame");
930     * m = f.getMass() # works (if the parent frame is a body)
931     * @endcode
932     */
getConnectee(const std::string & name)933     const Object& getConnectee(const std::string& name) const {
934         const AbstractSocket& socket = getSocket(name);
935         OPENSIM_THROW_IF_FRMOBJ(!socket.isConnected(), Exception,
936                 "Socket '" + name + "' not connected.");
937         return socket.getConnecteeAsObject();
938     }
939 
940     /** Get an AbstractSocket for the given socket name. This
941      * lets you get information about the connection (like if the socket is
942      * connected), but does not give you access to the socket's connectee.
943      * For that, use getConnectee().
944      *
945      * @internal If you have not yet called finalizeFromProperties() on this
946      * component, this function will update the Socket (to tell it which
947      * component it's in) before providing it to you.
948      *
949      * <b>C++ example</b>
950      * @code{.cpp}
951      * model.getComponent("/path/to/component").getSocket("socketName");
952      * @endcode
953      */
getSocket(const std::string & name)954     const AbstractSocket& getSocket(const std::string& name) const {
955         auto it = _socketsTable.find(name);
956 
957         if (it != _socketsTable.end()) {
958             // The following allows one to use a Socket immediately after
959             // copying the component;
960             // e.g., myComponent.clone().getSocket("a").getConnecteePath().
961             // Since we use the default copy constructor for Component,
962             // the copied AbstractSocket cannot know its new owner
963             // immediately after copying.
964             if (!it->second->hasOwner()) {
965                 // The `this` pointer must be non-const because the Socket
966                 // will want to be able to modify the connectee path property.
967                 const_cast<AbstractSocket*>(it->second.get())->setOwner(
968                         const_cast<Self&>(*this));
969             }
970             return it->second.getRef();
971         }
972 
973         OPENSIM_THROW_FRMOBJ(SocketNotFound, name);
974     }
975 
976     /** Get a writable reference to the AbstractSocket for the given
977      * socket name. Use this method to connect the Socket to something.
978      *
979      * <b>C++ example</b>
980      * @code
981      * joint.updSocket("parent_frame").connect(model.getGround());
982      * @endcode
983      *
984      * @internal If you have not yet called finalizeFromProperties() on this
985      * component, this function will update the Socket (to tell it which
986      * component it's in) before providing it to you.
987      */
updSocket(const std::string & name)988     AbstractSocket& updSocket(const std::string& name) {
989         return const_cast<AbstractSocket&>(getSocket(name));
990     }
991 
992     /**
993     * Get a const reference to the concrete Socket provided by this
994     * Component by name.
995     *
996     * @internal If you have not yet called finalizeFromProperties() on this
997     * component, this function will update the Socket (to tell it which
998     * component it's in) before providing it to you.
999     *
1000     * @param name       the name of the Socket
1001     * @return const reference to the (Abstract)Socket
1002     */
1003     template<typename T>
getSocket(const std::string & name)1004     const Socket<T>& getSocket(const std::string& name) const {
1005         return Socket<T>::downcast(getSocket(name));
1006     }
1007 
1008     /**
1009     * Get a writable reference to the concrete Socket provided by this
1010     * Component by name.
1011     *
1012     * @internal If you have not yet called finalizeFromProperties() on this
1013     * component, this function will update the Socket (to tell it which
1014     * component it's in) before providing it to you.
1015     *
1016     * @param name       the name of the Socket
1017     * @return const reference to the (Abstract)Socket
1018     */
updSocket(const std::string & name)1019     template<typename T> Socket<T>& updSocket(const std::string& name) {
1020         return const_cast<Socket<T>&>(getSocket<T>(name));
1021     }
1022     //@} end of Component Socket Access methods
1023 
1024     /** @name Component Inputs and Outputs Access methods
1025         Access inputs and outputs by name and iterate over all outputs.
1026     */
1027     //@{
1028 
1029     /** Access the number of Inputs that this component has. */
getNumInputs()1030     int getNumInputs() const {
1031         return int(_inputsTable.size());
1032     }
1033 
1034     /** Access the number of Outputs that this component has. */
getNumOutputs()1035     int getNumOutputs() const {
1036         return int(_outputsTable.size());
1037     }
1038 
1039     /** Collect and return the names of Inputs in this component as an
1040      * std::vector. */
getInputNames()1041     std::vector<std::string> getInputNames() const {
1042         std::vector<std::string> names;
1043         for (const auto& it : _inputsTable) {
1044             names.push_back(it.first);
1045         }
1046         return names;
1047     }
1048 
1049     /** Collect and return the names of Outputs in this component as an
1050      * std::vector. */
getOutputNames()1051     std::vector<std::string> getOutputNames() const {
1052         std::vector<std::string> names;
1053         for (const auto& entry : getOutputs()) {
1054             names.push_back(entry.first);
1055         }
1056         return names;
1057     }
1058 
1059     /**
1060     * Get an Input provided by this Component by name.
1061     *
1062     * <b>C++ example:</b> get an Input from a Component in the model
1063     * @code{.cpp}
1064     * model.getComponent("/path/to/component").getInput("inputName");
1065     * @endcode
1066     *
1067     * @internal If you have not yet called finalizeFromProperties() on this
1068     * component, this function will update the Input (to tell it which
1069     * component it's in) before providing it to you.
1070     *
1071     * @param name   the name of the Input
1072     * @return       const reference to the AbstractInput
1073     */
getInput(const std::string & name)1074     const AbstractInput& getInput(const std::string& name) const
1075     {
1076         auto it = _inputsTable.find(name);
1077 
1078         if (it != _inputsTable.end()) {
1079             // The following allows one to use an Input immediately after
1080             // copying the component;
1081             // e.g., myComponent.clone().getInput("a").getConnecteePath().
1082             // Since we use the default copy constructor for Component,
1083             // the copied AbstractSocket (base class of AbstractInput)
1084             // cannot know its new owner immediately after copying.
1085             if (!it->second->hasOwner()) {
1086 
1087                 // The `this` pointer must be non-const because the Socket
1088                 // will want to be able to modify the connectee_name property.
1089                 const_cast<AbstractInput*>(it->second.get())->setOwner(
1090                         const_cast<Self&>(*this));
1091             }
1092             return it->second.getRef();
1093         }
1094 
1095         OPENSIM_THROW_FRMOBJ(InputNotFound, name);
1096     }
1097 
1098     /**
1099     * Get a writable reference to an Input provided by this Component by name.
1100     *
1101     * <b>C++ example:</b> get a writable reference to an Input of a
1102     * Component in a model
1103     * @code{.cpp}
1104     * model.updComponent("/path/to/component").updInput("inputName");
1105     * @endcode
1106     *
1107     * @internal If you have not yet called finalizeFromProperties() on this
1108     * component, this function will update the Input (to tell it which
1109     * component it's in) before providing it to you.
1110 
1111     * @param name   the name of the Input
1112     * @return       reference to the AbstractInput
1113     */
updInput(const std::string & name)1114     AbstractInput& updInput(const std::string& name)
1115     {
1116         return *const_cast<AbstractInput *>(&getInput(name));
1117     }
1118 
1119 
1120     /**
1121     * Get a concrete Input that you can directly ask for its values.
1122     *
1123     * @internal If you have not yet called finalizeFromProperties() on this
1124     * component, this function will update the Input (to tell it which
1125     * component it's in) before providing it to you.
1126     *
1127     * @param name   the name of the Input
1128     * @throws Exception if an Input with the given name does not exist.
1129     * @throws std::bad_cast if the provided type T is incorrect for the given name.
1130     */
1131     template<typename T>
getInput(const std::string & name)1132     const Input<T>& getInput(const std::string& name) const {
1133         return dynamic_cast<const Input<T>&>(getInput(name));
1134     }
1135 
1136     /**
1137     * Get the Output provided by this Component by name.
1138     *
1139     * <b>C++ example:</b> get an Output from a Component in a model
1140     * @code{.cpp}
1141     * model.getComponent("/path/to/component").getOutput("outputName");
1142     * @endcode
1143     *
1144     * @param name   the name of the Output
1145     * @return       const reference to the AbstractOutput
1146     */
getOutput(const std::string & name)1147     const AbstractOutput& getOutput(const std::string& name) const
1148     {
1149         auto it = _outputsTable.find(name);
1150 
1151         if (it != _outputsTable.end()) {
1152             return it->second.getRef();
1153         }
1154 
1155         OPENSIM_THROW_FRMOBJ(OutputNotFound, name);
1156     }
1157 
1158     /**
1159     * Get a writable reference to an Output provided by this Component by name.
1160     *
1161     * <b>C++ example:</b> get a writable reference to an Output of a
1162     * Component in a model
1163     * @code{.cpp}
1164     * model.updComponent("/path/to/component").updOutput("outputName");
1165     * @endcode
1166 
1167     * @param name   the name of the Output
1168     * @return       reference to the AbstractOutput
1169     */
updOutput(const std::string & name)1170     AbstractOutput& updOutput(const std::string& name)
1171     {
1172         return *const_cast<AbstractOutput *>(&getOutput(name));
1173     }
1174 
1175     /** Define OutputConstIterator for convenience */
1176     typedef std::map<std::string, SimTK::ClonePtr<AbstractOutput>>::
1177         const_iterator OutputConstIterator;
1178 
1179     /** Iterate through all Outputs of this component. The intent is to use
1180      * this in a loop as such:
1181      * @code
1182      * for (const auto& entry : comp.getOutputs()) {
1183      *     const std::string& name = entry.first;
1184      *     const AbstractOutput* output = entry.second.get();
1185      *     std::cout << output->getTypeName() << std::endl;
1186      * }
1187      * @endcode
1188      * This provides access to the outputs as AbstractOutput%s, not as the
1189      * concrete type. This also does not permit modifying the outputs.
1190      *
1191      * Not available in Python/Java/MATLAB; use getOutputNames() and
1192      * getOutput() instead.
1193      */
getOutputs()1194     SimTK::IteratorRange<OutputConstIterator> getOutputs() const {
1195         return {_outputsTable.cbegin(), _outputsTable.cend()};
1196     }
1197     //@} end of Component Inputs and Outputs Access methods
1198 
1199 
1200 
1201     /** @name Component State Access methods
1202         Get and set modeling option, input and output values, state variable,
1203         discrete and/or cache variables in the State.
1204      */
1205     //@{
1206 
1207     /**
1208      * Get a ModelingOption flag for this Component by name.
1209      * The flag is an integer corresponding to the index of modelingOptionNames used
1210      * add the modeling option to the component. @see addModelingOption
1211     *
1212      * @param state  the State in which to set the modeling option
1213      * @param name   the name (string) of the modeling option of interest
1214      * @return flag  integer value for modeling option
1215     */
1216     int getModelingOption(const SimTK::State& state, const std::string& name) const;
1217 
1218     /**
1219      * %Set the value of a ModelingOption flag for this Component.
1220      * if the integer value exceeds the number of option names used to
1221      * define the options, an exception is thrown. The SimTK::State
1222      * Stage will be reverted back to Stage::Instance.
1223      *
1224      * @param state  the State in which to set the flag
1225      * @param name   the name (string) of the modeling option of interest
1226      * @param flag   the desired flag (int) value specifying the modeling option
1227      */
1228     void setModelingOption(SimTK::State& state, const std::string& name, int flag) const;
1229 
1230     /**
1231     * Get the Input value that this component is dependent on.
1232     * Checks if Input is connected, otherwise it will throw an
1233     * exception. You can only call this method for non-list inputs.
1234     * For list inputs, you must get the input using getInput(),
1235     * from which you can ask for its values.
1236     *
1237     * @param state      the State for which to set the value
1238     * @param name       the name of the input
1239     * @return T         const Input value
1240     */
1241     template<typename T> const T&
getInputValue(const SimTK::State & state,const std::string & name)1242         getInputValue(const SimTK::State& state, const std::string& name) const {
1243         // get the input and check if it is connected.
1244         const AbstractInput& in = getInput(name);
1245         // TODO could maybe remove this check and have the Input do it. Or,
1246         // here, we could catch Input's exception and give a different message.
1247         if (in.isConnected()) {
1248             return (Input<T>::downcast(in)).getValue(state);
1249         }
1250 
1251         else {
1252         std::stringstream msg;
1253             msg << "Component::getInputValue: ERR- Input '" << name << "' not connected.\n "
1254                 << "for component '" << getName() << "' of type "<< getConcreteClassName();
1255         throw Exception(msg.str(), __FILE__, __LINE__);
1256         }
1257     }
1258 
1259     /**
1260     * Get the Output value provided by this Component by name.
1261     *
1262     * @param state      the State for which to set the value
1263     * @param name       the name of the cache variable
1264     * @return T         const Output value
1265     */
1266     template<typename T> const T&
getOutputValue(const SimTK::State & state,const std::string & name)1267         getOutputValue(const SimTK::State& state, const std::string& name) const
1268     {
1269         return (Output<T>::downcast(getOutput(name))).getValue(state);
1270     }
1271 
1272 
1273     /**
1274      * Get the value of a state variable allocated by this Component.
1275      *
1276      * To connect this StateVariable as an input to another component (such as
1277      * a Reporter), use getOutput(name); each state variable has a
1278      * corresponding Output:
1279      *  @code
1280      *  foo.getInput("input1").connect(bar.getOutput(name));
1281      *  @endcode
1282      *
1283      * @param state   the State for which to get the value
1284      * @param name    the name (string) of the state variable of interest
1285      * @throws ComponentHasNoSystem if this Component has not been added to a
1286      *         System (i.e., if initSystem has not been called)
1287      */
1288     double getStateVariableValue(const SimTK::State& state, const std::string& name) const;
1289 
1290     /**
1291      * %Set the value of a state variable allocated by this Component by name.
1292      *
1293      * @param state  the State for which to set the value
1294      * @param name   the name of the state variable
1295      * @param value  the value to set
1296      * @throws ComponentHasNoSystem if this Component has not been added to a
1297      *         System (i.e., if initSystem has not been called)
1298      */
1299     void setStateVariableValue(SimTK::State& state, const std::string& name, double value) const;
1300 
1301 
1302     /**
1303      * Get all values of the state variables allocated by this Component.
1304      * Includes state variables allocated by its subcomponents.
1305      *
1306      * @param state   the State for which to get the value
1307      * @return Vector of state variable values of length getNumStateVariables()
1308      *                in the order returned by getStateVariableNames()
1309      * @throws ComponentHasNoSystem if this Component has not been added to a
1310      *         System (i.e., if initSystem has not been called)
1311      */
1312     SimTK::Vector getStateVariableValues(const SimTK::State& state) const;
1313 
1314     /**
1315      * %Set all values of the state variables allocated by this Component.
1316      * Includes state variables allocated by its subcomponents. Note, this
1317      * method simply sets the values on the input State. If other conditions
1318      * must be met (such as satisfying kinematic constraints for Coordinates,
1319      * or fiber and tendon equilibrium for muscles) you must invoke the
1320      * appropriate methods on Model (e.g. assemble() to satisfy constraints or
1321      * equilibrateMuscles()) to satisfy these conditions starting from the
1322      * State values provided by setStateVariableValues.
1323      *
1324      * @param state   the State whose values are set
1325      * @param values  Vector of state variable values of length
1326      *                getNumStateVariables() in the order returned by
1327      *                getStateVariableNames()
1328      * @throws ComponentHasNoSystem if this Component has not been added to a
1329      *         System (i.e., if initSystem has not been called)
1330      */
1331     void setStateVariableValues(SimTK::State& state,
1332                                 const SimTK::Vector& values) const;
1333 
1334     /**
1335      * Get the value of a state variable derivative computed by this Component.
1336      *
1337      * @param state   the State for which to get the derivative value
1338      * @param name    the name (string) of the state variable of interest
1339      * @throws ComponentHasNoSystem if this Component has not been added to a
1340      *         System (i.e., if initSystem has not been called)
1341      */
1342     double getStateVariableDerivativeValue(const SimTK::State& state,
1343         const std::string& name) const;
1344 
1345     /**
1346      * Get the value of a discrete variable allocated by this Component by name.
1347      *
1348      * @param state   the State from which to get the value
1349      * @param name    the name of the state variable
1350      * @return value  the discrete variable value
1351      * @throws ComponentHasNoSystem if this Component has not been added to a
1352      *         System (i.e., if initSystem has not been called)
1353      */
1354     double getDiscreteVariableValue(const SimTK::State& state,
1355                                     const std::string& name) const;
1356 
1357     /**
1358      * %Set the value of a discrete variable allocated by this Component by name.
1359      *
1360      * @param state  the State for which to set the value
1361      * @param name   the name of the discrete variable
1362      * @param value  the value to set
1363      * @throws ComponentHasNoSystem if this Component has not been added to a
1364      *         System (i.e., if initSystem has not been called)
1365      */
1366     void setDiscreteVariableValue(SimTK::State& state, const std::string& name,
1367                                   double value) const;
1368 
1369     /**
1370      * Get the value of a cache variable allocated by this Component by name.
1371      *
1372      * @param state  the State from which to get the value
1373      * @param name   the name of the cache variable
1374      * @return T     const reference to the cache variable's value
1375      * @throws ComponentHasNoSystem if this Component has not been added to a
1376      *         System (i.e., if initSystem has not been called)
1377      */
1378     template<typename T> const T&
getCacheVariableValue(const SimTK::State & state,const std::string & name)1379     getCacheVariableValue(const SimTK::State& state, const std::string& name) const
1380     {
1381         // Must have already called initSystem.
1382         OPENSIM_THROW_IF_FRMOBJ(!hasSystem(), ComponentHasNoSystem);
1383 
1384         std::map<std::string, CacheInfo>::const_iterator it;
1385         it = _namedCacheVariableInfo.find(name);
1386 
1387         if(it != _namedCacheVariableInfo.end()) {
1388             SimTK::CacheEntryIndex ceIndex = it->second.index;
1389             return SimTK::Value<T>::downcast(
1390                 getDefaultSubsystem().getCacheEntry(state, ceIndex)).get();
1391         } else {
1392             std::stringstream msg;
1393             msg << "Component::getCacheVariable: ERR- name not found.\n "
1394                 << "for component '"<< getName() << "' of type "
1395                 << getConcreteClassName();
1396             throw Exception(msg.str(),__FILE__,__LINE__);
1397         }
1398     }
1399     /**
1400      * Obtain a writable cache variable value allocated by this Component by
1401      * name. Do not forget to mark the cache value as valid after updating,
1402      * otherwise it will force a re-evaluation if the evaluation method is
1403      * monitoring the validity of the cache value.
1404      *
1405      * @param state  the State for which to set the value
1406      * @param name   the name of the state variable
1407      * @return value modifiable reference to the cache variable's value
1408      * @throws ComponentHasNoSystem if this Component has not been added to a
1409      *         System (i.e., if initSystem has not been called)
1410      */
1411     template<typename T> T&
updCacheVariableValue(const SimTK::State & state,const std::string & name)1412     updCacheVariableValue(const SimTK::State& state, const std::string& name) const
1413     {
1414         // Must have already called initSystem.
1415         OPENSIM_THROW_IF_FRMOBJ(!hasSystem(), ComponentHasNoSystem);
1416 
1417         std::map<std::string, CacheInfo>::const_iterator it;
1418         it = _namedCacheVariableInfo.find(name);
1419 
1420         if(it != _namedCacheVariableInfo.end()) {
1421             SimTK::CacheEntryIndex ceIndex = it->second.index;
1422             return SimTK::Value<T>::downcast(
1423                 getDefaultSubsystem().updCacheEntry(state, ceIndex)).upd();
1424         }
1425         else{
1426             std::stringstream msg;
1427             msg << "Component::updCacheVariable: ERR- '" << name
1428                 << "' name not found.\n "
1429                 << "for component '"<< getName() << "' of type "
1430                 << getConcreteClassName();
1431             throw Exception(msg.str(),__FILE__,__LINE__);
1432         }
1433     }
1434 
1435     /**
1436      * After updating a cache variable value allocated by this Component, you
1437      * can mark its value as valid, which will not change until the realization
1438      * stage falls below the minimum set at the time the cache variable was
1439      * created. If not marked as valid, the evaluation method monitoring this
1440      * flag will force a re-evaluation rather that just reading the value from
1441      * the cache.
1442      *
1443      * @param state  the State containing the cache variable
1444      * @param name   the name of the cache variable
1445      * @throws ComponentHasNoSystem if this Component has not been added to a
1446      *         System (i.e., if initSystem has not been called)
1447      */
markCacheVariableValid(const SimTK::State & state,const std::string & name)1448     void markCacheVariableValid(const SimTK::State& state, const std::string& name) const
1449     {
1450         // Must have already called initSystem.
1451         OPENSIM_THROW_IF_FRMOBJ(!hasSystem(), ComponentHasNoSystem);
1452 
1453         std::map<std::string, CacheInfo>::const_iterator it;
1454         it = _namedCacheVariableInfo.find(name);
1455 
1456         if(it != _namedCacheVariableInfo.end()) {
1457             SimTK::CacheEntryIndex ceIndex = it->second.index;
1458             getDefaultSubsystem().markCacheValueRealized(state, ceIndex);
1459         }
1460         else{
1461             std::stringstream msg;
1462             msg << "Component::markCacheVariableValid: ERR- name not found.\n "
1463                 << "for component '"<< getName() << "' of type "
1464                 << getConcreteClassName();
1465             throw Exception(msg.str(),__FILE__,__LINE__);
1466         }
1467     }
1468 
1469     /**
1470      * Mark a cache variable value allocated by this Component as invalid. When
1471      * the system realization drops to below the lowest valid stage, cache
1472      * variables are automatically marked as invalid. There are instances when
1473      * component-added state variables require invalidating a cache at a lower
1474      * stage. For example, a component may have a "length" state variable which
1475      * should invalidate calculations involving it and other positions when the
1476      * state variable is set. Changing the component state variable
1477      * automatically invalidates Dynamics and higher realizations, but to force
1478      * realizations at Position and Velocity requires setting the lowest valid
1479      * stage to Position and marking the cache variable as invalid whenever the
1480      * "length" state variable value is set/changed.
1481      *
1482      * @param state  the State containing the cache variable
1483      * @param name   the name of the cache variable
1484      * @throws ComponentHasNoSystem if this Component has not been added to a
1485      *         System (i.e., if initSystem has not been called)
1486      */
markCacheVariableInvalid(const SimTK::State & state,const std::string & name)1487     void markCacheVariableInvalid(const SimTK::State& state,
1488                                   const std::string& name) const
1489     {
1490         // Must have already called initSystem.
1491         OPENSIM_THROW_IF_FRMOBJ(!hasSystem(), ComponentHasNoSystem);
1492 
1493         std::map<std::string, CacheInfo>::const_iterator it;
1494         it = _namedCacheVariableInfo.find(name);
1495 
1496         if(it != _namedCacheVariableInfo.end()) {
1497             SimTK::CacheEntryIndex ceIndex = it->second.index;
1498             getDefaultSubsystem().markCacheValueNotRealized(state, ceIndex);
1499         }
1500         else{
1501             std::stringstream msg;
1502             msg << "Component::markCacheVariableInvalid: ERR- name not found.\n"
1503                 << "for component '"<< getName() << "' of type "
1504                 << getConcreteClassName();
1505             throw Exception(msg.str(),__FILE__,__LINE__);
1506         }
1507     }
1508 
1509     /**
1510      * Enables the user to monitor the validity of the cache variable value
1511      * using the returned flag. For components performing a costly evaluation,
1512      * use this method to force a re-evaluation of a cache variable value only
1513      * when necessary (i.e., returns false).
1514      *
1515      * @param state  the State in which the cache value resides
1516      * @param name   the name of the cache variable
1517      * @return bool  whether the cache variable value is valid or not
1518      * @throws ComponentHasNoSystem if this Component has not been added to a
1519      *         System (i.e., if initSystem has not been called)
1520      */
isCacheVariableValid(const SimTK::State & state,const std::string & name)1521     bool isCacheVariableValid(const SimTK::State& state, const std::string& name) const
1522     {
1523         // Must have already called initSystem.
1524         OPENSIM_THROW_IF_FRMOBJ(!hasSystem(), ComponentHasNoSystem);
1525 
1526         std::map<std::string, CacheInfo>::const_iterator it;
1527         it = _namedCacheVariableInfo.find(name);
1528 
1529         if(it != _namedCacheVariableInfo.end()) {
1530             SimTK::CacheEntryIndex ceIndex = it->second.index;
1531             return getDefaultSubsystem().isCacheValueRealized(state, ceIndex);
1532         }
1533         else{
1534             std::stringstream msg;
1535             msg << "Component::isCacheVariableValid: ERR- name not found.\n "
1536                 << "for component '"<< getName() << "' of type "
1537                 << getConcreteClassName();
1538             throw Exception(msg.str(),__FILE__,__LINE__);
1539         }
1540     }
1541 
1542     /**
1543      * %Set cache variable value allocated by this Component by name. All cache
1544      * entries are lazily evaluated (on a need basis) so a set also marks the
1545      * cache as valid.
1546      *
1547      * @param state  the State in which to store the new value
1548      * @param name   the name of the cache variable
1549      * @param value  the new value for this cache variable
1550      * @throws ComponentHasNoSystem if this Component has not been added to a
1551      *         System (i.e., if initSystem has not been called)
1552      */
1553     template<typename T> void
setCacheVariableValue(const SimTK::State & state,const std::string & name,const T & value)1554     setCacheVariableValue(const SimTK::State& state, const std::string& name,
1555                      const T& value) const
1556     {
1557         // Must have already called initSystem.
1558         OPENSIM_THROW_IF_FRMOBJ(!hasSystem(), ComponentHasNoSystem);
1559 
1560         std::map<std::string, CacheInfo>::const_iterator it;
1561         it = _namedCacheVariableInfo.find(name);
1562 
1563         if(it != _namedCacheVariableInfo.end()) {
1564             SimTK::CacheEntryIndex ceIndex = it->second.index;
1565             SimTK::Value<T>::downcast(
1566                 getDefaultSubsystem().updCacheEntry( state, ceIndex)).upd()
1567                 = value;
1568             getDefaultSubsystem().markCacheValueRealized(state, ceIndex);
1569         }
1570         else{
1571             std::stringstream msg;
1572             msg << "Component::setCacheVariable: ERR- name not found.\n "
1573                 << "for component '"<< getName() << "' of type "
1574                 << getConcreteClassName();
1575             throw Exception(msg.str(),__FILE__,__LINE__);
1576         }
1577     }
1578     // End of Model Component State Accessors.
1579     //@}
1580 
1581     /** @name Print information to the console */
1582     /// @{
1583     /** List all subcomponents by name and recurse into these components to
1584     list their subcomponents, and so on.                                      */
1585     void printSubcomponentInfo() const;
1586 
1587     /** List all the Sockets of this component and whether or not they are
1588     connected. Also list the connectee paths for sockets that are connected. */
1589     void printSocketInfo() const;
1590 
1591     /** List all the inputs of this component and whether or not they are
1592     connected. Also list the (desired) connectee paths for the inputs.       */
1593     void printInputInfo() const;
1594 
1595     template<typename C>
printSubcomponentInfo()1596     void printSubcomponentInfo() const {
1597 
1598         ComponentList<const C> compList = getComponentList<C>();
1599 
1600         // Step through compList once to determine if there are any
1601         // subcomponents and to find the longest concrete class name.
1602         const std::string concreteClassName = this->getConcreteClassName();
1603         unsigned numSubcomponents = 0;
1604         size_t maxlen = concreteClassName.length();
1605         for (const C& thisComp : compList) {
1606             ++numSubcomponents;
1607             auto len = thisComp.getConcreteClassName().length();
1608             maxlen = std::max(maxlen, len);
1609         }
1610 
1611         if (numSubcomponents == 0) {
1612             std::cout << "Component '" << getName()
1613                       << "' has no subcomponents." << std::endl;
1614             return;
1615         }
1616         maxlen += 4; //padding
1617 
1618         std::string className = SimTK::NiceTypeName<C>::namestr();
1619         // Remove "OpenSim::", etc. if it exists.
1620         const std::size_t colonPos = className.rfind(":");
1621         if (colonPos != std::string::npos)
1622             className = className.substr(colonPos+1,
1623                                          className.length()-colonPos);
1624 
1625         std::cout << "Class name and absolute path name for descendants of '"
1626                   << getName() << "' that are of type " << className << ":\n"
1627                   << std::endl;
1628 
1629         std::cout << std::string(maxlen-concreteClassName.length(), ' ')
1630                   << "[" << concreteClassName << "]"
1631                   << "  " << getAbsolutePathString() << std::endl;
1632 
1633         // Step through compList again to print.
1634         for (const C& thisComp : compList) {
1635             const std::string thisClass = thisComp.getConcreteClassName();
1636             std::cout << std::string(maxlen-thisClass.length(), ' ') << "["
1637                       << thisClass << "]  ";
1638             auto path = thisComp.getAbsolutePath();
1639             std::cout << std::string((path.getNumPathLevels() - 1) * 4, ' ')
1640                       << "/" << path.getComponentName() << std::endl;
1641         }
1642         std::cout << std::endl;
1643     }
1644 
1645     /** Print outputs of this component and optionally, those of all
1646     subcomponents.                                                            */
1647     void printOutputInfo(const bool includeDescendants = true) const;
1648     /// @}
1649 
1650 protected:
1651     class StateVariable;
1652     //template <class T> friend class ComponentSet;
1653     // Give the ComponentMeasure access to the realize() methods.
1654     template <class T> friend class ComponentMeasure;
1655 
1656 #ifndef SWIG
1657     /// @class MemberSubcomponentIndex
1658     /// Unique integer type for local member subcomponent indexing
1659     SimTK_DEFINE_UNIQUE_INDEX_TYPE(MemberSubcomponentIndex);
1660 
1661     /** Construct a subcomponent as a data member of this Component. All Component
1662         interface calls are automatically invoked on its subcomponents. */
1663     template<class C=Component>
constructSubcomponent(const std::string & name)1664     MemberSubcomponentIndex constructSubcomponent(const std::string& name) {
1665         C* component = new C();
1666         component->setName(name);
1667         component->setOwner(*this);
1668         _memberSubcomponents.push_back(SimTK::ClonePtr<Component>(component));
1669         return MemberSubcomponentIndex(_memberSubcomponents.size()-1);
1670     }
1671     template<class C = Component>
getMemberSubcomponent(MemberSubcomponentIndex ix)1672     const C& getMemberSubcomponent(MemberSubcomponentIndex ix) const {
1673         const C* comp = dynamic_cast<const C*>(_memberSubcomponents[ix].get());
1674         if(comp)
1675             return *comp;
1676 
1677         throw Exception("Component::getMemberSubcomponent() - Incorrect type requested.");
1678     }
1679     template<class C = Component>
updMemberSubcomponent(MemberSubcomponentIndex ix)1680     C& updMemberSubcomponent(MemberSubcomponentIndex ix) {
1681         C* comp = dynamic_cast<C*>(_memberSubcomponents[ix].upd());
1682         if (comp)
1683             return *comp;
1684 
1685         throw Exception("Component::updMemberSubcomponent() - Incorrect type requested.");
1686     }
1687 #endif //SWIG
1688 
1689     /**
1690     * Adopt a component as a subcomponent of this Component. Component
1691     * methods (e.g. addToSystem(), initStateFromProperties(), ...) are
1692     * automatically invoked on subcomponents when called on this Component.
1693     * Realization is also performed automatically on subcomponents. All
1694     * subcomponents are owned, therefore this Component also takes ownership.
1695     */
1696     void adoptSubcomponent(Component* subcomponent);
1697 
1698     /** Get the number of Subcomponents immediately owned by this Component */
getNumImmediateSubcomponents()1699     size_t getNumImmediateSubcomponents() const {
1700         return getNumMemberSubcomponents() + getNumPropertySubcomponents()
1701             + getNumAdoptedSubcomponents();
1702     }
1703 
1704     /** Get the number of Subcomponents that are data members of this Component */
1705     size_t getNumMemberSubcomponents() const;
1706     /** Get the number of Subcomponents that are properties of this Component */
1707     size_t getNumPropertySubcomponents() const;
1708     /** Get the number of Subcomponents adopted by this Component */
1709     size_t getNumAdoptedSubcomponents() const;
1710 
1711     /** Access this Component's immediate subcomponents (not those owned by
1712         subcomponents) */
1713     std::vector<SimTK::ReferencePtr<const Component>>
1714         getImmediateSubcomponents() const;
1715 
1716     /** @name  Component Extension Interface
1717     The interface ensures that deserialization, resolution of inter-connections,
1718     and handling of dependencies are performed systematically and prior to
1719     system creation, followed by allocation of necessary System resources. These
1720     methods are virtual and may be implemented by subclasses of
1721     Components.
1722 
1723     @note Every implementation of virtual extend method xxx(args) must begin
1724     with the line "Super::extend<xxx>(args);" to ensure that the parent class
1725     is called before the child class method.
1726 
1727     The base class implementations ensures that the corresponding calls are made
1728     to any subcomponents which are owned by this Component. Ownership is
1729     established by the subcomponent being a data member (not serialized), a
1730     property (serialized), or created and adopted based on other settings
1731     or options that arise from the properties. For example, a Model (Component)
1732     may have to split a body and add a Weld constraint to handle a closed
1733     loop specified by Joints that are properties of the Model. The new Body and
1734     Weld (components) are created and adopted as part of connecting the model to
1735     form a valid multibody tree.
1736 
1737     So assuming that your concrete %Component and all intermediate classes from
1738     which it derives properly follow the requirement of calling the Super class
1739     method first, the order of operations enforced here for a call to a single
1740     method will be
1741       -# %Component base class computations
1742       -# calls to that same method for intermediate %Component-derived
1743          objects' computations, in order down from %Component, and
1744       -# call to that method for the bottom-level concrete class.
1745       -# finally calls to that same method for \e all subcomponents
1746     You should consider this ordering when designing a %Component.  **/
1747 
1748     ///@{
1749 
1750     /** Perform any secondary operations, e.g. to investigate the component or
1751     to insert it into a particular internal list (for grouping), after adding
1752     the subcomponent to this component. This is intended primarily for composites
1753     like Model to have more control over the handling of a component being added
1754     to it.
1755 
1756     If you override this method, be sure to invoke the base class method first,
1757     using code like this :
1758     @code
1759     void MyComponent::extendAddComponent(Component* subcomponent) {
1760         Super::extendAddComponent(); // invoke parent class method
1761         // ... your code goes here
1762         // ... initialize any internal data structures
1763     }
1764     @endcode   */
extendAddComponent(Component * subcomponent)1765     virtual void extendAddComponent(Component* subcomponent) {};
1766 
1767     /** Perform any time-invariant calculations, data structure initializations,
1768     or other configuration based on the component's properties to form a
1769     functioning (but not yet connected) component. For example, each property
1770     should be checked to ensure that its value is within an acceptable range.
1771     When this method returns, the component will be marked as being up-to-date
1772     with its properties. Do not perform any configuration that depends on the
1773     SimTK::MultibodySystem; it is not available at this point.
1774 
1775     If you override this method, be sure to invoke the base class method first,
1776     using code like this:
1777         @code
1778         void MyComponent::extendFinalizeFromProperties() {
1779             Super::extendFinalizeFromProperties(); // invoke parent class method
1780             // ... your code goes here
1781             // ... catch invalid property values
1782             // ... initialize any internal data structures
1783         }
1784         @endcode   */
extendFinalizeFromProperties()1785     virtual void extendFinalizeFromProperties() {};
1786 
1787     /** Perform any necessary initializations required to connect the component
1788     (and it subcomponents) to other components and mark the connection status.
1789     Provides a check for error conditions. connect() is invoked on all components
1790     to form a directed acyclic graph of the multibody system, prior to creating the
1791     Simbody MultibodySystem to represent it computationally. It may also be invoked
1792     at times just for its error-checking side effects.
1793 
1794     The "root" Component argument is the root node of the directed graph composed
1795     of all the subcomponents (and their subcomponents and so on ...) and their
1796     interconnections. This should yield a fully connected root component. For
1797     ModelComponents this is the Model component. But a Model can be connected to
1798     an environment or world component with several other models, by choosing the
1799     environment/world as the root.
1800 
1801     If you override this method, be sure to invoke the base class method first,
1802     using code like this:
1803     @code
1804     void MyComponent::extendFinalizeConnections(Component& root) {
1805         Super::extendFinalizeConnections(root); // invoke parent class method
1806         // ... your code goes here
1807     }
1808     @endcode   */
extendFinalizeConnections(Component & root)1809     virtual void extendFinalizeConnections(Component& root) {};
1810 
1811     /** Build the tree of Components from this component through its descendants.
1812     This method is invoked whenever a ComponentList<C> is requested. Note that
1813     all components must have been added to the model (or its subcomponents),
1814     otherwise it will not be included in the tree and will not be found for
1815     iteration or for connection. The implementation populates the _nextComponent
1816     ReferencePtr with a pointer to the next Component in tree pre-order traversal.
1817 
1818     @throws ComponentIsRootWithNoSubcomponents if the Component is the root and
1819             yet has no subcomponents.
1820     */
1821     void initComponentTreeTraversal(const Component &root) const;
1822 
1823     ///@cond
1824     /** Opportunity to remove connection-related information.
1825     If you override this method, be sure to invoke the base class method first,
1826         using code like this:
1827         @code
1828         void MyComponent::disconnect(Component& root) {
1829         // disconnect your subcomponents and your Super first
1830         Super::extendDisconnect();
1831             //your code to wipe out your connection-related information
1832     }
1833     @endcode  */
1834     //virtual void extendDisconnect() {};
1835     ///@endcond
1836 
1837     /** Add appropriate Simbody elements (if needed) to the System
1838     corresponding to this component and specify needed state resources.
1839     extendAddToSystem() is called when the Simbody System is being created to
1840     represent a completed system (model) for computation. That is, connect()
1841     will already have been invoked on all components before any addToSystem()
1842     call is made. Helper methods for adding modeling options, state variables
1843     and their derivatives, discrete variables, and cache entries are available
1844     and can be called within extendAddToSystem() only.
1845 
1846     Note that this method is const; you may not modify your model component
1847     or the containing model during this call. Any modifications you need should
1848     instead be performed in finalizeFromProperties() or at the latest connect(),
1849     which are non-const. The only exception is that you may need to record access
1850     information for resources you create in the \a system, such as an index number.
1851     For most Components, OpenSim base classes either provide convenience methods
1852     or handle indices automatically. Otherwise, you must declare indices as mutable
1853     data members so that you can set them here.
1854 
1855     If you override this method, be sure to invoke the base class method at the
1856     beginning, using code like this:
1857     @code
1858     void MyComponent::extendAddToSystem(SimTK::MultibodySystem& system) const {
1859         // Perform any additions to the system required by your Super
1860         Super::extendAddToSystem(system);
1861         // ... your code goes here
1862     }
1863     @endcode
1864 
1865     This method assumes that this Component's addToSystem will be invoked before
1866     its subcomponents. If you need your subcomponents to be added to the system,
1867     first (e.g. require of a Force to be anchored to a SimTK::MobilizedBody
1868     specified by subcomponents) then you must implement:
1869         extendAddToSystemAfterSubcomponents().
1870     It is possible to implement both method to add system elements before and then
1871     after your subcomponents have added themselves. Caution is required that
1872     Simbody elements are not added twice especially when order is unimportant.
1873 
1874     @param[in,out] system   The MultibodySystem being added to.
1875 
1876     @see addModelingOption(), addStateVariable(), addDiscreteVariables(),
1877          addCacheVariable() **/
extendAddToSystem(SimTK::MultibodySystem & system)1878     virtual void extendAddToSystem(SimTK::MultibodySystem& system) const {};
1879 
1880     /** Add appropriate Simbody elements (if needed) to the System after your
1881     component's subcomponents have had a chance to add themselves to the system.
1882 
1883     If you override this method, be sure to invoke the base class method at the
1884     beginning, using code like this:
1885     @code
1886     void MyComponent::
1887         extendAddToSystemAfterSubcomponents(SimTK::MultibodySystem& system) const {
1888         // Perform any additions to the system required by your Super
1889         Super::extendAddToSystemAfterSubcomponents(system);
1890         // ... your code goes here
1891     }
1892     @endcode
1893 
1894     @param[in,out] system   The MultibodySystem being added to.
1895 
1896     @see extendAddToSystem() **/
1897     virtual void
extendAddToSystemAfterSubcomponents(SimTK::MultibodySystem & system)1898         extendAddToSystemAfterSubcomponents(SimTK::MultibodySystem& system)
1899                                                                       const {};
1900 
1901     /** Transfer property values or other state-independent initial values
1902     into this component's state variables in the passed-in \a state argument.
1903     This is called after a SimTK::System and State have been created for the
1904     Model (that is, after extendAddToSystem() has been called on all components).
1905     You should override this method if your component has properties
1906     (serializable values) that can affect initial values for your state
1907     variables. You can also perform any other state-independent calculations
1908     here that result in state initial conditions.
1909 
1910     If you override this method, be sure to invoke the base class method first,
1911     using code like this:
1912     @code
1913     void MyComponent::extendInitStateFromProperties(SimTK::State& state) const {
1914         Super::extendInitStateFromProperties(state); // invoke parent class method
1915         // ... your code goes here
1916     }
1917     @endcode
1918 
1919     @param      state
1920         The state that will receive the new initial conditions.
1921 
1922     @see extendSetPropertiesFromState() **/
extendInitStateFromProperties(SimTK::State & state)1923     virtual void extendInitStateFromProperties(SimTK::State& state) const {};
1924 
1925     /** Update this component's property values to match the specified State,
1926     if the component has created any state variable that is intended to
1927     correspond to a property. Thus, state variable values can persist as part
1928     of the model component and be serialized as a property.
1929 
1930     If you override this method, be sure to invoke the base class method first,
1931     using code like this:
1932     @code
1933     void MyComponent::extendSetPropertiesFromState(const SimTK::State& state) {
1934         Super::extendSetPropertiesFromState(state); // invoke parent class method
1935         // ... your code goes here
1936     }
1937     @endcode
1938 
1939     @param      state
1940         The State from which values may be extracted to set persistent
1941         property values.
1942 
1943     @see extendInitStateFromProperties() **/
extendSetPropertiesFromState(const SimTK::State & state)1944     virtual void extendSetPropertiesFromState(const SimTK::State& state) {};
1945 
1946     /** If a model component has allocated any continuous state variables
1947     using the addStateVariable() method, then %computeStateVariableDerivatives()
1948     must be implemented to provide time derivatives for those states.
1949     Override to set the derivatives of state variables added to the system
1950     by this component. (also see extendAddToSystem()). If the component adds states
1951     and computeStateVariableDerivatives is not implemented by the component,
1952     an exception is thrown when the system tries to evaluate its derivatives.
1953 
1954     Implement like this:
1955     @code
1956     void computeStateVariableDerivatives(const SimTK::State& state) const {
1957 
1958         // Let the parent class set the derivative values for the
1959         // the state variables that it added.
1960         Super::computeStateVariableDerivatives(state)
1961 
1962         // Compute derivative values for states allocated by this component
1963         // as a function of the state.
1964         double deriv = ...
1965 
1966         // Then set the derivative value by state variable name
1967         setStateVariableDerivativeValue(state, "<state_variable_name>", deriv);
1968     }
1969     @endcode
1970 
1971     For subclasses, it is highly recommended that you first call
1972     Super::computeStateVariableDerivatives(state) to preserve the derivative
1973     computation of the parent class and to only specify the derivatives of the state
1974     variables added by name. One does have the option to override all the derivative
1975     values for the parent by accessing the derivatives by their state variable name.
1976     This is necessary, for example, if a newly added state variable is coupled to the
1977     dynamics (derivatives) of the states variables that were added by the parent.
1978     **/
1979     virtual void computeStateVariableDerivatives(const SimTK::State& s) const;
1980 
1981     /**
1982      * %Set the derivative of a state variable by name when computed inside of
1983      * this Component's computeStateVariableDerivatives() method.
1984      *
1985      * @param state  the State for which to set the value
1986      * @param name   the name of the state variable
1987      * @param deriv  the derivative value to set
1988      */
1989     void setStateVariableDerivativeValue(const SimTK::State& state,
1990                             const std::string& name, double deriv) const;
1991 
1992 
1993     // End of Component Extension Interface (protected virtuals).
1994     ///@}
1995 
1996     /** @name           Component Advanced Interface
1997     You probably won't need to override methods in this section. These provide
1998     a way for you to perform computations ("realizations") that must be
1999     scheduled in carefully-ordered stages as described in the class description
2000     above. The typical operation will be that the given SimTK::State provides
2001     you with the inputs you need for your computation, which you will then
2002     write into some element of the state cache, where later computations can
2003     pick it up.
2004 
2005     @note Once again it is crucial that, if you override a method here,
2006     you invoke the superclass method as the <em>first line</em> in your
2007     implementation, via a call like "Super::extendRealizePosition(state);". This
2008     will ensure that all necessary base class computations are performed, and
2009     that subcomponents are handled properly.
2010 
2011     @warning Currently the realize() methods here are invoked early in the
2012     sequence of realizations at a given stage, meaning that you will not be
2013     able to access other computations at that same stage.
2014     @bug Should defer calls to these until at least kinematic realizations
2015     at the same stage have been performed.
2016 
2017     @see Simbody documentation for more information about realization.
2018     **/
2019     //@{
2020     /** Obtain state resources that are needed unconditionally, and perform
2021     computations that depend only on the system topology. **/
2022     virtual void extendRealizeTopology(SimTK::State& state) const;
2023     /** Obtain and name state resources (like state variables allocated by
2024     an underlying Simbody component) that may be needed, depending on modeling
2025     options. Also, perform any computations that depend only on topology and
2026     selected modeling options. **/
2027     virtual void extendRealizeModel(SimTK::State& state) const;
2028     /** Perform computations that depend only on instance variables, like
2029     lengths and masses. **/
2030     virtual void extendRealizeInstance(const SimTK::State& state) const;
2031     /** Perform computations that depend only on time and earlier stages. **/
2032     virtual void extendRealizeTime(const SimTK::State& state) const;
2033     /** Perform computations that depend only on position-level state
2034     variables and computations performed in earlier stages (including time). **/
2035     virtual void extendRealizePosition(const SimTK::State& state) const;
2036     /** Perform computations that depend only on velocity-level state
2037     variables and computations performed in earlier stages (including position,
2038     and time). **/
2039     virtual void extendRealizeVelocity(const SimTK::State& state) const;
2040     /** Perform computations (typically forces) that may depend on
2041     dynamics-stage state variables, and on computations performed in earlier
2042     stages (including velocity, position, and time), but not on other forces,
2043     accelerations, constraint multipliers, or reaction forces. **/
2044     virtual void extendRealizeDynamics(const SimTK::State& state) const;
2045     /** Perform computations that may depend on applied forces. **/
2046     virtual void extendRealizeAcceleration(const SimTK::State& state) const;
2047     /** Perform computations that may depend on anything but are only used
2048     for reporting and cannot affect subsequent simulation behavior. **/
2049     virtual void extendRealizeReport(const SimTK::State& state) const;
2050     //@} end of Component Advanced Interface
2051 
2052 
2053     /** @name     Component System Creation and Access Methods
2054      * These methods support implementing concrete Components. Add methods
2055      * can only be called inside of extendAddToSystem() and are useful for creating
2056      * the underlying SimTK::System level variables that are used for computing
2057      * values of interest.
2058      * @warning Accessors for System indices are intended for component internal use only.
2059      **/
2060 
2061     //@{
2062 
2063     /** Add a modeling option (integer flag stored in the State) for use by
2064     this Component. Each modeling option is identified by its own
2065     \a optionName, specified here. Modeling options enable the model
2066     component to be configured differently in order to represent different
2067     operating modes. For example, if two modes of operation are necessary (mode
2068     off and mode on) then specify optionName, "mode" with maxFlagValue = 1.
2069     Subsequent gets will return 0 or 1 and set will only accept 0 and 1 as
2070     acceptable values. Changing the value of a model option invalidates
2071     Stage::Instance and above in the State, meaning all calculations involving
2072     time, positions, velocity, and forces are invalidated. **/
2073     void addModelingOption(const std::string&  optionName,
2074                            int                 maxFlagValue) const;
2075 
2076 
2077     /** Add a continuous system state variable belonging to this Component,
2078     and assign a name by which to refer to it. Changing the value of this state
2079     variable will automatically invalidate everything at and above its
2080     \a invalidatesStage, which is normally Stage::Dynamics meaning that there
2081     are forces that depend on this variable. If you define one or more
2082     of these variables you must also override computeStateVariableDerivatives()
2083     to provide time derivatives for them. Note, all corresponding system
2084     indices are automatically determined using this interface. As an advanced
2085     option you may choose to hide the state variable from being accessed outside
2086     of this component, in which case it is considered to be "hidden".
2087     You may also want to create an Output for this state variable; see
2088     #OpenSim_DECLARE_OUTPUT_FOR_STATE_VARIABLE for more information. Reporters
2089     should use such an Output to get the StateVariable's value (instead of using
2090     getStateVariableValue()).
2091 
2092     @param[in] stateVariableName     string value to access variable by name
2093     @param[in] invalidatesStage      the system realization stage that is
2094                                      invalidated when variable value is changed
2095     @param[in] isHidden              flag (bool) to optionally hide this state
2096                                      variable from being accessed outside this
2097                                      component as an Output
2098     */
2099     void addStateVariable(const std::string&  stateVariableName,
2100          const SimTK::Stage& invalidatesStage=SimTK::Stage::Dynamics,
2101          bool isHidden = false) const;
2102 
2103     /** The above method provides a convenient interface to this method, which
2104     automatically creates an 'AddedStateVariable' and allocates resources in the
2105     SimTK::State for this variable.  This interface allows the creator to
2106     add/expose state variables that are allocated by underlying Simbody
2107     components and specify how the state variable value is accessed by
2108     implementing a concrete StateVariable and adding it to the component using
2109     this method.
2110     You may also want to create an Output for this state variable; see
2111     #OpenSim_DECLARE_OUTPUT_FOR_STATE_VARIABLE for more information. Reporters
2112     should use such an Output to get the StateVariable's value (instead of
2113     using getStateVariableValue()).
2114     */
2115     void addStateVariable(Component::StateVariable*  stateVariable) const;
2116 
2117     /** Add a system discrete variable belonging to this Component, give
2118     it a name by which it can be referenced, and declare the lowest Stage that
2119     should be invalidated if this variable's value is changed. **/
2120     void addDiscreteVariable(const std::string& discreteVariableName,
2121                              SimTK::Stage       invalidatesStage) const;
2122 
2123     /** Add a state cache entry belonging to this Component to hold
2124     calculated values that must be automatically invalidated when certain
2125     state values change. Cache entries contain values whose computations depend
2126     on state variables and provide convenience and/or efficiency by holding on
2127     to them in memory (cache) to avoid recomputation. Once the state changes,
2128     the cache values automatically become invalid and has to be
2129     recomputed based on the current state before it can be referenced again.
2130     Any attempt to reference an invalid cache entry results in an exception
2131     being thrown.
2132 
2133     Cache entry validity is managed by computation Stage, rather than by
2134     dependence on individual state variables. Changing a variables whose
2135     "invalidates" stage is the same or lower as the one specified as the
2136     "depends on" stage here cause the cache entry to be invalidated. For
2137     example, a body's momentum, which is dependent on position and velocity
2138     states, should have Stage::Velocity as its \a dependsOnStage. Then if a
2139     Velocity stage variable or lower (e.g. Position stage) changes, then the
2140     cache is invalidated. But, if a Dynamics stage variable (or above) is
2141     changed, the velocity remains valid so the cache entry does not have to be
2142     recomputed.
2143 
2144     @param[in]      cacheVariableName
2145         The name you are assigning to this cache entry. Must be unique within
2146         this model component.
2147     @param[in]      variablePrototype
2148         An object defining the type of value, and a default value of that type,
2149         to be held in this cache entry. Can be a simple int or an elaborate
2150         class, as long as it has deep copy semantics.
2151     @param[in]      dependsOnStage
2152         This is the highest computational stage on which this cache entry's
2153         value computation depends. State changes at this level or lower will
2154         invalidate the cache entry. **/
2155     template <class T> void
addCacheVariable(const std::string & cacheVariableName,const T & variablePrototype,SimTK::Stage dependsOnStage)2156     addCacheVariable(const std::string&     cacheVariableName,
2157                      const T&               variablePrototype,
2158                      SimTK::Stage           dependsOnStage) const
2159     {
2160         // Note, cache index is invalid until the actual allocation occurs
2161         // during realizeTopology.
2162         _namedCacheVariableInfo[cacheVariableName] =
2163             CacheInfo(new SimTK::Value<T>(variablePrototype), dependsOnStage);
2164     }
2165 
2166 
2167     /**
2168      * Get writable reference to the MultibodySystem that this component is
2169      * connected to.
2170      */
2171     SimTK::MultibodySystem& updSystem() const;
2172 
2173     /** Get the index of a Component's continuous state variable in the Subsystem for
2174         allocations. This method is intended for derived Components that may need direct
2175         access to its underlying Subsystem.*/
2176     const int getStateIndex(const std::string& name) const;
2177 
2178    /**
2179      * Get the System Index of a state variable allocated by this Component.
2180      * Returns an InvalidIndex if no state variable with the name provided is
2181      * found.
2182      * @param stateVariableName   the name of the state variable
2183      */
2184     SimTK::SystemYIndex
2185         getStateVariableSystemIndex(const std::string& stateVariableName) const;
2186 
2187    /**
2188      * Get the index of a Component's discrete variable in the Subsystem for
2189      * allocations. This method is intended for derived Components that may need
2190      * direct access to its underlying Subsystem.
2191      */
2192     const SimTK::DiscreteVariableIndex
2193     getDiscreteVariableIndex(const std::string& name) const;
2194 
2195     /** Get the index of a Component's cache variable in the Subsystem for allocations.
2196         This method is intended for derived Components that may need direct access
2197         to its underlying Subsystem.*/
2198     const SimTK::CacheEntryIndex
2199     getCacheVariableIndex(const std::string& name) const;
2200 
2201     // End of System Creation and Access Methods.
2202     //@}
2203 
2204 public:
2205 
2206     /** Find a Component to which this Component is an ancestor---in other
2207     words, a Component that is directly owned by this Component or is owned
2208     by one of its sub-components, sub-sub-components, etc. The Component can
2209     be found by type (by specifying a template argument) and either path or
2210     name.
2211 
2212     Here is an example of searching for a component of any type with the name
2213     'elbow_flexion':
2214     @code{.cpp}
2215     if (const Component* found =
2216             model.findComponent(ComponentPath("elbow_flexion"))) {
2217         std::cout << found.getName() << std::endl;
2218     }
2219     @endcode
2220 
2221     Here, we require that 'elbow_flexion' is of type Coordinate.
2222     @code{.cpp}
2223     if (const Coordinate* found =
2224             model.findComponent<Coordinate>(ComponentPath("elbow_flexion"))) {
2225         std::cout << "Coordinate " << found.getName() << std::endl;
2226     }
2227     @endcode
2228 
2229     The search can be sped up considerably if the path or even partial path
2230     name is known. For example, "forearm/elbow/elbow_flexion" will find
2231     the Coordinate component of the elbow joint that connects the forearm body
2232     in linear time (linear search for name at each component level). Whereas
2233     supplying "elbow_flexion" requires a tree search. Returns nullptr (None in
2234     Python, empty array in Matlab) if Component of that specified name cannot
2235     be found.
2236 
2237     NOTE: If the component name is ambiguous, an exception is thrown. To
2238     disambiguate, more information must be provided, such as the template
2239     argument to specify the type and/or a path rather than just the name. */
2240     template<class C = Component>
findComponent(const ComponentPath & pathToFind)2241     const C* findComponent(const ComponentPath& pathToFind) const {
2242         const std::string name = pathToFind.toString();
2243         std::string msg = getConcreteClassName() + "'" + getName() +
2244                           "'::findComponent() ";
2245         if (name.empty()) {
2246             msg += "cannot find a nameless subcomponent.";
2247             throw Exception(msg);
2248         }
2249 
2250         ComponentPath thisAbsPath = getAbsolutePath();
2251 
2252         const C* found = NULL;
2253         if (thisAbsPath == pathToFind) {
2254             found = dynamic_cast<const C*>(this);
2255             if (found)
2256                 return found;
2257         }
2258 
2259         std::vector<const C*> foundCs;
2260 
2261         std::string subname = pathToFind.getComponentName();
2262         std::string thisName = this->getName();
2263         if (thisName == subname) {
2264             if ( (found = dynamic_cast<const C*>(this)) )
2265                 foundCs.push_back(found);
2266         }
2267 
2268         ComponentList<const C> compsList = this->template getComponentList<C>();
2269 
2270         for (const C& comp : compsList) {
2271             // if a child of this Component, one should not need
2272             // to specify this Component's absolute path name
2273             ComponentPath compAbsPath = comp.getAbsolutePath();
2274             ComponentPath thisAbsPathPlusSubname = getAbsolutePath();
2275             thisAbsPathPlusSubname.pushBack(subname);
2276             if (compAbsPath == thisAbsPathPlusSubname) {
2277                 foundCs.push_back(&comp);
2278                 break;
2279             }
2280 
2281             // otherwise, we just have a type and name match
2282             // which we may need to support for compatibility with older models
2283             // where only names were used (not path or type)
2284             // TODO replace with an exception -aseth
2285             std::string compName = comp.getName();
2286             if (compName == subname) {
2287                 foundCs.push_back(&comp);
2288                 // TODO Revisit why the exact match isn't found when
2289                 // when what appears to be the complete path.
2290                 if (comp.getDebugLevel() > 0) {
2291                     std::string details = msg + " Found '" + compAbsPath.toString() +
2292                         "' as a match for:\n Component '" + name + "' of type " +
2293                         comp.getConcreteClassName() + ", but it "
2294                         "is not on specified path.\n";
2295                     //throw Exception(details, __FILE__, __LINE__);
2296                     std::cout << details << std::endl;
2297                 }
2298             }
2299         }
2300 
2301         if (foundCs.size() == 1) {
2302             //unique type and name match!
2303             return foundCs[0];
2304         }
2305 
2306         // Only error cases remain
2307         // too many components of the right type with the same name
2308         if (foundCs.size() > 1) {
2309             msg += "Found multiple '" + name + "'s of type " +
2310                 foundCs[0]->getConcreteClassName() + ".";
2311             throw Exception(msg, __FILE__, __LINE__);
2312         }
2313 
2314         // Not found
2315         return nullptr;
2316     }
2317 
2318     /** Same as findComponent(const ComponentPath&), but accepting a string (a
2319     path or just a name) as input. */
2320     template<class C = Component>
findComponent(const std::string & pathToFind)2321     const C* findComponent(const std::string& pathToFind) const {
2322         return findComponent<C>(ComponentPath(pathToFind));
2323     }
2324 
2325 protected:
2326 
2327     template<class C>
traversePathToComponent(ComponentPath path)2328     const C* traversePathToComponent(ComponentPath path) const
2329     {
2330         // Get rid of all the ".."'s that are not at the front of the path.
2331         path.trimDotAndDotDotElements();
2332 
2333         // Move up either to the root component or just enough to resolve all
2334         // the ".."'s.
2335         size_t iPathEltStart = 0u;
2336         const Component* current = this;
2337         if (path.isAbsolute()) {
2338             current = &current->getRoot();
2339         } else {
2340             while (iPathEltStart < path.getNumPathLevels() &&
2341                     path.getSubcomponentNameAtLevel(iPathEltStart) == "..") {
2342                 // The path sends us up farther than the root.
2343                 if (!current->hasOwner()) return nullptr;
2344                 current = &current->getOwner();
2345                 ++iPathEltStart;
2346             }
2347         }
2348 
2349         using RefComp = SimTK::ReferencePtr<const Component>;
2350 
2351         // Skip over the root component name.
2352         for (size_t i = iPathEltStart; i < path.getNumPathLevels(); ++i) {
2353             // At this depth in the tree, is there a component whose name
2354             // matches the corresponding path element?
2355             const auto& currentPathElement =
2356                 path.getSubcomponentNameAtLevel(i);
2357             const auto& currentSubs = current->getImmediateSubcomponents();
2358             const auto it = std::find_if(currentSubs.begin(), currentSubs.end(),
2359                     [currentPathElement](const RefComp& sub)
2360                     { return sub->getName() == currentPathElement; });
2361             if (it != currentSubs.end())
2362                 current = it->get();
2363             else
2364                 return nullptr;
2365         }
2366         if (const C* comp = dynamic_cast<const C*>(current))
2367             return comp;
2368         return nullptr;
2369     }
2370 
2371 public:
2372 #ifndef SWIG // StateVariable is protected.
2373     /**
2374      * Get a StateVariable anywhere in the Component tree, given a
2375      * StateVariable path. The StateVariable doesn't need to be in a
2376      * subcomponent of this compoonent; it could be located in a different
2377      * branch of the Component tree (in such a case, the specified path might
2378      * begin with "../").
2379      * This returns nullptr if a StateVariable does not exist at the specified
2380      * path or if the path is invalid.
2381      * @throws ComponentHasNoSystem if this Component has not been added to a
2382      *         System (i.e., if initSystem has not been called)
2383      */
2384     const StateVariable* traverseToStateVariable(
2385             const std::string& pathName) const;
2386 #endif
2387 
2388     /// @name Access to the owning component (advanced).
2389     /// @{
2390     /** Access the owner of this Component.
2391      * An exception is thrown if the %Component has no owner; in this case, the
2392      * component is the root component, or is orphaned.
2393      * @see hasOwner() */
2394     const Component& getOwner() const;
2395 
2396     /** (For advanced users) Check if this %Component has an owner.
2397      * A component may not have an owner if it:
2398      * (1) is the root component, or
2399      * (2) has not been added to another component */
2400     bool hasOwner() const;
2401 
2402     /** Obtain the root %Component, which is this component if it is orphaned.
2403      */
2404     const Component& getRoot() const;
2405 
2406 protected:
2407     /** %Set this %Component's reference to its owning %Component */
2408     void setOwner(const Component& owner);
2409 
2410     /// @}
2411 
2412     /** @name Internal methods for constructing Sockets, Outputs, Inputs
2413      * To declare Socket%s, Output%s, and Input%s for your component,
2414      * use the following macros within your class declaration (ideally at
2415      * the top near property declarations):
2416      *
2417      *  - #OpenSim_DECLARE_SOCKET
2418      *  - #OpenSim_DECLARE_OUTPUT
2419      *  - #OpenSim_DECLARE_LIST_OUTPUT
2420      *  - #OpenSim_DECLARE_OUTPUT_FOR_STATE_VARIABLE
2421      *  - #OpenSim_DECLARE_INPUT
2422      *  - #OpenSim_DECLARE_LIST_INPUT
2423      *
2424      * The methods below are used in those macros, and you should not use these
2425      * methods yourself.
2426      */
2427     /// @{
2428     /**
2429     * Construct a specialized Socket for this Component's dependence on
2430     * another Component. It serves as a placeholder for the Component and its
2431     * type and enables the Component to automatically traverse its dependencies
2432     * and provide a meaningful message if the provided Component is
2433     * incompatible or non-existent. This function also creates a Property in
2434     * this component to store the connectee path for this socket; the
2435     * propertyComment argument is the comment to use for that Property. */
2436     template <typename T>
constructSocket(const std::string & name,const std::string & propertyComment)2437     PropertyIndex constructSocket(const std::string& name,
2438                                      const std::string& propertyComment) {
2439         OPENSIM_THROW_IF(_socketsTable.count(name), Exception,
2440             getConcreteClassName() + " already has a socket named '"
2441             + name + "'.");
2442 
2443         // This property is accessed / edited by the Socket class. It is
2444         // not easily accessible to users.
2445         // TODO does putting the addProperty here break the ability to
2446         // create a custom-copy-ctor version of all of this?
2447         // TODO property type should be ComponentPath or something like that.
2448         PropertyIndex propIndex = this->template addProperty<std::string>(
2449                 "socket_" + name , propertyComment, "");
2450         // We must create the Property first: the Socket needs the property's
2451         // index in order to access the property later on.
2452         _socketsTable[name].reset(
2453             new Socket<T>(name, propIndex, SimTK::Stage::Topology, *this));
2454         return propIndex;
2455     }
2456 
2457 #ifndef SWIG // SWIG can't parse the const at the end of the second argument.
2458     /** Construct an output for a member function of the same component.
2459         The following must be true about componentMemberFunction, the function
2460         that returns the output:
2461 
2462            -# It is a member function of \a this component.
2463            -# The member function is const.
2464            -# It takes only one input, which is `const SimTK::State&`
2465            -# The function returns the computed quantity *by value* (e.g.,
2466               `double computeQuantity(const SimTK::State&) const`).
2467 
2468         You must also provide the stage on which the output depends.
2469 
2470         You can ask outputs for their value only after you call
2471         `finalizeFromProperties()`.
2472 
2473        @see constructOutputForStateVariable()
2474      */
2475     template <typename T, typename CompType = Component>
2476     bool constructOutput(const std::string& name,
2477             T (CompType::*const memFunc)(const SimTK::State&) const,
2478             const SimTK::Stage& dependsOn = SimTK::Stage::Acceleration) {
2479         // The `const` in `CompType::*const componentMemberFunction` means this
2480         // function can't assign componentMemberFunction to some other function
2481         // pointer. This is unlikely, since that function would have to match
2482         // the same template parameters (T and CompType).
2483         static_assert(std::is_base_of<Component, CompType>::value,
2484             "Template parameter 'CompType' must be derived from Component.");
2485 
2486         // This lambda takes a pointer to a component, downcasts it to the
2487         // appropriate derived type, then calls the member function of the
2488         // derived type. Thank you, klshrinidhi!
2489         // TODO right now, the assignment to result within the lambda is
2490         // making a copy! We can fix this using a reference pointer.
2491         auto outputFunc = [memFunc] (const Component* comp,
2492                 const SimTK::State& s, const std::string&, T& result) -> void {
2493             result = std::mem_fn(memFunc)(dynamic_cast<const CompType*>(comp), s);
2494         };
2495         return constructOutput<T>(name, outputFunc, dependsOn);
2496     }
2497     /** This variant handles component member functions that return the
2498      * output value by const reference (const T&).
2499      * @warning ONLY use this with member functions that fetch quantities that
2500      * are stored within the passed-in SimTK::State. The function cannot return
2501      * local variables. */
2502     template <typename T, typename CompType = Component>
2503     bool constructOutput(const std::string& name,
2504             const T& (CompType::*const memFunc)(const SimTK::State&) const,
2505             const SimTK::Stage& dependsOn = SimTK::Stage::Acceleration) {
2506         static_assert(std::is_base_of<Component, CompType>::value,
2507             "Template parameter 'CompType' must be derived from Component.");
2508 
2509         // This lambda takes a pointer to a component, downcasts it to the
2510         // appropriate derived type, then calls the member function of the
2511         // derived type. Thank you, klshrinidhi!
2512         auto outputFunc = [memFunc] (const Component* comp,
2513                 const SimTK::State& s, const std::string&, T& result) -> void {
2514             result = std::mem_fn(memFunc)(dynamic_cast<const CompType*>(comp), s);
2515         };
2516         return constructOutput<T>(name, outputFunc, dependsOn);
2517     }
2518     /** Construct an output that can have multiple channels. You add Channels
2519     to this Output in extendFinalizeFromProperties() using
2520     AbstractOutput::addChannel(). The member function
2521     you provide must take the name of the channel whose value is requested. */
2522     template <typename T, typename CompType>
2523     bool constructListOutput(const std::string& name,
2524              T (CompType::*const memFunc)(const SimTK::State&,
2525                                           const std::string& channel) const,
2526             const SimTK::Stage& dependsOn = SimTK::Stage::Acceleration) {
2527         // The `const` in `CompType::*const componentMemberFunction` means this
2528         // function can't assign componentMemberFunction to some other function
2529         // pointer. This is unlikely, since that function would have to match
2530         // the same template parameters (T and CompType).
2531         static_assert(std::is_base_of<Component, CompType>::value,
2532             "Template parameter 'CompType' must be derived from Component.");
2533 
2534         // This lambda takes a pointer to a component, downcasts it to the
2535         // appropriate derived type, then calls the member function of the
2536         // derived type. Thank you, klshrinidhi!
2537         auto outputFunc = [memFunc] (const Component* comp,
2538                 const SimTK::State& s, const std::string& channel, T& result) -> void {
2539             result = std::mem_fn(memFunc)(
2540                     dynamic_cast<const CompType*>(comp), s, channel);
2541         };
2542         return constructOutput<T>(name, outputFunc, dependsOn, true);
2543     }
2544 #endif
2545 
2546     /** Construct an Output for a StateVariable. While this method is a
2547      * convenient way to construct an Output for a StateVariable, it is
2548      * inefficient because it uses a string lookup. To create a more efficient
2549      * Output, create a member variable that returns the state variable
2550      * directly; see the implementations of Coordinate::getValue() or
2551      * Muscle::getActivation() for examples.
2552      *
2553      * @param name Name of the output, which must be the same as the name of
2554      * the corresponding state variable. */
2555     bool constructOutputForStateVariable(const std::string& name);
2556 
2557     /** Construct an Input (socket) for this Component's dependence on an
2558      * Output signal.  It is a placeholder for the Output and its type and
2559      * enables the Component to automatically traverse its dependencies and
2560      * provide a meaningful message if the provided Output is incompatible or
2561      * non-existent. This also specifies at what stage the output must be valid
2562      * for the component to consume it as an input.  If the Output's
2563      * dependsOnStage is above the Input's requiredAtStage, an Exception is
2564      * thrown because the output cannot satisfy the Input's requirement.
2565      * This function also creates a Property in this component to store the
2566      * connectee paths for this input; the
2567      * propertyComment argument is the comment to use for that Property. */
2568     template <typename T>
2569     PropertyIndex constructInput(const std::string& name, bool isList,
2570             const std::string& propertyComment,
2571             const SimTK::Stage& requiredAtStage = SimTK::Stage::Instance) {
2572 
2573         OPENSIM_THROW_IF(_inputsTable.count(name), Exception,
2574             getConcreteClassName() + " already has an input named '"
2575             + name + "'.");
2576 
2577         PropertyIndex propIndex;
2578         // This property is accessed / edited by the AbstractSocket class.
2579         // It is not easily accessible to users.
2580         // TODO property type should be OutputPath or ChannelPath.
2581         if (isList) {
2582             propIndex = this->template addListProperty<std::string>(
2583                     "input_" + name, propertyComment,
2584                     0, std::numeric_limits<int>::max());
2585         } else {
2586             propIndex = this->template addProperty<std::string>(
2587                     "input_" + name, propertyComment, "");
2588         }
2589         // We must create the Property first: the Input needs the property's
2590         // index in order to access the property later on.
2591         _inputsTable[name].reset(
2592                 new Input<T>(name, propIndex, requiredAtStage, *this));
2593         return propIndex;
2594     }
2595     /// @}
2596 
2597     /// For internal use. Update absolute connectee paths in all sockets and
2598     /// inputs in the subcomponent by prepending the absolute path of the
2599     /// subcomponent. To be used when adding subcomponent to another component.
2600     static void prependComponentPathToConnecteePath(Component& subcomponent);
2601 
2602 private:
2603 
2604     //Mark components that are properties of this Component as subcomponents of
2605     //this Component. This happens automatically upon construction of the
2606     //component. If a Component property is added programmatically, then one must
2607     //also mark it by calling markAsPropertySubcomponent() with that component.
2608     void markPropertiesAsSubcomponents();
2609 
2610     // Internal use: mark as a subcomponent, a component that is owned by this
2611     // Component by virtue of being one of its properties.
2612     void markAsPropertySubcomponent(const Component* subcomponent);
2613 
2614     /// Invoke finalizeFromProperties() on the (sub)components of this Component.
2615     void componentsFinalizeFromProperties() const;
2616 
2617     /// Invoke connect() on the (sub)components of this Component.
2618     void componentsFinalizeConnections(Component& root);
2619 
2620     /// Base Component must create underlying resources in computational System.
2621     void baseAddToSystem(SimTK::MultibodySystem& system) const;
2622 
2623     /// Invoke addToSystem() on the (sub)components of this Component.
2624     void componentsAddToSystem(SimTK::MultibodySystem& system) const;
2625 
2626     /// Invoke initStateFromProperties() on (sub)components of this Component
2627     void componentsInitStateFromProperties(SimTK::State& state) const;
2628 
2629     /// Invoke setPropertiesFromState() on (sub)components of this Component
2630     void componentsSetPropertiesFromState(const SimTK::State& state);
2631 
2632     /** Used internally to construct outputs. Creating the functions for
2633      outputs is potentially error-prone if the function binds to (or
2634      captures) a pointer to a class. When the component is copied, the
2635      pointer bound to the function is also copied and points to the original
2636      object. This is unlikely to be the intended behavior. For this reason,
2637      this variant of constructOutput should be used with care.
2638     */
2639     template <typename T>
2640     bool constructOutput(const std::string& name,
2641             const std::function<void (const Component*,
2642                                       const SimTK::State&,
2643                                       const std::string& channel, T&)> outputFunction,
2644             const SimTK::Stage& dependsOn = SimTK::Stage::Acceleration,
2645             bool isList = false) {
2646 
2647         OPENSIM_THROW_IF(_outputsTable.count(name), Exception,
2648             getConcreteClassName() + " already has an output named '"
2649             + name + "'.");
2650 
2651         _outputsTable[name].reset(
2652                 new Output<T>(name, outputFunction, dependsOn, isList));
2653         return true;
2654     }
2655 
2656     // Get the number of continuous states that the Component added to the
2657     // underlying computational system. It includes the number of built-in states
2658     // exposed by this component. It represents the number of state variables
2659     // managed by this Component.
getNumStateVariablesAddedByComponent()2660     int getNumStateVariablesAddedByComponent() const
2661     {   return (int)_namedStateVariableInfo.size(); }
2662     Array<std::string> getStateVariableNamesAddedByComponent() const;
2663 
getDefaultSubsystem()2664     const SimTK::DefaultSystemSubsystem& getDefaultSubsystem() const
2665         {   return getSystem().getDefaultSubsystem(); }
updDefaultSubsystem()2666     SimTK::DefaultSystemSubsystem& updDefaultSubsystem() const
2667         {   return updSystem().updDefaultSubsystem(); }
2668 
2669     // Clear all modeling options, continuous and discrete state variables,
2670     // and cache variable allocated by this Component
2671     void clearStateAllocations();
2672 
2673     // Reset by clearing underlying system indices.
2674     void reset();
2675 
2676     void warnBeforePrint() const override;
2677 
2678 protected:
2679     //Derived Components must create concrete StateVariables to expose their state
2680     //variables. When exposing state variables allocated by the underlying Simbody
2681     //component (MobilizedBody, Constraint, Force, etc...) use its interface to
2682     //implement the virtual methods below. Otherwise, if the Component is adding its
2683     //own state variables using the addStateVariable() helper, then an
2684     //AddedStateVariable implements the interface and automatically handles state
2685     //variable access.
2686     class StateVariable {
2687         friend void Component::addStateVariable(StateVariable* sv) const;
2688     public:
StateVariable()2689         StateVariable() : name(""), owner(nullptr),
2690             subsysIndex(SimTK::InvalidIndex), varIndex(SimTK::InvalidIndex),
2691             sysYIndex(SimTK::InvalidIndex), hidden(true) {}
2692         explicit StateVariable(const std::string& name, //state var name
2693             const Component& owner,     //owning component
2694             SimTK::SubsystemIndex sbsix,//subsystem for allocation
2695             int varIndex,               //variable's index in subsystem
2696             bool hide = false)          //state variable is hidden or not
name(name)2697             : name(name), owner(&owner),
2698             subsysIndex(sbsix), varIndex(varIndex),
2699             sysYIndex(SimTK::InvalidIndex), hidden(hide)  {}
2700 
~StateVariable()2701         virtual ~StateVariable() {}
2702 
getName()2703         const std::string& getName() const { return name; }
getOwner()2704         const Component& getOwner() const { return *owner; }
2705 
getVarIndex()2706         const int& getVarIndex() const { return varIndex; }
2707         // return the index of the subsystem used to make resource allocations
getSubsysIndex()2708         const SimTK::SubsystemIndex& getSubsysIndex() const { return subsysIndex; }
2709         // return the index in the global list of continuous state variables, Y
getSystemYIndex()2710         const SimTK::SystemYIndex& getSystemYIndex() const { return sysYIndex; }
2711 
isHidden()2712         bool isHidden() const { return hidden; }
hide()2713         void hide()  { hidden = true; }
show()2714         void show()  { hidden = false; }
2715 
setVarIndex(int index)2716         void setVarIndex(int index) { varIndex = index; }
setSubsystemIndex(const SimTK::SubsystemIndex & sbsysix)2717         void setSubsystemIndex(const SimTK::SubsystemIndex& sbsysix) {
2718             subsysIndex = sbsysix;
2719         }
2720 
2721         //Concrete Components implement how the state variable value is evaluated
2722         virtual double getValue(const SimTK::State& state) const = 0;
2723         virtual void setValue(SimTK::State& state, double value) const = 0;
2724         virtual double getDerivative(const SimTK::State& state) const = 0;
2725         // The derivative a state should be a cache entry and thus does not
2726         // change the state
2727         virtual void setDerivative(const SimTK::State& state, double deriv) const = 0;
2728 
2729     private:
2730         std::string name;
2731         SimTK::ReferencePtr<const Component> owner;
2732 
2733         // Identify which subsystem this state variable belongs to, which should
2734         // be determined and set at creation time
2735         SimTK::SubsystemIndex subsysIndex;
2736         // The local variable index in the subsystem also provided at creation
2737         // (e.g. can be QIndex, UIndex, or Zindex type)
2738         int  varIndex;
2739         // Once allocated a state in the system will have a global index
2740         // and that can be stored here as well
2741         SimTK::SystemYIndex sysYIndex;
2742 
2743         // flag indicating if state variable is hidden to the outside world
2744         bool hidden;
2745     };
2746 
2747     /// Helper method to enable Component makers to specify the order of their
2748     /// subcomponents to be added to the System during addToSystem(). It is
2749     /// highly unlikely that you will need to reorder the subcomponents of your
2750     /// custom component. This ability is primarily intended for Model (and
2751     /// other top-level) components that have the responsibility of creating a
2752     /// valid SimTK::MultibodySystem. MultibodySystem (Simbody) elements such as
2753     /// MobilizedBodies must be added sequentially to form a Multibody tree.
2754     /// SimTK::Constraints and SimTK::Forces must be applied to MobilizedBodies
2755     /// that are already present in the MultibodySystem. The Model component
2756     /// handles this order for you and should handle user-defined Components
2757     /// without any issues. You should rarely need to use this method yourself.
2758     /// If needed, use this method in extendFinalizeConnections() of your
2759     /// Component (or within your extendConnectToModel() for ModelComponents) to
2760     /// set the order of your subcomponents. For example, Model orders
2761     /// subcomponents according to the Multibody tree and adds bodies and joints
2762     /// in order starting from Ground and growing outward. If the subcomponent
2763     /// already appears in the ordered list setting it later in the list has no
2764     /// effect. The list remains unique. NOTE: If you do need to set the order
2765     /// of your subcomponents, you must do so for all your immediate
2766     /// subcomponents, otherwise those components not in the ordered list will
2767     /// not be added to the System.
2768     void setNextSubcomponentInSystem(const Component& sub) const;
2769 
2770     /// resetSubcomponentOrder clears this Component's list of ordered
2771     /// subcomponents (but otherwise leaves subcomponents untouched). You can
2772     /// form the ordered list using setNextSubcomponentInSystem() above.
resetSubcomponentOrder()2773     void resetSubcomponentOrder() {
2774         _orderedSubcomponents.clear();
2775     }
2776 
2777     /// Handle a change in XML syntax for Sockets.
2778     void updateFromXMLNode(SimTK::Xml::Element& node, int versionNumber)
2779             override;
2780 
2781 private:
2782     // Reference to the owning Component of this Component. It is not the
2783     // previous in the tree, but is the Component one level up that owns this
2784     // one.
2785     SimTK::ReferencePtr<const Component> _owner;
2786 
2787     // Reference pointer to the successor of the current Component in Pre-order traversal
2788     mutable SimTK::ReferencePtr<const Component> _nextComponent;
2789 
2790     // Reference pointer to the system that this component belongs to.
2791     SimTK::ReferencePtr<SimTK::MultibodySystem> _system;
2792 
2793     // propertiesTable maintained by Object
2794 
2795     // Table of Component's structural Sockets indexed by name.
2796     std::map<std::string, SimTK::ClonePtr<AbstractSocket>> _socketsTable;
2797 
2798     // Table of Component's Inputs indexed by name.
2799     std::map<std::string, SimTK::ClonePtr<AbstractInput>> _inputsTable;
2800 
2801     // Table of Component's Outputs indexed by name.
2802     std::map<std::string, SimTK::ClonePtr<AbstractOutput> > _outputsTable;
2803 
2804     // Underlying SimTK custom measure ComponentMeasure, which implements
2805     // the realizations in the subsystem by calling private concrete methods on
2806     // the Component. Every model component has one of these, allocated
2807     // in its extendAddToSystem() method, and placed in the System's default
2808     // subsystem.
2809     SimTK::ResetOnCopy<SimTK::MeasureIndex> _simTKcomponentIndex;
2810 
2811     // list of subcomponents that are contained in this Component's properties
2812     SimTK::ResetOnCopy<SimTK::Array_<SimTK::ReferencePtr<Component>>>
2813         _propertySubcomponents;
2814     // Keep fixed list of data member Components upon construction
2815     SimTK::Array_<SimTK::ClonePtr<Component> > _memberSubcomponents;
2816     // Hold onto adopted components
2817     SimTK::Array_<SimTK::ClonePtr<Component> > _adoptedSubcomponents;
2818 
2819     // A flat list of subcomponents (immediate and otherwise) under this
2820     // Component. This list must be populated prior to addToSystem(), and is
2821     // used strictly to specify the order in which addToSystem() is invoked
2822     // on its subcomponents. The order is necessary for the construction
2823     // of Simbody elements (e.g. MobilizedBodies, Constraints, Forces,
2824     // Measures, ...) which cannot be added to the SimTK::MultibodySystem in
2825     // arbitrary order. In the case of MobilizedBodies, for example, the parent
2826     // MobilizedBody must be part of the system before the child can be added.
2827     // OpenSim::Model performs the mapping from User specifications to the
2828     // system order required by the SimTK::MultibodySystem.
2829     // If the Component does not reset the list, it is by default the ownership
2830     // tree order of its subcomponents.
2831     mutable std::vector<SimTK::ReferencePtr<const Component> > _orderedSubcomponents;
2832 
2833     // Structure to hold modeling option information. Modeling options are
2834     // integers 0..maxOptionValue. At run time we keep them in a Simbody
2835     // discrete state variable that invalidates Model stage if changed.
2836     struct ModelingOptionInfo {
ModelingOptionInfoModelingOptionInfo2837         ModelingOptionInfo() : maxOptionValue(-1) {}
ModelingOptionInfoModelingOptionInfo2838         explicit ModelingOptionInfo(int maxOptVal)
2839         :   maxOptionValue(maxOptVal) {}
2840         // Model
2841         int                             maxOptionValue;
2842         // System
2843         SimTK::DiscreteVariableIndex    index;
2844     };
2845 
2846     // Class for handling state variable added (allocated) by this Component
2847     class AddedStateVariable : public StateVariable {
2848         public:
2849         // Constructors
AddedStateVariable()2850         AddedStateVariable() : StateVariable(),
2851             invalidatesStage(SimTK::Stage::Empty)  {}
2852 
2853         /** Convenience constructor for defining a Component added state variable */
2854         explicit AddedStateVariable(const std::string& name, //state var name
2855                         const Component& owner,       //owning component
2856                         SimTK::Stage invalidatesStage,//stage this variable invalidates
2857                         bool hide=false) :
StateVariable(name,owner,SimTK::SubsystemIndex (SimTK::InvalidIndex),SimTK::InvalidIndex,hide)2858                     StateVariable(name, owner,
2859                             SimTK::SubsystemIndex(SimTK::InvalidIndex),
2860                             SimTK::InvalidIndex, hide),
2861                         invalidatesStage(SimTK::Stage::Empty) {}
2862 
2863         //override virtual methods
2864         double getValue(const SimTK::State& state) const override;
2865         void setValue(SimTK::State& state, double value) const override;
2866 
2867         double getDerivative(const SimTK::State& state) const override;
2868         void setDerivative(const SimTK::State& state, double deriv) const override;
2869 
2870         private: // DATA
2871         // Changes in state variables trigger recalculation of appropriate cache
2872         // variables by automatically invalidating the realization stage specified
2873         // upon allocation of the state variable.
2874         SimTK::Stage    invalidatesStage;
2875     };
2876 
2877     // Structure to hold related info about discrete variables
2878     struct StateVariableInfo {
StateVariableInfoStateVariableInfo2879         StateVariableInfo() {}
StateVariableInfoStateVariableInfo2880         explicit StateVariableInfo(Component::StateVariable* sv, int order) :
2881         stateVariable(sv), order(order) {}
2882 
2883         // Need empty copy constructor because default compiler generated
2884         // will fail since it cannot copy a unique_ptr!
StateVariableInfoStateVariableInfo2885         StateVariableInfo(const StateVariableInfo&) {}
2886         // Now handle assignment by moving ownership of the unique pointer
2887         StateVariableInfo& operator=(const StateVariableInfo& svi) {
2888             if(this != &svi){
2889                 //assignment has to be const but cannot swap const
2890                 //want to keep unique pointer to guarantee no multiple reference
2891                 //so use const_cast to swap under the covers
2892                 StateVariableInfo* mutableSvi = const_cast<StateVariableInfo *>(&svi);
2893                 stateVariable.swap(mutableSvi->stateVariable);
2894             }
2895             order = svi.order;
2896             return *this;
2897         }
2898 
2899         // State variable
2900         std::unique_ptr<Component::StateVariable> stateVariable;
2901         // order of allocation
2902         int order;
2903     };
2904 
2905     // Structure to hold related info about discrete variables
2906     struct DiscreteVariableInfo {
DiscreteVariableInfoDiscreteVariableInfo2907         DiscreteVariableInfo() {}
DiscreteVariableInfoDiscreteVariableInfo2908         explicit DiscreteVariableInfo(SimTK::Stage invalidates)
2909         :   invalidatesStage(invalidates) {}
2910         // Model
2911         SimTK::Stage                    invalidatesStage;
2912         // System
2913         SimTK::DiscreteVariableIndex    index;
2914     };
2915 
2916     // Structure to hold related info about cache variables
2917     struct CacheInfo {
CacheInfoCacheInfo2918         CacheInfo() {}
CacheInfoCacheInfo2919         CacheInfo(SimTK::AbstractValue* proto,
2920                   SimTK::Stage          dependsOn)
2921         :   prototype(proto), dependsOnStage(dependsOn) {}
2922         // Model
2923         SimTK::ClonePtr<SimTK::AbstractValue>   prototype;
2924         SimTK::Stage                            dependsOnStage;
2925         // System
2926         SimTK::CacheEntryIndex                  index;
2927     };
2928 
2929     // Map names of modeling options for the Component to their underlying
2930     // SimTK indices.
2931     // These are mutable here so they can ONLY be modified in extendAddToSystem().
2932     // This is not an API bug. The purpose of these maps is to automate the
2933     // bookkeeping of component variables (state variables and cache entries) with
2934     // their index in the computational system. The earliest time we have a valid
2935     // index is when we ask the system to allocate the resources and that only
2936     // happens in extendAddToSystem. Furthermore, extendAddToSystem may not
2937     // alter the Component in any way that would affect its behavior- that is
2938     // why it is const!
2939     // The setting of the variable indices is not in the public interface and is
2940     // not polymorphic.
2941 
2942     mutable std::map<std::string, ModelingOptionInfo> _namedModelingOptionInfo;
2943     // Map names of continuous state variables of the Component to their
2944     // underlying SimTK indices.
2945     mutable std::map<std::string, StateVariableInfo> _namedStateVariableInfo;
2946     // Map names of discrete variables of the Component to their underlying
2947     // SimTK indices.
2948     mutable std::map<std::string, DiscreteVariableInfo> _namedDiscreteVariableInfo;
2949     // Map names of cache entries of the Component to their individual
2950     // cache information.
2951     mutable std::map<std::string, CacheInfo>            _namedCacheVariableInfo;
2952 
2953     // Check that the list of _allStateVariables is valid
2954     bool isAllStatesVariablesListValid() const;
2955 
2956     // Array of all state variables for fast access during simulation
2957     mutable SimTK::Array_<SimTK::ReferencePtr<const StateVariable> >
2958                                                             _allStateVariables;
2959     // A handle the System associated with the above state variables
2960     mutable SimTK::ReferencePtr<const SimTK::System> _statesAssociatedSystem;
2961 
2962 //==============================================================================
2963 };  // END of class Component
2964 //==============================================================================
2965 //==============================================================================
2966 
2967 // Implement methods for ComponentListIterator
2968 /// ComponentListIterator<T> pre-increment operator, advances the iterator to
2969 /// the next valid entry.
2970 template <typename T>
2971 ComponentListIterator<T>& ComponentListIterator<T>::operator++() {
2972     if (_node==nullptr)
2973         return *this;
2974     // If _node has children then successor is first child
2975     // move _node to point to it
2976     if (_node->_memberSubcomponents.size() > 0) {
2977         _node = _node->_memberSubcomponents[0].get();
2978     }
2979     else if (_node->_propertySubcomponents.size() > 0) {
2980         _node = _node->_propertySubcomponents[0].get();
2981     }
2982     else if (_node->_adoptedSubcomponents.size() > 0) {
2983         _node = _node->_adoptedSubcomponents[0].get();
2984     }
2985     // If processing a subtree under _root we stop when our successor is the same
2986     // as the successor of _root as this indicates we're leaving the _root's subtree.
2987     else if (_node->_nextComponent.get() == _root->_nextComponent.get())
2988         _node = nullptr;
2989     else // move on to the next component we computed earlier for the full tree
2990         _node = _node->_nextComponent.get();
2991     advanceToNextValidComponent(); // make sure we have a _node of type T after advancing
2992     return *this;
2993 }
2994 
2995 /// Internal method to advance iterator to next valid component.
2996 template <typename T>
advanceToNextValidComponent()2997 void ComponentListIterator<T>::advanceToNextValidComponent() {
2998     // Advance _node to next valid (of type T) if needed
2999     // Similar logic to operator++ but applies _filter->isMatch()
3000     while (_node != nullptr && (dynamic_cast<const T*>(_node) == nullptr ||
3001                                 !_filter.isMatch(*_node) ||
3002                                 (_node == _root))){
3003         if (_node->_memberSubcomponents.size() > 0) {
3004             _node = _node->_memberSubcomponents[0].get();
3005         }
3006         else if (_node->_propertySubcomponents.size() > 0) {
3007             _node = _node->_propertySubcomponents[0].get();
3008         }
3009         else if (_node->_adoptedSubcomponents.size() > 0) {
3010             _node = _node->_adoptedSubcomponents[0].get();
3011         }
3012         else {
3013             if (_node->_nextComponent.get() == _root->_nextComponent.get()){ // end of subtree under _root
3014                 _node = nullptr;
3015                 continue;
3016             }
3017             _node = _node->_nextComponent.get();
3018         }
3019     }
3020     return;
3021 }
3022 
3023 
3024 class ConnecteeNotSpecified : public Exception {
3025 public:
ConnecteeNotSpecified(const std::string & file,size_t line,const std::string & func,const AbstractSocket & socket,const Component & owner)3026     ConnecteeNotSpecified(const std::string& file,
3027                           size_t line,
3028                           const std::string& func,
3029                           const AbstractSocket& socket,
3030                           const Component& owner) :
3031     Exception(file, line, func) {
3032         std::string msg = "Connectee for Socket '" + socket.getName() +
3033                 "' of type " + socket.getConnecteeTypeName() + " in " +
3034                 owner.getConcreteClassName() + " at " +
3035                 owner.getAbsolutePathString() + " is unspecified. "
3036                 "If this model was built programmatically, perhaps "
3037                 "finalizeConnections() was not called before "
3038                 "printing.";
3039         addMessage(msg);
3040     }
3041 };
3042 
3043 template<class C>
getConnectee()3044 const C& Socket<C>::getConnectee() const {
3045     if (!isConnected()) {
3046         std::string msg = "Socket " + getName() + " of type " +
3047                           C::getClassName() + " in " +
3048                           getOwner().getAbsolutePathString() + " of type " +
3049                           getOwner().getConcreteClassName() + " is not connected.";
3050         OPENSIM_THROW(Exception, msg);
3051     }
3052     return connectee.getRef();
3053 }
3054 
3055 template<class C>
findAndConnect(const ComponentPath & connectee)3056 void Socket<C>::findAndConnect(const ComponentPath& connectee) {
3057     const auto* comp =
3058             getOwner().getRoot().template findComponent<C>(connectee);
3059     OPENSIM_THROW_IF(!comp, ComponentNotFound, connectee.toString(),
3060                      getConnecteeTypeName(),
3061                      getOwner().getAbsolutePathString());
3062     connect(*comp);
3063 }
3064 
3065 template<class C>
finalizeConnection(const Component & root)3066 void Socket<C>::finalizeConnection(const Component& root) {
3067 
3068     // If the reference to the connectee is set, use that. Otherwise, use the
3069     // connectee path property.
3070     if (isConnected()) {
3071         const auto& comp = *connectee;
3072         const auto& rootOfConnectee = comp.getRoot();
3073         const auto& myRoot = getOwner().getRoot();
3074         OPENSIM_THROW_IF(&myRoot != &rootOfConnectee, Exception,
3075             "Socket<" + getConnecteeTypeName() + "> '" + getName() +
3076             "' in " + getOwner().getConcreteClassName() + " at " +
3077             getOwner().getAbsolutePathString() + " cannot connect to " +
3078             comp.getConcreteClassName() + " at " +
3079             comp.getAbsolutePathString() + ": components do not have the same "
3080             "root component. Did you intend to add '" +
3081             rootOfConnectee.getName() + "' to '" + myRoot.getName() + "'?");
3082 
3083         ComponentPath connecteePath = connectee->getRelativePath(getOwner());
3084         // If the relative path starts with ".." then use an absolute path
3085         // instead.
3086         if (connecteePath.getNumPathLevels() > 1 &&
3087                 connecteePath.getSubcomponentNameAtLevel(0) == "..")
3088             connecteePath = connectee->getAbsolutePath();
3089         updConnecteePathProp().setValue(0, connecteePath.toString());
3090 
3091     } else {
3092         const auto connecteePath = getConnecteePath();
3093         OPENSIM_THROW_IF(connecteePath.empty(), ConnecteeNotSpecified,
3094                         *this, getOwner());
3095 
3096         ComponentPath path(connecteePath);
3097         const C* comp = nullptr;
3098         if (path.isAbsolute()) {
3099             comp = &root.template getComponent<C>(path);
3100         } else {
3101             comp = &getOwner().template getComponent<C>(path);
3102         }
3103         connectInternal(*comp);
3104     }
3105 }
3106 
3107 template<class T>
connect(const AbstractOutput & output,const std::string & alias)3108 void Input<T>::connect(const AbstractOutput& output,
3109                        const std::string& alias) {
3110     const auto* outT = dynamic_cast<const Output<T>*>(&output);
3111     if (!outT) {
3112         std::stringstream msg;
3113         msg << "Type mismatch between Input and Output: Input '" << getName()
3114             << "' of type " << getConnecteeTypeName()
3115             << " cannot connect to Output '" << output.getPathName()
3116             << "' of type " << output.getTypeName() << ".";
3117         OPENSIM_THROW(Exception, msg.str());
3118     }
3119 
3120     if (!isListSocket() && outT->getChannels().size() > 1) {
3121         OPENSIM_THROW(Exception,
3122             "Non-list input '" + getName() +
3123             "' cannot connect to output '" + output.getPathName() +
3124             " with more than 1 channel");
3125     }
3126 
3127     // For a non-list socket, there will only be one channel.
3128     for (const auto& chan : outT->getChannels()) {
3129         registerChannel(chan.second, alias);
3130     }
3131 }
3132 
3133 template<class T>
connect(const AbstractChannel & channel,const std::string & alias)3134 void Input<T>::connect(const AbstractChannel& channel,
3135                        const std::string& alias) {
3136     registerChannel(channel, alias);
3137 }
3138 
3139 template<class T>
finalizeConnection(const Component & root)3140 void Input<T>::finalizeConnection(const Component& root) {
3141 
3142     _connectees.clear();
3143     _aliases.clear();
3144     if (!_registeredChannels.empty()) {
3145         clearConnecteePath();
3146         OPENSIM_THROW_IF(!isListSocket() && getChannels().size() > 1,
3147                          Exception,
3148                          "Cannot connect single-value input to multiple channels.");
3149         for (const auto& reg : _registeredChannels) {
3150             const Output<T>& output = std::get<0>(reg).getRef();
3151             std::string channelName = std::get<1>(reg);
3152             const AbstractChannel& channel = output.getChannel(channelName);
3153             const std::string& alias = std::get<2>(reg);
3154             connectInternal(channel, std::get<2>(reg));
3155         }
3156 
3157         int i = -1;
3158         for (const auto& chan : getChannels()) {
3159 
3160             const auto& rootOfConnectee =
3161                     chan->getOutput().getOwner().getRoot();
3162             const auto& myRoot = getOwner().getRoot();
3163             OPENSIM_THROW_IF(&myRoot != &rootOfConnectee, Exception,
3164                 "Input<" + getConnecteeTypeName() + "> '" + getName() +
3165                 "' in " + getOwner().getConcreteClassName() + " at " +
3166                 getOwner().getAbsolutePathString() + " cannot connect to " +
3167                 "Channel " + chan->getPathName() + ": components do not have "
3168                 "the same root component. Did you intend to add '" +
3169                 rootOfConnectee.getName() + "' to '" + myRoot.getName() + "'?");
3170 
3171             ++i;
3172             // Update the connectee path as
3173             // <OwnerPath>/<Output><:Channel><(annotation)>
3174             const auto& outputOwner = chan->getOutput().getOwner();
3175             ComponentPath path = outputOwner.getRelativePath(getOwner());
3176             // If the relative path starts with ".." then use an absolute path
3177             // instead.
3178             if (path.getNumPathLevels() > 1 &&
3179                     path.getSubcomponentNameAtLevel(0) == "..")
3180                 path = outputOwner.getAbsolutePath();
3181 
3182             auto pathStr = composeConnecteePath(path.toString(),
3183                                                 chan->getOutput().getName(),
3184                                                 chan->getOutput().isListOutput()
3185                                                 ?
3186                                                 chan->getChannelName() :
3187                                                 "",
3188                                                 _aliases[i]);
3189 
3190             if (isListSocket())
3191                 updConnecteePathProp().appendValue(pathStr);
3192             else
3193                 updConnecteePathProp().setValue(pathStr);
3194         }
3195     } else {
3196         if (!isListSocket() && getConnecteePath().empty()) return;
3197         std::string compPathStr, outputName, channelName, alias;
3198         for (unsigned ix = 0; ix < getNumConnectees(); ++ix) {
3199             parseConnecteePath(getConnecteePath(ix),
3200                                compPathStr, outputName, channelName, alias);
3201             ComponentPath compPath(compPathStr);
3202             const AbstractOutput* output = nullptr;
3203 
3204             if (compPath.isAbsolute()) { //absolute path string
3205                 if (compPathStr.empty()) {
3206                     output = &root.getOutput(outputName);
3207                 } else {
3208                     output = &root.getComponent(compPathStr).getOutput(
3209                             outputName);
3210                 }
3211             } else { // relative path string
3212                 const Component* comp = nullptr;
3213                 if (compPathStr.empty()) {
3214                     comp = &getOwner();
3215                 } else {
3216                     comp = &getOwner().getComponent(compPathStr);
3217                 }
3218                 // comp should never be null at this point.
3219                 OPENSIM_THROW_IF(!comp, Exception, "Internal error: "
3220                                  "could not find component '" +
3221                                  compPathStr + ".");
3222                 output = &comp->getOutput(outputName);
3223             }
3224             const auto& channel = output->getChannel(channelName);
3225             connectInternal(channel, alias);
3226         }
3227     }
3228 }
3229 
3230 
3231 } // end of namespace OpenSim
3232 
3233 #endif // OPENSIM_COMPONENT_H_
3234 
3235