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"""A simple example for contact."""
 2
 3import sapien.core as sapien
 4import numpy as np
 5
 6
 7def main():
 8    engine = sapien.Engine()
 9    # renderer = sapien.SapienRenderer()
10    # engine.set_renderer(renderer)
11    scene = engine.create_scene()
12    dt = 1 / 100.0
13    scene.set_timestep(dt)
14
15    # ---------------------------------------------------------------------------- #
16    # Add two boxes
17    # ---------------------------------------------------------------------------- #
18    actor_builder = scene.create_actor_builder()
19    actor_builder.add_box_collision(half_size=[0.5, 0.5, 0.5])
20    # actor_builder.add_box_visual(half_size=[0.5, 0.5, 0.5], color=[1, 0, 0])
21    box1 = actor_builder.build_kinematic(name='box1')
22    box1.set_pose(sapien.Pose(p=[0, 0, 1.0]))
23    print('Mass of box1:', box1.mass)
24
25    actor_builder = scene.create_actor_builder()
26    actor_builder.add_box_collision(half_size=[0.25, 0.25, 0.25])
27    # actor_builder.add_box_visual(half_size=[0.25, 0.25, 0.25], color=[0, 1, 0])
28    box2 = actor_builder.build(name='box2')
29    box2.set_pose(sapien.Pose(p=[0, 0, 1.75]))
30    print('Mass of box2:', box2.mass)
31
32    # ---------------------------------------------------------------------------- #
33    # Check contacts
34    # ---------------------------------------------------------------------------- #
35    scene.step()
36    contacts = scene.get_contacts()
37    support_force = 0
38    for contact in contacts:
39        print(contact)
40        for point in contact.points:
41            print('Impulse (F * dt) on the first actor:', point.impulse)
42            print('Normal (same direction as impulse):', point.normal)
43            print('Contact position (in the world frame):', point.position)
44            print('Minimum distance between two shapes:', point.separation)
45            if contact.actor0.name == 'box2':
46                support_force += point.impulse[2] / dt
47            elif contact.actor0.name == 'box1':
48                support_force -= point.impulse[2] / dt
49            else:
50                raise RuntimeError('Impossible case in this example.')
51    # Sanity check: the support force should balance the gravity
52    np.testing.assert_allclose(support_force, 9.81 * box2.mass, rtol=1e-3)
53
54
55if __name__ == '__main__':
56    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.