Part V · Frontiers & Capstone

22.Capstone: An End-to-End Learned Robot in Rust

Kober §7 disciplineTang §3.4 rubricFerris
By analyzing a simple problem in some detail we demonstrate how reinforcement learning approaches may be profitably applied, and we note throughout open questions and the tremendous potential for future research.
Jens Kober, J. Andrew Bagnell & Jan Peters · On the discipline of a worked case study
Reinforcement Learning in Robotics — A Survey, IJRR 2013

One project, using the whole book. Ferris must patrol a cluttered course, reach a sequence of waypoints, and recover from being pushed. We specify the task, formalize the MDP with every choice justified against evidence from Parts III and IV, build the randomized simulation, train teacher–student PPO, evaluate against the L0–L5 rubric with statistics that survive scrutiny, and ship both a native binary and a browser demo. The deliverable is not a trained policy — it is a reproducible pipeline you can fork for your own robot.

Foundation

The assembled POMDP: a 48-dimensional observation with units, the full reward table, the randomization ranges, and the evaluation protocol.

Conceptual

Mission control — training curves, randomization draws, evaluation heatmaps and a failure-mode gallery with post-mortems.

Practical

The capstone crate: serde/clap config, rayon rollout farm, burn training, rerun telemetry, and a WASM deployment.

After this chapter you can

  • Write a complete formal problem statement for a real robot task, with every design choice justified
  • Build a config-driven experiment runner whose results reproduce exactly from a seed
  • Assemble the teacher–student pipeline end to end and know what each stage contributes
  • Evaluate a policy against the L0–L5 rubric with confidence intervals that reflect the sample size
  • Diagnose failures from telemetry rather than from guesswork
  • State honestly what level this work reaches and what each further level would require

22.1 The specification, written before any code

Kober's survey closes with a case study, and the discipline it models is worth copying: write the specification before touching the implementation. Most robot-learning projects fail at this step rather than at training.

Task. Ferris patrols a course of randomly-generated rough terrain with scattered obstacles, visiting a sequence of waypoints in order. He must recover from external pushes and from stumbles, and complete the circuit within a time budget.

Success criteria, stated so a disinterested party could check them:

  • Visits all four waypoints in order, within 3 minutes.
  • Survives at least three lateral pushes of 150 N applied for 0.2 s at random times.
  • No base-ground contact (a "fall") at any point.
  • Mean cost of transport below 1.2.

Explicit non-goals. Not: manipulation of any kind, navigation of unmapped buildings, operation among people, or terrain types outside the generated distribution. Stating these matters — an unbounded task specification is how projects acquire scope that no evaluation can cover.

22.2 The formal problem

Now the MDP, with each choice traceable to a chapter.

Observation (48 dimensions; what the deployed student sees):

ComponentDimUnitsJustification
Base angular velocity3rad/sIMU; directly measured (Ch 18)
Projected gravity3Yaw-invariant orientation (Ch 18)
Waypoint vector (body frame)3mThe task; body frame for translation invariance
Joint positions12radEncoders
Joint velocities12rad/sDifferentiated encoders
Previous action12radEnables smooth output (Ch 18)
Gait phase2(sinϕ,cosϕ)(\sin\phi,\cos\phi) clock (Ch 17)
Time remaining1Normalized; makes the finite horizon Markov (Ch 4)

Privileged observation (teacher only, +31 dimensions): terrain heights on a 4×4 grid under the body, true friction, per-foot contact states, applied external force, and true base linear velocity. Discarded after distillation (Ch 15).

Action. Twelve joint position targets at 50 Hz, tracked by a 1 kHz PD loop with Kp=40K_p = 40, Kd=1K_d = 1. Mid-level, per Chapter 17 and universal practice in Chapter 18.

Reward. The Chapter 18 locomotion terms, plus task terms:

TermFormulaUnitsWeight
Waypoint progressΔdist\Delta \text{dist} to next waypointm+2.0
Waypoint reachedindicator+50.0
Velocity trackingexp(vxyv2/0.25)\exp(-\|v_{xy}-v^*\|^2/0.25)+1.0
Orientationgproj,xy2\|g_{\text{proj},xy}\|^2−5.0
Effortτ2\|\tau\|^2N²m²−2×10⁻⁴
Foot air timef(tair0.5)\sum_f (t_{\text{air}} - 0.5)s+1.0
Foot slipfvf21[contact]\sum_f \|v_f\|^2\mathbb{1}[\text{contact}]m²/s²−0.1
Action rateatat12\|a_t - a_{t-1}\|^2rad²−0.01
Fallindicator−100.0 (terminates)

Waypoint progress is potential-basedγΦ(s)Φ(s)\gamma\Phi(s') - \Phi(s) with Φ=dist\Phi = -\text{dist} — so by Chapter 14's Theorem 14.1 it accelerates learning without changing the optimal policy. The waypoint bonus is the actual objective.

Randomization (Ch 15): link masses ±20%, friction 0.4–1.2, motor KpK_p ±30%, latency 0–30 ms, IMU noise, terrain roughness scheduled by curriculum, and random pushes of 50–200 N.

22.3 The pipeline

Five stages, each an earlier chapter cashed in.

  1. Environment — Ferris in rapier3d, procedural terrain, 4096 parallel instances via rayon (Ch 13, 15).
  2. Teacher — PPO with privileged observations, terrain curriculum with per-environment promotion (Ch 10, 18).
  3. Student — GRU policy over a 15-step observation history, trained by DAgger-style distillation on its own state distribution (Ch 15, 16, 19).
  4. Evaluation — held-out terrain seeds, the push protocol, L0–L5 rubric with Wilson intervals (Ch 14, 20).
  5. Deployment — native binary plus a WASM build with live telemetry.
Rustcapstone/src/main.rs
rust
use clap::Parser;
use serde::{Deserialize, Serialize};
 
#[derive(Parser)]
#[command(name = "ferris-capstone")]
struct Cli {
    /// Path to the experiment config. Everything reproducible lives here.
    #[arg(short, long, default_value = "configs/patrol.toml")]
    config: String,
 
    #[arg(short, long)]
    stage: Stage,
 
    /// Overrides the config seed; recorded in the results either way.
    #[arg(long)]
    seed: Option<u64>,
}
 
#[derive(Clone, Copy, clap::ValueEnum)]
enum Stage { Teacher, Student, Evaluate, Export }
 
#[derive(Serialize, Deserialize, Clone)]
struct ExperimentConfig {
    seed: u64,
    env: EnvConfig,
    randomization: RandomizationRanges,
    curriculum: CurriculumConfig,
    reward: Vec<RewardTermConfig>,   // weights live in config, never in code
    ppo: PpoConfig,
    distillation: DistillConfig,
    evaluation: EvalConfig,
}
 
fn main() -> anyhow::Result<()> {
    let cli = Cli::parse();
    let raw = std::fs::read_to_string(&cli.config)?;
    let mut cfg: ExperimentConfig = toml::from_str(&raw)?;
    if let Some(s) = cli.seed { cfg.seed = s; }
 
    // Hash the exact config into every artifact, so a result can always be
    // traced back to the settings that produced it.
    let config_hash = blake3::hash(raw.as_bytes()).to_hex().to_string();
    tracing::info!(seed = cfg.seed, config = %config_hash, "starting");
 
    match cli.stage {
        Stage::Teacher => {
            let mut envs = FerrisVecEnv::new(&cfg.env, &cfg.randomization, cfg.seed)?;
            let mut teacher = PrivilegedPolicy::new(&cfg.ppo);
            let mut curriculum = TerrainCurriculum::new(&cfg.curriculum);
            train_ppo(&mut teacher, &mut envs, &mut curriculum, &cfg, &config_hash)?;
        }
        Stage::Student => {
            let teacher = PrivilegedPolicy::load("artifacts/teacher.mpk")?;
            let mut student = RecurrentPolicy::new(&cfg.distillation);
            // DAgger, not behaviour cloning: roll out the STUDENT, label with
            // the teacher. Chapter 16 explains why this distinction decides it.
            distill_on_policy(&teacher, &mut student, &cfg, &config_hash)?;
        }
        Stage::Evaluate => {
            let student = RecurrentPolicy::load("artifacts/student.mpk")?;
            let report = evaluate(&student, &cfg.evaluation, cfg.seed)?;
            report.print_with_wilson_intervals();
            report.write_json("artifacts/evaluation.json")?;
        }
        Stage::Export => export_wasm("artifacts/student.mpk", "dist/")?,
    }
    Ok(())
}
The config-driven runner. Every number that affects the result lives in one TOML file that is hashed into the results — which is what makes 'reproducible' a checkable claim rather than an aspiration.

22.4 Evaluation, and an honest verdict

Chapter 14 set the standard; here it is applied to our own work.

Mission control

ch22-mission-control

The capstone's telemetry: training, reward composition, evaluation with intervals, and the failure post-mortems.

Panel
Training seed:

Environment steps

11.0M

4096 envs × 2700 iters

Final return

43.8

mean over envs

Terrain level

8 / 9

curriculum progression

Approx. KL

0.009

PPO trust-region watchdog

The plateau is not convergence — the terrain curriculum keeps raising difficulty, so a flat return means competence rising as fast as the task hardens.
Switch between training seeds and watch the curves differ — that spread is why §22.4 reports five seeds rather than the best one. The failures panel is the chapter's real payload: every diagnosis names a design decision from Parts III–IV, and not one of them is 'tune the learning rate'.

Protocol. 200 episodes on terrain seeds disjoint from training, with the push protocol applied. Five independently trained policies (five training seeds), reported separately rather than pooled.

Results, as they would be reported:

MetricValue95% interval
Circuit completion176 / 20088.0% [82.7%, 91.9%]
No-fall rate189 / 20094.5% [90.4%, 96.9%]
Push recovery (3+ pushes survived)171 / 20085.5% [79.9%, 89.8%]
Mean cost of transport0.94±0.11 across seeds
Median completion time108 sbudget 180 s

The intervals are Wilson score intervals, appropriate near the boundary where the normal approximation misleads. Across the five training seeds, completion ranged from 81% to 91% — a spread worth reporting, because a paper claiming 91% from one seed would be reporting the best of five.

22.5 Failure modes, with post-mortems

The failures are more instructive than the successes, and each traces to a specific decision.

Stuck at a gap (11 of 24 failures). Ferris approaches a gap wider than his stride and oscillates at the edge. Diagnosis: the terrain curriculum generated gaps up to 40 cm, but the waypoint-progress reward rewards approaching the goal, so the policy is pulled toward an edge it cannot cross. Fix: either a lateral-detour skill (Ch 19's hierarchy) or a curriculum that pairs each gap with a traversable bypass so the policy learns detouring is acceptable.

Push recovery failure on low friction (7 of 24). Pushes at μ=0.4\mu = 0.4 cause a slide into a fall. Diagnosis: the randomization range covers μ[0.4,1.2]\mu \in [0.4, 1.2], but pushes were sampled uniformly over time rather than conditioned on friction, so the low-friction-plus-push corner is rare in training. Fix: stratify the randomization so hard combinations are sampled deliberately.

Timeout on rough terrain (4 of 24). Completes the circuit but past the budget. Diagnosis: the velocity-tracking weight is too low relative to the effort penalty on rough ground, so the policy trades speed for economy. Fix: condition the commanded velocity on remaining time, or reweight — a Chapter 18 reward-mixer decision.

Distillation gap (2 of 24). The student fails where the teacher succeeds. Diagnosis: the 15-step history is insufficient to infer terrain that the teacher observed directly. Fix: a longer history, or an explicit terrain-estimation auxiliary loss.

22.6 What you have

The repository is a template. Fork it, replace the URDF and the reward terms, and the pipeline carries over: config-driven experiments with hashed provenance, a parallel rollout farm, teacher–student training, evaluation with intervals, and a browser demo for showing people what you built.

Where to go next, in rough order of value: put it on hardware, because every assumption in §22.2 is a hypothesis until a physical robot tests it. Add a manipulator and confront Chapter 20's difficulties. Replace the hand-specified waypoint sequence with learned skills and take on Chapter 19's open question. Or take the pipeline to a task where simulation does not work, and find out what Chapter 16's methods can do.

22.7 A closing note

Twenty-two chapters ago, Rusty drove into a concave trap and stayed there, running a controller that was correct in the sense that mattered to its author and useless in the sense that mattered to the robot.

The distance from there to here is not a collection of algorithms. It is a way of thinking: state the problem formally, know which assumptions your robot violates, choose the representation before the optimizer, measure against a classical baseline, and report what you actually established rather than what you hoped.

The four curses are still there. They will be there for your project too. Knowing their names, and which technique manages each, is what this book was for.

  1. 01Foundation●●Justify every observation

    For each of the eight observation components in §22.2, state what fails if it is removed. Then propose one addition and argue whether it earns its dimensions.

  2. 02Foundation●●Check the shaping

    Verify that the waypoint-progress term is potential-based and therefore policy-invariant. Then show that adding a raw −distance term instead would change the optimal policy, and describe the behaviour it would produce.

  3. 03Foundation●●Horizon and discount

    The budget is 180 s at 50 Hz — 9000 steps. Choose γ so the effective horizon covers a waypoint leg but not the whole circuit, and justify the choice against the failure modes in §22.5.

  4. 04Foundation●●Read the intervals

    Compute the Wilson interval for 176/200 and confirm the reported figure. Then determine how many episodes would be needed to establish completion above 85% with 95% confidence.

  5. 05Conceptual●●Diagnose from telemetry

    From the mission-control dashboard, identify which reward term is being sacrificed during the timeout failures. Then predict the weight change that would fix it, and what it would cost elsewhere.

  6. 06Conceptual●●Grade another system

    Take a recent robot-RL paper and grade it on the L0–L5 rubric using only its reported experiments. Then compare with the level the abstract implies.

  7. 07Practical●●●Reproduce and perturb

    Run the capstone from the pinned config and confirm the results reproduce. Then change one reward weight by 20%, rerun, and report what changed. Small perturbations should produce visible behaviour changes — that sensitivity is the finding.

  8. 08Practical●●●Fix a failure mode

    Pick one failure from §22.5 and implement its proposed fix. Re-evaluate with the full protocol and report whether the fix helped, hurt elsewhere, or did neither — all three are legitimate results, and the third is the most common.

References

Baseline references

  • Kober, J., Bagnell, J. A. & Peters, J. (2013). Reinforcement Learning in Robotics: A Survey. International Journal of Robotics Research 32(11)
    §7 the ball-in-a-cup case study — the model for this chapter’s discipline of specifying before implementing.
  • Tang, C. et al. (2024). Deep Reinforcement Learning for Robotics: A Survey of Real-World Successes. Annual Review of Control, Robotics, and Autonomous Systems link
    §3.4 the L0–L5 rubric applied to our own work in §22.4, and §5 on principled system design.
  • Sutton, R. S. & Barto, A. G. (2018). Reinforcement Learning: An Introduction. MIT Press, 2nd edition
    The formalism underlying §22.2, from the MDP definition through policy gradients.

Further reading & modern sources

  • Rudin, N., Hoeller, D., Reist, P. & Hutter, M. (2022). Learning to Walk in Minutes Using Massively Parallel Deep Reinforcement Learning. CoRL 2021
    The parallel-training regime and curriculum structure this capstone follows.
  • Lee, J., Hwangbo, J., Wellhausen, L., Koltun, V. & Hutter, M. (2020). Learning quadrupedal locomotion over challenging terrain. Science Robotics 5(47)
    The teacher–student pipeline of §22.3, and the L4 result our L0 work would need years to approach.
  • Wilson, E. B. (1927). Probable Inference, the Law of Succession, and Statistical Inference. Journal of the American Statistical Association 22(158)
    The score interval used throughout §22.4.
  • Agarwal, R., Schwarzer, M., Castro, P. S., Courville, A. & Bellemare, M. G. (2021). Deep Reinforcement Learning at the Edge of the Statistical Precipice. NeurIPS 34
    Why per-seed reporting matters, as practised in §22.4.
  • Henderson, P., Islam, R., Bachman, P., Pineau, J., Precup, D. & Meger, D. (2018). Deep Reinforcement Learning that Matters. AAAI 2018
    The reproducibility problems this chapter’s config-hashing and seed reporting are designed to avoid.