Homogenize contact sensor force semantics - #7382
Conversation
Clarify normal and friction force contracts across backends, expose Newton friction data, and retain deprecated aliases for migration. Add force-vector visualization and update affected documentation, tests, and callers.
Greptile SummaryThis PR makes contact-force semantics explicit and consistent across the shared, Newton, PhysX, and OVPhysX contact-sensor APIs.
Confidence Score: 4/5The PR appears safe to merge, with a non-blocking Newton debug-visualization issue that can briefly display stale friction arrows after reset. The force decomposition and cross-backend API migration are internally consistent, but Newton friction visualization bypasses the reset-aware sensor buffer and can render pre-reset contact values until the next step. Files Needing Attention: source/isaaclab_newton/isaaclab_newton/sensors/contact_sensor/contact_sensor.py Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
P[Backend contact data] --> N{Backend}
N -->|Newton total + friction| D[Decompose total]
D --> NN[net_normal_forces_w]
D --> NF[net_friction_forces_w]
N -->|PhysX / OVPhysX normal| NN
N -->|Filtered contacts| NM[normal_force_matrix_w]
N -->|Supported filtered friction| FM[friction_force_matrix_w]
NN --> C[Tasks, rewards, and visualization]
NF --> C
NM --> C
FM --> C
Reviews (1): Last reviewed commit: "Homogenize contact sensor force semantic..." | Re-trigger Greptile |
There was a problem hiding this comment.
Isaac Lab Review Bot
The contact-force API is consistently renamed and decomposed across the shared contract and all three backends, with deprecated aliases and migrated consumers. Two concrete issues remain in the new force-vector visualization: inconsistent arrow-length axes and Newton friction rendering that bypasses reset-aware owned buffers.
- Design and architecture: The normal/friction split is propagated through the shared data interface, backend containers, Warp kernels, reset paths, documentation, and consumers. The shared visualizer is an appropriate cross-backend abstraction, but Newton should feed it through the same owned sensor buffers used by the public API rather than a raw backend view.
- API: The canonical normal and friction names are documented, existing names remain warning-backed aliases, and backend limitations such as unsupported PhysX aggregate friction are explicit. Migration documentation and in-repository consumers have been updated consistently.
- Implementation: The visualization computes dynamic length on scale axis 0 but derives its prototype length from axis 2, producing an incorrect tail offset. Newton friction visualization also reads the raw backend friction view, bypassing timestamp stale-data protection, reset zeroing, and the track_friction_forces buffer contract. Use the matching length axis and render from net_friction_forces_w when available.
Minor fixes needed. Posted 2 actionable findings inline.
Automated review; human maintainers own approval decisions.
|
|
||
| self._visualizer = VisualizationMarkers(cfg) | ||
| self._force_scale = force_scale | ||
| self._prototype_length = marker_scale[2] |
There was a problem hiding this comment.
🟡 Warning · Implementation — Arrow length read from wrong scale axis
visualize() encodes the force magnitude into scales[:, 0], so index 0 is the arrow's length axis, but _prototype_length is taken from marker_scale[2]. displayed_lengths therefore mixes the Z extent with the X scale factor, and with the configured (0.04, 0.04, 0.2) arrow the tail offset is five times the drawn length, detaching arrows from the contact position. Read the prototype length from the same axis that is scaled.
|
run-ci |
|
@yufengsjtu lets not deprecate net_force_w, we can alias it to normal force for physx and give a one time warning that net_force_w is normal force instead |
…-contact-sensor-forces
…ations Keep net_forces_w as total force and friction_forces_w as aggregate friction. Newton reports those quantities directly; PhysX and OVPhysX fall back to normal or filtered-friction data and warn. Add friction history buffers.
|
run-ci |
|
Backported to |
# Description This PR clarifies and homogenizes the normal and friction contact-force contracts across the PhysX, Newton, and OVPhysX backends. ## Summary - Unified the physical meaning of the same contact sensor data `net_forces_w` under different backends - Introduced explicit normal-force property names: - `net_normal_forces_w` - `net_normal_forces_w_history` - `normal_force_matrix_w` - `normal_force_matrix_w_history` - Renamed filtered friction forces to `friction_force_matrix_w`. - Added `net_friction_forces_w` for aggregate friction forces. - Retained the previous property names as deprecated aliases for migration. - Documented the total contact-force relationship: `total_force = net_normal_forces_w + net_friction_forces_w`. - Updated affected callers, tests, benchmarks, tutorials, and documentation. ## Backend behavior - Newton now exposes aggregate and filtered friction forces. Normal forces are obtained by subtracting friction from Newton's total contact forces. - PhysX continues to expose filtered friction through `get_friction_data`. Aggregate friction is unavailable, so `net_friction_forces_w` raises `NotImplementedError`. - OVPhysX adopts the renamed normal-force API while retaining its existing unsupported friction behavior. ## Visualization Added force-vector visualization using separate markers for normal and friction forces: - Newton displays both aggregate normal and friction vectors. - PhysX displays aggregate normal-force vectors. - Arrow direction and length represent the world-frame force direction and magnitude. ## Motivation The previous contact sensor data had inconsistent physical semantics across backends. In particular, PhysX reported normal contact forces through `net_forces_w`, while Newton reported total contact forces, including both normal and friction components, through the same property. Consequently, identical API usage could represent different physical quantities depending on the selected backend. The previous names also made it unclear whether a force was normal, frictional, total, aggregate, or filtered. This PR establishes an explicit cross-backend contract and retains deprecated aliases to provide a migration path. ## Type of change - New feature - Breaking change - Documentation update ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` ## Screenshots ### PhysX normal-force visualization <img width="836" height="545" alt="image" src="https://github.com/user-attachments/assets/77cb3e1f-73ca-4e22-9143-5c008743521c" /> ### Newton normal- and friction-force visualization <img width="729" height="573" alt="image" src="https://github.com/user-attachments/assets/7ce48ff5-8826-4285-b283-92d98f7cfae3" /> ## Validation - Added tests for Newton normal/friction force decomposition. - Added tests for deprecated force-property aliases. - Added tests for contact-force vector visualization. - Manually verified visualization with PhysX and Newton MJWarp. - Built the updated contact sensor documentation. ## Checklist - [x] I have read and understood the [contribution guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html) - [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with `uv run isaaclab -f` - [x] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] I have added a changelog fragment under `source/<pkg>/changelog.d/` for every touched package - [ ] I have added my name to `CONTRIBUTORS.md` or my name already exists there (cherry picked from commit 5ea0a27)
Description
This PR clarifies and homogenizes the normal and friction contact-force contracts across the PhysX, Newton, and OVPhysX backends.
Summary
net_forces_wunder different backendsnet_normal_forces_wnet_normal_forces_w_historynormal_force_matrix_wnormal_force_matrix_w_historyfriction_force_matrix_w.net_friction_forces_wfor aggregate friction forces.total_force = net_normal_forces_w + net_friction_forces_w.Backend behavior
get_friction_data. Aggregate friction is unavailable, sonet_friction_forces_wraisesNotImplementedError.Visualization
Added force-vector visualization using separate markers for normal and friction forces:
Motivation
The previous contact sensor data had inconsistent physical semantics across backends. In particular, PhysX reported normal contact forces through
net_forces_w, while Newton reported total contact forces, including both normal and friction components, through the same property.Consequently, identical API usage could represent different physical quantities depending on the selected backend. The previous names also made it unclear whether a force was normal, frictional, total, aggregate, or filtered.
This PR establishes an explicit cross-backend contract and retains deprecated aliases to provide a migration path.
Type of change
Release backport
developScreenshots
PhysX normal-force visualization
Newton normal- and friction-force visualization
Validation
Checklist
pre-commitchecks withuv run isaaclab -fsource/<pkg>/changelog.d/for every touched packageCONTRIBUTORS.mdor my name already exists there