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:

    # 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.