Skip to content
Open

Cdx #41

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
6b9a2c9
add coupling to humanoid torques
sheim Mar 16, 2024
e52208f
add exp avg filtering
sheim Mar 16, 2024
54b826d
add oscillators and phase-based rewards, some tuning
sheim Mar 16, 2024
c9411cd
some tuning
sheim Mar 18, 2024
90ff50c
implement history with (approximated) arbitrary sampling frequency an…
sheim Mar 18, 2024
5020fd0
make pd gains specific for each robot
sheim Mar 19, 2024
82968b1
refactor sampled history to be more explicit and not overlap with `do…
sheim Mar 19, 2024
3ae04a0
properly roll histories, retune action_rate for mc
sheim Mar 23, 2024
ee05de4
enable arms in learnt urdf
sheim Mar 24, 2024
0aab100
hotfix old runner, and set as default for humanoid. New runner is num…
sheim Mar 24, 2024
d86162e
WIP: tuning, critic loss higher than expected
sheim Mar 29, 2024
816a18b
Merge branch 'dev' into humanoid
sheim Aug 6, 2024
098989a
fix hips_forward dimensionality
sheim Aug 6, 2024
0611bcd
lander env
sheim Aug 6, 2024
fd30865
unify humanoid and lander
sheim Aug 7, 2024
6248559
everything integrated and works
sheim Aug 27, 2024
1540cd2
fix faster training configs for benchmarking
sheim Aug 28, 2024
842b39e
just tweaks
sheim Aug 29, 2024
33efaf5
SAC: typo and params that work for pendulum
sheim Aug 29, 2024
fd06555
update ruff settings
sheim Aug 30, 2024
3550dfd
address deprecation in torch.load and add lr to trackables for SAC
sheim Aug 30, 2024
4247ea7
allow randomize_episode_counters for reset_to_uniform in pendulum
sheim Aug 30, 2024
66c9e1b
some slimmin and separation of utils
sheim Sep 3, 2024
dbd48c9
add layer norm to create_MLP, +kwargs flexibility
sheim Sep 3, 2024
7d97081
update for layernorm
sheim Sep 3, 2024
be2e990
wip
sheim Sep 4, 2024
3cd76b3
Merge branch 'dev' into humanoid
sheim Sep 4, 2024
2799110
Refactor for action frequency handled in runner
sheim Sep 4, 2024
0979fab
working SAC on pendulum, ready for merge
sheim Sep 6, 2024
54e7a8d
Merge branch 'psdNetworks' into dev
sheim Sep 8, 2024
1d3251f
hotfix: uncommited imports in init
sheim Sep 8, 2024
12e8327
Merge branch 'dev' into humanoid
sheim Sep 8, 2024
f105c0e
update nn_params
sheim Sep 9, 2024
c04b563
apply stash w/ sim-freq reward sampling.
sheim Sep 9, 2024
e395673
refactor skeleton with a super_init fix, and pre-initialize reward bu…
sheim Sep 9, 2024
ea5cdff
refactor: redo rewards computation, with a dict of reward functions i…
sheim Sep 9, 2024
7296c6c
compute switch once per decimation (speedup ~10%)
sheim Sep 9, 2024
69218dd
fixed logging bug that scaled with wrong dt
sheim Sep 10, 2024
b1bd4f2
hardcode Jacobian (halves time for _apply_coupling)
sheim Sep 11, 2024
08bb974
fixed config policy of osc
sheim Oct 22, 2025
de3212e
added option back in
sheim Oct 23, 2025
c0bda90
large refactor to get osc working again
sheim Oct 24, 2025
ec524f6
copilot rev fixes
sheim Oct 24, 2025
d9e2662
two test fixes: 1) reward shape in osc, 2) underactuation in fixed_robot
sheim Oct 31, 2025
3c4e6e5
modernized ruff formatting (apparently...)
sheim Oct 31, 2025
0606552
redo regression test to be standalone instead of running via CI
sheim Oct 31, 2025
7cf29c7
remove self-hosted unit tests, add cheap tests (gym, learning)
sheim Oct 31, 2025
c5a598f
change per-joint rewards to take the mean, to be more consistent acro…
sheim Nov 11, 2025
2022c82
merge in humanoid branch, which had some refactoring and bugfixes, in…
sheim Dec 10, 2025
2a7d1a1
ruff
sheim Dec 10, 2025
8b9fcb1
ruff
sheim Dec 10, 2025
1834328
catch sample history bug
sheim Dec 10, 2025
738b5d9
Merge pull request #37 from sheim/merge_humanoid
sheim Dec 10, 2025
b329655
remove old unused robots
sheim Mar 31, 2026
0153705
claude Phase 0, separate isaacGym backend code from base_task, preppi…
sheim Apr 2, 2026
05a51de
action plan and uv lock commited
sheim Apr 2, 2026
302f0a6
update plan for details of phase 1
sheim Apr 2, 2026
5d4ba51
WIP: works on CPU, not GPU (nvidia warp)
sheim Apr 7, 2026
ebc2925
WIP: fixed works on gpu and cpu
sheim Apr 7, 2026
1bdd0d8
backend runs for CPU, GPU relies on warp and newer python, and differ…
sheim Apr 8, 2026
63b5b3d
everything runs, but quadruped on GPU crashes partway through
sheim Apr 8, 2026
92cb8e9
good state, ready to test on macos
sheim Apr 8, 2026
2e28f8d
removed shims
sheim Apr 8, 2026
973b8d5
fix device assignment
sheim Apr 8, 2026
0abf893
update readme for macos
sheim Apr 8, 2026
bb8c981
runs on mac
sheim Apr 9, 2026
936a4cc
dynamically adjusts n_steps_per_env to get appropriate batch size
sheim Apr 20, 2026
6ef1f37
hook up wandb for train_mujoco
sheim Apr 20, 2026
45dcfc0
add play script
sheim May 8, 2026
fba2deb
terminate on contact properly
sheim May 8, 2026
2c5d64d
putting back mini cheetahs
sheim May 15, 2026
bfd6b2d
WIP: fixed props writing
sheim May 18, 2026
2bc709b
properly read in URDF joint limits
sheim May 18, 2026
4538b5e
reset some disabled configs
sheim May 18, 2026
83526ff
update visuals based on menagerie
sheim May 18, 2026
afa8642
make sky background base setting
sheim May 18, 2026
95b9a6e
fix pendulum training, add some visualization
sheim May 18, 2026
894cded
add keyboard interface
sheim May 21, 2026
bc2bd96
update plan
sheim May 21, 2026
8708c56
initial ruff format
JoshuaTchou Jun 23, 2026
831074e
hardcoded some warp model params for mini_cheetah to get around runti…
JoshuaTchou Jun 23, 2026
b6a6923
moved hardcoding of MjModel params to MujocoBackendBase
JoshuaTchou Jun 24, 2026
d734220
ruff format
JoshuaTchou Jun 24, 2026
513fbcb
check config for mjModel attributes instead of hardcode
JoshuaTchou Jun 25, 2026
daa3ef8
delete hardcoding of mjmodel params
JoshuaTchou Jun 25, 2026
8e2cfc7
implement state logging
JoshuaTchou Jul 1, 2026
e604532
state logging list instead of hardcode
JoshuaTchou Jul 8, 2026
2326b71
fixes root_states from not being updated. unknown why this works
JoshuaTchou Jul 8, 2026
163323c
fix mini_cheetah foot name
JoshuaTchou Jul 8, 2026
e7d8b0b
tuning reward weights
JoshuaTchou Jul 8, 2026
135adf2
set mujoco fusestatic option
JoshuaTchou Jul 9, 2026
15d3138
comment out logging debugging function
JoshuaTchou Jul 9, 2026
8e14174
add go2 env, also fix njmax bug
JoshuaTchou Jul 9, 2026
439a38e
delete print statement
JoshuaTchou Jul 9, 2026
5dd58f5
fix mujoco root tensor update (a la Joshua)
sheim Jul 11, 2026
c6fc8e6
ruff
sheim Jul 11, 2026
90d01f5
minor tweaks, still sucky
sheim Jul 11, 2026
93a4ee6
WIP: claude porting everything for vsim, but it currently fails on li…
sheim Jul 21, 2026
b947cb4
vsim working
sheim Jul 22, 2026
074955c
claude fabled used to generate claude opus skills
sheim Jul 21, 2026
99ea132
dimension error bugfix
sheim Jul 23, 2026
61af8fb
vsim works with both ref and osc
sheim Jul 23, 2026
bbc5cc2
fix keyboard commands for vsim
sheim Jul 23, 2026
0d735a9
parity between MJ_CPU/MJ_WARP/VSIM tested and checked on pendulum, in…
sheim Jul 27, 2026
c151cab
parity check for mini cheetah ref
sheim Jul 27, 2026
e787f90
WIP: robot layout
sheim Jul 28, 2026
d68b8bb
robot layout added for cross-back-end consistency
sheim Jul 28, 2026
f3728a0
fix cross-backend contact semantics
sheim Jul 28, 2026
bb4e811
URDF inertia fixes
sheim Jul 29, 2026
6fff514
WIP: tuning mini_cheetah
sheim Jul 29, 2026
cad0574
prep codex
sheim Aug 3, 2026
b01ba42
streamline tests
sheim Aug 4, 2026
87edf69
fix offending F
sheim Aug 4, 2026
593dad5
WIP: refacotring w codex
sheim Aug 4, 2026
c756ea3
removed lander
sheim Aug 4, 2026
0f599fd
fix cartpole URDF for inertias, and add untracked unit test
sheim Aug 4, 2026
3ec686c
WIP: removing isaacGym
sheim Aug 4, 2026
299f476
trimming out old isaac-gym only code and options
sheim Aug 4, 2026
ed5ca87
updated documentations, skills, and and reorganize tests
sheim Aug 4, 2026
d336089
renaming and adjusting to life without isaacgym
sheim Aug 5, 2026
fd9b18f
remove eval observer
sheim Aug 5, 2026
c501980
move eval(reset) into initialization
sheim Aug 5, 2026
f557b03
remove legacy naming
sheim Aug 5, 2026
8708969
add explanation for RobotLayout
sheim Aug 5, 2026
8b1604e
merge go2 branch
JoshuaTchou Aug 5, 2026
68bfb04
merge go2 branch and update go2, cfg
JoshuaTchou Aug 5, 2026
559a898
Merge branch 'cdx-merge' into cdx (adding go2 env)
JoshuaTchou Aug 5, 2026
c117c1d
fix bug: deprecated PATH name
sheim Aug 5, 2026
8cca8aa
update readmes for vsim
sheim Aug 6, 2026
5ab8715
update how vlearn is added/ignored
JoshuaTchou Aug 6, 2026
71382aa
sampling was weirdly not being tracked...
sheim Aug 6, 2026
a61952a
add fix_base_link back into config file for go2
sheim Aug 6, 2026
7d52849
basic trot sequence
sheim Aug 7, 2026
16e87fc
sinusoidal reference for residual policy
sheim Aug 7, 2026
ecbfcb6
restore original_cfg option
sheim Aug 7, 2026
7478bee
WIP: tuning. batch size makes a big diff
sheim Aug 7, 2026
28845ca
add parameter for total rollout-out collection size
sheim Aug 8, 2026
94acd7f
WIP: add some evaluation tools
sheim Aug 8, 2026
c64cfc9
WIP: freeze: smooth contact with sqrdexp. Policy learns well, but lif…
sheim Aug 8, 2026
5fcd377
WIP: add 'cross-dependent' trot reward
sheim Aug 8, 2026
bbea25d
WIP: good checkpoint
sheim Aug 9, 2026
73652f0
fix original_cfg flag loader
sheim Aug 9, 2026
f7c1b89
rename go2 env to go2trot
sheim Aug 9, 2026
66d9376
some of the testing and evaluation scripts updated
sheim Aug 10, 2026
7d82334
recover vanilla go2
sheim Aug 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .agents/skills/q2-backend-development/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
name: q2-backend-development
description: Implement, modify, or review Q2 physics backends and their task-facing state contract. Use for changes under gym/envs/base involving SimBackend, MuJoCo CPU or Warp, VSim, RobotLayout, state tensors, reset ordering, quaternion conversion, contacts, asset import, backend selection, or a new physics engine.
---

# Q2 Backend Development

Read `AGENTS.md`, `gym/envs/base/sim_backend.py`,
`gym/envs/base/robot_layout.py`, the affected backend, and its contract tests.
Read the relevant current section of `MIGRATION_PLAN.md` for parity decisions.

## Preserve the public contract

- Leave every public tensor valid after `setup()` and updated in place after
`step()` and reset. Tasks cache tensor objects; property getter side effects
do not satisfy liveness.
- Expose canonical `RobotLayout` order for DOFs, bodies, torques, contacts,
`dof_state`, and `rigid_body_states`. Keep engine-native indices private.
- Keep `dof_state` persistent with writable `dof_pos`/`dof_vel` views. If an
engine stores positions and velocities separately, gather into a persistent
assembled buffer and scatter public reset writes back to native storage.
- Follow write-then-commit resets. Do not refresh native root state over a
pending public `root_states` write between DOF and root commits.
- Keep task quaternions scalar-last `[x, y, z, w]`; convert once at the
backend boundary.
- Interpret input torques as canonical full-DOF generalized forces. Apply
free-joint offsets and native permutations in the backend.
- Expose robot-only bodies and world-frame contact force vectors in Newtons.
Build semantic contact groups in canonical space.

## Make a backend change

1. State the engine's native conventions: quaternion order, pose/velocity
layout, contact force meaning and frame, actuation interface, asset losses,
batching, device support, and deterministic behavior.
2. Decide which tensors are native views and which are assembled copies. Name
the exact refresh and scatter sites for each.
3. Implement fixed-base pendulum setup/step/reset first. Fail immediately on
unsupported devices or joint types.
4. Add the backend fixture and run shared contract and damped-energy tests.
5. Compare pendulum lockstep or analytic behavior against MuJoCo CPU.
6. Add floating-base root state, canonical body state, ground/contact support,
and partial resets.
7. Add named routing, legged contract, termination, and task-level liveness
tests before RL smoke tests.
8. Wire selection through `task_registry.select_backend()` without fallback.
9. Benchmark only after correctness gates pass; record environment count,
timestep, rollout geometry, device, warmup, and warnings.

## Engine-specific scars

- MuJoCo imports URDF effort/velocity limits incompletely; Q2 reparses them in
`urdf_limits.py`. Preserve that path and add asset-specific tests.
- MuJoCo may fuse fixed-linked bodies; Q2 disables `fusestatic` so canonical
bodies such as feet remain addressable.
- MuJoCo uses scalar-first quaternions, angular-first body velocities, and
`[torque, force]` spatial contact arrays. CPU and Warp must both call the
post-constraint RNE operation before exposing contact forces.
- MuJoCo Warp native arrays are zero-copy, but canonical/swizzled tensors are
assembled. Refresh them eagerly. Forward `njmax` to Warp data allocation;
a constraint overflow is incorrect physics, not a harmless warning.
- MuJoCo CPU and Warp model construction belongs in
`mujoco_backend_base.py`. Avoid backend-specific physics drift.
- VSim motor, articulation, body, and sensor order are independent. Route by
exact native indices/names, rotate link-attached force components to world
axes, and close its process singleton cleanly.
- Per-engine config pass-throughs must be explicit, validated, and covered by
a test showing that the engine actually consumes them.

## Validate

Start with targeted tests, then run:

```bash
uv run --frozen python -m pytest -q
```

For VSim changes also run:

```bash
bash scripts/run_vsim_tests.sh
```

A GPU-specific test skipped on a CPU machine is not evidence that the GPU path
works. For physics claims, add a predicted invariant, lockstep comparison, or
fidelity probe. For state/reset/contact bugs, land the regression test with
the fix and update `MIGRATION_PLAN.md` if campaign evidence changes.
4 changes: 4 additions & 0 deletions .agents/skills/q2-backend-development/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "Q2 Backend Development"
short_description: "Develop Q2 physics backends safely"
default_prompt: "Use $q2-backend-development to change a Q2 physics backend without breaking its contracts."
75 changes: 75 additions & 0 deletions .agents/skills/q2-development-environment/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
name: q2-development-environment
description: Set up, repair, and verify Q2's uv-managed .venv across Linux CPU, Linux NVIDIA GPU, macOS, and the optional licensed VSim backend. Use for fresh checkouts, dependency or Python problems, import failures, platform mismatches, CUDA/Warp setup, VSim loader or license failures, and local-versus-CI discrepancies.
---

# Q2 Development Environment

Read `AGENTS.md`, `.python-version`, `pyproject.toml`, `uv.lock`, and the
relevant setup section of `README_MUJOCO.md` before changing dependencies.
`pyproject.toml` and `uv.lock` are the only dependency sources of truth.

## Establish the target

- Use uv to create and manage the repository's `.venv`.
- Use Python 3.11 for the common tested environment and VSim wheel
compatibility. The package metadata permits Python 3.11 through 3.13.
- Use MuJoCo CPU for portable/headless development and the Linux CPU viewer.
- Use MuJoCo Warp only with a working NVIDIA driver and CUDA-visible PyTorch.
- Use VSim only when the machine has the local wheel, system library, node
license, and CUDA. Never replace a requested backend with another silently.

## Create or update the environment

Use the locked dependency graph for ordinary development:

```bash
uv sync --frozen
uv run --frozen python -c "import mujoco, torch; print(mujoco.__version__, torch.__version__)"
uv run --frozen python -m pytest -q
```

Use `.venv/bin/python` directly only when a tool must bypass uv resolution.

For MuJoCo Warp:

```bash
uv sync --frozen --extra gpu
uv run --frozen python -c "import torch, mujoco_warp; print(torch.cuda.is_available())"
```

Require the final command to print `True`. If it does not, inspect
`nvidia-smi`, the PyTorch build, and device visibility; do not add a CPU
fallback.

For VSim, follow `thirdparty/vlearn/README.md` exactly. Install the local wheel
with `uv sync --locked --extra vsim`; start every process with
`uv run --env-file .env.vsim ...`; validate using
`bash scripts/run_vsim_tests.sh`. Do not print or inspect license contents.

## Diagnose by boundary

- Resolution/install failure: compare `pyproject.toml`, `uv.lock`, local wheel
presence, and exact uv flags. Do not casually regenerate the lockfile.
- Python mismatch: check `uv run --frozen python --version` and
`sys.executable` before debugging imports.
- Warp import but no CUDA: confirm driver visibility and the installed torch
build separately.
- Long first Warp step: distinguish kernel compilation from a deadlock using
the traceback and GPU activity before interrupting it.
- VSim loader errors: environment variables must exist before process start;
in-process changes to `LD_LIBRARY_PATH` are too late.
- VSim license errors: verify paths and activation state without reading,
logging, or committing secrets. License repair may require the vendor.
- macOS viewer errors: use `mjpython` with the Homebrew-Python recipe in
`README_MUJOCO.md`, or validate headless behavior.
- CI mismatch: inspect `.github/workflows/` directly. CI runs the uv-managed
portable and colocated suites, Ruff, and a package build, but does not cover
smoke training, Warp, or licensed VSim.

## Change dependencies

Explain why a dependency belongs in the modern core, `gpu` extra, `vsim`
extra, or dev group. Update `pyproject.toml` and the lockfile together, then
test a clean sync appropriate to every affected platform. Update
`README_MUJOCO.md` when setup steps or supported versions change.
4 changes: 4 additions & 0 deletions .agents/skills/q2-development-environment/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "Q2 Development Environment"
short_description: "Set up and verify Q2 development"
default_prompt: "Use $q2-development-environment to set up and verify this Q2 checkout."
87 changes: 87 additions & 0 deletions .agents/skills/q2-rl-development/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
name: q2-rl-development
description: Design, implement, or review Q2 reinforcement-learning behavior, including observations, actions, rewards, PPO2, SAC, actors and critics, storage, normalization, runner data flow, and tuning methodology. Use for changes under learning/, reward or observation code in task classes, algorithm hyperparameters, network architecture, rollout geometry, inference, checkpoint state, or training-quality claims.
---

# Q2 RL Development

Read `AGENTS.md`, the selected task and runner config, the active runner and
algorithm, and their focused tests. Confirm which configured class names are
actually instantiated; the tree includes legacy and experimental paths.

## Trace data before editing

For the main on-policy path, trace one update end to end:

1. Actor/critic observation names are resolved from environment attributes.
2. `TaskSkeleton.get_state()` divides named states by configured scales.
3. The actor emits actions; runner assignment multiplies action states by
their scales.
4. The environment steps the backend for its configured decimation.
5. `DictStorage` records transitions for the collected temporal horizon.
6. `PPO2` performs repeated optimizer minibatches without recounting the same
rollout as fresh normalization data.
7. The logger records total and per-term episode metrics and checkpoints model,
optimizer, iteration, and normalization state.

Do not infer behavior from a config field alone; find its consumer.

## Observations and actions

- Keep actor and critic observation lists explicit. Every listed attribute must
exist with stable shape; every scaled attribute needs a scaling entry.
- Keep canonical joint/body order at the task boundary. Express semantic
subsets with cached `RobotLayout` group indices, not slices.
- Keep inference deterministic: switch modules/normalizers to evaluation mode
and use clean observations. Noise belongs only in rollout collection.
- Update observation statistics once per fresh rollout population. Freeze them
during repeated optimizer epochs, and save/load them with the policy.

## Rewards

- A nonzero runner-config weight selects `_reward_<name>`; zero weights should
remove unused computation. Each reward returns shape `[num_envs]`.
- `_sqrdexp(error)` is maximized when `error == 0`. Write down the intended
optimum before coding; do not pass a raw target quantity whose optimum is
elsewhere.
- Use means for comparable per-joint penalties so magnitude transfers across
robots. Use sums only when physical total magnitude is intended and tested.
- Keep termination handling separate from ordinary weighted rewards.
- When changing reward math, add a small test for its zero point, sign, scale,
shape, and boundary behavior before training.

## Rollout and optimizer geometry

Treat these as separate controls:

- `rollout_batch_size`: total new transition samples collected per update;
together with `num_envs`, it determines consecutive steps per environment.
- `batch_size`: optimizer minibatch size.
- `max_gradient_steps`: number of actor/critic optimization steps.

When comparing backends or configurations, hold temporal horizon and collected
sample count constant unless that variable is the experiment. Equal minibatch
size alone does not make two PPO experiments equivalent.

Discount and GAE values may be derived from physical horizons and control dt.
Re-run frequency conversion rather than editing derived values.

## Evidence workflow

1. State the proposed mechanism and a result that would falsify it.
2. Predict direction and useful numeric bounds before running.
3. Add a unit test for deterministic math, storage, normalization, inference,
or checkpoint behavior.
4. Run same-seed, same-task, same rollout-geometry before/after experiments.
5. Compare per-term rewards, episode duration/survival, action statistics,
losses/KL, throughput, and domain-relevant physical metrics. Do not select
only on aggregate reward or a viewer impression.
6. Record failed or invalid experiments in `MIGRATION_PLAN.md` when they affect
the active campaign. Keep tuning changes numerically explicit and separate
from algorithm/refactor changes.

Validate with focused learning tests and then:

```bash
uv run --frozen python -m pytest -q
```
4 changes: 4 additions & 0 deletions .agents/skills/q2-rl-development/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "Q2 RL Development"
short_description: "Design Q2 rewards and learning changes"
default_prompt: "Use $q2-rl-development to change Q2 rewards, observations, or learning code."
97 changes: 97 additions & 0 deletions .agents/skills/q2-task-authoring/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
name: q2-task-authoring
description: Add or modify a Q2 robot, environment, task variant, asset, config, or registry entry end to end. Use when introducing a URDF, creating fixed-base or legged tasks, adding semantic robot groups, changing task observations/actions/rewards, registering a task, or making an existing task work across MuJoCo CPU, Warp, and optional VSim.
---

# Q2 Task Authoring

Read `AGENTS.md`, the nearest existing task and config, the appropriate base
robot class/config, `gym/envs/__init__.py`, `robot_layout.py`, and task-focused
tests. Copy the nearest semantic example, not merely the newest file.

## Choose the task shape

- Use `FixedRobot` for a base attached to the world. Its MuJoCo path disables
contacts and has no `root_states` commit.
- Use `LeggedRobot` for a free base, ground contact, canonical body state, and
contact-driven termination/rewards.
- Prefer a config/task variant when physics and robot layout are shared. Do
not fork backend logic into a concrete task.

## Add the asset

- Place URDFs below `resources/robots/<robot>/`. Give every actuated joint
finite lower/upper, effort, and velocity limits.
- Keep source inertias physically valid: positive principal moments satisfying
the triangle inequality. Add a parser-level regression for repaired assets.
- Prefer supported `.stl`/`.obj` visual meshes; MuJoCo strips unsupported DAE
visuals. Keep collision geometry independent of visual availability.
- Keep files below the repository's 100 KB limit; never solve this by
force-adding a binary.
- Define an explicit `asset.robot_layout` when policy-facing order or semantic
groups matter. Canonical names must exactly cover movable URDF joints and
robot links. Define groups such as legs, feet, or end effectors by exact
names; avoid semantic slices and substring order assumptions.

## Add configuration

Create environment and runner config subclasses in the task package.

- Set `env.num_envs`, actuator count, episode length, asset path/base mode,
initial state, control frequencies, terrain/contact lists, scaling, and
robot layout explicitly.
- Set actor/critic observation attribute lists, action state names, algorithm
sampling/optimization parameters, reward weights, and experiment name.
- Treat `ctrl_frequency` and `desired_sim_frequency` as inputs. Never assign
derived dt/decimation values in the task config.
- Make required config axes required. If a backend does not implement a
configured feature such as per-env domain randomization, disable or document
it explicitly rather than implying that it works.

## Implement the task

- Keep engine imports and native indices out of concrete task code.
- Preserve the constructor's legacy positional parameters and forward
`backend=` to the base class.
- Build observations from stable environment attributes; add matching scales
for every scaled state. Keep action tensors and actuator routing in
canonical order.
- Name rewards `_reward_<config_weight>`, return `[num_envs]`, and use exact
semantic group indices cached at setup.
- Use zero-error inputs with `_sqrdexp`; reduce per-joint terms with `mean`
unless scale-by-DOF is explicitly intended.

## Register and package

Add all four mappings in `gym/envs/__init__.py`: `class_dict`, `config_dict`,
`runner_config_dict`, and `task_dict`. Update setuptools package/data discovery
so the built wheel contains the task module and its required assets. Imports
are fail-fast; inspect the live registry after adding the declarations:

```bash
uv run --frozen python -c "import gym.envs; from gym.utils.task_registry import task_registry; print(sorted(task_registry.task_classes))"
```

Do not treat an editable-tree import as packaging proof. Build the wheel and
smoke-import the registered task from an isolated installation.

## Prove the task

1. Add registry, layout/routing, asset-limit/inertia, and reward/observation
shape tests appropriate to the task.
2. Run the full unit gate:

```bash
uv run --frozen python -m pytest -q
```

3. Smoke train the CPU path with few environments and iterations, headless and
without W&B. Use the new task name:

```bash
uv run --frozen scripts/train.py --task TASK --backend mujoco --device cpu --num_envs 8 --max_iterations 2 --headless --disable_wandb
```

4. Exercise Warp and VSim only after CPU correctness, with their real contract
tests and exact-name routing checks. A skipped optional-backend test is not
a pass. Update `README_MUJOCO.md` if the public task list changes.
4 changes: 4 additions & 0 deletions .agents/skills/q2-task-authoring/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "Q2 Task Authoring"
short_description: "Add and modify Q2 robot tasks"
default_prompt: "Use $q2-task-authoring to add or modify a robot task in Q2."
Loading