Drake
Drake C++ Documentation
Loading...
Searching...
No Matches
CollisionFilterManager Class Reference

Detailed Description

Class for configuring "collision filters"; collision filters limit the scope of various proximity queries.

The sole source of CollisionFilterManager instances is SceneGraph. See SceneGraph's documentation for details on acquiring an instance.

A SceneGraph instance contains the set of geometries with assigned proximity properties G = R ⋃ V ⋃ A = {g₀, g₁, ..., gₙ}, where R is the set of dynamic rigid geometries, V is the set of deformable geometries, and A is the set of anchored rigid geometries. These three sets are pairwise disjoint. Many proximity queries operate on pairs of geometries (e.g., (gᵢ, gⱼ)). Those queries operate on a theoretical set of candidate pairs, C ⊂ G × G. C lacks many geometry pairs that have been excluded from consideration. CollisionFilterManager excludes many pairs intrinsically and provides mechanisms for the users to exclude even more pairs.

Intrinsic Exclusions

  • I = {(g, g)}, ∀ g ∈ G is the set of all pairs consisting of a geometry with itself; there is no meaningful proximity query on such a pair.
  • A × A represents all pairs consisting only of anchored geometries; an anchored geometry is never tested against another anchored geometry.
  • F = {(gᵢ, gⱼ)} ∀ i, j, such that gᵢ, gⱼ ∈ R and frame(gᵢ) == frame(gⱼ); the pairs where both rigid geometries are affixed to the same frame. Pairs of deformable geometries are not included in this set. While deformable geometries are all registered on the world frame, they are not rigidly affixed to it.
  • Intrinsic exclusions are immutable: they cannot be restored to the candidate set by the user.

User-Defined Exclusions

  • U = {(gᵢ, gⱼ)} is the set of geometry pairs which have been explicitly excluded via the appropriate CollisionFilterDeclaration. Subsequent declarations can remove the pair from U (restoring them to the candidate set). Those APIs encompass geometry pairs including deformable geometries. See the CollisionFilterDeclaration documentation for further details.

Geometry Active Status

In addition to excluding specific geometry pairs, a geometry can be declared inactive* (see Deactivate() and Activate()). An inactive geometry is essentially excluded from G. It still exists as a known geometry. So, adding or removing filters on that geometry is still valid. However, those declarations will have no apparent effect until the geometry is reactivated. An inactive geometry will simply never appear in any pair in the candidate set C.

We can define N as the set of inactive geometries and Gₐ = G - N as the set of active geometries.

Candidate Geometry Pairs

Therefore, the set of geometry pair candidates C for proximity queries is defined as:

C = (Gₐ × Gₐ) - (A × A) - F - I - U.

A CollisionFilterManager is a view into geometry data (either that owned by a SceneGraph instance or a SceneGraph context). The manager instance can be copied or moved and the resulting instance is a view into the same data. For both the original and the copy (or just the target when moving the manager), the source data must stay alive for at least as long as the manager instance.

Warning
Generally, the effect of applying a declaration is based on the state of SceneGraph's geometry data at the time of application. The geometry's active status is the one exception (see below). More concretely:
  • For a particular FrameId in a GeometrySet instance, only those geometries attached to the identified frame with the proximity role assigned at the time of the call will be included in the filter. If geometries are subsequently added or assigned the proximity role, they will not be retroactively added to the user-declared filter.
  • In general, adding collision geometries and assigning proximity roles should happen prior to collision filter configuration.
  • Declarations of user-defined exclusions and allowances can only be made on "known" geometries (geometries with assigned the proximity role). Declarations on unknown geometries will be rejected with an error.
  • Declaring a set of geometries active/inactive is the exception. These add or remove the geometries from the set Gₐ. We are not adding/deleting filtered pairs at the time of declaration, but simply changing the active status of the geometries. A geometry's active status doesn't change just because other geometries get added/removed.

Transient vs Persistent changes

Collision filtering is all about defining which geometry pairs are in the set C. The simplest way to modify the set C is through persistent modifications to a "base configuration" (via calls to Apply()). However, declarations can also be applied in a transient manner. Transient declarations form a history. The current definition of the set C is the result of applying the history of collision filter declarations to the persistent base configuration in order. That history can be modified:

  • New transient declarations can be appended.
  • Arbitrary transient declarations can be removed from the sequence.
  • The current configuration (based on a history with an arbitrary number of transient declarations) can be "flattened" into the persistent base (with no history).

The table below illustrates a sequence of operations and their effect on C. We define C's initial configuration as C = {P₁, P₂, ..., Pₙ} (for n geometry pairs). Each action is described as either persistent or transient.

Line C Action
1 {P₁, P₂, ..., Pₙ} Initial condition of the persistent base
2 {P₂, ..., Pₙ} Remove P₁ from the persistent base
3 {P₂, ..., Pₙ₋₁} Remove Pₙ from the persistent base
4 {P₂} Remove all pairs except P₂ from the persistent base
5 {P₂, P₄, P₅} Transient declaration #1 puts P₄ and P₅ into C
6 {P₂, P₃, P₄, P₅} Transient declaration #2 puts P₃ and P₄ into C
7 {P₂, P₃, P₄} Remove declaration #1.
8 {P₂, P₃, P₄} Configuration flattened; #2 no longer exists

Table 1: An example sequence of operations on collision filters.

Notes:

  • lines 2 - 4 represent a series of persistent operations, filtering pairs of geometry (aka removing them from C by calling Apply()).
  • line 5: the first transient filter declaration which is assigned the id value #1 (via a call to ApplyTransient()).
  • line 6: Adds a new transient filter declaration to the sequence (assigned id #2). Note, that it redundantly declares that P₄ is a member of C just as declaration #1 did. This redundancy is fine. In fact, it may be very important (see below).
  • line 7: We remove declaration #1. Although #1 added both P₄ and P₅ to C, the result of removing this declaration from the sequence is that P₅ is no longer a member of C but P₄ is. This is because #2's declaration that P₄ is* in C preserves its membership.
  • line 8: the current configuration is "flattened" into the persistent base. All history is thrown out and any filter identifiers are rendered invalid.

This example workflow above illustrates some key ideas in using transient declarations.

  • The persistent configuration can only be modified when there is no transient history. Applying a filter declaration should have the effect of realizing that declaration. If a pair is declared to be in C, the result of the declaration is that the pair is in C (assuming that the pair can* be in C). If we allowed modifying the persistent configuration with an active transient history, there might be no discernible change in the resultant configuration state because a subsequent transient declaration may supplant it. This would lead to inscrutable bugs. Therefore, it's simply not allowed.
  • When defining a transient declaration, the declaration should include all critical pairs explicitly. This includes those pairs that should and should not be in C. Any pair not explicitly accounted for should be one whose filter status is immaterial. It might seems desirable (from an optimization perspective) to examine the current configuration of C and apply the minimum change to put it into a desired state (i.e., if a pair I need filtered is already filtered, I would omit it from the declaration). This approach is fraught with peril. If the current configuration is the result of previous transient declarations, the removal of any of those declarations could invalidate the attempted difference calculation and my declaration would no longer be sufficient to guarantee the set C required.
  • Anyone at any time can add to the history. Some code can modify C to suit its needs. However, it can also make subsequent calls into code that also modifies C with no guarantees that the called code will undo those changes. Code that modifies collision filters configuration should document that it does so. It should also have a clear protocol for cleaning up its own changes. Finally, code that applies declarations should not take for granted that its transient declarations are necessarily the last declarations in the history.

Making transient filter declarations

There is a custom API for applying a filter declaration as a transient declaration. It returns the id for the transient API (used to remove the declaration from the history sequence).

Attempting to change the persistent configuration when there are active transient declarations in the history will throw an exception.

#include <drake/geometry/collision_filter_manager.h>

Public Member Functions

Implements CopyConstructible, CopyAssignable, MoveConstructible, MoveAssignable
 CollisionFilterManager (const CollisionFilterManager &)=default
CollisionFilterManageroperator= (const CollisionFilterManager &)=default
 CollisionFilterManager (CollisionFilterManager &&)=default
CollisionFilterManageroperator= (CollisionFilterManager &&)=default
Evaluating CollisionFilterDeclarations
void Apply (const CollisionFilterDeclaration &declaration)
 Applies the given declaration to the geometry state managed by this instance.
FilterId ApplyTransient (const CollisionFilterDeclaration &declaration)
 Applies the declaration as the newest transient modification to the collision filter configuration.
bool RemoveDeclaration (FilterId filter_id)
 Attempts to remove the transient declaration from the history for the declaration associated with the given filter_id.
bool has_transient_history () const
 Reports if there are any active transient filter declarations.
bool IsActive (FilterId filter_id) const
 Reports if the transient collision filter declaration indicated by the given filter_id is part of the history.
Deactivating and reactivating geometries

By default every geometry is active and participates in proximity queries subject to the pairwise filters configured via Apply(). A geometry can also be "deactivated". An inactive geometry is omitted from the geometry set that populates the collision candidate pairs. Therefore, no collision candidate pair can include an inactive geometry until it is reactivated. See the class documentation for how active status participates in the definition of the candidate pair set C (the set Nₚ).

Active status is independent of the declared pair-wise filters: Apply() never changes it just as activating and deactivating a geometry does not change the declared pair-wise filters between that geometry and others. Unlike Apply(), these may be called even when there is an active transient history. Apply() can reference an inactive geometry, but the effect of the declaration on any candidate pair including that geometry will not be apparent until the geometry is reactivated.

Remember, GeometrySet instances can be instantiated using FrameId values. As documented in GeometrySet, specifying a frame is merely a shorthand for specifying all geometries attached to that frame at the time the ids are extracted from the GeometrySet. Activate() and Deactivate() still only operate on those extracted GeometryIds. They shouldn't be interpreted as (de)activating the frame and any subsequent geometries that may be added to those frames.

void Deactivate (const GeometrySet &geometry_set)
 Marks every geometry in geometry_set inactive.
void Activate (const GeometrySet &geometry_set)
 Marks every geometry in geometry_set active.

Constructor & Destructor Documentation

◆ CollisionFilterManager() [1/2]

CollisionFilterManager ( const CollisionFilterManager & )
default

◆ CollisionFilterManager() [2/2]

CollisionFilterManager ( CollisionFilterManager && )
default

Member Function Documentation

◆ Activate()

void Activate ( const GeometrySet & geometry_set)

Marks every geometry in geometry_set active.

The inverse of calling Deactivate(). Activating an already-active geometry is a no-op. For more information, see the Activation documentation.

Exceptions
std::exceptionif geometry_set references invalid ids.

◆ Apply()

void Apply ( const CollisionFilterDeclaration & declaration)

Applies the given declaration to the geometry state managed by this instance.

The process of applying the collision filter data also validates it. The following polices are implemented during application:

  • Referencing an invalid id (FrameId or GeometryId): throws.
  • Declaring a filtered pair that is already filtered: no discernible change.
  • Attempts to "allow" collision between a pair that is strictly excluded (e.g., between two anchored geometries) will be ignored.
Exceptions
std::exceptionif the declaration references invalid ids or there is an active history.

◆ ApplyTransient()

FilterId ApplyTransient ( const CollisionFilterDeclaration & declaration)

Applies the declaration as the newest transient modification to the collision filter configuration.

The declaration must be considered "valid", as defined for Apply().

◆ Deactivate()

void Deactivate ( const GeometrySet & geometry_set)

Marks every geometry in geometry_set inactive.

The inverse of calling Activate(). Deactivating an already-inactive geometry is a no-op. For more information, see the Activation documentation.

Exceptions
std::exceptionif geometry_set references invalid ids.

◆ has_transient_history()

bool has_transient_history ( ) const

Reports if there are any active transient filter declarations.

◆ IsActive()

bool IsActive ( FilterId filter_id) const

Reports if the transient collision filter declaration indicated by the given filter_id is part of the history.

◆ operator=() [1/2]

CollisionFilterManager & operator= ( CollisionFilterManager && )
default

◆ operator=() [2/2]

CollisionFilterManager & operator= ( const CollisionFilterManager & )
default

◆ RemoveDeclaration()

bool RemoveDeclaration ( FilterId filter_id)

Attempts to remove the transient declaration from the history for the declaration associated with the given filter_id.

Parameters
filter_idThe id of the filter declaration to remove.
Returns
true iff is_active(filter_id) returns true before calling this method (i.e., filter_id refers to an existent filter that has successfully been removed).

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