Skip to content

Use ovphysx kinematic FK on articulation PR#11

Open
marcodiiga wants to merge 6 commits into
AntoineRichard:antoiner/feat/ovphysx_articulationfrom
marcodiiga:dev/malesiani/ovphysx_kinematic_fk_on_articulation_pr
Open

Use ovphysx kinematic FK on articulation PR#11
marcodiiga wants to merge 6 commits into
AntoineRichard:antoiner/feat/ovphysx_articulationfrom
marcodiiga:dev/malesiani/ovphysx_kinematic_fk_on_articulation_pr

Conversation

@marcodiiga

Copy link
Copy Markdown

Require ovphysx>=0.4.2, refresh FK before same-frame link-pose reads, and drop the stale FK-on-demand xfail.

Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context.
List any dependencies that are required for this change.

Fixes # (issue)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Screenshots

Please attach before and after screenshots of the change if applicable.

Checklist

  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the changelog and the corresponding version in the extension's config/extension.toml file
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

AntoineRichard and others added 3 commits May 5, 2026 16:27
The dual-Carbonite destructor race that crashed test_rigid_object.py
between tests is not test-specific: any production caller that closes
a SimulationContext and constructs a new one in the same process hits
the same path. The previous PR worked around it with session-scoped
class-level monkey patches in the test file (_PHYSX_BY_DEVICE cache,
_patched_release_physx, _patched_warmup_and_load); production code
remained latently buggy.

Move the workaround into the manager itself:

* _release_physx is now a soft reset -- physx.reset() + wait_op while
  keeping the cached ovphysx.PhysX reference alive on cls._physx, so
  the C++ destructor never fires mid-process.
* _warmup_and_load reuses the cached instance on subsequent calls.
  First call constructs + locks the device + registers atexit; later
  calls re-export the USD, run physx.reset() to clear the prior stage,
  add_usd, replay clones, and (on GPU) re-run warmup_gpu so the new
  stage's bodies are resident.
* New _locked_device class attribute mirrors the wheel's process-global
  device-mode lock; the manager raises RuntimeError with a clear
  message instead of letting the wheel's PhysXDeviceError fire.
* _construct_physx splits out the first-time bootstrap so the orchestration
  in _warmup_and_load stays linear.
* HACK comments on _release_physx are keyed to the same wheel-fix
  milestone (namespace-isolated Carbonite) tracked by gap G5.

The dict keyed by device (_PHYSX_BY_DEVICE) is gone -- since the wheel
locks the process to one device, the dict could never hold more than
one entry and was misleading.

In test_rigid_object.py, drop the entire patch block (~150 lines):
_PHYSX_BY_DEVICE, _patched_release_physx, _patched_warmup_and_load,
_orig_*, _ovphysx_session_patches. Keep _LOCKED_DEVICE plus
_ovphysx_skip_other_device autouse fixture -- the only remaining
test-side concern is pre-empting the device-lock RuntimeError with a
clean pytest.skip on parametrized device mismatch, so two-pass CI
finishes cleanly when only one device is exercised. Update
test_warmup_attach_stage_not_called_for_cpu to spy on a real PhysX
after construction (the old approach silently relied on the patch
overwriting cls._physx).

Tests: 42 CPU + 41 GPU passing (two pytest invocations per Marco's
two-pass requirement).

Bumps isaaclab_ovphysx 0.2.16 -> 0.2.17.
Add Articulation and ArticulationData for the OVPhysX backend, mirroring
the PhysX/Newton public API. Resolves PR isaac-sim#5459.

Articulation
^^^^^^^^^^^^

* index/mask split for every state writer, simulation-parameter writer,
  setter, and tendon setter; OVPhysX exposes both _index and _mask as
  first-class paths and intentionally drops the PhysX-specific
  ``full_data`` kwarg.
* Dedicated dynamic + viscous friction setters
  (write_joint_{dynamic,viscous}_friction_coefficient_to_sim_{index,mask})
  that touch only their slot of the combined (N, J, 3)
  DOF_FRICTION_PROPERTIES buffer.  The combined
  write_joint_friction_coefficient_to_sim_index/_mask still accepts all
  three components as kwargs (Coulomb static + dynamic + optional
  viscous) for source-compatible PhysX call sites.
* Deprecated non-indexed shorthand shims for friction (x3) and root /
  joint state (x4), forwarding to the index variants with a
  DeprecationWarning, matching PhysX's deprecated section.
* Wrench-composer return types tightened to non-None
  (instantaneous_wrench_composer / permanent_wrench_composer);
  composers are always set in _create_buffers, mirroring PhysX/Newton.
* Section organisation matches PhysX exactly: Properties -> Operations
  -> Operations - Finders -> Operations - State Writers -> Operations
  - Simulation Parameters Writers -> Operations - Setters -> Operations
  - Tendons -> Internal helper -> Internal simulation callbacks ->
  Internal helpers -- Actuators -> Internal helpers -- Debugging ->
  Deprecated methods.  Section delimiters use bare """Section."""
  docstring blocks (Newton/PhysX convention).

ArticulationData
^^^^^^^^^^^^^^^^

* Pull-on-demand timestamped buffers; CPU-only bindings route through
  pinned-host staging (PR isaac-sim#5329 pattern).
* Property names match PhysX exactly: joint_friction_coeff,
  joint_dynamic_friction_coeff, joint_viscous_friction_coeff (no
  *_static / *_dynamic / *_viscous renames).
* SI units annotated on every public property docstring
  ([m or rad, depending on joint type], [m/s or rad/s, ...], [N*m],
  [kg], etc.) per AGENTS.md.
* binding_getter parameter on __init__ typed as
  Callable[[int], Any] | None.
* Section organisation matches PhysX (Defaults -> Joint commands ->
  Joint properties -> Fixed tendon -> Spatial tendon -> Root state ->
  Body state -> Joint state -> Derived -> Sliced -> Internal helpers ->
  Deprecated properties).

Kernels
^^^^^^^

* Articulation-specific kernels in
  isaaclab_ovphysx/assets/articulation/kernels.py (soft-limit clamp,
  friction-data writer, finite-difference joint-acc helper, body-CoM
  pose composer); shared kernels promoted to
  isaaclab_ovphysx/assets/kernels.py.
* Per-kernel docstrings document purpose, shape/dtype/SI units, and
  divergence notes where the OVPhysX implementation differs (e.g.
  _fd_joint_acc takes inv_dt rather than dt to avoid per-element
  division).

Tests
^^^^^

* Real-backend test_articulation.py mirrors isaaclab_physx 1-to-1
  under run_ovphysx.sh; 99 tests pass on each of CPU + CUDA.
* test_articulation_helpers.py covers the kitless-only helpers
  (tendon scoping, mock binding shapes).
* Cross-backend test_articulation_iface.py runs the OVPhysX path:
  544 tests pass, 16 skipped, 0 failed on each of CPU + CUDA.  Brings
  the iface helper up to the actual ArticulationData constructor
  signature and broadcasts scalar inputs across joint / fixed-tendon
  / spatial-tendon mask setters that previously rejected them.

OVPhysX-only surface dropped
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* Articulation: set_external_force_and_torque_{index,mask} (use
  instantaneous_wrench_composer.add_forces_and_torques_*),
  set_spatial_tendon_limit_{index,mask}, and
  set_spatial_tendon_rest_length_{index,mask} (NotImplementedError
  stubs PhysX never had).
* ArticulationData: body_pose_w / body_lin_vel_w / body_ang_vel_w /
  body_acc_w / body_link_acc_w (base class provides matching
  defaults), body_inv_mass / body_inv_inertia, fixed_tendon_limit
  (PhysX exposes only fixed_tendon_pos_limits), spatial_tendon_limit /
  spatial_tendon_rest_length (no PhysX equivalent).
Require ovphysx>=0.4.2, refresh FK before same-frame link-pose reads, and drop the stale FK-on-demand xfail.
@AntoineRichard AntoineRichard force-pushed the antoiner/feat/ovphysx_articulation branch 5 times, most recently from 4d05d9d to 18c90dc Compare May 6, 2026 12:37
marcodiiga added 2 commits May 7, 2026 20:34
# Conflicts:
#	source/isaaclab_ovphysx/config/extension.toml
#	source/isaaclab_ovphysx/docs/CHANGELOG.rst
#	source/isaaclab_ovphysx/isaaclab_ovphysx/assets/articulation/articulation_data.py
#	source/isaaclab_ovphysx/isaaclab_ovphysx/physics/ovphysx_manager.py
#	source/isaaclab_ovphysx/setup.py
#	source/isaaclab_ovphysx/test/assets/test_articulation.py
#	source/isaaclab_ovphysx/test/assets/test_rigid_object.py

@AntoineRichard AntoineRichard left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@marcodiiga marcodiiga marked this pull request as ready for review May 8, 2026 08:28
@marcodiiga marcodiiga requested a review from Mayankm96 as a code owner May 8, 2026 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants