Rigid object group tutorial#

This tutorial shows how to create and use a RigidObjectGroup in SimulationManager. It follows the style used in the create_scene tutorial and references the example script located in scripts/tutorials/sim/create_rigid_object_group.py.

The Code#

The tutorial corresponds to the create_rigid_object_group.py script in the scripts/tutorials/sim directory.

Code for create_rigid_object_group.py
  1# ----------------------------------------------------------------------------
  2# Copyright (c) 2021-2025 DexForce Technology Co., Ltd.
  3#
  4# Licensed under the Apache License, Version 2.0 (the "License");
  5# you may not use this file except in compliance with the License.
  6# You may obtain a copy of the License at
  7#
  8#     http://www.apache.org/licenses/LICENSE-2.0
  9#
 10# Unless required by applicable law or agreed to in writing, software
 11# distributed under the License is distributed on an "AS IS" BASIS,
 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13# See the License for the specific language governing permissions and
 14# limitations under the License.
 15# ----------------------------------------------------------------------------
 16
 17"""
 18This script demonstrates how to create a rigid object group using SimulationManager.
 19"""
 20
 21import argparse
 22import time
 23
 24from embodichain.lab.sim import SimulationManager, SimulationManagerCfg
 25from embodichain.lab.sim.cfg import RigidBodyAttributesCfg
 26from embodichain.lab.sim.shapes import CubeCfg
 27from embodichain.lab.sim.objects import (
 28    RigidObjectGroup,
 29    RigidObjectGroupCfg,
 30    RigidObjectCfg,
 31)
 32
 33
 34def main():
 35    """Main function to create and run the simulation scene."""
 36
 37    # Parse command line arguments
 38    parser = argparse.ArgumentParser(
 39        description="Create a simulation scene with SimulationManager"
 40    )
 41    parser.add_argument(
 42        "--headless",
 43        action="store_true",
 44        default=False,
 45        help="Run simulation in headless mode",
 46    )
 47    parser.add_argument(
 48        "--num_envs", type=int, default=1, help="Number of parallel environments"
 49    )
 50    parser.add_argument(
 51        "--device", type=str, default="cpu", help="Simulation device (cuda or cpu)"
 52    )
 53    parser.add_argument(
 54        "--enable_rt",
 55        action="store_true",
 56        default=False,
 57        help="Enable ray tracing for better visuals",
 58    )
 59    args = parser.parse_args()
 60
 61    # Configure the simulation
 62    sim_cfg = SimulationManagerCfg(
 63        width=1920,
 64        height=1080,
 65        headless=True,
 66        physics_dt=1.0 / 100.0,  # Physics timestep (100 Hz)
 67        sim_device=args.device,
 68        enable_rt=args.enable_rt,  # Enable ray tracing for better visuals
 69    )
 70
 71    # Create the simulation instance
 72    sim = SimulationManager(sim_cfg)
 73
 74    # Build multiple arenas if requested
 75    if args.num_envs > 1:
 76        sim.build_multiple_arenas(args.num_envs, space=3.0)
 77
 78    physics_attrs = RigidBodyAttributesCfg(
 79        mass=1.0,
 80        dynamic_friction=0.5,
 81        static_friction=0.5,
 82        restitution=0.1,
 83    )
 84
 85    # Add objects to the scene
 86    obj_group: RigidObjectGroup = sim.add_rigid_object_group(
 87        cfg=RigidObjectGroupCfg(
 88            uid="obj_group",
 89            rigid_objects={
 90                "cube_1": RigidObjectCfg(
 91                    uid="cube_1",
 92                    shape=CubeCfg(size=[0.1, 0.1, 0.1]),
 93                    attrs=physics_attrs,
 94                    init_pos=[0.0, 0.0, 1.0],
 95                ),
 96                "cube_2": RigidObjectCfg(
 97                    uid="cube_2",
 98                    shape=CubeCfg(size=[0.2, 0.2, 0.2]),
 99                    attrs=physics_attrs,
100                    init_pos=[0.5, 0.0, 1.0],
101                ),
102                "cube_3": RigidObjectCfg(
103                    uid="cube_3",
104                    shape=CubeCfg(size=[0.3, 0.3, 0.3]),
105                    attrs=physics_attrs,
106                    init_pos=[-0.5, 0.0, 1.0],
107                ),
108            },
109        )
110    )
111
112    print("[INFO]: Scene setup complete!")
113    print(f"[INFO]: Running simulation with {args.num_envs} environment(s)")
114    print("[INFO]: Press Ctrl+C to stop the simulation")
115
116    # Open window when the scene has been set up
117    if not args.headless:
118        sim.open_window()
119
120    # Run the simulation
121    run_simulation(sim)
122
123
124def run_simulation(sim: SimulationManager):
125    """Run the simulation loop.
126
127    Args:
128        sim: The SimulationManager instance to run
129    """
130
131    # Initialize GPU physics if using CUDA
132    if sim.is_use_gpu_physics:
133        sim.init_gpu_physics()
134
135    step_count = 0
136
137    try:
138        last_time = time.time()
139        last_step = 0
140        while True:
141            # Update physics simulation
142            sim.update(step=1)
143            step_count += 1
144
145            # Print FPS every second
146            if step_count % 100 == 0:
147                current_time = time.time()
148                elapsed = current_time - last_time
149                fps = (
150                    sim.num_envs * (step_count - last_step) / elapsed
151                    if elapsed > 0
152                    else 0
153                )
154                print(f"[INFO]: Simulation step: {step_count}, FPS: {fps:.2f}")
155                last_time = current_time
156                last_step = step_count
157
158    except KeyboardInterrupt:
159        print("\n[INFO]: Stopping simulation...")
160    finally:
161        # Clean up resources
162        sim.destroy()
163        print("[INFO]: Simulation terminated successfully")
164
165
166if __name__ == "__main__":
167    main()

The Code Explained#

Adding a RigidObjectGroup#

The key part of the tutorial demonstrates creating a RigidObjectGroup via sim.add_rigid_object_group. The group is configured with a mapping of object UIDs to RigidObjectCfg entries. Each entry defines a shape (here CubeCfg), physics attributes, and initial pose.

    obj_group: RigidObjectGroup = sim.add_rigid_object_group(
        cfg=RigidObjectGroupCfg(
            uid="obj_group",
            rigid_objects={
                "cube_1": RigidObjectCfg(
                    uid="cube_1",
                    shape=CubeCfg(size=[0.1, 0.1, 0.1]),
                    attrs=physics_attrs,
                    init_pos=[0.0, 0.0, 1.0],
                ),
                "cube_2": RigidObjectCfg(
                    uid="cube_2",
                    shape=CubeCfg(size=[0.2, 0.2, 0.2]),
                    attrs=physics_attrs,
                    init_pos=[0.5, 0.0, 1.0],
                ),
                "cube_3": RigidObjectCfg(
                    uid="cube_3",
                    shape=CubeCfg(size=[0.3, 0.3, 0.3]),
                    attrs=physics_attrs,
                    init_pos=[-0.5, 0.0, 1.0],
                ),
            },
        )
    )

    print("[INFO]: Scene setup complete!")

Running the tutorial#

To run the script from the repository root:

python scripts/tutorials/sim/create_rigid_object_group.py

You can pass flags such as --headless, --num_envs <n>, and --device <cpu|cuda> to customize the run.