You walk a user through onboarding a new robot platform to COMPASS — generating the right config files, registering the embodiment, and verifying the robot spawns correctly. The handbook's extending.md is the canonical written guide; this skill is the operational sibling that does the work interactively.
This skill assumes the docker-as-venv environment from the compass skill — source ./docker/activate already done, container up. If the user hasn't set that up, recommend /compass first.
When NOT to use this skill
- The user wants to switch between built-in embodiments (carter / h1 / spot / g1 / digit) → just use
--embodiment <name>onrun.py. No code change needed. - The user is adding a new scene (USD), not a new robot → that's
/compass(Register Scene). - The user has registered a robot but training fails → run
/compass-doctorfirst to surface the actual error.
Workflow
Step 1: Parse what the user already supplied
A user prompt like "add a new robot called Galileo at /workspace/galileo.usd, similar to Spot" already contains three of the four fields the skill needs. Extract them first; only ask about what's missing or genuinely ambiguous. Don't re-ask for things the user already said — that's the dialogue-bot trap.
The four fields:
- Robot name (lowercase identifier like
galileo; used in CLI flags and config keys). - USD path (absolute or repo-relative; the asset that will be spawned).
- Base-class to inherit from (which existing pattern to mirror). See "Base-class choice" below.
- (Optional) display name for docs (e.g., "Galileo").
Step 2: Ask only for what's missing (AskUserQuestion)
If any of the three required fields are missing or ambiguous, ask in one batch. Sample question structure:
| Field | Question | Options |
|---|---|---|
| Robot name | "What's the robot's identifier?" | free text (default: lowercase the user's name) |
| USD path | "Where's the robot's USD file?" | free text (suggest checking ./assets/usd/ first) |
| Base-class | "Which existing robot's pattern is the best fit?" | wheeled (carter), quadruped (spot), humanoid (h1, g1, digit) |
For the base-class question, surface the trade-off in the option descriptions:
- wheeled: single base, velocity over base; simplest to onboard. Mirror
carter. - quadruped: articulated legs, ABS-style controller. Mirror
spot. - humanoid: full body; more complex action space. Mirror
h1(org1/digitfor smaller form factors).
Step 3: Read the existing-pattern files
Before generating anything, read the two files that match the user's base-class choice:
| Base class | Robot block | Env cfg file |
|---|---|---|
| wheeled | carter block in compass/rl_env/exts/mobility_es/mobility_es/config/robots.py |
compass/rl_env/exts/mobility_es/mobility_es/config/carter_env_cfg.py |
| quadruped | spot block in same robots.py |
compass/rl_env/exts/mobility_es/mobility_es/config/spot_env_cfg.py |
| humanoid | h1 block in same robots.py |
compass/rl_env/exts/mobility_es/mobility_es/config/h1_env_cfg.py |
Read both top-to-bottom. Don't skim — joint names, action term wiring, and reward shaping all come from this file. Confirming the reference exists before writing keeps you from generating content based on outdated assumptions.
Step 4: Show the diff before writing
Generate a preview of what will be created or modified:
- New ArticulationCfg block to be appended to
compass/rl_env/exts/mobility_es/mobility_es/config/robots.py. Mirror the matching reference, swap robot name + USD path + joint config. - New file:
compass/rl_env/exts/mobility_es/mobility_es/config/<robot_name>_env_cfg.py. Mirror the matching reference; swap class name (e.g.,<RobotName>GoalReachingEnvCfg),scene.robotto point at the new ArticulationCfg, action term to whatever joint controller fits. - Edit
run.py:- Add import:
from mobility_es.config.<robot_name>_env_cfg import <RobotName>GoalReachingEnvCfg. - Add row to
EmbodimentEnvCfgMap:'<robot_name>': <RobotName>GoalReachingEnvCfg,(around line 116–122).
- Add import:
- Optional gin update: if the user wants
<robot_name>to be the default embodiment, editconfigs/shared.gin'sembodimentfield. By default, leave existing default in place and let the user pass--embodiment <robot_name>on the CLI.
Show the user each preview block (or unified diff). Ask for confirmation before writing.
Anti-pattern guard: never silently write multi-file scaffolding. Robot onboarding is high-blast-radius — wrong joint counts or an inverted action sign can cause the robot to flail into the floor in simulation. The diff-then-confirm gate is non-negotiable.
Step 5: Apply the changes
After confirmation, write the files and edit run.py. Use the Edit tool for run.py (one Edit per insertion: import + map row). Use Write for the new env_cfg.py. For robots.py, use Edit to append the new ArticulationCfg block at the end (read the file first to find the right insertion point — the last existing config).
Step 6: Smoke test
Verify the robot spawns by running training with --num_envs 1 and without --headless so the user can see the robot appear:
python run.py \
-c configs/train_config.gin \
--enable_cameras \
-o /tmp/<robot_name>_smoke \
-b ./assets/x_mobility.ckpt \
--logger tensorboard \
--embodiment <robot_name> \
--environment warehouse_single_rack \
--num_envs 1
Use run_in_background: true. Tell the user to watch the GUI:
- Robot spawns at the configured initial pose (typically (0, 0, ~1.0)).
- Robot doesn't immediately fall through the floor (z-init too low) or shoot up (z-init too high).
- First PPO iteration completes without joint-controller errors in the log.
If the robot misbehaves, route to /compass-doctor for a deeper diagnostic. Common first-onboarding issues:
- Z-init too low → robot clips through floor → bump
init_state.pos[2]. - Joint names mismatch → ArticulationCfg fails to load → recheck against the USD's joint hierarchy.
- Action term sign flipped → robot drives backwards → invert sign in the action term.
Step 7: Document the new embodiment (optional)
Once smoke test passes, suggest the user add their robot to docs/handbook/extending.md (under "Built-in embodiments" or as a new subsection). This is optional — many users keep their custom embodiment private. Don't push the doc change if the user is in a hurry; just flag it for later.
Reference: file map
| File | What changes |
|---|---|
compass/rl_env/exts/mobility_es/mobility_es/config/robots.py |
Append new ArticulationCfg block |
compass/rl_env/exts/mobility_es/mobility_es/config/<robot_name>_env_cfg.py |
New file (mirror matching base-class reference) |
run.py |
Add import; add EmbodimentEnvCfgMap row (~L116–122) |
configs/shared.gin |
Optional default override; usually leave alone |
docs/handbook/extending.md |
Optional doc update (suggest, don't enforce) |
Reference: base-class examples
- Wheeled (carter): see
carterblock atrobots.py:23andcarter_env_cfg.py. - Quadruped (spot): see
spotblock atrobots.py:275andspot_env_cfg.py. - Humanoid (h1): see
h1block atrobots.py:72andh1_env_cfg.py.
For canonical written guidance (joint config, controller selection, reward shaping), the handbook's extending.md covers depth this skill won't replicate.