Simbody  3.7
SimTK::SimbodyMatterSubsystem Class Reference

This subsystem contains the bodies ("matter") in the multibody system, the mobilizers (joints) that define the generalized coordinates used to represent the motion of those bodies, and constraints that must be satisfied by the values of those coordinates. More...

+ Inheritance diagram for SimTK::SimbodyMatterSubsystem:

Public Member Functions

Construction, Destruction, Topological information

Methods in this section are used in the extended construction phase for a SimbodyMatterSubsystem which we call defining the "topology" of the multibody system.

This includes adding mobilized bodies and constraints. Topological information is always state-independent since it is kept in the SimbodyMatterSubsystem object directly. The construction phase ends when realizeTopology() is called on the containing System.

 SimbodyMatterSubsystem (MultibodySystem &)
 Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem. More...
 
 SimbodyMatterSubsystem ()
 Create an orphan matter subsystem containing only the Ground body (mobilized body 0); normally use the other constructor to place the subsystem in a MultibodySystem. More...
 
 ~SimbodyMatterSubsystem ()
 The destructor destroys the subsystem implementation object only if this handle is the last reference. More...
 
const MobilizedBodygetMobilizedBody (MobilizedBodyIndex) const
 Given a MobilizedBodyIndex, return a read-only (const) reference to the corresponding MobilizedBody within this matter subsystem. More...
 
MobilizedBodyupdMobilizedBody (MobilizedBodyIndex)
 Given a MobilizedBodyIndex, return a writable reference to the corresponding MobilizedBody within this matter subsystem. More...
 
const MobilizedBody::GroundgetGround () const
 Return a read-only (const) reference to the Ground MobilizedBody within this matter subsystem. More...
 
MobilizedBody::GroundupdGround ()
 Return a writable reference to the Ground MobilizedBody within this matter subsystem; you need a writable reference if you're adding a mobilized body that is directly connected to Ground. More...
 
MobilizedBody::GroundGround ()
 This is a synonym for updGround() that makes for nicer-looking examples. More...
 
const ConstraintgetConstraint (ConstraintIndex) const
 Given a ConstraintIndex, return a read-only (const) reference to the corresponding Constraint within this matter subsystem. More...
 
ConstraintupdConstraint (ConstraintIndex)
 Given a ConstraintIndex, return a writable reference to the corresponding Constraint within this matter subsystem. More...
 
void setShowDefaultGeometry (bool show)
 Normally the matter subsystem will attempt to generate some decorative geometry as a sketch of the defined multibody system; you can disable that with this method. More...
 
bool getShowDefaultGeometry () const
 Get whether this matter subsystem is set to generate default decorative geometry that can be used to visualize this multibody system. More...
 
int getNumBodies () const
 The number of bodies includes all mobilized bodies including Ground, which is the first mobilized body, at MobilizedBodyIndex 0. More...
 
int getNumConstraints () const
 This is the total number of defined constraints, each of which may generate more than one constraint equation. More...
 
int getNumMobilities () const
 The sum of all the mobilizer degrees of freedom. More...
 
int getTotalQAlloc () const
 The sum of all the q vector allocations for each joint. More...
 
MobilizedBodyIndex adoptMobilizedBody (MobilizedBodyIndex parent, MobilizedBody &child)
 Attach new matter by attaching it to the indicated parent body (not normally called by users – see MobilizedBody). More...
 
ConstraintIndex adoptConstraint (Constraint &)
 Add a new Constraint object to the matter subsystem (not normally called by users – see Constraint). More...
 
UnilateralContactIndex adoptUnilateralContact (UnilateralContact *)
 (Experimental) More...
 
int getNumUnilateralContacts () const
 Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem. More...
 
const UnilateralContactgetUnilateralContact (UnilateralContactIndex) const
 Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem. More...
 
UnilateralContactupdUnilateralContact (UnilateralContactIndex)
 Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem. More...
 
StateLimitedFrictionIndex adoptStateLimitedFriction (StateLimitedFriction *)
 (Experimental) More...
 
int getNumStateLimitedFrictions () const
 Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem. More...
 
const StateLimitedFrictiongetStateLimitedFriction (StateLimitedFrictionIndex) const
 Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem. More...
 
StateLimitedFrictionupdStateLimitedFriction (StateLimitedFrictionIndex)
 Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem. More...
 
 SimbodyMatterSubsystem (const SimbodyMatterSubsystem &ss)
 Copy constructor is not very useful. More...
 
SimbodyMatterSubsystemoperator= (const SimbodyMatterSubsystem &ss)
 Copy assignment is not very useful. More...
 
Set/get modeling options

Methods in this section involve setting and getting various modeling options that may be selected.

This includes whether to use quaternions or Euler angles to represent rotations, and enabling/disabling constraints.

void setUseEulerAngles (State &state, bool useEulerAngles) const
 For all mobilizers offering unrestricted orientation, decide what method we should use to model their orientations. More...
 
bool getUseEulerAngles (const State &state) const
 Return the current setting of the "use Euler angles" model variable as set in the supplied state. More...
 
int getNumQuaternionsInUse (const State &state) const
 Return the number of quaternions in use by the mobilizers of this system, given the current setting of the "use Euler angles" flag in the supplied state, and the types of mobilizers in the multibody tree. More...
 
bool isUsingQuaternion (const State &state, MobilizedBodyIndex mobodIx) const
 Check whether a given mobilizer is currently using quaternions, based on the type of mobilizer and the setting of the "use Euler angles" flag in the supplied state. More...
 
QuaternionPoolIndex getQuaternionPoolIndex (const State &state, MobilizedBodyIndex mobodIx) const
 If the given mobilizer is currently using a quaternion to represent orientation, return the QuaternionPoolIndex (a small integer) assigned to that quaternion. More...
 
void setConstraintIsDisabled (State &state, ConstraintIndex constraintIx, bool shouldDisableConstraint) const
 Disable or enable the Constraint whose ConstraintIndex is supplied within the supplied state. More...
 
bool isConstraintDisabled (const State &, ConstraintIndex constraint) const
 Determine whether a particular Constraint is currently disabled in the given state. More...
 
void convertToEulerAngles (const State &inputState, State &outputState) const
 Given a State which may be modeled using quaternions, copy it to another State which represents the same configuration using Euler angles instead. More...
 
void convertToQuaternions (const State &inputState, State &outputState) const
 Given a State which may be modeled using Euler angles, copy it to another State which represents the same configuration using quaternions instead. More...
 
void normalizeQuaternions (State &state) const
 (Advanced) Given a State whose generalized coordinates q have been modified in some manner that doesn't necessarily keep quaternions normalized, fix them. More...
 
Calculate whole-system properties

These methods perform calculations that yield properties of the system as a whole.

These are operators, meaning that they make use of the supplied State but do not modify the State. They simply calculate a result and return it to you without storing it internally. Each method requires that the State has already been realized to at least a particular stage which is documented with the method.

Real calcSystemMass (const State &s) const
 Calculate the total system mass. More...
 
Vec3 calcSystemMassCenterLocationInGround (const State &s) const
 Return the position vector p_GC of the system mass center C, measured from the Ground origin, and expressed in Ground. More...
 
MassProperties calcSystemMassPropertiesInGround (const State &s) const
 Return total system mass, mass center location measured from the Ground origin, and system inertia taken about the Ground origin, expressed in Ground. More...
 
Inertia calcSystemCentralInertiaInGround (const State &s) const
 Return the system inertia matrix taken about the system center of mass, expressed in Ground. More...
 
Vec3 calcSystemMassCenterVelocityInGround (const State &s) const
 Return the velocity v_GC = d/dt p_GC of the system mass center C in the Ground frame G, measured from Ground origin and expressed in G. More...
 
Vec3 calcSystemMassCenterAccelerationInGround (const State &s) const
 Return the acceleration a_GC = d/dt p_GC of the system mass center C in the Ground frame G, measured from Ground origin and expressed in G. More...
 
SpatialVec calcSystemMomentumAboutGroundOrigin (const State &s) const
 Return the momentum of the system as a whole (angular, linear) measured in the Ground frame, taken about the Ground origin and expressed in Ground. More...
 
SpatialVec calcSystemCentralMomentum (const State &s) const
 Return the momentum of the system as a whole (angular, linear) measured in the Ground frame, taken about the current system center of mass location C and expressed in Ground. More...
 
Real calcKineticEnergy (const State &state) const
 Calculate the total kinetic energy of all the mobilized bodies in this matter subsystem, given the configuration and velocities in state. More...
 
System and Task Space Kinematic Jacobian Operators

The system kinematic Jacobian maps between mobility space (generalized speeds and generalized forces) and Cartesian body space (mobilized body frame spatial velocities and spatial forces).

A task space Jacobian maps between mobility space and a specified set of task points or frames fixed to a subset of the bodies, and generally located away from the body frame. A task space Jacobian J can be used to construct various task space matrices such as the task space compliance matrix J M^-1 ~J or its inverse, the task space (or operational space) inertia matrix.

The system Jacobian J(q) maps n generalized speeds u to spatial velocities V of each of the nb mobilized bodies (including Ground), measured at the body frame origin relative to Ground, and expressed in the Ground frame. The transpose ~J of this matrix maps nb spatial forces to n generalized forces, where the spatial forces are applied at the body frame origin and expressed in Ground. Similarly, task space Jacobians map from n generalized speeds to nt task frame spatial velocities (expressed in Ground), and transposed task space Jacobians map between task frame spatial forces (or impulses), expressed in Ground, and generalized forces (or generalized impulses).

Simbody provides fast O(n) methods ("operators") that can form matrix-vector products like J*u or ~J*F without forming J. The "bias" term Jdot*u (also known as the Coriolis acceleration) is also available; this arises when working at the acceleration level because d/dt J*u = J*udot+Jdot*u (where dot means time derivative). The computational cost of these operators is O(n+nt) so it is much more efficient to work with a group of tasks simultaneously than to process one at a time, which would have complexity O(n*nt). Alternatively, we provide methods that will return all or part of J explicitly; in general it is much more efficient computationally to work with the O(n) matrix-vector multiply operators rather than to form explicit matrices and then perform O(n^2) matrix-vector products. Performance estimates are given with each method so that you can determine which methods to use. If you can, you should use the O(n) methods – it is a good habit to get into when using an O(n) multibody code like Simbody!

Note that the Jacobian is associated with an expressed-in frame for the velocity or force vector and a designated station (point) on each body. We always use the Ground frame for Jacobians. For the system Jacobian, the body origin is always the designated station; for task Jacobians different stations may be specified. We provide three different sets of methods for working with

  • the full System Jacobian: J, nb X n 6-vectors (or 6*nb X n scalars)
  • the Station Jacobian for a set of nt task stations (points): JS, nt rows of n 3-vectors (or a 3*nt X n Matrix of scalars)
  • the Frame Jacobian for a set of nt task frames fixed to a body: JF, nt rows of n 6-vectors (or a 6*nt X n Matrix of scalars)

The rotational part of a Jacobian is the same for any frame fixed to the same body. So for Frame Jacobians you need specify only a station on the body (the frame's origin point). That means if you want a 3*nt X n Orientation Jacobian, you can obtain it from alternate rows of a Frame Jacobian. Using the above terminology, the complete System Jacobian is a Frame Jacobian for which the task frames are the body frames, with each MobilizedBody appearing only once and in order of MobilizedBodyIndex (starting with Ground).

It is acceptable for the same body to appear more than once in a list of tasks; these are likely to conflict but that can be dealt with elsewhere.

void multiplyBySystemJacobian (const State &state, const Vector &u, Vector_< SpatialVec > &Ju) const
 Calculate the product of the System kinematic Jacobian J (also known as the partial velocity matrix) and a mobility-space vector u in O(n) time. More...
 
void calcBiasForSystemJacobian (const State &state, Vector_< SpatialVec > &JDotu) const
 Calculate the acceleration bias term for the System Jacobian, that is, the part of the acceleration that is due only to velocities. More...
 
void calcBiasForSystemJacobian (const State &state, Vector &JDotu) const
 Alternate signature that returns the bias as a 6*nb-vector of scalars rather than as an nb-vector of 2x3 spatial vectors. More...
 
void multiplyBySystemJacobianTranspose (const State &state, const Vector_< SpatialVec > &F_G, Vector &f) const
 Calculate the product of the transposed kinematic Jacobian ~J (==J^T) and a vector F_G of spatial force-like elements, one per body, in O(n) time to produce a generalized force-like result f=~J*F. More...
 
void calcSystemJacobian (const State &state, Matrix_< SpatialVec > &J_G) const
 Explicitly calculate and return the nb x nu whole-system kinematic Jacobian J_G, with each element a 2x3 spatial vector (SpatialVec). More...
 
void calcSystemJacobian (const State &state, Matrix &J_G) const
 Alternate signature that returns a system Jacobian as a 6*nb X n Matrix of scalars rather than as an nb X n matrix of 2x3 spatial vectors. More...
 
void multiplyByStationJacobian (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &stationPInB, const Vector &u, Vector_< Vec3 > &JSu) const
 Calculate the Cartesian ground-frame velocities of a set of task stations (points fixed on bodies) that results from a particular set of generalized speeds u. More...
 
Vec3 multiplyByStationJacobian (const State &state, MobilizedBodyIndex onBodyB, const Vec3 &stationPInB, const Vector &u) const
 Alternate signature for when you just have a single station task. More...
 
void multiplyByStationJacobianTranspose (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &stationPInB, const Vector_< Vec3 > &f_GP, Vector &f) const
 Calculate the generalized forces resulting from a single force applied to a set of nt station tasks (points fixed to bodies) P. More...
 
void multiplyByStationJacobianTranspose (const State &state, MobilizedBodyIndex onBodyB, const Vec3 &stationPInB, const Vec3 &f_GP, Vector &f) const
 Alternate signature for when you just have a single station task. More...
 
void calcStationJacobian (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &stationPInB, Matrix_< Vec3 > &JS) const
 Explicitly calculate and return the 3*nt x n kinematic Jacobian JS for a set of nt station tasks P (a station is a point fixed on a particular mobilized body). More...
 
void calcStationJacobian (const State &state, MobilizedBodyIndex onBodyB, const Vec3 &stationPInB, RowVector_< Vec3 > &JS) const
 Alternate signature for when you just have a single station task. More...
 
void calcStationJacobian (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &stationPInB, Matrix &JS) const
 Alternate signature that returns a station Jacobian as a 3*nt x n Matrix rather than as a Matrix of Vec3 elements. More...
 
void calcStationJacobian (const State &state, MobilizedBodyIndex onBodyB, const Vec3 &stationPInB, Matrix &JS) const
 Alternate signature for when you just have a single station task. More...
 
void calcBiasForStationJacobian (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &stationPInB, Vector_< Vec3 > &JSDotu) const
 Calculate the acceleration bias term for a station Jacobian, that is, the part of the station's acceleration that is due only to velocities. More...
 
void calcBiasForStationJacobian (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &stationPInB, Vector &JSDotu) const
 Alternate signature that returns the bias as a 3*nt-vector of scalars rather than as an nt-vector of Vec3s. More...
 
Vec3 calcBiasForStationJacobian (const State &state, MobilizedBodyIndex onBodyB, const Vec3 &stationPInB) const
 Alternate signature for when you just have a single station task. More...
 
void multiplyByFrameJacobian (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &originAoInB, const Vector &u, Vector_< SpatialVec > &JFu) const
 Calculate the spatial velocities of a set of nt task frames A={Ai} fixed to nt bodies B={Bi}, that result from a particular set of n generalized speeds u. More...
 
SpatialVec multiplyByFrameJacobian (const State &state, MobilizedBodyIndex onBodyB, const Vec3 &originAoInB, const Vector &u) const
 Simplified signature for when you just have a single frame task; see the main signature for documentation. More...
 
void multiplyByFrameJacobianTranspose (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &originAoInB, const Vector_< SpatialVec > &F_GAo, Vector &f) const
 Calculate the n generalized forces f resulting from a set of spatial forces (torque,force pairs) F applied at nt task frames Ai fixed to nt bodies Bi. More...
 
void multiplyByFrameJacobianTranspose (const State &state, MobilizedBodyIndex onBodyB, const Vec3 &originAoInB, const SpatialVec &F_GAo, Vector &f) const
 Simplified signature for when you just have a single frame task. More...
 
void calcFrameJacobian (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &originAoInB, Matrix_< SpatialVec > &JF) const
 Explicitly calculate and return the 6*nt x n frame task Jacobian JF for a set of nt frame tasks A={Ai} fixed to nt bodies B={Bi}. More...
 
void calcFrameJacobian (const State &state, MobilizedBodyIndex onBodyB, const Vec3 &originAoInB, RowVector_< SpatialVec > &JF) const
 Simplified signature for when you just have a single frame task. More...
 
void calcFrameJacobian (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &originAoInB, Matrix &JF) const
 Alternate signature that returns a frame Jacobian as a 6*nt X n Matrix rather than as an nt X n Matrix of SpatialVecs. More...
 
void calcFrameJacobian (const State &state, MobilizedBodyIndex onBodyB, const Vec3 &originAoInB, Matrix &JF) const
 Simplified signature for when you just have a single frame task. More...
 
void calcBiasForFrameJacobian (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &originAoInB, Vector_< SpatialVec > &JFDotu) const
 Calculate the acceleration bias term for a task frame Jacobian, that is, the parts of the frames' accelerations that are due only to velocities. More...
 
void calcBiasForFrameJacobian (const State &state, const Array_< MobilizedBodyIndex > &onBodyB, const Array_< Vec3 > &originAoInB, Vector &JFDotu) const
 Alternate signature that returns the bias as a 6*nt-vector of scalars rather than as an nt-vector of SpatialVec elements. More...
 
SpatialVec calcBiasForFrameJacobian (const State &state, MobilizedBodyIndex onBodyB, const Vec3 &originAoInB) const
 Simplified signature for when you just have a single frame task. More...
 
System matrix manipulation

The documentation for the SimbodyMatterSubsystem describes the system equations in matrix notion, although internal computations are generally matrix-free.

The operators in this section provide the ability to perform fast operations that can be described in terms of those matrices (e.g., multiply by the mass matrix) but are actually done using O(n), matrix-free algorithms. There are also routines here for obtaining the matrices explicitly, although working with explicit matrices should be avoided whenever performance is an issue.

The mass matrix M and constraint matrix G are the most significant. G=[P;V;A] is composed of submatrices P for position (holonomic), V for velocity (nonholonomic), and A for acceleration-only constraints. These matrices are sometimes needed separately. Also, these matrices are all in mobility space (generalized speeds u). When qdot != u, the matrix N in the equation qdot = N*u becomes important and operators for working with it efficiently are also provided here. In that case, the position constraint matrix in generalized coordinate q space, Pq, can also be accessed. (In terms of the other matrices, Pq=P*N^-1.)

void multiplyByM (const State &state, const Vector &a, Vector &Ma) const
 This operator calculates in O(n) time the product M*v where M is the system mass matrix and v is a supplied mobility-space vector (that is, it has one entry for each of the n mobilities). More...
 
void multiplyByMInv (const State &state, const Vector &v, Vector &MinvV) const
 This operator calculates in O(n) time the product M^-1*v where M is the system mass matrix and v is a supplied vector with one entry per u-space mobility. More...
 
void calcM (const State &, Matrix &M) const
 This operator explicitly calculates the n X n mass matrix M. More...
 
void calcMInv (const State &, Matrix &MInv) const
 This operator explicitly calculates the inverse of the part of the system mobility-space mass matrix corresponding to free (non-prescribed) mobilities. More...
 
void calcProjectedMInv (const State &s, Matrix &GMInvGt) const
 This operator calculates in O(m*n) time the m X m "projected inverse mass matrix" or "constraint compliance matrix" W=G*M^-1*~G, where G (mXn) is the acceleration-level constraint Jacobian mapped to generalized coordinates, and M (nXn) is the unconstrained system mass matrix. More...
 
void solveForConstraintImpulses (const State &state, const Vector &deltaV, Vector &impulse) const
 Given a set of desired constraint-space speed changes, calculate the corresponding constraint-space impulses that would cause those changes. More...
 
void multiplyByG (const State &state, const Vector &ulike, Vector &Gulike) const
 Returns Gulike = G*ulike, the product of the mXn acceleration constraint Jacobian G and a "u-like" (mobility space) vector of length n. More...
 
void multiplyByG (const State &state, const Vector &ulike, const Vector &bias, Vector &Gulike) const
 Multiply Gulike=G*ulike using the supplied precalculated bias vector to improve performance (approximately 2X) over the other signature. More...
 
void calcBiasForMultiplyByG (const State &state, Vector &bias) const
 Calculate the bias vector needed for the higher-performance signature of the multiplyByG() method above. More...
 
void calcG (const State &state, Matrix &G) const
 This O(m*n) operator explicitly calculates the m X n acceleration-level constraint Jacobian G which appears in the system equations of motion. More...
 
void calcBiasForAccelerationConstraints (const State &state, Vector &bias) const
 Calculate the acceleration constraint bias vector, that is, the terms in the acceleration constraints that are independent of the accelerations. More...
 
void calcConstraintAccelerationErrors (const State &state, const Vector &knownUDot, Vector &pvaerr) const
 Given a complete set of nu generalized accelerations udot, this operator computes the constraint acceleration errors that result due to the constraints currently active in the given state: More...
 
void multiplyByGTranspose (const State &state, const Vector &lambda, Vector &f) const
 Returns f = ~G*lambda, the product of the n X m transpose of the acceleration constraint Jacobian G (=[P;V;A]) and a multiplier-like vector lambda of length m, returning a generalized-force like quantity f of length n. More...
 
void calcGTranspose (const State &, Matrix &Gt) const
 This O(nm) operator explicitly calculates the n X m transpose of the acceleration-level constraint Jacobian G = [P;V;A] which appears in the system equations of motion. More...
 
void multiplyByPq (const State &state, const Vector &qlike, Vector &PqXqlike) const
 Calculate in O(n) time the product Pq*qlike where Pq is the mp X nq position (holonomic) constraint Jacobian and qlike is a "q-like" (generalized coordinate space) vector of length nq. More...
 
void multiplyByPq (const State &state, const Vector &qlike, const Vector &biasp, Vector &PqXqlike) const
 Multiply Pq*qlike using the supplied precalculated bias vector to improve performance (approximately 2X) over the other signature. More...
 
void calcBiasForMultiplyByPq (const State &state, Vector &biasp) const
 Calculate the bias vector needed for the higher-performance signature of the multiplyByPq() method above. More...
 
void calcPq (const State &state, Matrix &Pq) const
 This O(m*n) operator explicitly calculates the mp X nq position-level (holonomic) constraint Jacobian Pq (=P*N^-1), the partial derivative of the position error equations with respect to q. More...
 
void multiplyByPqTranspose (const State &state, const Vector &lambdap, Vector &f) const
 Returns f = ~Pq*lambdap, the product of the n X mp transpose of the position (holonomic) constraint Jacobian Pq (=P*N^-1) and a multiplier-like vector lambdap of length mp, returning a generalized-force like quantity f of length n. More...
 
void calcPqTranspose (const State &state, Matrix &Pqt) const
 This O(m*n) operator explicitly calculates the nq X mp transpose of the position-level (holonomic) constraint Jacobian Pq (=P*N^-1), the partial derivative of the position error equations with respect to q. More...
 
void calcP (const State &state, Matrix &P) const
 Returns the mp X nu matrix P which is the Jacobian of the first time derivative of the holonomic (position) constraint errors with respect to the generalized speeds u; that is, P = partial( dperr/dt )/partial(u). More...
 
void calcPt (const State &state, Matrix &Pt) const
 Returns the nu X mp matrix ~P - see calcP() for a description. More...
 
void multiplyByN (const State &s, bool transpose, const Vector &in, Vector &out) const
 Calculate out_q = N(q)*in_u (like qdot=N*u) or out_u = ~N*in_q. More...
 
void multiplyByNInv (const State &s, bool transpose, const Vector &in, Vector &out) const
 Calculate out_u = NInv(q)*in_q (like u=NInv*qdot) or out_q = ~NInv*in_u. More...
 
void multiplyByNDot (const State &s, bool transpose, const Vector &in, Vector &out) const
 Calculate out_q = NDot(q,u)*in_u or out_u = ~NDot(q,u)*in_q. More...
 
Miscellaneous Operators

Operators make use of the State but do not write their results back into the State, although they may realize the lazy-evaluation cache entries containing articulated body inertias and related computations.

If you want to avoid any implicit cache updates, use the explicit realization methods realizeArticulatedBodyInertias() and realizeArticulatedBodyVelocity() first to force those computations to complete.

void calcAcceleration (const State &state, const Vector &appliedMobilityForces, const Vector_< SpatialVec > &appliedBodyForces, Vector &udot, Vector_< SpatialVec > &A_GB) const
 This is the primary forward dynamics operator. More...
 
void calcAccelerationIgnoringConstraints (const State &state, const Vector &appliedMobilityForces, const Vector_< SpatialVec > &appliedBodyForces, Vector &udot, Vector_< SpatialVec > &A_GB) const
 This operator is similar to calcAcceleration() but ignores the effects of acceleration constraints although it obeys prescribed accelerations. More...
 
void calcResidualForceIgnoringConstraints (const State &state, const Vector &appliedMobilityForces, const Vector_< SpatialVec > &appliedBodyForces, const Vector &knownUdot, Vector &residualMobilityForces) const
 This is the inverse dynamics operator for the tree system; if there are any constraints or prescribed motion they are ignored. More...
 
void calcResidualForce (const State &state, const Vector &appliedMobilityForces, const Vector_< SpatialVec > &appliedBodyForces, const Vector &knownUdot, const Vector &knownLambda, Vector &residualMobilityForces) const
 This is the inverse dynamics operator for when you know both the accelerations and Lagrange multipliers for a constrained system. More...
 
void calcCompositeBodyInertias (const State &state, Array_< SpatialInertia, MobilizedBodyIndex > &R) const
 This operator calculates the composite body inertias R given a State realized to Position stage. More...
 
void calcBodyAccelerationFromUDot (const State &state, const Vector &knownUDot, Vector_< SpatialVec > &A_GB) const
 Given a complete set of n generalized accelerations udot, this kinematic operator calculates in O(n) time the resulting body accelerations, including velocity-dependent terms taken from the supplied state. More...
 
void calcConstraintForcesFromMultipliers (const State &state, const Vector &multipliers, Vector_< SpatialVec > &bodyForcesInG, Vector &mobilityForces) const
 Treating all Constraints together, given a comprehensive set of m Lagrange multipliers lambda, generate the complete set of body spatial forces and mobility (generalized) forces applied by all the Constraints. More...
 
void calcMobilizerReactionForces (const State &state, Vector_< SpatialVec > &forcesAtMInG) const
 Calculate the mobilizer reaction force generated at each MobilizedBody, as felt at the mobilizer's outboard frame M, and expressed in Ground. More...
 
const VectorgetMotionMultipliers (const State &state) const
 Return a reference to the prescribed motion multipliers tau that have already been calculated in the given state, which must have been realized through Acceleration stage. More...
 
Vector calcMotionErrors (const State &state, const Stage &stage) const
 Calculate the degree to which the supplied state does not satisfy the prescribed motion requirements at a particular Stage. More...
 
void findMotionForces (const State &state, Vector &mobilityForces) const
 Find the generalized mobility space forces produced by all the Motion objects active in this system. More...
 
const VectorgetConstraintMultipliers (const State &state) const
 Return a reference to the constraint multipliers lambda that have already been calculated in the given state, which must have been realized through Acceleration stage. More...
 
void findConstraintForces (const State &state, Vector_< SpatialVec > &bodyForcesInG, Vector &mobilityForces) const
 Find the forces produced by all the active Constraint objects in this system. More...
 
Real calcMotionPower (const State &state) const
 Calculate the power being generated or dissipated by all the Motion objects currently active in this system. More...
 
Real calcConstraintPower (const State &state) const
 Return the power begin generated or dissipated by all the Constraint objects currently active in this system. More...
 
void calcTreeEquivalentMobilityForces (const State &, const Vector_< SpatialVec > &bodyForces, Vector &mobilityForces) const
 Accounts for applied forces and inertial forces produced by non-zero velocities in the State. More...
 
void calcQDot (const State &s, const Vector &u, Vector &qdot) const
 Calculate qdot = N(q)*u in O(n) time (very fast). More...
 
void calcQDotDot (const State &s, const Vector &udot, Vector &qdotdot) const
 Calculate qdotdot = N(q)*udot + Ndot(q,u)*u in O(n) time (very fast). More...
 
void addInStationForce (const State &state, MobilizedBodyIndex bodyB, const Vec3 &stationOnB, const Vec3 &forceInG, Vector_< SpatialVec > &bodyForcesInG) const
 Add in to the given body forces vector a force applied to a station (fixed point) S on a body B. More...
 
void addInBodyTorque (const State &state, MobilizedBodyIndex mobodIx, const Vec3 &torqueInG, Vector_< SpatialVec > &bodyForcesInG) const
 Add in to the given body forces vector a torque applied to a body B. More...
 
void addInMobilityForce (const State &state, MobilizedBodyIndex mobodIx, MobilizerUIndex which, Real f, Vector &mobilityForces) const
 Add in to the given mobility forces vector a scalar generalized force, that is a force or torque applied to a mobilizer generalized speed. More...
 
Realization and response methods

Realization methods request that some calculation be performed ("realized") if it has not already been done since the last change to one of the state variables on which the result depends, with the result being placed in the state cache.

Methods beginning with "get" are called responses and are used to extract pre-calculated information that has been realized into the cache.

Realization is normally initiated at the System level. However, there are some "lazy" calculations in the SimbodyMatterSubsystem whose computations are delayed until needed; you can cause those calculations to be performed explicitly here if you want.

void realizePositionKinematics (const State &state) const
 Position kinematics is the first part of the Stage::Position realization, mapping generalized coordinates q to the spatial (Cartesian) poses of the mobilized bodies. More...
 
void realizeVelocityKinematics (const State &) const
 Velocity kinematics is the first part of the Stage::Velocity realization, mapping generalized speeds u to the spatial (Cartesian) velocities of the mobilized bodies. More...
 
void realizeCompositeBodyInertias (const State &) const
 This method checks whether composite body inertias have already been computed since the last change to a Position stage state variable (q) and if so returns immediately at little cost; otherwise, it initiates computation of composite body inertias for all of the mobilized bodies. More...
 
void realizeArticulatedBodyInertias (const State &) const
 This method ensures that articulated body inertias (ABIs) are up to date with the most recent change to the configuration state variables q. More...
 
void realizeArticulatedBodyVelocity (const State &) const
 (Advanced) This method ensures that velocity-dependent computations that also depend on articulated body inertias (ABIs) are up to date with the most recent changes to the configuration state variables q and velocity state variables u. More...
 
const Array_< QIndex > & getFreeQIndex (const State &state) const
 Return a list of the generalized coordinates q that are free, that is, not locked or prescribed with a Motion. More...
 
const Array_< UIndex > & getFreeUIndex (const State &state) const
 Return a list of the generalized speeds u that are free, that is, not locked or prescribed with a Motion. More...
 
const Array_< UIndex > & getFreeUDotIndex (const State &state) const
 Return a list of the generalized speeds whose time derivatives udot are unknown, that is, not locked or prescribed with a Motion. More...
 
const Array_< UIndex > & getKnownUDotIndex (const State &state) const
 Return a list of the generalized speeds whose time derivatives udot are known, that is, locked or prescribed with a Motion. More...
 
void packFreeQ (const State &s, const Vector &allQ, Vector &packedFreeQ) const
 Given a generalized coordinate (q-space) Vector, select only those elements that are free (in the sense of getFreeQIndex()) and pack them in order into packedFreeQ, which must already be allocated to the correct length, getFreeQIndex().size(). More...
 
void unpackFreeQ (const State &s, const Vector &packedFreeQ, Vector &unpackedFreeQ) const
 Given a free-q Vector, unpack it into a q-space Vector which must already be allocated to the correct size. More...
 
void packFreeU (const State &s, const Vector &allU, Vector &packedFreeU) const
 Given a generalized speed (u- or mobility-space) Vector, select only those elements that are free (in the sense of getFreeUIndex()) and pack them in order into packedFreeU, which must already be allocated to the correct length, getFreeUIndex().size(). More...
 
void unpackFreeU (const State &s, const Vector &packedFreeU, Vector &unpackedFreeU) const
 Given a free-u Vector, unpack it into a u-space Vector which must already be allocated to the correct size. More...
 
const SpatialInertiagetCompositeBodyInertia (const State &state, MobilizedBodyIndex mbx) const
 Return the composite body inertia (CBI) R for a particular mobilized body. More...
 
const ArticulatedInertiagetArticulatedBodyInertia (const State &state, MobilizedBodyIndex mbx) const
 Return the articulated body inertia (ABI) P for a particular mobilized body. More...
 
const SpatialVecgetGyroscopicForce (const State &state, MobilizedBodyIndex mbx) const
 This is the rotational velocity-dependent force b on the body due to rotational inertia. More...
 
const SpatialVecgetMobilizerCoriolisAcceleration (const State &state, MobilizedBodyIndex mbx) const
 This is the cross-mobilizer incremental contribution A to the Coriolis (angular velocity dependent) acceleration of a particular mobilized body; it is not too useful except as an intermediate calculation for more interesting quantities – you are probably interested in getTotalCoriolisAcceleration() instead. More...
 
const SpatialVecgetTotalCoriolisAcceleration (const State &state, MobilizedBodyIndex mbx) const
 This is the total Coriolis acceleration of a particular mobilized body, including the effect of the parent's angular velocity as well as the mobilizer's. More...
 
const SpatialVecgetTotalCentrifugalForces (const State &state, MobilizedBodyIndex mbx) const
 This is the total rotational velocity-dependent force acting on this body B, including forces due to Coriolis acceleration and gyroscopic forces due to rotational inertia. More...
 
Testing and debugging utilities

Methods in this section provide alternate ways of calculating quantities for which we provide more efficient methods above.

You should use the better methods normally, but these can be very useful for regression testing and Simbody development because the answers are obtained differently. Numerical results should agree with the faster methods to within numerical precision.

void calcMobilizerReactionForcesUsingFreebodyMethod (const State &state, Vector_< SpatialVec > &forcesAtMInG) const
 This is a slower alternative to calcMobilizerReactionForces(), for use in regression testing and Simbody development. More...
 
void invalidatePositionKinematics (const State &state) const
 (Advanced) Force invalidation of position kinematics, which otherwise remains valid until an instance-stage variable or a generalized coordinate q is modified. More...
 
bool isPositionKinematicsRealized (const State &) const
 (Advanced) Check whether position kinematics has already been realized. More...
 
void invalidateVelocityKinematics (const State &state) const
 (Advanced) Force invalidation of velocity kinematics, which otherwise remains valid until an instance-stage variable, generalized coordinate q, or generalized speed u is modified, or if PositionKinematics is explicitly invalidated. More...
 
bool isVelocityKinematicsRealized (const State &) const
 (Advanced) Check whether velocity kinematics has already been realized. More...
 
void invalidateCompositeBodyInertias (const State &state) const
 (Advanced) This is useful for timing computation time for realizeCompositeBodyInertias(), which otherwise will not recalculate them if called repeatedly. More...
 
bool isCompositeBodyInertiasRealized (const State &) const
 (Advanced) Check whether composite body inertias have already been realized. More...
 
void invalidateArticulatedBodyInertias (const State &state) const
 (Advanced) Force invalidation of articulated body inertias (ABIs), which otherwise remain valid until a position-stage variable is modified or any other prerequisite is invalidated. More...
 
bool isArticulatedBodyInertiasRealized (const State &) const
 (Advanced) Check whether articulated body inertias have already been realized. More...
 
void invalidateArticulatedBodyVelocity (const State &state) const
 (Advanced) Force invalidation of articulated body velocity computations, which otherwise remain valid until a velocity- or position-stage variable is modified or any other prerequisite is invalidated. More...
 
bool isArticulatedBodyVelocityRealized (const State &) const
 (Advanced) Check whether articulated body velocity computations have already been realized. More...
 
Proposed particle API

(NOT IMPLEMENTED YET) These methods are a proposed API for explicit handling of particles.

Currently a particle should be implemented as point mass with a Cartesian (translation) mobilizer to Ground instead. The idea here would be to special-case particles to make them faster; there would be no additional functionality.

int getNumParticles () const
 TODO: total number of particles. More...
 
const Vector_< Vec3 > & getAllParticleLocations (const State &) const
 TODO: total number of particles. More...
 
const Vector_< Vec3 > & getAllParticleVelocities (const State &) const
 TODO: total number of particles. More...
 
const Vec3getParticleLocation (const State &s, ParticleIndex p) const
 TODO: total number of particles. More...
 
const Vec3getParticleVelocity (const State &s, ParticleIndex p) const
 TODO: total number of particles. More...
 
VectorupdAllParticleMasses (State &s) const
 TODO: total number of particles. More...
 
void setAllParticleMasses (State &s, const Vector &masses) const
 TODO: total number of particles. More...
 
Vector_< Vec3 > & updAllParticleLocations (State &) const
 TODO: total number of particles. More...
 
Vector_< Vec3 > & updAllParticleVelocities (State &) const
 TODO: total number of particles. More...
 
Vec3updParticleLocation (State &s, ParticleIndex p) const
 TODO: total number of particles. More...
 
Vec3updParticleVelocity (State &s, ParticleIndex p) const
 TODO: total number of particles. More...
 
void setParticleLocation (State &s, ParticleIndex p, const Vec3 &r) const
 TODO: total number of particles. More...
 
void setParticleVelocity (State &s, ParticleIndex p, const Vec3 &v) const
 TODO: total number of particles. More...
 
void setAllParticleLocations (State &s, const Vector_< Vec3 > &r) const
 TODO: total number of particles. More...
 
void setAllParticleVelocities (State &s, const Vector_< Vec3 > &v) const
 TODO: total number of particles. More...
 
const VectorgetAllParticleMasses (const State &) const
 TODO: total number of particles. More...
 
const Vector_< Vec3 > & getAllParticleAccelerations (const State &) const
 TODO: total number of particles. More...
 
const Vec3getParticleAcceleration (const State &s, ParticleIndex p) const
 TODO: total number of particles. More...
 
Deprecated methods

If you are still using any methods in this section, please stop.

If that's a problem, please post to the Simbody forum and explain why the method should not be deprecated.

const SpatialVecgetMobilizerCentrifugalForces (const State &state, MobilizedBodyIndex mbx) const
 (Deprecated) This is an obscure internal quantity and shouldn't have been exposed; see getTotalCentrifugalForces() instead. More...
 
- Public Member Functions inherited from SimTK::Subsystem
 Subsystem ()
 Default constructor creates and empty handle with a null Subsystem::Guts pointer. More...
 
 Subsystem (const Subsystem &)
 Copy constructor clones the Subsystem::Guts object if there is one and makes this the owner handle of the new clone. More...
 
Subsystemoperator= (const Subsystem &)
 Copy assignment deletes the Subsystem::Guts object if there is one and then behaves like the copy constructor. More...
 
 ~Subsystem ()
 Destructor deletes the referenced Subsystem::Guts object if this is the owner handle of that object, otherwise does nothing. More...
 
QIndex allocateQ (State &s, const Vector &qInit) const
 
UIndex allocateU (State &s, const Vector &uInit) const
 
ZIndex allocateZ (State &s, const Vector &zInit) const
 
DiscreteVariableIndex allocateDiscreteVariable (State &s, Stage g, AbstractValue *v) const
 
DiscreteVariableIndex allocateAutoUpdateDiscreteVariable (State &s, Stage invalidates, AbstractValue *v, Stage updateDependsOn) const
 
CacheEntryIndex allocateCacheEntry (const State &s, Stage dependsOn, Stage computedBy, AbstractValue *v) const
 
CacheEntryIndex allocateCacheEntry (const State &state, Stage g, AbstractValue *v) const
 
CacheEntryIndex allocateLazyCacheEntry (const State &state, Stage earliest, AbstractValue *v) const
 
QErrIndex allocateQErr (const State &s, int nqerr) const
 
UErrIndex allocateUErr (const State &s, int nuerr) const
 
UDotErrIndex allocateUDotErr (const State &s, int nudoterr) const
 
EventTriggerByStageIndex allocateEventTriggersByStage (const State &s, Stage g, int ntriggers) const
 
const VectorgetQ (const State &s) const
 
const VectorgetU (const State &s) const
 
const VectorgetZ (const State &s) const
 
const VectorgetUWeights (const State &s) const
 
const VectorgetZWeights (const State &s) const
 
VectorupdQ (State &s) const
 
VectorupdU (State &s) const
 
VectorupdZ (State &s) const
 
const VectorgetQDot (const State &s) const
 
const VectorgetUDot (const State &s) const
 
const VectorgetZDot (const State &s) const
 
const VectorgetQDotDot (const State &s) const
 
VectorupdQDot (const State &s) const
 
VectorupdUDot (const State &s) const
 
VectorupdZDot (const State &s) const
 
VectorupdQDotDot (const State &s) const
 
const VectorgetQErr (const State &s) const
 
const VectorgetUErr (const State &s) const
 
const VectorgetQErrWeights (const State &s) const
 
const VectorgetUErrWeights (const State &s) const
 
const VectorgetUDotErr (const State &s) const
 
const VectorgetMultipliers (const State &s) const
 
const VectorgetEventTriggersByStage (const State &s, Stage g) const
 
VectorupdQErr (const State &s) const
 
VectorupdUErr (const State &s) const
 
VectorupdUDotErr (const State &s) const
 
VectorupdMultipliers (const State &s) const
 
VectorupdEventTriggersByStage (const State &s, Stage g) const
 
SystemQIndex getQStart (const State &s) const
 
int getNQ (const State &s) const
 
SystemUIndex getUStart (const State &s) const
 
int getNU (const State &s) const
 
SystemZIndex getZStart (const State &s) const
 
int getNZ (const State &s) const
 
SystemQErrIndex getQErrStart (const State &s) const
 
int getNQErr (const State &s) const
 
SystemUErrIndex getUErrStart (const State &s) const
 
int getNUErr (const State &s) const
 
SystemUDotErrIndex getUDotErrStart (const State &s) const
 
int getNUDotErr (const State &s) const
 
SystemMultiplierIndex getMultipliersStart (const State &s) const
 
int getNMultipliers (const State &s) const
 
SystemEventTriggerByStageIndex getEventTriggerStartByStage (const State &s, Stage g) const
 
int getNEventTriggersByStage (const State &s, Stage g) const
 
void setQ (State &s, const Vector &q) const
 
void setU (State &s, const Vector &u) const
 
void setZ (State &s, const Vector &z) const
 
Stage getStage (const State &s) const
 
void advanceToStage (const State &s, Stage g) const
 
const AbstractValuegetDiscreteVariable (const State &s, DiscreteVariableIndex index) const
 
AbstractValueupdDiscreteVariable (State &s, DiscreteVariableIndex index) const
 
const AbstractValuegetCacheEntry (const State &s, CacheEntryIndex index) const
 
AbstractValueupdCacheEntry (const State &s, CacheEntryIndex index) const
 
Real getDiscreteVarLastUpdateTime (const State &s, DiscreteVariableIndex dx) const
 
CacheEntryIndex getDiscreteVarUpdateIndex (const State &s, DiscreteVariableIndex dx) const
 
const AbstractValuegetDiscreteVarUpdateValue (const State &s, DiscreteVariableIndex dx) const
 
AbstractValueupdDiscreteVarUpdateValue (const State &s, DiscreteVariableIndex dx) const
 
bool isDiscreteVarUpdateValueRealized (const State &s, DiscreteVariableIndex dx) const
 
void markDiscreteVarUpdateValueRealized (const State &s, DiscreteVariableIndex dx) const
 
bool isCacheValueRealized (const State &s, CacheEntryIndex cx) const
 
void markCacheValueRealized (const State &s, CacheEntryIndex cx) const
 
void markCacheValueNotRealized (const State &s, CacheEntryIndex cx) const
 
const StringgetName () const
 Obtain the Subsystem name if one was given on construction of the concrete Subsystem. More...
 
const StringgetVersion () const
 Obtain the Subsystem version string if one was given on construction. More...
 
bool isInSystem () const
 Return true if this Subsystem is contained in a System. More...
 
bool isInSameSystem (const Subsystem &otherSubsystem) const
 Return true if this Subsystem is contained in the same System as contains the given otherSubsystem. More...
 
const SystemgetSystem () const
 Return a const reference to the System that contains this Subsystem. More...
 
SystemupdSystem ()
 Return a writable reference to the System that contains this Subsystem. More...
 
void setSystem (System &system, SubsystemIndex subx)
 Inform this Subsystem of the System that contains it, as well as the SubsystemIndex which the System has assigned to it. More...
 
SubsystemIndex getMySubsystemIndex () const
 Return the SubsystemIndex within the containing System. More...
 
bool isEmptyHandle () const
 Return true if this handle has a null Subsystem::Guts pointer. More...
 
bool isSameSubsystem (const Subsystem &otherSubsystem) const
 Determine if this Subsystem handle refers to the same Subsystem::Guts object as handle otherSubsystem. More...
 
bool isOwnerHandle () const
 Is this Subsystem handle the owner of the Subsystem::Guts object it points to? This is true if the handle is empty or if its Guts object points back to this handle. More...
 
bool subsystemTopologyHasBeenRealized () const
 Returns true if this Subsystem's realizeTopology() method has been called since the last topological change or call to invalidateSubsystemTopologyCache(). More...
 
void invalidateSubsystemTopologyCache () const
 Always call this method when a topological change is made to this Subsystem to indicate that any Stage::Topology cache values may need recomputation. More...
 
MeasureIndex adoptMeasure (AbstractMeasure &)
 Obtain the Subsystem name if one was given on construction of the concrete Subsystem. More...
 
AbstractMeasure getMeasure (MeasureIndex) const
 Obtain the Subsystem name if one was given on construction of the concrete Subsystem. More...
 
template<class T >
Measure_< T > getMeasure_ (MeasureIndex mx) const
 Obtain the Subsystem name if one was given on construction of the concrete Subsystem. More...
 
const Subsystem::GutsgetSubsystemGuts () const
 Obtain the Subsystem name if one was given on construction of the concrete Subsystem. More...
 
Subsystem::GutsupdSubsystemGuts ()
 Obtain the Subsystem name if one was given on construction of the concrete Subsystem. More...
 
void adoptSubsystemGuts (Subsystem::Guts *g)
 Obtain the Subsystem name if one was given on construction of the concrete Subsystem. More...
 
 Subsystem (Subsystem::Guts *g)
 Obtain the Subsystem name if one was given on construction of the concrete Subsystem. More...
 
bool hasGuts () const
 Obtain the Subsystem name if one was given on construction of the concrete Subsystem. More...
 

Related Functions

(Note that these are not member functions.)

std::ostream & operator<< (std::ostream &, const SimbodyMatterSubsystem &)
 Dump some debug information about the given subsystem to the given output stream; this is not for serialization. More...
 

Detailed Description

This subsystem contains the bodies ("matter") in the multibody system, the mobilizers (joints) that define the generalized coordinates used to represent the motion of those bodies, and constraints that must be satisfied by the values of those coordinates.

There are many methods in the API for this class. For whole-system information and calculations, the methods here are the right ones to use. For information associated with individual objects contained in the subsystem, such as MobilizedBody and Constraint objects, it is generally easier to obtain the information through the contained objects' APIs instead.

This class is a "handle" containing only an opaque reference to the underlying implementation class.

Theory discussion

The bodies, mobilizers, and constraints are represented mathematically with the following set of equations:

                     qdot = N u                 Kinematic differential eqns.
                     zdot = zdot(t,q,u,z)       Auxiliary states
         M udot + ~G mult = f(t,q,u,z)          Equations of motion
         G udot           = b(t,q,u)
                 where
          [P]    [bp]
        G=[V]  b=[bv]  f = T + ~J*(F-C)
          [A]    [ba]
          pdotdot = P udot - bp(t,q,u) = 0      Acceleration constraints
             vdot = V udot - bv(t,q,u) = 0
    a(t,q,u,udot) = A udot - ba(t,q,u) = 0
                   pdot = P u - c(t,q) = 0      Velocity constraints
                              v(t,q,u) = 0
                                p(t,q) = 0      Position constraints
                                  n(q) = 0      Normalization constraints

where M(q) is the mass matrix, G(t,q,u) the acceleration constraint matrix, C(q,u) the coriolis and gyroscopic forces, T is user-applied joint mobility forces, F is user-applied body forces and torques and gravity. J(q) is the System Jacobian (partial velocity matrix) whose transpose ~J maps spatial forces to joint mobility forces. p(t,q) are the holonomic (position) constraints, v(t,q,u) the non-holonomic (velocity) constraints, and a(t,q,u,udot) the acceleration-only constraints, which must be linear in udot, with A(t,q,u) the coefficient matrix for a(). pdot, pdotdot are obtained by differentiation of p(), vdot by differentiation of v(). P(t,q)=Dpdot/Du (yes, that's u, not q – we can get Pq=Dp/Dq when we need it as Pq=P*N^-1) and V(t,q,u)=Dv/Du. (We use capital "D" to indicate partial derivative.) n(q) is the set of quaternion normalization constraints, which exist only at the position level and are uncoupled from everything else.

We calculate the constraint multipliers like this:

          G M^-1 ~G mult = G udot0 - b
          where    udot0 = M^-1 f

using the pseudo inverse of G M^-1 ~G to give a least squares solution for mult: mult = pinv(G M^-1 ~G)(G M^-1 f - b). Then the real udot is udot = udot0 - udotC, with udotC = M^-1 ~G mult. Note: M^-1* is an O(n) operator that provides the desired result; it does not require forming or factoring M.

NOTE: only the following constraint matrices have to be formed and factored:

   [G M^-1 ~G]   to calculate multipliers
   [P N^-1]      for projection onto position manifold (a.k.a. Pq)
   [ P ]         for projection onto velocity manifold
   [ V ]  

When working in a weighted norm with weights W on the state variables and weights T (1/tolerance) on the constraint errors, the matrices we need are actually [Tp Pq Wq^-1], [Tpv [P;V] Wu^-1], etc. with T and W diagonal weighting matrices. These can then be used to find least squares solutions in the weighted norms.

In many cases these matrices consist of decoupled blocks which can be solved independently. (TODO: take advantage of that whenever possible to solve a set of smaller systems rather than one large one.) Also, in the majority of biosimulation applications we are likely to have only holonomic (position) constraints, so there is no V or A and G=P is the whole story.

Constructor & Destructor Documentation

◆ SimbodyMatterSubsystem() [1/3]

SimTK::SimbodyMatterSubsystem::SimbodyMatterSubsystem ( MultibodySystem )
explicit

Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem.

The MultibodySystem takes over ownership of the subsystem, which is not copied. The MultibodySystem and this subsystem handle both refer to the same subsystem after this call.

◆ SimbodyMatterSubsystem() [2/3]

SimTK::SimbodyMatterSubsystem::SimbodyMatterSubsystem ( )

Create an orphan matter subsystem containing only the Ground body (mobilized body 0); normally use the other constructor to place the subsystem in a MultibodySystem.

◆ ~SimbodyMatterSubsystem()

SimTK::SimbodyMatterSubsystem::~SimbodyMatterSubsystem ( )
inline

The destructor destroys the subsystem implementation object only if this handle is the last reference.

Normally, there is a MultibodySystem that holds a reference to the subsystem implementation, so this destruction will do nothing.

◆ SimbodyMatterSubsystem() [3/3]

SimTK::SimbodyMatterSubsystem::SimbodyMatterSubsystem ( const SimbodyMatterSubsystem ss)
inline

Copy constructor is not very useful.

Member Function Documentation

◆ getMobilizedBody()

const MobilizedBody& SimTK::SimbodyMatterSubsystem::getMobilizedBody ( MobilizedBodyIndex  ) const

Given a MobilizedBodyIndex, return a read-only (const) reference to the corresponding MobilizedBody within this matter subsystem.

This method will fail if the index is invalid or out of range. MobilizedBodyIndex(0) selects the Ground mobilized body.

◆ updMobilizedBody()

MobilizedBody& SimTK::SimbodyMatterSubsystem::updMobilizedBody ( MobilizedBodyIndex  )

Given a MobilizedBodyIndex, return a writable reference to the corresponding MobilizedBody within this matter subsystem.

This method will fail if the index is invalid or out of range. MobilizedBodyIndex(0) selects the Ground mobilized body.

◆ getGround()

const MobilizedBody::Ground& SimTK::SimbodyMatterSubsystem::getGround ( ) const

Return a read-only (const) reference to the Ground MobilizedBody within this matter subsystem.

◆ updGround()

MobilizedBody::Ground& SimTK::SimbodyMatterSubsystem::updGround ( )

Return a writable reference to the Ground MobilizedBody within this matter subsystem; you need a writable reference if you're adding a mobilized body that is directly connected to Ground.

◆ Ground()

MobilizedBody::Ground& SimTK::SimbodyMatterSubsystem::Ground ( )
inline

This is a synonym for updGround() that makes for nicer-looking examples.

Note: topology is not marked invalid upon returning a writable reference here; that will be done only if a non-const method of the returned MobilizedBody is called. That means it is OK to use Ground() to satisfy a const argument; it won't have an "invalidate topology" side effect.

See also
updGround()

◆ getConstraint()

const Constraint& SimTK::SimbodyMatterSubsystem::getConstraint ( ConstraintIndex  ) const

Given a ConstraintIndex, return a read-only (const) reference to the corresponding Constraint within this matter subsystem.

This method will fail if the index is invalid or out of range.

◆ updConstraint()

Constraint& SimTK::SimbodyMatterSubsystem::updConstraint ( ConstraintIndex  )

Given a ConstraintIndex, return a writable reference to the corresponding Constraint within this matter subsystem.

This method will fail if the index is invalid or out of range.

◆ setShowDefaultGeometry()

void SimTK::SimbodyMatterSubsystem::setShowDefaultGeometry ( bool  show)

Normally the matter subsystem will attempt to generate some decorative geometry as a sketch of the defined multibody system; you can disable that with this method.

◆ getShowDefaultGeometry()

bool SimTK::SimbodyMatterSubsystem::getShowDefaultGeometry ( ) const

Get whether this matter subsystem is set to generate default decorative geometry that can be used to visualize this multibody system.

◆ getNumBodies()

int SimTK::SimbodyMatterSubsystem::getNumBodies ( ) const

The number of bodies includes all mobilized bodies including Ground, which is the first mobilized body, at MobilizedBodyIndex 0.

(Note: if special particle handling were implemented, the count here would not include particles.) Bodies and their inboard mobilizers have the same index since they are grouped together as a MobilizedBody. MobilizedBody numbering (using unique integer type MobilizedBodyIndex) starts with Ground at MobilizedBodyIndex(0) with a regular labeling such that children have higher indices than their parents. Ground does not have a mobilizer (or I suppose you could think of its mobilizer as the Weld joint that attaches it to the universe), but otherwise every mobilized body has a unique body and mobilizer.

Example:

  • Here we use a model of a planar pendulum with 1 degree-of-freedom.
  • The command getNumBodies() will return 2.
    - Why? Ground counts as a mobilized body, and so does the pendulum.
  • Note that Ground is at MobilizedBodyIndex(0), and the pendulum is at the MobilizedBodyIndex(1).

◆ getNumConstraints()

int SimTK::SimbodyMatterSubsystem::getNumConstraints ( ) const

This is the total number of defined constraints, each of which may generate more than one constraint equation.

This is the number of Constraint objects that were defined; in a given State some of these may be disabled.

◆ getNumMobilities()

int SimTK::SimbodyMatterSubsystem::getNumMobilities ( ) const

The sum of all the mobilizer degrees of freedom.

This is also the length of the state variable vector u and the mobility forces array.

◆ getTotalQAlloc()

int SimTK::SimbodyMatterSubsystem::getTotalQAlloc ( ) const

The sum of all the q vector allocations for each joint.

There may be some that are not in use for particular modeling options.

◆ adoptMobilizedBody()

MobilizedBodyIndex SimTK::SimbodyMatterSubsystem::adoptMobilizedBody ( MobilizedBodyIndex  parent,
MobilizedBody child 
)

Attach new matter by attaching it to the indicated parent body (not normally called by users – see MobilizedBody).

The mobilizer and mass properties are provided by child. A new MobilizedBodyIndex is assigned for the child; it is guaranteed to be numerically larger than the MobilizedBodyIndex of the parent. We take over ownership of child's implementation object from the given MobilizedBody handle, leaving that handle as a reference to the implementation object now owned by the matter subsystem. It is an error if the given MobilizedBody handle wasn't the owner of the implementation object to which it refers.

Note
This method is usually called by concrete MobilizedBody constructors; it does not normally need to be called by end users.

◆ adoptConstraint()

ConstraintIndex SimTK::SimbodyMatterSubsystem::adoptConstraint ( Constraint )

Add a new Constraint object to the matter subsystem (not normally called by users – see Constraint).

The details of the Constraint are opaque here. A new ConstraintIndex is assigned. We take over ownership of the implementation object from the given Constraint handle, leaving that handle as a reference to the implementation object now owned by the matter subsystem. It is an error if the given Constraint handle wasn't the owner of the implementation object to which it refers.

Note
This method is usually called by concrete Constraint constructors; it does not normally need to be called by end users.

◆ adoptUnilateralContact()

UnilateralContactIndex SimTK::SimbodyMatterSubsystem::adoptUnilateralContact ( UnilateralContact )

(Experimental)

◆ getNumUnilateralContacts()

int SimTK::SimbodyMatterSubsystem::getNumUnilateralContacts ( ) const

Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem.

The MultibodySystem takes over ownership of the subsystem, which is not copied. The MultibodySystem and this subsystem handle both refer to the same subsystem after this call.

◆ getUnilateralContact()

const UnilateralContact& SimTK::SimbodyMatterSubsystem::getUnilateralContact ( UnilateralContactIndex  ) const

Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem.

The MultibodySystem takes over ownership of the subsystem, which is not copied. The MultibodySystem and this subsystem handle both refer to the same subsystem after this call.

◆ updUnilateralContact()

UnilateralContact& SimTK::SimbodyMatterSubsystem::updUnilateralContact ( UnilateralContactIndex  )

Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem.

The MultibodySystem takes over ownership of the subsystem, which is not copied. The MultibodySystem and this subsystem handle both refer to the same subsystem after this call.

◆ adoptStateLimitedFriction()

StateLimitedFrictionIndex SimTK::SimbodyMatterSubsystem::adoptStateLimitedFriction ( StateLimitedFriction )

(Experimental)

◆ getNumStateLimitedFrictions()

int SimTK::SimbodyMatterSubsystem::getNumStateLimitedFrictions ( ) const

Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem.

The MultibodySystem takes over ownership of the subsystem, which is not copied. The MultibodySystem and this subsystem handle both refer to the same subsystem after this call.

◆ getStateLimitedFriction()

const StateLimitedFriction& SimTK::SimbodyMatterSubsystem::getStateLimitedFriction ( StateLimitedFrictionIndex  ) const

Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem.

The MultibodySystem takes over ownership of the subsystem, which is not copied. The MultibodySystem and this subsystem handle both refer to the same subsystem after this call.

◆ updStateLimitedFriction()

StateLimitedFriction& SimTK::SimbodyMatterSubsystem::updStateLimitedFriction ( StateLimitedFrictionIndex  )

Create a matter subsystem containing only the Ground body (mobilized body 0), and add the subsystem to the indicated MultibodySystem.

The MultibodySystem takes over ownership of the subsystem, which is not copied. The MultibodySystem and this subsystem handle both refer to the same subsystem after this call.

◆ operator=()

SimbodyMatterSubsystem& SimTK::SimbodyMatterSubsystem::operator= ( const SimbodyMatterSubsystem ss)
inline

Copy assignment is not very useful.

◆ setUseEulerAngles()

void SimTK::SimbodyMatterSubsystem::setUseEulerAngles ( State state,
bool  useEulerAngles 
) const

For all mobilizers offering unrestricted orientation, decide what method we should use to model their orientations.

Choices are: quaternions (best for dynamics), or rotation angles (1-2-3 Euler sequence, good for optimization). Changing this flag invalidates Model stage and above in the supplied state, leaving it realized only through Topology stage, so you must call realizeModel() on the containing MultibodySystem prior to using this state in further calculations.

◆ getUseEulerAngles()

bool SimTK::SimbodyMatterSubsystem::getUseEulerAngles ( const State state) const

Return the current setting of the "use Euler angles" model variable as set in the supplied state.

◆ getNumQuaternionsInUse()

int SimTK::SimbodyMatterSubsystem::getNumQuaternionsInUse ( const State state) const

Return the number of quaternions in use by the mobilizers of this system, given the current setting of the "use Euler angles" flag in the supplied state, and the types of mobilizers in the multibody tree.

See also
isUsingQuaternion(), getQuaternionPoolIndex()

◆ isUsingQuaternion()

bool SimTK::SimbodyMatterSubsystem::isUsingQuaternion ( const State state,
MobilizedBodyIndex  mobodIx 
) const

Check whether a given mobilizer is currently using quaternions, based on the type of mobilizer and the setting of the "use Euler angles" flag in the supplied state.

See also
getNumQuaternionsInUse(), getQuaternionPoolIndex()

◆ getQuaternionPoolIndex()

QuaternionPoolIndex SimTK::SimbodyMatterSubsystem::getQuaternionPoolIndex ( const State state,
MobilizedBodyIndex  mobodIx 
) const

If the given mobilizer is currently using a quaternion to represent orientation, return the QuaternionPoolIndex (a small integer) assigned to that quaternion.

This is used, for example, to find which normalization constraint error is associated with which quaternion.

See also
isUsingQuaternion(), getNumQuaternionsInUse()

◆ setConstraintIsDisabled()

void SimTK::SimbodyMatterSubsystem::setConstraintIsDisabled ( State state,
ConstraintIndex  constraintIx,
bool  shouldDisableConstraint 
) const

Disable or enable the Constraint whose ConstraintIndex is supplied within the supplied state.

Whether a Constraint is disabled is an Instance-stage state variable so enabling or disabling invalidates Instance stage and higher in the given state, leaving the state realized no higher than Model stage.

See also
isConstraintDisabled()

◆ isConstraintDisabled()

bool SimTK::SimbodyMatterSubsystem::isConstraintDisabled ( const State ,
ConstraintIndex  constraint 
) const

Determine whether a particular Constraint is currently disabled in the given state.

See also
setConstraintIsDisabled()

◆ convertToEulerAngles()

void SimTK::SimbodyMatterSubsystem::convertToEulerAngles ( const State inputState,
State outputState 
) const

Given a State which may be modeled using quaternions, copy it to another State which represents the same configuration using Euler angles instead.

If the inputState already uses Euler angles, the output will just be a duplicate. All continuous and discrete State variables will be copied to the outputState but they will not necessarily have been realized to the same level as the inputState.

◆ convertToQuaternions()

void SimTK::SimbodyMatterSubsystem::convertToQuaternions ( const State inputState,
State outputState 
) const

Given a State which may be modeled using Euler angles, copy it to another State which represents the same configuration using quaternions instead.

If the inputState already uses quaternions, the output will just be a duplicate. All continuous and discrete State variables will be copied to the outputState but they will not necessarily have been realized to the same level as the inputState.

◆ normalizeQuaternions()

void SimTK::SimbodyMatterSubsystem::normalizeQuaternions ( State state) const

(Advanced) Given a State whose generalized coordinates q have been modified in some manner that doesn't necessarily keep quaternions normalized, fix them.

Note that all of Simbody's integrators and solvers take care of this automatically so most users will never need to make this call.

Since we are modifying q's here, Stage::Position is invalidated.

Parameters
[in,out]state

◆ calcSystemMass()

Real SimTK::SimbodyMatterSubsystem::calcSystemMass ( const State s) const

Calculate the total system mass.

Required stage
Stage::Instance

◆ calcSystemMassCenterLocationInGround()

Vec3 SimTK::SimbodyMatterSubsystem::calcSystemMassCenterLocationInGround ( const State s) const

Return the position vector p_GC of the system mass center C, measured from the Ground origin, and expressed in Ground.

Required stage
Stage::Position

◆ calcSystemMassPropertiesInGround()

MassProperties SimTK::SimbodyMatterSubsystem::calcSystemMassPropertiesInGround ( const State s) const

Return total system mass, mass center location measured from the Ground origin, and system inertia taken about the Ground origin, expressed in Ground.

Required stage
Stage::Position

◆ calcSystemCentralInertiaInGround()

Inertia SimTK::SimbodyMatterSubsystem::calcSystemCentralInertiaInGround ( const State s) const

Return the system inertia matrix taken about the system center of mass, expressed in Ground.

Required stage
Stage::Position

◆ calcSystemMassCenterVelocityInGround()

Vec3 SimTK::SimbodyMatterSubsystem::calcSystemMassCenterVelocityInGround ( const State s) const

Return the velocity v_GC = d/dt p_GC of the system mass center C in the Ground frame G, measured from Ground origin and expressed in G.

Required stage
Stage::Velocity

◆ calcSystemMassCenterAccelerationInGround()

Vec3 SimTK::SimbodyMatterSubsystem::calcSystemMassCenterAccelerationInGround ( const State s) const

Return the acceleration a_GC = d/dt p_GC of the system mass center C in the Ground frame G, measured from Ground origin and expressed in G.

Required stage
Stage::Acceleration

◆ calcSystemMomentumAboutGroundOrigin()

SpatialVec SimTK::SimbodyMatterSubsystem::calcSystemMomentumAboutGroundOrigin ( const State s) const

Return the momentum of the system as a whole (angular, linear) measured in the Ground frame, taken about the Ground origin and expressed in Ground.

(The linear component is independent of the "about" point.)

See also
calcSystemCentralMomentum()
Required stage
Stage::Velocity

◆ calcSystemCentralMomentum()

SpatialVec SimTK::SimbodyMatterSubsystem::calcSystemCentralMomentum ( const State s) const

Return the momentum of the system as a whole (angular, linear) measured in the Ground frame, taken about the current system center of mass location C and expressed in Ground.

(The linear component is independent of the "about" point.)

See also
calcSystemMomentumAboutGroundOrigin()
Required stage
Stage::Velocity

◆ calcKineticEnergy()

Real SimTK::SimbodyMatterSubsystem::calcKineticEnergy ( const State state) const

Calculate the total kinetic energy of all the mobilized bodies in this matter subsystem, given the configuration and velocities in state.

Required stage
Stage::Velocity

◆ multiplyBySystemJacobian()

void SimTK::SimbodyMatterSubsystem::multiplyBySystemJacobian ( const State state,
const Vector u,
Vector_< SpatialVec > &  Ju 
) const

Calculate the product of the System kinematic Jacobian J (also known as the partial velocity matrix) and a mobility-space vector u in O(n) time.

If the vector u is a set of generalized speeds, then this produces the body spatial velocities that result from those generalized speeds. That is, the result is V_GB = J*u where V_GB[i] is the spatial velocity of the i'th body's body frame origin (in Ground) that results from the given set of generalized speeds.

Parameters
[in]stateA State compatible with this System that has already been realized to Stage::Position.
[in]uA mobility-space Vector, such as a set of generalized speeds. The length and order must match the mobilities of this system (that is n, the number of generalized speeds u, not nq, the number of generalized coordinates q).
[out]JuThis is the product V=J*u as described above. Each element is a spatial vector, one per mobilized body, to be indexed by MobilizedBodyIndex. If the input vector is a set of generalized speeds u, then the results are nb spatial velocities V_GBi (that is, a pair of vectors w_GBi and v_GBi giving angular and linear velocity). Note that Ground is body 0 so the 0th element V_GB0=V_GG=Ju[0] is always zero on return.

The kinematic Jacobian (partial velocity matrix) J is defined as follows:

      partial(V)                                 T                        T
  J = ----------, V = [V_GB0 V_GB1 ... V_GB nb-1] ,  u = [u0 u1 ... u n-1]
      partial(u)

Thus the element J(i,j)=partial(V_GBi)/partial(uj) (each element of J is a spatial vector). The transpose of this matrix maps spatial forces to generalized forces; see multiplyBySystemJacobianTranspose().

Note that we're using "monogram" notation for the spatial velocities, where

            G Bi
    V_GBi =  V

the spatial velocity of body i's body frame Bi (at its origin), measured and expressed in the Ground frame G.

Performance discussion

This is a very fast operator, costing about 12*(nb+n) flops, where nb is the number of bodies and n the number of mobilities (degrees of freedom) u. In contrast, even if you have already calculated the entire nbXnX6 matrix J, the multiplication J*u would cost 12*nb*n flops. As an example, for a 20 body system with a free flying base and 19 pin joints (25 dofs altogether), this method takes 12*(20+25)=540 flops while the explicit matrix-vector multiply would take 12*20*25=6000 flops. So this method is already >10X faster for that small system; for larger systems the difference grows rapidly.

See also
multiplyBySystemJacobianTranspose(), calcSystemJacobian()

◆ calcBiasForSystemJacobian() [1/2]

void SimTK::SimbodyMatterSubsystem::calcBiasForSystemJacobian ( const State state,
Vector_< SpatialVec > &  JDotu 
) const

Calculate the acceleration bias term for the System Jacobian, that is, the part of the acceleration that is due only to velocities.

This term is also known as the Coriolis acceleration, and it is returned here as a spatial acceleration of each body frame in Ground.

Parameters
[in]stateA State that has already been realized through Velocity stage.
[out]JDotuThe product JDot*u where JDot = d/dt J, and u is the vector of generalized speeds taken from state. This is a Vector of nb SpatialVec elements.

Theory

The spatial velocity V_GBi of each body i can be obtained from the generalized speeds u by V = {V_GBi} = J*u. Taking the time derivative in G gives

    A = d/dt V = {A_GBi} = J*udot + JDot*u

where JDot=JDot(q,u). This method returns JDot*u, which depends only on configuration q and speeds u. Note that the same u is used to calculate JDot, which is linear in u, so this term is quadratic in u.

Implementation

This method simply extracts the total Coriolis acceleration for each body that is already available in the state cache so there is no computation done here.

See also
getTotalCoriolisAcceleration()

◆ calcBiasForSystemJacobian() [2/2]

void SimTK::SimbodyMatterSubsystem::calcBiasForSystemJacobian ( const State state,
Vector JDotu 
) const

Alternate signature that returns the bias as a 6*nb-vector of scalars rather than as an nb-vector of 2x3 spatial vectors.

See the other signature for documentation.

◆ multiplyBySystemJacobianTranspose()

void SimTK::SimbodyMatterSubsystem::multiplyBySystemJacobianTranspose ( const State state,
const Vector_< SpatialVec > &  F_G,
Vector f 
) const

Calculate the product of the transposed kinematic Jacobian ~J (==J^T) and a vector F_G of spatial force-like elements, one per body, in O(n) time to produce a generalized force-like result f=~J*F.

If F_G is actually a set of spatial forces applied at the body frame origin of each body, and expressed in the Ground frame, then the result is the equivalent set of generalized forces f that would produce the same accelerations as F_G.

Parameters
[in]stateA State compatible with this System that has already been realized to Stage::Position.
[in]F_GThis is a vector of SpatialVec elements, one per mobilized body and in order of MobilizedBodyIndex (with the 0th entry a force on Ground; hence ignored). Each SpatialVec is a spatial force-like pair of 3-vectors (torque,force) with the force applied at the body origin and the vectors expressed in Ground.
[out]fThis is the product f=~J*F_G as described above. This result is in the generalized force space, that is, it has one scalar entry for each of the n system mobilities (velocity degrees of freedom). Resized if necessary.

The kinematic Jacobian (partial velocity matrix) J is defined as follows:

      partial(V)                                 T                        T
  J = ----------, V = [V_GB0 V_GB1 ... V_GB nb-1] ,  u = [u0 u1 ... u n-1]
      partial(u)

Thus the element J(i,j)=partial(V_GBi)/partial(uj) (each element of J is a spatial vector). J maps generalized speeds to spatial velocities (see multiplyBySystemJacobian()); its transpose ~J maps spatial forces to generalized forces.

Note that we're using "monogram" notation for the spatial velocities, where

            G Bi
    V_GBi =  V

the spatial velocity of body i's body frame Bi (at its origin), measured and expressed in the Ground frame G.

Performance discussion

This is a very fast operator, costing about 18*nb+11*n flops, where nb is the number of bodies and n the number of mobilities (degrees of freedom) u. In contrast, even if you have already calculated the entire 6*nbXnu matrix J, the multiplication ~J*F would cost 12*nb*n flops. As an example, for a 20 body system with a free flying base and 19 pin joints (25 dofs altogether), this method takes 18*20+11*25=635 flops while the explicit matrix-vector multiply would take 12*20*25=6000 flops. So this method is already >9X faster for that small system; for larger systems the difference grows rapidly.

See also
multiplyBySystemJacobian(), calcSystemJacobian()

◆ calcSystemJacobian() [1/2]

void SimTK::SimbodyMatterSubsystem::calcSystemJacobian ( const State state,
Matrix_< SpatialVec > &  J_G 
) const

Explicitly calculate and return the nb x nu whole-system kinematic Jacobian J_G, with each element a 2x3 spatial vector (SpatialVec).

This matrix maps generalized speeds to the spatial velocities of all the bodies, which will be at the body origins, measured and expressed in Ground. That is, if you have a set of n generalized speeds u, you can find the spatial velocities of all nb bodies as V_G = J_G*u. The transpose of this matrix maps a set of spatial forces F_G, applied at the body frame origins and expressed in Ground, to the equivalent set of n generalized forces f: f = ~J_G*F_G.

Note
The 0th row of the returned Jacobian is always zero since it represents the spatial velocity of Ground.

Performance discussion

Before using this method, consider whether you really need to form this very large matrix which necessarily will take O(n^2) space and time; it will almost always be much faster to use the multiplyBySystemJacobian() method that directly calculate the matrix-vector product in O(n) time without explicitly forming the matrix. Here are the details:

As currently implemented, forming the full Jacobian J costs about 12*n*(nb+n) flops. Assuming nb ~= n, this is about 24*n^2 flops. Then if you want to form a product J*u explicitly, the matrix-vector multiply will cost about 12*n^2 flops each time you do it. In contrast the J*u product is calculated using multiplyBySystemJacobian() in about 24*n flops. Even for very small systems it is cheaper to make repeated calls to multiplyBySystemJacobian() than to form J explicitly and multiply by it. See the Performance section for multiplyBySystemJacobian() for more comparisons.

See also
multiplyBySystemJacobian(), multiplyBySystemJacobianTranspose()
calcSystemJacobian() alternate signature using scalar elements

◆ calcSystemJacobian() [2/2]

void SimTK::SimbodyMatterSubsystem::calcSystemJacobian ( const State state,
Matrix J_G 
) const

Alternate signature that returns a system Jacobian as a 6*nb X n Matrix of scalars rather than as an nb X n matrix of 2x3 spatial vectors.

See the other signature for documentation and important performance considerations.

◆ multiplyByStationJacobian() [1/2]

void SimTK::SimbodyMatterSubsystem::multiplyByStationJacobian ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  stationPInB,
const Vector u,
Vector_< Vec3 > &  JSu 
) const

Calculate the Cartesian ground-frame velocities of a set of task stations (points fixed on bodies) that results from a particular set of generalized speeds u.

The result is the station velocities measured and expressed in Ground.

Parameters
[in]stateA State that has already been realized through Position stage.
[in]onBodyBAn array of nt mobilized bodies (one per task) to which the stations of interest are fixed.
[in]stationPInBThe array of nt station points P of interest (one per task), each corresponding to one of the bodies B from onBodyB, given as vectors from each body B's origin Bo to its station P, expressed in frame B.
[in]uA mobility-space Vector, such as a set of generalized speeds. The length and order must match the mobilities of this system (that is n, the number of generalized speeds u, not nq, the number of generalized coordinates q).
[out]JSuThe resulting product JS*u, where JS is the station task Jacobian. Resized to nt if needed.

Performance discussion

It is almost always better to use this method than to form an explicit 3*nt X n station task Jacobian explicitly and then multiply by it. If you have only one or two tasks, so that the matrix is only 3xn or 6xn, and then perform many multiplies with that matrix, it might be slightly cheaper to form it. For example, it is about 4X cheaper to use this method than to form a one-task Station Jacobian JS explicitly and use it once. However, because this would be such a skinny matrix (3 X n) explicit multiplication is cheap so if you will re-use this same Jacobian repeatedly before recalculating (at least 6 times) then it may be worth calculating and saving it. Here are the details:

A call to this method costs 27*nt + 12*(nb+n) flops. If you assume that nb ~= n >> 1, you could say this is about 27*nt + 24*n flops. In contrast, assuming you already have the 3*nt X n station Jacobian JS available, you can compute the JS*u product in about 6*nt*n flops, 3X faster for one task, about even for three tasks, and slower for more than three tasks. However forming JS costs about 40*nt+90*n flops (see calcStationJacobian()). So to form a one-task Jacobian and use it once is 4X more expensive (96*n vs 24*n), but if you use it more than 5 times it is cheaper to do it explicitly. Forming a one-task JS and using it 100 times costs about 690*n flops while calling this method 100 times would cost about 2400*n flops.

See also
multiplyByStationJacobianTranspose(), calcStationJacobian()

◆ multiplyByStationJacobian() [2/2]

Vec3 SimTK::SimbodyMatterSubsystem::multiplyByStationJacobian ( const State state,
MobilizedBodyIndex  onBodyB,
const Vec3 stationPInB,
const Vector u 
) const
inline

Alternate signature for when you just have a single station task.

Returns
JS*u, where JS is the station task Jacobian.

◆ multiplyByStationJacobianTranspose() [1/2]

void SimTK::SimbodyMatterSubsystem::multiplyByStationJacobianTranspose ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  stationPInB,
const Vector_< Vec3 > &  f_GP,
Vector f 
) const

Calculate the generalized forces resulting from a single force applied to a set of nt station tasks (points fixed to bodies) P.

The applied forces f_GP should be 3-vectors expressed in Ground. This is considerably faster than forming the Jacobian explicitly and then performing the matrix-vector multiply.

Performance discussion

Cost is about 30*nt + 18*nb + 11*n. Assuming nb ~= n, this is roughly 30*(n+nt). In contrast, forming the complete 3*nt X n matrix would cost about 90*(n+nt/2), and subsequent explicit matrix-vector multiplies would cost about 6*nt*n each.

See also
multiplyByStationJacobian(), calcStationJacobian()

◆ multiplyByStationJacobianTranspose() [2/2]

void SimTK::SimbodyMatterSubsystem::multiplyByStationJacobianTranspose ( const State state,
MobilizedBodyIndex  onBodyB,
const Vec3 stationPInB,
const Vec3 f_GP,
Vector f 
) const
inline

Alternate signature for when you just have a single station task.

◆ calcStationJacobian() [1/4]

void SimTK::SimbodyMatterSubsystem::calcStationJacobian ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  stationPInB,
Matrix_< Vec3 > &  JS 
) const

Explicitly calculate and return the 3*nt x n kinematic Jacobian JS for a set of nt station tasks P (a station is a point fixed on a particular mobilized body).

This matrix maps generalized speeds to the Cartesian velocity of each station, measured and expressed in Ground. That is, if you have a set of n generalized speeds u, you can find the Cartesian velocities of stations P as v_GP = JS*u, where v_GP is a 3*nt column vector. The transpose of this matrix maps a 3*nt vector of forces f_GP (expressed in Ground and applied to P) to the equivalent set of n generalized forces f: f = ~JS*f_GP.

Note
It is almost always far more efficient to use multiplyByStationJacobian() or multiplyByStationJacobianTranspose() to form matrix-vector products rather than to use this method to form the Jacobian explicitly. See the performance discussions there.

Overloaded signatures of this method are available to allow you to obtain the Jacobian either as an nt X n Matrix with Vec3 elements, or as 3*nt X n Matrix with scalar elements.

Parameters
[in]stateA State that has already been realized through Position stage.
[in]onBodyBAn array of nt mobilized bodies (one per task) to which the stations of interest are fixed.
[in]stationPInBThe array of nt station points P of interest (one per task), each corresponding to one of the bodies B from onBodyB, given as vectors from each body B's origin Bo to its station P, expressed in frame B.
[out]JSThe resulting nt X n station task Jacobian. Resized if necessary.

Performance discussion

The cost of a call to this method is about 42*nt + 54*nb + 33*n flops. If we assume that nb ~= n >> 1, this is roughly 90*(n+nt/2) flops. Then once the Station Jacobian JS has been formed, each JS*u matrix-vector product costs 6*nt*n flops to form. When nt is small enough (say one or two tasks), and you plan to re-use it a lot, this can be computationally efficient; but for single use or more than a few tasks you can do much better with multiplyByStationJacobian() or multiplyByStationJacobianTranspose().

See also
multiplyByStationJacobian(), multiplyByStationJacobianTranspose()

◆ calcStationJacobian() [2/4]

void SimTK::SimbodyMatterSubsystem::calcStationJacobian ( const State state,
MobilizedBodyIndex  onBodyB,
const Vec3 stationPInB,
RowVector_< Vec3 > &  JS 
) const
inline

Alternate signature for when you just have a single station task.

◆ calcStationJacobian() [3/4]

void SimTK::SimbodyMatterSubsystem::calcStationJacobian ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  stationPInB,
Matrix JS 
) const

Alternate signature that returns a station Jacobian as a 3*nt x n Matrix rather than as a Matrix of Vec3 elements.

See the other signature for documentation and important performance considerations.

◆ calcStationJacobian() [4/4]

void SimTK::SimbodyMatterSubsystem::calcStationJacobian ( const State state,
MobilizedBodyIndex  onBodyB,
const Vec3 stationPInB,
Matrix JS 
) const
inline

Alternate signature for when you just have a single station task.

◆ calcBiasForStationJacobian() [1/3]

void SimTK::SimbodyMatterSubsystem::calcBiasForStationJacobian ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  stationPInB,
Vector_< Vec3 > &  JSDotu 
) const

Calculate the acceleration bias term for a station Jacobian, that is, the part of the station's acceleration that is due only to velocities.

This term is also known as the Coriolis acceleration, and it is returned here as a linear acceleration of the station in Ground.

Parameters
[in]stateA State that has already been realized through Velocity stage.
[in]onBodyBAn array of nt mobilized bodies (one per task) to which the stations of interest are fixed.
[in]stationPInBThe array of nt station points P of interest (one per task), each corresponding to one of the bodies B from onBodyB, given as vectors from each body B's origin Bo to its station P, expressed in frame B.
[out]JSDotuThe resulting product JSDot*u, where JSDot is the time derivative of JS, the station task Jacobian. Resized to nt if needed.

Theory

The velocity v_GP of a station point P in the Ground frame G can be obtained from the generalized speeds u using the station Jacobian for P, as

    v_GP = JS_P*u

Taking the time derivative in G gives

    a_GP = JS_P*udot + JSDot_P*u

This method returns JSDot_P*u, which depends only on configuration and velocities. We allow for a set of task points P so that all their bias terms can be calculated in a single sweep of the multibody tree. Note that u is taken from the state and that the same u shown above is also used to calculate JSDot_P, which is linear in u, so the bias term is quadratic in u.

Implementation

This method just obtains body B's total Coriolis acceleration already available in the state cache and shifts it to station point P. Cost is 48*nt flops.

See also
getTotalCoriolisAcceleration(), shiftAccelerationBy()

◆ calcBiasForStationJacobian() [2/3]

void SimTK::SimbodyMatterSubsystem::calcBiasForStationJacobian ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  stationPInB,
Vector JSDotu 
) const

Alternate signature that returns the bias as a 3*nt-vector of scalars rather than as an nt-vector of Vec3s.

See the other signature for documentation.

◆ calcBiasForStationJacobian() [3/3]

Vec3 SimTK::SimbodyMatterSubsystem::calcBiasForStationJacobian ( const State state,
MobilizedBodyIndex  onBodyB,
const Vec3 stationPInB 
) const
inline

Alternate signature for when you just have a single station task.

Returns
JSDot*u, where JSDot is the station Jacobian time derivative.

◆ multiplyByFrameJacobian() [1/2]

void SimTK::SimbodyMatterSubsystem::multiplyByFrameJacobian ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  originAoInB,
const Vector u,
Vector_< SpatialVec > &  JFu 
) const

Calculate the spatial velocities of a set of nt task frames A={Ai} fixed to nt bodies B={Bi}, that result from a particular set of n generalized speeds u.

The result is each task frame's angular and linear velocity measured and expressed in Ground. Using this method is considerably faster than forming the 6*nt X n Frame Jacobian explicitly and then performing the matrix-vector multiply. See the performance analysis below for details.

There is a simplified signature of this method available if you have only a single frame task.

Parameters
[in]stateA State that has already been realized through Position stage.
[in]onBodyBAn array of nt mobilized bodies (one per task) to which the task frames of interest are fixed. These may be in any order and the same body may appear more than once if there are multiple task frames on it.
[in]originAoInBAn array of nt frame origin points Ao for the task frames interest (one per task), each corresponding to one of the bodies B from onBodyB, given as vectors from each body B's origin Bo to its task frame origin Ao, expressed in frame B.
[in]uA mobility-space Vector, such as a set of generalized speeds. The length and order must match the mobilities of this system (that is n, the number of generalized speeds u, not nq, the number of generalized coordinates q).
[out]JFuThe resulting product JF*u, where JF is the frame task Jacobian. Resized if needed to a Vector of nt SpatialVec entries.
Note
All frames A fixed to a given body B have the same angular velocity so we do not actually need to know the task frames' orientations here, just the location on B of their origin points Ao. If you have a Transform X_BA giving the pose of frame A in the body frame B, you can extract the position vector for the origin point Ao using X_BA.p() and pass that as the originAoInB parameter here.

Performance discussion

A call to this method costs 27*nt + 12*(nb+n) flops. If you assume that nb ~= n >> 1, you could say this is about 25*(nt+n) flops. In contrast, assuming you already have the 6*nt X n Frame Jacobian JF available, you can compute the JF*u product in about 12*nt*n flops. If you have just one task (nt==1) this explicit multiplication is about twice as fast; at two tasks it is about even and for more than two it is more expensive. However forming JF costs about 180*(n+nt/4) flops (see calcFrameJacobian()). So to form a one-task Jacobian and use it once is almost 8X more expensive (192*n vs 25*n), but if you use it more than 16 times it is (marginally) cheaper to do it explicitly (for one task). For example, forming a one-task JF and using it 100 times costs 1392*n flops while calling this method 100 times would cost about 2500*n flops.

Conclusion: in almost all practical cases you are better off using this operator rather than forming JF, even if you have only a single frame task and certainly if you have more than two tasks.

See also
multiplyByFrameJacobianTranspose(), calcFrameJacobian()

◆ multiplyByFrameJacobian() [2/2]

SpatialVec SimTK::SimbodyMatterSubsystem::multiplyByFrameJacobian ( const State state,
MobilizedBodyIndex  onBodyB,
const Vec3 originAoInB,
const Vector u 
) const
inline

Simplified signature for when you just have a single frame task; see the main signature for documentation.

Returns
JF*u, where JF is the single frame task Jacobian.

◆ multiplyByFrameJacobianTranspose() [1/2]

void SimTK::SimbodyMatterSubsystem::multiplyByFrameJacobianTranspose ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  originAoInB,
const Vector_< SpatialVec > &  F_GAo,
Vector f 
) const

Calculate the n generalized forces f resulting from a set of spatial forces (torque,force pairs) F applied at nt task frames Ai fixed to nt bodies Bi.

The applied forces are spatial vectors (pairs of 3-vectors) expressed in Ground. Use of this O(n) method is considerably faster than forming the 6*nt X n Jacobian explicitly and then performing an O(n^2) matrix-vector multiply.

Parameters
[in]stateA State that has already been realized through Position stage.
[in]onBodyBAn array of nt mobilized bodies (one per task) to which the task frames of interest are fixed. These may be in any order and the same body may appear more than once if there are multiple task frames on it.
[in]originAoInBAn array of nt frame origin points Ao for the task frames interest (one per task), each corresponding to one of the bodies B from onBodyB, given as vectors from each body B's origin Bo to its task frame origin Ao, expressed in frame B.
[in]F_GAoA Vector of nt spatial forces, each applied one of the task frames. These are expressed in Ground.
[out]fThe Vector of n generalized forces that results from applying the forces F_GAo to the task frames. Resized if necessary.

Performance discussion

A call to this method costs 33*nt + 18*nb + 11*n flops. If you assume that nb ~= n >> 1, you could say this is about 30*(n+nt) flops. In contrast, assuming you already have the 6*nt X n Frame Jacobian JF available, you can compute the ~JF*F product in about 12*nt*n flops. For one or two tasks that would be faster than applying the operator. However forming JF costs about 180*(n+nt/4) flops (see calcFrameJacobian()). So to form even a one-task Frame Jacobian and use it once is about 6X more expensive than using the operator (192*n vs 30*n), but if you use it more than 10 times it is (marginally) cheaper to do it explicitly. For example, forming a one-task JF and using it 100 times costs around 1392*n flops while calling this method 100 times would cost about 3000*n flops.

Conclusion: in almost all practical cases you are better off using this operator rather than forming JF, even if you have only a single frame task and certainly if you have more than two tasks.

See also
multiplyByFrameJacobian(), calcFrameJacobian()

◆ multiplyByFrameJacobianTranspose() [2/2]

void SimTK::SimbodyMatterSubsystem::multiplyByFrameJacobianTranspose ( const State state,
MobilizedBodyIndex  onBodyB,
const Vec3 originAoInB,
const SpatialVec F_GAo,
Vector f 
) const
inline

Simplified signature for when you just have a single frame task.

See the other signature for documentation.

◆ calcFrameJacobian() [1/4]

void SimTK::SimbodyMatterSubsystem::calcFrameJacobian ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  originAoInB,
Matrix_< SpatialVec > &  JF 
) const

Explicitly calculate and return the 6*nt x n frame task Jacobian JF for a set of nt frame tasks A={Ai} fixed to nt bodies B={Bi}.

This matrix maps generalized speeds to the Cartesian spatial velocity (angular and linear velocity) of each frame, measured and expressed in Ground. That is, if you have a set of n generalized speeds u, you can find the Cartesian spatial velocities of task frames A as V_GA = JF*u, where V_GA is a 6*nt column vector. The transpose of this matrix maps a 6*nt vector of spatial forces F_GA (expressed in Ground and applied to the origins of frames A) to the equivalent set of n generalized forces f: f = ~JF*F_GA.

Note
It is almost always far more efficient to use multiplyByFrameJacobian() or multiplyByFrameJacobianTranspose() to form matrix-vector products rather than to use this method to form the Jacobian explicitly. See the performance discussion there.

Overloaded signatures of this method are available to allow you to obtain the Jacobian either as an nt X n Matrix with SpatialVec elements, or as 6*nt X n Matrix with scalar elements.

Parameters
[in]stateA State that has already been realized through Position stage.
[in]onBodyBAn array of nt mobilized bodies (one per task) to which the task frames of interest are fixed. These may be in any order and the same body may appear more than once if there are multiple task frames on it.
[in]originAoInBAn array of nt frame origin points Ao for the task frames of interest (one per task), each corresponding to one of the bodies B from onBodyB, given as vectors from each body B's origin Bo to its task frame origin Ao, expressed in frame B.
[out]JFThe resulting nt X n frame task Jacobian, with each element a SpatialVec. Resized if necessary.

Performance discussion

The cost of a call to this method is about 42*nt + 108*nb + 66*n flops. If we assume that nb ~= n >> 1, this is roughly 180*(n+nt/4) flops. Then once the Frame Jacobian JF has been formed, each JF*u matrix-vector product costs about 12*nt*n flops to form. When nt is small enough (say one or two tasks), and you plan to re-use it a lot, this can be computationally efficient; but for single use or more than a few tasks you can do much better with multiplyByFrameJacobian() or multiplyByFrameJacobianTranspose().

See also
multiplyByFrameJacobian(), multiplyByFrameJacobianTranspose()

◆ calcFrameJacobian() [2/4]

void SimTK::SimbodyMatterSubsystem::calcFrameJacobian ( const State state,
MobilizedBodyIndex  onBodyB,
const Vec3 originAoInB,
RowVector_< SpatialVec > &  JF 
) const
inline

Simplified signature for when you just have a single frame task.

See the other signature for documentation.

◆ calcFrameJacobian() [3/4]

void SimTK::SimbodyMatterSubsystem::calcFrameJacobian ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  originAoInB,
Matrix JF 
) const

Alternate signature that returns a frame Jacobian as a 6*nt X n Matrix rather than as an nt X n Matrix of SpatialVecs.

See the other signature for documentation and important performance considerations.

◆ calcFrameJacobian() [4/4]

void SimTK::SimbodyMatterSubsystem::calcFrameJacobian ( const State state,
MobilizedBodyIndex  onBodyB,
const Vec3 originAoInB,
Matrix JF 
) const
inline

Simplified signature for when you just have a single frame task.

See the other signature for documentation.

◆ calcBiasForFrameJacobian() [1/3]

void SimTK::SimbodyMatterSubsystem::calcBiasForFrameJacobian ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  originAoInB,
Vector_< SpatialVec > &  JFDotu 
) const

Calculate the acceleration bias term for a task frame Jacobian, that is, the parts of the frames' accelerations that are due only to velocities.

This term is also known as the Coriolis acceleration, and it is returned here as spatial accelerations of the frames in Ground.

There is a simplified signature of this method available if you have only a single frame task.

Parameters
[in]stateA State that has already been realized through Velocity stage.
[in]onBodyBAn array of nt mobilized bodies (one per task) to which the task frames of interest are fixed. These may be in any order and the same body may appear more than once if there are multiple task frames on it.
[in]originAoInBAn array of nt frame origin points Ao for the task frames of interest (one per task), each corresponding to one of the bodies B from onBodyB, given as vectors from each body B's origin Bo to its task frame origin Ao, expressed in frame B.
[out]JFDotuThe result JFDot*u, where JF is the task frame Jacobian and JFDot its time derivative, and u is the set of generalized speeds taken from the the supplied state.

Theory

The spatial velocity V_GA of frame A can be obtained from the generalized speeds u using the frame Jacobian for A, as V_GA = JF*u. Taking the time derivative in G gives

    A_GA = JF*udot + JFDot*u

This method returns JFDot*u, which depends only on configuration and velocities. Note that the same u is used to calculate JFDot, which is linear in u, so the term JFDot*u is quadratic in u.

Implementation

This method just obtains body B's total Coriolis acceleration already available in the state cache and shifts it to the A frame's origin Ao, for each of the nt task frames. Cost is 48*nt flops.

See also
getTotalCoriolisAcceleration(), shiftAccelerationBy()

◆ calcBiasForFrameJacobian() [2/3]

void SimTK::SimbodyMatterSubsystem::calcBiasForFrameJacobian ( const State state,
const Array_< MobilizedBodyIndex > &  onBodyB,
const Array_< Vec3 > &  originAoInB,
Vector JFDotu 
) const

Alternate signature that returns the bias as a 6*nt-vector of scalars rather than as an nt-vector of SpatialVec elements.

See the other signature for documentation.

◆ calcBiasForFrameJacobian() [3/3]

SpatialVec SimTK::SimbodyMatterSubsystem::calcBiasForFrameJacobian ( const State state,
MobilizedBodyIndex  onBodyB,
const Vec3 originAoInB 
) const
inline

Simplified signature for when you just have a single frame task.

Returns
JFDot*u, where JFDot is the frame task Jacobian time derivative and u the generalized speeds taken from state.

◆ multiplyByM()

void SimTK::SimbodyMatterSubsystem::multiplyByM ( const State state,
const Vector a,
Vector Ma 
) const

This operator calculates in O(n) time the product M*v where M is the system mass matrix and v is a supplied mobility-space vector (that is, it has one entry for each of the n mobilities).

If v is a set of mobility accelerations (generalized accelerations udot), then the result is a generalized force (f=M*udot). Only the supplied vector is used, and M depends only on position states, so the result here is not affected by velocities in the State. Constraints and prescribed motions are ignored.

The current implementation requires about 120*n flops and does not require realization of composite-body or articulated-body inertias.

Required stage
Stage::Position

◆ multiplyByMInv()

void SimTK::SimbodyMatterSubsystem::multiplyByMInv ( const State state,
const Vector v,
Vector MinvV 
) const

This operator calculates in O(n) time the product M^-1*v where M is the system mass matrix and v is a supplied vector with one entry per u-space mobility.

If v is a set of generalized forces f, the result is a generalized acceleration (udot=M^-1*f). Only the supplied vector is used, and M depends only on position states, so the result here is not affected by velocities in state. In particular, you'll have to obtain your own inertial forces and put them in f if you want them included.

Parameters
[in]stateThis is a State that has been realized through Position stage, from which the current system configuration and articulated body inertias are obtained. If necessary, the articulated body inertias will be realized in the state the first time this is called. They will then be retained in the state cache for speed.
[in]vThis is a generalized-force like vector in mobility space (u-space). If there is any prescribed motion specified using Motion objects or mobilizer locking (see below), then only the entries of v corresponding to non-prescribed mobilities are examined by this method; the prescribed ones are not referenced at all.
[out]MinvVThis is the result M^-1*v. If there is any prescribed motion specified using Motion objects or mobilizer locks (see below), then only the non-prescribed entries in MinvV are calculated; the prescribed ones are set to zero.

Behavior with prescribed motion

If you prescribe the motion of one or more mobilizers using Motion objects or mobilizer locking, the behavior of this method is altered. (This does not apply if you use Constraint objects to specify the motion.) With prescribed motion enabled, this method works only with the free (non-prescribed) mobilities. Only the entries in v corresponding to free mobilities are examined, and only the entries in the result MinvV corresponding to free mobilities are calculated; the others are set to zero.

Theory

View the unconstrained, prescribed zero-velocity equations of motion M udot + tau = f as partitioned into "free" and "prescribed" variables like this:

    [M_ff ~M_fp] [udot_f]   [ 0 ]   [f_f]
    [          ] [      ] + [   ] = [   ]
    [M_fp  M_pp] [udot_p]   [tau]   [f_p]

The free and prescribed variables have been grouped here for clarity but in general they are interspersed among the columns and rows of M.

Given that decomposition, this method returns

    [udot_f]   [udot_f]   [M_ff^-1  0  ][f_f]
    [      ] = [      ] = [            ][   ]
    [udot_p]   [  0   ]   [   0     0  ][f_p]

When there is no prescribed motion M_ff is the entire mass matrix, and the result is udot_f=udot=M^-1*f. When there is prescribed motion, M_ff is a submatrix of M, and the result is the nf elements of udot_f, with udot_p=0.

Implementation

This is a stripped-down version of forward dynamics. It requires the hybrid free/prescribed articulated body inertias to have been realized and will initiate that calculation if necessary the first time it is called for a given configuration q. The M^-1*f calculation requires two sweeps of the multibody tree, an inward sweep to accumulate forces, followed by an outward sweep to propagate accelerations.

Performance

If the supplied State does not already contain realized values for the articulated body inertias, then they will be realized when this operator is first called for a new set of positions. Calculating articulated body inertias is O(n) but relatively expensive. Once the appropriate articulated body inertias are available, repeated calls to this operator are very fast, with worst case around 80*n flops when all mobilizers have 1 dof. If you want to force realization of the articulated body inertias, call the method realizeArticulatedBodyInertias().

Required stage
Stage::Position (articulated body inertias realized first if necessary)
See also
multiplyByM(), calcMInv(), realizeArticulatedBodyInertias()

◆ calcM()

void SimTK::SimbodyMatterSubsystem::calcM ( const State ,
Matrix M 
) const

This operator explicitly calculates the n X n mass matrix M.

Note that this is inherently an O(n^2) operation since the mass matrix has n^2 elements (although only n(n+1)/2 are unique due to symmetry). DO NOT USE THIS CALL DURING NORMAL DYNAMICS. To do so would change an O(n) operation into an O(n^2) one. Instead, see if you can accomplish what you need with O(n) operators like multiplyByM() which calculates the matrix-vector product M*v in O(n) without explicitly forming M. Also, don't invert this matrix numerically to get M^-1. Instead, call the method calcMInv() which can produce M^-1 directly.

Required stage
Stage::Position
See also
multiplyByM(), calcMInv()

◆ calcMInv()

void SimTK::SimbodyMatterSubsystem::calcMInv ( const State ,
Matrix MInv 
) const

This operator explicitly calculates the inverse of the part of the system mobility-space mass matrix corresponding to free (non-prescribed) mobilities.

The returned matrix is always n X n, but rows and columns corresponding to prescribed mobilities are zero. This is an O(n^2) operation, which is of course within a constant factor of optimal for returning a matrix with n^2 elements explicitly. (There are actually only n(n+1)/2 unique elements since the matrix is symmetric.) DO NOT USE THIS CALL DURING NORMAL DYNAMICS. To do so would change an O(n) operation into an O(n^2) one. Instead, see if you can accomplish what you need with O(n) operators like multiplyByMInv() which calculates the matrix-vector product M^-1*v in O(n) without explicitly forming M or M^-1. If you need M explicitly, you can get it with the calcM() method.

Required stage
Stage::Position (articulated body inertias realized first if necessary)
See also
multiplyByMInv(), calcM()

◆ calcProjectedMInv()

void SimTK::SimbodyMatterSubsystem::calcProjectedMInv ( const State s,
Matrix GMInvGt 
) const

This operator calculates in O(m*n) time the m X m "projected inverse mass matrix" or "constraint compliance matrix" W=G*M^-1*~G, where G (mXn) is the acceleration-level constraint Jacobian mapped to generalized coordinates, and M (nXn) is the unconstrained system mass matrix.

In case there is prescribed motion specified with Motion objects or mobilizer locking, M^-1 here is really M_ff^-1, that is, it is restricted to the free (non-prescribed) mobilities, but scattered into a full n X n matrix (conceptually). See multiplyByMInv() and calcMInv() for more information.

W is the projection of the inverse mass matrix into the constraint coordinate space (that is, the vector space of the multipliers lambda). It can be used to solve for the constraint forces that will eliminate a given constraint acceleration error:

    (1)     W * lambda = aerr
    (2)     aerr = G*udot - b(t,q,u)

where udot is an unconstrained generalized acceleration. Note that you can view equation (1) as a dynamic system in a reduced set of m generalized coordinates, with the caveat that W may be singular.

In general W is singular and does not uniquely determine lambda. Simbody normally calculates a least squares solution for lambda so that loads are distributed among redundant constraints.

Note
If you just need to multiply W by a vector or matrix, you do not need to form W explicitly. Instead you can use the method described in the Implementation section to produce a W*v product in the O(n) time it takes to compute a single column of W.

Implementation

We are able to form W without forming G or M^-1 and without performing any matrix-matrix multiplies. Instead, W is calculated using m applications of O(n) operators:

Even if G and M^-1 were already available, computing W by matrix multiplication would cost O(m^2*n + m*n^2) time and O(m*n) intermediate storage. Here we do it in O(m*n) time with O(n) intermediate storage, which is a lot better.

Required stage
Stage::Velocity (articulated body inertias realized first if necessary)
See also
multiplyByG(), calcG(), multiplyByGTranspose(), calcGTranspose()
multiplyByMInv(), calcMInv()

◆ solveForConstraintImpulses()

void SimTK::SimbodyMatterSubsystem::solveForConstraintImpulses ( const State state,
const Vector deltaV,
Vector impulse 
) const

Given a set of desired constraint-space speed changes, calculate the corresponding constraint-space impulses that would cause those changes.

Here we are solving the equation

    W * impulse = deltaV

for impulse, where W=G*M^-1*~G is the "projected inverse mass matrix" as described for calcProjectedMInv(). In general W is singular due to constraint redundancies, so the solution for impulse is not unique. Simbody handles redundant constraints by finding least squares solutions, and this operator method duplicates the method Simbody uses for determining the rank and performing the factorization of W.

Parameters
[in]stateThe State whose generalized coordinates and speeds define the matrix W. Must already be realized to Velocity stage.
[in]deltaVThe set of desired velocity changes to be produced by the impulse, in constraint space. These will consist of observed velocity constraint violations (-verr) and constraint violations that would be generated by impulsive applied forces (-G*M^-1*f).
[out]impulseThe set of constraint multiplier-space impulses that will produce the desired velocity changes without violating the constraints.

To convert these constraint-space impulses into updates to the mobility-space generalized speeds u, use code like this:

const SimbodyMatterSubsystem& matter=...;
Vector deltaV=...; // constraint space speed change desired; length m
Vector impulse; // constraint space impulses; length m
solveForConstraintImpulses(state, deltaV, impulse);
Vector f; // mobility space impulses; length n
Vector du; // change to generalized speeds u; length n
matter.multiplyByGTranspose(s,impulse,f);
matter.multiplyByMInv(s,f,du);
state.updU() += du; // update generalized speeds

Note that the length of the constraint-space vectors is m=mp+mv+ma, the total number of acceleration-level constraints including the second time derivatives of the position (holonomic) constraints, the first time derivatives of the velocity (nonholonomic) constraints, and the acceleration-only constraints.

See also
calcProjectedMInv(), multiplyByGTranspose(), multiplyByMInv()

◆ multiplyByG() [1/2]

void SimTK::SimbodyMatterSubsystem::multiplyByG ( const State state,
const Vector ulike,
Vector Gulike 
) const
inline

Returns Gulike = G*ulike, the product of the mXn acceleration constraint Jacobian G and a "u-like" (mobility space) vector of length n.

m is the number of active acceleration-level constraint equations, n is the number of mobilities. This is an O(m+n) operation.

If you are going to call this method repeatedly at the same time, positions and velocities, you should precalculate the bias term once and supply it to the alternate signature of this method. See the Implementation section for more information.

Precondition
state realized to Velocity stage
Implementation
This is accomplished by treating the input vector ulike as though it were a set of generalized accelerations (for nonholonomic and acceleration-only constraints) or generalized speeds (for holonomic constraints). These are mapped to body accelerations (or velocities) in O(n) time. See calcBodyAccelerationFromUDot() for more information (converting from generalized speeds to velocities is just multiplying by the System Jacobian). The method calcBiasForMultiplyByG() is used to determine the state-dependent term of the constraint error equations. Then a second call is made to evaluate the bias term aerr(t,q,u;0)=-b(t,q,u). We then calculate Gulike = aerr(t,q,u;ulike)-aerr(t,q,u;0) in O(m) time.
See also
calcBiasForMultiplyByG()

◆ multiplyByG() [2/2]

void SimTK::SimbodyMatterSubsystem::multiplyByG ( const State state,
const Vector ulike,
const Vector bias,
Vector Gulike 
) const

Multiply Gulike=G*ulike using the supplied precalculated bias vector to improve performance (approximately 2X) over the other signature.

See also
calcBiasForMultiplyByG()

◆ calcBiasForMultiplyByG()

void SimTK::SimbodyMatterSubsystem::calcBiasForMultiplyByG ( const State state,
Vector bias 
) const

Calculate the bias vector needed for the higher-performance signature of the multiplyByG() method above.

Parameters
[in]stateProvides time t, positions q, and speeds u; must be realized through Velocity stage so that all body spatial velocities are known.
[out]biasThis is the bias vector for use in repeated calls to multiplyByG(). It will be resized if necessary to length m=mp+mv+ma, the total number of active acceleration-level constraint equations.
Precondition
state realized to Velocity stage
Implementation
This method uses either velocity- or acceleration- level constraint error functions with zero input to determine the bias term for use in multiplyByG(). Body quantities and generalized quantities are supplied to each of the m active constraints' (constant time) error methods to calculate
   pverr(t,q,u;ulike)=G*ulike - c(t,q)    (holonomic) 
or aerr(t,q,u;ulike)=G*ulike - b(t,q,u)   (nonholonomic or acceleration-only)
with ulike=0, giving the bias term in O(m) time.

If you want the acceleration-level bias terms b for all the constraints, even if they are holonomic, use calcBiasForAccelerationConstraints().

◆ calcG()

void SimTK::SimbodyMatterSubsystem::calcG ( const State state,
Matrix G 
) const

This O(m*n) operator explicitly calculates the m X n acceleration-level constraint Jacobian G which appears in the system equations of motion.

Consider using the multiplyByG() method instead of this one, which forms the matrix-vector product G*v in O(m+n) time without explicitly forming G.

Implementation
This method generates G columnwise using repeated calls to multiplyByG(), which makes use of the constraint error methods to perform a G*v product in O(m+n) time. To within numerical error, for non-working constraints this should be identical to the transpose of the matrix returned by calcGt() which uses the constraint force methods instead.
See also
multiplyByG(), calcGt(), calcPq()

◆ calcBiasForAccelerationConstraints()

void SimTK::SimbodyMatterSubsystem::calcBiasForAccelerationConstraints ( const State state,
Vector bias 
) const

Calculate the acceleration constraint bias vector, that is, the terms in the acceleration constraints that are independent of the accelerations.

Parameters
[in]stateProvides time t, positions q, and speeds u; must be realized through Velocity stage so that all body spatial velocities are known.
[out]biasThis is the bias vector for all the acceleration constraint equations together. It will be resized if necessary to length m=mp+mv+ma, the total number of active acceleration-level constraint equations.
Precondition
state realized to Velocity stage
Implementation
We have constant-time constraint acceleration error methods
   
paerr(t,q,u;udot)=P*udot - b_p(t,q,u) 
vaerr(t,q,u;udot)=V*udot - b_v(t,q,u) 
 aerr(t,q,u;udot)=A*udot - b_a(t,q,u)   
that together define the acceleration constraint equation G*udot-b=0 where G=[P;V;A] and b=[b_p b_v b_a]. There is one of these error functions for each Constraint, with paerr() the twice-differentiated position (holonomic) constraints, vaerr() the once-differentiated velocity (nonholonomic) constraints, and aerr() the acceleration-only constraints. This method sets udot = 0 and invokes each of those methods to obtain bias = -[b_p b_v b_a].

Performance note

The actual acceleration constraint functions require both udot and body accelerations for the constrained bodies; even with udot==0 body accelerations may have a non-zero velocity-dependent component (the coriolis accelerations). Those are already available in the state, but only as accelerations in Ground. For constraints that have a non-Ground Ancestor, we have to convert the accelerations to A at a cost of 105 flops/constrained body.

See also
calcConstraintAccelerationErrors()

◆ calcConstraintAccelerationErrors()

void SimTK::SimbodyMatterSubsystem::calcConstraintAccelerationErrors ( const State state,
const Vector knownUDot,
Vector pvaerr 
) const

Given a complete set of nu generalized accelerations udot, this operator computes the constraint acceleration errors that result due to the constraints currently active in the given state:

       pvaerr = G udot - b(t,q,u)
             where
              [P]    [bp]
            G=[V]  b=[bv]
              [A]    [ba]

The quantity Subsystem::getUDotErr() is computed by the same operation as this method performs.

Parameters
[in]stateA State compatible with this System that has already been realized to Stage::Velocity.
[in]knownUDotA complete set of generalized accelerations. Must have the same length as the number of mobilities nu, or if length zero the udots will be taken as all zero in which case only the bias vector -b will be returned.
[out]pvaerrThe error in the acceleration-level constraint equations. All acceleration-level constraints are included: holonomic second derivatives, nonholonomic first derivatives, and acceleration-only constraints. The vector will be resized if necessary to length m=mp+mv+ma, the total number of active acceleration-level constraint equations.
Implementation
This operator takes O(m+n) time.
Required stage
Stage::Velocity
See also
calcG(), calcBiasForAccelerationConstraints()

◆ multiplyByGTranspose()

void SimTK::SimbodyMatterSubsystem::multiplyByGTranspose ( const State state,
const Vector lambda,
Vector f 
) const

Returns f = ~G*lambda, the product of the n X m transpose of the acceleration constraint Jacobian G (=[P;V;A]) and a multiplier-like vector lambda of length m, returning a generalized-force like quantity f of length n.

m=mp+mv+ma is the total number of active constraint equations, n (==nu) is the number of mobilities (generalized speeds u). If lambda is a set of constraint multipliers, then f=~G*lambda is the set of forces generated by the constraints, mapped into generalized forces. This is an O(m+n) operation.

Because the velocity (non-holonomic) or acceleration-only constraint Jacobians V and A can have velocity dependence, the state supplied here must generally be realized through Velocity stage. If the system has only position (holonomic) constraints then the state need be realized only through Position stage.

Parameters
[in]stateA State that has been realized through Velocity stage (or Position stage if the system has no velocity-dependent constraint Jacobians). Configuration and velocities if needed are taken from state.
[in]lambdaA multiplier-like vector to be multiplied by ~G. Its length must be the same as the total number of active constraint equations m.
[out]fThis is the generalized force-like output. It will be resized if necessary to length equal to the number of mobilities (generalized speeds) n (==nu).
Implementation
This is accomplished by treating the input vector lambda as though it were a set of Lagrange multipliers, then calling each of the active Constraints' (constant time) force generation methods, providing the appropriate subset of the multipliers each time. That gives body forces F0 and mobility forces f0 in O(m) time. We then use the equivalent of multiplyBySystemJacobianTranspose() to convert the returned body spatial forces to generalized forces in O(n) time, and finally return the generalized force-like result f = ~J*F0 + f0.
See also
multiplyByG(), multiplyBySystemJacobianTranspose()

◆ calcGTranspose()

void SimTK::SimbodyMatterSubsystem::calcGTranspose ( const State ,
Matrix Gt 
) const

This O(nm) operator explicitly calculates the n X m transpose of the acceleration-level constraint Jacobian G = [P;V;A] which appears in the system equations of motion.

This method generates ~G columnwise use the constraint force generating methods which map constraint multipliers to constraint forces. To within numerical error, this should be identical to the transpose of the matrix returned by calcG() which uses a different method. Consider using the multiplyByGTranspose() method instead of this one, which forms the matrix-vector product ~G*v in O(n) time without explicitly forming ~G.

Required stage
Stage::Velocity
See also
calcG(), multiplyByGTranspose()

◆ multiplyByPq() [1/2]

void SimTK::SimbodyMatterSubsystem::multiplyByPq ( const State state,
const Vector qlike,
Vector PqXqlike 
) const
inline

Calculate in O(n) time the product Pq*qlike where Pq is the mp X nq position (holonomic) constraint Jacobian and qlike is a "q-like" (generalized coordinate space) vector of length nq.

Here mp is the number of active position-level constraint equations in this system.

If you are going to call this method repeatedly at the same time t and configuration q and want maximum efficiency, you can gain a factor of almost 2X by precalculating a bias term once using calcBiasForMultiplyByPq() and supplying it to the alternate signature of this method. See the Theory section below for an explanation of the bias term.

Precondition
state realized to Position stage

Theory

Simbody's position (holonomic) constraints are defined by the constraint error equation

    (1)    perr(t;q) = p(t,q)

where we try to maintain perr=0 at all times. We also have available time derivatives of equation (1); the first time derivative is relevant here:

    (2)    pverr(t,q;qdot) = dperr/dt = Pq * qdot + Pt

where Pq=Dperr/Dq and Pt=Dperr/Dt (capital "D" means partial derivative). Pt=Pt(t,q) is called the "bias" term. (Note that because u=N^-1*qdot we also have Pq=P*N^-1, where P=Dpverr/Du is the very useful mobility-space holonomic constraint Jacobian.) Eq. (2) can be used to perform efficient multiplication by Pq, since it can be used to calculate Pq*qlike+Pt, and a second evaluation at qlike=0 can be used to calculate the unwanted bias term for removal:

    (3)    Pq*qlike = pverr(t,q;qlike) - pverr(t,q;0)  

Despite appearances, eq. (2) calculates its result in constant time per constraint equation, for a total cost that is O(n) or more strictly O(mp+nq). The matrix Pq is never actually formed; instead the matrix-vector product is calculated directly.

Implementation

We treat the input vector qlike as though it were a set of generalized coordinate derivatives qdot. These are mapped to body velocities V in O(n) time, using V=Jq*qdot, where Jq is the coordinate space system Jacobian (partial velocity matrix), with Jq=J*N^-1. Then the body velocities and qdots are supplied to each of the mp active position constraints' (constant time) velocity error methods to get pverr(t,q;qlike)=Pq*qlike-Pt in O(n) time. A second call is made to evaluate the bias term pverr(t,q;0)=-Pt. We then calculate the result PqXqlike = pverr(t,q;qlike)-pverr(t,q;0) in O(n) time using equation (3).

See also
calcBiasForMultiplyByPq()

◆ multiplyByPq() [2/2]

void SimTK::SimbodyMatterSubsystem::multiplyByPq ( const State state,
const Vector qlike,
const Vector biasp,
Vector PqXqlike 
) const

Multiply Pq*qlike using the supplied precalculated bias vector to improve performance (approximately 2X) over the other signature.

See also
calcBiasForMultiplyByPq()

◆ calcBiasForMultiplyByPq()

void SimTK::SimbodyMatterSubsystem::calcBiasForMultiplyByPq ( const State state,
Vector biasp 
) const

Calculate the bias vector needed for the higher-performance signature of the multiplyByPq() method above.

Parameters
[in]stateProvides time t, and positions q; must be realized through Position stage so that all body spatial poses are known.
[out]biaspThis is the bias vector for use in repeated calls to multiplyByPq(). It will be resized if necessary to length mp, the total number of active position-level (holonomic) constraint equations.
Precondition
state realized to Position stage

See multiplyByPq() for theory and implementation; this method is just performing the qlike=0 case described there for calculating the bias term Pt.

◆ calcPq()

void SimTK::SimbodyMatterSubsystem::calcPq ( const State state,
Matrix Pq 
) const

This O(m*n) operator explicitly calculates the mp X nq position-level (holonomic) constraint Jacobian Pq (=P*N^-1), the partial derivative of the position error equations with respect to q.

Consider using the multiplyByPq() method instead of this one, which forms the matrix-vector product Pq*v in O(m+n) time without explicitly forming Pq.

Note that quaternion normalization constraints are not included in mp; we do not consider those holonomic constraints.

Precondition
state realized to Position stage
Parameters
[in]stateA State realized through Position stage so that time and the pose (configuration) of each body is known.
[out]PqThe position constraint Jacobian Dperr/Dq. This will be resized to mp X nq if necessary.
Implementation
This method generates Pq columnwise using repeated calls to multiplyByPq(), which makes use of the position constraint velocity-level error methods to perrform a Pq*v product in O(m+n) time. See multiplyByPq() for a more detailed explanation. If Pq's columns are in contiguous memory we'll work in place, otherwise columns are generated into a contiguous temporary and then copied into Pq.
See also
multiplyByPq()

◆ multiplyByPqTranspose()

void SimTK::SimbodyMatterSubsystem::multiplyByPqTranspose ( const State state,
const Vector lambdap,
Vector f 
) const

Returns f = ~Pq*lambdap, the product of the n X mp transpose of the position (holonomic) constraint Jacobian Pq (=P*N^-1) and a multiplier-like vector lambdap of length mp, returning a generalized-force like quantity f of length n.

mp is the number of active position constraint equations, n (==nu) is the number of mobilities (generalized speeds u). If lambdap is a set of mp constraint multipliers, then f=~G*lambdap is the set of forces generated by the position constraints, mapped into generalized forces. This is an O(mp+n) operation.

A holonomic constraint Jacobian cannot have a velocity dependence, so the state need be realized only to Position stage here.

Parameters
[in]stateA State that has been realized through Position stage. Time and configuration are taken from state.
[in]lambdapA multiplier-like vector to be multiplied by ~Pq. Its length must be the same as the number of active position constraint equations mp.
[out]fThis is the generalized force-like output. It will be resized if necessary to length equal to the number of mobilities (generalized speeds) n (==nu).
Implementation
This is accomplished by treating the input vector lambdap as though it were a set of Lagrange multipliers, then calling each of the active holonomic Constraints' (constant time) force generation methods, providing the appropriate subset of the multipliers each time. That gives body forces F0 and mobility forces f0 in O(mp) time. We then use the equivalent of multiplyBySystemJacobianTranspose() to convert the returned body spatial forces to generalized forces in O(n) time, and finally return the generalized force-like result f = ~J*F0 + f0.
See also
multiplyByPq(), multiplyBySystemJacobianTranspose()

◆ calcPqTranspose()

void SimTK::SimbodyMatterSubsystem::calcPqTranspose ( const State state,
Matrix Pqt 
) const

This O(m*n) operator explicitly calculates the nq X mp transpose of the position-level (holonomic) constraint Jacobian Pq (=P*N^-1), the partial derivative of the position error equations with respect to q.

Consider using the multiplyByPqTranspose() method instead of this one, which forms the matrix-vector product ~Pq*v in O(m+n) time without explicitly forming ~Pq.

Note that quaternion normalization constraints are not included in mp; we do not consider those holonomic constraints.

Precondition
state realized to Position stage
Parameters
[in]stateA State realized through Position stage so that time and the pose (configuration) of each body is known.
[out]PqtThe transposed position constraint Jacobian ~Pq=(Dperr/Dq)^T. This will be resized to nq X mp if necessary.
Implementation
This method generates Pqt columnwise using repeated calls to multiplyByPqTranspose(), which makes use of the position constraint force generating methods to perform a ~Pq*v product in O(m+n) time. See multiplyByPqTranspose() for a more detailed explanation. If Pqt's columns are in contiguous memory we'll work in place, otherwise columns are generated into a contiguous temporary and then copied into Pqt.
See also
multiplyByPqTranspose()

◆ calcP()

void SimTK::SimbodyMatterSubsystem::calcP ( const State state,
Matrix P 
) const

Returns the mp X nu matrix P which is the Jacobian of the first time derivative of the holonomic (position) constraint errors with respect to the generalized speeds u; that is, P = partial( dperr/dt )/partial(u).

Here mp is the number of holonomic constraint equations (not including quaternion normalization constraints) and nu is the total number of generalized speeds as found in the supplied State. P is resized if necessary; an error will be thrown if the Matrix is not the right size and not resizeable.

Precondition
state is realized to Position stage
Complexity:
Calculates the m X n matrix in O(m*n) time, which is good if you really need this matrix. However, in many cases what is really needed is the product of this matrix with a vector which can be done in O(n) time; consider whether you really need the whole matrix explicitly.
Required stage
Stage::Position

◆ calcPt()

void SimTK::SimbodyMatterSubsystem::calcPt ( const State state,
Matrix Pt 
) const

Returns the nu X mp matrix ~P - see calcP() for a description.

Required stage
Stage::Position

◆ multiplyByN()

void SimTK::SimbodyMatterSubsystem::multiplyByN ( const State s,
bool  transpose,
const Vector in,
Vector out 
) const

Calculate out_q = N(q)*in_u (like qdot=N*u) or out_u = ~N*in_q.

Note that one of "in" and "out" is always "q-like" while the other is "u-like", but which is which changes if the matrix is transposed. Note that the transposed operation here is the same as multiplying by N on the right, with the Vectors viewed as RowVectors instead. This is an O(n) operator since N is block diagonal.

Required stage
Stage::Position

◆ multiplyByNInv()

void SimTK::SimbodyMatterSubsystem::multiplyByNInv ( const State s,
bool  transpose,
const Vector in,
Vector out 
) const

Calculate out_u = NInv(q)*in_q (like u=NInv*qdot) or out_q = ~NInv*in_u.

Note that one of "in" and "out" is always "q-like" while the other is "u-like", but which is which changes if the matrix is transposed. Note that the transposed operation here is the same as multiplying by NInv on the right, with the Vectors viewed as RowVectors instead. This is an O(N) operator since NInv is block diagonal. The configuration q is taken from the supplied state.

Required stage
Stage::Position

◆ multiplyByNDot()

void SimTK::SimbodyMatterSubsystem::multiplyByNDot ( const State s,
bool  transpose,
const Vector in,
Vector out 
) const

Calculate out_q = NDot(q,u)*in_u or out_u = ~NDot(q,u)*in_q.

This is used, for example, as part of the conversion between udot and qdotdot. Note that one of "in" and "out" is always "q-like" while the other is "u-like", but which is which changes if the matrix is transposed. Note that the transposed operation here is the same as multiplying by NDot on the right, with the Vectors viewed as RowVectors instead. This is an O(N) operator since NDot is block diagonal. Configuration q and generalized speeds u are taken from the supplied state.

Required stage
Stage::Velocity

◆ calcAcceleration()

void SimTK::SimbodyMatterSubsystem::calcAcceleration ( const State state,
const Vector appliedMobilityForces,
const Vector_< SpatialVec > &  appliedBodyForces,
Vector udot,
Vector_< SpatialVec > &  A_GB 
) const

This is the primary forward dynamics operator.

It takes a state which has been realized to the Dynamics stage, a complete set of forces to apply, and returns the accelerations that result. Only the forces supplied here, and those calculated internally from prescribed motion, constraints, and centrifugal effects, affect the results. Acceleration constraints are always satisfied on return as long as the constraints are consistent. If the position and velocity constraints aren't already satisified in the State, results are harder to interpret physically, but they will still be calculated and the acceleration constraints will still be satisfied. No attempt will be made to satisfy position and velocity constraints, or to set prescribed positions and velocities, nor even to check whether these are satisfied; position and velocity constraint and prescribed positions and velocities are simply irrelevant here.

Given applied forces f_applied, this operator solves this set of equations:

     M udot + tau + ~G lambda + f_inertial = f_applied       (1)
                                  G udot   = b               (2)
                                    udot_p = udot_p(t,q,u,z) (3)

where udot={udot_f,udot_p}, tau={0,tau_p}. The unknowns are: the free generalized accelerations udot_f, the constraint multipliers lambda, and the prescribed motion generalized forces tau_p. A subset udot_p of udot may have been prescribed as a known function of state via Motion objects or locks associated with the mobilized bodies. On return all the entries in udot will have been set to their calculated or prescribed values, and body spatial accelerations A_GB (that is, measured and expressed in Ground) are also returned. Lambda and tau_p are necessarily calculated but are not returned here.

f_applied is the set of generalized (mobility) forces equivalent to the appliedMobilityForces and appliedBodyForces arguments supplied here. That is,

    f_applied = appliedMobilityForces + ~J * appliedBodyForces

where J is the system Jacobian mapping between spatial and generalized coordinates. Typically these forces will have been calculated as a function of state so we will have f_applied(t,q,u,z).

M(t,q), G(t,q,u), and b(t,q,u) are defined by the mobilized bodies and constraints present in the system. f_inertial(q,u) includes the velocity-dependent gyroscopic and coriolis forces due to rigid body rotations and is extracted internally from the already-realized state.

Note that this method does not allow you to specify your own prescribed udots; those are calculated from the mobilizers' state-dependent Motion specifications (or are zero due to mobilizer locks) that are already part of the system.

This is an O(n*m + m^3) operator where n is the number of generalized speeds and m the number of constraint equations (mobilities with prescribed motion are counted in n, not m).

Required stage
Stage::Dynamics (articulated body inertia will be realized if needed)

◆ calcAccelerationIgnoringConstraints()

void SimTK::SimbodyMatterSubsystem::calcAccelerationIgnoringConstraints ( const State state,
const Vector appliedMobilityForces,
const Vector_< SpatialVec > &  appliedBodyForces,
Vector udot,
Vector_< SpatialVec > &  A_GB 
) const

This operator is similar to calcAcceleration() but ignores the effects of acceleration constraints although it obeys prescribed accelerations.

The supplied forces, prescribed motion forces, and velocity-induced centrifugal and gyroscopic effects are properly accounted for, but any forces that would have resulted from enforcing the constraints are not present. This operator solves the equations

            M udot + tau + f_inertial = f_applied           (1)
                               udot_p = udot_p(t,q,u,z)     (2)

where udot={udot_f,udot_p}, tau={0,tau_p}. The unknowns are the free generalized accelerations udot_f and the prescribed motion generalized forces tau_p. f_inertial contains the velocity-dependent gyroscopic and coriolis forces due to rigid body rotations. No constraint forces are included.

On return all the entries in udot will have been set to their calculated or prescribed values, and body spatial accelerations A_GB (that is, measured and expressed in Ground) are also returned. tau_p is not returned.

This is an O(n) operator.

Required stage
Stage::Dynamics (articulated body inertia will be realized if needed)

◆ calcResidualForceIgnoringConstraints()

void SimTK::SimbodyMatterSubsystem::calcResidualForceIgnoringConstraints ( const State state,
const Vector appliedMobilityForces,
const Vector_< SpatialVec > &  appliedBodyForces,
const Vector knownUdot,
Vector residualMobilityForces 
) const

This is the inverse dynamics operator for the tree system; if there are any constraints or prescribed motion they are ignored.

This method solves

     f_residual = M udot + f_inertial - f_applied

for f_residual in O(n) time, meaning that the mass matrix M is never formed. Inverse dynamics is considerably faster than forward dynamics, even though both are O(n) in Simbody.

In the above equation we solve for the residual forces f_residual given desired accelerations and (optionally) a set of applied forces. Here f_applied is the mobility-space equivalent of all the applied forces (including mobility and body forces), f_inertial is the mobility-space equivalent of the velocity-dependent inertial forces due to rigid body rotations (coriolis and gyroscopic forces), and udot is the given set of values for the desired generalized accelerations. The returned f_residual is the additional generalized force (that is, mobility force) that would have to be applied at each mobility to give the desired udot. The inertial forces depend on the velocities u already realized in the State. Otherwise, only the explicitly-supplied forces affect the results of this operator; any forces that may be present elsewhere in the system are ignored.

Parameters
[in]stateA State valid for the containing System, already realized to Stage::Velocity.
[in]appliedMobilityForcesOne scalar generalized force applied per mobility. Can be zero length if there are no mobility forces; otherwise must have exactly one entry per mobility in the matter subsystem.
[in]appliedBodyForcesOne spatial force for each body. A spatial force is a force applied to the body origin and a torque on the body, each expressed in the Ground frame. Gravity, if present, is specified here as a body force. The supplied Vector must be either zero length (interpreted as all-zero) or have exactly one entry per body in the matter subsystem, starting with Ground as body zero.
[in]knownUdotThese are the desired generalized accelerations, one per mobility. If this is zero length it will be treated as all-zero; otherwise it must have exactly one entry per mobility in the matter subsystem.
[out]residualMobilityForcesThese are the residual generalized forces which, if added to the applied forces, would produce the given knownUdot in forward dynamics (assuming the system is unconstrained). This will be resized if necessary to have length nu; that is, one scalar entry per mobility. You can view this as a measure of how much the given knownUdot fails to satisfy the equations of motion.
Required stage
Stage::Velocity
See also
calcResidualForce(), multiplyByM()
calcAcceleration(), calcAccelerationIgnoringConstraints()

◆ calcResidualForce()

void SimTK::SimbodyMatterSubsystem::calcResidualForce ( const State state,
const Vector appliedMobilityForces,
const Vector_< SpatialVec > &  appliedBodyForces,
const Vector knownUdot,
const Vector knownLambda,
Vector residualMobilityForces 
) const

This is the inverse dynamics operator for when you know both the accelerations and Lagrange multipliers for a constrained system.

Prescribed motion is ignored. Using position and velocity from the given state, a set of applied forces, and a known set of generalized accelerations udot and constraint multipliers lambda, it calculates the additional generalized forces that would be required to satisfy Newton's 2nd law, f=Ma. That is, this operator returns

    f_residual = M udot + ~G lambda + f_inertial - f_applied

where f_applied is the mobility-space equivalent to all the applied forces (including mobility and body forces), f_inertial is the mobility-space equivalent of the velocity-dependent inertial forces due to rigid body rotations (coriolis and gyroscopic forces), and the udots and lambdas are given values of the generalized accelerations and constraint multipliers, resp.

Note that there is no requirement that the given udots satisfy the constraint equations; we simply solve the above equation for f_residual.

The inertial forces depend on the velocities u already realized in the State. Otherwise, only the explicitly-supplied forces affect the results of this operator; any forces that may be defined elsewhere in the system are ignored here.

Parameters
[in]stateA State valid for the containing System, already realized to Stage::Velocity.
[in]appliedMobilityForcesOne scalar generalized force applied per mobility. Can be zero length if there are no mobility forces; otherwise must have exactly one entry per mobility in the matter subsystem.
[in]appliedBodyForcesOne spatial force for each body. A spatial force is a force applied to the body origin and a torque on the body, each expressed in the Ground frame. Gravity, if present, is specified here as a body force. The supplied Vector must be either zero length (interpreted as all-zero) or have exactly one entry per body in the matter subsystem, starting with Ground as body zero.
[in]knownUdotThese are the specified generalized accelerations, one per mobility so the length should be nu. If this is zero length it will be treated as all-zero of length nu; otherwise it must have exactly one entry per mobility in the matter subsystem.
[in]knownLambdaThese are the specified Lagrange multipliers, one per constraint equation. If this is zero length it will be treated as all-zero; otherwise it must have exactly m entries, where m=mp+mv+ma is the total number of position, velocity, and acceleration-only constraints. There are no entries here corresponding to quaternion constraints, which do not generate forces.
[out]residualMobilityForcesThese are the residual generalized forces which, if added to the applied forces along with the constraint forces ~G*lambda, would produce the given knownUdot in unconstrained forward dynamics. This will be resized if necessary to have length nu; that is, one scalar entry per mobility. You can view this as a measure of how much the given udot and lambda fail to satisfy the equations of motion.
Required stage
Stage::Velocity
See also
calcResidualForceIgnoringConstraints()

◆ calcCompositeBodyInertias()

void SimTK::SimbodyMatterSubsystem::calcCompositeBodyInertias ( const State state,
Array_< SpatialInertia, MobilizedBodyIndex > &  R 
) const

This operator calculates the composite body inertias R given a State realized to Position stage.

Composite body inertias are the spatial mass properties of the rigid body formed by a particular body and all bodies outboard of that body as if all the outboard mobilizers were welded in their current orientations.

This is a very fast O(n) operator.

Required stage
Stage::Position

◆ calcBodyAccelerationFromUDot()

void SimTK::SimbodyMatterSubsystem::calcBodyAccelerationFromUDot ( const State state,
const Vector knownUDot,
Vector_< SpatialVec > &  A_GB 
) const

Given a complete set of n generalized accelerations udot, this kinematic operator calculates in O(n) time the resulting body accelerations, including velocity-dependent terms taken from the supplied state.

Precondition
state must already be realized to Velocity stage
Parameters
[in]stateThe State from which position- and velocity- related terms are taken; must already have been realized to Velocity stage.
[in]knownUDotA complete set of generalized accelerations. Must have the same length as the number of mobilities nu, or if length zero the udots will be taken as all zero in which case only velocity-dependent (Coriolis) accelerations will be returned in A_GB.
[out]A_GBSpatial accelerations of all the body frames measured and expressed in the Ground frame, resulting from supplied generalized accelerations knownUDot and velocity-dependent acceleration terms taken from state. This will be resized if necessary to the number of bodies including Ground so that the returned array may be indexed by MobilizedBodyIndex with A_GB[0]==0 always. The angular acceleration vector for MobilizedBody i is A_GB[i][0]; linear acceleration of the body's origin is A_GB[i][1].
Theory
The generalized speeds u and spatial velocities V are related by the system Jacobian J as V=J*u. Thus the spatial accelerations A=Vdot=J*udot+Jdot*u.
Implementation
The Coriolis accelerations Jdot*u are already available in a State realized to Velocity stage. The J*udot term is equivalent to an application of multiplyBySystemJacobian() to the knownUdot vector. The current implementation uses 12*nu + 18*nb flops to produce nb body accelerations.
Required stage
Stage::Velocity
See also
multiplyBySystemJacobian(), getTotalCoriolisAcceleration()

◆ calcConstraintForcesFromMultipliers()

void SimTK::SimbodyMatterSubsystem::calcConstraintForcesFromMultipliers ( const State state,
const Vector multipliers,
Vector_< SpatialVec > &  bodyForcesInG,
Vector mobilityForces 
) const

Treating all Constraints together, given a comprehensive set of m Lagrange multipliers lambda, generate the complete set of body spatial forces and mobility (generalized) forces applied by all the Constraints.

Spatial forces are applied at each body's origin and the moment and force vectors therein are expressed in the Ground frame. Watch the sign – normally constraint forces have opposite sign from applied forces, because our equations of motion are

   M udot + ~G lambda = f_applied  

If you want to take Simbody-calculated multipliers and use them to generate forces that look like applied forces, negate the multipliers in the argument passed to this call.

State must be realized to Stage::Velocity to call this operator (although typically the multipliers are obtained by realizing to Stage::Acceleration).

This is an O(m) operator. In particular it does not involve forming or multiplying by the constraint force matrix ~G. Instead, one constant-time call is made to each Constraint's calcConstraintForce methods.

Required stage
Stage::Velocity

◆ calcMobilizerReactionForces()

void SimTK::SimbodyMatterSubsystem::calcMobilizerReactionForces ( const State state,
Vector_< SpatialVec > &  forcesAtMInG 
) const

Calculate the mobilizer reaction force generated at each MobilizedBody, as felt at the mobilizer's outboard frame M, and expressed in Ground.

Parameters
[in]state
A State compatible with this System that has already been realized to Stage::Acceleration.
[out]forcesAtMInG
A Vector of spatial force vectors, indexed by MobilizedBodyIndex (beginning with 0 for Ground), giving the reaction moment and force applied by each body's unique inboard mobilizer to that body. The force is returned as though it were applied at the origin of the body's mobilizer frame M. The returned force is expressed in the Ground frame. Applied mobility (generalized) forces are included in the returned reaction forces.

A simple way to think of the reaction force is to think of cutting the mobilizer, then imagine the force required to make the system move in the same manner as when the mobilizer was present. This is what the reaction forces accomplish. With that definition, mobility forces (that is, generalized forces as opposed to body forces) are included in the reactions. Some conventions do not include the mobility forces in the definition of a reaction force. We chose to include them since this preserves Newton's 3rd law of equal and opposite reactions between bodies. Ours is the same convention as used in SD/FAST.

Note
You can think of the Ground body being welded to the universe at the Ground origin. The reactions reported for Ground are the ones that would occur in that Weld mobilizer if it were really present. That is, it includes the effects of all the base bodies on Ground.

How to find the reaction felt by the parent body

A mobilizer connects a frame F fixed on the parent (inboard) body P to a frame M fixed on the child (outboard) body B. It exerts equal and opposite reaction forces on the two bodies, at a given location in space. This method reports the force on the child body, as though it were applied at the origin Mo of frame M, and expressed in the Ground frame. The force on the parent body at Mo is just the negative of the returned value. However, it is more likely that you would want it as felt at Fo, the origin of the F frame on the parent. Here is one way to calculate that from the returned quantities:

matter.calcMobilizerReactionForces(state,forcesAtMInG); // This method.
const int nb = matter.getNumBodies();
Vector_<SpatialVec> forcesAtFInG(nb); // to hold the result
forcesAtFInG[0] = -forcesAtMInG[0]; // Ground is "welded" at origin
for (MobilizedBodyIndex i(1); i < nb; ++i) {
const MobilizedBody& mobod = matter.getMobilizedBody(i);
const MobilizedBody& parent = mobod.getParentMobilizedBody();
// Want to shift reaction by p_MF, the vector from M to F across the
// mobilizer, and negate. Can get p_FM; must reexpress in G.
const Vec3& p_FM = mobod.getMobilizerTransform(state).p();
const Rotation& R_PF = mobod.getInboardFrame(state).R(); // In parent.
const Rotation& R_GP = parent.getBodyTransform(state).R();
Rotation R_GF = R_GP*R_PF; // F frame orientation in Ground.
Vec3 p_MF_G = -(R_GF*p_FM); // Re-express and negate shift vector.
forcesAtFInG[i] = -shiftForceBy(forcesAtMInG[i], p_MF_G);
}

Implementation

This method combines already-calculated quantities to calculate the reactions. See Abhi Jain's 2011 book "Robot and Multibody Dynamics", Eq. 7.34 page 128:

   F_reaction = PPlus*APlus + zPlus  

where P is the articulated body inertia, A is the spatial acceleration, a the Coriolis acceleration and z the articulated body forces, and "Plus" indicates that we evaluate these on the inboard (parent) side of the mobilizer rather than on the body's side. (The alternative P(A-a)+z given there does not work for prescribed mobilizers unless you replace "a" with "a_underscore" from equation 16.14.) After calculating F_reaction at the body frame origin Bo, we shift it to M for reporting.

Performance

The cost of the above calculation is 114 flops/body. The code presented above for converting from M to F costs an additional 81 flops/body if you use it.

Required stage
Stage::Acceleration
See also
SimTK::MobilizedBody::findMobilizerReactionOnBodyAtMInGround()
calcMobilizerReactionForcesUsingFreebodyMethod()

◆ getMotionMultipliers()

const Vector& SimTK::SimbodyMatterSubsystem::getMotionMultipliers ( const State state) const

Return a reference to the prescribed motion multipliers tau that have already been calculated in the given state, which must have been realized through Acceleration stage.

The result contains entries only for prescribed mobilities; if you want these unpacked into u-space mobility forces, use findMotionForces() instead. A mobilizer may follow prescribed motion either because of a Motion object or a call to MobilizedBody::lock().

Required stage
Stage::Acceleration

◆ calcMotionErrors()

Vector SimTK::SimbodyMatterSubsystem::calcMotionErrors ( const State state,
const Stage stage 
) const

Calculate the degree to which the supplied state does not satisfy the prescribed motion requirements at a particular Stage.

For Position and Velocity stage, a call to the prescribe() solver using the same stage will eliminate the error. Accelerations should have been calculated to satisfy all prescribed accelerations, so the returned value should be zero always. The returned Vector has one element per known (prescribed) q, known u, or known udot.

The state must be realized to Time stage to check Position errors, Position stage to check Velocity errors, and Acceleration stage to check Acceleration errors.

Errors are calculated actualValue - prescribedValue so a positive error indicates that the value in state is too large.

◆ findMotionForces()

void SimTK::SimbodyMatterSubsystem::findMotionForces ( const State state,
Vector mobilityForces 
) const

Find the generalized mobility space forces produced by all the Motion objects active in this system.

These are the same values as returned by getMotionMultipliers() but unpacked into u-space slots, with zeroes corresponding to any "free" mobilities, that is, those whose motion is not prescribed.

Required stage
Stage::Acceleration

◆ getConstraintMultipliers()

const Vector& SimTK::SimbodyMatterSubsystem::getConstraintMultipliers ( const State state) const

Return a reference to the constraint multipliers lambda that have already been calculated in the given state, which must have been realized through Acceleration stage.

Constraint multipliers are not directly interpretable as forces; if you want the actual forces use findConstraintForces() instead. If you want to know individual Constraint contributions to these forces, ask the Constraint objects rather than this SimbodyMatterSubsystem object.

Required stage
Stage::Acceleration

◆ findConstraintForces()

void SimTK::SimbodyMatterSubsystem::findConstraintForces ( const State state,
Vector_< SpatialVec > &  bodyForcesInG,
Vector mobilityForces 
) const

Find the forces produced by all the active Constraint objects in this system.

Constraints produce both body spatial forces and generalized mobility-space forces. The supplied state must have been realized through Acceleration stage.

Required stage
Stage::Acceleration

◆ calcMotionPower()

Real SimTK::SimbodyMatterSubsystem::calcMotionPower ( const State state) const

Calculate the power being generated or dissipated by all the Motion objects currently active in this system.

The sign is chosen so that a positive value for power means the Motion is adding energy to the system; negative means it is removing energy. The state must already have been realized through Acceleration stage so that the prescribed motion forces are available.

Parameters
[in]stateA State realized through Acceleration stage from which we obtain the prescribed motion forces and the velocities needed to calculate power.

Implementation

We calculate power=-dot(tau, u) where tau is the set of mobility reaction forces generated by Motion objects and mobilizer locks (tau[i]==0 if mobility i is free), and u is the set of all generalized speeds.

Required stage
Stage::Acceleration
See also
calcConstraintPower()

◆ calcConstraintPower()

Real SimTK::SimbodyMatterSubsystem::calcConstraintPower ( const State state) const

Return the power begin generated or dissipated by all the Constraint objects currently active in this system.

The sign is chosen so that a positive value for power means the Constraints (taken together) are adding energy to the system; negative means they are removing energy. The state must already have been realized through Acceleration stage so that the constraint forces are available.

Note that if you want to know the power output of an individual Constraint, you should call that Constraint's calcPower() method; here they are all summed together.

Parameters
[in]stateA State realized through Acceleration stage from which we obtain the constraint forces and the velocities needed to calculate power.
Returns
The signed sum over all the Constraint objects of the power being generated or dissipated by each Constraint. A positive value means that together the constraints are adding energy to the system; negative means they are removing energy.

Implementation

We calculate power=-(dot(F,V)+dot(f,u)) where F is the set of body spatial reaction forces produced by the Constraints, V is the body spatial velocities, f is the set of mobility reaction forces produced by the Constraints, and u is the set of generalized speeds.

Required stage
Stage::Acceleration
See also
calcMotionPower()

◆ calcTreeEquivalentMobilityForces()

void SimTK::SimbodyMatterSubsystem::calcTreeEquivalentMobilityForces ( const State ,
const Vector_< SpatialVec > &  bodyForces,
Vector mobilityForces 
) const

Accounts for applied forces and inertial forces produced by non-zero velocities in the State.

Returns a set of mobility forces which replace both the applied bodyForces and the inertial forces.

Required stage
Stage::Dynamics

◆ calcQDot()

void SimTK::SimbodyMatterSubsystem::calcQDot ( const State s,
const Vector u,
Vector qdot 
) const

Calculate qdot = N(q)*u in O(n) time (very fast).

Note that q is taken from the supplied state while u is an argument to this operator method.

Required stage
Stage::Position

◆ calcQDotDot()

void SimTK::SimbodyMatterSubsystem::calcQDotDot ( const State s,
const Vector udot,
Vector qdotdot 
) const

Calculate qdotdot = N(q)*udot + Ndot(q,u)*u in O(n) time (very fast).

Note that q and u are taken from the supplied state while udot is an argument to this operator method.

Required stage
Stage::Velocity

◆ addInStationForce()

void SimTK::SimbodyMatterSubsystem::addInStationForce ( const State state,
MobilizedBodyIndex  bodyB,
const Vec3 stationOnB,
const Vec3 forceInG,
Vector_< SpatialVec > &  bodyForcesInG 
) const

Add in to the given body forces vector a force applied to a station (fixed point) S on a body B.

The new force is added into the existing spatial force slot for the body. Note that this does not actually apply any forces to the multibody system! This is just a "helper" utility that makes it easier to fill in a body forces array. This has no effect on the system unless you later supply the body forces array for use.

Provide the station in the body frame, force in the Ground frame.

Required stage
Stage::Position

◆ addInBodyTorque()

void SimTK::SimbodyMatterSubsystem::addInBodyTorque ( const State state,
MobilizedBodyIndex  mobodIx,
const Vec3 torqueInG,
Vector_< SpatialVec > &  bodyForcesInG 
) const

Add in to the given body forces vector a torque applied to a body B.

The new torque is added into the existing spatial force slot for the body. Note that this does not actually apply any torques to the multibody system! This is just a "helper" utility that makes it easier to fill in a body forces array. This has no effect on the system unless you later supply the body forces array for use. Provide the torque vector in the Ground frame.

◆ addInMobilityForce()

void SimTK::SimbodyMatterSubsystem::addInMobilityForce ( const State state,
MobilizedBodyIndex  mobodIx,
MobilizerUIndex  which,
Real  f,
Vector mobilityForces 
) const

Add in to the given mobility forces vector a scalar generalized force, that is a force or torque applied to a mobilizer generalized speed.

Note that this does not actually apply any forces to the multibody system! This is just a "helper" utility that makes it easier to fill in a mobility forces array. This has no effect on the system unless you later supply the mobility forces array for use. The meaning of a generalized force f is determined by the definition of the corresponding generalized speed u, so that f*u has physical units of power.

◆ realizePositionKinematics()

void SimTK::SimbodyMatterSubsystem::realizePositionKinematics ( const State state) const

Position kinematics is the first part of the Stage::Position realization, mapping generalized coordinates q to the spatial (Cartesian) poses of the mobilized bodies.

This mapping depends only on instance variables and q; it is time-independent, so does not get invalidated by a time change. This computation is normally initiated by a realize(state,Stage::Position) call, but you can realize just the kinematics explicitly here. The calculation will not be repeated when realizing Stage::Position for the same q values.

Required stage
Stage::Instance
See also
invalidatePositionKinematics()

◆ realizeVelocityKinematics()

void SimTK::SimbodyMatterSubsystem::realizeVelocityKinematics ( const State ) const

Velocity kinematics is the first part of the Stage::Velocity realization, mapping generalized speeds u to the spatial (Cartesian) velocities of the mobilized bodies.

This mapping depends only on instance variables, position kinematics, and u; it is time-independent, so does not get invalidated by a time change. This computation is normally initiated by a realize(state,Stage::Velocity) call, but you can realize just the kinematics explicitly here. The calculation will not be repeated when realizing Stage::Velocity for the same q and u values. Note that you must already have realized position kinematics in order to call this method.

Required stage
Stage::Position, or Stage::Instance and PositionKinematics
See also
invalidateVelocityKinematics()

◆ realizeCompositeBodyInertias()

void SimTK::SimbodyMatterSubsystem::realizeCompositeBodyInertias ( const State ) const

This method checks whether composite body inertias have already been computed since the last change to a Position stage state variable (q) and if so returns immediately at little cost; otherwise, it initiates computation of composite body inertias for all of the mobilized bodies.

These are not otherwise computed unless specifically requested.

Required stage
Stage::Position, or Stage::Instance and PositionKinematics
See also
invalidateCompositeBodyInertias()

◆ realizeArticulatedBodyInertias()

void SimTK::SimbodyMatterSubsystem::realizeArticulatedBodyInertias ( const State ) const

This method ensures that articulated body inertias (ABIs) are up to date with the most recent change to the configuration state variables q.

If already up to date, it returns immediately at little cost; otherwise, it initiates the relatively expensive computation of ABIs for all of the mobilized bodies, which will then be retained for reuse until the next configuration change. ABIs are not otherwise computed until they are needed for forward dynamics computations, typically due to realization of Stage::Acceleration. Invoking any operator that needs the effect of the inverse mass matrix will realize ABIs implicitly. They are guaranteed to be available by Stage::Acceleration.

Required stage
Stage::Position, or Stage::Instance and PositionKinematics
See also
invalidateArticulatedBodyInertias()

◆ realizeArticulatedBodyVelocity()

void SimTK::SimbodyMatterSubsystem::realizeArticulatedBodyVelocity ( const State ) const

(Advanced) This method ensures that velocity-dependent computations that also depend on articulated body inertias (ABIs) are up to date with the most recent changes to the configuration state variables q and velocity state variables u.

If already up to date, it returns immediately at little cost; otherwise, it initiates the computations for all of the mobilized bodies, which will then be retained for reuse until the next velocity change. ABI-dependent computations are not otherwise computed until they are needed for forward dynamics computations, typically due to realization of Stage::Acceleration. Invoking any operator that needs the effect of both the inverse mass matrix and internal Coriolis forces will realize these computations implicitly. They are guaranteed to be available by Stage::Acceleration.

Note that this method does not implicitly realize anything it depends on; you must make sure its prerequisites VelocityKinematics and ArticulatedBodyInertias are already realized; see realizeVelocityKinematics() and realizeArticulatedBodyInertias() for that purpose.

The actual computations here are not made available through the API since (unlike the ABIs) they are not particularly meaningful. They do save time during repeated acceleration computations where forces are changing but configuration and velocity are fixed; these are common. The ability to force realization here is provided so that you can make sure the state cache doesn't get implicitly updated behind your back; this can be necessary in some multithreaded applications.

Required stage
Stage::Instance and VelocityKinematics and ArticulatedBodyInertias
See also
invalidateArticulatedBodyVelocity()

◆ getFreeQIndex()

const Array_<QIndex>& SimTK::SimbodyMatterSubsystem::getFreeQIndex ( const State state) const

Return a list of the generalized coordinates q that are free, that is, not locked or prescribed with a Motion.

Required stage
Stage::Instance

◆ getFreeUIndex()

const Array_<UIndex>& SimTK::SimbodyMatterSubsystem::getFreeUIndex ( const State state) const

Return a list of the generalized speeds u that are free, that is, not locked or prescribed with a Motion.

Required stage
Stage::Instance

◆ getFreeUDotIndex()

const Array_<UIndex>& SimTK::SimbodyMatterSubsystem::getFreeUDotIndex ( const State state) const

Return a list of the generalized speeds whose time derivatives udot are unknown, that is, not locked or prescribed with a Motion.

This is the complement of getKnownUDotIndex().

Required stage
Stage::Instance

◆ getKnownUDotIndex()

const Array_<UIndex>& SimTK::SimbodyMatterSubsystem::getKnownUDotIndex ( const State state) const

Return a list of the generalized speeds whose time derivatives udot are known, that is, locked or prescribed with a Motion.

This is the complement of getFreeUDotIndex().

Required stage
Stage::Instance

◆ packFreeQ()

void SimTK::SimbodyMatterSubsystem::packFreeQ ( const State s,
const Vector allQ,
Vector packedFreeQ 
) const

Given a generalized coordinate (q-space) Vector, select only those elements that are free (in the sense of getFreeQIndex()) and pack them in order into packedFreeQ, which must already be allocated to the correct length, getFreeQIndex().size().

Required stage
Stage::Instance

◆ unpackFreeQ()

void SimTK::SimbodyMatterSubsystem::unpackFreeQ ( const State s,
const Vector packedFreeQ,
Vector unpackedFreeQ 
) const

Given a free-q Vector, unpack it into a q-space Vector which must already be allocated to the correct size.

The not-free elements already in unpackedFreeQ are not touched.

Required stage
Stage::Instance

◆ packFreeU()

void SimTK::SimbodyMatterSubsystem::packFreeU ( const State s,
const Vector allU,
Vector packedFreeU 
) const

Given a generalized speed (u- or mobility-space) Vector, select only those elements that are free (in the sense of getFreeUIndex()) and pack them in order into packedFreeU, which must already be allocated to the correct length, getFreeUIndex().size().

Required stage
Stage::Instance

◆ unpackFreeU()

void SimTK::SimbodyMatterSubsystem::unpackFreeU ( const State s,
const Vector packedFreeU,
Vector unpackedFreeU 
) const

Given a free-u Vector, unpack it into a u-space Vector which must already be allocated to the correct size.

The not-free elements already in unpackedFreeU are not touched.

Required stage
Stage::Instance

◆ getCompositeBodyInertia()

const SpatialInertia& SimTK::SimbodyMatterSubsystem::getCompositeBodyInertia ( const State state,
MobilizedBodyIndex  mbx 
) const

Return the composite body inertia (CBI) R for a particular mobilized body.

You can call this any time after the State has been realized to Position stage (or in fact any time after PositionKinematics have been realized). However, the first call to this method will trigger realization of all the CBIs if they have not already been calculated using realizeCompositeBodyInertias(). Ground is mobilized body zero; its CBI has infinite mass and principle moments of inertia, and center of mass at (0,0,0).

Although CBIs can be useful in inverse dynamics calculations, Simbody does not use them for that purpose so they won't be calculated unless requested.

Required stage
Stage::Position, or Stage::Instance and realizePositionKinematics()
See also
realizeCompositeBodyInertias()

◆ getArticulatedBodyInertia()

const ArticulatedInertia& SimTK::SimbodyMatterSubsystem::getArticulatedBodyInertia ( const State state,
MobilizedBodyIndex  mbx 
) const

Return the articulated body inertia (ABI) P for a particular mobilized body.

These are normally not needed until some forward dynamics operation is to be performed, such as realize(Acceleration) or applying the multiplyByMInv() operator. ABIs are expensive to calculate and require invertible mass properties so we normally defer their calculation until they are actually required. However, you can ask for an ABI anytime after the State has been realized to Position stage (or in fact any time after PositionKinematics have been realized). If ABIs haven't been calculated yet for the current configuration, either implicitly as discussed above or explicitly with realizeArticulatedBodyInertias(), then their calculation will be triggered by the first call to this method (they must all be calculated at the same time). ABIs are saved once calculated and will be reused until the configuration q changes.

Ground is mobilized body zero; its articulated body inertia is the same as its composite body inertia – an ordinary Spatial Inertia but with infinite mass and principle moments of inertia, and center of mass at (0,0,0).

Required stage
Stage::Position, or Stage::Instance and realizePositionKinematics()
See also
realizeArticulatedBodyInertias(), multiplyByMInv(), realizePositionKinematics()

◆ getGyroscopicForce()

const SpatialVec& SimTK::SimbodyMatterSubsystem::getGyroscopicForce ( const State state,
MobilizedBodyIndex  mbx 
) const

This is the rotational velocity-dependent force b on the body due to rotational inertia.

Required stage
Stage::Velocity

◆ getMobilizerCoriolisAcceleration()

const SpatialVec& SimTK::SimbodyMatterSubsystem::getMobilizerCoriolisAcceleration ( const State state,
MobilizedBodyIndex  mbx 
) const

This is the cross-mobilizer incremental contribution A to the Coriolis (angular velocity dependent) acceleration of a particular mobilized body; it is not too useful except as an intermediate calculation for more interesting quantities – you are probably interested in getTotalCoriolisAcceleration() instead.

Required stage
Stage::Velocity

◆ getTotalCoriolisAcceleration()

const SpatialVec& SimTK::SimbodyMatterSubsystem::getTotalCoriolisAcceleration ( const State state,
MobilizedBodyIndex  mbx 
) const

This is the total Coriolis acceleration of a particular mobilized body, including the effect of the parent's angular velocity as well as the mobilizer's.

This is one element of Jdot*u where J is the system kinematic Jacobian and u is the current set of generalized speeds in the supplied state. It is thus the remainder term in calculation of body accelerations from generalized accelerations udot: since V=J*u, A=J*udot + Jdot*u.

Required stage
Stage::Velocity

◆ getTotalCentrifugalForces()

const SpatialVec& SimTK::SimbodyMatterSubsystem::getTotalCentrifugalForces ( const State state,
MobilizedBodyIndex  mbx 
) const

This is the total rotational velocity-dependent force acting on this body B, including forces due to Coriolis acceleration and gyroscopic forces due to rotational inertia.

This is F=M*a+b where M is the spatial inertia matrix of body B (not its articulated body inertia), a is the total spatial Coriolis acceleration of B, and b is the (rotational velocity-dependent) spatial gyroscopic force acting on B.

Required stage
Stage::Velocity

◆ calcMobilizerReactionForcesUsingFreebodyMethod()

void SimTK::SimbodyMatterSubsystem::calcMobilizerReactionForcesUsingFreebodyMethod ( const State state,
Vector_< SpatialVec > &  forcesAtMInG 
) const

This is a slower alternative to calcMobilizerReactionForces(), for use in regression testing and Simbody development.

This method builds a freebody "diagram" for each body in turn to determine the unknown reaction force at its inboard mobilizer.

The given state must have been realized through Acceleration stage.

Implementation

We use a tip-to-base recursion in which we assemble all applied body forces from force elements, constraints, and gyroscopic effects and compare that with the apparent rigid body force determined from F=M*A where M is a body's spatial inertia (in G) and A its already-calculated spatial acceleration. The difference is the missing force applied by the body's mobilizer, i.e. the reaction force. That is shifted to the M frame and reported. Then the equal and opposite reaction is applied to the parent body and included in its collection of applied forces, which can be used to determine its reaction force and so on.

This is is about 3X slower than the method used by calcMobilizerReactionForces().

See also
calcMobilizerReactionForces()

◆ invalidatePositionKinematics()

void SimTK::SimbodyMatterSubsystem::invalidatePositionKinematics ( const State state) const

(Advanced) Force invalidation of position kinematics, which otherwise remains valid until an instance-stage variable or a generalized coordinate q is modified.

This is useful for timing computation time for realizePositionKinematics(), which otherwise will not recalculate if called repeatedly. Note that this also invalidates Position stage and above in state because position kinematics is assumed to be valid after Position stage, regardless of lazy evaluation status.

◆ isPositionKinematicsRealized()

bool SimTK::SimbodyMatterSubsystem::isPositionKinematicsRealized ( const State ) const

(Advanced) Check whether position kinematics has already been realized.

This will be true after realizePositionKinematics() or realize(Position); false after invalidation of Stage::Instance, a change to a generalized coordinate q, or after a call to invalidatePositionKinematics().

◆ invalidateVelocityKinematics()

void SimTK::SimbodyMatterSubsystem::invalidateVelocityKinematics ( const State state) const

(Advanced) Force invalidation of velocity kinematics, which otherwise remains valid until an instance-stage variable, generalized coordinate q, or generalized speed u is modified, or if PositionKinematics is explicitly invalidated.

This is useful for timing computation time for realizeVelocityKinematics(), which otherwise will not recalculate if called repeatedly. Note that this also invalidates Velocity stage and above in state because velocity kinematics is assumed to be valid after Velocity stage, regardless of lazy evaluation status.

◆ isVelocityKinematicsRealized()

bool SimTK::SimbodyMatterSubsystem::isVelocityKinematicsRealized ( const State ) const

(Advanced) Check whether velocity kinematics has already been realized.

This will be true after realizeVelocityKinematics() or realize(Velocity); false if isPositionKinematicsRealized() would return false, after a change to a generalized speed u, or after a call to invalidateVelocityKinematics().

◆ invalidateCompositeBodyInertias()

void SimTK::SimbodyMatterSubsystem::invalidateCompositeBodyInertias ( const State state) const

(Advanced) This is useful for timing computation time for realizeCompositeBodyInertias(), which otherwise will not recalculate them if called repeatedly.

◆ isCompositeBodyInertiasRealized()

bool SimTK::SimbodyMatterSubsystem::isCompositeBodyInertiasRealized ( const State ) const

(Advanced) Check whether composite body inertias have already been realized.

This will be true only after an explicit call to realizeCompositeBodyInertias(); false if isPositionKinematicsRealized() would return false or after a call to invalidateCompositeBodyInertias().

◆ invalidateArticulatedBodyInertias()

void SimTK::SimbodyMatterSubsystem::invalidateArticulatedBodyInertias ( const State state) const

(Advanced) Force invalidation of articulated body inertias (ABIs), which otherwise remain valid until a position-stage variable is modified or any other prerequisite is invalidated.

This is useful for timing computation time for realizeArticulatedBodyInertias(), which otherwise will not recalculate if called repeatedly. Note that this also invalidates Acceleration stage in state because ABIs are assumed to be valid after Acceleration stage, regardless of lazy evaluation status.

◆ isArticulatedBodyInertiasRealized()

bool SimTK::SimbodyMatterSubsystem::isArticulatedBodyInertiasRealized ( const State ) const

(Advanced) Check whether articulated body inertias have already been realized.

This will be true after realizeArticulatedBodyInertias() or realize(Acceleration); false if isPositionKinematicsRealized() would return false, or after a call to invalidateArticulatedBodyInertias().

◆ invalidateArticulatedBodyVelocity()

void SimTK::SimbodyMatterSubsystem::invalidateArticulatedBodyVelocity ( const State state) const

(Advanced) Force invalidation of articulated body velocity computations, which otherwise remain valid until a velocity- or position-stage variable is modified or any other prerequisite is invalidated.

This is useful for timing computation time for realizeArticulatedBodyVelocity(), which otherwise will not recalculate if called repeatedly. Note that this also invalidates Acceleration stage in state because these computations are assumed to be valid after Acceleration stage, regardless of lazy evaluation status.

◆ isArticulatedBodyVelocityRealized()

bool SimTK::SimbodyMatterSubsystem::isArticulatedBodyVelocityRealized ( const State ) const

(Advanced) Check whether articulated body velocity computations have already been realized.

This will be true after realizeArticulatedBodyVelocity() or realize(Acceleration); false if isArticulatedBodyInertiasRealized() or isVelocityKinematicsRealized() would return false, or after a call to invalidateArticulatedBodyVelocity().

◆ getNumParticles()

int SimTK::SimbodyMatterSubsystem::getNumParticles ( ) const

TODO: total number of particles.

◆ getAllParticleLocations()

const Vector_<Vec3>& SimTK::SimbodyMatterSubsystem::getAllParticleLocations ( const State ) const

TODO: total number of particles.

◆ getAllParticleVelocities()

const Vector_<Vec3>& SimTK::SimbodyMatterSubsystem::getAllParticleVelocities ( const State ) const

TODO: total number of particles.

◆ getParticleLocation()

const Vec3& SimTK::SimbodyMatterSubsystem::getParticleLocation ( const State s,
ParticleIndex  p 
) const
inline

TODO: total number of particles.

◆ getParticleVelocity()

const Vec3& SimTK::SimbodyMatterSubsystem::getParticleVelocity ( const State s,
ParticleIndex  p 
) const
inline

TODO: total number of particles.

◆ updAllParticleMasses()

Vector& SimTK::SimbodyMatterSubsystem::updAllParticleMasses ( State s) const

TODO: total number of particles.

◆ setAllParticleMasses()

void SimTK::SimbodyMatterSubsystem::setAllParticleMasses ( State s,
const Vector masses 
) const
inline

TODO: total number of particles.

◆ updAllParticleLocations()

Vector_<Vec3>& SimTK::SimbodyMatterSubsystem::updAllParticleLocations ( State ) const

TODO: total number of particles.

◆ updAllParticleVelocities()

Vector_<Vec3>& SimTK::SimbodyMatterSubsystem::updAllParticleVelocities ( State ) const

TODO: total number of particles.

◆ updParticleLocation()

Vec3& SimTK::SimbodyMatterSubsystem::updParticleLocation ( State s,
ParticleIndex  p 
) const
inline

TODO: total number of particles.

◆ updParticleVelocity()

Vec3& SimTK::SimbodyMatterSubsystem::updParticleVelocity ( State s,
ParticleIndex  p 
) const
inline

TODO: total number of particles.

◆ setParticleLocation()

void SimTK::SimbodyMatterSubsystem::setParticleLocation ( State s,
ParticleIndex  p,
const Vec3 r 
) const
inline

TODO: total number of particles.

◆ setParticleVelocity()

void SimTK::SimbodyMatterSubsystem::setParticleVelocity ( State s,
ParticleIndex  p,
const Vec3 v 
) const
inline

TODO: total number of particles.

◆ setAllParticleLocations()

void SimTK::SimbodyMatterSubsystem::setAllParticleLocations ( State s,
const Vector_< Vec3 > &  r 
) const
inline

TODO: total number of particles.

◆ setAllParticleVelocities()

void SimTK::SimbodyMatterSubsystem::setAllParticleVelocities ( State s,
const Vector_< Vec3 > &  v 
) const
inline

TODO: total number of particles.

◆ getAllParticleMasses()

const Vector& SimTK::SimbodyMatterSubsystem::getAllParticleMasses ( const State ) const

TODO: total number of particles.

◆ getAllParticleAccelerations()

const Vector_<Vec3>& SimTK::SimbodyMatterSubsystem::getAllParticleAccelerations ( const State ) const

TODO: total number of particles.

◆ getParticleAcceleration()

const Vec3& SimTK::SimbodyMatterSubsystem::getParticleAcceleration ( const State s,
ParticleIndex  p 
) const
inline

TODO: total number of particles.

◆ getMobilizerCentrifugalForces()

const SpatialVec& SimTK::SimbodyMatterSubsystem::getMobilizerCentrifugalForces ( const State state,
MobilizedBodyIndex  mbx 
) const

(Deprecated) This is an obscure internal quantity and shouldn't have been exposed; see getTotalCentrifugalForces() instead.

Friends And Related Function Documentation

◆ operator<<()

std::ostream & operator<< ( std::ostream &  ,
const SimbodyMatterSubsystem  
)
related

Dump some debug information about the given subsystem to the given output stream; this is not for serialization.


The documentation for this class was generated from the following file: