RigidBody Prim is not updated in rendering pipeline if set to kinematic

Isaac Sim Version

5.0.0

Operating System

Ubuntu 22.04

GPU Information

  • Model: RTX 3090
  • Driver Version: 575.64.03

Topic Description

If we create a prim with RigidBodyAPI and set the kinematic attribute to true, then this prim’s rendering pose will not be updated if we use physx set_transforms api to change its pose.

This bug happens when we use cuda backend for the SimulationContext class. No such issue when used with numpy backend. I think this is related to the GPU pipeline of physX and the sync between physX and RTX renderings.

In the video you can see that if I change the kinematic during simulation in the GUI, suddenly the bug disappears.

Detailed Description

import os
import isaacsim

use_full_exp_file = True
simulation_app = isaacsim.SimulationApp(
    launch_config={"headless": False},
    experience=os.path.join(os.path.dirname(isaacsim.__file__), "apps/isaacsim.exp.full.kit") if use_full_exp_file else None,
)

import torch
import omni
from pxr import Usd, UsdGeom, Gf, UsdPhysics, Sdf, UsdLux, PhysxSchema
from isaacsim.core.simulation_manager import SimulationManager
from isaacsim.core.api import SimulationContext
from isaacsim.core.api.objects.ground_plane import GroundPlane
from isaacsim.core.utils.viewports import set_camera_view


FRAME_RATE = 60
RENDER_DECIMATION = 1

def create_cube(prim_path: str, kinematic: bool, center: list[float], size: list[float]):
    stage = omni.usd.get_context().get_stage()

    distantLight = UsdLux.DistantLight.Define(stage, Sdf.Path("/Light"))
    distantLight.CreateIntensityAttr(3000)

    xform = UsdGeom.Cube.Define(stage, prim_path)
    xform.CreateSizeAttr().Set(1.0)

    xform.AddTranslateOp(UsdGeom.XformOp.PrecisionDouble).Set(Gf.Vec3d(center[0], center[1], center[2]))
    xform.AddOrientOp(UsdGeom.XformOp.PrecisionDouble).Set(Gf.Quatd(1.0, 0.0, 0.0, 0.0))
    xform.AddScaleOp(UsdGeom.XformOp.PrecisionDouble).Set(Gf.Vec3d(size[0], size[1], size[2]))

    collision_api = UsdPhysics.CollisionAPI.Apply(xform.GetPrim())
    rigid_body_api = UsdPhysics.RigidBodyAPI.Apply(xform.GetPrim())

    if kinematic:
        rigid_body_api.CreateKinematicEnabledAttr().Set(True)


def init_physics():
    SimulationManager.initialize_physics()
    physics_sim_view = SimulationManager.get_physics_sim_view()
    physx_view = physics_sim_view.create_rigid_body_view(["/World/Box1", "/World/Box2"])
    
    return physx_view

def main():
    sim = SimulationContext(
        physics_dt=1 / FRAME_RATE, 
        rendering_dt=1 / FRAME_RATE, 
        backend='torch', 
        device='cuda:0',
    )
    GroundPlane(prim_path="/World/GroundPlane", z_position=0, size=10.0)
    create_cube(
        prim_path="/World/Box1", 
        kinematic=True, 
        center=[0, 1, 2], 
        size=[1, 1, 1],
    )
    create_cube(
        prim_path="/World/Box2", 
        kinematic=False, 
        center=[0, 1, 5], 
        size=[1, 1, 1],
    )
    physx_view = init_physics()
    
    set_camera_view(
        eye=[12.0, 0.0, 3], 
        target=[0.0, 0.0, 2.0], 
        camera_prim_path="/OmniverseKit_Persp"
    ) 

    sim.reset()

    # Define simulation stepping
    frame = 0
    # Simulate physics
    while simulation_app.is_running():
        # perform step
        sim.step()

        frame += 1
        if frame % 100 == 0:
            print(f"Stepped {frame} frames")

        if frame % 300 == 0:
            tf = physx_view.get_transforms()
            print(f"Transforms at frame {frame}: {tf}")
            tf[0, 0] = 0.0
            tf[0, 1] = 1.0
            tf[0, 2] = 2.0

            tf[1, 0] = 0.0
            tf[1, 1] = 1.0
            tf[1, 2] = 5.0
            physx_view.set_transforms(tf, indices=torch.arange(len(tf), device='cuda:0'))

        if frame % 300 == 150:
            tf = physx_view.get_transforms()
            print(f"Transforms at frame {frame}: {tf}")
            tf[0, 0] = 0.0
            tf[0, 1] = -1.0
            tf[0, 2] = 2.0

            tf[1, 0] = 0.0
            tf[1, 1] = -1.0
            tf[1, 2] = 5.0
            physx_view.set_transforms(tf, indices=torch.arange(len(tf), device='cuda:0'))


if __name__ == "__main__":
    main()
    simulation_app.close()

Steps to Reproduce

Run the above code in Isaac Sim 5.0 conda environment.

Screenshots or Videos

Thanks for reporting this. The issue only happens when SimulationContext is using GPU as the backend. I will follow up with our Isaac Sim team to resolve it.

This is fixed in Isaac Sim 5.1 release, please let us know if you still have this issue with 5.1.