Skip to content

[WIP] Onboard new assets from Mujoco Menagerie#5330

Open
matthewtrepte wants to merge 3 commits intoisaac-sim:developfrom
matthewtrepte:mtrepte/mujoco_menagerie
Open

[WIP] Onboard new assets from Mujoco Menagerie#5330
matthewtrepte wants to merge 3 commits intoisaac-sim:developfrom
matthewtrepte:mtrepte/mujoco_menagerie

Conversation

@matthewtrepte
Copy link
Copy Markdown
Contributor

Description

Working change to benchmark and onboard new robot assets from Mujoco Menagerie

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (existing functionality will not work without user modification)
  • Documentation update

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

@github-actions github-actions Bot added the asset New asset feature or request label Apr 20, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This PR onboards several robot assets (ANYmal-B/C, Spot, Allegro, Shadow Hand, Unitree H1/G1/Go2) from the MuJoCo Menagerie USD collection, replacing legacy Nucleus paths. It introduces a Physics USD variant system (physx / mujoco) auto-injected at spawn time, a sim_launcher.py context manager that selects Kit vs kitless backends, a training asset path logger, and a new mujoco_configs.yaml benchmark suite with a --sim-backend CI flag.

  • P1 — broken distributed benchmark flag: --nnprod_per_node in test_environments_training.py line 101 is an unrecognized argument; it is silently swallowed by parse_known_args(), meaning multi-GPU benchmark jobs always run single-process.

Confidence Score: 4/5

Safe to merge after fixing the distributed training flag typo; all other findings are style/robustness suggestions.

One P1 bug (--nnprod_per_node typo) would silently break any multi-GPU benchmark run; remaining issues are P2 quality suggestions. Core asset-path switching and variant-injection logic are well-structured.

source/isaaclab_tasks/test/benchmarking/test_environments_training.py (distributed flag typo), source/isaaclab/isaaclab/utils/assets.py (case-sensitive path match, unhandled ValueError)

Important Files Changed

Filename Overview
source/isaaclab_tasks/test/benchmarking/test_environments_training.py Adds sim_backend support and Menagerie variant CLI wiring to benchmarks; --nnprod_per_node typo at line 101 breaks distributed training paths.
source/isaaclab/isaaclab/utils/assets.py Adds MuJoCo Menagerie Nucleus path constants, physics variant resolution logic (env-var + argv-based), and recursive USD dependency download; case-sensitive Menagerie path detection and unhandled ValueError from bad env var are noted.
source/isaaclab_tasks/test/benchmarking/env_benchmark_test_utils.py Adds failure_kind discriminator, improved log retrieval, and Newton-compatible log paths; ValueError for unknown threshold names escapes the exception guard.
source/isaaclab_tasks/isaaclab_tasks/utils/sim_launcher.py New context-manager launch_simulation that applies Menagerie variant from launcher args and decides whether to start Kit or kitless backend; clean implementation.
source/isaaclab_tasks/isaaclab_tasks/utils/training_asset_log.py New utility that recursively walks env_cfg dataclass tree and prints resolved USD/URDF/MJCF asset paths for training logs; implementation looks correct.
source/isaaclab_tasks/test/benchmarking/mujoco_configs.yaml New benchmark/test config for Menagerie-backed environments (ANYmal-B/C, Spot, Go2, H1, G1, Allegro, Shadow); thresholds and smoke-test floor values look reasonable.
source/isaaclab_assets/isaaclab_assets/robots/anymal.py Switches ANYmal-B and ANYmal-C USD paths from legacy ISAACLAB_NUCLEUS_DIR to MUJOCO_MENAGERIE_DIR; ANYmal-D retains the original path.
source/isaaclab_assets/isaaclab_assets/robots/spot.py Switches Spot USD path to MUJOCO_MENAGERIE_DIR with updated joint names (lleg links); actuator config unchanged.
source/isaaclab_assets/isaaclab_assets/robots/allegro.py Switches Allegro Hand to Menagerie USDA path with updated joint name patterns (ffj*/thj0) to handle both legacy and Menagerie naming.
source/isaaclab_assets/isaaclab_assets/robots/shadow_hand.py Switches Shadow Hand to Menagerie USDA path with updated rh_ joint prefix and revised actuator effort limits.
source/isaaclab/isaaclab/sim/spawners/from_files/from_files.py Integrates Menagerie physics variant auto-injection into _spawn_from_usd_file via merge_mujoco_menagerie_spawn_variants; logic looks correct.
source/isaaclab_tasks/test/benchmarking/conftest.py Adds --sim-backend CLI option, shard-based test distribution, and sim_backend fixture; implementation looks correct.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[train.py / sim_launcher] -->|--menagerie-physics-variant| B[apply_menagerie_physics_variant_from_launcher_args]
    B -->|writes| C[ISAACLAB_MUJOCO_MENAGERIE_PHYSICS_VARIANT env var]
    D[spawn_from_usd] --> E[_spawn_from_usd_file]
    E --> F[merge_mujoco_menagerie_spawn_variants]
    F --> G{is_mujoco_menagerie_usd_path?}
    G -- No --> H[return cfg.variants unchanged]
    G -- Yes --> I[resolve_mujoco_menagerie_physics_variant_selection]
    I --> J{env var value}
    J -- auto --> K[infer_menagerie_physics_variant_from_argv]
    K -->|presets=newton in argv?| L{newton?}
    L -- yes --> M[variant = mujoco]
    L -- no --> N[variant = physx]
    J -- physx/mujoco --> O[use explicit value]
    J -- none --> P[skip variant injection]
    J -- invalid --> Q[raise ValueError]
    M & N & O --> R[select_usd_variants on prim]
    C -.->|read by| I
Loading

Comments Outside Diff (1)

  1. source/isaaclab_tasks/test/benchmarking/env_benchmark_test_utils.py, line 285-289 (link)

    P2 ValueError for unrecognized threshold names bypasses all exception handling

    The try/except at lines 282–287 only guards the reward and episode_length branches. If a config YAML ever introduces a threshold name other than reward, episode_length, or duration (e.g. a custom metric), the raise ValueError at line 289 escapes the inner try/except and surfaces as an unhandled exception in evaluate_job, stopping the test run rather than marking the job as failed. Adding this path to the outer except Exception guard (or returning None with a warning) would be more resilient.

Reviews (1): Last reviewed commit: "prep for osmo wf benchmarks" | Re-trigger Greptile

Comment on lines 101 to 102
cmd.append(f"--nnprod_per_node={num_gpus}")
cmd.append("--distributed")
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 Typo in distributed flag name

--nnprod_per_node is not a recognized flag in any of the RL training scripts; they all use parse_known_args(), so this argument is silently swallowed without ever setting the number of workers. Distributed training benchmarks will launch as single-process runs rather than multi-GPU, producing wrong timings and potentially wrong KPI numbers.

Suggested change
cmd.append(f"--nnprod_per_node={num_gpus}")
cmd.append("--distributed")
cmd.append(f"--nproc_per_node={num_gpus}")

Comment on lines +109 to +123
def resolve_mujoco_menagerie_physics_variant_selection() -> str | None:
"""Resolve the ``Physics`` variant selection string, or None to skip variant application."""
raw = os.environ.get(ISAACLAB_MUJOCO_MENAGERIE_PHYSICS_VARIANT_ENV, "auto")
mode = raw.strip().lower()
if mode in ("", "auto"):
return infer_menagerie_physics_variant_from_argv()
if mode == "none":
return None
if mode in (MUJOCO_MENAGERIE_PHYSICS_VARIANT_PHYSX, MUJOCO_MENAGERIE_PHYSICS_VARIANT_MUJOCO):
return mode
raise ValueError(
f"Invalid {ISAACLAB_MUJOCO_MENAGERIE_PHYSICS_VARIANT_ENV}={raw!r}. "
f"Expected 'auto', 'none', '{MUJOCO_MENAGERIE_PHYSICS_VARIANT_PHYSX}', or "
f"'{MUJOCO_MENAGERIE_PHYSICS_VARIANT_MUJOCO}'."
)
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 Unhandled ValueError from invalid env var propagates through USD spawn

resolve_mujoco_menagerie_physics_variant_selection raises ValueError when ISAACLAB_MUJOCO_MENAGERIE_PHYSICS_VARIANT is set to an invalid value. This exception is called from merge_mujoco_menagerie_spawn_variants, which is called in the middle of _spawn_from_usd_file — after the prim has already been created in the stage. The resulting stack trace won't clearly indicate the root cause (an env var) to the user.

Consider catching ValueError in merge_mujoco_menagerie_spawn_variants (or in _spawn_from_usd_file) and re-raising with a more actionable message, or validating the env var eagerly at process startup (e.g. in apply_menagerie_physics_variant_from_launcher_args).

Comment on lines +85 to +88
def is_mujoco_menagerie_usd_path(usd_path: str) -> bool:
"""True if *usd_path* points at assets under the MuJoCo Menagerie tree (Nucleus or downloaded)."""
norm = usd_path.replace("\\", "/")
return "Mujoco_Menagerie" in norm
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 Case-sensitive path matching may silently skip variant injection

"Mujoco_Menagerie" in norm is case-sensitive after only normalizing backslashes. A locally downloaded path, a symlink, or a Nucleus server that uses a different casing (mujoco_menagerie, MuJoCo_Menagerie) would return False and never receive the Physics variant selection. Using a case-insensitive check would be more robust.

Suggested change
def is_mujoco_menagerie_usd_path(usd_path: str) -> bool:
"""True if *usd_path* points at assets under the MuJoCo Menagerie tree (Nucleus or downloaded)."""
norm = usd_path.replace("\\", "/")
return "Mujoco_Menagerie" in norm
return "mujoco_menagerie" in norm.lower()

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

Labels

asset New asset feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant