Simbody
3.3
|
This subsystem identifies and tracks potential contacts between bodies of a multibody system, but does not generate any physical responses to those contacts. More...
#include <ContactTrackerSubsystem.h>
Public Member Functions | |
ContactTrackerSubsystem () | |
ContactTrackerSubsystem (MultibodySystem &) | |
int | getNumSurfaces () const |
Get the number of surfaces being managed by this contact tracker subsystem. More... | |
const MobilizedBody & | getMobilizedBody (ContactSurfaceIndex surfIx) const |
Get the MobilizedBody associated with a particular contact surface. More... | |
const ContactSurface & | getContactSurface (ContactSurfaceIndex surfIx) const |
Get the ContactSurface object (detailed geometry and material properties) that is associated with the given ContactSurfaceIndex. More... | |
const Transform & | 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. More... | |
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 ContactTracker & | 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. More... | |
const ContactSnapshot & | getPreviousActiveContacts (const State &state) const |
Obtain the value of the ContactSnapshot state variable representing the most recently known set of Contacts for this system. More... | |
const ContactSnapshot & | getPreviousPredictedContacts (const State &state) const |
Obtain the value of the ContactSnapshot state variable representing the most recently predicted set of impending Contacts for this system. More... | |
const ContactSnapshot & | getActiveContacts (const State &state) const |
Get the calculated value of the ContactSnapshot cache entry representing the current set of Contacts for this system, as determined by the various Tracker algorithms registered with this subsystem. More... | |
const ContactSnapshot & | getPredictedContacts (const State &state) const |
Get an additional set of predicted Contacts that can be anticipated from current velocity and acceleration information. More... | |
bool | realizeActiveContacts (const State &state, bool lastTry, Real &stepAdvice) const |
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 |
Calculate the set of anticipated Contacts set at Acceleration stage if not already calculated and return true if successful. More... | |
SimTK_PIMPL_DOWNCAST (ContactTrackerSubsystem, Subsystem) | |
Public Member Functions inherited from SimTK::Subsystem | |
Subsystem () | |
Subsystem (const Subsystem &) | |
Subsystem & | operator= (const Subsystem &) |
~Subsystem () | |
const String & | getName () const |
const String & | getVersion () const |
QIndex | allocateQ (State &, const Vector &qInit) const |
UIndex | allocateU (State &, const Vector &uInit) const |
ZIndex | allocateZ (State &, const Vector &zInit) const |
DiscreteVariableIndex | allocateDiscreteVariable (State &, Stage invalidates, AbstractValue *v) const |
DiscreteVariableIndex | allocateAutoUpdateDiscreteVariable (State &, Stage invalidates, AbstractValue *v, Stage updateDependsOn) const |
CacheEntryIndex | allocateCacheEntry (const State &, 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 &, int nqerr) const |
UErrIndex | allocateUErr (const State &, int nuerr) const |
UDotErrIndex | allocateUDotErr (const State &, int nudoterr) const |
EventTriggerByStageIndex | allocateEventTriggersByStage (const State &, Stage, int ntriggers) const |
const Vector & | getQ (const State &) const |
const Vector & | getU (const State &) const |
const Vector & | getZ (const State &) const |
const Vector & | getQDot (const State &) const |
const Vector & | getUDot (const State &) const |
const Vector & | getZDot (const State &) const |
const Vector & | getQDotDot (const State &) const |
const Vector & | getQErr (const State &) const |
const Vector & | getUErr (const State &) const |
const Vector & | getUDotErr (const State &) const |
const Vector & | getMultipliers (const State &) const |
const Vector & | getEventTriggersByStage (const State &, Stage) const |
Vector & | updQ (State &) const |
Vector & | updU (State &) const |
Vector & | updZ (State &) 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 |
Vector & | updQDot (const State &) const |
Vector & | updUDot (const State &) const |
Vector & | updZDot (const State &) const |
Vector & | updQDotDot (const State &) const |
Vector & | updQErr (const State &) const |
Vector & | updUErr (const State &) const |
Vector & | updUDotErr (const State &) const |
Vector & | updMultipliers (const State &) const |
Vector & | updEventTriggersByStage (const State &, Stage) const |
Stage | getStage (const State &) const |
const AbstractValue & | getDiscreteVariable (const State &s, DiscreteVariableIndex dx) const |
Real | getDiscreteVarLastUpdateTime (const State &s, DiscreteVariableIndex dx) const |
CacheEntryIndex | getDiscreteVarUpdateIndex (const State &s, DiscreteVariableIndex dx) const |
const AbstractValue & | getDiscreteVarUpdateValue (const State &s, DiscreteVariableIndex dx) const |
AbstractValue & | updDiscreteVarUpdateValue (const State &s, DiscreteVariableIndex dx) const |
bool | isDiscreteVarUpdateValueRealized (const State &s, DiscreteVariableIndex dx) const |
void | markDiscreteVarUpdateValueRealized (const State &s, DiscreteVariableIndex dx) const |
AbstractValue & | updDiscreteVariable (State &, DiscreteVariableIndex) const |
const AbstractValue & | getCacheEntry (const State &, CacheEntryIndex) const |
AbstractValue & | updCacheEntry (const State &, CacheEntryIndex) const |
bool | isCacheValueRealized (const State &, CacheEntryIndex) const |
void | markCacheValueRealized (const State &, CacheEntryIndex) const |
void | markCacheValueNotRealized (const State &, CacheEntryIndex) const |
SystemQIndex | getQStart (const State &) const |
int | getNQ (const State &) const |
SystemUIndex | getUStart (const State &) const |
int | getNU (const State &) const |
SystemZIndex | getZStart (const State &) const |
int | getNZ (const State &) const |
SystemQErrIndex | getQErrStart (const State &) const |
int | getNQErr (const State &) const |
SystemUErrIndex | getUErrStart (const State &) const |
int | getNUErr (const State &) const |
SystemUDotErrIndex | getUDotErrStart (const State &) const |
int | getNUDotErr (const State &) const |
SystemMultiplierIndex | getMultipliersStart (const State &) const |
int | getNMultipliers (const State &) const |
SystemEventTriggerByStageIndex | getEventTriggerStartByStage (const State &, Stage) const |
int | getNEventTriggersByStage (const State &, Stage) const |
bool | isInSystem () const |
bool | isInSameSystem (const Subsystem &otherSubsystem) const |
const System & | getSystem () const |
System & | updSystem () |
SubsystemIndex | getMySubsystemIndex () const |
bool | isOwnerHandle () const |
bool | isEmptyHandle () const |
bool | isSameSubsystem (const Subsystem &otherSubsystem) const |
bool | subsystemTopologyHasBeenRealized () const |
void | invalidateSubsystemTopologyCache () const |
MeasureIndex | adoptMeasure (AbstractMeasure &) |
AbstractMeasure | getMeasure (MeasureIndex) const |
template<class T > | |
Measure_< T > | getMeasure_ (MeasureIndex mx) const |
const Subsystem::Guts & | getSubsystemGuts () const |
Subsystem::Guts & | updSubsystemGuts () |
void | adoptSubsystemGuts (Subsystem::Guts *g) |
void | setSystem (System &, SubsystemIndex) |
Subsystem (Subsystem::Guts *g) | |
bool | hasGuts () const |
This subsystem identifies and tracks potential contacts between bodies of a multibody system, but does not generate any physical responses to those contacts.
It operates on the undeformed, material-independent geometry of ContactSurfaces that have been associated with those 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 Contacts 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 ContactSurfaces; 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 conjuction 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 ContactSurfaces. 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 ContactSurfaces 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 multiple ContactTrackerSubsystems, they will each have independent sets of ContactSurfaces (and know nothing about one another), so the (Subsystem, ContactSurfaceIndex) pair would be unique but not the index alone.
Within a ContactTrackerSubsystem, all the ContactSurfaces are presumed to be capable of interacting with one another unless they share membership in a "contact clique". All surfaces attached to the same 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 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 SimTK 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 ContactTrackers to be used with a given ContactTrackerSubsystem must be registered with that subsystem during extended construction (Topology stage). Simbody provides default ContactTrackers for interactions among most of its built-in Geometry 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.
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 ContactSurfaces, then receives an update from the algorithm.
SimTK::ContactTrackerSubsystem::ContactTrackerSubsystem | ( | ) |
|
explicit |
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.
const MobilizedBody& SimTK::ContactTrackerSubsystem::getMobilizedBody | ( | ContactSurfaceIndex | surfIx | ) | const |
Get the MobilizedBody associated with a particular contact surface.
const ContactSurface& SimTK::ContactTrackerSubsystem::getContactSurface | ( | ContactSurfaceIndex | surfIx | ) | const |
Get the ContactSurface object (detailed geometry and material properties) that is associated with the given ContactSurfaceIndex.
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.
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.
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.
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.
const ContactSnapshot& SimTK::ContactTrackerSubsystem::getPreviousActiveContacts | ( | const State & | state | ) | const |
Obtain the value of the ContactSnapshot state variable representing the most recently known set of Contacts for this system.
const ContactSnapshot& SimTK::ContactTrackerSubsystem::getPreviousPredictedContacts | ( | const State & | state | ) | const |
Obtain the value of the ContactSnapshot state variable representing the most recently predicted set of impending Contacts for this system.
const ContactSnapshot& SimTK::ContactTrackerSubsystem::getActiveContacts | ( | const State & | state | ) | const |
Get the calculated value of the ContactSnapshot cache entry representing the current set of Contacts for this system, as determined by the various Tracker algorithms registered with this subsystem.
You can call this at Position stage 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 should realize contacts explicitly first.
const ContactSnapshot& SimTK::ContactTrackerSubsystem::getPredictedContacts | ( | const State & | state | ) | const |
Get an additional set of predicted Contacts that can be anticipated from current velocity and acceleration information.
You can call this at Acceleration stage; computation will be initiated if needed. This cache entry value is precisely what will become the "previous impending 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 should realize them explicitly first.
bool SimTK::ContactTrackerSubsystem::realizeActiveContacts | ( | const State & | state, |
bool | lastTry, | ||
Real & | stepAdvice | ||
) | const |
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.
bool SimTK::ContactTrackerSubsystem::realizePredictedContacts | ( | const State & | state, |
bool | lastTry, | ||
Real & | stepAdvice | ||
) | const |
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::ContactTrackerSubsystem::SimTK_PIMPL_DOWNCAST | ( | ContactTrackerSubsystem | , |
Subsystem | |||
) |