TAI BUI
Back to curriculum
BuildPython

Sim-to-Real Transfer

A policy trained in a simulator that fails on real hardware never learned to walk. It memorized the simulator. Domain randomization, domain adaptation, and system identification are the three tools that get a learned controller across the reality gap.

TIME: ~45 minutesPREREQUISITES: Phase 9 · 08 (PPO), Phase 2 · 10 (Bias/Variance)

Learning Objectives

  • Define the reality gap and explain why a policy trained purely in simulation degrades once it meets real hardware.
  • Compare domain randomization, system identification, and domain adaptation, including Real2Sim2Real and teacher-student distillation, as strategies for closing that gap, with the upside and downside of each.
  • Implement domain randomization on a parameterized GridWorld: train across a range of slip probabilities and evaluate zero-shot on slip values the policy never trained on.
  • Diagnose the recurring domain-randomization failure modes, over-randomization, under-randomization, misidentified parameters, privileged-info leakage, and missing safety envelopes, and produce a sim-to-real transfer plan that avoids them.

The Problem

Training a real robot is slow, dangerous, and expensive. A biped needs millions of training episodes to learn to walk, and a real biped that falls over even once breaks hardware. Simulation fixes that: unlimited resets, deterministic reproducibility, parallel environments, no physical damage.

But simulators are wrong, in specific and predictable ways. The systematic gap between the sim distribution and the real distribution is the reality gap: the central problem of deployed RL for robotics. Bearings have more friction than MuJoCo models assume. Cameras carry lens distortion the simulator never modeled. Motors have delays, backlash (slack in the gear train), and saturation that 99% of sim models skip entirely. Wind, dust, and variable lighting sabotage a policy trained on sterile rendering.

You need a policy that's robust to sim-to-real distribution shift. Three approaches carry the field this far: randomize the simulator (domain randomization), adapt the policy with a little real data (domain adaptation, or fine-tuning), or measure the real system's parameters and match the sim to them (system identification). By 2026 the dominant recipe combines all three, running on massive parallel simulation such as Isaac Sim, Isaac Lab, or Mujoco MJX on GPU.

Warm-up0/3
1. A robot's control policy is trained entirely inside a physics simulator, then run on the real robot for the first time with no further tuning. Based on general intuition, what would you expect?Warm-up
Three boxes joined by arrows: a physics simulator where the policy is trained, a real robot running it for the first time with no further tuning, and a performance box compared to the simulator marked with a question mark.
2. Why might it make sense to train a robot's control policy in a simulator before ever running it on physical hardware?Warm-up
A stick-figure biped shown stepping, stumbling and falling in one training episode of a walking policy.
3. A model fits its training data very closely, but that data covers only a narrow range of situations. What do you expect on inputs far outside that range?Warm-up
Scatter of 14 training points between x = 0 and 3 with a close fitted curve, and a dashed empty region from x = 3 to 10 labelled inputs far outside the training range, accuracy here: question mark.
Illustrative: sine data with noise and a degree-4 polynomial fit, computed with numpy.
Check: The Problem0/2
1. What is the reality gap in sim-to-real transfer?Define
A three-column table comparing one robot in the simulator and on the real robot: joint bearing friction, camera distortion, motor delay and backlash, and sterile rendering versus dust, wind and variable light.
Sources named in the lesson's Problem section.
2. Why does a policy trained only in simulation tend to degrade on real hardware?Explain
A policy trained only in simulation exchanging actions and observations with an environment box that is the simulator during training and the robot at deployment, beside a rising training return curve and a first hardware run with return marked by a question mark.
The curve is a schematic, not a measurement.

The Concept

Three sim-to-real regimes: domain randomization, adaptation, system identification

Domain Randomization (DR). Tobin et al. 2017, Peng et al. 2018. During training, randomize every sim parameter that might differ on the real robot: masses, friction coefficients, motor PD gains (the stiffness and damping settings controlling each joint), sensor noise, camera position, lighting, textures, contact models. The policy learns a conditional distribution over "which sim it is in today" and generalizes across the full span. If the real robot falls inside the training envelope, the policy works.

  • Upside: no real data needed. One recipe, many robots.
  • Downside: over-randomized training produces a "universal" but overly cautious policy. Too much noise acts like too much regularization.

System Identification (SI). Fit the simulator's parameters to real-world data before training. Measure arm-joint friction on the real robot, plug that number into the sim, then train a policy that expects it. SI needs access to the real system, but it reduces the reality gap directly.

  • Upside: precise, low-noise training target.
  • Downside: residual model error stays invisible to the policy. Small un-identified effects, like motor deadband, still break deployment.

Domain Adaptation. Train in sim, then fine-tune with a small amount of real data. Two flavors:

  • Real2Sim2Real: learn a residual simulator f(s, a, z) - f_sim(s, a) from real rollouts, and train inside the corrected sim. Closes the gap without needing much real data.
  • Observation adaptation: train a policy that maps real obs → sim-like obs through a learned feature extractor, a GAN doing pixel-to-pixel translation, for example. The controller itself never leaves sim.

Privileged learning, or teacher-student. Miki et al. 2022 trained this way on the ANYmal quadruped. A teacher trains in simulation with access to privileged information: ground truth friction, terrain height, IMU (inertial measurement unit) drift. A student is then distilled from it that only sees real-sensor observations, and learns to infer those privileged features from its own observation history, which makes it robust across physical parameters it was never told directly.

Massively parallel simulation. From 2024 to 2026, Isaac Lab, Mujoco MJX, and Brax all started running thousands of parallel robots on a single GPU. PPO with 4,096 parallel humanoids collects years of experience in hours. The reality gap shrinks as the training distribution widens, and DR gets almost free once each of those 4,096 environments carries its own randomized parameters.

The 2026 recipe for real-world deployment (quadruped walking, as an example):

  1. Massively parallel sim with domain-randomized gravity, friction, motor gains, payload.
  2. Teacher policy trained with privileged info (terrain map, body velocity ground truth).
  3. Student policy distilled from the teacher using only proprioception (leg joint encoders).
  4. Optional observation adaptation via an autoencoder on the real IMU.
  5. Deploy. Zero-shot across 10+ environments. If it fails, run minutes of real-world fine-tuning with safety-constrained PPO.
Check: The Concept0/15
1. What is domain randomization?Define
Two lines of train_dr code that draw slip_ep from rng.uniform(slip_low, slip_high) and pass it to step, above eight episode cards each showing a different slip_ep value between 0.00 and 0.30.
Illustrative draws: the first eight values of random.Random(1).uniform(0.0, 0.3), not taken from inside a training run. The range 0.0 to 0.3 is the one main.py uses.
2. What is system identification (SI) in sim-to-real work?Define
Two panels: a real robot arm joint 2 whose measured friction is 0.42, and a simulator config file with joint2_friction 0.30 and other default values, with a note that training has not started yet.
Numbers are illustrative.
3. What is the teacher-student ('privileged learning') approach described in the lesson, citing Miki et al. 2022 on the ANYmal quadruped?Define
Two policy boxes for the ANYmal quadruped: Policy 1 sees ground-truth friction, terrain height and IMU drift; Policy 2 sees only real-sensor observation history; a question mark on a plain line between them asks how they are related.
4. What are the two domain-adaptation flavors the lesson names?Define
A chain from train in simulation to domain adaptation (a little real data) to the real robot, with two empty dashed slots below labelled flavor 1 and flavor 2, each a question mark.
5. What counts as privileged information in teacher-student training?Define
A table listing five quantities for a quadruped, each readable in the simulator: true ground friction, terrain height, ground-truth IMU drift, joint encoder history and IMU reading.
6. What is Real2Sim2Real?Define
Line chart over 16 time steps: one smooth blue simulator trajectory and three orange real rollouts from the same command sequence, which start together, differ most around the peak at step 5 and come back close by step 16.
Illustrative one-dimensional system computed with numpy; the real rollouts include noise.
7. What does the lesson say massively parallel simulators like Isaac Lab, MuJoCo MJX, and Brax enable?Define
Three cards naming the simulators Isaac Lab, MuJoCo MJX and Brax, with an arrow to a highlighted box asking what they enable, marked with a question mark, and a note that the lesson pairs them with PPO training and domain randomization.
8. What is the main downside of domain randomization the lesson warns about?Explain
Six rows (masses, friction coefficients, motor PD gains, sensor noise, camera position, lighting), each with a bar showing the range sampled during training and a dot for the real robot's value inside it.
Ranges are illustrative.
9. How does domain randomization differ from system identification in how it closes the reality gap?Explain
A friction axis from 0.2 to 0.6 with the simulator default marked near 0.3 and the real robot's value marked at 0.42, and a note that the real value is not known before hardware is touched.
Positions are illustrative.
10. What upside and downside does the lesson give for System Identification (SI)?Explain
Four boxes in a row for system identification: 1 measure arm-joint friction on the real robot, 2 plug that number into the sim, 3 train a policy against that sim, 4 deploy on the real robot.
11. Why can Real2Sim2Real close the gap with only a small amount of real data?Explain
A curve labelled f_sim(s, a) for next state against state at one fixed action, with six orange dots for real transitions lying close to the curve.
Illustrative one-dimensional dynamics computed with numpy.
12. Why does the student in teacher-student distillation get an observation history rather than the teacher's privileged inputs?Explain
Left card: teacher input in simulation (ground-truth friction, terrain height, IMU drift). Right: a joint encoder signal over time with its last k steps outlined as the student's input.
Encoder signal is a schematic sine wave.
13. What is the key property of observation adaptation as a form of domain adaptation?Explain
Two frames of the same grid scene: a simulator render with straight lines and a real camera frame with curved, distorted lines, with a note that the controller was trained on frames like the left one.
Distortion drawn with a barrel model in numpy.
14. Your simulator exposes a terrain height map, but the real quadruped has only joint encoders. Which design fits?Design
Two columns: the simulator provides a terrain height map and joint encoder signals; the real quadruped has joint encoder signals but a dashed empty box saying no terrain height sensor.
Height map and encoder trace are schematic.
15. Simulated physics match your robot well, but its real camera has lens distortion the simulator never modeled, and you want the controller left untouched. Which approach fits?Design
A status table: simulated physics match the robot well, the real camera has lens distortion not in the sim, and the controller must stay untouched; below it a small distorted grid frame labelled frames from the real camera look like this.
Distortion drawn with a barrel model in numpy.

Build It

This lesson's code is a small demonstration of domain randomization on a GridWorld with noisy transitions. We train a policy that experiences randomized slip probabilities in "sim," then evaluate it on "real" at a slip level it never saw during training. The shape maps directly onto MuJoCo-to-hardware transfer.

Step 1: parameterized sim

python
def step(state, action, slip):
    if rng.random() < slip:
        action = random_perpendicular(action)
    ...

slip is a parameter the simulator exposes. In real robotics that could be friction, mass, or motor gain: anything that shifts between sim and real.

Step 2: train with DR

At the start of each episode, sample slip ~ Uniform[0.0, 0.4]. Train PPO, Q-learning, whatever algorithm you like, for many episodes.

Step 3: evaluate zero-shot on "real" slips

Evaluate on slip ∈ {0.0, 0.1, 0.2, 0.3, 0.5, 0.7}. The first four sit within training support; 0.5 and 0.7 sit outside it. A DR-trained policy should stay near-optimal inside that support and degrade gracefully outside it. A fixed-slip-trained policy won't: it's brittle the moment it leaves its training slip.

Step 4: compare to narrow training

Train a second policy with slip = 0.0 only, and run it through the same sweep. Watch for a catastrophic drop the moment real slip climbs above zero.

Check: Build It0/4
1. In the lesson's GridWorld demonstration of domain randomization, what parameter is randomized during 'sim' training, and what happens during evaluation?Apply
Three boxes for the lesson's GridWorld demonstration: step 1 a parameterized sim, step 2 training in sim with the randomized parameter marked by a question mark, step 3 evaluation on real with what happens marked by a question mark.
Step names follow the lesson's Build It section.
2. What does the lesson predict will happen to a policy trained only at slip=0.0 when evaluated at slip>0?Apply
A card saying Policy A is trained only with slip 0.0, above an empty chart of Policy A's return against evaluation slips 0, 0.1, 0.2, 0.3, 0.5 and 0.7, with a dashed line at slip 0.0 marking where it trained and the return values left as a question mark.
No result is drawn: the chart is empty on purpose.
3. In the step function below, slip is 0.0 and rng.random() returns a number between 0 and 1. What happens to the chosen action? ```python def step(state, action, slip): if rng.random() < slip: action = random_perpendicular(action) ```Apply
The first two lines of the step function with slip = 0.0, above a table of six random draws between 0 and 1 next to slip 0.0 with the column branch runs left as a question mark in every row.
Draws computed with Python's random module.
4. A policy is trained with slip ~ Uniform[0.0, 0.4] and evaluated on slip in {0.0, 0.1, 0.2, 0.3, 0.5, 0.7}. Which evaluation slips are outside its training support?Apply
A histogram of 200 training slip draws as blue bars on an axis from 0 to 0.8, with tick marks and labels for the evaluation slips 0, 0.1, 0.2, 0.3, 0.5 and 0.7.
Draws from Uniform[0.0, 0.4] with Python's random module.

Pitfalls

  • Too much randomization. Train on slip ∈ [0, 0.9] and the policy gets so risk-averse it never tries the optimal path. Match the expected real-world distribution, not "anything could happen."
  • Too little randomization. Train on a thin slice and the policy can't generalize at all. Use an adaptive curriculum, Automatic Domain Randomization, that widens the distribution as the policy improves.
  • Misidentified parameter space. Randomize the wrong thing, camera hue when the real gap is actually motor delay, and DR doesn't help at all. Profile the real robot first.
  • Privileged info leakage. A teacher that acts on global state instead of just observations can produce a student that never catches up. Make sure the teacher's policy is realizable by the student given its observation history.
  • Sim-to-sim transfer failure. A policy that isn't robust to a harder sim variant won't be robust to the real world either. Always test on a held-out sim variant before deploying.
  • No real-world safety envelope. A policy that works in sim, and seems to work in real, can still break hardware without a low-level safety shield. Add rate limits, torque limits, and joint limits in a non-learned controller.
Check: Pitfalls0/7
1. What is Automatic Domain Randomization (ADR)?Define
A slip axis from 0.0 to 0.9 with only the interval 0.0 to 0.1 marked as sampled, above a card reading sampling slip from Uniform 0.0 to 0.1.
Illustrative snapshot, not a measured run.
2. What does the lesson recommend as a fix for training on too narrow a randomization range?Explain
A slip axis from 0 to 0.8 with ticks at 0, 0.1, 0.2, 0.3, 0.5 and 0.7, and a thin training interval Uniform 0.0 to 0.05 marked at the left end.
Illustrative narrow training range.
3. A team randomizes camera hue and lighting heavily, yet the real robot still fails because of an unmodeled motor delay. Which pitfall is this?Analyze
A table of three parameters: camera hue and lighting are randomized heavily in simulator training, while motor delay is not modeled and is present as an unmodeled delay on the real robot; a note says the policy still fails on the real robot.
4. After distillation, a student policy never matches its teacher's performance, and the teacher was acting on global simulator state. What is the most likely cause?Analyze
A teacher box that acts on global simulator state and is trained first, an arrow labelled distill to a student box that sees only its own observation history, and two schematic bars showing student return staying below teacher return.
Bar lengths are schematic.
5. A DR-trained policy scores well on its training simulator but collapses on a harder variant of the same simulator. What does this suggest about deploying it?Analyze
Bars of one DR-trained policy's score: high on its training simulator, low on a harder variant of that simulator, and a dashed empty bar with a question mark for real hardware.
Scores are illustrative.
6. A policy seems to work in real trials, then drives a joint into its limit and breaks the arm. Which missing piece does the lesson blame?Analyze
A joint angle trace rising until it crosses a dashed joint limit line, with a marker where the arm breaks.
Trace is a schematic computed with numpy.
7. A policy trained with slip ~ Uniform[0, 0.9] never attempts the shortest path, even when the environment is calm. Which pitfall is this?Analyze
A histogram of 300 training slip draws spread evenly between 0 and 0.9, beside a 5 by 5 GridWorld from S to G with an 8-step shortest path drawn for a calm environment with slip 0.
Draws from Uniform[0, 0.9] with Python's random module.

Use It

Here's the 2026 sim-to-real stack, by domain:

DomainStack
Legged locomotion (ANYmal, Spot, humanoid)Isaac Lab + DR + privileged teacher / student
Manipulation (dexterous hands, pick-and-place)Isaac Lab + DR + DR-GAN for vision
Autonomous drivingCARLA / NVIDIA DRIVE Sim + DR + real fine-tune
Drone racingRotorS / Flightmare + DR + online adaptation
Finger/in-hand manipulationOpenAI Dactyl (DR at unprecedented scale)
Industrial armsMuJoCo-Warp + SI + small real fine-tune

Across all of these, the workflow stays the same: fit the sim as well as you can, randomize whatever you can't fit, train enormous policies, distill them down, and deploy behind a safety shield.

Check: Use It0/2
1. What stack does the Use It table recommend for finger/in-hand manipulation?Define
The lesson's Use It table with six rows (legged locomotion, manipulation, autonomous driving, drone racing, finger or in-hand manipulation, industrial arms) where the stack for finger or in-hand manipulation is replaced by a question mark.
Domain names and stacks shortened from the lesson table.
2. You are deploying a new quadruped. You can measure its motor gains and friction on the real robot, but motor delay varies unit to unit and cannot be measured. Which plan fits the lesson's workflow?Design
A table for a new quadruped: motor gains and friction can be measured on the real robot, while motor delay varies unit to unit and cannot be measured.

Ship It

Save as outputs/skill-sim2real-planner.md:

markdown
---
name: sim2real-planner
description: Plan a sim-to-real transfer pipeline for a given robot + task, covering DR, SI, and safety.
version: 1.0.0
phase: 9
lesson: 11
tags: [rl, sim2real, robotics, domain-randomization]
---
 
Given a robot platform, a task, and access to real hardware time, output:
 
1. Reality gap inventory. Suspected sources ranked by expected impact (contact, sensing, actuation delay, vision).
2. DR parameters. Exact list, ranges, distribution. Justify each range against real measurements.
3. SI steps. Which parameters to measure; measurement method.
4. Teacher/student split. What privileged info the teacher uses; what obs the student uses.
5. Safety envelope. Low-level limits, emergency stops, backup controller.
 
Refuse to deploy without (a) a zero-shot sim-variant test, (b) a safety shield, (c) a rollback plan. Flag any DR range wider than 3× measured real variability as likely over-randomized.
Check: Ship It0/3
1. What does the lesson recommend as a heuristic for flagging an over-randomized DR range?Explain
An excerpt of the sim2real-planner skill: item 2 about DR parameters and ranges justified against real measurements, and a last rule about flagging a DR range wider than a hidden multiple of measured real variability.
The multiplier is hidden on purpose.
2. Per the lesson, what should never be skipped before deploying a sim-to-real policy on real hardware?Explain
The five numbered outputs of the sim2real-planner skill, followed by a deploy gate box that says refuse to deploy without three checkbox items, each hidden as a question mark.
3. The measured real variability of a parameter is 0.1. Using the sim2real-planner rule of thumb (flag any range whose width exceeds 3 times that variability), which DR sampling range is flagged as likely over-randomized?Apply
An axis from 0 to 0.6 with a bar from 0 to 0.1 marked as the measured real variability, and the rule that a range is flagged if its width exceeds 3 times 0.1 where the width of Uniform a to b is b minus a.

Exercises

  1. Easy. Train a Q-learning agent on the fixed-slip GridWorld (slip=0.0). Evaluate on slip ∈ {0.0, 0.1, 0.3, 0.5}. Plot return vs slip.
  2. Medium. Train a DR Q-learning agent sampling slip ~ Uniform[0, 0.3]. Evaluate the same sweep. How much does DR buy at slip=0.5 (out-of-distribution)?
  3. Hard. Implement a curriculum: start with slip=0.0, widen the DR range every time the policy hits 90% of optimal. Measure total environment steps to reach slip=0.3 zero-shot vs. a fixed DR baseline.

Key Terms

TermWhat people sayWhat it actually means
Reality gap"Sim-to-real difference"Distribution shift between training and deployment physics/sensing.
Domain randomization (DR)"Train across random sims"Randomize sim parameters during training so policy generalizes.
System identification (SI)"Measure real and fit sim"Estimate real physical parameters; set sim to match.
Domain adaptation"Fine-tune on real data"Small real-world fine-tune after sim training; may adapt obs or dynamics.
Privileged info"Ground truth for teacher"Information only the sim has; student must infer it from obs history.
Teacher/student"Distill privileged -> observable"Teacher trained with shortcuts; student learns to mimic without them.
ADR"Automatic Domain Randomization"Curriculum that widens DR ranges as the policy improves.
Real2Sim"Close the gap with real data"Learn a residual to make the sim mimic real rollouts.

Further Reading

Code

Ships With