From 412cac4340e192f0db07227238ba7c308c89bd64 Mon Sep 17 00:00:00 2001 From: Octi Zhang Date: Thu, 17 Sep 2026 04:15:25 -0700 Subject: [PATCH 1/3] Preserve instanced visuals when cloning active OVRTX sources --- .../fix-legacy-ovrtx-instance-cloning.rst | 6 +++ .../isaaclab_ov/renderers/ovrtx_renderer.py | 9 ++-- .../isaaclab_ov/renderers/ovrtx_usd.py | 13 ++++-- .../isaaclab_ov/test/test_ovrtx_clone_plan.py | 29 +++++++++++++ source/isaaclab_ov/test/test_ovrtx_usd.py | 42 ++++++++++++++++++- 5 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst diff --git a/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst b/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst new file mode 100644 index 000000000000..89726882fc2b --- /dev/null +++ b/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst @@ -0,0 +1,6 @@ +Fixed +^^^^^ + +* Fixed missing cloned visuals in the legacy OVRTX renderer by expanding nested USD instances + in its exported clone sources. Simulation stages and the ovstage renderer path retained + their original instancing. diff --git a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py index 641aa4af78a9..d7cdd9b28619 100644 --- a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py +++ b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py @@ -440,12 +440,15 @@ def prepare_stage(self, stage: Any, num_envs: int) -> None: # Composed scales must be read while the full stage is still live, before export trims it. self._capture_object_scales(stage, self._clone_plan) - # The clone plan already identifies every source row. Keep those rows independent so - # backend bindings for dynamic assets retain the paths they were compiled against. + # Unused variant rows retain placeholder source paths but have no spawned prim. + # Keep active rows independent so dynamic assets retain their compiled binding paths. + active_sources = tuple( + path for path, mask in zip(self._clone_plan.sources, self._clone_plan.clone_mask, strict=True) if mask.any() + ) self._exported_usd_string = export_stage_to_string( stage, num_envs, - source_paths=self._clone_plan.sources, + source_paths=active_sources, keep_env_roots=not self._use_ovstage, ) diff --git a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py index 2d008bd25e1e..891a9e9c0a7d 100644 --- a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py +++ b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py @@ -14,6 +14,8 @@ from pxr import Sdf, Usd, UsdGeom +from isaaclab.sim.utils import make_uninstanceable + logger = logging.getLogger(__name__) @@ -426,9 +428,10 @@ def export_stage_to_string( anonymous session layer used only for export, so the input stage remains unchanged. When ``keep_env_roots`` is True (the legacy ``renderer.clone_usd`` path) the non-source env root prims stay - active so the exported stage retains a slot for every env. The ovstage ``stage.clone`` path passes False, which - additionally trims the non-source env roots themselves; ``stage.clone`` recreates them and the RenderProduct's - camera relationship is re-authored after clone. + active so the exported stage retains a slot for every env. Nested instances in source subtrees are expanded + on the export session because legacy cloning otherwise drops their geometry. The ovstage ``stage.clone`` + path passes False, retaining source instancing and trimming the non-source env roots themselves; + ``stage.clone`` recreates them and the RenderProduct's camera relationship is re-authored after clone. Args: stage: USD stage to export. @@ -455,6 +458,10 @@ def export_stage_to_string( prim_paths: list[Sdf.Path] = [] if keep_env_roots: + # Native legacy cloning omits instanced visuals; expand only the renderer's copy. + with Usd.EditContext(export_stage, export_session): + for source_path in source_paths: + make_uninstanceable(source_path, stage=export_stage) for child in envs_prim.GetChildren(): # Legacy code path: keep env roots so we can query their xforms after opening stage child_path = child.GetPath() diff --git a/source/isaaclab_ov/test/test_ovrtx_clone_plan.py b/source/isaaclab_ov/test/test_ovrtx_clone_plan.py index c5d215ecc82d..265e8d201d39 100644 --- a/source/isaaclab_ov/test/test_ovrtx_clone_plan.py +++ b/source/isaaclab_ov/test/test_ovrtx_clone_plan.py @@ -350,6 +350,35 @@ def test_prepare_stage_rejects_non_dense_environment_ids(monkeypatch: pytest.Mon _make_ovrtx_renderer_without_backend().prepare_stage(_make_multi_env_stage(2), 2) +@pytest.mark.parametrize("use_ovstage", [False, True]) +def test_prepare_stage_ignores_unspawned_variant_sources(monkeypatch: pytest.MonkeyPatch, use_ovstage: bool): + """Unused variants retain plan rows but have no source prim to export.""" + num_envs, num_variants = 4, 16 + stage = _make_multi_env_stage(num_envs) + plan = ClonePlan( + sources=tuple(f"/World/envs/env_{index}/Robot" for index in range(num_variants)), + destinations=("/World/envs/env_{}/Robot",) * num_variants, + clone_mask=np.eye(num_variants, num_envs, dtype=np.bool_), + env_ids=np.arange(num_envs, dtype=np.int64), + positions=np.zeros((num_envs, 3), dtype=np.float32), + ) + _patch_simulation_context(monkeypatch, plan) + renderer = _make_ovrtx_renderer_without_backend() + renderer._use_ovstage = use_ovstage + + renderer.prepare_stage(stage, num_envs) + + exported_layer = Sdf.Layer.CreateAnonymous(".usda") + assert exported_layer.ImportFromString(renderer._exported_usd_string) + exported_stage = Usd.Stage.Open(exported_layer) + for source in plan.sources[:num_envs]: + assert exported_stage.GetPrimAtPath(source) + for source in plan.sources[num_envs:]: + assert not exported_stage.GetPrimAtPath(source) + assert renderer._clone_plan is plan + assert len(plan.sources) == num_variants + + def test_capture_object_scales_populates_source_and_destination_scale_array(): """Projected source scales reach the body array without replacing a real destination scale.""" stage = Usd.Stage.CreateInMemory() diff --git a/source/isaaclab_ov/test/test_ovrtx_usd.py b/source/isaaclab_ov/test/test_ovrtx_usd.py index 1dc05838c820..d45cc07e059b 100644 --- a/source/isaaclab_ov/test/test_ovrtx_usd.py +++ b/source/isaaclab_ov/test/test_ovrtx_usd.py @@ -430,8 +430,8 @@ def test_export_stage_without_keep_env_roots_trims_non_source_env_roots(): """The ovstage clone path also trims the non-source env roots themselves. ``ovstage.Stage.clone`` requires every target path to not already exist, so the exported stage - must not retain env roots that the clone will recreate. This is the only difference from the - legacy ``renderer.clone_usd`` path, which keeps the roots as placeholders. + must not retain env roots that the clone will recreate. The legacy ``renderer.clone_usd`` + path keeps the roots as placeholders. """ num_envs = 4 stage = _make_multi_env_stage(num_envs) @@ -494,6 +494,44 @@ def test_export_stage_restores_active_state(): assert stage.GetPrimAtPath(f"{env_path}/Object_env{env_idx}_only").IsActive() +@pytest.mark.parametrize( + ("num_envs", "keep_env_roots", "keep_instances"), + [(4, True, False), (4, False, True), (1, True, True), (1, False, True)], +) +def test_export_stage_expands_nested_instances_only_for_legacy_cloning(num_envs, keep_env_roots, keep_instances): + """Legacy cloning receives concrete geometry without changing the simulation's instancing.""" + stage = _make_multi_env_stage(num_envs) + mesh = UsdGeom.Mesh.Define(stage, "/MeshPrototype/Mesh") + mesh.CreatePointsAttr([(0, 0, 0), (1, 0, 0), (0, 1, 0)]) + mesh.CreateFaceVertexCountsAttr([3]) + mesh.CreateFaceVertexIndicesAttr([0, 1, 2]) + visuals = UsdGeom.Xform.Define(stage, "/RobotPrototype/Visuals").GetPrim() + visuals.GetReferences().AddInternalReference("/MeshPrototype") + visuals.SetInstanceable(True) + robot_path = "/World/envs/env_0/Robot" + robot = stage.GetPrimAtPath(robot_path) + robot.GetReferences().AddInternalReference("/RobotPrototype") + robot.SetInstanceable(True) + mesh_path = f"{robot_path}/Visuals/Mesh" + assert robot.IsInstance() + assert stage.GetPrimAtPath(mesh_path).IsInstanceProxy() + input_layers = [layer.ExportToString() for layer in stage.GetLayerStack()] + + exported = export_stage_to_string(stage, num_envs, ("/World/envs/env_0",), keep_env_roots) + exported_layer = Sdf.Layer.CreateAnonymous("exported.usda") + exported_layer.ImportFromString(exported) + exported_stage = Usd.Stage.Open(exported_layer) + + assert exported_stage.GetPrimAtPath(robot_path).IsInstance() == keep_instances + assert exported_stage.GetPrimAtPath(f"{robot_path}/Visuals").IsInstanceable() == keep_instances + exported_mesh = exported_stage.GetPrimAtPath(mesh_path) + assert exported_mesh.IsInstanceProxy() == keep_instances + assert UsdGeom.Mesh(exported_mesh).GetPointsAttr().Get() == mesh.GetPointsAttr().Get() + assert [layer.ExportToString() for layer in stage.GetLayerStack()] == input_layers + assert robot.IsInstance() + assert stage.GetPrimAtPath(mesh_path).IsInstanceProxy() + + def test_create_scene_partition_attributes_all_envs(): """Scene partition attributes are authored on every env root and camera.""" num_envs = 4 From 578e6e0d1df1c51dc52cee7db3f75172119e5d44 Mon Sep 17 00:00:00 2001 From: Maximilian Krause Date: Thu, 17 Sep 2026 18:09:48 +0200 Subject: [PATCH 2/3] Default OVRTX to ovstage cloning --- .../changelog.d/fix-legacy-ovrtx-instance-cloning.rst | 6 ++++++ .../isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py | 8 ++++---- source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py | 3 ++- source/isaaclab_ov/test/test_ovrtx_renderer_contract.py | 6 +++--- .../changelog.d/default-ovstage-render-tests.skip | 0 source/isaaclab_tasks/test/conftest.py | 6 ++---- source/isaaclab_tasks/test/rendering_test_utils.py | 2 +- 7 files changed, 18 insertions(+), 13 deletions(-) create mode 100644 source/isaaclab_tasks/changelog.d/default-ovstage-render-tests.skip diff --git a/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst b/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst index 89726882fc2b..1b5f094e75f9 100644 --- a/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst +++ b/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst @@ -1,3 +1,9 @@ +Changed +^^^^^^^ + +* Changed OVRTX to use ovstage scene ownership by default, preserving USD instancing and avoiding + legacy clone expansion costs. Set ``ISAAC_LAB_OVRTX_USE_OVSTAGE=0`` to retain the legacy path. + Fixed ^^^^^ diff --git a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py index d7cdd9b28619..89035fd54902 100644 --- a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py +++ b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py @@ -148,7 +148,7 @@ _READ_GPU_TRANSFORMS_ENV = "ISAAC_LAB_OVRTX_READ_GPU_TRANSFORMS" -# Runtime environment variable used to enable the ovstage code path for ovrtx. +# Runtime environment variable used to select the ovstage or legacy OVRTX path. _USE_OVSTAGE_ENV = "ISAAC_LAB_OVRTX_USE_OVSTAGE" @@ -160,13 +160,13 @@ def ovrtx_use_ovstage_enabled() -> bool: """Return whether the ovstage scene-ownership path should be used. - Enabled by ``ISAAC_LAB_OVRTX_USE_OVSTAGE=1``. Defaults to ``0`` so existing deployments are - unaffected until ovstage is explicitly opted into. + Ovstage is enabled by default. Set ``ISAAC_LAB_OVRTX_USE_OVSTAGE=0`` to use the legacy + renderer-owned stage path. Raises: ValueError: If the environment variable is set to anything other than ``0`` or ``1``. """ - value = os.environ.get(_USE_OVSTAGE_ENV, "0").strip() + value = os.environ.get(_USE_OVSTAGE_ENV, "1").strip() if value not in {"0", "1"}: raise ValueError(f"Invalid value for environment variable `{_USE_OVSTAGE_ENV}`: {value}. Expected 0 or 1.") return value == "1" diff --git a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py index 891a9e9c0a7d..9412ba095ca1 100644 --- a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py +++ b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py @@ -458,7 +458,8 @@ def export_stage_to_string( prim_paths: list[Sdf.Path] = [] if keep_env_roots: - # Native legacy cloning omits instanced visuals; expand only the renderer's copy. + # Legacy ``renderer.clone_usd`` does not preserve nested instances. Expand them in the + # temporary export before OVRTX loads and clones it, without modifying the simulation stage. with Usd.EditContext(export_stage, export_session): for source_path in source_paths: make_uninstanceable(source_path, stage=export_stage) diff --git a/source/isaaclab_ov/test/test_ovrtx_renderer_contract.py b/source/isaaclab_ov/test/test_ovrtx_renderer_contract.py index 487ba5d76461..df25fc9f02ec 100644 --- a/source/isaaclab_ov/test/test_ovrtx_renderer_contract.py +++ b/source/isaaclab_ov/test/test_ovrtx_renderer_contract.py @@ -382,10 +382,10 @@ def test_ovrtx_instance_segmentation_spec_follows_colorize_flag(): ) -def test_ovrtx_use_ovstage_defaults_to_disabled(monkeypatch): - """The ovstage path is off unless explicitly opted into, so existing deployments are unaffected.""" +def test_ovrtx_use_ovstage_defaults_to_enabled(monkeypatch): + """The ovstage path is used by default while the legacy path remains an explicit fallback.""" monkeypatch.delenv("ISAAC_LAB_OVRTX_USE_OVSTAGE", raising=False) - assert ovrtx_use_ovstage_enabled() is False + assert ovrtx_use_ovstage_enabled() is True monkeypatch.setenv("ISAAC_LAB_OVRTX_USE_OVSTAGE", "0") assert ovrtx_use_ovstage_enabled() is False diff --git a/source/isaaclab_tasks/changelog.d/default-ovstage-render-tests.skip b/source/isaaclab_tasks/changelog.d/default-ovstage-render-tests.skip new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/source/isaaclab_tasks/test/conftest.py b/source/isaaclab_tasks/test/conftest.py index 197139877399..d7819bdd3b64 100644 --- a/source/isaaclab_tasks/test/conftest.py +++ b/source/isaaclab_tasks/test/conftest.py @@ -27,8 +27,6 @@ def ovstage_variant(request, monkeypatch): if request.param == "ovstage": monkeypatch.setenv("ISAAC_LAB_OVRTX_USE_OVSTAGE", "1") else: - # Clear explicitly rather than relying on the variable being unset. An ambient - # ISAAC_LAB_OVRTX_USE_OVSTAGE=1 would otherwise make both variants exercise the ovstage - # path, silently dropping legacy coverage while still reporting two passing variants. - monkeypatch.delenv("ISAAC_LAB_OVRTX_USE_OVSTAGE", raising=False) + # Select legacy explicitly so both variants retain coverage when ovstage is the default. + monkeypatch.setenv("ISAAC_LAB_OVRTX_USE_OVSTAGE", "0") return request.param diff --git a/source/isaaclab_tasks/test/rendering_test_utils.py b/source/isaaclab_tasks/test/rendering_test_utils.py index e3f6eba486ba..fa9a6d4c73b0 100644 --- a/source/isaaclab_tasks/test/rendering_test_utils.py +++ b/source/isaaclab_tasks/test/rendering_test_utils.py @@ -1327,7 +1327,7 @@ def _alpha_only(img: Image.Image) -> Image.Image: "test": test_name, "backend": physics_backend, "renderer": renderer, - "ovstage_variant": "Yes" if os.environ.get("ISAAC_LAB_OVRTX_USE_OVSTAGE") == "1" else "No", + "ovstage_variant": "Yes" if os.environ.get("ISAAC_LAB_OVRTX_USE_OVSTAGE", "1") == "1" else "No", "aov": data_type, "diff_pct": diff_pct, "ssim": ssim_score, From 0280116cc96703da314cfad6f9585727d00e4e01 Mon Sep 17 00:00:00 2001 From: Maximilian Krause Date: Thu, 17 Sep 2026 18:38:28 +0200 Subject: [PATCH 3/3] Revert "Default OVRTX to ovstage cloning" This reverts commit 578e6e0d1df1c51dc52cee7db3f75172119e5d44. --- .../changelog.d/fix-legacy-ovrtx-instance-cloning.rst | 6 ------ .../isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py | 8 ++++---- source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py | 3 +-- source/isaaclab_ov/test/test_ovrtx_renderer_contract.py | 6 +++--- .../changelog.d/default-ovstage-render-tests.skip | 0 source/isaaclab_tasks/test/conftest.py | 6 ++++-- source/isaaclab_tasks/test/rendering_test_utils.py | 2 +- 7 files changed, 13 insertions(+), 18 deletions(-) delete mode 100644 source/isaaclab_tasks/changelog.d/default-ovstage-render-tests.skip diff --git a/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst b/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst index 1b5f094e75f9..89726882fc2b 100644 --- a/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst +++ b/source/isaaclab_ov/changelog.d/fix-legacy-ovrtx-instance-cloning.rst @@ -1,9 +1,3 @@ -Changed -^^^^^^^ - -* Changed OVRTX to use ovstage scene ownership by default, preserving USD instancing and avoiding - legacy clone expansion costs. Set ``ISAAC_LAB_OVRTX_USE_OVSTAGE=0`` to retain the legacy path. - Fixed ^^^^^ diff --git a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py index 89035fd54902..d7cdd9b28619 100644 --- a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py +++ b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py @@ -148,7 +148,7 @@ _READ_GPU_TRANSFORMS_ENV = "ISAAC_LAB_OVRTX_READ_GPU_TRANSFORMS" -# Runtime environment variable used to select the ovstage or legacy OVRTX path. +# Runtime environment variable used to enable the ovstage code path for ovrtx. _USE_OVSTAGE_ENV = "ISAAC_LAB_OVRTX_USE_OVSTAGE" @@ -160,13 +160,13 @@ def ovrtx_use_ovstage_enabled() -> bool: """Return whether the ovstage scene-ownership path should be used. - Ovstage is enabled by default. Set ``ISAAC_LAB_OVRTX_USE_OVSTAGE=0`` to use the legacy - renderer-owned stage path. + Enabled by ``ISAAC_LAB_OVRTX_USE_OVSTAGE=1``. Defaults to ``0`` so existing deployments are + unaffected until ovstage is explicitly opted into. Raises: ValueError: If the environment variable is set to anything other than ``0`` or ``1``. """ - value = os.environ.get(_USE_OVSTAGE_ENV, "1").strip() + value = os.environ.get(_USE_OVSTAGE_ENV, "0").strip() if value not in {"0", "1"}: raise ValueError(f"Invalid value for environment variable `{_USE_OVSTAGE_ENV}`: {value}. Expected 0 or 1.") return value == "1" diff --git a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py index 9412ba095ca1..891a9e9c0a7d 100644 --- a/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py +++ b/source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py @@ -458,8 +458,7 @@ def export_stage_to_string( prim_paths: list[Sdf.Path] = [] if keep_env_roots: - # Legacy ``renderer.clone_usd`` does not preserve nested instances. Expand them in the - # temporary export before OVRTX loads and clones it, without modifying the simulation stage. + # Native legacy cloning omits instanced visuals; expand only the renderer's copy. with Usd.EditContext(export_stage, export_session): for source_path in source_paths: make_uninstanceable(source_path, stage=export_stage) diff --git a/source/isaaclab_ov/test/test_ovrtx_renderer_contract.py b/source/isaaclab_ov/test/test_ovrtx_renderer_contract.py index df25fc9f02ec..487ba5d76461 100644 --- a/source/isaaclab_ov/test/test_ovrtx_renderer_contract.py +++ b/source/isaaclab_ov/test/test_ovrtx_renderer_contract.py @@ -382,10 +382,10 @@ def test_ovrtx_instance_segmentation_spec_follows_colorize_flag(): ) -def test_ovrtx_use_ovstage_defaults_to_enabled(monkeypatch): - """The ovstage path is used by default while the legacy path remains an explicit fallback.""" +def test_ovrtx_use_ovstage_defaults_to_disabled(monkeypatch): + """The ovstage path is off unless explicitly opted into, so existing deployments are unaffected.""" monkeypatch.delenv("ISAAC_LAB_OVRTX_USE_OVSTAGE", raising=False) - assert ovrtx_use_ovstage_enabled() is True + assert ovrtx_use_ovstage_enabled() is False monkeypatch.setenv("ISAAC_LAB_OVRTX_USE_OVSTAGE", "0") assert ovrtx_use_ovstage_enabled() is False diff --git a/source/isaaclab_tasks/changelog.d/default-ovstage-render-tests.skip b/source/isaaclab_tasks/changelog.d/default-ovstage-render-tests.skip deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/source/isaaclab_tasks/test/conftest.py b/source/isaaclab_tasks/test/conftest.py index d7819bdd3b64..197139877399 100644 --- a/source/isaaclab_tasks/test/conftest.py +++ b/source/isaaclab_tasks/test/conftest.py @@ -27,6 +27,8 @@ def ovstage_variant(request, monkeypatch): if request.param == "ovstage": monkeypatch.setenv("ISAAC_LAB_OVRTX_USE_OVSTAGE", "1") else: - # Select legacy explicitly so both variants retain coverage when ovstage is the default. - monkeypatch.setenv("ISAAC_LAB_OVRTX_USE_OVSTAGE", "0") + # Clear explicitly rather than relying on the variable being unset. An ambient + # ISAAC_LAB_OVRTX_USE_OVSTAGE=1 would otherwise make both variants exercise the ovstage + # path, silently dropping legacy coverage while still reporting two passing variants. + monkeypatch.delenv("ISAAC_LAB_OVRTX_USE_OVSTAGE", raising=False) return request.param diff --git a/source/isaaclab_tasks/test/rendering_test_utils.py b/source/isaaclab_tasks/test/rendering_test_utils.py index fa9a6d4c73b0..e3f6eba486ba 100644 --- a/source/isaaclab_tasks/test/rendering_test_utils.py +++ b/source/isaaclab_tasks/test/rendering_test_utils.py @@ -1327,7 +1327,7 @@ def _alpha_only(img: Image.Image) -> Image.Image: "test": test_name, "backend": physics_backend, "renderer": renderer, - "ovstage_variant": "Yes" if os.environ.get("ISAAC_LAB_OVRTX_USE_OVSTAGE", "1") == "1" else "No", + "ovstage_variant": "Yes" if os.environ.get("ISAAC_LAB_OVRTX_USE_OVSTAGE") == "1" else "No", "aov": data_type, "diff_pct": diff_pct, "ssim": ssim_score,