Contact and Collision¶
Collision Group and Mask¶
Collision group and mask in RaiSim uses bit operations as most other physics engines. The below example is self-explanatory
raisim::World world;
auto sphere0 = world.addSphere(1, 1, raisim::COLLISION(0), raisim::COLLISION(0) | raisim::COLLISION(1));
auto sphere1 = world.addSphere(1, 1, raisim::COLLISION(1), raisim::COLLISION(0) | raisim::COLLISION(1));
auto sphere2 = world.addSphere(1, 1, raisim::COLLISION(2), raisim::COLLISION(1));
auto sphere3 = world.addSphere(1, 1, raisim::COLLISION(3), -1);
In the above example, sphere0
is in collision group 0 and can collide with collision group 0 and 1.
sphere1
is in collision group 1 and can collide with collision group 0 and 1.
sphere2
is in collision group 2 and can collide with collision group 1.
sphere3
is in collision group 3 and can collide with any object (-1 means all groups).
The collision group and mask is AND logic. In order for A and B collide, A should be able to collide with B and vice versa.
sphere0
can collide with sphere1
.
sphere1
cannot collide with spehre2
(both conditions must be satisfied).
sphere3
cannot collide with any objects (because sphere0
, sphere1
and sphere2
cannot collide with the collision group 3).
By default, movable object are in collision group 1 and can collide with anything (collision mask = -1). All static objects (e.g., ground and height map) are by default in collision group 63 and can collide with anything.
Contacts¶
raisim::Object
(and thus raisim::ArticulatedSystem
and raisim:SingleBodyObject
) have a method getContacts
which returns the list of contacts.
For example,
auto& contactsOnAnymal = anymal->getContacts();
Contact class is header-only and can be found at include/raisim/contact/Contact.hpp
.
Note that all vector quantities are expressed in the respective Contact Frame. A contact frame is defined such that its z-axis is colinear with the contact normal and its origin is at the contact point. Its x- and y-axes are chosen arbitrary. Here is an extensive example
/// Let's check all contact impulses acting on "LF_SHANK"
auto footIndex = anymal->getBodyIdx("LF_SHANK");
/// for all contacts on the robot, check ...
for(auto& contact: anymal->getContacts()) {
if (contact.skip()) continue; /// if the contact is internal, one contact point is set to 'skip'
if ( footIndex == contact.getlocalBodyIndex() ) {
std::cout<<"Contact impulse in the contact frame: "<<contact.getImpulse()->e()<<std::endl;
/// the impulse is acting from objectB to objectA. You can check if this object is objectA or B by
std::cout<<"is ObjectA: "<<contact.isObjectA()<<std::endl;
std::cout<<"Contact frame: \n"<<contact.getContactFrame().e().transpose()<<std::endl;
/// contact frame is transposed.
std::cout<<"Contact impulse in the world frame: "<<contact.getContactFrame().e().transpose() * contact.getImpulse()->e()<<std::endl;
std::cout<<"Contact Normal in the world frame: "<<contact.getNormal().e().transpose()<<std::endl;
std::cout<<"Contact position in the world frame: "<<contact.getPosition().e().transpose()<<std::endl;
std::cout<<"It collides with: "<<world.getObject(contact.getPairObjectIndex())<<std::endl;
if (contact.getPairContactIndexInPairObject() != raisim::BodyType::STATIC) {
/// Static objects do not have Contacts store. So you must check if the pair object is static
/// This saves computation in raisim
world.getObject(contact.getPairObjectIndex()).getContacts(); /// You can use the same methods on the pair object
}
std::cout<<"please check Contact.hpp for the full list of the methods"<<std::endl;
}
}
API¶
You can get a vector of collisions on an object using raisim::Object::getContacts
.
Each element in the vector has the following API:
-
class
Contact
¶ Public Functions
-
inline const Vec<3> &
getPosition
() const¶ the contact position
- Returns
the contact position
-
inline const Vec<3> &
getNormal
() const¶ the contact normal vector pointing to ObjectA
- Returns
frame
-
inline const Mat<3, 3> &
getContactFrame
() const¶ returns a TRANSPOSE of the frame that the impulse is expressed.
- Returns
contact frame
-
inline size_t
getIndexContactProblem
() const¶ returns the corresponding index in raisim::World::getContactProblem
- Returns
contact index
-
inline size_t
getIndexInObjectContactList
() const¶ returns the corresponding index in raisim::Object::getContacts
- Returns
contact index
-
inline size_t
getPairObjectIndex
() const¶ returns the contacting object index in raisim::World::getObjectList
- Returns
object index
-
inline size_t
getPairContactIndexInPairObject
() const¶ returns the contact index in the contacting (the paired) object in raisim::Object::getContacts This does not work if the pair body is STATIC because contacts on static bodies are not stored. First check the pair body type with getPairObjectBodyType
- Returns
contact index
-
inline const Vec<3> *
getImpulsePtr
() const¶ returns the impulse pointer. You have to divide this number by the time step to get the force
- Returns
impulse
-
inline const Vec<3> &
getImpulse
() const¶ returns the impulse. You have to divide this number by the time step to get the force
- Returns
impulse
-
inline bool
isObjectA
() const¶ returns if the object is objectA. When there is a contact, the two paired objects are assigned to be objectA and objectB arbitrarily. The contact frame is defined such that its z-axis is pointing towards the objectA. The contact impulse is defined as an external force that objectA experiences.
- Returns
impulse
-
inline BodyType
getPairObjectBodyType
() const¶ returns the body type of the paired object. Please read https://raisim.com/sections/Object.html#body-types to learn about it
- Returns
the body type
-
inline Mat<3, 3> &
getInvInertia
()¶ returns the inverse apparent inertia of the contacting point
- Returns
inertia
-
inline size_t
getlocalBodyIndex
() const¶ get local body index of this contact. The local index is assigned to each moving body in an object
- Returns
the body index.
-
inline double
getDepth
() const¶ The penetration depth of the contact
- Returns
the depth of the contact
-
inline bool
isSelfCollision
() const¶ returns if the contact is self collision
- Returns
if this is a self collision
-
inline bool
skip
() const¶ this is set true for one self-collision point so that you don’t count them twice
- Returns
if you can skip this contact point while iterating contact points
-
inline dGeomID
getCollisionBodyA
()¶ get the collision body of this object. This is ODE interface
- Returns
collision body
-
inline dGeomID
getCollisionBodyB
()¶ get the collision body of the pairing object. This is ODE interface
- Returns
collision body
-
inline const Vec<3> &