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.