From e39376fcec28b8b980b741a5ed18f4c02288454f Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Sun, 16 Aug 2026 11:29:01 +0100 Subject: [PATCH 01/10] Fix backend factory fallback before simulator initialization Signed-off-by: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> --- .../sylvesterkaczmarek-fix-backend-fallback.rst | 5 +++++ source/isaaclab/isaaclab/utils/backend_utils.py | 6 +++++- .../test/utils/test_backend_fallback.py | 17 +++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 source/isaaclab/changelog.d/sylvesterkaczmarek-fix-backend-fallback.rst create mode 100644 source/isaaclab/test/utils/test_backend_fallback.py diff --git a/source/isaaclab/changelog.d/sylvesterkaczmarek-fix-backend-fallback.rst b/source/isaaclab/changelog.d/sylvesterkaczmarek-fix-backend-fallback.rst new file mode 100644 index 000000000000..e3e2725722bd --- /dev/null +++ b/source/isaaclab/changelog.d/sylvesterkaczmarek-fix-backend-fallback.rst @@ -0,0 +1,5 @@ +Fixed +^^^^^ + +* Fixed backend factory resolution raising before simulator initialization instead of using the documented + ``physx`` compatibility fallback when no ``SimulationContext`` exists. diff --git a/source/isaaclab/isaaclab/utils/backend_utils.py b/source/isaaclab/isaaclab/utils/backend_utils.py index ad350e3cadac..9c171e05100a 100644 --- a/source/isaaclab/isaaclab/utils/backend_utils.py +++ b/source/isaaclab/isaaclab/utils/backend_utils.py @@ -79,7 +79,11 @@ def _get_backend(cls, *args, **kwargs) -> str: # Import lazily to avoid import cycles at module load time. from isaaclab.sim.simulation_context import SimulationContext - manager_name = SimulationContext.instance().physics_manager.__name__.lower() + sim_context = SimulationContext.instance() + if sim_context is None: + return "physx" + + manager_name = sim_context.physics_manager.__name__.lower() if manager_name.startswith("newton"): return "newton" if manager_name.startswith("ovphysx"): diff --git a/source/isaaclab/test/utils/test_backend_fallback.py b/source/isaaclab/test/utils/test_backend_fallback.py new file mode 100644 index 000000000000..6b70d6aaddbc --- /dev/null +++ b/source/isaaclab/test/utils/test_backend_fallback.py @@ -0,0 +1,17 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import pytest + +from isaaclab.sim.simulation_context import SimulationContext +from isaaclab.utils.backend_utils import FactoryBase + +pytestmark = pytest.mark.unit + + +def test_factory_backend_falls_back_to_physx_without_simulation_context(monkeypatch): + monkeypatch.setattr(SimulationContext, "_instance", None) + + assert FactoryBase._get_backend() == "physx" From 84ca92bab25b1eb6f2f26982ae50c70b8f6cb591 Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Fri, 21 Aug 2026 21:57:57 +0100 Subject: [PATCH 02/10] Use Newton as pre-context backend fallback --- source/isaaclab/isaaclab/utils/backend_utils.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/isaaclab/isaaclab/utils/backend_utils.py b/source/isaaclab/isaaclab/utils/backend_utils.py index 9c171e05100a..4f0614232bcc 100644 --- a/source/isaaclab/isaaclab/utils/backend_utils.py +++ b/source/isaaclab/isaaclab/utils/backend_utils.py @@ -73,15 +73,14 @@ def register(cls, name: str, sub_class) -> None: def _get_backend(cls, *args, **kwargs) -> str: """Return active backend name for this factory. - Falls back to ``"physx"`` for backward compatibility when no simulation - context is initialized yet. + Falls back to ``"newton"`` when no simulation context is initialized yet. """ # Import lazily to avoid import cycles at module load time. from isaaclab.sim.simulation_context import SimulationContext sim_context = SimulationContext.instance() if sim_context is None: - return "physx" + return "newton" manager_name = sim_context.physics_manager.__name__.lower() if manager_name.startswith("newton"): From 48ab329c6e957803b6997cce2560e8db3a986a03 Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Fri, 21 Aug 2026 21:58:05 +0100 Subject: [PATCH 03/10] Update backend fallback regression for Newton --- source/isaaclab/test/utils/test_backend_fallback.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/isaaclab/test/utils/test_backend_fallback.py b/source/isaaclab/test/utils/test_backend_fallback.py index 6b70d6aaddbc..a25e30ffe305 100644 --- a/source/isaaclab/test/utils/test_backend_fallback.py +++ b/source/isaaclab/test/utils/test_backend_fallback.py @@ -11,7 +11,7 @@ pytestmark = pytest.mark.unit -def test_factory_backend_falls_back_to_physx_without_simulation_context(monkeypatch): +def test_factory_backend_falls_back_to_newton_without_simulation_context(monkeypatch): monkeypatch.setattr(SimulationContext, "_instance", None) - assert FactoryBase._get_backend() == "physx" + assert FactoryBase._get_backend() == "newton" From 9a5d31046d40563f0d031faa57aa6961b093f992 Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Fri, 21 Aug 2026 21:58:14 +0100 Subject: [PATCH 04/10] Document Newton pre-context backend fallback --- .../changelog.d/sylvesterkaczmarek-fix-backend-fallback.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/isaaclab/changelog.d/sylvesterkaczmarek-fix-backend-fallback.rst b/source/isaaclab/changelog.d/sylvesterkaczmarek-fix-backend-fallback.rst index e3e2725722bd..5414a814009f 100644 --- a/source/isaaclab/changelog.d/sylvesterkaczmarek-fix-backend-fallback.rst +++ b/source/isaaclab/changelog.d/sylvesterkaczmarek-fix-backend-fallback.rst @@ -1,5 +1,5 @@ Fixed ^^^^^ -* Fixed backend factory resolution raising before simulator initialization instead of using the documented - ``physx`` compatibility fallback when no ``SimulationContext`` exists. +* Fixed backend factory resolution raising before simulator initialization by using the team-confirmed ``newton`` + fallback when no ``SimulationContext`` exists. From 7871d6ee1f4adf627f0faf2a34acc3516362ff98 Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Sat, 22 Aug 2026 11:39:29 +0100 Subject: [PATCH 05/10] test: move backend fallback coverage into backend utils tests --- source/isaaclab/test/utils/test_backend_utils.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/isaaclab/test/utils/test_backend_utils.py b/source/isaaclab/test/utils/test_backend_utils.py index 0b056ffa2f52..a9ef64ddab69 100644 --- a/source/isaaclab/test/utils/test_backend_utils.py +++ b/source/isaaclab/test/utils/test_backend_utils.py @@ -5,6 +5,7 @@ """Tests for backend module resolution.""" +from isaaclab.sim.simulation_context import SimulationContext from isaaclab.utils.backend_utils import FactoryBase @@ -24,3 +25,9 @@ def test_get_module_name_preserves_other_backend_conventions(monkeypatch): assert FactoryBase._get_package_name("newton") == "isaaclab_newton" assert FactoryBase._get_module_name("physx") == "isaaclab_physx.assets.articulation" assert FactoryBase._get_module_name("newton") == "isaaclab_newton.assets.articulation" + +def test_factory_backend_falls_back_to_newton_without_simulation_context(monkeypatch): + """Backend resolution uses Newton before a simulation context exists.""" + monkeypatch.setattr(SimulationContext, "_instance", None) + + assert FactoryBase._get_backend() == "newton" From a5abd95ef97da5af54462611b2ed60c106507f70 Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Sat, 22 Aug 2026 11:39:34 +0100 Subject: [PATCH 06/10] test: remove standalone backend fallback test file --- .../test/utils/test_backend_fallback.py | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 source/isaaclab/test/utils/test_backend_fallback.py diff --git a/source/isaaclab/test/utils/test_backend_fallback.py b/source/isaaclab/test/utils/test_backend_fallback.py deleted file mode 100644 index a25e30ffe305..000000000000 --- a/source/isaaclab/test/utils/test_backend_fallback.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). -# All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause - -import pytest - -from isaaclab.sim.simulation_context import SimulationContext -from isaaclab.utils.backend_utils import FactoryBase - -pytestmark = pytest.mark.unit - - -def test_factory_backend_falls_back_to_newton_without_simulation_context(monkeypatch): - monkeypatch.setattr(SimulationContext, "_instance", None) - - assert FactoryBase._get_backend() == "newton" From 0fbeb516da589bceb83c41c110ce8b51eeafe66c Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Sat, 22 Aug 2026 11:40:10 +0100 Subject: [PATCH 07/10] style: separate backend utility tests --- source/isaaclab/test/utils/test_backend_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/source/isaaclab/test/utils/test_backend_utils.py b/source/isaaclab/test/utils/test_backend_utils.py index a9ef64ddab69..dae867231f8b 100644 --- a/source/isaaclab/test/utils/test_backend_utils.py +++ b/source/isaaclab/test/utils/test_backend_utils.py @@ -26,6 +26,7 @@ def test_get_module_name_preserves_other_backend_conventions(monkeypatch): assert FactoryBase._get_module_name("physx") == "isaaclab_physx.assets.articulation" assert FactoryBase._get_module_name("newton") == "isaaclab_newton.assets.articulation" + def test_factory_backend_falls_back_to_newton_without_simulation_context(monkeypatch): """Backend resolution uses Newton before a simulation context exists.""" monkeypatch.setattr(SimulationContext, "_instance", None) From cd112ef7dfe604fdab16c7c1f6772c47abaa6933 Mon Sep 17 00:00:00 2001 From: Octi Zhang Date: Sat, 22 Aug 2026 04:53:03 -0700 Subject: [PATCH 08/10] Remove stale pre-context visualizer assertion --- source/isaaclab/test/visualizers/test_visualizer.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/source/isaaclab/test/visualizers/test_visualizer.py b/source/isaaclab/test/visualizers/test_visualizer.py index b78d802aae94..876a9f35fc08 100644 --- a/source/isaaclab/test/visualizers/test_visualizer.py +++ b/source/isaaclab/test/visualizers/test_visualizer.py @@ -245,9 +245,3 @@ def test_resolve_camera_pose_from_usd_path_uses_provider_transforms(): pos, target = viz._resolve_camera_pose_from_usd_path("/World/envs/env_0/Camera") assert pos == (1.0, 2.0, 3.0) assert target == pytest.approx((1.0, 2.0, 2.0)) - - -def test_physics_backend_returns_none_without_simulation_context(): - """physics_backend is None when no SimulationContext is active.""" - viz = _DummyVisualizer(_make_cfg()) - assert viz.physics_backend is None From c6854badb9ad9618004e407b04294ef42735adce Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Sat, 22 Aug 2026 15:49:29 +0100 Subject: [PATCH 09/10] fix: preserve visualizer backend contract before context --- source/isaaclab/isaaclab/visualizers/base_visualizer.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/isaaclab/isaaclab/visualizers/base_visualizer.py b/source/isaaclab/isaaclab/visualizers/base_visualizer.py index b76417a55abb..5dc259a3950d 100644 --- a/source/isaaclab/isaaclab/visualizers/base_visualizer.py +++ b/source/isaaclab/isaaclab/visualizers/base_visualizer.py @@ -153,8 +153,11 @@ def physics_backend(self) -> str | None: Backend name string, or ``None`` when no simulation context is active yet. """ try: + from isaaclab.sim.simulation_context import SimulationContext from isaaclab.utils.backend_utils import FactoryBase + if SimulationContext.instance() is None: + return None return FactoryBase._get_backend() except Exception: return None From 1d9764b69020672dfb2f61d2333688b53a7b83d5 Mon Sep 17 00:00:00 2001 From: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com> Date: Sat, 22 Aug 2026 15:49:36 +0100 Subject: [PATCH 10/10] test: retain pre-context visualizer coverage --- source/isaaclab/test/visualizers/test_visualizer.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/isaaclab/test/visualizers/test_visualizer.py b/source/isaaclab/test/visualizers/test_visualizer.py index 876a9f35fc08..b78d802aae94 100644 --- a/source/isaaclab/test/visualizers/test_visualizer.py +++ b/source/isaaclab/test/visualizers/test_visualizer.py @@ -245,3 +245,9 @@ def test_resolve_camera_pose_from_usd_path_uses_provider_transforms(): pos, target = viz._resolve_camera_pose_from_usd_path("/World/envs/env_0/Camera") assert pos == (1.0, 2.0, 3.0) assert target == pytest.approx((1.0, 2.0, 2.0)) + + +def test_physics_backend_returns_none_without_simulation_context(): + """physics_backend is None when no SimulationContext is active.""" + viz = _DummyVisualizer(_make_cfg()) + assert viz.physics_backend is None