Skip to content

Clear self-collision filter pairs before finalizing shadow Newton model - #7505

Merged
ooctipus merged 5 commits into
isaac-sim:developfrom
matthewtrepte:mtrepte/debug-3
Sep 4, 2026
Merged

Clear self-collision filter pairs before finalizing shadow Newton model#7505
ooctipus merged 5 commits into
isaac-sim:developfrom
matthewtrepte:mtrepte/debug-3

Conversation

@matthewtrepte

@matthewtrepte matthewtrepte commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • 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.

Test plan

  • 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
  • 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
  • uv run isaaclab -f

Release backport

  • Backport this pull request to the active release branch after it merges into develop

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().
@matthewtrepte
matthewtrepte requested a review from a team September 2, 2026 23:54
@github-actions github-actions Bot added bug Something isn't working isaac-lab Related to Isaac Lab team labels Sep 2, 2026

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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-apps

greptile-apps Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR prevents PhysX-backed shadow Newton models from packing unused, environment-replicated self-collision filter pairs during finalization.

  • Clears shape_collision_filter_pairs immediately before shadow-model finalization.
  • Adds a focused regression test and Newton changelog entry documenting the memory-exhaustion fix.

Confidence Score: 4/5

The 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

Filename Overview
source/isaaclab_newton/isaaclab_newton/physics/newton_manager.py Clears unused collision-filter pairs on the exclusively owned PhysX shadow builder before finalization, avoiding excessive memory use without affecting the Newton physics model.
source/isaaclab/test/sim/test_newton_manager_visualization_state.py Adds regression coverage for clearing the list, but does not enforce that clearing occurs before finalization.
source/isaaclab_newton/changelog.d/fix-shadow-model-collision-filter-oom.rst Accurately documents the shadow-model memory-exhaustion fix and its affected visualization paths.

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]
Loading

Reviews (1): Last reviewed commit: "Clear self-collision filter pairs before..." | Re-trigger Greptile


NewtonManager._ensure_visualization_model()

assert builder.shape_collision_filter_pairs == []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 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.
@matthewtrepte

Copy link
Copy Markdown
Contributor Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 3, 2026
@ooctipus

ooctipus commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

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 (24bd863528d6b91137408930d0fbe8fa216ad962):

10 replicated filtered pairs, unchanged:       10 filters,  0 contacts
builder.shape_collision_filter_pairs = []:      0 filters, 10 contacts
clear filters + collision group 0:              0 filters,  0 contacts

At 1,024 worlds × 48 shapes, clearing alone generated 1,155,072 contact pairs. ModelBuilder.finalize() currently always calls _find_shape_contact_pairs(), so deleting an exclusion makes that pair eligible for the contact array. The new test mocks finalize(), which hides this transfer.

I suggest moving the policy into build_visualization_builder_from_stage_envs(), where we know every produced builder is scene-only, and applying it before composition/replication:

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 [] replaces Newton's compact filter representation with a plain list; adding already-stripped component builders to a fresh builder keeps the destination compact-empty and preserves homogeneous contact-template finalization. Please retain assignment rather than .clear(), because reading the property can materialize the compact replicated filters.

Then _ensure_visualization_model() can return to simply finalizing the already-correct builder; the late clear and its comment go away. This keeps the generic cloner unchanged and adds no cfg field, helper, fallback, or public API.

For the regression, I would replace the mocked-ordering test with a small real CPU ModelBuilder.finalize() test covering replicated filtered shapes and asserting both:

assert len(model.shape_collision_filter_pairs) == 0
assert model.shape_contact_pair_count == 0

Collision 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 NewtonReplicateContext branch before plan replication, while Newton physics resources retain collision data.

@ooctipus

ooctipus commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Implemented the construction-boundary fix in 4716126cc.

  • Collision filters and groups are stripped from visualization-only component builders before composition/replication.
  • A fresh destination builder preserves Newton's compact empty-filter representation.
  • The manager-level late clear and mocked-order test are removed.
  • A real in-memory USD/Newton finalization test now checks both standalone and replicated models have geometry but no filters or contact pairs.

Validation:

@kellyguo11

Copy link
Copy Markdown
Contributor

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 4, 2026

@AntoineRichard AntoineRichard left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM thanks Matthew!

…lision-model

# Conflicts:
#	source/isaaclab_newton/isaaclab_newton/physics/visualization_builder.py
@ooctipus

ooctipus commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

run-ci

@isaaclab-bot isaaclab-bot Bot added the ci:run-docker Trigger the on-demand Docker and GPU CI workflow label Sep 4, 2026
@isaaclab-bot isaaclab-bot Bot removed the ci:run-docker Trigger the on-demand Docker and GPU CI workflow label Sep 4, 2026
@ooctipus
ooctipus merged commit 4b9ba22 into isaac-sim:develop Sep 4, 2026
53 checks passed
kellyguo11 pushed a commit to kellyguo11/IsaacLab-public that referenced this pull request Sep 4, 2026
…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)
kellyguo11 added a commit that referenced this pull request Sep 4, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants