Two YAM arms must turn an industrial hand tool face down on a mat and let go, using only static RGB-D cameras and the joint encoders (four cameras in simulation). A coding agent builds the policy from scratch as ordinary, inspectable code and improves it in a self-learning loop: run 360 simulated episodes, group the failures by mechanism, change the source, and regression-test. Over 36 versions the agent added 20 motion primitives in 5 families, combined into 4 flip strategies, and took the tune success rate from 24.7 % to 95.0 %. Nothing is learned inside the policy; what is learned lives in the code.
FlipAnything: 24 hand tools, each spawned face up at a random pose on a gridded mat in front of a bimanual YAM rig. One policy has to flip all of them, without being told which tool it is looking at.
Each iteration is a frozen snapshot evaluated on all 360 tune episodes. The agent reads the policy's own event log, groups the failures by the first mechanism recorded (no plan, lost grip, squeeze-out, receiving-hand pinch, false "done", lost track), writes a probe for the largest group, changes the code and evaluates again. Every version is kept, including the regressions. Run-to-run spread on identical code is about ±1.4 points.
The policy flips a tool with one of four strategies, chosen per observation from geometry and reachability, with both hand assignments searched. The strategies are built from 20 motion primitives. The chip on each primitive is the version where the self-learning loop added it or made it work; unmarked ones were in the first version.
Hand A pinches top-down, lifts and rolls 90°. Hand B pinches the far face, A releases, and B rolls back and sets the tool down face down. Used for 19 of 24 tools.
When no handover is reachable, A carries the tool to the middle of the mat, rotating it if needed. The target pose is chosen by planning the handover on the predicted scene.
For compact parts. A pivots the part about its bottom edge onto its side, past the tipping angle atan(W/H) read from the height map. B pushes it the rest of the way over.
For parts too wide to pinch. Two arc pushes with closed fingertips and no grasp. Since v012 the first direction is chosen so that the second push is also reachable.
Each row is a family. The table-assisted and in-hand families grew most during self-learning, because those were where episodes failed.
| Family | Primitives |
|---|---|
| Free motion & safety 4 | joint-space approachmove homeguarded descent, stop on stallfixed v015fingertip touch-offv014 |
| Grasping 4 | pinch closewidest band v0061 cm test liftv017open-to-width gentle releasev008back off along the fingersv008 |
| In-hand & bimanual 6 | lift and roll 90°slow v019A in-hand pose correction (ICP)v002B approach and insertB deepen and re-closev024A put-back, reversing its own pathv009B roll by the face normalv022 |
| Table-assisted 5 | pinch pivot about the bottom edgev003arc push with press-in biasv003brace the far edge while pushingpress a propped part flatset down to contact |
| Transport 1 | pick, carry, rotate, placev017 |
Most of the gain after v010 came from runtime checks wrapped around the primitives. Each turns a drop into a retry.
B's pinch is checked from the finger encoder before A releases (v010); A's grip after closing (v011). A width narrower than the planned section sends B 8 mm deeper (v024).
A 1 cm test lift catches a pinch squeezing out before the full lift (v017). The part is set down and re-planned instead of dropped mid-air.
A tool stopped part-way through a topple is finished with another push (v021). After a drop, the visible top is aligned against the first-seen top to tell up from down (v036).
Four fixed RGB-D cameras, no wrist camera and no learned models. Every step is explicit geometry: filtering, RANSAC, connected components, PCA and ICP. The pipeline runs every time the policy re-observes: at the start, after each stage, and when checking a grasp or a placement.
| Camera setting | Self-learning (simulation) | Real rig (Figure 2) |
|---|---|---|
| Static cameras | 4 rendered RGB-D cameras: top, bench, close, profile | 1 ZED Mini stereo camera overhead |
| Wrist camera | None | D405 on the right wrist |
| Depth | Rendered planar depth; optional noise ∝ z², dropout and extrinsic error | Stereo depth from real sensors |
| Viewpoints of the object | Four views from fixed, separated poses | One fixed overhead view, plus the moving wrist view |
The two camera settings differ. Every self-learning result on this page (the learning curve, the primitives, the per-tool scores and the videos) was measured with the four static simulation cameras below. The real rig has a single overhead camera and a wrist camera, so the policy sees fewer and different viewpoints there. This is one of the sim-to-real gaps.
Pinch lines every 8 mm and 15° of yaw, kept when the section fits the 94 mm gripper. Pads at the widest band; wedges rejected; ranked by gravity stability.
A yaw sweep plus 2-D ICP aligns the first-seen top surface to the current one. Footprint overlap, height RMS and colour difference decide up, side or down.
faces.pyTrimmed point-to-point ICP registers the pick-time model onto the points around the held tool (40 iterations, 12 mm trim). A corrects its pose or B re-plans.
perception.py · icp()No mass or friction is estimated. Tipping angle and slide-vs-tip come from the perceived shape.
Offline run of the policy on the saved episode-0 camera frames. Top-down view of the perceived height map, darker cells higher, world +x up the page. Everything shown is computed from the cameras; the tool mesh is never read.
Tune column: v036, the best full run (342 / 360). Held-out column: v016, the frozen policy's single registered run on episodes 15–19, from before the scissors contact pinch existed. Strategy column: what the policy chose in the example episode for that tool.
| Tool | Tune v036 (/ 15) | Held-out v016 (/ 5) | Strategy in example episode |
|---|
| Version | Tune (360) | Held-out (120) | Tune 0–4 with depth noise + calibration error |
|---|---|---|---|
| v001 handover only | 24.7 % | – | – |
| v012 push look-ahead | 86.9 % | 85.8 % | 58.5 % |
| v016 touch-off (frozen) | 89.4 % | 90.8 % | 88.3 % |
| v025 Graph-as-Policy | 91.9 % | – | – |
| v036 face check | 95.0 % | – | – |
The fingertip touch-off is what made the policy robust to calibration error: under noise it moved the score from 65.8 % (v015) to 88.3 % (v016) while leaving the clean tune score unchanged.
One recorded episode per tool from the frozen v021 policy. Left half: overview camera. Right half: side view. Pick a tool to play it.
Success is judged by the simulator. The policy never sees the score; it decides it is done from its own observation.
In simulation the policy reaches 95 %. On the real bench it fails far more often, and in different ways. This section lists what still fails in simulation, measures how the real rig differs, and reports what happened when those differences were put back into the simulator for another round of self-learning.
Measured from the policy's own event logs on 27 real sessions (YAM bench, 21–22 Oct 2026) and on the simulated runs.
| Signal | Real rig | Simulation | Note |
|---|---|---|---|
| Missed grasps | 21 % | 3.7 % | Simulation pools v001–v036; v036 alone is 1.8 %. Without 11 unusable real sessions (a gripper-direction bug), real misses are 14 %. |
| Slip in the air after a passed lift test | 29 % | 0 % | Zero by construction in simulation, which ran without the slip guard. |
| Hand A's in-hand correction diverged | 15 % | 0 % | |
| Close width vs plan | −15 mm | −1 mm | Real grippers close well past the planned width. |
| Fingertip height at close | 15.6 mm | 8.4 mm | Real closes end higher above the mat. |
Each difference was modelled as a physical mechanism in the simulator and checked against a first-principles prediction. No rate was fitted to the real failures.
The real joints run a PD controller at kp 80/80/80/40/10/10, against 300 on every joint in the old twin. The hand sags 12 mm under a 0.47 kg load (real: 10 mm).
A blocked real grip holds about 50 N whatever gap is commanded. The old twin held 18 N.
With a soft arm (about 2.3 mm/N at the fingertips), a 50 N squeeze on a rounded section above its equator lifts the hand over the part. This explains the higher closes and the misses on round or thin parts.
The EVA mat lets a pressing fingertip sink 2–5 mm before it stiffens. The old twin's mat gave 0.4 mm.
Round rubber handles modelled as curved sleeves, not one convex hull. The spring clamp as two halves on a sprung pivot, not one rigid body.
Stereo depth artefacts, rig calibration error, encoder offsets, gripper reading error and one step of latency. The real rig also has different cameras (see Perception).
About 250 episodes over 10 hours on the rig's own code path, with the clamp, tape roll and folding tool at their real positions. A new primitive counted only if removing it lost episodes.