Skip to the lesson
FixTheRobot Home / VLA / Phase 7 / 7.7

VLA · Phase 7 · VLA Implementation and Experimentation

7.7 — Simulation-Based Manipulation Experiments

Running controlled manipulation experiments in simulation.

  • Roadmap phase 7
  • VLA Implementation and Experimentation
  • About 14 minutes to read

Simulation lets you run the same experiment a thousand times. This lesson shows how to do it properly: seeded scenes, paired comparisons, one-factor sweeps and a check on how far to trust the result.

Claims about papers, models and textbooks carry numbered references, listed with what each one is cited for in the References. Code marked “Toy model” is our own illustration, not the cited system.

Learning objectives

After this lesson, you should be able to:

  • Generate repeatable scenes from seeds.
  • Compare two policies on shared scenes.
  • Run a one-factor sweep.
  • Check whether simulation ranks policies like the real robot.
  1. Define scenes by seed
  2. Run each policy on the same seeds
  3. Count agreements and disagreements
  4. Sweep one factor at a time
  5. Check the simulator’s ranking against reality
Controlled experiments in simulation.

The one-sentence idea

Fix the scenes, change one thing, compare in pairs.

Repeatable and paired.

Why experiment in simulation

Real-robot trials are slow, costly and hard to repeat. Simulation is fast, free and exactly repeatable, which makes it the right place for controlled experiments, with one caveat: it is not the real world (the reality gap, lesson 1.1[1]). Simulators such as MuJoCo are physics engines for control: MuJoCo handles multi-joint dynamics in generalised coordinates and uses velocity-stepping algorithms for contact, with models written in an XML format or through a C++ API.[2] Benchmarks package scenes and tasks on top of an engine. LIBERO, for example, has 130 tasks in four suites (LIBERO-Spatial, -Object and -Goal with 10 tasks each, and LIBERO-100) with human teleoperated demonstrations.[3] And SIMPLER builds simulated versions of real evaluation setups (RT-1 and Bridge-V2) after finding that real-world evaluation is not scalable and has reproducibility problems.[4]

This lesson is about the experimental method, which applies to any simulator. The cells use a tiny simulated reaching task so you can run them here; lesson 8.1 covers benchmarks in more detail.

Repeatability: seeds and scenes

A trial is a scene plus a policy. If the scene comes from a seed, anyone can regenerate the exact same scenes. That makes comparisons fair (same scenes for both policies) and failures reproducible (rerun scene 17):

import numpy as np

def make_scene(seed):
    rng = np.random.default_rng(seed)
    return {"hand": rng.uniform(-1, 1, 2).round(3).tolist(), "goal": rng.uniform(-1, 1, 2).round(3).tolist(), "light": round(float(rng.uniform(0.5, 1.5)), 2)}

print("scene 17:", make_scene(17))
print("scene 17 again:", make_scene(17))
print("identical:", make_scene(17) == make_scene(17))
print("scene 18:", make_scene(18))

Output:

scene 17: {'hand': [0.69, -0.678], 'goal': [0.115, -0.264], 'light': 0.71}
scene 17 again: {'hand': [0.69, -0.678], 'goal': [0.115, -0.264], 'light': 0.71}
identical: True
scene 18: {'hand': [-0.201, 0.435], 'goal': [-0.438, -0.835], 'light': 1.47}

Log the seed with every result. “Fails on seed 17” is a debugging handle; “fails sometimes” is not.

Fair comparison: the same scenes for both policies

Run policy A and policy B on the same set of seeds. Then count, per scene, who succeeded. Only the scenes where they disagree tell you anything about which is better:

import numpy as np

def run(policy_gain, seed, noise=0.05):
    rng = np.random.default_rng(seed)
    hand, goal = rng.uniform(-1, 1, 2), rng.uniform(-1, 1, 2)
    for _ in range(10):
        hand = hand + policy_gain * (goal - hand) + rng.normal(0, noise, 2)
    return bool(np.linalg.norm(hand - goal) < 0.15)

seeds = range(200)
a = np.array([run(0.30, s) for s in seeds])               # policy A
b = np.array([run(0.45, s) for s in seeds])               # policy B reaches faster

both, neither = int(np.sum(a & b)), int(np.sum(~a & ~b))
only_a, only_b = int(np.sum(a & ~b)), int(np.sum(~a & b))
print("A success rate:", a.mean(), "| B success rate:", b.mean())
print("both succeed:", both, "| neither:", neither, "| only A:", only_a, "| only B:", only_b)

Output:

A success rate: 0.875 | B success rate: 0.94
both succeed: 174 | neither: 11 | only A: 1 | only B: 14

Toy model. A one-line controller with two settings. The structure of the comparison, not the policies, is the point.

The scenes in which only one policy succeeded carry the evidence. If “only B” is far larger than “only A”, B is better on these scenes; if they are close, the difference between the success rates is probably noise. This is a sign test on the disagreements, the paired version of the bootstrap in lesson 7.6.

Randomising on purpose

Varying the scene deliberately, in lighting, positions and object properties, is called randomisation. The domain randomisation paper trained a detector only on simulated images with randomised, non-realistic textures and localised real objects to about 1.5 cm; the argument is that with enough variability in the simulator the real world looks like just another variation.[5] In evaluation, the same idea lets you measure how success changes along one axis (lesson 5.5):

import numpy as np

def run(seed, noise):
    rng = np.random.default_rng(seed)
    hand, goal = rng.uniform(-1, 1, 2), rng.uniform(-1, 1, 2)
    for _ in range(10):
        hand = hand + 0.3 * (goal - hand) + rng.normal(0, noise, 2)
    return bool(np.linalg.norm(hand - goal) < 0.15)

for noise in (0.02, 0.05, 0.10, 0.20):                      # one factor: how noisy the actuators are
    rate = np.mean([run(s, noise) for s in range(300)])
    print(f"actuator noise {noise:.2f}: success {rate:.2f}")

Output:

actuator noise 0.02: success 1.00
actuator noise 0.05: success 0.87
actuator noise 0.10: success 0.44
actuator noise 0.20: success 0.16

One factor at a time gives a curve, and a curve shows where the policy starts to break.

How far to trust the simulator

The question is always whether the simulator ranks policies the way reality does. SIMPLER reports a strong correlation between simulated and real performance in its paired evaluations.[4] You can compute the same kind of check yourself: rank your policies in simulation and on the real robot, and measure how well the orderings agree with a rank correlation (1 means identical order, −1 reversed):

import numpy as np

sim  = np.array([0.80, 0.65, 0.50, 0.40, 0.30])             # invented success rates of five policies in simulation
real = np.array([0.55, 0.60, 0.35, 0.20, 0.25])             # invented success rates of the same policies on the robot

def ranks(x):
    return np.argsort(np.argsort(x))

def spearman(a, b):
    ra, rb = ranks(a), ranks(b)
    return float(np.corrcoef(ra, rb)[0, 1])

print("rank correlation, simulation vs real:", round(spearman(sim, real), 2))
print("the simulator overestimates every policy:", bool(np.all(sim > real)))

Output:

rank correlation, simulation vs real: 0.8
the simulator overestimates every policy: True

Toy model. The success rates are invented to show the calculation. They are not SIMPLER’s numbers.

Here the simulator is optimistic about every policy yet mostly orders them as the robot does (correlation 0.8): the middle policy agrees, while the top two and the bottom two each swap places. That is the kind of agreement you need for simulation to guide choices, though with five policies it is weak evidence. If the ranking does not hold, do not use simulation to choose; use it only to catch gross failures.

Common misconceptions

Misconception 1 “If it works in simulation, it works on the robot.”

Correction There is a reality gap; check that rankings agree.

Misconception 2 “More random trials is the same as a fair comparison.”

Correction Paired scenes remove luck of the draw.

Misconception 3 “Randomisation guarantees transfer.”

Correction It helps for the variation you randomise.

Engineering takeaways

  1. Seeds make scenes repeatable.
  2. Paired comparison counts disagreements.
  3. Sweep one factor.
  4. Validate the simulator.

Same scenes, one change.

Knowledge check

Try each question first, then reveal the explanation.

Question 1

Why log the seed with every result?

Explanation

So a specific failure can be reproduced and debugged.

Question 2

In a paired comparison, which scenes carry the evidence?

Explanation

Those where only one policy succeeded.

Question 3

A rank correlation of 1 means what?

Explanation

Simulation and the robot order the policies identically.

References

Numbered notes in the text, like [1], point here. Each entry says what it is cited for and how that was checked. Papers and books can be revised or misread, so follow the links before relying on a detail. Code marked “Toy model” is our own illustration of an idea, not the code of the cited system.

  1. Zhao, W., Queralta, J. P. and Westerlund, T. (2020). Sim-to-real transfer in deep reinforcement learning for robotics: a survey. IEEE Symposium Series on Computational Intelligence (SSCI) 2020. arXiv:2009.13303 · doi:10.1109/SSCI47803.2020.9308468

    Cited for:

    • Policies trained in simulation can perform worse on real hardware because simulated and real environments differ (the reality gap); the survey covers domain randomization, domain adaptation, imitation learning, meta-learning and knowledge distillation as responses. Checked against the paper’s abstract.
  2. Todorov, E., Erez, T. and Tassa, Y. (2012). MuJoCo: A physics engine for model-based control. IEEE/RSJ IROS 2012, pp. 5026–5033. doi:10.1109/IROS.2012.6386109

    Cited for:

    • A physics engine for model-based control that handles multi-joint dynamics in generalised coordinates, uses velocity-stepping algorithms for contact, and supports models written in a C++ API or an XML format. Checked against the paper’s abstract.
  3. Liu, B., Zhu, Y., Gao, C., Feng, Y., Liu, Q., Zhu, Y. and Stone, P. (2023). LIBERO: Benchmarking knowledge transfer for lifelong robot learning. NeurIPS 2023 Datasets and Benchmarks / arXiv. arXiv:2306.03310

    Cited for:

    • A benchmark of 130 tasks in four procedurally generated task suites: LIBERO-Spatial, LIBERO-Object and LIBERO-Goal with 10 tasks each (targeting spatial relationships, objects and task goals), and LIBERO-100 with 100 tasks; human-teleoperated demonstrations are provided for all tasks. Checked against the paper, via summaries of its text.
  4. Li, X., et al. (2024). Evaluating real-world robot manipulation policies in simulation. CoRL 2024 / arXiv. arXiv:2405.05941

    Cited for:

    • Real-world evaluation of manipulation policies is not scalable and has reproducibility problems; SIMPLER is a suite of simulated environments for the RT-1 and Bridge-V2 setups, and paired simulation and real evaluations show a strong correlation between performance in the two. Checked against the paper’s abstract.
  5. Tobin, J., Fong, R., Ray, A., Schneider, J., Zaremba, W. and Abbeel, P. (2017). Domain randomization for transferring deep neural networks from simulation to the real world. IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS) 2017. arXiv:1703.06907

    Cited for:

    • A detector trained only on simulated images with randomised, non-realistic textures localised real objects to about 1.5 cm; the argument is that with enough variability in the simulator the real world looks like just another variation. Checked against the paper’s abstract.

What’s next

That completes the implementation phase. Next: evaluating and generalising, starting with benchmarks.

Next lesson

8.1 — LIBERO and other suitable simulation benchmarks

Standard simulated task suites for comparing policies.

Back to the VLA roadmap