Deformable Body Simulation
Isaac Sim supports deformable body simulation on GPU. This page in the Omniverse extensions documentation provides detailed (still inadequate yet) information. In this page, we provide some handy snippets.
Create a deformable mesh for deformable body
As an example, this code creates a cube mesh via the kit
command:
def create_cube_mesh(stage, target_path):
_, tmp_path = omni.kit.commands.execute("CreateMeshPrim", prim_type="Cube")
omni.kit.commands.execute("MovePrim", path_from=tmp_path, path_to=target_path)
omni.usd.get_context().get_selection().set_selected_prim_paths([], False)
return UsdGeom.Mesh.Get(stage, target_path)
# Add a cube mesh to `/World/deformable`
stage = omni.usd.get_context().get_stage()
deformable_prim_path = "/World/deformable"
cube_mesh = create_cube_mesh(stage, deformable_prim_path)
# You can specify its pose and scale:
pos = ...
rot = ...
scale = ...
cube_mesh.AddTranslateOp().Set(tuple(Gf.Vec3f(*pos)))
cube_mesh.AddOrientOp().Set(Gf.Quatf(*rot))
cube_mesh.AddScaleOp().Set(tuple(Gf.Vec3f(*scale*)))
# Add PhysX deformable body
deformableUtils.add_physx_deformable_body(
stage,
deformable_prim_path,
simulation_hexahedral_resolution=4,
collision_simplification=True,
self_collision=False,
solver_position_iteration_count=20,
)
simulation_hexahedral_resolution
specifies the resolution of the hexahedron (the blue ones) to be created in order to simulate deformation. Use collision_simplification
to simplify the collision computation. 20 should be enough for solver_position_iteration_count
. More details of setting these parameters can be found here.
Note that you don't need to add collider and rigid body API to a deformable body mesh, for the deformable body API will handle the collision itself.
Create a physics material
Normally, adding deformable body material will make a mesh deformable. However, if you want to adjust the parameters, you need to create a physics material, and apply it to the mesh.
def_mat_path = "/DeformableBodyMaterial"
deformable_material_path = omni.usd.get_stage_next_free_path(stage, def_mat_path, True)
deformableUtils.add_deformable_body_material(
stage,
self.deformable_material_path,
youngs_modulus=100000.0,
poissons_ratio=0.499,
damping_scale=0.0,
elasticity_damping=0.0001,
dynamic_friction=1.0,
density=300,
)
These parameters are vital:
youngs_modulus
should be a positive float number. Higher value results in more stiff body.dynamic_friction
should be a positive float number. It indicates the dymaic friction of the contact surface.
Assign the material to the mesh
physicsUtils.add_physics_material_to_prim(stage, get_prim_at_path(deformable_prim_path), self.deformable_material_path)
physxCollisionAPI = PhysxSchema.PhysxCollisionAPI.Apply(get_prim_at_path(deformable_prim_path))
physxCollisionAPI.CreateRestOffsetAttr().Set(0.0)
physxCollisionAPI.GetContactOffsetAttr().Set(0.0)
Set attachment
Creating attachment will attach some texahedrons (the green ones) to a mesh with either collider API, rigid body API, or deformable body API. A known issue is that the deformable body cannot be attached to a part in an articulation (e.g., on a link of the Franka robot).
# Specify which mesh to attach to. It should have at least one of: collider API, rigid body API, or deformable body API.
attach_prim_path = "/World/base"
attach_prim = stage.GetPrimAtPath(attach_prim_path)
# Set up attachment
attachment_path = cube_mesh.GetPath().AppendElementString("attachment")
attachment = PhysxSchema.PhysxPhysicsAttachment.Define(stage, attachment_path)
attachment.GetActor0Rel().SetTargets([cube_mesh.GetPath()])
attachment.GetActor1Rel().SetTargets([attach_prim.GetPath()])
PhysxSchema.PhysxAutoAttachmentAPI.Apply(attachment.GetPrim())