Isaac Sim Version
5.0.0
Operating System
Ubuntu 22.04
GPU Information
- Model: RTX 3090
Topic Description
Detailed Description
I’m using Isaac Sim to do reinforment learning. Normally we will create parallel env(room) to let multiple robot to play in. And when a robot finishes a game, the room is reset, for example, obstacles be randomized and robot reset to initial random pose.
One thing I found now working is that, I cannot create such object that fulfills all the following request:
- The physX works in GPU mode, not CPU mode. The simulation speed is crucial for RL
- The object is represented by a triangle mesh, not convex shapes. It serves as a static collider, such as static obstacles.
- The object can be transformed to another location using python code. Calling some omni/isaac/physx API to modify the position and orientation of this object.
I tried different method:
If I use rigid body with kinematic turned on, then we know the rigid body do not accept arbitrary triangle mesh as collider, falling back to convex hull, which is not good for me
If I use non-rigid-body static collider, which supports triangle mesh, then once the GPU physX is initialized (the triangle mesh is baked as AABB tree during this init I think), and cannot be transformed to new places during simulation. There is no such entry in the pytorch tensor physX API.
I wonder is there an option to let the GPU physX pipeline rebuild all static mesh ? Reading vertices and faces from the USD scene tree and build again the AABB tree ?
I have a piece of code here to represent what I want:
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, rigid_body: bool, 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())
if rigid_body:
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/Box2"])
return physx_view
def main():
sim = SimulationContext(
physics_dt=1 / FRAME_RATE,
rendering_dt=1 / FRAME_RATE,
backend='torch',
device='cuda:0',
)
# Get USD stage for direct manipulation
stage = omni.usd.get_context().get_stage()
GroundPlane(prim_path="/World/GroundPlane", z_position=0, size=10.0)
create_cube(
prim_path="/World/Box1",
rigid_body=False,
kinematic=False,
center=[0, 1, 2],
size=[1, 1, 1],
)
create_cube(
prim_path="/World/Box2",
rigid_body=True,
kinematic=False,
center=[0, 1, 5],
size=[1, 1, 1],
)
physx_view = init_physics()
physics_sim_view = SimulationManager.get_physics_sim_view()
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:
# Move Box1 (static collider) via USD API
box1_prim = stage.GetPrimAtPath("/World/Box1")
xformable = UsdGeom.Xformable(box1_prim)
translate_op = xformable.GetOrderedXformOps()[0]
translate_op.Set(Gf.Vec3d(0.0, 1.0, 2.0))
# Move Box2 (dynamic rigid body) via PhysX view
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] = 5.0
physx_view.set_transforms(tf, indices=torch.arange(len(tf), device='cuda:0'))
assert physics_sim_view.check()
if frame % 300 == 150:
# Move Box1 (static collider) via USD API
box1_prim = stage.GetPrimAtPath("/World/Box1")
xformable = UsdGeom.Xformable(box1_prim)
translate_op = xformable.GetOrderedXformOps()[0]
translate_op.Set(Gf.Vec3d(0.0, -1.0, 2.0))
# Move Box2 (dynamic rigid body) via PhysX view
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] = 5.0
physx_view.set_transforms(tf, indices=torch.arange(len(tf), device='cuda:0'))
if __name__ == "__main__":
main()
simulation_app.close()
Screenshots or Videos
The video of the above code. I want to update the pose of the static collider, of course currently the GPU physX pipeline will not update the static triangle mesh collider at each frame. But if there is at least an option to trigger the rebuild manually ?