Φferromotion · textbook · chapter 4 rust → wasm · on-device
A hand can be pressed against an object and still not hold it. What separates a grip from mere contact is one geometric property — force closure — and this page computes it on your device with the same Rust metric a grasp planner optimizes.
Put two fingers on the same side of a mug and squeeze: it slips away the instant anything nudges it sideways. Put them on opposite sides and it is locked. Both are "touching." Only one is a grasp. The difference is whether the fingers, together, can push back against a disturbance from every direction at once — a shove, a pull, a twist, any combination.
That is a hard-sounding requirement — infinitely many directions — but it collapses to a single geometric test, and once you see it you can read a grip by eye.
A finger cannot pull, and it cannot push purely sideways — friction only lets it push within a cone around the surface normal, half-angle arctan μ. Every force it can apply, and the twist that force makes about the object's centre, is one point in a three-dimensional wrench space of (force, torque). A grip's whole repertoire is the cone of combinations its fingers can jointly produce.
Below, drag the fingers around the object and widen the friction with μ. Each gold wedge is one finger's cone.
the arrow is the weakest direction — the push the grip resists least; drag the fingers until it turns green
Here is the whole test. Collect the extreme wrenches at the edges of every finger's cone. The grasp can resist a disturbance in a given direction exactly when some combination of those wrenches points back against it. It can resist every direction — force closure — precisely when those wrenches surround the origin: when 0 lies strictly inside their convex hull.
Force closure is yes-or-no, but grips have degrees. The Ferrari–Canny Q1 metric measures the margin: the radius of the largest wrench-ball the grasp resists in every direction — the strength of its weakest direction. Q1 > 0 is force closure; larger is firmer. On load, this page ran the metric on two grips:
| Q1 — two fingers, opposite sides (a pinch) | … |
| Q1 — two fingers, same side | … |
| verdict | … |
The pinch scores positive and the same-side grip scores negative, on your device — the metric agrees with the intuition that one holds and one slips, and puts a number on how much.
Because a smoothed Q1 is differentiable in where the fingers land, a grasp synthesizer does not search blindly — it slides the contacts uphill on exactly this margin until the object is locked, then keeps climbing for robustness.
This is how a robot decides where to put its fingers. Not by matching a library of remembered grasps, but by holding a differentiable measure of "how securely am I holding this" and improving it — the same number you were just dragging fingers to maximize by hand. It generalizes to any object whose surface you can sample, and it degrades gracefully: a grip with a small positive margin is one a careful controller can still use, and the number tells you which.
What you just drove: force_closure_q1, primitive_wrenches and GraspContact from ferromotion-core, compiled to WebAssembly — the same code the native tools link against, not a reimplementation. Each contact's friction cone is linearized to primitive wrenches; Q1 is the Ferrari–Canny support-function minimum over sampled directions; the weakest-direction arrow is the argmin of that minimum. Nothing precomputed — every drag re-solves it.
Verified in the library: an antipodal pinch is force closure and a same-side grip is not · a narrow pinch needs enough friction to close · a symmetric tripod grips more firmly than a two-finger pinch · more friction never lowers Q1 · the reported weakest direction realises Q1 exactly. Each is a test in cargo test, not a claim in prose. See also ch.1 · ch.2 · ch.3.
Institute for Physical AI · the Rust library · crates.io