Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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,17 @@
Fixed
^^^^^

* Fixed :class:`~isaaclab_ov.sim.views.OvPhysxView` routing eight CPU-resident
tensor types to the simulation device. The per-collision-shape contact and rest
offsets, the articulation and rigid-body gravity-disable flags, and the DOF drive
type and drive model are CPU-resident even on a GPU simulation, but were absent
from the internal CPU-only classification. Reads and writes of these types
incurred a hidden per-call host-to-device staging copy, and a correctly placed
host buffer was rejected with ``OvPhysxView.DeviceMismatch``. Residency was
measured on a GPU simulation by counting CUDA memcpys around a binding read.
* **Breaking:** Fixed ``articulation_dof_drive_type`` not being classified as
read-only. The underlying tensor type is read-only, but
:meth:`~isaaclab_ov.sim.views.OvPhysxView.set_attribute` previously accepted
writes to it and silently forwarded them. Such calls now raise
``OvPhysxView.ReadOnlyAttribute``. Remove any write to this attribute; drive
type is authored through the USD drive schema, not the tensor path.
1 change: 1 addition & 0 deletions source/isaaclab_ov/isaaclab_ov/sim/views/ovphysx_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"articulation_body_inv_mass",
"articulation_body_inv_inertia",
"articulation_dof_projected_joint_force",
"articulation_dof_drive_type",
"articulation_jacobian",
"articulation_mass_center_world",
"articulation_mass_center_local",
Expand Down
11 changes: 11 additions & 0 deletions source/isaaclab_ov/isaaclab_ov/tensor_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,17 @@
RIGID_BODY_MASS,
RIGID_BODY_COM_POSE,
RIGID_BODY_INERTIA,
# Collision-shape offsets, gravity-disable flags and DOF drive metadata. Measured
# CPU-resident on a GPU sim; referenced through ``_TT`` since this module exposes
# no public alias for them.
_TT.ARTICULATION_DOF_DRIVE_TYPE,
_TT.ARTICULATION_DOF_DRIVE_MODEL,
_TT.ARTICULATION_BODY_DISABLE_GRAVITY,
_TT.ARTICULATION_CONTACT_OFFSET,
_TT.ARTICULATION_REST_OFFSET,
_TT.RIGID_BODY_DISABLE_GRAVITY,
_TT.RIGID_BODY_CONTACT_OFFSET,
_TT.RIGID_BODY_REST_OFFSET,
DEFORMABLE_MATERIAL_DYNAMIC_FRICTION,
DEFORMABLE_MATERIAL_YOUNGS_MODULUS,
DEFORMABLE_MATERIAL_POISSONS_RATIO,
Expand Down
54 changes: 52 additions & 2 deletions source/isaaclab_ov/test/sim/test_ovphysx_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"articulation_body_inv_mass",
"articulation_body_inv_inertia",
"articulation_dof_projected_joint_force",
"articulation_dof_drive_type",
"articulation_link_incoming_joint_force",
"articulation_mass_center_world",
"articulation_mass_center_local",
Expand All @@ -70,6 +71,48 @@
}
)

# CPU-resident on a GPU sim. Each name was measured, not assumed: with DirectGPU
# (``suppressReadback=True``) the residency of every tensor type was determined by counting
# CUDA memcpys around a binding read into a host buffer and into a device buffer.
_EXPECTED_CPU_ONLY_NAMES = frozenset(
{
"articulation_body_com_pose",
"articulation_body_disable_gravity",
"articulation_body_inertia",
"articulation_body_inv_inertia",
"articulation_body_inv_mass",
"articulation_body_mass",
"articulation_contact_offset",
"articulation_dof_armature",
"articulation_dof_damping",
"articulation_dof_drive_model",
"articulation_dof_drive_type",
"articulation_dof_friction_properties",
"articulation_dof_limit",
"articulation_dof_max_force",
"articulation_dof_max_velocity",
"articulation_dof_stiffness",
"articulation_rest_offset",
"articulation_shape_friction_and_restitution",
"deformable_material_bending_damping",
"deformable_material_bending_stiffness",
"deformable_material_dynamic_friction",
"deformable_material_elasticity_damping",
"deformable_material_poissons_ratio",
"deformable_material_thickness",
"deformable_material_youngs_modulus",
"rigid_body_com_pose",
"rigid_body_contact_offset",
"rigid_body_disable_gravity",
"rigid_body_inertia",
"rigid_body_inv_inertia",
"rigid_body_inv_mass",
"rigid_body_mass",
"rigid_body_rest_offset",
"rigid_body_shape_friction_and_restitution",
}
)

# Per-type shapes used by the fakes (only the types touched by the tests).
_SHAPES = {
TensorType.RIGID_BODY_POSE: lambda n: (n, 7),
Expand Down Expand Up @@ -201,18 +244,25 @@ def test_read_only_names_are_valid_vocabulary():
def test_read_only_and_cpu_only_classification():
assert is_read_only("articulation_jacobian")
assert is_read_only("rigid_body_acceleration")
assert is_read_only("articulation_dof_drive_type")
assert not is_read_only("articulation_dof_stiffness")
assert is_cpu_only("articulation_dof_stiffness")
assert is_cpu_only("rigid_body_mass")
assert is_cpu_only("rigid_body_disable_gravity")
assert is_cpu_only("articulation_dof_drive_type")
assert not is_cpu_only("rigid_body_pose")


def test_cpu_only_names_match_canonical_set():
# The view derives its CPU-only set from tensor_types so the two cannot drift.
# Comparing the view's derived set against the canonical one cannot fail, since the
# former is built from the latter. The expected inventory is what gives this test
# teeth: it is measured residency, so it also rejects a set that is merely incomplete.
from isaaclab_ov.sim.views import ovphysx_view as mod
from isaaclab_ov.tensor_types import _CPU_ONLY_TYPES

assert frozenset(tt.name.lower() for tt in _CPU_ONLY_TYPES) == mod._CPU_ONLY_NAMES
assert frozenset(tt.name.lower() for tt in _CPU_ONLY_TYPES) == _EXPECTED_CPU_ONLY_NAMES
assert mod._CPU_ONLY_NAMES == _EXPECTED_CPU_ONLY_NAMES
assert set(attribute_vocabulary()) >= mod._CPU_ONLY_NAMES


# -----------------------------------------------------------------------------
Expand Down
Loading