# Training and evaluation details Command-level companion to the root README. Covers demo collection, behaviour cloning, PPO fine-tuning, and evaluation flags; use the root README for the high-level architecture and Webots quick start. The pipeline is two strictly-sequential stages per `(drive, world)` combo: ``` sim demos (universal teacher on tracker output, K=4 frame stack) │ ▼ bc/pretrain.py ──► runs/bc__ (MLP) │ ▼ KL-regularised PPO fine-tune │ runs/rl__ (deployed `rl` mode) ``` ## Files ``` herding_env.py — Gymnasium env (LiDAR raycast + tracker by default) bc/collect.py — universal-teacher sim demos bc/pretrain.py — MSE + cosine BC of (obs, action) demos into MlpPolicy rl/train.py — KL-regularised PPO fine-tune of a BC checkpoint rl/train_lstm.py — RecurrentPPO variant (ablation) eval.py — multi-seed analytic / learned policy comparison runs/ — checkpoints (gitignored except for policy.zip) ``` Unit + integration tests live in the top-level `tests/`. Run with `make test` or `python -m pytest tests/`. ## End-to-end pipeline The simplest way to train one combo is the project-root Makefile: ```bash make DRIVE=differential WORLD=field # demos → bc → rl → eval make DRIVE=differential WORLD=field_round make train_all # all four combos sequentially ``` The individual stages below are kept explicit for cases where you want to tune a single step. ```bash # 1. Sim demos with the active-scan + universal teacher under LiDAR # perception. K=4 frame stack so the MLP has temporal context. python -m training.bc.collect \ --teacher universal --drive-mode differential --world field \ --out training/bc/demos_differential_field.npz \ --seeds-per-n 15 --subsample 3 --frame-stack 4 # 2. Behaviour-clone the demos. python -m training.bc.pretrain \ --demos training/bc/demos_differential_field.npz \ --out training/runs/bc_differential_field \ --epochs 60 --net-arch 512,512 # 3. KL-regularised PPO fine-tune of bc. python -m training.rl.train \ --bc training/runs/bc_differential_field \ --out training/runs/rl_differential_field \ --drive-mode differential --world field \ --total-timesteps 1000000 # 4. Multi-seed eval (env-side, fast). python -m training.eval --policy training/runs/rl_differential_field \ --drive-mode differential --world field \ --max-flock 10 --max-steps 15000 --n-seeds 10 ``` `bc/pretrain.py` saves the **best-val_cos** snapshot, not the final epoch — multi-modal teachers make training noisy and the last epoch is often worse than an earlier one. `rl/train.py` loads BC weights into both a trainable policy and a frozen reference, fixes `log_std` small, and adds `β · KL(π‖π_ref)` to the loss so the policy can only move within a trust region around BC. See the file header for hyperparameter rationale. ## Mecanum retraining For mecanum runs, pass `--use-webots-preset`. Both `collect.py` and `train.py` detect `--drive-mode mecanum` and switch to the `HERDING_MEC_WEBOTS` preset, which matches the physical-roller Webots proto's strafe efficiency (~0.4) and forward bleed (~−0.28). Training without this preset produces a policy that herds in textbook gym mecanum but not in Webots. ## Analytic teachers | Name | What it does | Notes | |---|---|---| | `strombom` | Strömbom 2014 — collect when flock is scattered, drive CoM otherwise | Round-world aware (radially-inward fallback when natural target lies outside the curved boundary) | | `sequential` | Three-phase: collect, drive, then single-target push for the last 1–2 stragglers | Alternative to strombom | | `universal` | Strömbom core + mecanum omega + last-straggler recovery | Used as the BC demo teacher | All three are wrapped at demo-collection time in `herding/control/active_scan.py:ActiveScanTeacher`, which adds an opening in-place rotation, walk-to-centre when the LiDAR sees nothing, and near-sheep speed modulation (same modulation `herding/control/modulation.py` applies to every dog mode at inference). ## Evaluating analytic teachers directly ```bash python -m training.eval --policy strombom \ --drive-mode differential --world field \ --max-flock 10 --max-steps 15000 --n-seeds 10 python -m training.eval --policy sequential \ --drive-mode differential --world field_round \ --max-flock 10 --max-steps 15000 --n-seeds 10 ```