Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Fixed PhysX startup error logs in static-only scenes by avoiding empty scene-data rigid-body view requests.
37 changes: 20 additions & 17 deletions source/isaaclab_physx/isaaclab_physx/physics/physx_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import omni.timeline
import omni.usd
import usdrt
from pxr import Sdf, UsdGeom, UsdPhysics, UsdUtils
from pxr import Sdf, Usd, UsdGeom, UsdPhysics, UsdUtils

import isaaclab.sim as sim_utils
from isaaclab.physics import CallbackHandle, PhysicsEvent, PhysicsManager
Expand Down Expand Up @@ -1025,22 +1025,25 @@ def _warmup_and_create_views(cls) -> None:
# Register the complete tensor view only after PhysX has loaded the stage.
cls.backend = sim.get_or_create_backend(PhysxBackendCfg(stage_id=stage_id))
cls._scene_data_backend.backend = cls.backend
view = cls.backend.simulation_view.create_rigid_body_view("/**")
# PhysX returns a wrapper with no native handle for an empty selection.
cls._scene_data_backend._rigid_body_view = view if view._backend is not None else None
if view._backend is not None:
# Wildcard bindings expose articulation aliases; publish the actual root-link paths.
native = cls.backend.simulation_view
paths = view.prim_paths
articulation_type = omni.physics.tensors.ObjectType.Articulation
roots = [path for path in paths if native.get_object_type(path) == articulation_type]
if roots:
articulations = native.create_articulation_view(roots)
links = (body_paths[0] for body_paths in articulations.link_paths)
aliases = dict(zip(articulations.prim_paths, links, strict=True))
cls._scene_data_backend._rigid_body_view = native.create_rigid_body_view(
[aliases.get(path, path) for path in paths]
)
# omni.physics.tensors logs errors for an empty selection, so static scenes skip the request.
prims = Usd.PrimRange.Stage(sim.stage, Usd.TraverseInstanceProxies())
if any(prim.HasAPI(UsdPhysics.RigidBodyAPI) for prim in prims):
view = cls.backend.simulation_view.create_rigid_body_view("/**")
# PhysX returns a wrapper with no native handle for an empty selection.
cls._scene_data_backend._rigid_body_view = view if view._backend is not None else None
if view._backend is not None:
# Wildcard bindings expose articulation aliases; publish the actual root-link paths.
native = cls.backend.simulation_view
paths = view.prim_paths
articulation_type = omni.physics.tensors.ObjectType.Articulation
roots = [path for path in paths if native.get_object_type(path) == articulation_type]
if roots:
articulations = native.create_articulation_view(roots)
links = (body_paths[0] for body_paths in articulations.link_paths)
aliases = dict(zip(articulations.prim_paths, links, strict=True))
cls._scene_data_backend._rigid_body_view = native.create_rigid_body_view(
[aliases.get(path, path) for path in paths]
)

# Final update after view creation
physx.update_simulation(cls.get_physics_dt(), 0.0)
Expand Down
28 changes: 28 additions & 0 deletions source/isaaclab_physx/test/sim/test_simulation_context_kit.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,34 @@ def test_setup_teardown():
SimulationContext.clear_instance()


@pytest.mark.isaacsim_ci
def test_reset_without_rigid_bodies_skips_rigid_body_view(monkeypatch):
"""Resetting a static scene must not request an empty native rigid-body view."""
create_simulation_view = omni.physics.tensors.create_simulation_view
requested_patterns = []

class _SimulationViewGuard:
def __init__(self, *args, **kwargs):
self._view = create_simulation_view(*args, **kwargs)

def __getattr__(self, name):
return getattr(self._view, name)

def create_rigid_body_view(self, pattern):
requested_patterns.append(pattern)
return self._view.create_rigid_body_view(pattern)

monkeypatch.setattr(omni.physics.tensors, "create_simulation_view", _SimulationViewGuard)
sim = SimulationContext()
cube_cfg = sim_utils.CuboidCfg(size=(0.1, 0.1, 0.1), collision_props=sim_utils.UsdPhysicsCollisionCfg())
cube_cfg.func("/World/Cube", cube_cfg)

sim.reset()

assert requested_patterns == []
assert sim.physics_manager.get_scene_data_backend().get_rigid_body_view() is None


@pytest.mark.isaacsim_ci
def test_timeline_play_stop(monkeypatch):
"""Playing shares one native view; stopping releases it before the next play."""
Expand Down
Loading