Domain randomization in code
slip_ep = rng.uniform(slip_low, slip_high)new sim each episode
s_next, r, done = step(s, a, slip_ep, rng)slip moves perpendicular
Q_fixed = train_fixed(0.0, rng=rng)policy A, no DR
Q_dr = train_dr(0.0, 0.3, rng=rng)policy B, DR
for slip in (0.0, 0.1, 0.2, 0.3, 0.5, 0.7):0.5 and 0.7 are OOD
r_fixed = evaluate(Q_fixed, slip)
r_dr = evaluate(Q_dr, slip)
Sources
Original source
---
id: marl-sim-to-real
title: Multi-Agent RL and Sim-to-Real
code: MR
subtitle: CTDE, value decomposition, self-play, domain randomization and VLA action formats. Formulas, numbers and fixes.
hue: 60
sources: phases/09-reinforcement-learning/10-multi-agent-rl, phases/09-reinforcement-learning/11-sim-to-real-transfer, phases/16-multi-agent-and-swarms/20-marl-maddpg-qmix-mappo, phases/12-multimodal-ai/21-embodied-vlas-openvla-pi0-groot
source_hash: 8c321f58504cb71c
---
## Core ideas and formulas
type: concepts
from: phases/09-reinforcement-learning/10-multi-agent-rl/docs/en.md, phases/16-multi-agent-and-swarms/20-marl-maddpg-qmix-mappo/docs/en.md, phases/09-reinforcement-learning/11-sim-to-real-transfer/docs/en.md, phases/12-multimodal-ai/21-embodied-vlas-openvla-pi0-groot/docs/en.md
- **Markov game**: $(S, A_1, \ldots, A_n, P, R_1, \ldots, R_n)$. Each agent has its own reward.
- **Reward types**: identical is cooperative, zero-sum is adversarial, mixed is general-sum.
- **Non-stationarity**: $P(s' \mid s, a_i)$ depends on $\pi_{-i}$, and $\pi_{-i}$ changes.
- **CTDE**: critic $Q(s, a_1, \ldots, a_n)$ in training. Policy $\pi_i$ reads only $o_i$.
- **QMIX**: $Q_{\text{tot}} = f(Q_1, \ldots, Q_n)$ with $\partial f / \partial Q_i \ge 0$.
- **COMA**: advantage is my Q minus the expected Q over my own action.
- **Reality gap**: the shift between sim and real physics or sensing.
- **Control budget**: a 30 Hz loop gives 33ms for each action.
## MADDPG, QMIX, MAPPO
type: comparison
from: phases/16-multi-agent-and-swarms/20-marl-maddpg-qmix-mappo/docs/en.md, phases/09-reinforcement-learning/10-multi-agent-rl/docs/en.md
| Factor | MADDPG | QMIX | MAPPO |
|---|---|---|---|
| Year | 2017 | 2018 | 2022 |
| Idea | Per-agent critic sees all obs and actions | Monotonic mix of per-agent Qs | PPO with a centralized value function |
| Setting | Cooperative, competitive, mixed | Cooperative only | Cooperative |
| Testbed | Particle World | SMAC | Particle-world, SMAC, Football, Hanabi, MPE |
| Learning | Off-policy, DDPG | Value decomposition | On-policy, PPO |
| Key trait | Critic grows with N, ~10 agents | Monotonic constraint is strict | Stable, minimal tuning |
| Status | Introduced CTDE | Dominant on SMAC | Default cooperative baseline |
## CTDE: train central, act local
type: architecture
from: phases/16-multi-agent-and-swarms/20-marl-maddpg-qmix-mappo/docs/en.md, phases/09-reinforcement-learning/10-multi-agent-rl/docs/en.md
```arch
node | o1 | 1,1 | Agent 1 obs | local only | client
node | o2 | 1,2 | Agent 2 obs | local only | client
node | act1 | 2,1 | Actor 1 | maps own obs to action | model
node | act2 | 2,2 | Actor 2 | maps own obs to action | model
node | env | 3,1 | Environment | joint action, shared reward
node | critic | 3,2 | Centralized critic | all obs and actions, training only | process
edge | o1 | act1 |
edge | o2 | act2 |
edge | act1 | env | action
edge | act2 | env | action
edge | env | critic | reward
edge | critic | act1 | gradient
edge | critic | act2 | gradient
```
## Sim-to-real recipe (quadruped)
type: flow
from: phases/09-reinforcement-learning/11-sim-to-real-transfer/docs/en.md
1. **Sim**: massively parallel sim, with randomized gravity, friction, motor gains and payload.
2. **Teacher**: train with privileged info, terrain map and true body velocity.
3. **Student**: distill from the teacher with proprioception only.
4. **Adapt**: optional observation adaptation with an autoencoder on real IMU.
5. **Deploy**: zero-shot on 10+ environments.
6. **Fallback**: minutes of real fine-tuning with safety-constrained PPO.
## Independent against joint Q
type: annotated-code
lang: python
from: phases/09-reinforcement-learning/10-multi-agent-rl/code/main.py
```python
a1 = epsilon_greedy(Q1, s, rng, epsilon) # each agent picks alone
a2 = epsilon_greedy(Q2, s, rng, epsilon)
s_next, r, done = step(s, (a1, a2)) # joint step, shared reward
target1 = r + gamma * max(Q1[s_next].values())
Q1[s][a1] += alpha * (target1 - Q1[s][a1]) # own Q table
reward = 10.0 if done else -1.0 # +10 when both arrive
joint_actions = [(a, b) for a in ACTIONS for b in ACTIONS] # 16 pairs
ja = max(joint_actions, key=lambda a: Q[s][a]) # one greedy joint pick
```
## Domain randomization in code
type: annotated-code
lang: python
from: phases/09-reinforcement-learning/11-sim-to-real-transfer/code/main.py
```python
slip_ep = rng.uniform(slip_low, slip_high) # new sim each episode
s_next, r, done = step(s, a, slip_ep, rng) # slip moves perpendicular
Q_fixed = train_fixed(0.0, rng=rng) # policy A, no DR
Q_dr = train_dr(0.0, 0.3, rng=rng) # policy B, DR
for slip in (0.0, 0.1, 0.2, 0.3, 0.5, 0.7): # 0.5 and 0.7 are OOD
r_fixed = evaluate(Q_fixed, slip)
r_dr = evaluate(Q_dr, slip)
```
## Four VLAs side by side
type: comparison
span: 2
from: phases/12-multimodal-ai/21-embodied-vlas-openvla-pi0-groot/docs/en.md
| Factor | RT-2 | OpenVLA | π0 | GR00T N1 |
|---|---|---|---|---|
| Action format | Text tokens, 256 bins | 256-bin tokens | Flow-matching action expert | System 1 action head |
| Backbone | PaLM-X VLM | 7B Llama, DINOv2 + SigLIP | VLM plus small action transformer | Large VLM plus small action head |
| Speed | 3-5 Hz | 4-5 Hz on an A100 | ~5 denoising steps, about 50 Hz | System 1 at 50-100 Hz, System 2 ~1 Hz |
| Detail | 10 tokens per step for 10-DOF | LoRA fine-tuning for new robots | 50-step action sequence | Joint commands, >30 DOF |
| Data | Web plus robot, ~1:1 | Open X-Embodiment, ~0.5:1 web-to-robot | Open X-Embodiment, similar ratio | Sim-to-real data from Omniverse |
## Tasks in code
type: task-table
from: phases/09-reinforcement-learning/10-multi-agent-rl/code/main.py, phases/09-reinforcement-learning/11-sim-to-real-transfer/code/main.py, phases/16-multi-agent-and-swarms/20-marl-maddpg-qmix-mappo/code/main.py, phases/16-multi-agent-and-swarms/20-marl-maddpg-qmix-mappo/docs/en.md, phases/12-multimodal-ai/21-embodied-vlas-openvla-pi0-groot/code/main.py
| Task | Code |
|---|---|
| Independent Q for two agents | `independent_q(episodes=1500)` |
| One Q over 16 joint actions | `joint_q_learning(episodes=1500)` |
| Train with DR | `train_dr(0.0, 0.3, rng=rng)` |
| Zero-shot eval at one slip | `evaluate(Q_dr, slip)` |
| Benchmark a CTDE pattern | `bench(label, run_mappo_style)` |
| Run the MARL pattern demo | `python3 code/main.py` |
| Action to 256 bins | `discretize(action, bins=256)` |
| FAST-style compression | `fast_compress(trajectory, keep_coeff=4)` |
## Defaults in the lesson code
type: defaults
from: phases/09-reinforcement-learning/10-multi-agent-rl/code/main.py, phases/09-reinforcement-learning/11-sim-to-real-transfer/code/main.py, phases/16-multi-agent-and-swarms/20-marl-maddpg-qmix-mappo/code/main.py, phases/12-multimodal-ai/21-embodied-vlas-openvla-pi0-groot/code/main.py
| Setting | Default | Note |
|---|---|---|
| `alpha` | 0.1 | MARL and DR toys |
| `gamma` | 0.95 | MARL and DR toys |
| `epsilon`, `eps` | 0.15 | ε-greedy exploration |
| MARL `episodes` | 1500 | 3000 in the DR toy |
| DR slip range | Uniform[0.0, 0.3] | Policy B |
| `max_steps` | 50 | CTDE pattern demo, 500 trials |
| `bins` | 256 | Bin width 2/255 |
| `keep_coeff` | 4 | Low-frequency DCT terms per dim |
## Troubleshooting
type: troubleshooting
from: phases/09-reinforcement-learning/10-multi-agent-rl/docs/en.md, phases/09-reinforcement-learning/11-sim-to-real-transfer/docs/en.md
| Symptom | Cause | Fix |
|---|---|---|
| Agents chase each other | Each best response moves | Centralized critic, slow LR, freeze one |
| Replay makes it worse | Obsolete opponents in old data | Relabel, or weight by recency |
| No credit for shared reward | Credit assignment | COMA baseline or per-agent shaping |
| Self-play stuck in a cycle | Dominance cycle | League play with diverse opponents |
| DR policy too cautious | Too much randomization | Match the expected real distribution |
| DR does not help | Wrong parameter randomized | Profile the real robot first |
| Student cannot match teacher | Privileged info leakage | Keep the teacher realizable from obs |
| Policy breaks hardware | No safety envelope | Rate, torque and joint limits outside |
## Abbreviations
type: glossary
from: phases/09-reinforcement-learning/10-multi-agent-rl/docs/en.md, phases/09-reinforcement-learning/11-sim-to-real-transfer/docs/en.md, phases/12-multimodal-ai/21-embodied-vlas-openvla-pi0-groot/docs/en.md
- **CTDE**: Centralized training, decentralized execution.
- **IPPO**: Independent PPO. Each agent runs PPO alone.
- **COMA**: counterfactual multi-agent. Isolates my contribution.
- **DR**: domain randomization. Random sim parameters in training.
- **SI**: system identification. Measure the real robot, fit the sim.
- **ADR**: Automatic Domain Randomization. Widens DR as the policy improves.
- **VLA**: vision-language-action. Image and instruction in, actions out.
- **FAST**: Frequency-domain Action Sequence Tokenizer. DCT, then quantize.
## Rules of thumb
type: tips
from: phases/16-multi-agent-and-swarms/20-marl-maddpg-qmix-mappo/docs/en.md, phases/09-reinforcement-learning/10-multi-agent-rl/docs/en.md, phases/09-reinforcement-learning/11-sim-to-real-transfer/docs/en.md, phases/12-multimodal-ai/21-embodied-vlas-openvla-pi0-groot/docs/en.md
- Start with MAPPO for cooperative MARL.
- Use independent Q only for loosely-coupled tasks.
- Use self-play for zero-sum games. Use league play for strategy cycles.
- Log the observation and action stream of every agent.
- Test on a held-out sim variant before you deploy.
- Flag a DR range wider than 3× the measured real variability.
- Close a VLA domain gap with LoRA on 100-1000 task demos.
## Questions
type: qa
from: phases/09-reinforcement-learning/10-multi-agent-rl/docs/en.md, phases/16-multi-agent-and-swarms/20-marl-maddpg-qmix-mappo/docs/en.md, phases/09-reinforcement-learning/11-sim-to-real-transfer/docs/en.md, phases/12-multimodal-ai/21-embodied-vlas-openvla-pi0-groot/docs/en.md
- **Where does independent Q fail?** On tightly-coupled tasks, where one agent must wait.
- **Why does QMIX allow local argmax?** The mixer is monotonic in each per-agent Q.
- **What does narrow training do?** Slip 0.0 only drops hard as soon as real slip is above 0.
- **Why co-fine-tune a VLA?** Robot-only models fail on new instructions.
- **Why the GR00T split?** Slow planning does not block fast control.