diff --git a/source/isaaclab_ovphysx/changelog.d/antoiner-feat-ovphysx_frameview_scenedata.skip b/source/isaaclab_ovphysx/changelog.d/antoiner-feat-ovphysx_frameview_scenedata.skip new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/source/isaaclab_ovphysx/isaaclab_ovphysx/physics/ovphysx_manager.py b/source/isaaclab_ovphysx/isaaclab_ovphysx/physics/ovphysx_manager.py index 01803d51a769..f21eeb094363 100644 --- a/source/isaaclab_ovphysx/isaaclab_ovphysx/physics/ovphysx_manager.py +++ b/source/isaaclab_ovphysx/isaaclab_ovphysx/physics/ovphysx_manager.py @@ -98,6 +98,7 @@ def setup(self, physx, stage, device: str) -> None: device: Warp device string used to allocate the staging and merged buffers. """ from isaaclab_ovphysx import tensor_types as TT # local: keep heavy ovphysx out of module load + from isaaclab_ovphysx.sim.views.ovphysx_view import OvPhysxView self._physx = physx self._rigid_bindings = [] @@ -119,7 +120,8 @@ def setup(self, physx, stage, device: str) -> None: total_count = 0 for pattern in sorted(patterns): try: - pose_binding = physx.create_tensor_binding(pattern=pattern, tensor_type=TT.RIGID_BODY_POSE) + view = OvPhysxView(physx, pattern=pattern, device=device) + pose_binding = view.binding_for(TT.RIGID_BODY_POSE) except Exception as exc: logger.warning("Failed to create RIGID_BODY_POSE binding for %s: %s", pattern, exc) continue @@ -141,6 +143,7 @@ def setup(self, physx, stage, device: str) -> None: self._rigid_bindings.append( { "pattern": pattern, + "view": view, "pose": pose_binding, "pose_buf": pose_buf, "pose_buf_transformf": pose_buf_transformf, @@ -175,7 +178,7 @@ def transforms(self) -> SceneDataFormat.Transform: for entry in self._rigid_bindings: try: - entry["pose"].read(entry["pose_buf"]) + entry["view"].read_into("rigid_body_pose", entry["pose_buf"]) except Exception as exc: logger.warning("RIGID_BODY_POSE read failed for %s: %s", entry["pattern"], exc) continue diff --git a/source/isaaclab_ovphysx/isaaclab_ovphysx/sim/views/ovphysx_frame_view.py b/source/isaaclab_ovphysx/isaaclab_ovphysx/sim/views/ovphysx_frame_view.py index 879ecddf385f..5965662d4209 100644 --- a/source/isaaclab_ovphysx/isaaclab_ovphysx/sim/views/ovphysx_frame_view.py +++ b/source/isaaclab_ovphysx/isaaclab_ovphysx/sim/views/ovphysx_frame_view.py @@ -357,6 +357,7 @@ def _initialize_impl(self, physx: Any) -> None: ``env_0`` replaced by the row's env_id. """ from isaaclab_ovphysx import tensor_types as TT # noqa: PLC0415 + from isaaclab_ovphysx.sim.views.ovphysx_view import OvPhysxView # noqa: PLC0415 xform_cache = UsdGeom.XformCache(Usd.TimeCode.Default()) identity_xform7 = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0] @@ -406,8 +407,11 @@ def _initialize_impl(self, physx: Any) -> None: # 4. Create the RIGID_BODY_POSE binding (or operate in world-only mode). if patterns: pattern = patterns[0] - self._pose_binding = physx.create_tensor_binding(pattern=pattern, tensor_type=TT.RIGID_BODY_POSE) - if self._pose_binding.shape[0] == 0: + self._root_view = OvPhysxView(physx, pattern=pattern, device=self._device) + # ``try_binding_for`` returns None for a zero-match binding (the view rejects a + # 0-count binding); surface that as the explicit zero-bodies error below. + self._pose_binding = self._root_view.try_binding_for(TT.RIGID_BODY_POSE) + if self._pose_binding is None: raise RuntimeError( f"OvPhysxFrameView: RIGID_BODY_POSE binding for pattern {pattern!r} matched zero bodies." ) @@ -415,6 +419,7 @@ def _initialize_impl(self, physx: Any) -> None: binding_paths: list[str] = list(self._pose_binding.prim_paths) else: # All prims resolved as world-attached: no binding needed; kernels only hit the -1 branch. + self._root_view = None self._pose_binding = None self._pose_buf = wp.zeros((1, 7), dtype=wp.float32, device=self._device) binding_paths = [] @@ -613,7 +618,7 @@ def _current_body_q(self) -> wp.array: buffer ``[num_bodies]``. """ if self._pose_binding is not None: - self._pose_binding.read(self._pose_buf) + self._root_view.read_into("rigid_body_pose", self._pose_buf) return self._pose_buf.view(wp.transformf) # ------------------------------------------------------------------ diff --git a/source/isaaclab_ovphysx/test/physics/test_ovphysx_scene_data_backend.py b/source/isaaclab_ovphysx/test/physics/test_ovphysx_scene_data_backend.py index 37487b5dd85e..d57efdddfdd1 100644 --- a/source/isaaclab_ovphysx/test/physics/test_ovphysx_scene_data_backend.py +++ b/source/isaaclab_ovphysx/test/physics/test_ovphysx_scene_data_backend.py @@ -186,6 +186,7 @@ def fake_read_b(dst): { "pattern": "/World/envs/env_*/Cube", "pose": SimpleNamespace(read=fake_read_a, prim_paths=["/Cube0", "/Cube1"]), + "view": SimpleNamespace(read_into=lambda name, dst, _r=fake_read_a: _r(dst)), "pose_buf": buf_a, "pose_buf_transformf": buf_a_tf, "row_offset": 0, @@ -194,6 +195,7 @@ def fake_read_b(dst): { "pattern": "/World/envs/env_*/Pole", "pose": SimpleNamespace(read=fake_read_b, prim_paths=["/Pole"]), + "view": SimpleNamespace(read_into=lambda name, dst, _r=fake_read_b: _r(dst)), "pose_buf": buf_b, "pose_buf_transformf": buf_b_tf, "row_offset": 2, @@ -324,6 +326,7 @@ def bad_read(dst): { "pattern": "/World/envs/env_*/Good", "pose": SimpleNamespace(read=good_read, prim_paths=["/Good"]), + "view": SimpleNamespace(read_into=lambda name, dst, _r=good_read: _r(dst)), "pose_buf": buf_good, "pose_buf_transformf": buf_good_tf, "row_offset": 0, @@ -332,6 +335,7 @@ def bad_read(dst): { "pattern": "/World/envs/env_*/Bad", "pose": SimpleNamespace(read=bad_read, prim_paths=["/Bad"]), + "view": SimpleNamespace(read_into=lambda name, dst, _r=bad_read: _r(dst)), "pose_buf": buf_bad, "pose_buf_transformf": buf_bad_tf, "row_offset": 1,