Creating a soft-body simulation#
This tutorial shows how to create a soft-body simulation using SimulationManager. It covers the setup of the simulation context, adding a deformable mesh (soft object), and running the simulation loop.
The Code#
The tutorial corresponds to the create_softbody.py script in the scripts/tutorials/sim directory.
Code for create_softbody.py
1# ----------------------------------------------------------------------------
2# Copyright (c) 2021-2026 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 simulation scene using SimulationManager.
19It shows the basic setup of simulation context, adding objects, lighting, and sensors.
20"""
21
22from __future__ import annotations
23
24import argparse
25import time
26from dexsim.utility.path import get_resources_data_path
27from embodichain.lab.sim import SimulationManager, SimulationManagerCfg
28from embodichain.lab.gym.utils.gym_utils import add_env_launcher_args_to_parser
29from embodichain.lab.visualization import visualization_cfg_from_args
30from embodichain.lab.sim.cfg import (
31 RenderCfg,
32 SoftbodyVoxelAttributesCfg,
33 SoftbodyPhysicalAttributesCfg,
34)
35from embodichain.lab.sim.shapes import MeshCfg
36from embodichain.lab.sim.objects import (
37 SoftObject,
38 SoftObjectCfg,
39)
40
41
42def main():
43 """Main function to create and run the simulation scene."""
44
45 # Parse command line arguments
46 parser = argparse.ArgumentParser(
47 description="Create a simulation scene with SimulationManager"
48 )
49 add_env_launcher_args_to_parser(parser)
50 args = parser.parse_args()
51
52 # Configure the simulation
53 sim_cfg = SimulationManagerCfg(
54 width=1920,
55 height=1080,
56 headless=True,
57 num_envs=args.num_envs,
58 physics_dt=1.0 / 100.0, # Physics timestep (100 Hz)
59 sim_device="cuda", # soft simulation only supports cuda device
60 render_cfg=RenderCfg(
61 renderer=args.renderer
62 ), # Enable ray tracing for better visuals
63 visualization=visualization_cfg_from_args(args),
64 )
65
66 # Create the simulation instance
67 sim = SimulationManager(sim_cfg)
68
69 print("[INFO]: Scene setup complete!")
70
71 # add softbody to the scene
72 cow: SoftObject = sim.add_soft_object(
73 cfg=SoftObjectCfg(
74 uid="cow",
75 shape=MeshCfg(
76 fpath=get_resources_data_path("Model", "cow", "cow.obj"),
77 ),
78 init_pos=[0.0, 0.0, 3.0],
79 voxel_attr=SoftbodyVoxelAttributesCfg(
80 simulation_mesh_resolution=8,
81 maximal_edge_length=0.5,
82 ),
83 physical_attr=SoftbodyPhysicalAttributesCfg(
84 youngs=1e6,
85 poissons=0.45,
86 density=100,
87 dynamic_friction=0.1,
88 min_position_iters=30,
89 ),
90 ),
91 )
92 print("[INFO]: Add soft object complete!")
93
94 # Open window when the scene has been set up
95 if not args.headless:
96 sim.open_window()
97
98 print(f"[INFO]: Running simulation with {args.num_envs} environment(s)")
99 print("[INFO]: Press Ctrl+C to stop the simulation")
100
101 # Run the simulation
102 run_simulation(sim, cow)
103
104
105def run_simulation(sim: SimulationManager, soft_obj: SoftObject) -> None:
106 """Run the simulation loop.
107
108 Args:
109 sim: The SimulationManager instance to run
110 soft_obj: soft object
111 """
112
113 # Initialize GPU physics
114 sim.init_gpu_physics()
115
116 step_count = 0
117
118 try:
119 last_time = time.time()
120 last_step = 0
121 while True:
122 # Update physics simulation
123 sim.update(step=1)
124 step_count += 1
125
126 # Print FPS every second
127 if step_count % 100 == 0:
128 current_time = time.time()
129 elapsed = current_time - last_time
130 fps = (
131 sim.num_envs * (step_count - last_step) / elapsed
132 if elapsed > 0
133 else 0
134 )
135 print(f"[INFO]: Simulation step: {step_count}, FPS: {fps:.2f}")
136 last_time = current_time
137 last_step = step_count
138 if step_count % 500 == 0:
139 soft_obj.reset()
140
141 except KeyboardInterrupt:
142 print("\n[INFO]: Stopping simulation...")
143 finally:
144 # Clean up resources
145 sim.destroy()
146 print("[INFO]: Simulation terminated successfully")
147
148
149if __name__ == "__main__":
150 main()
The Code Explained#
Configuring the simulation#
The first step is to configure the simulation environment. This is done using the SimulationManagerCfg data class, which allows you to specify parameters like window dimensions, headless mode, physics timestep, simulation device (CPU/GPU), and rendering options like ray tracing. Reminded that soft body simulation can only run on cuda deive.
# Configure the simulation
sim_cfg = SimulationManagerCfg(
width=1920,
height=1080,
headless=True,
num_envs=args.num_envs,
physics_dt=1.0 / 100.0, # Physics timestep (100 Hz)
sim_device="cuda", # soft simulation only supports cuda device
render_cfg=RenderCfg(
renderer=args.renderer
), # Enable ray tracing for better visuals
visualization=visualization_cfg_from_args(args),
)
# Create the simulation instance
sim = SimulationManager(sim_cfg)
print("[INFO]: Scene setup complete!")
Adding a soft body to the scene#
With the simulation context created, we can add a soft (deformable) object. This tutorial demonstrates adding a soft-body cow mesh to the scene using the SimulationManager.add_soft_object() method. The object’s geometry and physical parameters are defined through configuration objects:
cfg.MeshCfgfor the mesh shape (cow.obj)cfg.SoftbodyVoxelAttributesCfgfor voxelization and simulation mesh resolutioncfg.SoftbodyPhysicalAttributesCfgfor material properties (Young’s modulus, Poisson’s ratio, density, frictions, solver iterations)
# add softbody to the scene
cow: SoftObject = sim.add_soft_object(
cfg=SoftObjectCfg(
uid="cow",
shape=MeshCfg(
fpath=get_resources_data_path("Model", "cow", "cow.obj"),
),
init_pos=[0.0, 0.0, 3.0],
voxel_attr=SoftbodyVoxelAttributesCfg(
simulation_mesh_resolution=8,
maximal_edge_length=0.5,
),
physical_attr=SoftbodyPhysicalAttributesCfg(
youngs=1e6,
poissons=0.45,
density=100,
dynamic_friction=0.1,
min_position_iters=30,
),
),
)
print("[INFO]: Add soft object complete!")
The Code Execution#
To run the script and see the result, execute the following command:
python scripts/tutorials/sim/create_softbody.py
A window should appear showing a soft-body cow mesh falling onto a ground plane. To stop the simulation, you can either close the window or press Ctrl+C in the terminal.
You can also pass arguments to customize the simulation. For example, to run in headless mode with n parallel environments using the specified device:
python scripts/tutorials/sim/create_softbody.py --headless --num_envs <n> --device <cuda/cpu>
To inspect the deforming collision surface in a browser:
python scripts/tutorials/sim/create_softbody.py \
--viser \
--viser-soft-body-fps 5
DexSim exposes live soft-body collision vertices but not their triangle
connectivity. The Viser preview therefore uses a stable convex-hull surface:
motion and deformation are visible, while concave details of the original cow
render mesh are intentionally simplified. Lower
--viser-soft-body-fps when publishing large soft bodies or several
environments.
See Browser visualization with Viser for details.
Now that we have a basic understanding of how to create a soft-body scene, let’s move on to more advanced topics.