Simbody  3.7
SimTK::ContactTrackerSubsystem Class Reference

This subsystem identifies and tracks potential contacts between the mobilized bodies of a multibody system. More...

+ Inheritance diagram for SimTK::ContactTrackerSubsystem:

Public Member Functions

 ContactTrackerSubsystem (MultibodySystem &system)
 Create a new ContactTrackerSubsystem and install it into the given MultibodySystem. More...
 
 SimTK_PIMPL_DOWNCAST (ContactTrackerSubsystem, Subsystem)
 
Find Active Contacts

Determine what contacts are occurring.

const ContactSnapshotgetActiveContacts (const State &state) const
 Get the calculated value of the ContactSnapshot cache entry representing the current set of Contact pairs for this system, as determined by the various Tracker algorithms registered with this subsystem. More...
 
const ContactSnapshotgetPredictedContacts (const State &state) const
 (Advanced) Get an additional set of predicted Contacts that can be anticipated from current velocity and acceleration information. More...
 
Contact Surface Identification

These methods map between the assigned ContactSurfaceIndex and the surfaces that were attached to each MobilizedBody in the MultibodySystem.

int getNumSurfaces () const
 Get the number of surfaces being managed by this contact tracker subsystem. More...
 
ContactSurfaceIndex getContactSurfaceIndex (MobilizedBodyIndex mobod, int contactSurfaceOrdinal) const
 Obtain the ContactSurfaceIndex that was assigned by this ContactTrackerSubsystem to a particular instance of a ContactSurface on a MobilizedBody. More...
 
const MobilizedBodygetMobilizedBody (ContactSurfaceIndex surfIx) const
 Get the MobilizedBody associated with a particular contact surface. More...
 
const ContactSurfacegetContactSurface (ContactSurfaceIndex surfIx) const
 Get the ContactSurface object (detailed geometry and material properties) that is associated with the given ContactSurfaceIndex. More...
 
const TransformgetContactSurfaceTransform (ContactSurfaceIndex surfIx) const
 Get the transform X_BS that gives the pose of the indicated contact surface with respect to the body frame of the body to which it is attached. More...
 
Contact Tracker management

Most users won't need to use these methods.

void adoptContactTracker (ContactTracker *tracker)
 Register the contact tracking algorithm to use for a particular pair of ContactGeometry types, replacing the existing tracker if any. More...
 
bool hasContactTracker (ContactGeometryTypeId surface1, ContactGeometryTypeId surface2) const
 Return true if this subsystem has a contact tracker registered that can deal with ineractions between surfaces using the indicated pair of geometry types, in either order. More...
 
const ContactTrackergetContactTracker (ContactGeometryTypeId surface1, ContactGeometryTypeId surface2, bool &reverseOrder) const
 Return the contact tracker to be used for an interaction between the indicated types of contact geometry. More...
 
Advanced/Obscure

You probably don't want to call any of these methods.

Some may be unimplemented.

const ContactSnapshotgetPreviousActiveContacts (const State &state) const
 (Advanced) Obtain the value of the ContactSnapshot state variable representing the most recently known set of Contacts for this system. More...
 
const ContactSnapshotgetPreviousPredictedContacts (const State &state) const
 (Advanced) Obtain the value of the ContactSnapshot state variable representing the most recently predicted set of impending Contacts for this system. More...
 
bool realizeActiveContacts (const State &state, bool lastTry, Real &stepAdvice) const
 (Advanced) Calculate the current ActiveContacts set at Position stage or later if it hasn't already been done and return true if successful. More...
 
bool realizePredictedContacts (const State &state, bool lastTry, Real &stepAdvice) const
 (Advanced) Calculate the set of anticipated Contacts set at Acceleration stage if not already calculated and return true if successful. More...
 
 ContactTrackerSubsystem ()
 (Advanced) Default constructor creates an empty Subsystem not associated with any MultibodySystem; not very useful. 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...
 

Detailed Description

This subsystem identifies and tracks potential contacts between the mobilized bodies of a multibody system.

It operates on the undeformed, material-independent geometry of ContactSurface objects that have been associated with those mobilized bodies, identifying and characterizing pairwise geometric relationships that occur between surfaces, and tracking the evolution of particular contacts through time. No physical response to contact is generated here; this subsystem provides only a general contact-tracking service that can be used by other parts of the MultibodySystem to generate forces, impulses, visualizations, messages, noises, or whatever. The goal here is to provide robust and extremely high performance characterization of geometric interactions in a way that is useful for a variety of contact response models.

The ContactTrackerSubsystem maintains an evolving set of tracked Contact objects throughout a simulation; for any given State of the system the subsystem can calculate the current value of that set, which we call the "contact status" of that state. The most recently known prior valid contact status is maintained as part of the system state because the correct instantaneous evaluation of contact status may require past information, and because we are interested in discrete contact events such as initiation and breaking of contact as well as ongoing interactions.

Each Contact being tracked represents the interaction between a unique pair of ContactSurface objects; by definition there is at most one Contact between any such pair (per ContactTrackerSubsystem). The presence of a Contact in the set does not necessarily mean its two surfaces are touching, just that their proximity is interesting in some way. Each Contact is characterized as impending, initiated, ongoing, broken, or separating. At each evaluation, the last-known set of Contacts is used in conjunction with the current State to determine a disposition for each of the tracked Contacts. Contacts that have become boring are removed from the tracked set, and newly-interesting ones are assigned a new ContactId and added to the tracked contacts set. The ContactId persists as long as that Contact continues to remain in the set.

Ambiguous or impossible contact situations can occur during trial steps and can be detected as long as we know the correct contact status in the immediate past. Problems are more common when a simulation contains fast-moving objects, small objects, or thin surfaces, and a relatively large time step size is being attempted by the integrator. For example, we may find that we could have missed a contact that may have occurred since the end of the last step (pass-through), or can't determine whether a small object is deeply penetrated through a thin surface or has simple "gone around the back". In such cases the subsystem reports an error condition that will cause the integrator to reduce the step size. At the start of a time stepping study, there is no past information available to help disambiguate; in that case heuristics are used to make a "best guess" at which surfaces are in contact; those can be overridden by a knowledgable human.

As mentioned above, we track at most one Contact at a time between any pair of ContactSurface objects. However, for some surface types a single Contact may involve many geometric interactions; a mesh Contact, for example, may include a list of all the mesh faces that overlap between the two surfaces, and these do not have to be contiguous over the mesh surface. You may want to break up a concave surface into several ContactSurface objects so that you can separately track several Contacts between that surface and others.

A ContactSurface consists of a piece of surface geometry and a contact material that describes the contact-related physical properties of the surface. A body may have many ContactSurface objects attached to it, each with its own associated contact material. Within an instance of the ContactTrackerSubsystem, each ContactSurface is assigned a unique ContactSurfaceIndex. If you have more than one ContactTrackerSubsystem (not common), they will each have independent sets of ContactSurface objects (and know nothing about one another), so the (Subsystem,ContactSurfaceIndex) pair would be unique but not the index alone. You can map between the assigned ContactSurfaceIndex and the actual surface using methods of this class.

Within a ContactTrackerSubsystem, all the contact surfaces are presumed to be capable of interacting with one another unless they share membership in a "contact clique". All surfaces attached to the same mobilized body are placed together in a clique, so they will never interact. It is also common to create a clique associated with each joint and place nearby contact surfaces on adjacent mobilized bodies into that clique to avoid having to build excessively precise geometry around joints.

Each concrete type of ContactGeometry object (whether provided as part of Simbody or as an extension by the user) has a unique integer ContactGeometryTypeId. Ordered pairs of these Ids are used as a key to select a ContactTracker that is able to identify and manage contacts or potential contacts between those two kinds of geometric objects. You can provide a default tracking algorithm for unhandled pairs that will either ignore them or throw an error. Note that a ContactTracker is invoked only for "narrow phase" contact; the ContactTrackerSubsytem handles the "broad phase" and weeds out all but a few possible contacting surfaces that are then passed to ContactTracker for final disposition. All the ContactTracker objects to be used with a given ContactTrackerSubsystem must be registered with that subsystem during extended construction (Topology stage). Simbody provides default ContactTracker implementations for interactions among most of its built-in ContactGeometry types, such as Sphere-Sphere, Sphere-HalfSpace, Mesh-Sphere, Mesh-Mesh, etc. These will be pre-registered in every ContactTrackerSubsystem but you can replace them with something else if you want.

Note
ContactGeometryTypeIds are unique and persistent within any execution of a program that uses them, but they are assigned at run time, possibly by multiple asynchronous threads, and are likely to be different in different programs and in separate runs of the same program.

The result of a ContactTracker when applied to a pair of contact surfaces, is either a determination that the surfaces are not in contact, or a Contact object describing their contact interaction. There are different types of these Contact objects (for example, PointContact, LineContact, MeshContact) and the same algorithm may result in different kinds of Contact under different circumstances. At each evaluation, the subsystem passes in the previous Contact object, if any, that was associated with two ContactSurface objects, then receives an update from the algorithm.

Constructor & Destructor Documentation

◆ ContactTrackerSubsystem() [1/2]

SimTK::ContactTrackerSubsystem::ContactTrackerSubsystem ( MultibodySystem system)
explicit

Create a new ContactTrackerSubsystem and install it into the given MultibodySystem.

◆ ContactTrackerSubsystem() [2/2]

SimTK::ContactTrackerSubsystem::ContactTrackerSubsystem ( )

(Advanced) Default constructor creates an empty Subsystem not associated with any MultibodySystem; not very useful.

Member Function Documentation

◆ getActiveContacts()

const ContactSnapshot& SimTK::ContactTrackerSubsystem::getActiveContacts ( const State state) const

Get the calculated value of the ContactSnapshot cache entry representing the current set of Contact pairs for this system, as determined by the various Tracker algorithms registered with this subsystem.

You can call this at Stage::Position or later; computation of contact status will be initiated if needed. Only the past contact status and current positions are used. This cache entry value is precisely what will become the "previous active contacts" state variable at the beginning of the next time step. An error will be thrown if we have to calculate the contacts here but fail to do so; if you don't want to deal with the possibility that an error might occur here, you can realize contacts explicitly first (not common).

See also
realizeActiveContacts()

◆ getPredictedContacts()

const ContactSnapshot& SimTK::ContactTrackerSubsystem::getPredictedContacts ( const State state) const

(Advanced) Get an additional set of predicted Contacts that can be anticipated from current velocity and acceleration information.

You can call this at Stage::Acceleration; computation will be initiated if needed. This cache entry value is precisely what will become the "previous predicted contacts" state variable at the beginning of the next time step. An error will be thrown if we have to calculate the contacts here but fail to do so; to avoid that you can realize them explicitly first (not common).

See also
realizePredictedContacts()

◆ getNumSurfaces()

int SimTK::ContactTrackerSubsystem::getNumSurfaces ( ) const

Get the number of surfaces being managed by this contact tracker subsystem.

These are identified by ContactSurfaceIndex values from 0 to getNumSurfaces()-1. This is available after realizeTopology() and does not change subsequently. You can find out which ContactSurfaceIndex got assigned any particular ContactSurface using getContactSurfaceIndex().

◆ getContactSurfaceIndex()

ContactSurfaceIndex SimTK::ContactTrackerSubsystem::getContactSurfaceIndex ( MobilizedBodyIndex  mobod,
int  contactSurfaceOrdinal 
) const

Obtain the ContactSurfaceIndex that was assigned by this ContactTrackerSubsystem to a particular instance of a ContactSurface on a MobilizedBody.

A ContactSurface is attached to a body description using Body::addContactSurface() and then that body description is used to create an actual body instance in a MobilizedBody. The surface is identified here by specifying the MobilizedBody of interest and the small integer ordinal that was returned when Body::addContactSurface() was called. (You can provide either a MobilizedBody or MobilizedBodyIndex here; there is an implicit conversion from MobilizedBody to its MobilizedBodyIndex.) This method will throw an exception if either argument is illegal or out of range.

See also
Body::addContactSurface()

◆ getMobilizedBody()

const MobilizedBody& SimTK::ContactTrackerSubsystem::getMobilizedBody ( ContactSurfaceIndex  surfIx) const

Get the MobilizedBody associated with a particular contact surface.

◆ getContactSurface()

const ContactSurface& SimTK::ContactTrackerSubsystem::getContactSurface ( ContactSurfaceIndex  surfIx) const

Get the ContactSurface object (detailed geometry and material properties) that is associated with the given ContactSurfaceIndex.

◆ getContactSurfaceTransform()

const Transform& SimTK::ContactTrackerSubsystem::getContactSurfaceTransform ( ContactSurfaceIndex  surfIx) const

Get the transform X_BS that gives the pose of the indicated contact surface with respect to the body frame of the body to which it is attached.

◆ adoptContactTracker()

void SimTK::ContactTrackerSubsystem::adoptContactTracker ( ContactTracker tracker)

Register the contact tracking algorithm to use for a particular pair of ContactGeometry types, replacing the existing tracker if any.

If the tracker takes a pair (id1,id2), we will use it both for that pair and for (id2,id1) by calling it with the arguments reversed. The subsystem takes over ownership of the supplied heap-allocated object.

◆ hasContactTracker()

bool SimTK::ContactTrackerSubsystem::hasContactTracker ( ContactGeometryTypeId  surface1,
ContactGeometryTypeId  surface2 
) const

Return true if this subsystem has a contact tracker registered that can deal with ineractions between surfaces using the indicated pair of geometry types, in either order.

◆ getContactTracker()

const ContactTracker& SimTK::ContactTrackerSubsystem::getContactTracker ( ContactGeometryTypeId  surface1,
ContactGeometryTypeId  surface2,
bool &  reverseOrder 
) const

Return the contact tracker to be used for an interaction between the indicated types of contact geometry.

If the tracker requires the geometry types to be in reverse order from the (surface1,surface2) order given here, then the return argument reverseOrder will be set true, otherwise it will be false. If no tracker was registered, this will be the default tracker.

◆ getPreviousActiveContacts()

const ContactSnapshot& SimTK::ContactTrackerSubsystem::getPreviousActiveContacts ( const State state) const

(Advanced) Obtain the value of the ContactSnapshot state variable representing the most recently known set of Contacts for this system.

◆ getPreviousPredictedContacts()

const ContactSnapshot& SimTK::ContactTrackerSubsystem::getPreviousPredictedContacts ( const State state) const

(Advanced) Obtain the value of the ContactSnapshot state variable representing the most recently predicted set of impending Contacts for this system.

◆ realizeActiveContacts()

bool SimTK::ContactTrackerSubsystem::realizeActiveContacts ( const State state,
bool  lastTry,
Real stepAdvice 
) const

(Advanced) Calculate the current ActiveContacts set at Position stage or later if it hasn't already been done and return true if successful.

If we can't unambiguously determine the contact status, we'll return false and give the caller a hint as to the latest time at which we think we could have succeeded. If lastTry is true, then we throw an error on failure rather than returning false.

◆ realizePredictedContacts()

bool SimTK::ContactTrackerSubsystem::realizePredictedContacts ( const State state,
bool  lastTry,
Real stepAdvice 
) const

(Advanced) Calculate the set of anticipated Contacts set at Acceleration stage if not already calculated and return true if successful.

Otherwise, problems are handled as for realizeActiveContacts().

◆ SimTK_PIMPL_DOWNCAST()

SimTK::ContactTrackerSubsystem::SimTK_PIMPL_DOWNCAST ( ContactTrackerSubsystem  ,
Subsystem   
)

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