Clear self-collision filter pairs before finalizing shadow Newton model - #7505
Conversation
The PhysX-backend shadow Newton visualization model never runs collision detection, but USD-authored self-collision filter pairs were still being imported into it and replicated across every cloned env. At real training env counts this could reach billions of entries and OOM ModelBuilder.finalize().
There was a problem hiding this comment.
Isaac Lab Review Bot
The change removes unused collision-filter pairs from the PhysX-backend shadow Newton visualization model before finalization, directly addressing the reported memory growth. It includes focused regression coverage and appropriate package changelog fragments.
- Design and architecture: The clearing occurs after the visualization builder is populated and immediately before finalization, and only on the PhysX shadow-model path. Newton-native simulation behavior, deformable registry population, state synchronization, and lifecycle callbacks remain unchanged.
- API: No public API, exported symbol, default, or compatibility contract changes. The modification is confined to the private shadow-model construction path, with the user-visible fix documented in the isaaclab_newton changelog and the test-only isaaclab change marked with a .skip fragment.
- Implementation: Assigning an empty collection before finalize directly prevents the unused pairs from being packed. The proposed concern about changing the container type is not supported by evidence that finalize performs set-specific mutations; the regression test confirms that the collection is removed along the intended construction path.
No blocking issues. No inline issue met the actionable-evidence threshold; the assessment above records the review feedback.
Automated review; human maintainers own approval decisions.
Greptile SummaryThe PR prevents PhysX-backed shadow Newton models from packing unused, environment-replicated self-collision filter pairs during finalization.
Confidence Score: 4/5The implementation appears safe to merge, with a non-blocking opportunity to make the regression test enforce the critical pre-finalization ordering. The functional change is confined to the PhysX visualization-only builder and occurs before finalization; the only accepted concern is that the test could remain green if that ordering later regresses. Files Needing Attention: source/isaaclab/test/sim/test_newton_manager_visualization_state.py Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[PhysX USD stage] --> B[Build shadow Newton ModelBuilder]
B --> C[Imported collision filter pairs]
C --> D[Clear unused filter pairs]
D --> E[Finalize shadow model]
E --> F[Visualizers and renderers]
Reviews (1): Last reviewed commit: "Clear self-collision filter pairs before..." | Re-trigger Greptile |
|
|
||
| NewtonManager._ensure_visualization_model() | ||
|
|
||
| assert builder.shape_collision_filter_pairs == [] |
There was a problem hiding this comment.
Finalize ordering remains untested
The assertion verifies only that the list is eventually empty, while the finalize stub never inspects it. Moving the clear after finalize() would leave this test green while restoring the production memory-exhaustion path, so the stub should assert that the list is empty when finalization begins.
…fter Addresses Greptile review feedback: the regression test previously only checked the builder's post-call state, which would stay green even if a future change cleared the pairs after finalize() instead of before.
|
run-ci |
|
Thanks for fixing this. I agree with the invariant: a Newton model used only for visualization/scene queries should not carry solver-only collision data. I think the current late clear is incomplete, though, because Newton generates contact pairs during the same finalization. I reproduced this against both Newton 1.5.1 and the exact 1.6 development commit pinned by #7453 ( At 1,024 worlds × 48 shapes, clearing alone generated 1,155,072 contact pairs. I suggest moving the policy into for visual_builder in (global_builder, *source_builders.values()):
visual_builder.shape_collision_filter_pairs = []
visual_builder.shape_collision_group[:] = [0] * visual_builder.shape_count
builder = ModelBuilder(up_axis=up_axis)
builder.add_builder(global_builder)
replicate_builder_mapping(builder, sources, mapping, positions, quaternions, source_builders)The standalone branch should apply the same two assignments before returning its builder. The fresh assembled builder is important: assigning Then For the regression, I would replace the mocked-ordering test with a small real CPU assert len(model.shape_collision_filter_pairs) == 0
assert model.shape_contact_pair_count == 0Collision group 0 leaves shape flags and the BVH intact; I also verified the same Newton raycast hit and distance with groups 1 and 0. The existing raycaster suite should still be run, but a second large test is unnecessary. This also ports cleanly to the planned ownership model: the same normalization belongs on source/global builders in the visualization-only |
|
Implemented the construction-boundary fix in
Validation:
|
|
run-ci |
AntoineRichard
left a comment
There was a problem hiding this comment.
LGTM thanks Matthew!
…lision-model # Conflicts: # source/isaaclab_newton/isaaclab_newton/physics/visualization_builder.py
|
run-ci |
…el (isaac-sim#7505) - The PhysX-backend shadow Newton visualization model never runs collision detection, but USD-authored self-collision filter pairs (`physxArticulation:enabledSelfCollisions`) were still imported into it and replicated across every cloned env. - At real training env counts, this filter-pair set could reach billions of entries, causing `ModelBuilder.finalize()` to run out of memory. - Clears `builder.shape_collision_filter_pairs` before finalizing the shadow model since it has no use for them. - [x] `uv run python -m pytest source/isaaclab/test/sim/test_newton_manager_visualization_state.py` — 23 passed, including new regression test `test_ensure_visualization_model_clears_shape_collision_filter_pairs_before_finalize` - [x] `uv run python -m pytest source/isaaclab/test/sim/test_simulation_context_visualizers.py source/isaaclab_newton/test/physics/test_newton_manager_abstraction.py` — 200 passed - [x] `uv run isaaclab -f` - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` --------- Co-authored-by: Octi Zhang <zhengyuz@nvidia.com> (cherry picked from commit 4b9ba22)
…alizing shadow Newton model (#7505) (#7580) # Description Backports #7505 to `release/3.0.0` by cherry-picking the merged commit `4b9ba22508895906bb856845153b6409b5e86b3c` with `-x` provenance. The [automatic backport run](https://github.com/isaac-sim/IsaacLab/actions/runs/33862657583) encountered the expected visualization-builder conflict, but its inferred resolution dropped the release-only `rename_builder_labels` import and failed Ruff with `F821`. This manual backport preserves the source change while retaining the release branch's API sequence: it strips collision filters and groups before composition and replication, calls the release signature of `replicate_builder_mapping`, and then calls `rename_builder_labels` separately. No runtime dependencies are added. | Field | Commit | |---|---| | Original merged change | `4b9ba22508895906bb856845153b6409b5e86b3c` | | Release base used | `355dc9ba107527d7baae7600e89229a89d4e4628` | | Proposed backport | `64c6d483803bf706404236516d92c8ec77ab8211` | ## Type of change - Bug fix (non-breaking change which fixes an issue) ## Release backport - This PR already targets the active release branch. ## Validation - Repository backport candidate validation passed with all five source paths preserved and no extra paths changed. - Full repository pre-commit suite passed against `release/3.0.0`, including changelog and Git LFS checks. - `uv run --no-project python -m compileall -q` passed for all three modified Python files. - `git diff --check upstream/release/3.0.0...HEAD` passed. - Focused Newton regression tests are pending Linux CI because the repository lockfile does not support the local macOS/arm64 host. The original source PR completed 53 checks successfully. ## Checklist - [x] I have read and understood the contribution guidelines - [x] I have run the available pre-commit checks - [x] Documentation changes are not needed for this backport - [ ] My changes generate no new runtime warnings (pending Linux CI) - [x] The original regression test is preserved in the backport - [x] Changelog fragments are preserved for both touched packages - [x] The original contributor is already listed in `CONTRIBUTORS.md` Co-authored-by: matthewtrepte <mtrepte@nvidia.com> Co-authored-by: Octi Zhang <zhengyuz@nvidia.com>
Summary
physxArticulation:enabledSelfCollisions) were still imported into it and replicated across every cloned env.ModelBuilder.finalize()to run out of memory.builder.shape_collision_filter_pairsbefore finalizing the shadow model since it has no use for them.Test plan
uv run python -m pytest source/isaaclab/test/sim/test_newton_manager_visualization_state.py— 23 passed, including new regression testtest_ensure_visualization_model_clears_shape_collision_filter_pairs_before_finalizeuv run python -m pytest source/isaaclab/test/sim/test_simulation_context_visualizers.py source/isaaclab_newton/test/physics/test_newton_manager_abstraction.py— 200 passeduv run isaaclab -fRelease backport
develop