Deformables#
A deformable is an asset whose shape changes during simulation. Unlike a rigid body, it has no rigid root frame: its state is the position and velocity of every node of its simulation mesh.
Isaac Lab models three kinds of deformable, distinguished by the dimensionality of the simulated geometry:
Property |
Volume |
Surface |
Cable |
|---|---|---|---|
Models |
Soft solids: rubber blocks, teddy bears, organs |
Cloth, sheets, membranes |
Ropes, hoses, wires, harnesses |
Simulated geometry |
Tetrahedral mesh ( |
Triangle mesh ( |
Open curve ( |
Asset class |
|||
Runtime state |
Nodal positions and velocities |
Nodal positions and velocities |
Per-segment poses and velocities |
Volume and surface deformables share one asset class and one authoring pattern; they differ only in the physics material assigned to them. Cables are a separate asset class with their own spawner, material, and state layout, and are covered in Cables.
Particle-based materials such as fluids and granular media are not deformables in this sense. They use a separate asset and solver; see Using Implicit MPM.
Note
All three kinds are under active development. On Newton, deformables are implemented in
isaaclab_contrib.deformable and re-exported through isaaclab_newton.assets.
Cable support in particular is experimental: its spawner cfg, asset class, and material
defaults may still change.
Backend support#
Kind |
PhysX |
Newton |
OvPhysX |
|---|---|---|---|
Volume |
Yes |
Yes, VBD solver only |
Experimental, CUDA devices only |
Surface |
Yes |
Yes, VBD solver only |
Experimental, CUDA devices only |
Cable |
No |
Yes, VBD solver only |
No |
On Newton, deformables of every kind are simulated by the VBD solver, so a scene containing them must select a physics cfg whose solver is VBD. For the solver parameters, for running a rigid robot and a deformable in one scene, and for the tuning workflow, see VBD Solver and Coupled Solvers.
OvPhysX deformables carry further restrictions on node counts and startup cost. See OvPhysX Backend.
Volume and surface deformables#
Loading from USD#
A deformable can also come from a pre-authored asset. Pass deformable_props and
physics_material to UsdFileCfg; the spawner applies
the deformable schema to the loaded prim, or modifies it in place if the prim already carries one.
cfg_usd = sim_utils.UsdFileCfg(
usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Objects/Teddy_Bear/teddy_bear.usd",
deformable_props=PhysxDeformableBodyPropertiesCfg(),
physics_material=PhysxDeformableBodyMaterialCfg(),
scale=[0.05, 0.05, 0.05],
)
Volume or surface#
There is no explicit type field, and no separate cloth asset class. At authoring time the kind
follows from the material cfg: a material deriving from
SurfaceDeformableBodyMaterialBaseCfg produces a surface
deformable, and anything else produces a volume deformable. That choice decides what USD is
authored, a UsdGeom.TetMesh simulation mesh for volume and a triangle UsdGeom.Mesh copy of
the visual mesh for surface.
At initialization the asset re-derives the kind from the stage. PhysX and OvPhysX read the applied
schema on the bound physics material, falling back to mesh topology when that is inconclusive;
Newton uses topology alone, treating a UsdGeom.TetMesh under the prim as volume and a plain
UsdGeom.Mesh as surface.
So the material cfg is load-bearing: pairing a volume material with a cloth-shaped mesh authors a tetrahedralized solid, not a sheet.
Tetrahedralization#
Volume deformables need a tetrahedral simulation mesh. When the spawned prim does not already
contain a UsdGeom.TetMesh, Isaac Lab generates one, which requires the optional
tetrahedralization dependencies on every backend:
uv sync --inexact --extra tetrahedralization
# With the legacy installer.
./isaaclab.sh -i tetrahedralization
Surface deformables never need it, and neither do volume deformables loaded from a USD that already
ships a pre-tetrahedralized UsdGeom.TetMesh under the deformable prim.
Runtime state#
The state of a deformable is nodal, expressed in the simulation world frame. N below is
max_sim_vertices_per_body.
data.nodal_pos_wanddata.nodal_vel_w, shape(num_instances, N)ofvec3f, positions [m] and velocities [m/s].data.nodal_state_w, the same data as(num_instances, N)ofvec6f.data.default_nodal_state_w, the spawn state, used for resets.data.root_pos_wanddata.root_vel_w, shape(num_instances,). These are derived quantities, computed as the mean over the simulation nodes. There is no root orientation.
Write state back with the indexed setters. transform_nodal_pos()
applies a pose offset relative to the current nodal mean, which is how a spawn-state buffer is
scattered across environment origins.
nodal_state = cube.data.default_nodal_state_w.torch[env_ids].clone()
nodal_state[..., :3] = cube.transform_nodal_pos(nodal_state[..., :3], pos, quat)
cube.write_nodal_state_to_sim_index(nodal_state, env_ids=env_ids)
cube.reset(env_ids=env_ids)
Like every other asset, a DeformableObject integrates with
InteractiveScene, scene.get_state / scene.reset_to, and the
reset_scene_to_default event term.
Note
The unsuffixed writers (write_nodal_state_to_sim and friends) are deprecated in favor of the
_to_sim_index and _to_sim_mask variants. The mask variants are CUDA-graph capturable.
Cables#
A cable is a 1D rod: a single open UsdGeom.BasisCurves prim carrying the
PhysicsCurvesDeformableSimAPI schema, simulated as a chain of per-segment capsule bodies joined
by cable joints.
Cable material parameters#
CableMaterialCfg defines the cable’s geometry and
stiffness. All values are validated at author time; nonfinite or out-of-range values raise a
ValueError before any prim is created.
The stiffness fields are elastic moduli, not joint stiffnesses. Each rod joint gets its own
discretized stiffness, using that joint’s dual rest length L = 0.5 * (L_parent + L_child),
where L_parent and L_child are the rest lengths of the two segments it spans.
Parameter |
Description |
|---|---|
|
Full cable thickness (diameter) [m]. Must be finite and positive. Used as
|
|
Cable density [kg/m^3]. Must be finite and positive. Per-segment mass is derived from the
density and the capsule volume. Default |
|
Axial (stretch) elastic modulus |
|
Bending elastic modulus |
|
Transverse shear elastic modulus [Pa]. Must be finite and nonnegative. Optional: when left
at |
|
Torsional elastic modulus [Pa]. Must be finite and nonnegative. Optional: when left at
|
Note
A cable joint has four degrees of freedom: linear stretch and shear, and angular bend and
twist. Leaving shear_stiffness or twist_stiffness unset does not mean the cable has
no shear or twist resistance; it means the solver falls back to the stretch and bend values.
Authoring 0.0 is distinct from leaving them unset: it removes that resistance.
The two fallbacks are not symmetric. Shear reuses the stretch modulus, applied to the same
cross-section area. Twist reuses the bend structural stiffness E * I / L, whereas an
explicitly authored twist_stiffness is applied to the polar moment J = 2 * I. Setting
twist_stiffness = bend_stiffness therefore gives twice the fallback stiffness, not the same
value.
Damping is not exposed. The rod joints have damping, but the USD curve-material schema Isaac Lab authors has no attribute for it.
To target a specific axial E * A or bending E * I, invert these relations to pick the
modulus; scripts/demos/cables.py does this from a target stiffness and the segment geometry.
Cable collision#
Collision is opt-in through collision_props. When enabled, the importer applies
adjacent-segment-only filtering: directly connected segments, which share a joint anchor and
would otherwise jitter, are filtered, while every other pair collides. As a result:
The cable collides with the ground and with other cables.
Non-adjacent segments of the same cable collide, so a cable can self-arrest when it loops back on itself.
When collision_props is omitted, the cable imports as a dynamics-only rod and does not collide.
Cable runtime state#
CableObject exposes per-segment world state and integrates with
InteractiveScene, scene.get_state / scene.reset_to, and the
reset_scene_to_default event term.
cable.data.segment_pose_w, shape(num_instances, num_segments)ofwp.transformf, position [m] followed by quaternion(x, y, z, w). The Torch view has a trailing dimension of 7.cable.data.segment_velocity_w, shape(num_instances, num_segments)ofwp.spatial_vectorf, linear [m/s] followed by angular [rad/s]. The Torch view has a trailing dimension of 6.cable.data.default_segment_pose_wanddefault_segment_velocity_w, the spawn state.
Write per-segment state back with the indexed or masked setters; the masked form is CUDA-graph capturable.
cable.write_segment_pose_to_sim_index(segment_pose=cable.data.default_segment_pose_w)
cable.write_segment_velocity_to_sim_index(segment_velocity=cable.data.default_segment_velocity_w)
Writes update the maximal-coordinate body state directly, for both simulation states, and flag the affected environments for a solver reset.
Loading cables from USD#
Physics is authored in place on the curve: spawn_cable() applies
the PhysicsCurvesDeformableSimAPI schema and binds a deformable-curve material, and the curve is
imported natively. Topology comes from the curve’s own points and curveVertexCounts; no
custom edge attribute is required.
A cable can therefore also be loaded from an external USD, for example one authored in a DCC tool,
via UsdFileCfg, provided the curve already carries:
a single open, linear, nonperiodic
UsdGeom.BasisCurvesunder the loaded prim,the
PhysicsCurvesDeformableSimAPIapplied schema, anda bound deformable-curve material (
PhysicsCurvesDeformableMaterialAPI) supplyingthickness,density,stretchStiffness, andbendStiffnessin thephysics:namespace.
Two failure modes follow from that list. A curve without the sim schema is not part of the
deformable import at all and is silently skipped. A curve that has the schema but no resolvable
thickness is imported with a default radius and a warning. Author cables through
spawn_cable(), or apply the schema and material to the imported
prim before construction.
Cable rendering#
Cables render in the Kit viewport as UsdGeom.BasisCurves. At render cadence the curve points are
refreshed from the cable segment endpoints so the rendered shape always matches the simulation.
Note
Curve points are synchronized through CPU Fabric because the RTX Hydra delegate does not
read GPU-backed Fabric arrays for BasisCurves (NVBug 6502662). Periodic curves are skipped
by the sync.
Cable limitations#
One standalone, unwelded cable per object.
CableObjectrequires exactly oneBasisCurvesprim carryingPhysicsCurvesDeformableSimAPIunderprim_path, holding a single open curve that is not welded to another cable. Multi-curveBasisCurvesprims, periodic (closed) curves, and hard coincident curve-to-curvePhysicsAttachmentwelds all fail during initialization.Cable ends can be pinned, not clamped. A
PhysicsAttachmentto an xform target lowers to a ball joint, so it constrains position only and the cable pivots freely at the anchor. Rigid plugs and end fittings that must transfer orientation are not representable.No damping knobs. The four stiffness moduli are exposed; their damping counterparts are not.
CPU-only render sync (NVBug 6502662); periodic curves are not synced.
Culled by Isaac RTX scene partitioning once the cable deforms beyond its initial extent (OMPE-105749). See Animated curves disappear under Isaac RTX scene partitioning.
Note
An attachment joint is created only when the attachment stiffness is unauthored or infinite. A finite stiffness is kept as metadata and no joint is created. Both cases are import warnings rather than errors, so the cable initializes normally with the attachment missing. Check the importer output when an attachment appears to have no effect.
Note
Topologies the runtime object rejects still simulate: the physics model is built from the whole
USD stage, so every curve carrying PhysicsCurvesDeformableSimAPI is imported whether or not
a CableObject wraps it. Drive them through
NewtonManager get_model() / get_state_0() and your own
newton.selection.ArticulationView. There is no Isaac Lab asset wrapper for those cases.
Material parameters in practice#
Each animation below runs the same scene three times, changing one material parameter and holding everything else fixed. The labels give the value used in each run.
Volume#
Young’s modulus: overall stiffness. At 1e3 Pa the ball collapses into a pancake on
impact; at 1e5 Pa it barely deforms. This is the first knob to reach for when a soft body
is too floppy or too rigid.#
Poisson’s ratio: how strongly the material preserves volume under compression. At 0.10
the ball squashes without spreading. At 0.49 it is nearly incompressible, so the same
squash has to go somewhere and pushes outward into a wide bulge.#
Particle radius: the contact thickness around each simulation node, not a material property. A larger radius detects contact further from the surface, so the ball rests visibly higher off the table and cannot be compressed as thin. Too small and contacts are missed or detected late; too large relative to the mesh resolution and they start too early.#
Surface#
Stretch stiffness: resistance to in-plane elongation. The low value lets the sheet stretch and sag under its own weight; the high value holds it near its rest length.#
Bend stiffness: resistance to folding. At 1e-2 the sheet crumples into a loose heap; at
1e0 it keeps large, stiff folds and stays draped over the roller. This is the difference
between silk and canvas.#
Cable#
Bend stiffness: at 1e0 the cable droops between its supports like slack rope; at
1e2 it holds itself straight like a stiff hose.#
Twist stiffness: a weighted cable is twisted at its anchor. At 1e-1 the twist is
absorbed locally and the cable hangs straight. At 1e1 torsion is carried along the rod
until it buckles and coils into a helix. Set this explicitly when a cable should resist
winding, since leaving it unset falls back to the bend value as described above.#
Demos and tasks#
Run a demo first to confirm that the spawner, solver, and visualizer all work in your environment.
Kind |
Demo |
Tasks |
|---|---|---|
Volume |
|
|
Surface |
|
|
Cable |
|
|
# Volume and surface deformables falling onto a ground plane.
uv run --extra isaacsim --extra tetrahedralization python scripts/demos/deformables.py
# A pile of cables that collide and settle. Newton VBD only.
uv run --extra isaacsim python scripts/demos/cables.py
# A larger cable pile, without a visualizer, stopping after a fixed number of steps.
uv run python scripts/demos/cables.py --visualizer none --num_cables 40 --num_segments 15 --max_steps 500
scripts/environments/state_machine/lift_franka_soft.py drives Isaac-Lift-Soft-Franka with a
scripted state machine, which is a useful starting point for a deformable manipulation task.