Physics

Since SAPIEN is a physical simulation framework, we would like to showcase how to change physical properties which lead to different behaviors.

In this tutorial, you will learn the following:

  • Use SceneConfig to initialize default physical properties

  • Use PhysicalMaterial to set different physical materials

  • Create kinematic actors

  • Enable damping for actors

  • Get kinematic quantities (pose, velocity, angular velocity) of an actor

The example illustrates an object sliding down the slope. You can run the script with different arguments. transforms3d is required to compute poses, which can be installed by pip install transforms3d.

../../_images/physics.gif

The full script can be downloaded here physics.py

Set default physical properties

Default physical properties can be specified when a scene is created. Those properties include gravity, static and dynamic friction, as well as restitution (elasticity of collision).

def main():
    args = parse_args()

    engine = sapien.Engine()
    renderer = sapien.SapienRenderer()
    engine.set_renderer(renderer)

    scene_config = sapien.SceneConfig()
    # The default physical properties can be modified through sapien.SceneConfig
    print(scene_config.gravity)
    print(scene_config.default_static_friction)
    print(scene_config.default_dynamic_friction)
    print(scene_config.default_restitution)
    scene_config.gravity = np.array([0.0, 0.0, args.gravity])
    scene = engine.create_scene(scene_config)
    scene.set_timestep(1 / 100.0)

SceneConfig describes default physical properties, and can be passed to Scene.

Set physical materials

PhysicalMaterial describes physical (contact) properties (friction and restitution) of the material of an actor. It can be specified when an actor is created. If not provided, the default physical material, induced by the scene’s default physical properties, will be used. Note that PhysicalMaterial can only be created by create_physical_material(...).

    physical_material: sapien.PhysicalMaterial = scene.create_physical_material(
        static_friction=args.static_friction,
        dynamic_friction=args.dynamic_friction,
        restitution=args.restitution,
    )

Some other physical properties, like density, are directly provided to collision shapes. We update create_sphere function in Create Actors.

def create_sphere(
        scene: sapien.Scene,
        pose: sapien.Pose,
        radius,
        color=None,
        density=1000.0,
        physical_material: sapien.PhysicalMaterial = None,
        name='',
) -> sapien.Actor:
    """Create a sphere."""
    builder = scene.create_actor_builder()
    builder.add_sphere_collision(radius=radius, material=physical_material, density=density)
    builder.add_sphere_visual(radius=radius, color=color)
    sphere = builder.build(name=name)
    sphere.set_pose(pose)
    return sphere

Note

The rolling resistance (friction) is not modeled in SAPIEN currently.

Create a kinematic actor

Now, let’s create a slope. The slope should be a kinematic object, rather than a dynamic object. In other words, it can not be affected by external forces. We can set is_kinematic=True when building the actor.

def create_box(
        scene: sapien.Scene,
        pose: sapien.Pose,
        half_size,
        color=None,
        is_kinematic=False,
        density=1000.0,
        physical_material: sapien.PhysicalMaterial = None,
        name='',
) -> sapien.Actor:
    """Create a box.

    Args:
        scene: sapien.Scene to create a box.
        pose: 6D pose of the box.
        half_size: [3], half size along x, y, z axes.
        color: [3] or [4], rgb or rgba.
        is_kinematic: whether an object is kinematic (can not be affected by forces).
        density: float, the density of the box.
        physical_material: physical material of the actor.
        name: name of the actor.

    Returns:
        sapien.Actor
    """
    half_size = np.array(half_size)
    builder = scene.create_actor_builder()
    builder.add_box_collision(half_size=half_size, material=physical_material, density=density)  # Add collision shape
    builder.add_box_visual(half_size=half_size, color=color)  # Add visual shape
    if is_kinematic:
        box = builder.build_kinematic(name=name)
    else:
        box = builder.build(name=name)
    box.set_pose(pose)
    return box

Set damping for the actor

Sometimes, you might model some resistance proportional to (linear or angular) velocity, like air resistance. It can be achieved by setting the damping of an actor.

    actor.set_damping(linear=args.linear_damping, angular=args.angular_damping)

Get kinematic quantities (pose, velocity) of an actor

We can acquire kinematic quantities (pose, linear velocity, angular velocity) of an actor through get_pose(), get_velocity(), get_angular_velocity().

            print('Pose', actor.get_pose())
            print('Velocity', actor.get_velocity())
            print('Angular velocity', actor.get_angular_velocity())