@@ -214,6 +214,18 @@ def _usd_replicate(stage, *args, **kwargs):
214214 assert len (set_plan_calls ) == 1
215215
216216
217+ def test_clone_environments_skips_replication_without_plan ():
218+ """Direct-path cfg scenes publish no plan and do not dispatch cloners."""
219+ scene = object .__new__ (InteractiveScene )
220+ scene ._clone_plan = None
221+ set_plan_calls = []
222+ scene .sim = SimpleNamespace (set_clone_plan = set_plan_calls .append )
223+
224+ scene .clone_environments (copy_from_source = False )
225+
226+ assert set_plan_calls == [None ]
227+
228+
217229def test_clone_environments_executes_asset_level_plan_without_usd_positions (monkeypatch : pytest .MonkeyPatch ):
218230 """Asset-level plans preserve env-root transforms by skipping USD positions."""
219231 from isaaclab .cloner import ClonePlan
@@ -290,6 +302,7 @@ def test_build_clone_plan_from_cfg_plans_multi_and_single_spawners(monkeypatch:
290302
291303 plan = scene ._build_clone_plan_from_cfg ()
292304
305+ assert plan is not None
293306 assert plan .sources == [
294307 "/World/envs/env_0/Object" ,
295308 "/World/envs/env_1/Object" ,
@@ -325,12 +338,33 @@ def test_build_clone_plan_from_cfg_defaults_to_env0_plan(monkeypatch: pytest.Mon
325338
326339 plan = scene ._build_clone_plan_from_cfg ()
327340
341+ assert plan is not None
328342 assert plan .sources == ["/World/envs/env_0" ]
329343 assert plan .destinations == [scene .env_fmt ]
330344 assert plan .clone_mask .shape == (1 , scene .num_envs )
331345 assert scene .cfg .robot .spawn .spawn_path == "/World/envs/env_0/Robot"
332346
333347
348+ def test_build_clone_plan_from_cfg_returns_none_without_env_scoped_groups (monkeypatch : pytest .MonkeyPatch ):
349+ """Direct-path cfg scenes should not force env-root replication."""
350+ from isaaclab .cloner import sequential
351+
352+ scene = object .__new__ (InteractiveScene )
353+ scene .cfg = SimpleNamespace (
354+ num_envs = 1 ,
355+ robot = SimpleNamespace (
356+ prim_path = "/World/Robot" ,
357+ spawn = sim_utils .CuboidCfg (size = (0.1 , 0.1 , 0.1 )),
358+ ),
359+ )
360+ scene .env_fmt = "/World/envs/env_{}"
361+ scene .cloner_cfg = SimpleNamespace (clone_strategy = sequential )
362+ monkeypatch .setattr (InteractiveScene , "device" , property (lambda self : "cpu" ))
363+
364+ assert scene ._build_clone_plan_from_cfg () is None
365+ assert scene .cfg .robot .spawn .spawn_path is None
366+
367+
334368def test_build_clone_plan_from_cfg_sets_collection_member_paths (monkeypatch : pytest .MonkeyPatch ):
335369 """Rigid object collection members are planned independently."""
336370 from isaaclab .cloner import sequential
@@ -356,6 +390,7 @@ def test_build_clone_plan_from_cfg_sets_collection_member_paths(monkeypatch: pyt
356390
357391 plan = scene ._build_clone_plan_from_cfg ()
358392
393+ assert plan is not None
359394 planned_cube = scene .cfg .objects .rigid_objects ["cube" ]
360395 planned_shape = scene .cfg .objects .rigid_objects ["shape" ]
361396 assert planned_cube .spawn .spawn_path == "/World/envs/env_0/Cube"
@@ -388,6 +423,7 @@ def test_build_clone_plan_from_cfg_marks_unused_variants(monkeypatch: pytest.Mon
388423
389424 plan = scene ._build_clone_plan_from_cfg ()
390425
426+ assert plan is not None
391427 assert scene .cfg .object .spawn .spawn_paths == ["/World/envs/env_0/Object" , "/World/envs/env_1/Object" , None ]
392428 assert plan .clone_mask [2 ].sum () == 0
393429
0 commit comments