Skip to content

Fix cloner failing to clone USD prims with tree-structured prim paths#6604

Open
jnskkmhr wants to merge 3 commits into
isaac-sim:developfrom
jnskkmhr:develop
Open

Fix cloner failing to clone USD prims with tree-structured prim paths#6604
jnskkmhr wants to merge 3 commits into
isaac-sim:developfrom
jnskkmhr:develop

Conversation

@jnskkmhr

@jnskkmhr jnskkmhr commented Jul 18, 2026

Copy link
Copy Markdown

Description

The cloner fails to clone assets whose prim_path contains more than one regex wildcard (.*), which is common for tree-structured USD prims where a wildcard is used both for the environment index and for an inner subtree.

For example, given:

prim_path = "/World/envs/env_.*/Robot/.*/link"

make_clone_plan builds a destination template by replacing every .* with a {} format placeholder:

"/World/envs/env_{}/Robot/{}/link"

It then formats this template with a single environment index (e.g. 0), which only fills the first {}. The second placeholder is left unfilled, so str.format raises and cloning fails.

Fixes

Replace only the first .* with the {} placeholder and leave any remaining .* in place:

destination = prim_path.replace(".*", "{}", 1)

The leading wildcard (the per-environment index) is substituted with the env id, while the rest of the path keeps its .*, so the cloner can handle tree-structured prim paths.

Type of change

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

Screenshots

Please attach before and after screenshots of the change if applicable.

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the changelog and the corresponding version in the extension's config/extension.toml file
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

🤖 Generated with Claude Code

@jnskkmhr
jnskkmhr requested a review from a team July 18, 2026 19:29
@github-actions github-actions Bot added the isaac-lab Related to Isaac Lab team label Jul 18, 2026
@greptile-apps

greptile-apps Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a one-line bug in make_clone_plan where str.replace was replacing every .* with a {} format placeholder, causing str.format(env_id) to raise when a prim path contained more than one wildcard (e.g. tree-structured USD prims with a per-environment and a per-subtree wildcard). The fix adds count=1 so only the leading wildcard is turned into a placeholder; downstream formatters receive a single argument and the remaining .* is left intact for the cloner to handle.

  • cloner_utils.py line 266: prim_path.replace(\".*\", \"{}\")prim_path.replace(\".*\", \"{}\", 1) — the sole code change.
  • No tests were added for the multi-wildcard scenario; the existing test suite only covers single-wildcard prim paths.

Confidence Score: 4/5

Safe to merge — the fix is a minimal, well-scoped change that unblocks a crash path without affecting single-wildcard prim paths or any other logic.

The change is a single-character addition that correctly resolves a crash when prim paths contain more than one .* wildcard. The fix preserves existing behavior for the common single-wildcard case. The only concern is the absence of a regression test for the multi-wildcard scenario — the bug being fixed is not covered by the current test suite, so a future accidental revert would go undetected.

source/isaaclab/isaaclab/cloner/cloner_utils.py and the corresponding test file source/isaaclab/test/sim/test_cloner.py — a new test case for multi-wildcard prim paths would be valuable here.

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/cloner/cloner_utils.py Single-character fix: adds count=1 to str.replace so only the first .* is converted to a format placeholder, preventing a format() call with too few arguments when prim paths contain multiple wildcards

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["prim_path\n/World/envs/env_.*/Robot/.*/link"] --> B["prim_path.replace('.*', '{}', 1)"]
    B --> C["destination\n/World/envs/env_{}/Robot/.*/link"]
    C --> D{homogeneous?}
    D -- yes --> E["destination.format(0)\n→ /World/envs/env_0/Robot/.*/link"]
    D -- no --> F["destination.format(env_id)\n→ /World/envs/env_N/Robot/.*/link"]
    E --> G["set_spawn_paths / ClonePlan"]
    F --> G
    G --> H["Cloner handles remaining .* wildcard\nfor tree-structured prims"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["prim_path\n/World/envs/env_.*/Robot/.*/link"] --> B["prim_path.replace('.*', '{}', 1)"]
    B --> C["destination\n/World/envs/env_{}/Robot/.*/link"]
    C --> D{homogeneous?}
    D -- yes --> E["destination.format(0)\n→ /World/envs/env_0/Robot/.*/link"]
    D -- no --> F["destination.format(env_id)\n→ /World/envs/env_N/Robot/.*/link"]
    E --> G["set_spawn_paths / ClonePlan"]
    F --> G
    G --> H["Cloner handles remaining .* wildcard\nfor tree-structured prims"]
Loading

Reviews (1): Last reviewed commit: "handle tree USD in cloner." | Re-trigger Greptile

if count <= 0:
raise ValueError(f"Spawner at '{prim_path}' must have at least one variant.")
destination = prim_path.replace(".*", "{}")
destination = prim_path.replace(".*", "{}", 1)

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 No regression test for the multi-wildcard case

The existing tests in test_cloner.py only exercise prim paths with a single .* (e.g. /World/envs/env_.*/Robot). There is no test that covers a path like /World/envs/env_.*/Robot/.*/link, so the bug being fixed here has no automated guard against regressions. A unit test for make_clone_plan with a two-wildcard path (asserting that destination.format(env_id) produces the expected resolved path and that ClonePlan is populated correctly) would lock in this fix.

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!

@AntoineRichard

Copy link
Copy Markdown
Collaborator

@jnskkmhr can you add the missing changelog fragment? :)

@jnskkmhr

Copy link
Copy Markdown
Author

@AntoineRichard
Added changelog. I hope I did correctly.

@AntoineRichard

Copy link
Copy Markdown
Collaborator

@jnskkmhr looks good :). @ooctipus can you take a look and give a second approval :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants