From 7f0d812bdace278b34e14e39957df8b658713195 Mon Sep 17 00:00:00 2001 From: Clemens Volk Date: Mon, 2 Mar 2026 10:11:41 +0100 Subject: [PATCH 1/7] Add CLAUDE.md with build commands and architecture overview Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Clemens Volk --- CLAUDE.md | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..a34cb89ab --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,111 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Isaac-Lab Arena is a scalable robotics simulation environment creation and evaluation framework built on top of NVIDIA Isaac Lab. It provides a composable system for defining robotic tasks, assembling scenes from modular assets, solving spatial object relationships, and evaluating learning policies. + +## Common Commands + +### Running Tests +Tests require Isaac Sim and run via pytest. All simulation tests use `run_simulation_app_function()` to handle Isaac Sim's process lifecycle: + +```bash +# Run all tests +pytest isaaclab_arena/tests/ + +# Run a single test file +pytest isaaclab_arena/tests/test_asset_registry.py + +# Run a specific test function +pytest isaaclab_arena/tests/test_asset_registry.py::test_default_assets_registered + +# Run tests that require cameras +pytest isaaclab_arena/tests/ -m with_cameras +``` + +### Linting and Formatting +Pre-commit hooks enforce: black (line length 120), flake8, isort, pyupgrade (py310+), codespell, and Apache-2.0 license headers. + +```bash +# Install pre-commit hooks +pre-commit install + +# Run all pre-commit checks +pre-commit run --all-files + +# Run individually +black --line-length 120 --unstable +flake8 +isort --profile black +``` + +### Contributing +All commits must be signed off per DCO requirements: +```bash +git commit -s -m "Your commit message" +``` + +## Architecture + +### Core Composition Model + +An environment is assembled by composing four components into an `IsaacLabArenaEnvironment` descriptor, which `ArenaEnvBuilder` then translates into Isaac Lab's `ManagerBasedRLEnvCfg`: + +``` +IsaacLabArenaEnvironment(name, scene, embodiment, task, [teleop_device], [orchestrator]) + ↓ ArenaEnvBuilder.make_rl() / make_mimic() +IsaacLabArenaManagerBasedRLEnvCfg + ↓ +IsaacLabArenaManagerBasedRLEnv (wraps isaaclab.envs.ManagerBasedRLEnv) +``` + +### Key Packages + +- **`isaaclab_arena/`** — Main package + - **`environments/`** — `IsaacLabArenaEnvironment` (descriptor), `ArenaEnvBuilder` (config composer), `IsaacLabArenaManagerBasedRLEnv` (runtime) + - **`scene/`** — `Scene` assembles assets (objects, backgrounds, HDR, ground planes) and exports to USD + - **`embodiments/`** — Robot definitions (Franka, GR1T2, G1, DROID, AgiBot, Galbot); each implements `EmbodimentBase` + - **`tasks/`** — Task implementations (pick-and-place, open/close door, sorting, assembly, etc.); each implements `TaskBase` + - **`assets/`** — `AssetRegistry`/`DeviceRegistry` singletons for dynamic asset lookup; `Object`, `Background`, `HDRImage`, `ObjectSet` + - **`relations/`** — Spatial constraint solver: `ObjectPlacer` + `RelationSolver` optimize positions using loss primitives (NextTo, On, Above, etc.) + - **`affordances/`** — Object capability descriptors: `Openable`, `Turnable`, `Pressable`, `Placeable` + - **`policy/`** — Policy interface (`PolicyBase`) and implementations: `ZeroActionPolicy`, `RslRlActionPolicy`, `ReplayActionPolicy`, `ActionChunking` + - **`evaluation/`** — `PolicyRunner`, `EvalRunner`, `JobManager` for running and recording evaluations + - **`metrics/`** — Pluggable metrics (`MetricBase`): success rate, object moved, revolute joint moved rate + - **`remote_policy/`** — Client/server policy execution over network (`PolicyServer`, `PolicyClient`) + - **`terms/`** — Custom Isaac Lab manager terms (events, articulations, transforms) + - **`cli/`** — Argument parser (`get_isaaclab_arena_cli_parser`) + - **`utils/`** — Pose math, USD helpers, joint utilities, bounding boxes, RNG management + +- **`isaaclab_arena_environments/`** — Pre-built environment definitions +- **`isaaclab_arena_examples/`** — Example scripts and notebooks +- **`isaaclab_arena_gr00t/`** — GR00T humanoid robot utilities +- **`isaaclab_arena_g1/`** — G1 robot-specific code +- **`submodules/IsaacLab/`** — Core Isaac Lab framework +- **`submodules/Isaac-GR00T/`** — GR00T implementation + +### Test Infrastructure + +Tests use `run_simulation_app_function()` (`isaaclab_arena/tests/utils/subprocess.py`) to wrap simulation tests. This creates a persistent `SimulationApp` (reused across tests in a session) and handles Isaac Sim's process-termination quirk—Isaac Sim would otherwise kill the pytest process with exit code 0 even on test failures. The `conftest.py` tracks test failures and forces exit code 1 when needed. + +Test functions follow the pattern: +```python +def _test_foo(simulation_app): # inner function runs inside SimulationApp + from isaaclab_arena.X import Y # deferred imports after sim init + ... + return True # indicates pass + +def test_foo(): # pytest-visible outer function + result = run_simulation_app_function(_test_foo) + assert result +``` + +### Configuration System + +Configs are `@configclass` dataclasses (Isaac Lab pattern). `ArenaEnvBuilder` dynamically merges configs from scene, embodiment, task, and optional components using `combine_configclass_instances()`. The `env_cfg_callback` on `IsaacLabArenaEnvironment` allows post-merge customization. + +### Relation Solver + +Object placement in a scene can be specified declaratively using spatial relations (e.g., `NextTo(table)`, `On(shelf)`). `ObjectPlacer` collects all objects with relations, identifies the anchor object (`IsAnchor`), and runs `RelationSolver` which minimizes a sum of loss primitives (defined in `loss_primitives.py`) to find valid non-overlapping poses. From 00ca3ac17e55424bab6c1eb1a4792d92648d290c Mon Sep 17 00:00:00 2001 From: Clemens Volk Date: Mon, 2 Mar 2026 10:19:04 +0100 Subject: [PATCH 2/7] CLAUDE.md: add Docker environment section Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Clemens Volk --- CLAUDE.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index a34cb89ab..6f2d3960e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,6 +6,26 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Isaac-Lab Arena is a scalable robotics simulation environment creation and evaluation framework built on top of NVIDIA Isaac Lab. It provides a composable system for defining robotic tasks, assembling scenes from modular assets, solving spatial object relationships, and evaluating learning policies. +## Docker Environment + +All commands must be run inside the Docker container. From the repo root: + +```bash +# Build image (if needed) and start/attach to container +./docker/run_docker.sh + +# Force rebuild the image +./docker/run_docker.sh -r + +# With GR00T N1.6 dependencies +./docker/run_docker.sh -g + +# Custom host mount directories (datasets, models, eval) +./docker/run_docker.sh -d ~/datasets -m ~/models -e ~/eval +``` + +The script builds the image on first run and reuses it on subsequent runs. If a container is already running it attaches to it instead of starting a new one. The repo root is mounted at `/workspaces/isaaclab_arena` inside the container. + ## Common Commands ### Running Tests From d89a781e3276f150d09bdabc044459d133345ee2 Mon Sep 17 00:00:00 2001 From: Clemens Volk Date: Mon, 2 Mar 2026 10:23:19 +0100 Subject: [PATCH 3/7] CLAUDE.md: document docker exec approach for running commands Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Clemens Volk --- CLAUDE.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 6f2d3960e..14f67db1c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,24 +8,21 @@ Isaac-Lab Arena is a scalable robotics simulation environment creation and evalu ## Docker Environment -All commands must be run inside the Docker container. From the repo root: +All commands (tests, linting, training scripts, etc.) must be run inside the Docker container. The default container is `isaaclab_arena-latest`, started via: ```bash -# Build image (if needed) and start/attach to container -./docker/run_docker.sh - -# Force rebuild the image -./docker/run_docker.sh -r +./docker/run_docker.sh # build image (if needed) and start/attach +./docker/run_docker.sh -r # force rebuild +./docker/run_docker.sh -g # include GR00T N1.6 dependencies +./docker/run_docker.sh -d ~/datasets -m ~/models -e ~/eval # custom mount dirs +``` -# With GR00T N1.6 dependencies -./docker/run_docker.sh -g +The repo root is mounted at `/workspaces/isaaclab_arena` inside the container. To run a command in the already-running container: -# Custom host mount directories (datasets, models, eval) -./docker/run_docker.sh -d ~/datasets -m ~/models -e ~/eval +```bash +docker exec isaaclab_arena-latest bash -c "cd /workspaces/isaaclab_arena && " ``` -The script builds the image on first run and reuses it on subsequent runs. If a container is already running it attaches to it instead of starting a new one. The repo root is mounted at `/workspaces/isaaclab_arena` inside the container. - ## Common Commands ### Running Tests From 8f5dd2749f088b5e090d1b2d5c1121029c64fab3 Mon Sep 17 00:00:00 2001 From: Clemens Volk Date: Mon, 2 Mar 2026 10:31:08 +0100 Subject: [PATCH 4/7] CLAUDE.md: document /isaac-sim/python.sh and policy_runner example Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Clemens Volk --- CLAUDE.md | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 14f67db1c..4e16b61bb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,6 +23,19 @@ The repo root is mounted at `/workspaces/isaaclab_arena` inside the container. T docker exec isaaclab_arena-latest bash -c "cd /workspaces/isaaclab_arena && " ``` +**Important:** Use `/isaac-sim/python.sh` as the Python interpreter inside the container (not `python` or `python3`). + +```bash +# Example: run kitchen_pick_and_place with zero_action policy +docker exec isaaclab_arena-latest bash -c "cd /workspaces/isaaclab_arena && \ + /isaac-sim/python.sh isaaclab_arena/evaluation/policy_runner.py \ + --policy_type zero_action \ + --num_episodes 1 \ + kitchen_pick_and_place \ + --object cracker_box \ + --embodiment franka" +``` + ## Common Commands ### Running Tests @@ -30,16 +43,16 @@ Tests require Isaac Sim and run via pytest. All simulation tests use `run_simula ```bash # Run all tests -pytest isaaclab_arena/tests/ +/isaac-sim/python.sh -m pytest isaaclab_arena/tests/ # Run a single test file -pytest isaaclab_arena/tests/test_asset_registry.py +/isaac-sim/python.sh -m pytest isaaclab_arena/tests/test_asset_registry.py # Run a specific test function -pytest isaaclab_arena/tests/test_asset_registry.py::test_default_assets_registered +/isaac-sim/python.sh -m pytest isaaclab_arena/tests/test_asset_registry.py::test_default_assets_registered # Run tests that require cameras -pytest isaaclab_arena/tests/ -m with_cameras +/isaac-sim/python.sh -m pytest isaaclab_arena/tests/ -m with_cameras ``` ### Linting and Formatting From 8f7fee380693274408526503c037788e310e3a3b Mon Sep 17 00:00:00 2001 From: Clemens Volk Date: Mon, 2 Mar 2026 15:01:39 +0100 Subject: [PATCH 5/7] CLAUDE.md: add coding style, contributing guidelines, and env convention - Add pre-commit workflow note (run before committing, not after) - Document branch naming, commit message format, and PR iteration rules - Fix architecture diagram method names (make_registered vs make_rl) - Add wrapped environment convention section (env.unwrapped usage) Signed-off-by: Clemens Volk --- CLAUDE.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4e16b61bb..207db5474 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -71,12 +71,32 @@ flake8 isort --profile black ``` +### Coding Style + +Follow the pre-commit hooks as the enforced style guide (black, flake8, isort, pyupgrade, codespell). Run checks before committing — not after: + +```bash +pre-commit run --all-files # check all files +# if pre-commit modifies files, stage them and re-run before committing +``` + ### Contributing + All commits must be signed off per DCO requirements: ```bash git commit -s -m "Your commit message" ``` +**Branch naming:** `/feature-desc` (e.g. `cvolk/feature-video-recording`, `cvolk/refactor-no-unwrap`). + +**Commit messages:** +- Subject: imperative mood, ~50 chars, no trailing period (e.g. "Fix attribute access on wrapped env") +- Separate subject from body with a blank line +- Body: explain *what* and *why* (not how — the diff shows that), wrap at 72 chars +- Do not include AI attribution lines (e.g. "Co-Authored-By: Claude...") + +**PR iteration:** when addressing review feedback, add new commits rather than amending existing ones — this lets reviewers easily verify each change was addressed. + ## Architecture ### Core Composition Model @@ -85,10 +105,10 @@ An environment is assembled by composing four components into an `IsaacLabArenaE ``` IsaacLabArenaEnvironment(name, scene, embodiment, task, [teleop_device], [orchestrator]) - ↓ ArenaEnvBuilder.make_rl() / make_mimic() + ↓ ArenaEnvBuilder.build_registered() / make_registered() IsaacLabArenaManagerBasedRLEnvCfg ↓ -IsaacLabArenaManagerBasedRLEnv (wraps isaaclab.envs.ManagerBasedRLEnv) +gym.make() → OrderEnforcing(IsaacLabArenaManagerBasedRLEnv) ``` ### Key Packages @@ -132,6 +152,17 @@ def test_foo(): # pytest-visible outer function assert result ``` +### Wrapped Environment Convention + +`ArenaEnvBuilder.make_registered()` returns the gym-wrapped env (not the base env). This aligns with Isaac Lab's convention. Use `env.unwrapped` explicitly to access Isaac Lab-specific attributes (`cfg`, `device`, `step_dt`, etc.) that are not forwarded by gymnasium's `OrderEnforcing` wrapper: + +```python +env = arena_builder.make_registered() # wrapped env +env.step(actions) # goes through OrderEnforcing +env.unwrapped.cfg # access Isaac Lab config +env.unwrapped.device # access Isaac Lab device +``` + ### Configuration System Configs are `@configclass` dataclasses (Isaac Lab pattern). `ArenaEnvBuilder` dynamically merges configs from scene, embodiment, task, and optional components using `combine_configclass_instances()`. The `env_cfg_callback` on `IsaacLabArenaEnvironment` allows post-merge customization. From 7da12d32cf66f26599e5699995c69bd5ea3daefd Mon Sep 17 00:00:00 2001 From: Clemens Volk Date: Mon, 2 Mar 2026 15:05:19 +0100 Subject: [PATCH 6/7] Move content to AGENTS.md, point CLAUDE.md at it AGENTS.md is the convention for OpenAI agents; CLAUDE.md is the convention for Claude Code. By maintaining one source of truth in AGENTS.md and having CLAUDE.md reference it via @AGENTS.md, both tools pick up the same guidance. Signed-off-by: Clemens Volk --- AGENTS.md | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 173 +----------------------------------------------------- 2 files changed, 173 insertions(+), 172 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..c5bc2a4d5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,172 @@ +# AGENTS.md + +This file provides guidance to AI coding agents (Claude Code, OpenAI Codex, etc.) when working with code in this repository. + +## Project Overview + +Isaac-Lab Arena is a scalable robotics simulation environment creation and evaluation framework built on top of NVIDIA Isaac Lab. It provides a composable system for defining robotic tasks, assembling scenes from modular assets, solving spatial object relationships, and evaluating learning policies. + +## Docker Environment + +All commands (tests, linting, training scripts, etc.) must be run inside the Docker container. The default container is `isaaclab_arena-latest`, started via: + +```bash +./docker/run_docker.sh # build image (if needed) and start/attach +./docker/run_docker.sh -r # force rebuild +./docker/run_docker.sh -g # include GR00T N1.6 dependencies +./docker/run_docker.sh -d ~/datasets -m ~/models -e ~/eval # custom mount dirs +``` + +The repo root is mounted at `/workspaces/isaaclab_arena` inside the container. To run a command in the already-running container: + +```bash +docker exec isaaclab_arena-latest bash -c "cd /workspaces/isaaclab_arena && " +``` + +**Important:** Use `/isaac-sim/python.sh` as the Python interpreter inside the container (not `python` or `python3`). + +```bash +# Example: run kitchen_pick_and_place with zero_action policy +docker exec isaaclab_arena-latest bash -c "cd /workspaces/isaaclab_arena && \ + /isaac-sim/python.sh isaaclab_arena/evaluation/policy_runner.py \ + --policy_type zero_action \ + --num_episodes 1 \ + kitchen_pick_and_place \ + --object cracker_box \ + --embodiment franka" +``` + +## Common Commands + +### Running Tests +Tests require Isaac Sim and run via pytest. All simulation tests use `run_simulation_app_function()` to handle Isaac Sim's process lifecycle: + +```bash +# Run all tests +/isaac-sim/python.sh -m pytest isaaclab_arena/tests/ + +# Run a single test file +/isaac-sim/python.sh -m pytest isaaclab_arena/tests/test_asset_registry.py + +# Run a specific test function +/isaac-sim/python.sh -m pytest isaaclab_arena/tests/test_asset_registry.py::test_default_assets_registered + +# Run tests that require cameras +/isaac-sim/python.sh -m pytest isaaclab_arena/tests/ -m with_cameras +``` + +### Linting and Formatting +Pre-commit hooks enforce: black (line length 120), flake8, isort, pyupgrade (py310+), codespell, and Apache-2.0 license headers. + +```bash +# Install pre-commit hooks +pre-commit install + +# Run all pre-commit checks +pre-commit run --all-files + +# Run individually +black --line-length 120 --unstable +flake8 +isort --profile black +``` + +### Coding Style + +Follow the pre-commit hooks as the enforced style guide (black, flake8, isort, pyupgrade, codespell). Run checks before committing — not after: + +```bash +pre-commit run --all-files # check all files +# if pre-commit modifies files, stage them and re-run before committing +``` + +### Contributing + +All commits must be signed off per DCO requirements: +```bash +git commit -s -m "Your commit message" +``` + +**Branch naming:** `/feature-desc` (e.g. `cvolk/feature-video-recording`, `cvolk/refactor-no-unwrap`). + +**Commit messages:** +- Subject: imperative mood, ~50 chars, no trailing period (e.g. "Fix attribute access on wrapped env") +- Separate subject from body with a blank line +- Body: explain *what* and *why* (not how — the diff shows that), wrap at 72 chars +- Do not include AI attribution lines (e.g. "Co-Authored-By: Claude...") + +**PR iteration:** when addressing review feedback, add new commits rather than amending existing ones — this lets reviewers easily verify each change was addressed. + +## Architecture + +### Core Composition Model + +An environment is assembled by composing four components into an `IsaacLabArenaEnvironment` descriptor, which `ArenaEnvBuilder` then translates into Isaac Lab's `ManagerBasedRLEnvCfg`: + +``` +IsaacLabArenaEnvironment(name, scene, embodiment, task, [teleop_device], [orchestrator]) + ↓ ArenaEnvBuilder.build_registered() / make_registered() +IsaacLabArenaManagerBasedRLEnvCfg + ↓ +gym.make() → OrderEnforcing(IsaacLabArenaManagerBasedRLEnv) +``` + +### Key Packages + +- **`isaaclab_arena/`** — Main package + - **`environments/`** — `IsaacLabArenaEnvironment` (descriptor), `ArenaEnvBuilder` (config composer), `IsaacLabArenaManagerBasedRLEnv` (runtime) + - **`scene/`** — `Scene` assembles assets (objects, backgrounds, HDR, ground planes) and exports to USD + - **`embodiments/`** — Robot definitions (Franka, GR1T2, G1, DROID, AgiBot, Galbot); each implements `EmbodimentBase` + - **`tasks/`** — Task implementations (pick-and-place, open/close door, sorting, assembly, etc.); each implements `TaskBase` + - **`assets/`** — `AssetRegistry`/`DeviceRegistry` singletons for dynamic asset lookup; `Object`, `Background`, `HDRImage`, `ObjectSet` + - **`relations/`** — Spatial constraint solver: `ObjectPlacer` + `RelationSolver` optimize positions using loss primitives (NextTo, On, Above, etc.) + - **`affordances/`** — Object capability descriptors: `Openable`, `Turnable`, `Pressable`, `Placeable` + - **`policy/`** — Policy interface (`PolicyBase`) and implementations: `ZeroActionPolicy`, `RslRlActionPolicy`, `ReplayActionPolicy`, `ActionChunking` + - **`evaluation/`** — `PolicyRunner`, `EvalRunner`, `JobManager` for running and recording evaluations + - **`metrics/`** — Pluggable metrics (`MetricBase`): success rate, object moved, revolute joint moved rate + - **`remote_policy/`** — Client/server policy execution over network (`PolicyServer`, `PolicyClient`) + - **`terms/`** — Custom Isaac Lab manager terms (events, articulations, transforms) + - **`cli/`** — Argument parser (`get_isaaclab_arena_cli_parser`) + - **`utils/`** — Pose math, USD helpers, joint utilities, bounding boxes, RNG management + +- **`isaaclab_arena_environments/`** — Pre-built environment definitions +- **`isaaclab_arena_examples/`** — Example scripts and notebooks +- **`isaaclab_arena_gr00t/`** — GR00T humanoid robot utilities +- **`isaaclab_arena_g1/`** — G1 robot-specific code +- **`submodules/IsaacLab/`** — Core Isaac Lab framework +- **`submodules/Isaac-GR00T/`** — GR00T implementation + +### Test Infrastructure + +Tests use `run_simulation_app_function()` (`isaaclab_arena/tests/utils/subprocess.py`) to wrap simulation tests. This creates a persistent `SimulationApp` (reused across tests in a session) and handles Isaac Sim's process-termination quirk—Isaac Sim would otherwise kill the pytest process with exit code 0 even on test failures. The `conftest.py` tracks test failures and forces exit code 1 when needed. + +Test functions follow the pattern: +```python +def _test_foo(simulation_app): # inner function runs inside SimulationApp + from isaaclab_arena.X import Y # deferred imports after sim init + ... + return True # indicates pass + +def test_foo(): # pytest-visible outer function + result = run_simulation_app_function(_test_foo) + assert result +``` + +### Wrapped Environment Convention + +`ArenaEnvBuilder.make_registered()` returns the gym-wrapped env (not the base env). This aligns with Isaac Lab's convention. Use `env.unwrapped` explicitly to access Isaac Lab-specific attributes (`cfg`, `device`, `step_dt`, etc.) that are not forwarded by gymnasium's `OrderEnforcing` wrapper: + +```python +env = arena_builder.make_registered() # wrapped env +env.step(actions) # goes through OrderEnforcing +env.unwrapped.cfg # access Isaac Lab config +env.unwrapped.device # access Isaac Lab device +``` + +### Configuration System + +Configs are `@configclass` dataclasses (Isaac Lab pattern). `ArenaEnvBuilder` dynamically merges configs from scene, embodiment, task, and optional components using `combine_configclass_instances()`. The `env_cfg_callback` on `IsaacLabArenaEnvironment` allows post-merge customization. + +### Relation Solver + +Object placement in a scene can be specified declaratively using spatial relations (e.g., `NextTo(table)`, `On(shelf)`). `ObjectPlacer` collects all objects with relations, identifies the anchor object (`IsAnchor`), and runs `RelationSolver` which minimizes a sum of loss primitives (defined in `loss_primitives.py`) to find valid non-overlapping poses. diff --git a/CLAUDE.md b/CLAUDE.md index 207db5474..43c994c2d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,172 +1 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -Isaac-Lab Arena is a scalable robotics simulation environment creation and evaluation framework built on top of NVIDIA Isaac Lab. It provides a composable system for defining robotic tasks, assembling scenes from modular assets, solving spatial object relationships, and evaluating learning policies. - -## Docker Environment - -All commands (tests, linting, training scripts, etc.) must be run inside the Docker container. The default container is `isaaclab_arena-latest`, started via: - -```bash -./docker/run_docker.sh # build image (if needed) and start/attach -./docker/run_docker.sh -r # force rebuild -./docker/run_docker.sh -g # include GR00T N1.6 dependencies -./docker/run_docker.sh -d ~/datasets -m ~/models -e ~/eval # custom mount dirs -``` - -The repo root is mounted at `/workspaces/isaaclab_arena` inside the container. To run a command in the already-running container: - -```bash -docker exec isaaclab_arena-latest bash -c "cd /workspaces/isaaclab_arena && " -``` - -**Important:** Use `/isaac-sim/python.sh` as the Python interpreter inside the container (not `python` or `python3`). - -```bash -# Example: run kitchen_pick_and_place with zero_action policy -docker exec isaaclab_arena-latest bash -c "cd /workspaces/isaaclab_arena && \ - /isaac-sim/python.sh isaaclab_arena/evaluation/policy_runner.py \ - --policy_type zero_action \ - --num_episodes 1 \ - kitchen_pick_and_place \ - --object cracker_box \ - --embodiment franka" -``` - -## Common Commands - -### Running Tests -Tests require Isaac Sim and run via pytest. All simulation tests use `run_simulation_app_function()` to handle Isaac Sim's process lifecycle: - -```bash -# Run all tests -/isaac-sim/python.sh -m pytest isaaclab_arena/tests/ - -# Run a single test file -/isaac-sim/python.sh -m pytest isaaclab_arena/tests/test_asset_registry.py - -# Run a specific test function -/isaac-sim/python.sh -m pytest isaaclab_arena/tests/test_asset_registry.py::test_default_assets_registered - -# Run tests that require cameras -/isaac-sim/python.sh -m pytest isaaclab_arena/tests/ -m with_cameras -``` - -### Linting and Formatting -Pre-commit hooks enforce: black (line length 120), flake8, isort, pyupgrade (py310+), codespell, and Apache-2.0 license headers. - -```bash -# Install pre-commit hooks -pre-commit install - -# Run all pre-commit checks -pre-commit run --all-files - -# Run individually -black --line-length 120 --unstable -flake8 -isort --profile black -``` - -### Coding Style - -Follow the pre-commit hooks as the enforced style guide (black, flake8, isort, pyupgrade, codespell). Run checks before committing — not after: - -```bash -pre-commit run --all-files # check all files -# if pre-commit modifies files, stage them and re-run before committing -``` - -### Contributing - -All commits must be signed off per DCO requirements: -```bash -git commit -s -m "Your commit message" -``` - -**Branch naming:** `/feature-desc` (e.g. `cvolk/feature-video-recording`, `cvolk/refactor-no-unwrap`). - -**Commit messages:** -- Subject: imperative mood, ~50 chars, no trailing period (e.g. "Fix attribute access on wrapped env") -- Separate subject from body with a blank line -- Body: explain *what* and *why* (not how — the diff shows that), wrap at 72 chars -- Do not include AI attribution lines (e.g. "Co-Authored-By: Claude...") - -**PR iteration:** when addressing review feedback, add new commits rather than amending existing ones — this lets reviewers easily verify each change was addressed. - -## Architecture - -### Core Composition Model - -An environment is assembled by composing four components into an `IsaacLabArenaEnvironment` descriptor, which `ArenaEnvBuilder` then translates into Isaac Lab's `ManagerBasedRLEnvCfg`: - -``` -IsaacLabArenaEnvironment(name, scene, embodiment, task, [teleop_device], [orchestrator]) - ↓ ArenaEnvBuilder.build_registered() / make_registered() -IsaacLabArenaManagerBasedRLEnvCfg - ↓ -gym.make() → OrderEnforcing(IsaacLabArenaManagerBasedRLEnv) -``` - -### Key Packages - -- **`isaaclab_arena/`** — Main package - - **`environments/`** — `IsaacLabArenaEnvironment` (descriptor), `ArenaEnvBuilder` (config composer), `IsaacLabArenaManagerBasedRLEnv` (runtime) - - **`scene/`** — `Scene` assembles assets (objects, backgrounds, HDR, ground planes) and exports to USD - - **`embodiments/`** — Robot definitions (Franka, GR1T2, G1, DROID, AgiBot, Galbot); each implements `EmbodimentBase` - - **`tasks/`** — Task implementations (pick-and-place, open/close door, sorting, assembly, etc.); each implements `TaskBase` - - **`assets/`** — `AssetRegistry`/`DeviceRegistry` singletons for dynamic asset lookup; `Object`, `Background`, `HDRImage`, `ObjectSet` - - **`relations/`** — Spatial constraint solver: `ObjectPlacer` + `RelationSolver` optimize positions using loss primitives (NextTo, On, Above, etc.) - - **`affordances/`** — Object capability descriptors: `Openable`, `Turnable`, `Pressable`, `Placeable` - - **`policy/`** — Policy interface (`PolicyBase`) and implementations: `ZeroActionPolicy`, `RslRlActionPolicy`, `ReplayActionPolicy`, `ActionChunking` - - **`evaluation/`** — `PolicyRunner`, `EvalRunner`, `JobManager` for running and recording evaluations - - **`metrics/`** — Pluggable metrics (`MetricBase`): success rate, object moved, revolute joint moved rate - - **`remote_policy/`** — Client/server policy execution over network (`PolicyServer`, `PolicyClient`) - - **`terms/`** — Custom Isaac Lab manager terms (events, articulations, transforms) - - **`cli/`** — Argument parser (`get_isaaclab_arena_cli_parser`) - - **`utils/`** — Pose math, USD helpers, joint utilities, bounding boxes, RNG management - -- **`isaaclab_arena_environments/`** — Pre-built environment definitions -- **`isaaclab_arena_examples/`** — Example scripts and notebooks -- **`isaaclab_arena_gr00t/`** — GR00T humanoid robot utilities -- **`isaaclab_arena_g1/`** — G1 robot-specific code -- **`submodules/IsaacLab/`** — Core Isaac Lab framework -- **`submodules/Isaac-GR00T/`** — GR00T implementation - -### Test Infrastructure - -Tests use `run_simulation_app_function()` (`isaaclab_arena/tests/utils/subprocess.py`) to wrap simulation tests. This creates a persistent `SimulationApp` (reused across tests in a session) and handles Isaac Sim's process-termination quirk—Isaac Sim would otherwise kill the pytest process with exit code 0 even on test failures. The `conftest.py` tracks test failures and forces exit code 1 when needed. - -Test functions follow the pattern: -```python -def _test_foo(simulation_app): # inner function runs inside SimulationApp - from isaaclab_arena.X import Y # deferred imports after sim init - ... - return True # indicates pass - -def test_foo(): # pytest-visible outer function - result = run_simulation_app_function(_test_foo) - assert result -``` - -### Wrapped Environment Convention - -`ArenaEnvBuilder.make_registered()` returns the gym-wrapped env (not the base env). This aligns with Isaac Lab's convention. Use `env.unwrapped` explicitly to access Isaac Lab-specific attributes (`cfg`, `device`, `step_dt`, etc.) that are not forwarded by gymnasium's `OrderEnforcing` wrapper: - -```python -env = arena_builder.make_registered() # wrapped env -env.step(actions) # goes through OrderEnforcing -env.unwrapped.cfg # access Isaac Lab config -env.unwrapped.device # access Isaac Lab device -``` - -### Configuration System - -Configs are `@configclass` dataclasses (Isaac Lab pattern). `ArenaEnvBuilder` dynamically merges configs from scene, embodiment, task, and optional components using `combine_configclass_instances()`. The `env_cfg_callback` on `IsaacLabArenaEnvironment` allows post-merge customization. - -### Relation Solver - -Object placement in a scene can be specified declaratively using spatial relations (e.g., `NextTo(table)`, `On(shelf)`). `ObjectPlacer` collects all objects with relations, identifies the anchor object (`IsAnchor`), and runs `RelationSolver` which minimizes a sum of loss primitives (defined in `loss_primitives.py`) to find valid non-overlapping poses. +@AGENTS.md From 00cbeb31e4d348177e6753a196d27566190821f1 Mon Sep 17 00:00:00 2001 From: Clemens Volk Date: Mon, 2 Mar 2026 15:15:00 +0100 Subject: [PATCH 7/7] AGENTS.md: slim down to operational essentials MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove project overview, architecture, key packages, config system, and relation solver sections — these are discoverable from the code. Keep Docker setup, test/lint commands, contributing guidelines, and non-obvious conventions (wrapped env, test infrastructure pattern). Signed-off-by: Clemens Volk --- AGENTS.md | 98 ++++++++++--------------------------------------------- 1 file changed, 18 insertions(+), 80 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index c5bc2a4d5..a739a2777 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,10 +2,6 @@ This file provides guidance to AI coding agents (Claude Code, OpenAI Codex, etc.) when working with code in this repository. -## Project Overview - -Isaac-Lab Arena is a scalable robotics simulation environment creation and evaluation framework built on top of NVIDIA Isaac Lab. It provides a composable system for defining robotic tasks, assembling scenes from modular assets, solving spatial object relationships, and evaluating learning policies. - ## Docker Environment All commands (tests, linting, training scripts, etc.) must be run inside the Docker container. The default container is `isaaclab_arena-latest`, started via: @@ -30,7 +26,7 @@ docker exec isaaclab_arena-latest bash -c "cd /workspaces/isaaclab_arena && -flake8 -isort --profile black -``` - -### Coding Style - -Follow the pre-commit hooks as the enforced style guide (black, flake8, isort, pyupgrade, codespell). Run checks before committing — not after: - -```bash -pre-commit run --all-files # check all files -# if pre-commit modifies files, stage them and re-run before committing ``` ### Contributing @@ -97,53 +81,26 @@ git commit -s -m "Your commit message" **PR iteration:** when addressing review feedback, add new commits rather than amending existing ones — this lets reviewers easily verify each change was addressed. -## Architecture +## Conventions -### Core Composition Model +### Wrapped Environment -An environment is assembled by composing four components into an `IsaacLabArenaEnvironment` descriptor, which `ArenaEnvBuilder` then translates into Isaac Lab's `ManagerBasedRLEnvCfg`: +`ArenaEnvBuilder.make_registered()` returns the gym-wrapped env (not the base env). Use `env.unwrapped` explicitly to access Isaac Lab-specific attributes (`cfg`, `device`, `step_dt`, etc.) that are not forwarded by gymnasium's `OrderEnforcing` wrapper: +```python +env = arena_builder.make_registered() # wrapped env +env.step(actions) # goes through OrderEnforcing +env.unwrapped.cfg # access Isaac Lab config +env.unwrapped.device # access Isaac Lab device ``` -IsaacLabArenaEnvironment(name, scene, embodiment, task, [teleop_device], [orchestrator]) - ↓ ArenaEnvBuilder.build_registered() / make_registered() -IsaacLabArenaManagerBasedRLEnvCfg - ↓ -gym.make() → OrderEnforcing(IsaacLabArenaManagerBasedRLEnv) -``` - -### Key Packages - -- **`isaaclab_arena/`** — Main package - - **`environments/`** — `IsaacLabArenaEnvironment` (descriptor), `ArenaEnvBuilder` (config composer), `IsaacLabArenaManagerBasedRLEnv` (runtime) - - **`scene/`** — `Scene` assembles assets (objects, backgrounds, HDR, ground planes) and exports to USD - - **`embodiments/`** — Robot definitions (Franka, GR1T2, G1, DROID, AgiBot, Galbot); each implements `EmbodimentBase` - - **`tasks/`** — Task implementations (pick-and-place, open/close door, sorting, assembly, etc.); each implements `TaskBase` - - **`assets/`** — `AssetRegistry`/`DeviceRegistry` singletons for dynamic asset lookup; `Object`, `Background`, `HDRImage`, `ObjectSet` - - **`relations/`** — Spatial constraint solver: `ObjectPlacer` + `RelationSolver` optimize positions using loss primitives (NextTo, On, Above, etc.) - - **`affordances/`** — Object capability descriptors: `Openable`, `Turnable`, `Pressable`, `Placeable` - - **`policy/`** — Policy interface (`PolicyBase`) and implementations: `ZeroActionPolicy`, `RslRlActionPolicy`, `ReplayActionPolicy`, `ActionChunking` - - **`evaluation/`** — `PolicyRunner`, `EvalRunner`, `JobManager` for running and recording evaluations - - **`metrics/`** — Pluggable metrics (`MetricBase`): success rate, object moved, revolute joint moved rate - - **`remote_policy/`** — Client/server policy execution over network (`PolicyServer`, `PolicyClient`) - - **`terms/`** — Custom Isaac Lab manager terms (events, articulations, transforms) - - **`cli/`** — Argument parser (`get_isaaclab_arena_cli_parser`) - - **`utils/`** — Pose math, USD helpers, joint utilities, bounding boxes, RNG management - -- **`isaaclab_arena_environments/`** — Pre-built environment definitions -- **`isaaclab_arena_examples/`** — Example scripts and notebooks -- **`isaaclab_arena_gr00t/`** — GR00T humanoid robot utilities -- **`isaaclab_arena_g1/`** — G1 robot-specific code -- **`submodules/IsaacLab/`** — Core Isaac Lab framework -- **`submodules/Isaac-GR00T/`** — GR00T implementation ### Test Infrastructure -Tests use `run_simulation_app_function()` (`isaaclab_arena/tests/utils/subprocess.py`) to wrap simulation tests. This creates a persistent `SimulationApp` (reused across tests in a session) and handles Isaac Sim's process-termination quirk—Isaac Sim would otherwise kill the pytest process with exit code 0 even on test failures. The `conftest.py` tracks test failures and forces exit code 1 when needed. +Simulation tests use an inner/outer function pattern to handle Isaac Sim's process lifecycle: -Test functions follow the pattern: ```python -def _test_foo(simulation_app): # inner function runs inside SimulationApp - from isaaclab_arena.X import Y # deferred imports after sim init +def _test_foo(simulation_app): # runs inside SimulationApp + from isaaclab_arena.X import Y # deferred imports after sim init ... return True # indicates pass @@ -151,22 +108,3 @@ def test_foo(): # pytest-visible outer function result = run_simulation_app_function(_test_foo) assert result ``` - -### Wrapped Environment Convention - -`ArenaEnvBuilder.make_registered()` returns the gym-wrapped env (not the base env). This aligns with Isaac Lab's convention. Use `env.unwrapped` explicitly to access Isaac Lab-specific attributes (`cfg`, `device`, `step_dt`, etc.) that are not forwarded by gymnasium's `OrderEnforcing` wrapper: - -```python -env = arena_builder.make_registered() # wrapped env -env.step(actions) # goes through OrderEnforcing -env.unwrapped.cfg # access Isaac Lab config -env.unwrapped.device # access Isaac Lab device -``` - -### Configuration System - -Configs are `@configclass` dataclasses (Isaac Lab pattern). `ArenaEnvBuilder` dynamically merges configs from scene, embodiment, task, and optional components using `combine_configclass_instances()`. The `env_cfg_callback` on `IsaacLabArenaEnvironment` allows post-merge customization. - -### Relation Solver - -Object placement in a scene can be specified declaratively using spatial relations (e.g., `NextTo(table)`, `On(shelf)`). `ObjectPlacer` collects all objects with relations, identifies the anchor object (`IsAnchor`), and runs `RelationSolver` which minimizes a sum of loss primitives (defined in `loss_primitives.py`) to find valid non-overlapping poses.