Skip to content

Conversation

@nv-sachdevkartik
Copy link
Contributor

Type / Scope

  • Type: Feature
  • Scope: envs, processor

Summary / Motivation

This PR introduces NVIDIA IsaacLab-Arena integration into LeRobot, enabling GPU-accelerated simulation environments through the EnvHub infrastructure. IsaacLab-Arena provides high-fidelity physics simulation for large-scale policy evaluation for various tasks. The community is encouraged to create custom environments using the IsaacLab-Arena framework.

The integration allows developers to:

  • Train imitation learning policies (PI0, SmolVLA, ACT, Diffusion) with the collected teleop dataset
  • Evaluate trained policies in high-fidelity IsaacLab-Arena simulation environments

This implementation follows the EnvHub pattern, loading environments from the Hub repository nvkartik/isaaclab-arena-envs while providing a native environment configuration (IsaaclabArenaEnv) for seamless CLI integration.

Available Environments

The following are example environments built with NVIDIA IsaacLab-Arena:

Preview Environment Description
GR1 Microwave gr1_microwave Reach out to the microwave and open it.
Galileo Pick and Place galileo_pnp Pick objects and place in target location
G1 Loco-manipulation g1_locomanip_pnp Pick up the brown box from the shelf, and place it into the blue bin on the table located at the right of the shelf.
Kitchen Pick and Place kitchen_pnp Kitchen object manipulation tasks
Press Button press_button Locate and press button

This is just the start, more examples coming soon! 🚀

What Changed

New Files

File Description
tests/processor/test_arena_processor.py Comprehensive test suite for IsaacLab-Arena observation processor

Modified Files

File Description
src/lerobot/envs/configs.py Added IsaaclabArenaEnv configuration dataclass with IsaacLab-Arena-specific parameters (embodiment, object, environment, camera/state keys)
src/lerobot/envs/factory.py Added IsaacLab-Arena environment instantiation via Hub loading and IsaaclabArenaProcessorStep creation
src/lerobot/envs/utils.py Extended preprocess_observation() to handle IsaacLab-Arena's observation format (policy, camera_obs)
src/lerobot/processor/env_processor.py Added IsaaclabArenaProcessorStep for processing IsaacLab-Arena observations (state concatenation, image normalization/permutation)
src/lerobot/scripts/lerobot_eval.py Added render_all() support for IsaacLab wrapper video recording
tests/processor/test_pipeline.py Additional processor pipeline tests

Key Implementation Details

Environment Configuration (IsaaclabArenaEnv):

@EnvConfig.register_subclass("isaaclab_arena")
@dataclass
class IsaaclabArenaEnv(EnvConfig):
    hub_repo_id: str = "nvkartik/isaaclab-arena-envs"
    environment: str = "gr1_microwave"
    embodiment: str = "gr1_pink"
    object: str = "power_drill"
    state_keys: str = "robot_joint_pos"
    camera_keys: str = "robot_pov_cam_rgb"
    # ... additional configuration

Observation Processor (IsaaclabArenaProcessorStep):

  • Extracts state from obs["policy"] based on configurable state_keys
  • Processes images from obs["camera_obs"] based on camera_keys
  • Handles BHWC→BCHW permutation and uint8→float32 normalization
  • Concatenates multiple state components into single observation.state vector

Breaking Changes: None

How Was This Tested

Automated Tests

pytest -q tests/processor/test_arena_processor.py

Test coverage includes:

  • State extraction and float32 conversion
  • Multiple state key concatenation with ordering verification
  • Higher-dimensional state flattening
  • State key filtering
  • Camera BHWC→BCHW permutation
  • uint8→normalized float32 image conversion
  • float32 image passthrough
  • Camera key filtering
  • Missing observation section handling
  • Empty observation handling
  • Default and custom key configuration
  • Feature transform passthrough

Manual Verification

Zero-agent environment test:

python test_env_load_arena.py \
    --env.type=isaaclab_arena \
    --env.environment=galileo_pnp \
    --env.embodiment=gr1_pink \
    --env.object=cracker_box \
    --env.num_envs=4 \
    --env.enable_cameras=true \
    --env.seed=1000

Policy evaluation (SmolVLA):

lerobot-eval \
    --policy.path=nvkartik/smolvla-arena-gr1-microwave \
    --env.type=isaaclab_arena \
    --rename_map='{"observation.images.robot_pov_cam_rgb": "observation.images.robot_pov_cam"}' \
    --env.environment=gr1_microwave \
    --env.embodiment=gr1_pink \
    --env.num_envs=1 \
    --env.headless=true \
    --policy.device=cuda \
    --env.enable_cameras=true \
    --env.video=true

Policy evaluation (PI0.5):

TORCH_COMPILE_DISABLE=1 TORCHINDUCTOR_DISABLE=1 lerobot-eval \
    --policy.path=nvkartik/pi05-arena-gr1-microwave \
    --env.type=isaaclab_arena \
    --rename_map='{"observation.images.robot_pov_cam_rgb": "observation.images.robot_pov_cam"}' \
    --env.environment=gr1_microwave \
    --env.embodiment=gr1_pink \
    --env.num_envs=1 \
    --env.headless=true \
    --policy.device=cuda \
    --env.enable_cameras=true

Training (PI0.5):

lerobot-train \
    --policy.type=pi05 \
    --dataset.repo_id nvkartik/Arena-GR1-Manipulation-Task \
    --rename_map '{"observation.images.robot_pov_cam":"observation.images.camera1"}' \
    --policy.empty_cameras=2 \
    --policy.max_state_dim=64 \
    --policy.max_action_dim=64 \
    --batch_size=16 \
    --steps=20000

How to Run Locally (Reviewer)

1. Install Dependencies

sudo apt update && sudo apt install -y libglu1-mesa libxt6

# Create conda environment
conda create -y -n lerobot-arena python=3.11
conda activate lerobot-arena
conda install -y -c conda-forge ffmpeg=7.1.1
pip install uv

# Install IsaacSim 5.1.0
uv pip install "isaacsim[all,extscache]==5.1.0" --extra-index-url https://pypi.nvidia.com
export ACCEPT_EULA=Y
export PRIVACY_CONSENT=Y

# Install IsaacLab 2.3.0
git clone https://github.com/isaac-sim/IsaacLab.git
cd IsaacLab && git checkout v2.3.0 && ./isaaclab.sh -i && cd ..

# Install LeRobot from source
git clone https://github.com/liorbenhorin/lerobot.git
cd lerobot
git checkout isaaclab_arena_lerobot
##  fix transformer version as per issue: #2641
sed -i 's|^pi = \[.*\]|pi = ["transformers @ git+https://github.com/huggingface/transformers.git@dcddb970176382c0fcf4521b0c0e6fc15894dfe0"]|' pyproject.toml
uv pip install -e ".[pi]"
 
# Install NVIDIA IsaacLab-Arena
cd ..
git clone [email protected]:isaac-sim/IsaacLab-Arena.git
cd IsaacLab-Arena
git checkout b4feca387f280e3d2d08ed3c4825f7877ab709f4
uv pip install -e .
uv pip install onnxruntime lightwheel-sdk vuer[all]

# Fix dependencies
pip install numpy==1.26.0 qpsolvers==4.8.1 lxml==4.9.4 packaging==23.2

2. Run Tests

pytest -q tests/processor/test_arena_processor.py -v

3. Run Environment Smoke Test

python -c "
from lerobot.envs.configs import IsaaclabArenaEnv
cfg = IsaaclabArenaEnv(environment='gr1_microwave')
print(f'Config created: {cfg.environment}')
print(f'Hub kwargs: {cfg.hub_kwargs}')
"

Checklist (Required Before Merge)

  • Linting/formatting run (pre-commit run -a)
  • All tests pass locally (pytest tests/processor/test_arena_processor.py)
  • Documentation updated
  • CI is green

Reviewer Notes

Focus Areas

  1. IsaaclabArenaProcessorStep (src/lerobot/processor/env_processor.py): Core observation processing logic - verify state concatenation ordering and image normalization
  2. IsaaclabArenaEnv config (src/lerobot/envs/configs.py): Validate Hub kwargs mapping and feature definitions
  3. Factory integration (src/lerobot/envs/factory.py): Ensure proper Hub loading and processor instantiation

Available Resources

Datasets:

Trained Policies:

Environment Repository:

Notes for Community Reviewers

  • GPU required for running IsaacLab environments
  • NVIDIA driver and CUDA toolkit must be compatible with IsaacSim 5.1.0
  • Environment loading requires accepting NVIDIA EULA (export ACCEPT_EULA=Y)

Integrate NVIDIA IsaacLab Arena with LeRobot to enable GPU-accelerated
simulation through the EnvHub infrastructure.

This enables:
- Training imitation learning policies (PI0, SmolVLA, etc.)
- Evaluating trained policies in with IsaacLab Arena

The implementation adds:
- IsaaclabArenaEnv config with Arena-specific parameters
- IsaaclabArenaProcessorStep for observation processing
- Hub loading from nvkartik/isaaclab-arena-envs repository
- Video recording support

Available environments include GR1 microwave manipulation, Galileo
pick-and-place, G1 loco-manipulation, and button pressing tasks.

Datasets: nvkartik/Arena-GR1-Manipulation-Task
Policies: nvkartik/pi05-arena-gr1-microwave,
          nvkartik/smolvla-arena-gr1-microwave
@github-actions github-actions bot added documentation Improvements or fixes to the project’s docs tests Problems with test coverage, failures, or improvements to testing processor Issue related to processor evaluation For issues or PRs related to environment evaluation, and benchmarks. labels Dec 23, 2025
@jadechoghari jadechoghari self-requested a review December 23, 2025 11:34
@liorbenhorin
Copy link
Contributor

@imstevenpmwork - For the installation phase - we will try to simplify the process as possible - and include it in the documentation page [to be written] - it will be similar to how it is done for our gr00t implementation.
This is mainly due to to
pip install numpy==1.26.0 qpsolvers==4.8.1 lxml==4.9.4 packaging==23.2
The numpy dependency will be resolved as soon as Isaac Sim 6.0.0 will be available. (it is technically already available, but developers need to build from source, so we prefer to wait)

Comment on lines +102 to +108
# Handle IsaacLab Arena format: observations have 'policy' and 'camera_obs' keys
if "policy" in observations:
return_observations[f"{OBS_STR}.policy"] = observations["policy"]

if "camera_obs" in observations:
return_observations[f"{OBS_STR}.camera_obs"] = observations["camera_obs"]

Copy link
Member

Choose a reason for hiding this comment

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

This might be unecesary.
If "policy" represents the robot state, you can change the IsaaclabArenaProcessorStep to conform to the accepted namings of preprocess_observation which include agent_pos or robot_state.
Same thing for camera_obs. Our naming convenion is OBS_IMAGES.{camera_name} not "{OBS_STR}.camera_obs" for visual observations.

I also see you're already renaming correclty in the env processor

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jadechoghari : is there a plan to complete this todo as mentioned, this would give flexibility to use custom names?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@aliberts : it would be great to remove the hardcoded features.


key: str = "a"
value: PolicyFeature = PolicyFeature(type=FeatureType.STATE, shape=(1,))
value: PolicyFeature = field(default_factory=lambda: PolicyFeature(type=FeatureType.STATE, shape=(1,)))
Copy link
Member

Choose a reason for hiding this comment

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

why is this change necessary?

Comment on lines 311 to 313
elif hasattr(env, "render_all"):
# IsaacLabVectorEnvWrapper uses render_all() method for video recording
ep_frames.append(np.stack(env.render_all()[:n_to_render_now]))
Copy link
Member

Choose a reason for hiding this comment

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

Can we instead introduce a small env.render wrapper for the env? instead of adding a special case branch here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done, added IsaacLab wrapper based on AsyncVectorEnv, thus removing this code.

hub_repo_id: str = "nvkartik/isaaclab-arena-envs"
episode_length: int = 300
num_envs: int = 1
embodiment: str | None = "gr1_pink"
Copy link
Member

Choose a reason for hiding this comment

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

Can i switch embodiments in each tasks?. For instance in task A, can i select robot A or robot B

Choose a reason for hiding this comment

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

yes

cd ..

# 6. Install additional dependencies
pip install qpsolvers==4.8.1 numpy==1.26.0
Copy link
Member

Choose a reason for hiding this comment

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

Won't this version of numpy break compatibailtiy with the current numpy version in LeRobot?

Copy link
Contributor

Choose a reason for hiding this comment

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

It is not ideal, but so far our tests didn't exhibited any breaking.
We can include a note recommending the developer to create a dedicated conda env for evaluation using this feature, and other conda env for training, in case they encounter any numpy-related warnings

Comment on lines +85 to +89

- NVIDIA GPU with CUDA support
- NVIDIA driver compatible with IsaacSim 5.1.0
- Linux (Ubuntu 22.04 recommended)

Copy link
Member

Choose a reason for hiding this comment

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

If i don't have a nvidia gpu, i won't be able to run isaac arena?

Copy link
Contributor

Choose a reason for hiding this comment

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

Isaac Lab requires NVIDIA GPU - if one does not have one handy we usually point them to Brev

Comment on lines 174 to 184
elif "isaaclab_arena" in cfg.type:
# Load IsaacLab Arena environment from the Hub
repo_id, file_path, local_file, revision = _download_hub_file(
cfg.hub_repo_id, trust_remote_code=True, hub_cache_dir=hub_cache_dir
)
module = _import_hub_module(local_file, repo_id)
raw_result = _call_make_env(
module, n_envs=cfg.num_envs, use_async_envs=use_async_envs, **cfg.hub_kwargs, **kwargs
)

return _normalize_hub_result(raw_result)
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this what this conditioning branch (envhub) already does?

if isinstance(cfg, str):

So we can just pass the hub string instead, no? nvkartik/isaaclab-arena-envs



def _call_make_env(module: Any, n_envs: int, use_async_envs: bool) -> Any:
def _call_make_env(module: Any, n_envs: int, use_async_envs: bool, **kwargs: Any) -> Any:
Copy link
Member

Choose a reason for hiding this comment

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

FYI, we will merge this PR soon: https://github.com/huggingface/lerobot/pull/2599/files for the custom kwargs if it works for you

@github-actions github-actions bot added the configuration Problems with configuration files or settings label Dec 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

configuration Problems with configuration files or settings documentation Improvements or fixes to the project’s docs evaluation For issues or PRs related to environment evaluation, and benchmarks. processor Issue related to processor tests Problems with test coverage, failures, or improvements to testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants