Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Expand Up @@ -330,6 +330,29 @@ def _finalize(device):
assert NewtonManager._state_0 is not None


def test_ensure_visualization_model_clears_shape_collision_filter_pairs_before_finalize(monkeypatch):
"""The shadow model never runs collision detection, so USD-authored self-collision
filters (which scale with the number of cloned envs) must not be packed into it.
"""
from isaaclab_newton.physics import NewtonManager
from isaaclab_newton.physics import newton_manager as nm

_reset_newton_manager_state()
monkeypatch.setattr(NewtonManager, "_backend_is_newton", classmethod(lambda cls, scene_data_provider=None: False))
monkeypatch.setattr(nm, "get_current_stage", lambda *args, **kwargs: _make_env_stage())
monkeypatch.setattr(nm.PhysicsManager, "_sim", None, raising=False)
_set_sim_context(monkeypatch, nm)
monkeypatch.setattr(nm.PhysicsManager, "_device", "cpu", raising=False)

builder = _make_finalize_builder(body_count=3)
builder.shape_collision_filter_pairs = [(0, 1), (0, 2)]
monkeypatch.setattr(nm, "build_visualization_builder_from_stage_envs", lambda *args, **kwargs: (builder, ([], [])))

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.



def test_physx_shadow_model_is_rebuilt_after_physics_stop(monkeypatch):
"""Sequential PhysX scenes must not reuse the prior scene's Newton visualization model."""
from isaaclab_newton.physics import NewtonManager
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Fixed
^^^^^

* Fixed :class:`~isaaclab_newton.physics.NewtonManager` building the PhysX-backend
shadow Newton visualization model (used by Newton-native visualizers/renderers such
as viser, rerun, and Newton GL/RTX) with USD-authored self-collision filter pairs.
These pairs scale with the number of cloned environments and could reach billions
of entries, causing ``ModelBuilder.finalize()`` to run out of memory. The shadow
model never runs collision detection, so its collision filter pairs are now cleared
before finalization.
Original file line number Diff line number Diff line change
Expand Up @@ -2815,6 +2815,14 @@ def _ensure_visualization_model(cls) -> None:

device = PhysicsManager._device or "cpu"
try:
# The shadow model never runs collision detection -- body_q is overwritten every
# frame from the PhysX SceneDataProvider state, not computed by a Newton solver.
# USD-authored self-collision filters (e.g. physxArticulation:enabledSelfCollisions)
# still get imported by add_usd though, and replicated across every cloned env.
# At real env counts that PhysX tasks train with, that filter-pair set can reach
# billions of entries and blow up ModelBuilder.finalize() trying to pack it.
# Drop it before finalizing since the shadow model has no use for it.
builder.shape_collision_filter_pairs = []
NewtonManager._model = builder.finalize(device=device)
NewtonManager._state_0 = cls._model.state()
cls._model.num_envs = cls._num_envs
Expand Down
Loading