Φferromotion · textbook · chapter 10 rust → wasm · on-device
A robot rarely has just one job. It has to reach the target and keep its whole body clear of things and move smoothly — all at the same time, and reacting to a world that moves. This chapter fuses those into one motion, geometrically, with the same Rust code the native tools use.
Give an arm a goal for its hand and it is easy to servo toward it. Add an obstacle and it gets awkward: now the elbow, the forearm, the whole body has to stay clear too, and the importance of that flips from irrelevant when the obstacle is far to overriding when it is close. Stitching such behaviors together with hand-tuned weights is brittle, and re-planning every time the world moves is slow. What you want is for the behaviors to combine themselves, correctly, moment to moment.
RMPflow makes each behavior a Riemannian Motion Policy: a desired acceleration paired with a metric — a state-dependent weight that says how much this behavior should matter right now. Reach-the-goal has a modest, steady metric. Avoid-the-obstacle has a metric that blows up as the arm nears the surface. The behaviors are fused by a metric-weighted combination pulled back onto the joints, so near the obstacle its policy dominates and far away it simply disappears — no mode switch, no planner.
Below, a two-link arm reaches for the goal. Drag the obstacle into its path and watch the whole arm bend around it; drag the goal anywhere in reach.
the dashed ring is the obstacle's influence; push it onto the arm and the whole body flows around while the hand keeps reaching — clearance never goes negative
The obstacle's dashed ring is where its metric starts to bite. Drag the obstacle outside everything and the arm reaches in a clean line — the avoidance policy is present but weighted to nothing, so it contributes nothing. Slide it onto the path and, as the nearest arm point crosses the ring, that policy's weight climbs steeply and the arm yields exactly as much as it must, no more.
On load, this page put the obstacle squarely on the straight path between the arm's start and its goal, and ran the policy to rest:
| smallest clearance to the obstacle over the run | … |
| final hand-to-goal error | … |
| verdict | … |
The clearance stays positive the whole way — the metric's blow-up makes contact impossible — and the hand still lands on the goal. Both jobs, done at once, with nothing planned ahead.
Every behavior carries its own metric, and the geometry fuses them into one reactive motion — reaching where reaching matters, yielding where safety matters — so new behaviors compose in without re-planning and without a tangle of hand-tuned weights.
This is why reactive geometric methods took hold for whole-body control: a real robot faces a moving, cluttered world where a plan is stale the moment it is made, and RMPflow answers it by making arbitration a property of the geometry rather than a script. It draws on the same kinematics — the real Jacobians of the arm — as the model-based controllers, but spends them on reacting rather than planning. It is the composition member of this series: where other chapters found the one quantity that governs a system, this one lets many behaviors each name their own, and trusts the metric to referee.
What you just drove: RmpArm from ferromotion-control on a two-link arm built from URDF through the real ferromotion-core kinematics, compiled to WebAssembly — the same code the native tools link against. Every frame pulls back the attractor and per-control-point obstacle policies to a joint acceleration and integrates it; the Jacobians are the arm's real ones. Nothing precomputed — the motion is solved live as you drag.
Verified in the library: the arm reaches the goal while every control point clears an obstacle on the direct path · a far obstacle does not perturb the reach at all · the pass tightens continuously as the obstacle nears the path · clearance never goes negative. Each is a test in cargo test, not a claim in prose. See also ch.1 · ch.2 · ch.3 · ch.4 · ch.5 · ch.6 · ch.7 · ch.8 · ch.9.
Institute for Physical AI · the Rust library · crates.io