Hello World

SAPIEN provides APIs to build physical simulation environments.

In this tutorial, you will learn the following:

  • Create a simulation engine Engine

  • Create a simulation scene Scene

  • Setup a renderer to visualize

  • Run a simulation loop

../../_images/hello_world.png

The full script can be downloaded here hello_world.py

Simulation engine and scene

To simulate with SAPIEN, you need to first create a simulation engine, and then create a simulation scene by the engine.

    engine = sapien.Engine()  # Create a physical simulation engine
    renderer = sapien.VulkanRenderer()  # Create a Vulkan renderer
    engine.set_renderer(renderer)  # Bind the renderer and the engine

    scene = engine.create_scene()  # Create an instance of simulation world (aka scene)
    scene.set_timestep(1 / 100.0)  # Set the simulation frequency

Engine is the physical simulation engine connected to the PhysX backend. One engine per process is allowed. Scene is an instance of the simulation world. Multiple scenes can be created through create_scene, and run independently. VulkanRenderer is the rendering engine connected to our vulkan-based renderer. The renderer should be bound with an engine, and then all the scenes created by the engine will be bound with the renderer.

Add rigid bodies

So far, our scene is empty. Actor (rigid body) is simulated in SAPIEN. Let’s add two actors, a ground and a box, to the scene. How to create actors will be elaborated in Create Actors.

    scene.add_ground(altitude=0)  # Add a ground
    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.])
    box = actor_builder.build(name='box')  # Add a box
    box.set_pose(sapien.Pose(p=[0, 0, 0.5]))

Viewer

Viewer creates a window (GUI) to render the simulation world. How to use the GUI will be elaborated in Viewer.


    # Add some lights so that you can observe the scene
    scene.set_ambient_light([0.5, 0.5, 0.5])
    scene.add_directional_light([0, 1, -1], [0.5, 0.5, 0.5])

    viewer = Viewer(renderer)  # Create a viewer (window)
    viewer.set_scene(scene)  # Bind the viewer and the scene

    # The coordinate frame in Sapien is: x(forward), y(left), z(upward)
    # The principle axis of the camera is the x-axis
    viewer.set_camera_xyz(x=-4, y=0, z=2)
    # The rotation of the free camera is represented as [roll(x), pitch(-y), yaw(-z)]
    # The camera now looks at the origin
    viewer.set_camera_rpy(r=0, p=-np.arctan2(2, 4), y=0)
    viewer.window.set_camera_parameters(near=0.05, far=100, fovy=1)

Note

The GUI is not necessary when you only need physical simulation, e.g. collecting experiences for policy learning.

Simulation loop

After setting up the simulation world, the actual simulation happens in a loop. For each iteration, the scene simulates for one step and updates the world to the renderer. The viewer calls render to update the results on the screen.

    while not viewer.closed:  # Press key q to quit
        scene.step()  # Simulate the world
        scene.update_render()  # Update the world to the renderer
        viewer.render()

Full script

 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
import sapien.core as sapien
from sapien.utils import Viewer
import numpy as np


def main():
    engine = sapien.Engine()  # Create a physical simulation engine
    renderer = sapien.VulkanRenderer()  # Create a Vulkan renderer
    engine.set_renderer(renderer)  # Bind the renderer and the engine

    scene = engine.create_scene()  # Create an instance of simulation world (aka scene)
    scene.set_timestep(1 / 100.0)  # Set the simulation frequency

    # NOTE: How to build actors (rigid bodies) is elaborated in create_actors.py
    scene.add_ground(altitude=0)  # Add a ground
    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.])
    box = actor_builder.build(name='box')  # Add a box
    box.set_pose(sapien.Pose(p=[0, 0, 0.5]))


    # Add some lights so that you can observe the scene
    scene.set_ambient_light([0.5, 0.5, 0.5])
    scene.add_directional_light([0, 1, -1], [0.5, 0.5, 0.5])

    viewer = Viewer(renderer)  # Create a viewer (window)
    viewer.set_scene(scene)  # Bind the viewer and the scene

    # The coordinate frame in Sapien is: x(forward), y(left), z(upward)
    # The principle axis of the camera is the x-axis
    viewer.set_camera_xyz(x=-4, y=0, z=2)
    # The rotation of the free camera is represented as [roll(x), pitch(-y), yaw(-z)]
    # The camera now looks at the origin
    viewer.set_camera_rpy(r=0, p=-np.arctan2(2, 4), y=0)
    viewer.window.set_camera_parameters(near=0.05, far=100, fovy=1)

    while not viewer.closed:  # Press key q to quit
        scene.step()  # Simulate the world
        scene.update_render()  # Update the world to the renderer
        viewer.render()


if __name__ == '__main__':
    main()