Two front wheels cannot both point straight ahead on a curve. Ackermann steering is the geometry that lets inner and outer wheels follow different radii so neither skids.
Most hobby robots use skid steering because it is simple. It also scrubs tyres, wastes battery and loses odometry accuracy on any surface with grip. For an outdoor AGV, an agricultural platform, a delivery robot or a small car-like rover, Ackermann steering is the correct answer. This guide covers the geometry, the linkage, the controller maths and the mistakes that make a build pull to one side.
Why the wheels need different angles
When a vehicle turns, all four wheels should rotate about a single point called the instantaneous centre of rotation. The inner wheel is closer to that point, so it must turn more sharply than the outer one. If both wheels are parallel, one of them must slip sideways, and the tyre resists.
The ideal relationship for a rear-drive vehicle steered by the front axle is:
cot(delta_outer) - cot(delta_inner) = track_width / wheelbaseWith that condition met, each wheel’s axis passes through the same turning centre. Real vehicles approximate it with a four-bar linkage because the exact curve is not producible with simple parts, and the error is small at normal steering angles.
The numbers that define your chassis
| Parameter | What it controls | Practical note |
|---|---|---|
| Wheelbase L | Stability and minimum radius | Longer is stable but turns wider |
| Track width W | Roll stability and inner wheel angle | Wider resists rollover, needs more space |
| Kingpin offset | Steering feel and scrub radius | Keep small on a light robot |
| Maximum steer angle | Minimum turning radius | Mechanically limit before the linkage binds |
| Caster angle | Self-centring tendency | Small on a servo-steered robot |
Minimum turning radius at the vehicle centreline, for a given maximum inner wheel angle, follows from the geometry:
R_min = L / tan(delta_max) + W / 2For a robot with a 500 mm wheelbase, 400 mm track and 30 degree maximum steer, the radius is about 900 mm to the centreline. Measure it after the build, because linkage losses usually stop the wheel well before the nominal angle.
Linkage options that work at robot scale
- Single servo, track rod. One servo drives an arm connected to both steering knuckles by a rod. Simple, cheap, and adequate up to about 30 degrees of steer on a light robot.
- Twin servos, one per wheel. Each wheel gets its own commanded angle from the Ackermann equation. No linkage bind, but the two servos must be calibrated to the same zero.
- Steering axle with bell cranks. Closer to a real vehicle, more fabrication, better load sharing on heavier platforms.
- Four wheel steering. Used on some AGVs for crab motion and tighter turns; considerably more control complexity.
On a 3D printed chassis, twin servos are usually the better first build. The linkage geometry is the hard part, and two independent servos let you correct the Ackermann relationship in software rather than in a printed part you have to reprint.
Sizing the steering servo
Steering torque is highest when the robot is stationary and the wheels are turned, because the tyres must scrub. That is a case to avoid, not a case to design for. Estimate the running torque and then add margin for kerbs and rough ground.
# rough steering torque estimate
# F_lateral from cornering, mu is tyre friction coefficient
F_lat = mu * m * g * (rear_share)
T_servo = F_lat * scrub_radius / linkage_ratio
# example: 8 kg robot, mu 0.7, rear share 0.5, 25 mm scrub, ratio 1.2
# F_lat = 0.7 * 8 * 9.81 * 0.5 = 27.5 N
# T_servo = 27.5 * 0.025 / 1.2 = 0.57 NmA standard hobby servo rated at 10 to 20 kg-cm gives roughly 1 to 2 Nm and is adequate for a small platform. Add a factor of two for shocks, and never rely on the servo to hold position against a wheel jammed against a kerb without a servo saver or clutch.
From path curvature to wheel angle
The controller should think in curvature, not in servo degrees. Given a desired path curvature kappa, the equivalent bicycle model steering angle is:
delta = atan(wheelbase * kappa)Then split that into inner and outer wheel angles with the Ackermann relation, and map each to a servo command using a measured centre and span. Doing the split in software keeps the linkage honest and makes the geometry easy to correct later.
def wheel_angles(delta, L, W):
if abs(delta) < 1e-6:
return 0.0, 0.0
R = L / math.tan(delta)
inner = math.atan(L / (R - W / 2))
outer = math.atan(L / (R + W / 2))
if delta > 0:
return inner, outer # turning left
return -outer, -inner # turning rightClamp the result to the mechanical limit. Commanding an angle the linkage cannot reach stalls the servo, heats it and eventually strips gears, while the robot keeps driving straight.
Steering and speed are coupled
Ackermann steering has a lateral acceleration limit set by tyre grip. If the robot drives too fast for the curvature it is asked to follow, the front tyres lose grip and the robot understeers wide. The safe speed for a commanded curvature is bounded by:
v_max = sqrt(mu * g / abs(kappa))With a friction coefficient near 0.7 and a curvature of 1 per metre, that is about 2.6 m/s. On wet concrete or loose gravel it is far lower. Most small robots never reach the limit, but a lightweight outdoor platform can, and the failure looks like a steering fault when it is a grip fault.
Common build mistakes
- Linkage arms that are too short, so the wheel angle is highly non-linear against servo travel and the two wheels stop agreeing.
- No mechanical stop, letting the servo push past the knuckle travel on every hard turn.
- Servo zero set by eye instead of by measuring the wheel with a straight edge.
- Wheels rubbing the chassis at full lock, which the servo fights without any visible sign.
- Different tyre diameters left to right, which makes the robot pull even with perfect geometry.
- Rear axle misaligned, so the robot crabbing down the road regardless of steering angle.
Before any control work, push the robot in a straight line on a smooth floor and check it travels straight with the steering centred. If it does not, fix the chassis. No controller can correct a bent frame without permanently steering into the error.
Odometry with steered wheels
Track the rear wheels for distance, because they follow the path more closely than steered wheels, and use the steering angle for heading rate. The bicycle model gives heading change per metre travelled directly:
d_theta = distance * tan(delta) / wheelbase
theta += d_theta
x += distance * cos(theta)
y += distance * sin(theta)This is the same model used by most path followers, which is convenient: the controller and the odometry agree by construction. Expect a few percent error over ten metres, dominated by wheel diameter uncertainty and tyre slip on turns.
Related: wheel encoders for robots, AGV versus AMR, agricultural robots in India, robot chassis buying guide, PID control explained.
Do I really need Ackermann geometry on a small robot?
Not always. Below walking pace on smooth floors, skid steering is simpler and works. Ackermann pays off when tyres grip, when odometry must stay accurate, or when the robot drives outdoors on grass, gravel or concrete.
Can I use one servo for both front wheels?
Yes, with a track rod and knuckles. Keep the steering arms long enough to stay near linear and add mechanical stops. Above roughly 30 degrees of steer on a heavier robot, twin servos are easier to make work.
What is the minimum turning radius of my robot?
It is the wheelbase divided by the tangent of the maximum steer angle, plus half the track width to the centreline. Measure the real maximum angle at the wheel after the linkage is built, since it is usually less than the nominal figure.
Why does my robot pull to one side?
Usually rear axle misalignment, unequal tyre diameters, a steering zero that was set by eye, or a servo horn installed one spline off centre. Check the chassis before changing the controller.
How fast can an Ackermann robot corner?
The limit is tyre grip. Safe speed falls as curvature rises, roughly as the square root of grip times gravity divided by curvature. Wet or loose surfaces reduce that figure sharply.
Sources and further reading
- Ackermann steering geometry — the geometric derivation and linkage history.
- ROS 2 documentation — ackermann steering controller interfaces and message types.
- Arduino Servo library — servo control reference used in the examples.


