How to get the updated pose from isaacsim USD stage using curobo?

Important: Isaac Sim support

Note: For Isaac Sim support, the community is gradually transitioning from this forum to the Isaac Sim GitHub repository so that questions and issues can be tracked, searched, and resolved more efficiently in one place. Whenever possible, please create a GitHub Discussion or Issue there instead of starting a new forum topic.

Note: For any Isaac Lab topics, please submit your topic to its GitHub repo ( GitHub - isaac-sim/IsaacLab: Unified framework for robot learning built on NVIDIA Isaac Sim ) following the instructions provided on Isaac Lab’s Contributing Guidelines ( Contribution Guidelines — Isaac Lab Documentation ).

Please provide all relevant details below before submitting your post. This will help the community provide more accurate and timely assistance. After submitting, you can check the appropriate boxes. Remember, you can always edit your post later to include additional information if needed.

6.0.0
5.1.0
5.0.0
4.5.0
4.2.0
4.1.0
4.0.0
4.5.0
2023.1.1
2023.1.0-hotfix.1
Other (please specify):

Operating System

Ubuntu 24.04
Ubuntu 22.04
Ubuntu 20.04
Windows 11
Windows 10
Other (please specify):

GPU Information

  • Model: NVIDIA GeForce RTX 3090 Ti
  • Driver Version: 535.183.01

Topic Description

Detailed Description

I’m trying to use Curobo as my motion planner to avoid obstacles along with isaac sim simulator.
I’m planning to use multiple environemnts so I built everything in batch with num_envs, where for Curobo, I only planned single environment at once and right now I only have one environment.

I did not have the world config file (eg. world.yml) but build and read everything from the simulator.
After I move the object using the arm, the pose is updated in the sim but not updated after I called get_obstacles_from_stage().get_collision_check_world() and motion_gen.update_world(obstacles)

Initialized Isaac Sim:

Steps to Reproduce

Initialized Isaac Sim:

device = 'cuda'
backend = 'torch'
world = World(stage_units_in_meters=1.0, device=device, backend=backend, physics_dt=1/240, rendering_dt=1/60)
world.get_physics_context().enable_gpu_dynamics(True)
world.get_physics_context().set_broadphase_type("GPU")
world.scene.add_default_ground_plane()

cube_path = f"{base_env_path}/cube"
cube = DynamicCuboid(
    prim_path=cube_path,
    scale=torch.tensor([0.06, 0.06, 0.06]).to(device),
    position=torch.tensor([0.6, 0.43, 0.63]).to(device),
    color=torch.tensor([1.0, 0.0, 0.0]).to(device), 
    physics_material=cube_material,
)
cloner.clone(
    source_prim_path=base_env_path, 
    prim_paths=target_paths,
    copy_from_source=True,
)
cubes = RigidPrim(prim_paths_expr="/World/envs/env.*/cube", name="cube_view")
world.scene.add(cubes)

# same for the robot ...

Initialize Curobo:

tensor_args = TensorDeviceType()
usd_helper.load_stage(world.stage)
world_cfg = usd_helper.get_obstacles_from_stage(
    reference_prim_path="/World",
    ignore_substring=
    [
        f"{base_env_path}/robot",
        "/World/defaultGroundPlane",
    ]
)
robot_cfg_path = get_robot_configs_path()
robot_cfg = load_yaml(join_path(robot_cfg_path, "bimanual_robotiq_flat.yml"))['robot_cfg']
robot_cfg["kinematics"]["extra_collision_spheres"] = {"attached_object": 10}

tensor_args = TensorDeviceType()

motion_gen_config = MotionGenConfig.load_from_robot_config(
    robot_cfg,
    world_cfg,
    tensor_args=tensor_args,
    collision_checker_type=CollisionCheckerType.MESH,
    num_trajopt_seeds=64,      
    num_graph_seeds=64,   
    optimize_dt=False,       
    interpolation_dt=0.15,   
    trajopt_tsteps=32,      
    maximum_trajectory_dt=0.3,
    collision_cache={"obb": 10, "mesh": 10},
)

motion_gen = MotionGen(motion_gen_config)
print("[INFO] warming up...")
motion_gen.warmup(enable_graph=True)

plan_config = MotionGenPlanConfig(
    enable_graph=True,        
    enable_graph_attempt=10,   
    max_attempts=50,         
    enable_finetune_trajopt=False,
    time_dilation_factor=0.8,
)

obstacles = world_cfg.get_collision_check_world()
motion_gen.update_world(obstacles)
print("[INFO] CuRobo MotionGen is ready.")

Main Loop:

while simulation_app.is_running():

    plan_and_execute(robots, cubes, curobo, ...)
    world.step()

    obstacles = usd_helper.get_obstacles_from_stage(
        reference_prim_path="/World",
        ignore_substring=
        [
            f"{base_env_path}/robot",
            "/World/defaultGroundPlane",
        ]
    ).get_collision_check_world()

    motion_gen.update_world(obstacles)
    print("[INFO] Updated World!\n")

    cube_pos, _ = cubes.get_world_poses()
    print(f"[INFO] Cube position: {cube_pos}")
    print(obstacles.objects)  

Error Messages

The cube is being moved after the action and updated inside the sim, but when I printed the obstacles’ pose, it is still the initial pose and the robot will have collision with the cube in the new pose as Curobo thought there’s no object.

[INFO]: Setup complete...

[INFO] Picking...
[INFO] Cube position: tensor([[0.6001, 0.4299, 0.6300]], device='cuda:0')
[INFO]:  Cuboid(name='/World/envs/env_0/cube', pose=[0.6000000238418579, 0.4300000071525574, 0.6299999952316284, 1.0, 0.0, 0.0, 0.0], scale=None, color=None, texture_id=None, texture=None, material=Material(metallic=0.0, roughness=0.4), tensor_args=TensorDeviceType(device=device(type='cuda', index=0), dtype=torch.float32, collision_geometry_dtype=torch.float32, collision_gradient_dtype=torch.float32, collision_distance_dtype=torch.float32), dims=[0.05999999865889549, 0.05999999865889549, 0.05999999865889549])

[INFO] Moving...
[INFO] Cube position: tensor([[0.5992, 0.4281, 0.7742]], device='cuda:0')
[INFO]:  Cuboid(name='/World/envs/env_0/cube', pose=[0.6000000238418579, 0.4300000071525574, 0.6299999952316284, 1.0, 0.0, 0.0, 0.0], scale=None, color=None, texture_id=None, texture=None, material=Material(metallic=0.0, roughness=0.4), tensor_args=TensorDeviceType(device=device(type='cuda', index=0), dtype=torch.float32, collision_geometry_dtype=torch.float32, collision_gradient_dtype=torch.float32, collision_distance_dtype=torch.float32), dims=[0.05999999865889549, 0.05999999865889549, 0.05999999865889549])

[INFO] Dropping...
[INFO] Cube position: tensor([[0.6252, 0.0343, 0.6408]], device='cuda:0')
[INFO]:  Cuboid(name='/World/envs/env_0/cube', pose=[0.6000000238418579, 0.4300000071525574, 0.6299999952316284, 1.0, 0.0, 0.0, 0.0], scale=None, color=None, texture_id=None, texture=None, material=Material(metallic=0.0, roughness=0.4), tensor_args=TensorDeviceType(device=device(type='cuda', index=0), dtype=torch.float32, collision_geometry_dtype=torch.float32, collision_gradient_dtype=torch.float32, collision_distance_dtype=torch.float32), dims=[0.05999999865889549, 0.05999999865889549, 0.05999999865889549])

Additional Information

Additional Context

I’m not sure if this is a bug in my code regarding how to set up the scene correctly, or a communication issue with Curobo reading the USD stage.

I just found that if I switch the simulator from GPU to cpu then everything worked, which I still don’t understand why and wonder how to solve this issue since I want to do large-scale data collection.

device = 'cpu'
backend = 'numpy'
world = World(stage_units_in_meters=1.0, device=device, backend=backend, physics_dt=1/240, rendering_dt=1/60)

@lyx010318 the latest curobot supports Isaac sim 4.5.

You probably want to downgrade to this version.

You can refer to this example for motion generation with obstacle avoidance: Using with Isaac Sim - cuRobo

I downgraded to 4.5, but still not working.

Apparently, the example you refer to is using cpu as the backend of the Isaac Sim, and I have already checked before posting this issue.

I’d like to know an actual solution to this issue.

@lyx010318 Could you please share the complete files and detailed steps for us to replicate this issue? Thanks!

test.zip (2.0 MB)

Hi, @zhengwang

The code is not the simplest version, but it should give you the idea of what I’m saying.

By default, it’s running on cpu, and everything works fine.

python bimanual_test.py --sim_device cuda If you run it using this command, which switches to GPU, then from the output you can see that after the robot lifts the box,

The sim updated the pose

cube_pos, _ = cubes.get_world_poses()
print(f"[INFO] Cube position: {cube_pos}")

but curobo does not

check_obstacle()

if len(obstacles.objects) > 1:
        print("[INFO]: ", obstacles.objects[1])

Result

[INFO]:  Cuboid(name='/World/envs/env_0/cube', pose=[0.6000000238418579, 0.4300000071525574, 0.6299999952316284, 1.0, 0.0, 0.0, 0.0],
[INFO] Cube position: tensor([[0.5990, 0.4280, 0.7738]], device='cuda:0')

@lyx010318 Thanks! I think you are missing the bimanual_robotiq_flat.yml file. Could you please share that with me as well?

Oh sorry, let me know what else you need!

curobo_configs.zip (2.7 MB)

@lyx010318 thanks for your config files. I am able to replicate this issue. I do observe that in GPU mode, the object pose is not updating. And this issue is not observed in CPU mode.

The issue seems to be the synchronization between the USD stage and GPU backend. update_stage() may not sync GPU state to USD reliably. When you get the cube position inside the function check_obstacle(), it is still reading the old position from the USD stage.

So I tried manually to update USD prims for each cube from GPU backend before calling update_stage()- it is a clumsy fix though. But it works. Please check out the attached file.

Let me also reach out to the internal team to see if there is a better way to handle this.

bimanual_test.py (19.5 KB)

@zhengwang Thanks! I tried your code, and it seems working.

But I kept receiving this

[WARN] Failed to update USD prim for cube at /World/envs/env_0/cube:
Error in ‘pxrInternal_v0_24__pxrReserved__::UsdGeomXformable::AddXformOp’ at line 203 in file /builds/omniverse/usd-ci/USD/pxr/usd/usdGeom/xformable.cpp : ‘XformOp </World/envs/env_0/cube.xformOp:scale> has typeName ‘double3’ which does not match the requested precision ‘PrecisionFloat’. Proceeding to use existing typeName / precision.’`

Also in that case, do I have to manually update all the objects in the scene?

Yes, for any dynamic object whose pose cuRobo needs to be aware of.

As for the warning, you can fix it by matching the precision. Use double-precision types to match what Isaac Sim already put on the prim. Take line 253 for example.

  scale_op = xform.AddScaleOp()                                                                           

Change to:

  scale_op = xform.AddScaleOp(precision=UsdGe om.XformOp.PrecisionDouble)                                 

You can make similar changes throughout the script.