Skip to content

Commit 43b2211

Browse files
Address PR isaac-sim#5426 review feedback
* Untrack docs/superpowers/specs/2026-04-27-ovphysx-rigid-body-tensortypes-gap.md (file is gitignored under docs/superpowers/; keep locally only). * Revert the ovphysx variant additions to allegro_hand_env_cfg.py (ObjectCfg.ovphysx, PhysicsCfg.ovphysx, OvPhysxCfg import) and the matching isaaclab_tasks 1.5.30 CHANGELOG entry / version bump. * Trim test_rigid_object.py module docstring: drop the PhysX-mirror prose and the PhysX adaptation walk-through (both inferable from the file contents); drop the gap-G5 / superpowers spec reference. * Tighten the _ovphysx_skip_other_device fixture docstring; the module docstring now carries the device-lock rationale. * Move test_mock_binding_set_rigid_object_shapes from test_articulation_helpers.py to a parallel test_rigid_object_helpers.py so the rigid-object mock-binding contract test sits next to the rest of the rigid-object scaffolding. * Convert the new "Rigid-body TensorTypes" section header in tensor_types.py to the triple-quoted-string style used elsewhere in the file.
1 parent 8ef6471 commit 43b2211

8 files changed

Lines changed: 66 additions & 235 deletions

File tree

docs/superpowers/specs/2026-04-27-ovphysx-rigid-body-tensortypes-gap.md

Lines changed: 0 additions & 124 deletions
This file was deleted.

source/isaaclab_ovphysx/isaaclab_ovphysx/tensor_types.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,12 @@
191191
Shape is ``[N, L, 9]``, dtype ``float32``.
192192
"""
193193

194-
# ---------------------------------------------------------------------------
195-
# Rigid-body TensorTypes
196-
# ---------------------------------------------------------------------------
197-
# Shapes assume N = number of rigid actor instances matched by the binding
198-
# pattern. Components and units are stated per alias below.
194+
"""
195+
Rigid-body TensorTypes
196+
197+
Shapes assume N = number of rigid actor instances matched by the binding
198+
pattern. Components and units are stated per alias below.
199+
"""
199200

200201
RIGID_BODY_POSE = _TT.RIGID_BODY_POSE
201202
"""Rigid actor root transform — read/write, GPU. Shape ``(N, 7)``,

source/isaaclab_ovphysx/test/assets/test_articulation_helpers.py

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66
"""OVPhysX-only unit tests for articulation helpers.
77
8-
These tests cover OVPhysX-specific scaffolding (USD tendon-scope resolution,
9-
mock binding-set shape contracts) that has no PhysX equivalent and therefore
10-
does not appear in the PhysX-mirrored ``test_articulation.py``.
8+
These tests cover OVPhysX-specific scaffolding (USD tendon-scope resolution)
9+
that has no PhysX equivalent and therefore does not appear in the
10+
PhysX-mirrored ``test_articulation.py``.
1111
"""
1212

1313
from __future__ import annotations
@@ -119,24 +119,3 @@ def test_process_tendons_scopes_to_articulation_root(tmp_path):
119119
assert articulation.spatial_tendon_names == ["spatial_joint"]
120120
assert articulation._data.fixed_tendon_names == ["fixed_joint"]
121121
assert articulation._data.spatial_tendon_names == ["spatial_joint"]
122-
123-
124-
def test_mock_binding_set_rigid_object_shapes():
125-
pytest.importorskip("isaaclab_ovphysx.tensor_types").RIGID_BODY_POSE # gates on wheel
126-
from isaaclab_ovphysx import tensor_types as TT
127-
from isaaclab_ovphysx.test.mock_interfaces.views import MockOvPhysxBindingSet
128-
129-
bindings = MockOvPhysxBindingSet(
130-
num_instances=4,
131-
num_joints=0,
132-
num_bodies=1,
133-
asset_kind="rigid_object",
134-
)
135-
assert bindings.bindings[TT.RIGID_BODY_POSE].shape == (4, 7)
136-
assert bindings.bindings[TT.RIGID_BODY_VELOCITY].shape == (4, 6)
137-
assert bindings.bindings[TT.RIGID_BODY_WRENCH].shape == (4, 9)
138-
assert bindings.bindings[TT.RIGID_BODY_MASS].shape == (4,)
139-
assert bindings.bindings[TT.RIGID_BODY_INERTIA].shape == (4, 9)
140-
# Articulation-only bindings must be absent
141-
assert TT.DOF_POSITION not in bindings.bindings
142-
assert TT.LINK_WRENCH not in bindings.bindings

source/isaaclab_ovphysx/test/assets/test_rigid_object.py

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,15 @@
99

1010
"""Real-backend tests for the OVPhysX RigidObject.
1111
12-
Mirrors :mod:`isaaclab_physx.test.assets.test_rigid_object` 1-to-1: same set
13-
of test functions, names, parametrizations, and assertions.
14-
15-
OVPhysX runs kitless under ``./scripts/run_ovphysx.sh`` so there is no
16-
``AppLauncher`` boot — :class:`~isaaclab.sim.SimulationContext` is driven
17-
directly via ``build_simulation_context(sim_cfg=SimulationCfg(physics=OvPhysxCfg(), ...))``
18-
which works because :func:`isaaclab.app.has_kit` returns False in this
19-
environment.
20-
21-
PhysX-specific ``cube_object.root_view.set_X(...)`` / ``get_X(...)`` calls are
22-
adapted to OVPhysX by going through the backend's per-tensor-type binding
23-
dictionary (``cube_object._bindings`` / :meth:`~isaaclab_ovphysx.assets.RigidObject._get_binding`)
24-
and the public setters (:meth:`set_masses_index`, :meth:`set_coms_index`,
25-
:meth:`set_inertias_index`). Reads use the data-class properties
26-
(``cube_object.data.body_mass``, ``body_inertia``, ``body_com_pose_b``).
27-
28-
Process-global device lock
29-
--------------------------
12+
Run via ``./scripts/run_ovphysx.sh -m pytest`` (kitless, no ``AppLauncher``).
3013
3114
``ovphysx<=0.3.7`` binds device mode (CPU vs GPU) at the C++ layer on the
32-
first ``ovphysx.PhysX(device=...)`` call and cannot release/swap it without a
33-
process restart. :class:`~isaaclab_ovphysx.physics.OvPhysxManager` tracks
34-
this on ``_locked_device`` and raises :exc:`RuntimeError` if a later
35-
:class:`SimulationContext` requests a different device. The
36-
``_ovphysx_skip_other_device`` autouse fixture below preempts that error in
37-
parametrized tests by ``pytest.skip``-ing on the unlocked device, so the
38-
session finishes cleanly when only one device is exercised.
39-
40-
CI note
41-
-------
42-
Because the lock is process-global, full coverage requires **two separate
43-
``./scripts/run_ovphysx.sh -m pytest`` invocations** -- once with ``-k 'cpu'``
44-
and once with ``-k 'cuda:0'``. Tracked as gap G5 in
45-
``docs/superpowers/specs/2026-04-28-ovphysx-wheel-gaps-for-marco.md``; until
46-
the wheel exposes a way to reset Carbonite device state, this is the supported
47-
pattern.
15+
first ``ovphysx.PhysX(device=...)`` construction and cannot swap it without a
16+
process restart. Full coverage therefore requires two separate pytest
17+
invocations -- once with ``-k 'cpu'`` and once with ``-k 'cuda:0'``. The
18+
``_ovphysx_skip_other_device`` autouse fixture below preempts the manager's
19+
:exc:`RuntimeError` by ``pytest.skip``-ing on the unlocked device so
20+
single-device runs finish cleanly.
4821
"""
4922

5023
from __future__ import annotations
@@ -80,23 +53,15 @@
8053
_logger = logging.getLogger(__name__)
8154

8255

83-
# Session-locked device. Set on the first parametrized test that runs and
84-
# never reassigned -- ovphysx's process-global device lock means subsequent
85-
# tests on the other device must skip.
8656
_LOCKED_DEVICE: list[str | None] = [None]
57+
"""Device the session pins to on the first parametrized test that runs."""
8758

8859

8960
@pytest.fixture(autouse=True)
9061
def _ovphysx_skip_other_device(request):
91-
"""Skip tests whose ``device`` parameter mismatches the session-locked device.
92-
93-
``ovphysx<=0.3.7`` binds the process-global device mode on the first
94-
``ovphysx.PhysX(device=...)`` call.
95-
:class:`~isaaclab_ovphysx.physics.OvPhysxManager._warmup_and_load` raises
96-
:exc:`RuntimeError` if a later context requests a different device. We
97-
detect the locked device on the first encounter and skip subsequent tests
98-
on the other device with a clear message, so the run finishes cleanly
99-
rather than failing on the second-device test.
62+
"""Skip parametrized tests on the device the session is not pinned to.
63+
64+
See the module docstring for the wheel's process-global device-mode lock.
10065
"""
10166
callspec = getattr(request.node, "callspec", None)
10267
device = callspec.params.get("device") if callspec is not None else None
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
2+
# All rights reserved.
3+
#
4+
# SPDX-License-Identifier: BSD-3-Clause
5+
6+
"""OVPhysX-only unit tests for rigid-object helpers.
7+
8+
These tests cover OVPhysX-specific scaffolding (mock binding-set shape
9+
contracts for ``asset_kind="rigid_object"``) that has no PhysX equivalent
10+
and therefore does not appear in the PhysX-mirrored ``test_rigid_object.py``.
11+
"""
12+
13+
from __future__ import annotations
14+
15+
import pytest
16+
import warp as wp
17+
18+
# The CI isaaclab_ov* pattern unintentionally collects isaaclab_ovphysx tests,
19+
# but the ovphysx wheel is not installed in that environment. Skip gracefully
20+
# so the isaaclab_ov CI pipeline is not blocked by an unrelated dependency.
21+
pytest.importorskip("ovphysx.types", reason="ovphysx wheel not installed")
22+
23+
from isaaclab_ovphysx import tensor_types as TT # noqa: E402
24+
from isaaclab_ovphysx.test.mock_interfaces.views import MockOvPhysxBindingSet # noqa: E402
25+
26+
wp.init()
27+
28+
29+
def test_mock_binding_set_rigid_object_shapes():
30+
pytest.importorskip("isaaclab_ovphysx.tensor_types").RIGID_BODY_POSE # gates on wheel
31+
32+
bindings = MockOvPhysxBindingSet(
33+
num_instances=4,
34+
num_joints=0,
35+
num_bodies=1,
36+
asset_kind="rigid_object",
37+
)
38+
assert bindings.bindings[TT.RIGID_BODY_POSE].shape == (4, 7)
39+
assert bindings.bindings[TT.RIGID_BODY_VELOCITY].shape == (4, 6)
40+
assert bindings.bindings[TT.RIGID_BODY_WRENCH].shape == (4, 9)
41+
assert bindings.bindings[TT.RIGID_BODY_MASS].shape == (4,)
42+
assert bindings.bindings[TT.RIGID_BODY_INERTIA].shape == (4, 9)
43+
# Articulation-only bindings must be absent
44+
assert TT.DOF_POSITION not in bindings.bindings
45+
assert TT.LINK_WRENCH not in bindings.bindings

source/isaaclab_tasks/config/extension.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
# Note: Semantic Versioning is used: https://semver.org/
4-
version = "1.5.30"
4+
version = "1.5.29"
55

66
# Description
77
title = "Isaac Lab Environments"

source/isaaclab_tasks/docs/CHANGELOG.rst

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,6 @@
11
Changelog
22
---------
33

4-
1.5.30 (2026-04-27)
5-
~~~~~~~~~~~~~~~~~~~
6-
7-
Changed
8-
^^^^^^^
9-
10-
* Added an ``ovphysx`` preset variant to the in-hand object and physics
11-
configs in
12-
``isaaclab_tasks.direct.allegro_hand.allegro_hand_env_cfg``, mirroring
13-
the existing Cartpole/Ant pattern. Enables running
14-
``Isaac-Repose-Cube-Allegro-Direct-v0`` against the OVPhysX backend via
15-
``./scripts/run_ovphysx.sh``.
16-
17-
184
1.5.29 (2026-04-27)
195
~~~~~~~~~~~~~~~~~~~
206

source/isaaclab_tasks/isaaclab_tasks/direct/allegro_hand/allegro_hand_env_cfg.py

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66

77
from isaaclab_newton.physics import MJWarpSolverCfg, NewtonCfg
8-
from isaaclab_ovphysx.physics import OvPhysxCfg
98
from isaaclab_physx.physics import PhysxCfg
109

1110
import isaaclab.sim as sim_utils
@@ -44,25 +43,6 @@ class ObjectCfg(PresetCfg):
4443
),
4544
init_state=RigidObjectCfg.InitialStateCfg(pos=(0.0, -0.17, 0.56), rot=(0.0, 0.0, 0.0, 1.0)),
4645
)
47-
ovphysx = RigidObjectCfg(
48-
prim_path="/World/envs/env_.*/object",
49-
spawn=sim_utils.UsdFileCfg(
50-
usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/DexCube/dex_cube_instanceable.usd",
51-
rigid_props=sim_utils.RigidBodyPropertiesCfg(
52-
kinematic_enabled=False,
53-
disable_gravity=False,
54-
enable_gyroscopic_forces=True,
55-
solver_position_iteration_count=8,
56-
solver_velocity_iteration_count=0,
57-
sleep_threshold=0.005,
58-
stabilization_threshold=0.0025,
59-
max_depenetration_velocity=1000.0,
60-
),
61-
mass_props=sim_utils.MassPropertiesCfg(density=400.0),
62-
scale=(1.2, 1.2, 1.2),
63-
),
64-
init_state=RigidObjectCfg.InitialStateCfg(pos=(0.0, -0.17, 0.56), rot=(0.0, 0.0, 0.0, 1.0)),
65-
)
6646
newton = ArticulationCfg(
6747
prim_path="/World/envs/env_.*/object",
6848
spawn=sim_utils.UsdFileCfg(
@@ -84,7 +64,6 @@ class PhysicsCfg(PresetCfg):
8464
physx = PhysxCfg(
8565
bounce_threshold_velocity=0.2,
8666
)
87-
ovphysx: OvPhysxCfg = OvPhysxCfg()
8867
newton = NewtonCfg(
8968
solver_cfg=MJWarpSolverCfg(
9069
solver="newton",

0 commit comments

Comments
 (0)