ContactΒΆ
Contact information is useful to check whether two rigid bodies collide or whether an object is grasped by a gripper. The example shows how to check the contact between two actors (one box supported by another box).
In this tutorial, you will learn the following:
Get contact information from
Contact
The full script is included as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | """A simple example for contact."""
import sapien.core as sapien
import numpy as np
def main():
engine = sapien.Engine()
# renderer = sapien.VulkanRenderer()
# engine.set_renderer(renderer)
scene = engine.create_scene()
dt = 1 / 100.0
scene.set_timestep(dt)
# ---------------------------------------------------------------------------- #
# Add two boxes
# ---------------------------------------------------------------------------- #
actor_builder = scene.create_actor_builder()
actor_builder.add_box_collision(half_size=[0.5, 0.5, 0.5])
# actor_builder.add_box_visual(half_size=[0.5, 0.5, 0.5], color=[1, 0, 0])
box1 = actor_builder.build_kinematic(name='box1')
box1.set_pose(sapien.Pose(p=[0, 0, 1.0]))
print('Mass of box1:', box1.mass)
actor_builder = scene.create_actor_builder()
actor_builder.add_box_collision(half_size=[0.25, 0.25, 0.25])
# actor_builder.add_box_visual(half_size=[0.25, 0.25, 0.25], color=[0, 1, 0])
box2 = actor_builder.build(name='box2')
box2.set_pose(sapien.Pose(p=[0, 0, 1.75]))
print('Mass of box2:', box2.mass)
# ---------------------------------------------------------------------------- #
# Check contacts
# ---------------------------------------------------------------------------- #
scene.step()
contacts = scene.get_contacts()
support_force = 0
for contact in contacts:
print(contact)
for point in contact.points:
print('Impulse (F * dt) on the first actor:', point.impulse)
print('Normal (same direction as impulse):', point.normal)
print('Contact position (in the world frame):', point.position)
print('Minimum distance between two shapes:', point.separation)
if contact.actor0.name == 'box2':
support_force += point.impulse[2] / dt
elif contact.actor0.name == 'box1':
support_force -= point.impulse[2] / dt
else:
raise RuntimeError('Impossible case in this example.')
# Sanity check: the support force should balance the gravity
np.testing.assert_allclose(support_force, 9.81 * box2.mass, rtol=1e-3)
if __name__ == '__main__':
main()
|
You can call get_contacts
to fetch all contacts after the current simulation step.
It returns a list of Contact
.
contact.actor0
and contact.actor1
refer to two actors involved in the contact.
contact.points
contains a list of ContactPoint
.
For each contact point,
impulse
: the impulse applied on the first actor.normal
: the direction of impulse.position
: the point of application in the world frame.seperation
: minimum distance between two shapes involved in the contact.
Note
Contact
in SAPIEN does not mean that two actors are contacting each other.
It will be generated when the contact is about to start or end, and, of course, when the contact is happening.