Educational Content  /  Engineering

Teaching a Three-Point Turn

Article 6 min read

A one-line brief, a week of AI agents, and a lot of cutting.

Andrej Karpathy's autoresearch inspired the shape of this experiment: let an AI agent change one thing, give it a cheap score, and run the loop. Ours proposed a motion maneuver, simulated it against vehicle geometry, and scored whether the robot fits the aisle.

Same family. Very different geometry. Sherpa XT Lite Skid steer • In-place pivot • R = 0 m swept footprint turn radius 0 m Sherpa 10K Bicycle model • Sweeping arc • R_min ≈ 1.5 m swept footprint along arc arc center no in-place turn possible The drivetrain change made in-place rotation physically impossible on the 10K.

The motivation: "make it turn around"

The Ati Robotics Sherpa XT Lite tugs up to 1,500 kg and pivots in place: a 0 m turn radius inside roughly 1.5 m of swept envelope.

The Sherpa 10K pulls 10,000 lb (≈4,500 kg). Getting there meant a drivetrain rebuilt for the duty cycle and a steered axle in place of independent left-and-right traction. Far more capable hauler, different kinematics, no in-place rotation.

Customers liked the platform, then hit the same wall in every real aisle: "it can't turn around here."

Same aisle. Two outcomes. XT Lite — in-place turn 1.5 m corridor • success 1.5 m ✓ FITS Sherpa 10K — can’t pivot Same 1.5 m corridor • footprint clips walls 1.5 m ✕ CLIPS WALLS The exact constraint a three-point turn was meant to solve.

The brief was a single sentence: build a reliable, planner-callable three-point turn (forward, reverse, forward) in the smallest aisle the geometry allows. Over a week, agents wrote most of the spec, math, simulation and tests. Nearly all the work that mattered was taking things out.

Spec PRD from data Simulate Plot, find bugs Shrink 8 knobs → 2 Hand off To coding agent

Act 1: from a one-liner to a real spec

The first prompt was the brief itself. What came back was a placeholder: the maneuver in words, two constraints, and no contact with how our planner composes routes or what the vehicle can do.

It got serious when we anchored the agent in real data: logs from a manual three-point turn (motor CAN, controller inputs, SLAM poses), with instructions to find the segment structure. Now the spec had ground truth: a known-good human run to fit against and to beat.

Annotated XY trace of a manual three-point turn

Least-squares fits where the operator held steering lock came back almost embarrassingly clean: RMS residuals around 1 cm, R_min ≈ 1.0 m at full steering, implied wheelbase 0.85 m, within a hair of CAD. The bicycle model described this vehicle exactly. Every geometry decision after that had a closed-form check beside it.

Geometry recovered from telemetry: three-panel sequence

Act 2: the simulator as a thinking tool

We wrote a 200-line simulator that read routes in our production format and forward-integrated the kinematics, so anything it accepted, the planner would accept too. That throwaway became the workbench: design a route → expand → simulate → plot.

Four design attempts on the same 3.5 by 3.5 m aisle

The design that died first

Our first variant wasn't a three-point turn at all: pre-shift sideways with a Bézier lane change, then a tighter forward/reverse. Clean on paper, dead in minutes. A cubic Bézier with matched end tangents, lateral offset D and longitudinal run Lx has endpoint curvature κ = 8D/(3·Lx²). The run, not the offset, is what kills it. Curvature scales as 1/Lx², and a tight aisle is exactly where Lx is short. It stays in the design folder marked rejected so nobody rediscovers why.

Three things the plots surfaced

  1. The blend penalty. Our planner's turn primitive is a cubic Hermite blend between tangent vectors. At the arc angles this maneuver uses, peak curvature inside the blend is 1.5/R rather than 1/R. Ask for radius R and the chassis absorbs 50% more curvature. That factor propagates into aisle widths, feasibility checks and the envelope math.
  2. The reverse-leg collapse. In a symmetric turn the reverse leg sweeps the tangent from −ψ to +ψ, driving Σsin(θ) ≈ 0 in our path expansion and collapsing the y-component under the blend rescaling. The result was a flat line where an arc belonged. Fix: split the reverse turn at the arc's midpoint, where sin(θ_mid) = 0 makes tangent continuity exact.
  3. Body envelope vs. rear-axle path. In a plot of a 3.5 × 3.5 m aisle, the rear-axle path stayed cleanly inside the box while the body clipped a corner. Customers care about the swept envelope. Padding by the body diagonal √(ℓ² + w²) separates the two. A textbook check. What the simulator supplied was the reason to look.
1. Cubic-blend penalty Peak curvature is 1.5/R, not 1/R Path along arc Curvature κ 1/R 1.5/R peak +50% 2. Reverse-leg collapse Symmetry flattens the path; split the arc x y Bug: flat split point Fix: arc 3. Body vs. axle path Pad by √(L² + W²), not just rear axle aisle rear-axle (inside) body clips! Three subtle bugs the geometry didn’t reveal until we plotted it.

Act 3: shrinking the surface area

The first feasibility analysis had eight knobs: ψ, R, drift, wheelbase, R_min, body length, body width, blend penalty. Far too many to hand a planner caller.

The constraint chain collapsed them. Aisle aspect ratio sets a feasible band for ψ, 60° to 70.5° (arccos(1/3)). Drift goes to zero at the bottom of that band, so ψ pins to 60°, and R follows from aisle width and ψ. The rest are platform constants. What a planner sees is two numbers, aisle width W and length L, and the shorthand ["3pt_turn", W, L] fell out mechanically.

From 8 knobs to 2 ψ R drift wheelbase R_min body L body W blend penalty ["3pt_turn", W, L] The hard part of an API is what you take out, not what you put in.

Then we stopped generating and started auditing. Three questions, all answered by grep:

  • Where does the solver compose the dispatchable route? Exactly one site, so a two-line hook suffices.
  • Are there existing three-point-shaped waypoints? Zero, so there was no migration burden.
  • Does anything already own the name? One function, parking-specific, different geometry, no conflict.

That cut the integration plan from "redesign the route schema" to "add two lines."

Act 4: handing it off to another AI

The spec went to a coding agent, packaged as documentation, tests and constraints. That was enough for the agent to build the feature without inventing anything, and without being able to disturb existing route planning.

Coding-agent-ready handoff Six artifacts, three test tiers, 49 pytest scaffolds PRD.md The why Requirements + 12 feasibility studies REQUIREMENTS { } implementation.md The what + how Types, signatures, phases DESIGN test_plan.md Definition of done Primitive-level tests 5 layers, 18 unit tests TESTS v2_wps_test_plan.md Load-bearing safety net 35 integration tests across 6 categories REGRESSION-CRITICAL v2_integration_plan.md Where it hooks in Two-line preprocessor hook + scope INTEGRATION 49 three_point_turn/ Skip on main, light up on import 49 pytest contracts scaffolded under ati/tests/ CONTRACTS Coding-agent-ready means more documentation discipline, not less.

The piece that made it work was a regression net: every existing route had to come through the new code completely unchanged. With that guarantee in place, handing the implementation to an agent stopped being a risk decision.

The handoff itself was a self-contained brief: the spec, the tests, and the handful of constraints not derivable from either. Those were written down explicitly rather than left for the agent to infer.

The agent pipeline, with human cuts in red Manual run telemetry CSVs, CAN, pose AI agent segment detection F1 / R / F2 Bicycle-model fit R_min, wheelbase wp_simulate.py design → expand → simulate → plot Design loop (iterate) 3 discoveries re-design PRD + tests written 6 docs, 49 pytests Coding agent implementation spec → code Production code 2-line v2 hook ✕ CUT lane-change variant ✕ CUT 6 of 8 knobs ✕ CUT scratch dirs deleted ✕ CUT v5 carveout AI produced the volume. The work was in choosing what to keep.

What we actually learned

The headline isn't "AI wrote the PRD." AI is very good at volume: long specs, alternative designs, exhaustive test grids. What made this work was repeated cutting: killing the lane-change variant, collapsing eight knobs to two, deleting scratch directories, carving the newer format out of the first PR. That loop of proposing, simulating, scoring and discarding is what Physical AI looks like at the geometry level.

Real data is the cheapest thing you can give an agent.

The spec was guesswork until we handed the agent logs from a manual run.

A throwaway simulator pays for itself in a week.

Two hundred lines, deleted the day the PR landed. It surfaced three bugs and settled every design tradeoff.

Agent-ready handoffs demand more discipline than human ones.

Every ambiguity is a place the agent guesses, and guesses propagate. Consistent naming, sourced-vs-derived constants and an explicit list of non-obvious constraints separate a clean landing from a week of rework.

The 10K now turns around in an aisle barely bigger than its own footprint, behind a planner call two numbers wide.

Customers asked us to teach it to drive like a car. The harder part was teaching ourselves to write a spec like an engineer.

Side by side: the human demonstration (left), and the maneuver the agents produced from it, running autonomously in the same aisle (right).

Sherpa 10K turning around in a 3.5 by 3.5 m aisle

See Ati in Action at Your Facility.

A live walkthrough of your floor, your routes, and your workflow is where the real questions get answered.