Deformable Body Visualization problem from python

Isaac Sim Version

4.5.0

Operating System

Ubuntu 22.04

GPU Information

  • Model: RTX 4090

Topic Description

Detailed Description

following my question from this post: Deformable object not connected to mesh

I try to make a deformable object in the shape of a rope, but the visualization of the object dont follow the mesh.
The solution in this post: Deformable Body Visualization Issues - #3 by michalin
solved it in the GUI, yet when I generate the rope purely from Python I get the same mesh-vs-visual mismatch.

How can I apply the fix from that thread within a Python script?

Steps to Reproduce

this is the python file for configuring the rope I use
rope_cfg_file.txt (2.5 KB)

Hi @ido.sefi, this config file is able to create the mesh for the deformable body but it does not update the visual mesh which is the problem. I think the currently implementation does not support updating the deformable mesh so I will create a ticket to have that fixed.

In the meantime, another approach you can take is to use the Deformable Prim API directly and provide it mesh data. Here is example code that generates a cylinder programatically and assigns it to the deformable prim. I noticed you were trying to use very thin cylinder which may be an issue for simulation as interpenetrations can happen easily. If you can try to not use such small objects, it will be better.

Example code:

# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#

from isaacsim import SimulationApp

simulation_app = SimulationApp({"headless": False})

from isaacsim.core.api import World
from isaacsim.core.utils.stage import add_reference_to_stage
from isaacsim.storage.native import get_assets_root_path
import carb
import sys
from pxr import UsdGeom, Gf, PhysxSchema, Sdf
import numpy as np
import torch
import math

# Create a deformable mesh
from isaacsim.core.api.materials.deformable_material import DeformableMaterial
from isaacsim.core.prims import SingleDeformablePrim
from omni.physx.scripts import deformableUtils, physicsUtils
import isaacsim.core.utils.deformable_mesh_utils as deformableMeshUtils

def createTriangleMeshCylinder(radius=0.5, height=1.0, num_segments=16):
    """
    Create a triangle mesh cylinder programmatically.
    
    Args:
        radius: Radius of the cylinder
        height: Height of the cylinder
        num_segments: Number of segments around the circumference
    
    Returns:
        tuple: (points, indices) - Triangle mesh points and indices
    """
    points = []
    indices = []
    
    # Generate vertices for top and bottom circles
    for i in range(num_segments):
        angle = 2.0 * math.pi * i / num_segments
        x = radius * math.cos(angle)
        y = radius * math.sin(angle)
        
        # Bottom circle vertices
        points.append(Gf.Vec3f(x, y, -height/2.0))
        # Top circle vertices  
        points.append(Gf.Vec3f(x, y, height/2.0))
    
    # Add center vertices for top and bottom faces
    bottom_center_idx = len(points)
    points.append(Gf.Vec3f(0.0, 0.0, -height/2.0))
    top_center_idx = len(points)
    points.append(Gf.Vec3f(0.0, 0.0, height/2.0))
    
    # Generate triangles for side faces
    for i in range(num_segments):
        next_i = (i + 1) % num_segments
        
        # Bottom vertices indices
        bottom_curr = i * 2
        bottom_next = next_i * 2
        
        # Top vertices indices
        top_curr = i * 2 + 1
        top_next = next_i * 2 + 1
        
        # Side face triangles (two triangles per quad)
        indices.extend([bottom_curr, top_curr, bottom_next])
        indices.extend([top_curr, top_next, bottom_next])
    
    # Generate triangles for top and bottom faces
    for i in range(num_segments):
        next_i = (i + 1) % num_segments
        
        # Bottom face
        bottom_curr = i * 2
        bottom_next = next_i * 2
        indices.extend([bottom_center_idx, bottom_curr, bottom_next])
        
        # Top face
        top_curr = i * 2 + 1
        top_next = next_i * 2 + 1
        indices.extend([top_center_idx, top_next, top_curr])
    
    return points, indices

# Create world with torch backend for better deformable performance
my_world = World(stage_units_in_meters=1.0, backend="torch", device="cuda")
print("Using torch backend with CUDA")

# # Add default ground plane
my_world.scene.add_default_ground_plane()


# Get stage
stage = simulation_app.context.get_stage()

# Create parent scope for organization
env_scope = UsdGeom.Scope.Define(stage, "/World/Envs")
cube_path = "/World/Envs/DeformableCylinder"
cube_xform = UsdGeom.Xform.Define(stage, cube_path)

# Define the mesh path where deformable physics will be applied
mesh_path = cube_xform.GetPrim().GetPath().AppendChild("cylinder").pathString
cube_mesh = UsdGeom.Mesh.Define(stage, mesh_path)

# Rotate the cube mesh by 90 degrees around the X-axis
# Create rotation attribute and set it to 90 degrees around X-axis
# Get the prim at the mesh path and add rotation attribute
rotation_attr = cube_mesh.AddRotateXOp().Set(90.0)

# Create cylinder mesh
tri_points, tri_indices = createTriangleMeshCylinder(radius=0.01, height=1.0, num_segments=16)

# Set initial location
init_loc = Gf.Vec3f(0.0, 0.0, 4.0)
physicsUtils.set_or_add_translate_op(cube_mesh, init_loc)

# Set mesh attributes
cube_mesh.GetPointsAttr().Set(tri_points)
cube_mesh.GetFaceVertexIndicesAttr().Set(tri_indices)
cube_mesh.GetFaceVertexCountsAttr().Set([3] * (len(tri_indices) // 3))

# Create deformable material
deformable_material = DeformableMaterial(
    prim_path=cube_path + "/deformableMaterial",
    dynamic_friction=0.5,
    youngs_modulus=5e4,      # Controls stiffness
    poissons_ratio=0.4,      # Controls volume preservation
    damping_scale=0.1,       # Controls damping of deformation
    elasticity_damping=0.1,  # Controls damping of elastic forces
)

# Create deformable prim
deformable_cube = SingleDeformablePrim(
    name="deformableCylinder",
    prim_path=mesh_path,
    deformable_material=deformable_material,
    vertex_velocity_damping=0.0,
    sleep_damping=1.0,
    sleep_threshold=0.05,
    settling_threshold=0.1,
    self_collision=True,
    self_collision_filter_distance=0.05,
    solver_position_iteration_count=20,
    kinematic_enabled=False,
    simulation_hexahedral_resolution=2,  # Resolution of the simulation mesh
    collision_simplification=True,
)

# Add the deformable cube to the scene
my_world.scene.add(deformable_cube)

physx_scene = PhysxSchema.PhysxSceneAPI.Apply(stage.GetPrimAtPath("/physicsScene"))
physx_scene.GetTimeStepsPerSecondAttr().Set(240)

# Set simulation timesteps
my_world.reset()

# Main simulation loop
import time
start_time = time.time()

print("Simulation started. The cylinder will be pushed every 3 seconds.")
print("Press Ctrl+C to exit.")

while simulation_app.is_running():
    current_time = time.time() - start_time
    
    # Step the simulation
    my_world.step(render=True)

1 Like

thank you very much!

1 Like