Skip to content

Commit 53f53c4

Browse files
Adapt remaining root_view.X calls to OVPhysX direct API
Substitutes the verbatim PhysX-mirror's ``articulation.root_view.get_X()`` / ``set_X()`` calls with OVPhysX-direct equivalents, mirroring the RigidObject test precedent (test_rigid_object.py:21-25). - ``get_dof_max_velocities()`` / ``get_dof_max_forces()`` / ``get_dof_friction_properties()``: replaced by ``_read_binding_to_torch(...)``, a small test-side helper that reads the wheel binding into a torch tensor on the requested device for the cross-check against ``data.<X>``. - ``get_coms()`` / ``set_coms()``: replaced by ``_read_binding_to_torch(..., TT.BODY_COM_POSE, device)`` and ``set_coms_index(coms=..., env_ids=...)`` (wp.transformf contract). - ``test_set_material_properties``: xfailed with ``_MATERIAL_GAP_REASON`` pointing at the wheel-gaps spec — same gap as the rigid-object ``set_material_properties`` xfail in isaac-sim#5426. The wheel does not expose ``RIGID_BODY_MATERIAL`` / ``max_shapes``, so neither ``set`` nor ``get`` material properties via ``root_view`` is available.
1 parent 2f2a4e1 commit 53f53c4

1 file changed

Lines changed: 45 additions & 15 deletions

File tree

source/isaaclab_ovphysx/test/assets/test_articulation.py

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import sys
7575
import tempfile
7676

77+
import numpy as np
7778
import pytest
7879
import torch
7980
import warp as wp
@@ -110,6 +111,29 @@
110111
"docs/superpowers/specs/2026-04-28-ovphysx-wheel-gaps-for-marco.md."
111112
)
112113

114+
_MATERIAL_GAP_REASON = (
115+
"Requires a ``RIGID_BODY_MATERIAL`` TensorType (or a view-helper) on the "
116+
"ovphysx wheel side. ``Articulation.root_view`` is a per-tensor-type "
117+
"bindings dict on OVPhysX, so ``root_view.get_material_properties()`` / "
118+
"``set_material_properties()`` / ``max_shapes`` are not available. See "
119+
"docs/superpowers/specs/2026-04-28-ovphysx-wheel-gaps-for-marco.md."
120+
)
121+
122+
123+
def _read_binding_to_torch(articulation: Articulation, tensor_type: int, device: str | torch.device) -> torch.Tensor:
124+
"""Read an OVPhysX TensorBinding into a torch tensor on *device*.
125+
126+
Test-side adapter for the verbatim PhysX mirror. PhysX cross-checks the
127+
data class against the simulation via ``articulation.root_view.get_X()``
128+
accessors; on OVPhysX, ``root_view`` is a per-tensor-type bindings dict
129+
(no view-level getters), so we read the binding directly into a CPU
130+
numpy buffer (CPU-only types) and move the result to *device*.
131+
"""
132+
binding = articulation.root_view[tensor_type]
133+
np_buf = np.zeros(binding.shape, dtype=np.float32)
134+
binding.read(np_buf)
135+
return torch.from_numpy(np_buf).to(device)
136+
113137

114138
# ---------------------------------------------------------------------------
115139
# Session-level OvPhysxManager patches
@@ -1617,7 +1641,7 @@ def test_setting_velocity_limit_implicit(sim, num_articulations, device, vel_lim
16171641
sim.reset()
16181642

16191643
# read the values set into the simulation
1620-
physx_vel_limit = wp.to_torch(articulation.root_view.get_dof_max_velocities()).to(device)
1644+
physx_vel_limit = _read_binding_to_torch(articulation, TT.DOF_MAX_VELOCITY, device)
16211645
# check data buffer
16221646
torch.testing.assert_close(articulation.data.joint_velocity_limits.torch, physx_vel_limit)
16231647
# check actuator has simulation velocity limit
@@ -1666,7 +1690,7 @@ def test_setting_velocity_limit_explicit(sim, num_articulations, device, vel_lim
16661690
sim.reset()
16671691

16681692
# collect limit init values
1669-
physx_vel_limit = wp.to_torch(articulation.root_view.get_dof_max_velocities()).to(device)
1693+
physx_vel_limit = _read_binding_to_torch(articulation, TT.DOF_MAX_VELOCITY, device)
16701694
actuator_vel_limit = articulation.actuators["joint"].velocity_limit
16711695
actuator_vel_limit_sim = articulation.actuators["joint"].velocity_limit_sim
16721696

@@ -1730,7 +1754,7 @@ def test_setting_effort_limit_implicit(sim, num_articulations, device, effort_li
17301754
sim.reset()
17311755

17321756
# obtain the physx effort limits
1733-
physx_effort_limit = wp.to_torch(articulation.root_view.get_dof_max_forces()).to(device=device)
1757+
physx_effort_limit = _read_binding_to_torch(articulation, TT.DOF_MAX_FORCE, device)
17341758

17351759
# check that the two are equivalent
17361760
torch.testing.assert_close(
@@ -1784,7 +1808,7 @@ def test_setting_effort_limit_explicit(sim, num_articulations, device, effort_li
17841808
usd_default_effort_limit = 80.0
17851809

17861810
# collect limit init values
1787-
physx_effort_limit = wp.to_torch(articulation.root_view.get_dof_max_forces()).to(device)
1811+
physx_effort_limit = _read_binding_to_torch(articulation, TT.DOF_MAX_FORCE, device)
17881812
actuator_effort_limit = articulation.actuators["joint"].effort_limit
17891813
actuator_effort_limit_sim = articulation.actuators["joint"].effort_limit_sim
17901814

@@ -1941,16 +1965,19 @@ def test_body_root_state(sim, num_articulations, device, with_offset):
19411965

19421966
# create com offsets — apply offset to the Arm body
19431967
num_bodies = articulation.num_bodies
1944-
com = wp.to_torch(articulation.root_view.get_coms())
1968+
com = _read_binding_to_torch(articulation, TT.BODY_COM_POSE, device)
19451969
link_offset = [1.0, 0.0, 0.0] # the offset from CenterPivot to Arm frames
19461970
new_com = torch.tensor(offset, device=device).repeat(num_articulations, 1, 1)
19471971
com[:, arm_idx, :3] = new_com.squeeze(-2)
1948-
articulation.root_view.set_coms(
1949-
wp.from_torch(com.cpu(), dtype=wp.float32), wp.from_torch(env_idx.cpu(), dtype=wp.int32)
1972+
# PhysX uses ``root_view.set_coms``; OVPhysX wraps the wheel
1973+
# ``BODY_COM_POSE`` write in :meth:`set_coms_index` (wp.transformf contract).
1974+
articulation.set_coms_index(
1975+
coms=wp.from_torch(com.contiguous(), dtype=wp.transformf),
1976+
env_ids=wp.from_torch(env_idx, dtype=wp.int32),
19501977
)
19511978

19521979
# check they are set
1953-
torch.testing.assert_close(wp.to_torch(articulation.root_view.get_coms()), com.cpu())
1980+
torch.testing.assert_close(_read_binding_to_torch(articulation, TT.BODY_COM_POSE, device), com)
19541981

19551982
for i in range(50):
19561983
# perform step
@@ -2059,15 +2086,17 @@ def test_write_root_state(sim, num_articulations, device, with_offset, state_loc
20592086
offset = torch.tensor([0.0, 0.0, 0.0]).repeat(num_articulations, 1, 1)
20602087

20612088
# create com offsets
2062-
com = wp.to_torch(articulation.root_view.get_coms())
2063-
new_com = offset
2089+
com = _read_binding_to_torch(articulation, TT.BODY_COM_POSE, device)
2090+
new_com = offset.to(device)
20642091
com[:, 0, :3] = new_com.squeeze(-2)
2065-
articulation.root_view.set_coms(
2066-
wp.from_torch(com.cpu(), dtype=wp.float32), wp.from_torch(env_idx.cpu(), dtype=wp.int32)
2092+
# See test_body_root_state for the PhysX → OVPhysX setter substitution.
2093+
articulation.set_coms_index(
2094+
coms=wp.from_torch(com.contiguous(), dtype=wp.transformf),
2095+
env_ids=wp.from_torch(env_idx, dtype=wp.int32),
20672096
)
20682097

20692098
# check they are set
2070-
torch.testing.assert_close(wp.to_torch(articulation.root_view.get_coms()), com)
2099+
torch.testing.assert_close(_read_binding_to_torch(articulation, TT.BODY_COM_POSE, device), com)
20712100

20722101
rand_state = torch.zeros(num_articulations, 13, device=device)
20732102
rand_state[..., :7] = articulation.data.default_root_pose.torch
@@ -2443,7 +2472,7 @@ def test_write_joint_frictions_to_sim(sim, num_articulations, device, add_ground
24432472
# update buffers
24442473
articulation.update(sim.cfg.dt)
24452474

2446-
friction_props_from_sim = wp.to_torch(articulation.root_view.get_dof_friction_properties())
2475+
friction_props_from_sim = _read_binding_to_torch(articulation, TT.DOF_FRICTION_PROPERTIES, "cpu")
24472476
joint_friction_coeff_sim = friction_props_from_sim[:, :, 0]
24482477
joint_dynamic_friction_coeff_sim = friction_props_from_sim[:, :, 1]
24492478
joint_viscous_friction_coeff_sim = friction_props_from_sim[:, :, 2]
@@ -2483,7 +2512,7 @@ def test_write_joint_frictions_to_sim(sim, num_articulations, device, add_ground
24832512
sim.step()
24842513
articulation.update(sim.cfg.dt)
24852514

2486-
friction_props_from_sim_2 = wp.to_torch(articulation.root_view.get_dof_friction_properties())
2515+
friction_props_from_sim_2 = _read_binding_to_torch(articulation, TT.DOF_FRICTION_PROPERTIES, "cpu")
24872516
joint_friction_coeff_sim_2 = friction_props_from_sim_2[:, :, 0]
24882517
friction_dynamic_coef_sim_2 = friction_props_from_sim_2[:, :, 1]
24892518
friction_viscous_coeff_sim_2 = friction_props_from_sim_2[:, :, 2]
@@ -2499,6 +2528,7 @@ def test_write_joint_frictions_to_sim(sim, num_articulations, device, add_ground
24992528
@pytest.mark.parametrize("device", ["cuda:0", "cpu"])
25002529
@pytest.mark.parametrize("articulation_type", ["panda"])
25012530
@pytest.mark.isaacsim_ci
2531+
@pytest.mark.xfail(reason=_MATERIAL_GAP_REASON, strict=False)
25022532
def test_set_material_properties(sim, num_articulations, device, add_ground_plane, articulation_type):
25032533
"""Test getting and setting material properties (friction/restitution) of articulation shapes."""
25042534
articulation_cfg = generate_articulation_cfg(articulation_type=articulation_type)

0 commit comments

Comments
 (0)