Blog

Notes from the lab.

What we're learning while building the cognition layer for machines that move.

2026-07-14

Closing the loop: why feedback matters more than models

Most of the impressive robot demos you see are open-loop. A model perceives a scene, predicts a plan, and the robot executes that plan once — and if nothing disturbs it, the result looks sharp. The problem is that "nothing disturbs it" is not a property of the real world. A part shifts a few millimeters, a person steps into the corridor, a pallet gets set down mid-route, and the whole plan is quietly wrong from that point on. The model was never asked to notice.

What separates a system that works from one that demos well is the loop. We run perceive–plan–act forty times a second, and at every cycle we measure the difference between what the robot is actually doing and what it intended, then fold that error back into the next plan. A model gives you a plan; a loop gives you a plan that keeps being true. We've found the second-order benefits compound too: when perception knows planning will actually use its uncertainty, it stops overclaiming, and when control knows it'll be corrected, it stops trying to be perfect in one shot.

The honest trade-off is that a closed loop is harder to make fast. You can't afford a cloud round-trip, so everything has to fit in a fixed on-board budget — ours is 24 milliseconds end to end. That constraint shapes every architectural decision we make, and it's the reason we'd rather ship a slightly smaller model that runs in the loop than a bigger one that doesn't.

2026-05-28

Perception with uncertainty, not just labels

A label tells you what something is. It doesn't tell you how sure the robot is — and in the physical world, the second thing is usually the one that matters. If a robot confidently classifies a half-occluded obstacle as empty space, it drives into it. If it confidently reports a healthy bushing as corroded, a maintenance crew climbs out to fix something that isn't broken. Confidence that isn't calibrated is worse than no confidence at all.

So we made uncertainty a first-class output rather than a post-hoc score. Every estimate the perception stack emits carries a covariance, and where it matters we predict it heteroscedastically — the model outputs how wrong it might be, per estimate, instead of assuming a fixed error everywhere. Lidar dropout in a dust cloud, camera bloom at sunset, a reflective surface that neither sensor reads well: these show up as widening uncertainty rather than confident garbage.

The payoff is downstream. Planning can treat a low-confidence region as something to route around rather than a fact to act on. Inspection robots can flag a reading they can't trust and move on, which turns out to be exactly what operators want — a robot that tells you where it's unsure is more useful than one that's always confident and occasionally wrong.

2026-03-09

Running a 40 Hz cognition loop on the edge

"Run it in the cloud" is a tempting answer until you look at the control path. A round-trip to a remote GPU adds tens to hundreds of milliseconds of latency that you can't hide, and worse, it adds variance — the same input can come back in 30 milliseconds or 300 depending on network conditions. For motion control you need the opposite: a hard guarantee, every cycle, no exceptions. So the loop runs entirely on the robot's own compute, under a real-time scheduler with a fixed budget.

Our budget is 24 milliseconds: 11 for perception, 8 for planning, 5 for actuation, at 40 Hz. The numbers aren't arbitrary — they're what it takes to keep a mobile manipulator's contact tasks stable and a vehicle's re-planning ahead of the world. Getting there meant a lot of unglamorous systems work: quantized models, fused kernels, a scheduler that enforces the budget rather than hoping for it, and a watchdog that degrades gracefully when a stage overruns instead of stalling the whole loop.

The degradation path is the part we're proudest of. If perception misses its window, the loop drops to a slower replanning cadence and keeps the safety filter running — the robot gets more cautious, not stopped. That's the difference between a system that's fast on average and one that's fast when it matters.

2025-11-12

Why we stopped scripting grasp poses

Early on we built grasping the way everyone builds grasping: an engineer measures the part in CAD, defines a canonical approach vector, and the robot replays it. It works perfectly — on the one part, in the one orientation, in the fixture it was measured in. The moment the part is a few degrees rotated, or stacked, or sitting on an uneven surface, the scripted pose is wrong, and every correction is another hand-authored special case.

We tore that out in favor of learned affordances: the robot predicts where and how a part can be grasped, over a distribution of poses, and the planner picks a grasp that's reachable from where the arm actually is. Then force/torque feedback does the fine work — impedance control means the gripper complies when a part is a millimeter off, instead of jamming and faulting the cycle.

The shift changed what we optimize for. A scripted grasp is fast when it's right and broken when it isn't; a learned grasp with compliant contact is slightly less deterministic but keeps working across the variation a real bin actually contains. That trade — a little determinism for a lot of robustness — turned out to be the right one, and it's the same shape of trade we've made across the whole stack since.