Particle system from python script not rendering in GUI

Hello everyone. I found an issue with a simulation including a particle system and I would like to ask you for your input. To me it seems like a bug during rendering but of course I might have done something wrong. Thanks a lot!.

Isaac Sim Version

4.2.0

Operating System

Ubuntu 22.04

GPU Information

  • Model: NVIDIA GeForce RTX 4070
  • Driver Version: 560.35.03

Topic Description

Detailed Description

Found a rendering issue when particle sampler objects are used from a Python script. I am trying to generate a liquid spills dataset and for that I am combining a simple physic simulation (for the liquid to fall) + replicator step to save the data. Given that writing a liquid in python can be a little bit complicated I decided to create a simple version from the GUI and then save it as a .usd file that I can load from the script. I tested this .usd file in a new instance of the GUI (opening it) and it works as expected.

The problem I found is that when I try to do the same from a python script, the blob of liquid floats and never reaches the ground (Or so it seems) even though the command world.step(render = True) is used. I tried several things to no avail until I added a rigid body below the blob and found that after a few frames it suddenly got thrown around the stage.

From this I can infer that the liquid is simulated but not rendered.

Steps to Reproduce

  1. Create a particle system from the GUI and save it as .usd
  2. Write a python script to simulate the physics and read the file.

You can find a small example here:

import isaacsim
from omni.isaac.kit import SimulationApp
import datetime
now = datetime.datetime.now()
now=now.strftime("%Y-%m-%d_%H:%M:%S")

ENV = "http://omniverse-content-production.s3-us-west-2.amazonaws.com/Assets/Isaac/4.2/Isaac/Environments/Simple_Warehouse/warehouse.usd"
OUTPUT_DIR =  "/home/alexismenendez/Downloads/Omniverse/test_sdg/replicator_output_"+ now
num_frames = 30
rt_subframes = 32

# Create the SimulationApp

# Use default config, otherwise pass a dict with the desired configuration
# Set headless to False to visualize the simulation
sim_app = SimulationApp(launch_config={"headless": False})

import omni.replicator.core as rep
import numpy as np
from omni.isaac.core.utils import prims
from omni.isaac.core import World
from omni.isaac.core.utils.stage import open_stage, get_current_stage
from pxr import Gf, UsdGeom, Usd

# Open the stage using the open_stage func.
# This function returns a boolean value indicating if the stage was opened successfully
if open_stage(ENV):
    print("Stage opened successfully")

stage = get_current_stage()

# Create cameras in stage
camera = rep.create.camera(
    focus_distance=400.0, focal_length=24.0, clipping_range=(0.1, 10000000.0), name="Cam"
)

# Set the writer and render products
render_prod = rep.create.render_product(camera, resolution = (1024, 1024), name = "RenderProduct")

writer = rep.WriterRegistry.get(writer_name = "BasicWriter")
writer.initialize( output_dir=OUTPUT_DIR, rgb=True, bounding_box_2d_tight=True)
# Attach the render products
writer.attach([render_prod])

# Create the water from the Sphere_liquid.usd
water = prims.create_prim(
    prim_path="/World",
    prim_type="Xform",
    usd_path="omniverse://localhost/Sphere_liquid.usd",
    semantic_label="water",
)

children_prim= water.GetAllChildren()
# Translate the water to the desired position by adding a translate op.
for k in children_prim:
    # Get children prims from the water prim
    subchildren_prim = k.GetAllChildren()
    for j in subchildren_prim:
        if j.GetName() in ["ParticleSystem", "Sphere"]:
            continue
        # Translate the ParticleSet prim
        prim_path = j.GetPath()
        xform = UsdGeom.Xformable(j)
        transform = xform.AddTranslateOp()
        transform.Set(Gf.Vec3f(0, 0, 2.5))
    
# Setup the randomizations to be triggered every frame
with rep.trigger.on_frame():
    with camera:
        # Fix camera position for now
        rep.modify.pose(
            position=(1, 9, 2),
            look_at=(0,0,0),
        )

# Create the physical sim
def water_phys(world, max_sim_steps=256):
    # Reset the world
    world.reset()
    # Iterate until the max_sim_steps or the liquid stops flowing
    for _ in range(max_sim_steps):
        # Step the world
        world.step(render = True)

# Start the SDG
print(f"Running SDG for {num_frames} frames")
# Set the world to use the torch backend and CUDA as particle systems require gpu dynamic flag true
world = World(physics_dt = 1/60, stage_units_in_meters = 1, backend= "torch", device = "cuda")

for i in range(num_frames):
    # Run a simulation before generating data
    water_phys(world)

    # Trigger any on_frame registered randomizers and the writers (delta_time=0.0 to avoid advancing the timeline)
    rep.orchestrator.step(delta_time=0.0, rt_subframes=32)

# Wait for the data to be written to disk
rep.orchestrator.wait_until_complete()

Screenshots or Videos

Flying liquid and the rigid body:

The rigid body moving as if it had collided with something:

Additional Information

What I’ve Tried

Tried to disable fabric (world.get_physics_context().enable_fabric(False)) but it did not work. Tested the liquid .usd file from the GUI and it works as expected

Related Issues

Found this git issue in IsaacLab with the same problem: [Question] Rendered as if the particles stopped in their initial state · Issue #996 · isaac-sim/IsaacLab · GitHub

Hi @alexis.menendez ,
Indeed Isosurface meshes don’t work with fabric enabled, because fabric doesn’t support mesh topology updates. The meshes can only be updated through USD. I am trying to inquire why disabling fabric might not work for you. I assume, if you disable the isosurface, the particles move just fine?

Hi @SimonPhysX,
Apologies I was traveling last week and was unable to answer sooner.
I tried disabling the isosurface (By creating a new usd file and loading it) but the results are the same (With fabric on and off). Maybe the way I am disabling fabric is wrong (or something is missing)? I am doing it like this:

world = World(physics_dt = 1/60, stage_units_in_meters = 1, backend= "torch", device = "cuda")
world.get_physics_context().enable_fabric(False)

If I may ask a question, would write the particle system directly in the script work? Or running the replicator through the GUI using a yaml? Thanks!

Hi!

I found a solution to this, you just need to add these lines to your script

# Set to CPU so that fabric is completely disabled and liquids are simulated
world = World(physics_dt = 1/60, stage_units_in_meters = 1, device = "cpu")
physx_interface = omni.physx.get_physx_interface()
# Override CPU setting to use GPU
physx_interface.overwrite_gpu_setting(1)

It seems you need to start the simulation with the GPU completely disabled and only then you can ask for the GPU to be used. I got this from the git issues in the IsaacLab repo [Question] Rendered as if the particles stopped in their initial state · Issue #996 · isaac-sim/IsaacLab · GitHub but as it was related to fabric I only tried to disable it.