A modular manipulation system that bolts pretrained vision foundation models onto a GPU-accelerated task-and-motion planner — matching a VLA trained on 350 hours of robot data, with zero robot data of its own.
You walk up to a robot arm, point a camera at a cluttered table, and type: "serve the peanut butter crackers on each tray." Among the snacks are Goldfish, Cheez-Its, and nuts — and a reflective soda can is blocking the grasp on one of the cracker packs. You want the robot to just do it. No demonstrations. No retraining. No fiddling with the specific brand of cracker.
This is the dream of open-vocabulary manipulation: a robot that takes natural language + camera images in, and outputs correct motion out, on objects and in scenes it has never been trained on.
Approach 1 — VLA (Vision-Language-Action): train a giant transformer on hundreds of hours of teleoperated robot demonstrations. Input pixels + text, output joint commands directly. This is π0.5, OpenVLA, RT-2. It works, but the data is brutally expensive: π0.5-DROID was fine-tuned on 350 hours of embodiment-specific demos. And when it fails, you can't say why — it's one opaque blob.
Approach 2 — TAMP (Task and Motion Planning): explicitly reason about discrete action sequences (pick this, then place that) and continuous geometry (where exactly, along what collision-free path) at the same time. Precise and interpretable. But classical TAMP assumed you already had 3D models of every object — fine in a factory, useless on a random kitchen table.
The whole paper hangs on this table. Watch the data cost collapse:
| System | Robot training data | Setup time | Failures are... |
|---|---|---|---|
| π0.5-DROID (VLA) | 350 hours of demos | weeks of data collection | opaque (one blob) |
| TiPToP | 0 hours | < 1 hour install + camera calibration | traceable to a module |
And the punchline from 165 trials across 28 scenes: TiPToP matches or beats the 350-hour VLA — especially on tasks needing semantic reasoning, distractor rejection, and multi-step sequencing.
To "just work" on pixels, a system must solve, in one shot from a single camera view:
TiPToP's bet is that each of these is now a solved-enough sub-problem thanks to foundation models — and the win comes from composing them, not training a monolith.
The insight is almost embarrassingly simple, which is exactly why it's powerful: foundation models have quietly made every hard sub-problem of classical TAMP cheap — so stop training a giant policy, and instead glue the best off-the-shelf model into each slot of a planner.
TiPToP = TiPToP is a Planner That just works on Pixels. The emphasis on "planner" is the whole thesis: instead of a learned policy mapping pixels→actions, there is an explicit planner in the middle that reasons.
Every component is pretrained and frozen — TiPToP never updates a single weight. This has three consequences that drive the entire paper:
| Property | Consequence |
|---|---|
| No robot data needed | Deploy on a new arm in <1 hour — just calibrate the camera |
| Components are independent | Swap FoundationStereo for a better depth model tomorrow; nothing else changes |
| Failures are localized | When it drops a banana, you trace it to one module (here: convex-hull meshing) and fix that |
Contrast a VLA: improving it means collecting more data and retraining the whole blob. A modular system improves the way software improves — one library upgrade at a time.
Before we trace TiPToP's pipeline, we need to genuinely understand the two worldviews it bridges — because the experiments later show they fail in complementary ways, and that complementarity is the paper's deepest finding.
A VLA like π0.5-DROID is a closed-loop reactive policy. At every timestep t it observes images ot and joint state qt, and emits an action: at = π(ot, qt | L). It runs at 15 Hz, outputting chunks of 15 actions: joint velocities q̇ plus a binary gripper g. Crucially, it keeps looking — if a grasp slips, the next frame sees the slip and corrects. Reactivity is its superpower.
Its weakness: it must implicitly discover multi-step structure ("move the can, then grab the cracker") from raw language and pixels, with no explicit notion of geometry or sequencing.
TiPToP observes the scene once, at t=0, from a calibrated wrist camera. From that single stereo snapshot o0 = (I0left, I0right) it produces a complete timed trajectory a0 = {(qt, q̇t, gt)} for the entire task — then executes it open-loop, with no further looking. All the reasoning is up-front.
This phrase is the heart of TAMP. The discrete part is the symbolic plan skeleton — which actions in what order: [MoveFree, Pick(cracker), MoveHolding, Place(cracker, tray)]. The continuous part is the geometry — exactly which grasp pose, exactly where to place, along what arm trajectory. The two are coupled: a discrete plan might be infeasible because no continuous grasp exists (the can blocks everything), forcing a different discrete plan that moves the can first.
Plan-once: the trajectory is locked at t=0. Try perturbing the object mid-execution.
TiPToP is three modules in series. Each consumes a typed input and emits a typed output — and tracing those types is understanding the system. Let's follow one stereo image pair all the way to joint torques.
Three modules: Perception → Planning → Execution. Click a box.
Here is the contract, written as data with shapes — read this once and the whole paper unlocks:
| Stage | Input | Output |
|---|---|---|
| Perception | o0: stereo pair (2 × H×W×3), intrinsics K, baseline b, instruction L | per-object meshes + grasps, symbolic goal G |
| Planning | scene meshes, candidate grasps, goal G | timed trajectory {(qt, q̇t, gt)} |
| Execution | trajectory waypoints | joint torques τ at each control step |
The perception module forks into two branches that run simultaneously and only merge at the end:
They are deliberately decoupled: geometry doesn't care what an object is, and semantics doesn't care where it is in 3D. The merge step (Chapter 4) stitches "this mask" to "this chunk of point cloud" to "these grasps."
This branch turns flat pixels into graspable 3D geometry. Three steps: estimate depth, unproject to a world-frame point cloud, and predict grasps. Then the merge: convex-hull meshing and grasp-to-object assignment.
FoundationStereo takes the stereo pair and predicts a dense depth map D, aligned to the left image. Why a foundation model instead of the ZED camera's built-in stereo matching? Because the camera's matcher falls apart on the surfaces robots care about most: transparent, specular, and textureless objects (that reflective soda can!). FoundationStereo gives sharp object boundaries where it counts.
A depth map is per-pixel distance. To plan motion you need 3D points in the robot's world frame. Two transforms chained together do it:
Every symbol, in plain terms:
M2T2 looks at the full scene point cloud and predicts ranked 6-DoF grasp poses (position + orientation of the gripper). "Full scene" matters: because M2T2 sees surrounding geometry, its grasps are informed by clutter — though they are not guaranteed collision-free (that's the planner's job later). Some objects get no grasp; for those, the planner falls back to a heuristic top-down sampler.
Left: depth map. Right: unprojected world-frame point cloud. Tilt the camera and watch the cloud re-register.
Now the two branches meet. Using each object's SAM-2 mask (from Chapter 5), the corresponding points are pulled from the cloud, projected down to the object's lowest observed point, and a convex hull is computed — a watertight mesh. Each M2T2 grasp is assigned to its nearest object via a KD-tree lookup; grasps too far from any object point are discarded as noise.
Geometry alone can't tell "peanut butter crackers" from "Cheez-Its." That requires a model that has read the internet. The semantic branch is one VLM call that does two jobs at once, plus a segmentation step.
Gemini Robotics-ER 1.5 is queried once with the image and the instruction L. It jointly returns: (1) labels + 2D bounding boxes for every object, and (2) a symbolic goal G — a logical conjunction of predicates over those objects. The VLM's web-scale common sense is what grounds "peanut butter crackers" to the two Lance packages, and reasons that "each tray" means one package per tray.
TiPToP currently supports one predicate: On(a, b) — "object a should end up on object/surface b." The instruction "serve peanut butter crackers on each tray" compiles to:
A VLA has no explicit grounding step. To handle "pick up the largest toy," it must learn that relation implicitly from demonstrations. TiPToP's VLM just reasons about it and emits On(largest_toy, plate). In the experiments, π0.5-DROID scored 0/5 on four separate semantic scenes; TiPToP won seven of eight. The explicit symbolic layer is the difference.
The VLM gives a coarse bounding box. To extract clean per-object geometry you need a pixel-perfect mask. So each box is fed to SAM-2, which returns a tight segmentation mask from the left image. These masks are what Chapter 4's merge uses to carve the point cloud into per-object pieces.
The VLM grounds language to specific objects and emits On() predicates.
This is the engine room. We have a symbolic goal G and a scene of meshes and grasps. cuTAMP must find a sequence of actions and the continuous parameters (which grasp, where to place, what trajectory) that satisfies G without collisions. It does this with a beautiful trick: thousands of guesses, optimized in parallel on a GPU.
A PDDL-style symbolic planner lists candidate skeletons: action sequences with unbound continuous parameters (written with ?):
Critically, the planner generates multiple skeletons. Short ones grab the cracker directly. Longer ones first move the obstructing soda can. The planner doesn't know yet which is feasible — that's decided by optimization.
For each skeleton, cuTAMP samples a big batch of particles — each particle is one complete guess for all the unbound parameters: a specific grasp pose (from M2T2 or the heuristic sampler), a placement pose on the tray, and robot configurations via inverse kinematics. Most initial particles are infeasible — they collide, or the placement is unstable, or no IK solution exists.
Here's the magic. Each constraint becomes a differentiable cost: collision penetration depth, placement instability, kinematic infeasibility. cuTAMP runs gradient descent on all particles simultaneously on the GPU, nudging each guess toward satisfying every constraint. The total cost for a particle is roughly:
where each C is ≥0 and equals 0 only when that constraint is satisfied. A particle is feasible when C→0. Skeletons are ranked by how easily their particles reach C=0; the first to get enough feasible particles wins. If the "grab cracker directly" skeleton can't drive C to zero (the can always collides), cuTAMP abandons it for the "move can first" skeleton.
For each feasible particle, cuTAMP calls cuRobo (a GPU motion planner) to solve the remaining trajectory parameters ?τ — collision-free, time-parameterized paths between configurations. Output: the final {(qt, q̇t, gt)}.
Below is cuTAMP's core loop made interactive. Each dot is a particle — a candidate placement pose for an object. Red = high cost (colliding or unstable), green = feasible (C→0). Press Optimize to run gradient descent; particles flow toward the valid region (the tray, away from the obstacle). Add the obstacle to see particles forced to a different valid zone. This is exactly how "move the can first" emerges from "grab directly" failing.
Click Optimize. Watch red (infeasible) particles flow to green (feasible) zones.
# cuTAMP, in spirit: optimize a BATCH of particles in parallel # Each particle = one candidate (grasp, placement, config). import torch def total_cost(place_xy, obstacle_xy, tray_center, tray_r): # place_xy: [N, 2] batch of candidate placement poses # 1) stay inside the tray (stability/goal) d_tray = (place_xy - tray_center).norm(dim=1) c_goal = torch.relu(d_tray - tray_r) ** 2 # 2) avoid the obstacle (collision penetration) d_obs = (place_xy - obstacle_xy).norm(dim=1) c_col = torch.relu(0.12 - d_obs) ** 2 # penalize if too close return 1.0*c_goal + 3.0*c_col # weighted sum, all ≥0 place = torch.rand(64, 2, requires_grad=True) # 64 particles opt = torch.optim.Adam([place], lr=0.02) for step in range(100): cost = total_cost(place, obs, tray_c, tray_r).sum() opt.zero_grad(); cost.backward(); opt.step() # all particles, one step feasible = total_cost(place, obs, tray_c, tray_r) < 1e-4 # C → 0
The planner produced a perfect trajectory. But a plan is only as good as the controller that tracks it. TiPToP's planner assumes the robot's joints follow the plan exactly — and even sub-centimeter tracking error makes a grasp miss or a placement topple.
The authors found existing open-source controllers (including DROID's default Polymetis) couldn't track timed trajectories precisely enough. So they wrote their own joint impedance controller for the Franka arms. At every control timestep it computes joint torques:
Decoding every term — this is a PD controller plus physics feed-forward:
Once execution starts, TiPToP does not look again. No re-perception, no replanning. This works when the world is static and tracking is tight. It fails when an object moves unexpectedly or a grasp slips — there is no mechanism to notice and retry. This single design choice is the root of the dominant failure mode (Chapter 9).
Dashed = desired trajectory. Solid = actual. Watch tracking error with vs without feed-forward.
The claim is bold — zero-data TiPToP matches a 350-hour VLA — so the evidence has to be careful. The authors ran 165 trials across 28 scenes, in simulation, on their own DROID hardware, and (crucially) on an external team's DROID setup they'd never touched.
Toggle the categories below and watch the gap open as tasks get harder. On simple tasks they're roughly tied. On everything requiring reasoning, TiPToP pulls ahead — and on semantic tasks π0.5-DROID often scores zero.
Overall: TiPToP 98/165 (74.6% progress) vs π0.5-DROID 55/165 (52.4%).
TiPToP isn't just more accurate — it's usually faster. It plans one time-optimal trajectory and executes it; the VLA runs a reactive loop that idles and re-attempts. On can → mug: 18.6 s vs 41.0 s. On single-step real tasks, TiPToP finishes in ~15 s, roughly half the VLA's time. Of that, planning (perception + cuTAMP) is ~7–20 s.
Because nothing is trained, moving to a new robot is config, not data. Deploying on a UR5e took "a few hours": provide the URDF, generate collision spheres, write a cuRobo config, implement camera/controller interfaces. It also ran on a Trossen WidowX AI. And extending to a new skill (whiteboard wiping) took under a day — two new predicates, one new TAMP operator, a small wiping controller — touching zero existing perception/execution code.
Here's where modularity earns its keep. The authors ran 173 extra trials and traced every failure to a specific module. A VLA can't do this — failures are a single opaque blob. TiPToP turns "the robot failed" into "module X failed," which turns into "swap a better X."
Hover the bars: grasping dominates, and it traces straight back to the open-loop design choice from Chapter 7.
Grasping is the bottleneck — and most grasp failures are recoverable with a retry the open-loop system can't do.
| Failure | Count | Root cause | Modular fix |
|---|---|---|---|
| Grasping | 31/55 | M2T2 grasp looks good, fails in execution; or heuristic fallback is weak; no retry (open-loop) | Better grasp model; closed-loop re-perception |
| Scene completion | 13/55 | Convex hull over/under-approximates (the banana) → collisions | Learned shape completion (SAM-3D) |
| VLM errors | 6/55 | Gemini mis-detects or wrong bounding box | Better VLM (drops in directly) |
| cuTAMP | 5/55 | No feasible plan within time budget (cluttered) | More planning attempts; relax thresholds |
Open-loop execution. Over half of all failures are grasps that a simple retry would fix — but the system commits to one trajectory and never looks again. The most direct improvement: re-run perception and planning after each pick-and-place step. The honest framing here is itself a lesson: a clean modular architecture lets you name your single biggest weakness with a number.
TiPToP sits at the seam of two research traditions. Its real contribution is less a new algorithm than a demonstration: foundation models have made modular, training-free manipulation competitive with end-to-end learning. That reframes the field.
| Symbol / term | Means |
|---|---|
| o0 = (Ileft, Iright) | The single stereo image pair captured at t=0 |
| pworld = TeeworldTcameepcam | Unprojection: camera 3D point → world frame via FK + calibration |
| G = On(a,b) ∧ ... | Symbolic goal: conjunction of predicates from the VLM |
| Plan skeleton | Action sequence with unbound continuous params (?g, ?p, ?q, ?τ) |
| Particle | One complete guess for all continuous params; thousands optimized in parallel |
| C = Σ w·Cconstraint | Differentiable cost; particle feasible when C→0 |
| τ = KpΔq + KdΔq̇ + τg + τcor + Mq̈d | Impedance control law: PD + physics feed-forward |
| Open-loop | Plan once, execute without re-observing — TiPToP's defining choice (and weakness) |
Re-run the cuTAMP showcase (Chapter 6) with the obstacle toggled on and off. Notice: with the obstacle, some particles can never reach the tray without colliding — exactly the moment cuTAMP gives up on the direct skeleton and reaches for the "move the obstacle first" plan. You've just watched task-and-motion planning happen.