Pluggable simulator branch#97
Open
itokeiic wants to merge 27 commits into
Open
Conversation
Sketches the planned URDF backend (Isaac Lab UrdfConverter as the URDF→USD half) alongside the existing blueprint_to_usd stub. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Schema refactor preparing for blueprint_to_urdf. Mass and inertia are now read off the Blueprint nodes themselves rather than passed as backend kwargs, so MJCF / URDF / future USD backends share one source of truth. - blueprint.py: add CylindricalCrossSection / HollowTubeCrossSection / RectangularCrossSection sub-objects, each with `area` and `principal_inertia(length, mass)`. Extend ArmNode with `density` + `cross_section` + derived `mass` / `inertia_diag` properties. Extend MotorNode with derived `mass` / `radius` / `thickness` / `inertia_diag` via PROPELLER_LIBRARY lookup. Default cross-section is HollowTube (4mm OD / 3mm ID) which with density=1500 kg/m³ reproduces existing BEAM_DENSITY = 0.034 kg/m. Extend from_dict to rebuild cross_section sub-dataclasses on load. - propeller_data.py: add motor_radius / motor_thickness per prop entry, values from the APC propeller-motor pairing table — outer-can radius plateaus at ~14mm for prop5+ (all use 22mm-class stators), only thickness grows. - backends.py: blueprint_to_mjspec drops motor_mass / arm_mass / arm_radius / motor_radius / motor_thickness kwargs, reads from node properties, dispatches arm geometry on isinstance(cross_section, …) (capsule for circular, box for rectangular). blueprint_to_urdf stub signature trimmed to match. - DRONE_BLUEPRINT_PLAN.md: Phase 3 marked in-progress, blueprint_to_mjspec description refreshed, new §6 Design decisions captures the 11 choices made on this branch (URDF-first vs direct USD, hybrid mass model, cross-section sub-object, compliant-joint two-layer pattern, etc.). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Walks the blueprint tree and emits a URDF file: one <link> per CorePlate / Arm / Motor node (with diagonal <inertial> sourced from the node's derived mass + inertia_diag) and one <joint type="fixed"> per parent-child edge. Arm geometry dispatches on cross-section type: <cylinder> for solid / hollow-tube, <box> for rectangular. Rotor visuals are folded into the parent motor link (no separate rotor link; rotor mass is already lumped into motor.mass). No actuators emitted — Isaac Lab applies thrust at runtime via force on the motor link's local +Z. This is the URDF half of the Blueprint → URDF → USD path; the soft_ airframe_optimization repo already has the URDF → USD half via isaaclab.sim.converters.UrdfConverter, so the two combine into a full Isaac Lab asset pipeline. Compliant joints (a future ArmNode.CompliantJoint annotation) will swap the joint type to "revolute" with zero physics stiffness and stash the non-linear τ(θ) law as sidecar ariel:* attributes, mirroring soft_ airframe's morphy:* USD two-layer pattern. Smoke test: decoder-built quad emits 9 links + 8 joints; mixed-cross- section drone correctly dispatches box vs cylinder per arm; output is well-formed XML that MuJoCo's URDF parser accepts without error. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The conversion is split across two scripts because ariel requires
Python 3.12 (PEP 695 type-statement syntax) while the local isaaclab
conda env runs Python 3.11. The URDF file is the boundary between the
two envs.
* scripts/blueprint_to_urdf.py — runs in the ariel env. Builds a
DroneBlueprint (either a preset or from a saved JSON), calls
blueprint_to_urdf, writes the .urdf to --out.
* scripts/urdf_to_usd.py — runs in the isaaclab env. Takes a URDF
path and writes a USD via isaaclab.sim.converters.UrdfConverter.
All joints in the v1 URDF are fixed, so joint_drive is configured
with target_type="none" and zero PD gains (just satisfies the
required-field validator). Progress messages go to stderr to survive
Isaac Sim's stdout capture.
End-to-end smoke test passed: blueprint_to_urdf produces a 4-arm quad
URDF; urdf_to_usd produces the standard Isaac Lab layered USD output
(quad.usd + configuration/{quad_base, quad_physics, quad_robot,
quad_sensor}.usd, ~10 KB total).
Sample run:
python scripts/blueprint_to_urdf.py --preset quad --out /tmp/quad.urdf
/home/keiichi-ito/miniconda3/envs/isaaclab/bin/python \
scripts/urdf_to_usd.py --headless \
--input /tmp/quad.urdf --output_dir /tmp/quad_usd
# (the second invocation needs ${ISAAC_SIM}/setup_conda_env.sh sourced)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Builds an X-quad blueprint, calls blueprint_to_urdf, parses the result back and reports link/joint counts, total mass, and which geometry tags ended up in the URDF — verifying the arm cross-section dispatch (<cylinder> for default HollowTube vs <box> for --rect-arms). End-to-end smoke check: both the default and --rect-arms outputs round- tripped cleanly through scripts/urdf_to_usd.py to USD (1453 bytes, standard Isaac Lab layered layout). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Updated Phase 3 in §5 from "In progress" to "Largely landed for rigid drones," with a numbered list of the 5 commits that landed today and what each does. Calls out what's still pending: compliant joints (schema + URDF revolute + USD ariel:* attrs + example), the optional wrapper script, and pytest integration coverage. * Added §6 entries 12–14 capturing decisions made during the pipeline bring-up: two-env split with URDF as the boundary, stderr-based logging in urdf_to_usd.py to survive Isaac Sim's stdout capture, and the joint_drive workaround for the all-fixed-joints case. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces PEP 695 type-statement syntax (Python 3.12+) with PEP 613
TypeAlias, so ariel can run in the Python 3.11 conda env that Isaac
Sim 5.1 requires. Goal: one unified env in which ariel and Isaac Lab
both work, eliminating the two-script subprocess split documented in
DRONE_BLUEPRINT_PLAN.md §6 entry 12.
Changes:
* 31 `type X = ...` statements rewritten to `X: TypeAlias = ...`
across 14 files in src/ariel/{ec,parameters,utils,body_phenotypes}
and examples/{re_book,z_ec_course}. Each file adds `TypeAlias` to
its existing typing import (or adds a new import where there was
none).
* src/ariel/ec/ea.py: `class EAOperation[**P]:` (PEP 695 generic class
syntax) → `class EAOperation(Generic[P]):` using the module-level
`P = ParamSpec("P")` that already existed at line 26.
* src/ariel/ec/individual.py: dropped the self-referential typing of
JSONType / JSONIterable. PEP 695 `type X = ...` evaluates the body
lazily, so recursive aliases worked transparently; PEP 613 evaluates
eagerly, and forward-ref strings then break at runtime when SQLModel
introspects `JSONIterable | None` field annotations. Nested values
fall through to `Any` — same approach pydantic.JsonValue takes for
runtime use.
* pyproject.toml: `requires-python` from `>=3.12` to `>=3.11`.
Validation:
* Python 3.12 (current dev env): full import chain works, blueprint
decoder + URDF + MJCF backends all functional. No regression.
* Python 3.11 (isaaclab conda env): syntax is now clean — what was
`SyntaxError: invalid syntax (archive.py, line 14)` is now just
`ModuleNotFoundError: No module named 'sqlmodel'` (an env-setup
issue, not a code issue). The migration is complete; remaining
work is installing ariel's runtime deps into the isaaclab env.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Phase 3 follow-on commit list extended with the 3.11 migration; the "Still pending" section drops the obsoleted wrapper-script item (single env makes it unnecessary) and adds the dep-pin item as a deferred stretch. * §6 entry 12 (the two-env split rationale) marked superseded with a forward pointer to the new entry. * §6 entry 15 added documenting the migration: scope, the self-referential-alias subtlety, and validation status (URDF→USD pipeline runs end-to-end in one isaaclab env despite the pip resolver's warnings about numpy 2 / gymnasium 1.3 / torch CUDA build swaps). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous version said the migration was for "simulator-agnostic" without naming the use case that actually forced it: EA objective functions that simulate each morphology, where the two-env subprocess split would pay ~60–90 s of Isaac Sim launch overhead per individual. Also lists alternatives we considered (Isaac→3.12, long-running worker, MuJoCo-only EA loop) and why we picked the migration. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Defines the BlueprintGateEnv Protocol — ariel's contract for a
simulator-backend-agnostic gymnasium VecEnv constructed from a
DroneBlueprint. The PPO trainer (and any other consumer) accepts any
implementation; collaborators can plug in their own simulator while
keeping ariel's EA + learning infrastructure. This is the
architectural payoff of the unified-env work in §6 entry 15.
Phase 1 ships:
* src/ariel/simulation/tasks/blueprint_gate_env.py — the
@runtime_checkable BlueprintGateEnv Protocol, plus
NumpyBlueprintGateEnv: a thin subclass of the existing DroneGateEnv
that adds a Blueprint → propellers-list adapter at the constructor.
Inherits all VecEnv methods, gate definitions, reward shaping, and
observation/action spaces unchanged.
* src/ariel/simulation/tasks/isaaclab_gate_env.py —
IsaacLabBlueprintGateEnv stub with the planned constructor
signature and NotImplementedError. Pins the API so the tutorial's
--simulator isaaclab path compiles against the intended shape;
body is Phase 2 work.
* tutorials/pluggable_simulator/{README.md, train.py} — README walks
through the architecture, the Protocol contract, and a five-step
"add your own backend" recipe. train.py is the unified entry point
with --simulator {numpy,isaaclab} dispatch, demonstrating that the
PPO loop is identical across backends.
Bug fix bundled in:
* src/ariel/simulation/tasks/drone_gate_env.py: renamed self.seed →
self._seed. DroneGateEnv stored its seed as an int attribute
shadowing the inherited VecEnv.seed() method that stable-baselines3
PPO calls in set_random_seed. Anyone passing seed= to PPO would
have hit "TypeError: 'int' object is not callable". Surfaced
because the new tutorial passes a seed through the entire pipeline;
fix is targeted (3 lines across __init__ and reset_seed).
Validation:
* Smoke test (ariel 3.12 venv): PPO 2000 timesteps, num_envs=4,
quad preset → completes in 4.7 s at ~6600 env-steps/sec.
ep_rew_mean ~-21 (expected for a from-scratch policy).
Protocol isinstance assert passes.
* Smoke test (unified isaaclab 3.11 conda env): hits a segfault
during PPO startup, likely numpy 2 ABI conflict with stable-
baselines3 compiled deps. This is exactly the "if pip conflicts
bite elsewhere" risk we flagged in §6 entry 15; promoted to a
blocking item in the "Still pending" list.
Doc updates (DRONE_BLUEPRINT_PLAN.md):
* Phase 3 follow-on commit list extended with the pluggable-
simulator branch and entry 7.
* "Still pending" rewritten: Phase 2 (Isaac Lab implementation) is
the next item; numpy<2 pinning promoted from stretch since the
segfault means it now blocks RL training in the unified env.
* §6 entry 17 added documenting the design decisions: why the seam
is a Protocol (not ABC, not gymnasium-only duck typing), why
NumpyBlueprintGateEnv is a subclass rather than composition,
and the seed-attribute bug we found and fixed in passing.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Lands the Isaac-Lab-side env construction for the pluggable-simulator
architecture. The full Blueprint → URDF → USD → DirectRLEnv → N parallel
drones pipeline runs in-process. Trains via random-action stepping for
v1; rl_games PPO wiring is in place but blocked by a layered env-stack
issue (see §6 entry 17). Architecture pivot from Phase 1: the Isaac Lab
backend follows the DirectRLEnv shape rather than the gymnasium VecEnv
Protocol, accepting that different simulator ecosystems use different
RL libraries.
Renamed (preserves git history):
* src/ariel/simulation/tasks/isaaclab_gate_env.py
→ src/ariel/simulation/tasks/isaaclab_hover_env.py
Implementation (isaaclab_hover_env.py):
* `make_blueprint_usd(blueprint, output_dir)` — in-process URDF→USD
conversion via blueprint_to_urdf + UrdfConverter. Requires Isaac Sim
app to already be running.
* `IsaacLabBlueprintHoverEnvCfg` (@configclass extending DirectRLEnvCfg)
with a `.from_blueprint(bp, num_envs=...)` classmethod that generates
the USD as a side effect and slots its path into `robot.spawn.usd_path`.
Overrides default `joint_pos`/`joint_vel` `{".*": 0.0}` regexes to
empty dicts, since our rigid-drone articulations have zero movable
joints (otherwise: "Not all regular expressions are matched!").
* `IsaacLabBlueprintHoverEnv(DirectRLEnv)` — modeled on Isaac Lab's
reference QuadcopterEnv. 4-action thrust+moment wrench at root body;
12-D observation (root_lin_vel_b, root_ang_vel_b, projected_gravity_b,
desired_pos_b); reward = -distance_to_goal × step_dt (numerically
stable for all distance values, per the project lead's design note);
done on episode length or z bounds.
* `make_rl_games_agent_cfg(...)` — returns an rl_games PPO config dict
matched to Isaac Lab's reference quadcopter `rl_games_ppo_cfg.yaml`.
Defined as a function (not @configclass) because rl_games is dict-
configured. Ready to plug into Phase 2.5 once the env-stack issue
is resolved.
train.py:
* New `main_isaaclab` that launches AppLauncher, generates USD,
constructs env, then runs a random-action stepping loop for
`max_iterations × 24` steps (the rl_games horizon shape). Verifies
end-to-end correctness of obs/reward/done plumbing.
* Per-step progress + final stats logged to stderr (stdout is captured
by Isaac Sim's launcher; same trick we used in urdf_to_usd.py).
* Peek-parser dispatch on `--simulator` so the numpy path doesn't
pay the Isaac Lab import cost.
Verified:
* `--simulator numpy --total-timesteps 2000` in the ariel 3.12 venv:
PPO trains in 3.8 s at ~525 steps/sec.
* `--simulator isaaclab --headless --num-envs 16 --max-iterations 3`
in the unified isaaclab conda env: env constructs + spawns 16
drones + steps 72 times in 1.6 s. Mean reward ~ -0.03 (consistent
with -distance × dt for small distances and short episodes).
Env-stack issues encountered (documented in §6 entry 17's "Phase 2.5
deferred" subsection):
* sb3 + numpy 2 ABI segfault → avoided by NOT routing Isaac Lab via
sb3 / `isaaclab_rl.sb3` adapter.
* `isaaclab_rl.rsl_rl` adapter vs `rsl-rl-lib`: tried 3.0.1 and 5.3.0;
both fail on different config-shape mismatches (`optimizer`,
`share_cnn_encoders`, `class_name`). Shim
`handle_deprecated_rsl_rl_cfg` didn't catch the relevant fields.
* `rl_games` + Isaac Sim bundled torch: tensorboard import pulls in
bundled pip_prebundle torch which transitively imports older
tensorflow → jax → tries `numpy.dtypes.StringDType` on a bundled
older numpy. v1 ships with a random-action stepping loop instead;
PPO wiring is reachable in `make_rl_games_agent_cfg` and ready to
plug in once the env-stack is resolved (Phase 2.5).
Doc updates:
* tutorials/pluggable_simulator/README.md: rewrote the architecture
section as a 2-row table (numpy / isaaclab) with honest Phase 2
status. Updated the "Adding your own simulator" recipe to cover
both contracts (gymnasium VecEnv path AND Isaac Lab DirectRLEnv
path).
* DRONE_BLUEPRINT_PLAN.md: added Phase 3 follow-on commit 8; rewrote
§6 entry 17 to capture the architectural pivot (one Protocol →
two contracts) and the layered env-stack issues that informed it.
Promoted Phase 2.5 to the "Still pending" headline item.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Stops ariel's base package from owning Isaac-Lab-sensitive binary deps (numpy 2, torch, gymnasium), and unblocks two import chains that were dragging optional heavy deps into common code paths. This is the architectural prerequisite to actually running rl_games PPO on the Isaac Lab backend — the Phase 2.5 plan documented in §6 entry 15 / Phase 3 "Still pending" of DRONE_BLUEPRINT_PLAN.md. pyproject.toml — dependency ownership split: * `[project.dependencies]` trimmed to simulator-agnostic essentials. Base `numpy` is now pinned conservatively to `>=1.26,<2` (was `>=2.0.2`) so installing ariel into an Isaac Lab env doesn't drag in numpy 2's ABI and segfault sb3. * New optional extras: `rl-sb3` (gymnasium==1.2.1 + sb3>=2.7.0), `torch` (torch + torchvision), `viz` (opencv/pillow/panel/plotly/ kaleido), `fabrication` (cadquery), `experimental` (the long tail of attrs/deap/dm-control/ipykernel/jupyter/keyboard/manifold3d/ nevergrad/nicegui/omegaconf/polars/pyserial/pyvista). torch and gymnasium leave [project.dependencies] entirely — Isaac Lab's env owns those. README.md — installation matrix: * Documents `uv sync --extra rl-sb3 --extra torch` for the sb3 path, and crucially `pip install -e . --no-deps` for installing ariel into an Isaac Lab env without replacing simulator-owned binaries. src/ariel/ec/drone/genome_handlers/__init__.py — lazy imports: * Replaced eager handler imports with `__getattr__`-based lazy resolution. Importing `genome_handlers` no longer pulls in `fcl` (or any other optional heavy dep) just because something under the package is touched. Verified: `from ariel.ec.drone. genome_handlers import GenomeHandler` succeeds with fcl absent from sys.modules. src/ariel/body_phenotypes/drone/phenotype_assembly/parts/ — new fabrication package (added by user): * 4 CAD-part factories: `create_core_plate`, `create_arm_mount`, `create_motor_arm`, `create_motor_mount`. Imported by the assembly code; previously missing, so `fabrication` extra imports failed even with cadquery installed. .gitignore — source-tree `parts/` exception: * The pre-existing `parts/` rule at line 33 is the standard Python/buildout block; it was silently swallowing the new source-tree `parts/` package above. Added `!src/**/parts/` exception so source `parts/` packages are tracked normally; the buildout-style ignore still applies to output directories elsewhere. DRONE_BLUEPRINT_PLAN.md — extensive doc updates: * Phase 2.5 in "Still pending" rewritten with a concrete Option A execution recipe (clean conda env from Isaac Lab's environment.yml + `pip install -e . --no-deps` for ariel) and an acceptance checklist. Options B and C demoted to diagnostic-only fallbacks with their own minimal runbooks. * The old "Targeted dep pins" pending item replaced with a summary of what was implemented this session. * §6 entry 15 (the unified-env entry) expanded with the dependency-ownership split rationale. * New §6 entry 18 documenting the lazy-imports + parts/ fixes and the clean-env smoke validation across `rl-sb3`, `torch`, `viz`, `fabrication`, `experimental` extras. uv.lock — regenerated to match pyproject.toml's new dependency shape. Co-Authored-By: Keiichi Ito (Phase 2.5 architectural changes) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Closes two reproducibility gaps that Copilot's readiness review flagged on the otherwise-complete Phase 2.5 work: 1. **Vendor Isaac Lab's `environment.yml`** to `tutorials/pluggable_simulator/isaaclab-env.yml`, snapshotted at IsaacLab SHA `f4aa17f87e2`. The Option A recipe now references this vendored copy instead of `$ISAACLAB_ROOT/environment.yml`, so the recipe is reproducible across upstream Isaac Lab evolution. The file header documents the upstream SHA and reminds future maintainers to refresh deliberately, not silently follow upstream. 2. **Binary-guardrail check** added to the Option A recipe. Steps 4 and 6 of the recipe now snapshot the installed versions of `torch / torchvision / gymnasium / numpy` immediately before and after `pip install -e . --no-deps`, and diff them. The recipe exits non-zero with a clear error if ariel's install bumped any simulator-owned binary. Catches the failure mode that motivated the whole dependency-ownership split (numpy 2 / gymnasium 1.3 sneaking in via transitive resolution). The Option A acceptance checklist gained two new boxes for the pre-install snapshot and the post-install diff being empty (`BINARIES UNCHANGED ✓`). Phase 2.5 trial readiness moves from ~80% to closer to 100% on the doc/spec axis; the remaining work is purely the execution pass (creating the conda env, running the install, ticking the checklist) which needs a human session, not more docs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Makes the tutorial self-contained — readers don't have to dig into DRONE_BLUEPRINT_PLAN.md to find the conda env build. New §3 covers both backends: * §3a NumPy backend: one-line `uv sync --extra rl-sb3 --extra torch` for the ariel venv. * §3b Isaac Lab backend: full copy-paste recipe (vendored isaaclab-env.yml + `./isaaclab.sh -i` + ariel `--no-deps` install + binary guardrail diff). Mirrors the Option A recipe in DRONE_BLUEPRINT_PLAN.md §5; the design doc keeps the deeper "why" (env-stack issues, alternatives considered), the tutorial just shows you how to build the env. Renumbered downstream sections so the structure stays contiguous: §3 → §4 Running the shipped backends, §4 → §5 Adding your own simulator, §5 → §6 Why this matters. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Closes Phase 2.5 with all seven Option A acceptance boxes ticked except the last one (real rl_games PPO training), which is now unblocked. Executed the recipe end-to-end on 2026-05-27 — 72 env-steps through Isaac Sim PhysX in 0.4 s on 16 parallel envs, binaries unchanged. Code: lazy __init__.py refactor (4 files): Eager package-level imports were the failure mode that kept tripping us during the execution pass. Each retry surfaced a different missing dep — sympy, sqlalchemy, sqlmodel, pydantic_settings — none of which the Isaac Lab path actually needed, but all of which were dragged in by transitive __init__.py chains. * src/ariel/simulation/__init__.py: was eagerly importing ariel.simulation.mujoco_worker (needs mujoco). Now lazy. * src/ariel/ec/__init__.py: was eagerly importing Archive / EA / Individual / Population (needs sqlalchemy + sqlmodel + pydantic-settings). Now lazy via a single _LAZY_IMPORTS dispatch table. * src/ariel/body_phenotypes/drone/__init__.py: was eagerly importing operations (which needs ariel.ec.ea → pydantic-settings). Now lazy. * src/ariel/simulation/drone/__init__.py: was eagerly importing DroneSimulator (needs sympy). Now lazy. External API unchanged — `from ariel.ec import Archive` etc. still work; the import is just deferred until the symbol is accessed. Recipe fixes (DRONE_BLUEPRINT_PLAN.md §5 + tutorials/pluggable_simulator/README.md §3b): * Insert `source $ISAACLAB_ROOT/_isaac_sim/setup_conda_env.sh` as step 3b — missing prerequisite for bare `python` invocations to find isaacsim / omni.* / pxr on PYTHONPATH. `./isaaclab.sh -p` handled this internally so step 3 worked; bare `python` from step 7 onward did not. * Add step 6b: install pure-Python ariel deps that --no-deps skipped (networkx, rich, pydantic, pydantic-settings, sqlalchemy, sqlmodel, numpy-quaternion, matplotlib, mujoco), with `--constraint /tmp/ariel_phase25_binaries_before.txt` so pip can't bump the simulator-owned binaries. Skip evotorch + mujoco-mjx (they fight Isaac Lab's torch / jax / numpy). * Replace step 7's DroneGateEnv import smoke with a Blueprint-chain smoke (blueprint, decoders, backends). DroneGateEnv was the NumPy backend's env; importing it dragged in EA orchestration deps that the Isaac Lab path intentionally doesn't pull in. The Blueprint-chain test exercises exactly what step 8 needs. Acceptance checklist: marked the six trivially-testable boxes as done with timestamps and observed values; the seventh (rl_games PPO smoke) is the next session's task and explicitly flagged STILL PENDING. New §6 entries: * Entry 19: Lazy __init__.py is required across ariel's package surface. Documents the pattern (TYPE_CHECKING re-exports + _LAZY_IMPORTS dispatch + __getattr__), the rule (any package re-exporting from submodules should be lazy), and the future- maintenance recommendation (new __init__.py files start lazy, not refactor later). * Entry 20: Operational gotcha — failed Isaac Sim smoke runs leak processes. Documents the symptom (~120% CPU for hours after a 3-iteration smoke "ended"), the cause (Isaac Sim's app threads don't co-operatively shut down on launcher errors), the detection command (`ps -u $USER | grep train.py`), and the cleanup command (`pkill -KILL -f "tutorials/pluggable_simulator/ train.py"`). Observed five such orphans across Phases 2 and 2.5, cumulatively ~25 core-hours burned silently. Tutorial README also gets a §3c "Operational gotcha: stale Isaac Sim processes after a failed run" subsection mirroring entry 20, so users encountering the issue have the fix at hand without needing to dig into the design doc. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Last Option A acceptance box now ticks empirically. Full Blueprint
→ URDF → USD → IsaacLabBlueprintHoverEnv → rl_games PPO trains
end-to-end in the ariel-isaaclab-train conda env. 3 PPO epochs in
0.9 s on 16 envs, fps_total 719 → 2787 → 3318 across epochs.
train.py — `--mode {train, step}` flag:
* `--mode train` (default): runs the full rl_games training path
via Isaac Lab's `isaaclab_rl.rl_games` adapter and
`rl_games.torch_runner.Runner`. The agent config comes from
`make_rl_games_agent_cfg` in isaaclab_hover_env.py (mirrors Isaac
Lab's reference QuadcopterPPO config).
* `--mode step`: the previously-default random-action env-stepping
loop. Kept as an explicit alternative because it's faster and
useful for env-construction sanity / debugging the Isaac-Lab-side
env-stack without paying for a PPO run.
Restructured `main_isaaclab` into:
* `_isaaclab_step_smoke(env, args)`: random-action loop (unchanged
from prior commit, just extracted).
* `_isaaclab_rl_games_train(env, args)`: real PPO, mirrors Isaac
Lab's `scripts/reinforcement_learning/rl_games/train.py`. Wraps
env via `RlGamesVecEnvWrapper`, registers in rl_games' global
registries, builds `Runner(IsaacAlgoObserver())`, loads + resets +
runs `{"train": True, ...}`.
Tutorial README §4 (Isaac Lab subsection) rewritten to describe both
modes with explicit invocations; `train.py` example block in the
header docstring updated similarly.
DRONE_BLUEPRINT_PLAN.md updates:
* Phase 3 status header: "Largely landed" → "✅ Landed end-to-end
for rigid drones." Notes today's execution.
* Phase 2.5 acceptance checklist: last box (rl_games PPO smoke)
ticked with observed values (epoch fps, final reward, checkpoint
path).
.gitignore: added `runs/` (rl_games auto-creates ./runs/<exp>/nn/
when training launches from the repo root). Sits alongside the
existing source-tree `parts/` exception.
Phase 2.5 deliverables (full list):
- Dependency-ownership split in pyproject.toml (commit 53d5fb0)
- Vendored isaaclab-env.yml + binary guardrail (commit 7dfaea4)
- Tutorial env-setup section in README (commit 2613bef)
- Lazy __init__.py refactor + recipe corrections (commit 4b68081)
- Re-enabled rl_games PPO training (this commit)
The architecture validated end-to-end: pluggable-simulator
(commit 57592d4) + Phase 2 Isaac Lab env (commit 47a1af7) + Phase
2.5 dep / env work runs from one clean conda env via one
`train.py --simulator isaaclab` command.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- README §6: new stub for partners wiring their RL pipeline to ariel's EA layer (three roles, five-step recipe, forward link to companion). - connect_your_pipeline.md: companion doc with file-by-role table, in-process vs subprocess patterns, fitness-extraction options, common pitfalls, and measured calibration numbers (~160s for 3 gen x 4 ind x 30 PPO epochs). - evolve.py: subprocess-per-individual EA reference loop. Each individual gets a fresh Isaac Sim process; fitness comes from the rl_games checkpoint filename. - train.py: --blueprint-json + --experiment-prefix flags so the EA driver can hand in per-individual morphologies. Hard-exit via os._exit() after PPO to bypass simulation_app.close()'s ~120% CPU hang (orphan-thread pattern already noted in README §3c). - README cleanup: drop DRONE_BLUEPRINT_PLAN.md cross-refs and Phase 2/2.5 jargon that didn't mean anything to consortium partners; status paragraph rewritten to current reality. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Role 2 sketch in connect_your_pipeline.md called make_blueprint_usd with a positional output_dir, but the real signature is keyword-only (def make_blueprint_usd(blueprint, *, output_dir, robot_name="drone")). Copy-pasting the sketch would have raised TypeError. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contains a tutorial of the backend simulator+RL swapping.