Skip to content

skip usd cloning in pure newton path (#5743)#5872

Merged
kellyguo11 merged 1 commit into
isaac-sim:release/3.0.0-beta2from
ooctipus:cherrypick/newton_skip_usd_cloning
May 30, 2026
Merged

skip usd cloning in pure newton path (#5743)#5872
kellyguo11 merged 1 commit into
isaac-sim:release/3.0.0-beta2from
ooctipus:cherrypick/newton_skip_usd_cloning

Conversation

@ooctipus
Copy link
Copy Markdown
Collaborator

No description provided.

# Description

Fixes Newton replicated-scene cloning so clone-plan source paths are
available before sensor construction and asset USD replication is
skipped when Newton handles physics replication.

This also updates Newton frame views, ray caster and joint wrench sensor
resolution, Newton camera preparation, deformable managers, and DexSuite
point-cloud sampling to resolve against clone-plan source prims and
Newton model labels instead of cloned destination USD prims.

Fixes # N/A

## Type of change

- Bug fix (non-breaking change which fixes an issue)

## Screenshots

N/A

## Validation

- `./isaaclab.sh -f` was attempted. It passed ruff, formatting,
whitespace, YAML/TOML, merge-conflict, private-key, debug-statement,
codespell, license, and RST checks before failing in `end-of-file-fixer`
with `PermissionError` on root-owned files in this checkout. The working
tree remained clean after the attempt.
- `git diff --check upstream/develop...HEAD` passed.

## Checklist

- [x] I have read and understood the [contribution
guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html)
- [ ] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] I have added a changelog fragment under
`source/<pkg>/changelog.d/` for every touched package (do **not** edit
`CHANGELOG.rst` or bump `extension.toml` -- CI handles that)
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there
@github-actions github-actions Bot added documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team labels May 29, 2026
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

🤖 Isaac Lab Review Bot

Cherry-Pick Review: #5743 → release/3.0.0-beta2

This PR is a cherry-pick of #5743 (merged to develop on 2026-05-29) to the release/3.0.0-beta2 branch.

✅ Cherry-Pick Assessment

Check Status
Single commit (clean cherry-pick)
Pre-commit checks ✅ Passed
Changelog fragments added ✅ Passed
CI checks ⏳ In progress (critical checks passed)

📋 Change Summary

This cherry-pick brings Newton replicated-scene cloning improvements to the release branch:

  • Core fix: Clone-plan source paths available before sensor construction
  • USD replication skip: Newton handles physics replication internally
  • Updated components: Newton frame views, ray caster, joint wrench sensor, camera preparation, deformable managers, DexSuite point-cloud sampling
  • 58 files changed across isaaclab, isaaclab_newton, isaaclab_physx, isaaclab_ovphysx, isaaclab_contrib, and isaaclab_tasks

🔍 Release Branch Appropriateness

Appropriate for release branch because:

  • Bug fix type change (non-breaking)
  • Already validated on develop branch
  • Includes proper changelog fragments
  • Has test coverage additions

Verdict

LGTM 👍 - Clean cherry-pick of a validated fix. Ready for release branch integration pending CI completion.


Automated review by Isaac Lab Review Bot

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 29, 2026

Greptile Summary

This PR skips USD prim cloning in the pure-Newton (headless, no-Kit) code path, avoiding the overhead of replicating USD stage structure that Newton doesn't need for physics simulation. It also introduces three plan-aware prim-resolution helpers (get_suffix, resolve_clone_plan_source, iter_clone_plan_matches) and a new per_world site type so sensors at env-root level are correctly injected per Newton world.

  • USD clone bypass: InteractiveScene sets clone_usd=not is_newton_replicated_scene or has_kit(), and all asset/sensor _initialize_impl paths are switched from find_first_matching_prim to the new resolve_matching_prims_from_source utility so they find source prims even when destination USD copies don't exist.
  • make_clone_plan return type changed: The function now returns a raw 3-tuple instead of a ClonePlan; all internal callers are updated, but this is a breaking change for any external consumer of the public API.
  • Newton per_world sites: NewtonManager.cl_register_site gains a per_world flag; _cl_inject_sites returns a third dict for world-frame sites that are injected with the correct env transform during _build_newton_builder_from_mapping and the USD-load path in newton_manager.

Confidence Score: 3/5

The core USD-skip logic and new per_world site injection appear sound, but two concrete runtime crashes are present in the changed code paths that need fixing before merge.

Newton multi-mesh ray casters with track_mesh_transforms=True will throw KeyError at runtime because _create_tracked_target_view now does a direct dict lookup whose key (built with * wildcards via resolve_clone_plan_source) never matches the keys passed by base_multi_mesh_ray_caster._build_mesh_records (built with .*); the previous .get() fallback that silently papered over this is gone. Additionally, resolve_matching_prims_from_source dereferences SimulationContext.instance() without a null guard.

source/isaaclab_newton/isaaclab_newton/sensors/ray_caster/ray_caster.py (KeyError in _create_tracked_target_view) and source/isaaclab/isaaclab/sim/utils/queries.py (null deref in resolve_matching_prims_from_source) need fixes before merge.

Important Files Changed

Filename Overview
source/isaaclab_newton/isaaclab_newton/sensors/ray_caster/ray_caster.py Rewrites site registration to use per_world=True for env-root sensors; removes lazy fallback in _create_tracked_target_view, exposing a KeyError from a * vs .* key format mismatch with the base class.
source/isaaclab/isaaclab/sim/utils/queries.py New resolve_matching_prims_from_source utility; unguarded SimulationContext.instance().get_clone_plan() raises AttributeError before sim context exists.
source/isaaclab/isaaclab/scene/interactive_scene.py Core USD-skip logic; dropped ValueError for zero-variant spawners; _default_env_origins replaced with full pose tensor.
source/isaaclab/isaaclab/cloner/cloner_utils.py Adds three plan-aware helpers; make_clone_plan return type changed to raw 3-tuple (breaking public API).
source/isaaclab/isaaclab/sensors/sensor_base.py Replaces _resolve_and_spawn with _resolve_rigid_body_ancestor_expr; uses clone plan to set _num_envs and empties _parent_prims in plan mode.
source/isaaclab_newton/isaaclab_newton/physics/newton_manager.py Adds per_world site type and _world_xforms; _cl_inject_sites now returns a third world-sites dict.
source/isaaclab_newton/isaaclab_newton/cloner/newton_replicate.py Adds null defaults for positions/quaternions, sets _world_xforms, and injects world-frame sites per-env.
source/isaaclab_physx/isaaclab_physx/assets/articulation/articulation.py Switches to resolve_matching_prims_from_source; drops articulationEnabled attribute check.
source/isaaclab_physx/isaaclab_physx/sensors/ray_caster/ray_caster.py Replaces manual ancestor walk with resolve_matching_prims_from_source + get_first_matching_ancestor_prim.

Reviews (1): Last reviewed commit: "skip usd cloning in pure newton path (#5..." | Re-trigger Greptile

Comment on lines 241 to 246
def _create_tracked_target_view(self: Any, target_prim_path: str | list[str]):
"""Resolve dynamic multi-mesh target sites to raw Newton site indices."""
target_key = tuple(target_prim_path) if isinstance(target_prim_path, list) else target_prim_path
labels = self._tracked_site_labels_by_expr.get(target_key)
if labels is None:
target_exprs = target_prim_path if isinstance(target_prim_path, list) else [target_prim_path]
labels = self._register_target_sites_for_exprs([_newton_body_pattern(expr) for expr in target_exprs])
self._tracked_site_labels_by_expr[target_key] = labels
target_exprs = target_prim_path if isinstance(target_prim_path, list) else [target_prim_path]
labels = self._tracked_site_labels_by_target[tuple(target_exprs)]
site_indices = self._resolve_site_indices(labels, str(target_prim_path), self._num_envs)
return wp.array(site_indices, dtype=wp.int32, device=self._device)
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.

P1 KeyError when Newton + clone plan + tracked mesh transforms are combined

_create_tracked_target_view does a direct dict lookup with no fallback. The keys stored in _tracked_site_labels_by_target at __init__ time come from _resolve_target_owner_exprs, which produces destination expressions using bare * (via resolve_clone_plan_sourcematching_template.replace("{}", "*")). However, base_multi_mesh_ray_caster._build_mesh_records builds tracked_target_exprs using destination_template.format(".*") (dot-star), and passes those as the lookup keys. A concrete example: stored key ("/World/envs/*/Robot",) vs lookup key ("/World/envs/.*/Robot",)KeyError. In the legacy (no-plan) path, the same mismatch exists between the _newton_body_pattern output (env_.*) and the concrete path from reference_prim.GetPath(). The previous code used .get() with a lazy-registration fallback that masked this discrepancy; removing the fallback without fixing the format inconsistency makes this a hard crash for any Newton multi-mesh ray caster with track_mesh_transforms=True.

Comment on lines +392 to +393
plan = SimulationContext.instance().get_clone_plan()
resolved = resolve_clone_plan_source(path_expr, plan) if plan is not None else None
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.

P1 SimulationContext.instance() returns None before initialization; calling .get_clone_plan() directly on it will raise AttributeError. This guard matches the pattern used in sensor_base.py and elsewhere.

Suggested change
plan = SimulationContext.instance().get_clone_plan()
resolved = resolve_clone_plan_source(path_expr, plan) if plan is not None else None
sim = SimulationContext.instance()
plan = sim.get_clone_plan() if sim is not None else None
resolved = resolve_clone_plan_source(path_expr, plan) if plan is not None else None

Comment on lines +252 to +253
if (count := num_variants(cfg.spawn)) > 0:
groups.append((cfg, cfg.spawn, prim_path.replace(self.env_regex_ns, self.env_fmt), count))
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 Changing from raising ValueError to silently skipping spawners that return zero variants removes a validation that was protecting against misconfigured spawn configs. A spawner unexpectedly returning 0 variants will now produce a scene that is missing an asset without any diagnostic error.

Suggested change
if (count := num_variants(cfg.spawn)) > 0:
groups.append((cfg, cfg.spawn, prim_path.replace(self.env_regex_ns, self.env_fmt), count))
if (count := num_variants(cfg.spawn)) <= 0:
raise ValueError(f"Spawner at '{prim_path}' must have at least one variant.")
groups.append((cfg, cfg.spawn, prim_path.replace(self.env_regex_ns, self.env_fmt), count))

Comment on lines 285 to +288

masking = torch.zeros((sum(group_sizes), num_clones), dtype=torch.bool, device=device)
masking[rows, cols] = True
return ClonePlan(sources=src, destinations=dest, clone_mask=masking)
return src, dest, masking
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 Breaking return-type change for make_clone_plan

make_clone_plan previously returned a ClonePlan and is now changed to return a raw tuple[tuple[str, ...], tuple[str, ...], torch.Tensor]. All internal callers in the repo are updated, but the function is exported in cloner/__init__.pyi as part of the public API. Any external downstream packages that call make_clone_plan and access .sources, .destinations, or .clone_mask attributes on the result will receive an AttributeError at runtime with no compile-time warning. Consider keeping a thin ClonePlan-returning wrapper or clearly marking the deprecation.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@kellyguo11 kellyguo11 merged commit e9fe73c into isaac-sim:release/3.0.0-beta2 May 30, 2026
60 of 61 checks passed
@ooctipus ooctipus deleted the cherrypick/newton_skip_usd_cloning branch May 30, 2026 23:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants