E1 · Inside × outside
3 minRun the sampling for both ranges.
Done when: python3 kit/randomizar.py --seeds 20 → faixa treino sobreviveu: 20/20 and faixa fora sobreviveu: 8/20.
Lesson 2 · 16 min
If the simulator never gets the world right, you train the policy in many randomly drawn worlds. In this lesson you read the ranges Unitree itself randomized when training the policy, draw 20 worlds inside them and 20 outside, and measure the difference. The policy handles what it saw in training and fails just past it.
Start the lesson
Goal: read the randomization ranges of a real training run and measure the policy's survival inside and outside them.
Click each block.
Randomization is not "more is better": it's covering the world where the robot will walk.
Read in velocity_env_cfg.py, unitree_rl_lab 4960b84 (Nov 19, 2025). Click each item.
physics_material event, at startup: static and dynamic friction between 0.3 and 1.0 on all of the robot's bodies.
In this lesson's out-of-range draw, the worlds with friction near 0.2 (2 and 5) fall; the floor of the training range is the floor the policy has seen.
add_base_mass event: adds −1 to +3 kg to the torso_link. A real payload (extra battery, camera, gripper) can go beyond that.
push_robot event, every 5 s: changes the base velocity by up to ±0.5 m/s in x and y. The kit applies the equivalent as a 0.1 s force on the torso.
There is also noise in the observations (angular velocity, gravity, joints).
There is no randomization of kp, kd or latency (delay) in this task. In lesson 1, kp alone already changed the gait (0.75 m/s when asking for 0.50); latency (delay) matters under a push (lesson 4).
Other projects randomize gains and latency (delay); what matters is knowing what your training covered before you power on the robot.
treino.json copies Unitree's ranges; fora.json goes a bit beyond and adds kp and latency (delay).
{
"nome": "treino",
"descricao": "as faixas que a própria tarefa Unitree-G1-29dof-Velocity randomiza no treino (unitree_rl_lab 4960b84, velocity_env_cfg.py, classe EventCfg)",
"atrito": [0.3, 1.0],
"massa": [-1.0, 3.0],
"empurrao_vel": [-0.5, 0.5]
}{
"nome": "fora",
"descricao": "além do treino: atrito um pouco abaixo de 0.3, carga maior e kp e atraso, que o treino não randomizou",
"atrito": [
0.2,
0.6
],
"massa": [
2.0,
8.0
],
"kp": [
0.6,
1.0
],
"atraso_ms": [
0,
30
],
"empurrao_vel": [
-0.5,
0.5
]
}randomizar.py samples 20 worlds per range with a fixed seed (7) and runs 10 s of walking in each one, with the push at t = 3 s.
F=${FTH:-$HOME/fth}; cd $F/sim2real && . $F/.venv/bin/activate
python3 kit/randomizar.py --seeds 20F=${FTH:-$HOME/fth}; cd $F/sim2real && . $F/.venv/bin/activate
python3 kit/randomizar.py --seeds 20 --faixa fora --detalhe | head -6faixa treino sobreviveu: 20/20 faixa fora sobreviveu: 8/20
Inside the training range, 20 out of 20. Outside, 8 out of 20.
1 atrito=0.45 massa=7.38 kp=0.91 atraso_ms=6 empurrão 172 N → de pé 2 atrito=0.20 massa=6.93 kp=0.92 atraso_ms=14 empurrão 119 N → caiu 3 atrito=0.30 massa=4.67 kp=0.80 atraso_ms=16 empurrão 219 N → caiu 4 atrito=0.45 massa=7.93 kp=0.69 atraso_ms=4 empurrão 194 N → caiu 5 atrito=0.21 massa=5.09 kp=0.79 atraso_ms=28 empurrão 50 N → caiu 6 atrito=0.40 massa=3.49 kp=0.60 atraso_ms=6 empurrão 131 N → caiu
World 1 has a mass of 7.4 kg and stays up; world 4, at 7.9 kg, falls; world 6 has friction 0.40 and falls. No single parameter explains the score: outside the range, it is the combination. Looking at just one world and blaming one parameter is the common mistake; compare scores and, to claim a cause, vary one parameter at a time (E2).
Measure what the training covered.
Run the sampling for both ranges.
Done when: python3 kit/randomizar.py --seeds 20 → faixa treino sobreviveu: 20/20 and faixa fora sobreviveu: 8/20.
Write a range identical to the training one, but with kp between 0.5 and 0.8 (the block below already does it), and run it.
Done when: python3 kit/randomizar.py --seeds 20 --faixa ~/fth/so-kp.json → faixa so-kp sobreviveu: 11/20.
For a G1 that will walk on a factory floor with a 2 kg camera on its head, write in three lines what you would add to the training ranges and why.
Done when: three lines, each with a parameter, a range, and the measured reason (e.g., "kp 0.5–1.0: only kp outside gave 11/20").
Same ranges as the training, plus kp between 0.5 and 0.8.
F=${FTH:-$HOME/fth}; cd $F/sim2real && . $F/.venv/bin/activate
cat > $F/so-kp.json <<'J'
{"nome": "so-kp", "atrito": [0.3, 1.0], "massa": [-1.0, 3.0], "kp": [0.5, 0.8], "empurrao_vel": [-0.5, 0.5]}
J
python3 kit/randomizar.py --seeds 20 --faixa $F/so-kp.jsonfaixa so-kp sobreviveu: 11/20
Just adding kp, which the training did not vary, knocks down 9 out of 20.
The explanation appears after your answer.
Question 1 of 4
The policy survived 20/20 inside the training ranges and 8/20 outside. What does that measure?skill
Question 2 of 4
In this policy, what does the unitree_rl_lab task not randomize?
Question 3 of 4
Why not randomize everything across the widest possible range?
Question 4 of 4
Why does randomizar.py use a fixed seed (7)?
Pick one answer. The explanation appears after you try.