← kavinjain.in Source on GitHub ↗

Distributed robotics · ESP32 · ESP-NOW · WebAssembly

A warehouse with no workers.

Small ESP32 robots run the floor themselves. They grip each parcel and carry it to the right dock, plan their own routes, and team up to carry a crate too heavy for one. There's no central server: every robot runs the same planner on the same shared picture, so they agree without negotiating. Amazon-style systems need a central planner and codes stuck all over the floor; this needs a phone camera and a radio.

On real robots. Georgia Tech's Robotarium ran the planner on 8 of its robots: 46 parcels in 300 s, where 8 runs of their simulator predicted 44 (95% CI 40.8–47.2). 0 plan disagreements in 3,029 snapshots, a crate carried by a pair, and one robot's battery "died" mid-run while the other 7 carried on. Their robots, camera and arena; my planner; the parcels are projected. 5× speed.

The floor below is live, not a video. It runs the robots' actual firmware, compiled to WebAssembly in your browser. Drop parcels, add robots, switch one off, and watch the swarm re-plan.

Same C++ that's flashed onto the robots (core/brain.h), driving a physics model of the floor with camera noise, motor mismatch, dropped radio packets and a gripper that misses 5% of the time. Proven in simulation; carrying needs a gripper on the physical robots, which run push mode until one is fitted.

0 s

Click the floor to drop a parcel · switch to heavy crate for a load one robot can't move · click a robot to cut its battery (click again to revive) · drag a dock to move it. In Morning rush there are two docks: parcels alternate between them.

robot · dashed line = its job · dots = its planned route carrying (or pushing) / calling for help parcel colour and letter = the dock it goes to faint lines = robots that can hear each other
01. How it's wired
SeesCeiling cameraA phone looks down at the floor. Tags on every robot and at the corners turn pixels into millimetres; parcels are found by colour.
RelaysGateway radioOne ESP32 on a laptop broadcasts a shared "where is everything" snapshot 15× a second over ESP-NOW.
DecidesEvery robotCounts who's nearby, picks its job, plans a route round everything, lines up, grips and carries. All on the robot.
SafetyFails to stoppedLose the snapshot for half a second, or hit the e-stop, and the motors cut out. A dead robot simply stops getting work.
02. The six rules

Count who's here

Every robot broadcasts a heartbeat 10× a second and counts who it hears. Switch a robot off and the rest notice within a second.

Split the work

Each robot runs the same plan on the same snapshot, so they agree without negotiating. Big jobs wait until enough robots are free; a spare robot doubles up on a parcel.

Grip, tug, carry

A robot lines up, drives in slowly, grips, then tugs back a few cm: a held parcel follows, a missed one doesn't. Then it carries the parcel to a free slot, keeping it clear of walls and other parcels.

Call for help

Nobody tells a robot a crate is heavy. If it drives and nothing moves, it radios for help; two robots grip it side by side and drive as one wide vehicle: ant-style teamwork.

Give up honestly

If every robot has tried and the load won't move, it's flagged stuck for a human instead of being shoved forever. It re-opens when more robots come online.

Run the floor

Like a shift manager, with no manager: carriers wait beside a full dock, ready the moment it clears; idle robots learn where trucks unload and wait just outside that bay, clear of where the next box will land. Parcels wait 54% less for pickup.

03. How it was tested
TestWhat has to holdResult
8 scenarios × 60 random seedsAll delivered (to the right dock), work split, crates carried in pairs, zero collisions. Seeds vary camera noise, motor mismatch (±8%), lost radio packets and missed grips. Carry vs push, same seeds:480 vs 462 / 480
Parcels right against the walls200 random floors. A pusher can't get behind a parcel on a wall; a gripper takes it from the open side.200 vs 118 / 200
Dense floors200 crowded floors: 6–10 robots, 10–14 parcels, two docks. All delivered with no collisions; carrying vs pushing (42,992 collision events). Of the 7 carry failures, 5 deliver everything but two robots touch.193 vs 15 / 200
Parcels dragged along a wallEvery seeded run, carry mode.0
Energy per delivered parcelEnergy model (motors, driver loss, gripper peak-and-hold), to be calibrated on the real robots. Carry vs push:20 vs 28 mWh
Floor manager40 ten-minute shifts of trucks arriving at random at 2–3 bays, the same trucks with the manager rules off and on. Mean wait before a robot picks a parcel up:14.8 → 7.5 s
CapacityTrucks arriving faster than the robots can clear them, 3 × 2 m floor. Parcels sorted per hour with 10 robots, and how much of ten times one robot's rate that keeps:1,502 /h · 68%
Leaderless consensusEvery robot computes the identical plan from the same snapshot, in any order.unit-tested
Camera pipelineSynthetic tilted-camera frames: robot position, heading, parcel position error; parcel colour picks the right dock.≤ 1.3 mm · 0.4° · 2.8 mm
04. From desk to a real warehouse
Smarter
  • Robots plan their next 2–3 pickups, not just the next one.
  • ✓ Done: sort by colour into separate docks (try Morning rush).
  • ✓ Done: grip and carry, like real warehouse robots, incl. two-robot carries.
  • ✓ Done: a floor manager with no manager: staging, learned arrival hotspots.
  • ✓ Done: ArUco tags on parcels, so no colour tuning under changing light.
  • Reserve route cells in time so robots never meet head-on.
  • Battery-aware jobs: low robots take short trips, then go charge.
Faster
  • Wheel encoders + IMU: steer at 100 Hz between camera frames, not 15 Hz.
  • Smoother path following and higher top speed once the steering is tight.
Real-world useful
  • Kiva (now Amazon Robotics) robots lift whole shelves and bring them to the picker: a baseline 600 picks an hour per person, against 200–400 for the best other automation.
  • No single point of failure: one robot failing doesn't stop the floor (true here too).
  • Replace the one ceiling camera with on-robot localisation to cover any floor size.
  • An orders API so a warehouse system can hand the swarm real work.

Kiva figures: Wurman, D'Andrea & Mountz, "Coordinating Hundreds of Cooperative, Autonomous Vehicles in Warehouses", AI Magazine 29(1), 2008.

05. What the research found

The floor is the limit, not the robots

On a 1.5 × 1 m floor, throughput stops growing at about 4 robots (≈ 800 parcels/h): the bays can't be unloaded and the docks can't clear any faster. Six more robots add no parcels, only 74% more energy per parcel.

My first benchmark lied

It showed the swarm collapsing as robots were added. The real cause: simulated trucks dropped boxes 13 cm from robots, boxing them in for good. A 30 cm "don't drop next to a robot" rule (a bay light on a real floor) took one layout from 36 to 134 parcels per shift.

Every failure, classified

Each failed run is labelled by what was left on the floor, then traced to its cause: a crate pair whose grip face flickered, a hold-and-wait deadlock at the dock, a parcel dragged out of its dock. When every robot ends up holding a parcel and none can move, all of them agree, without talking, which one sets its parcel down. Same 1,380 test runs: 97.3% → 99.35% (McNemar p = 8 × 10⁻⁷).

Ideas that didn't make it

Docks that drive to the busy bay: +20% at best. The mathematically optimal job assignment: worse (it reshuffles jobs every frame). Right of way by priority on free paths: 14% faster but robots bumped. Capping the fleet: saves energy, adds no parcels. Collision-free motion with a proof (Voronoi cells): robots stopped touching but started deadlocking.

Theory meets simulation

A queueing model (Mean Value Analysis), fed only measured one-robot timings, predicts throughput within 7% up to 8 robots. The 12% it overshoots at 10 robots is traffic: the most any better traffic planner could add.

Read the write-up

Design, every benchmark with its confidence interval, the rejected ideas and the papers this builds on: PAPER.md ↗

06. Known limits