Ackermann steering for car-like robots
Cars don't pivot. They turn around an instantaneous center, with both front wheels at different angles. The kinematic constraints, the bicycle-model approximation, and what changes for planners and controllers.
Diff-drive robots can pivot in place. Cars cannot. The wheels are anchored to a fixed steering axis and the inner wheel turns at a tighter angle than the outer one. This is Ackermann steering, and it constrains every controller and planner that touches a car-like robot.
The geometry
Two front wheels and two rear wheels. The rear wheels are fixed (no steering). The front wheels can each rotate around their own steering pivot — but their angles aren't free: they must point at a common instantaneous center of rotation (ICR) on the rear-axle line. That's the Ackermann condition.
Mechanically: a four-bar linkage between the steering wheel and the two front wheels enforces this geometric constraint. Software-wise: you command an "average" steering angle δ, and the linkage produces the correct asymmetric inner/outer angles automatically.
The bicycle model
For control, almost everyone replaces the four-wheel model with a bicycle: one rear wheel, one steered front wheel, separated by the wheelbase L. The kinematics:
ẋ = v · cos(θ)
ẏ = v · sin(θ)
θ̇ = (v / L) · tan(δ)
Where v is forward speed (rear-wheel velocity), θ is heading, δ is steering angle, L is wheelbase.
The ratio v/L · tan(δ) is the angular rate of the chassis. Equivalent: turning radius R = L / tan(δ). Bigger L means wider turns. Larger |δ| means tighter turns. δ = 0 means straight.
What's different from diff-drive
- Cannot pivot in place. If
v = 0, thenθ̇ = 0regardless ofδ. Steering only works while moving. - Has a minimum turning radius.
R_min = L / tan(δ_max). Your robot can't make a U-turn in a corridor narrower than2 · R_min. - Steering rate is limited. The mechanism takes time to slew. Real controllers respect a steering-rate limit, not just a steering-angle limit.
This is what makes parallel parking multi-step: a single forward arc can't reach a parking spot orthogonal to your direction. You need forward + reverse maneuvers.
Velocity-vs-Twist control
Diff-drive controllers consume geometry_msgs/Twist (linear vx + angular wz). Ackermann controllers consume ackermann_msgs/AckermannDriveStamped (speed + steering_angle). Many ROS 2 stacks accept Twist and convert internally:
δ = atan2(wz · L, vx)
This works as long as vx ≠ 0. Pivot-in-place commands (vx = 0, wz ≠ 0) are infeasible — most controllers either reject the command or stop.
Planning for Ackermann robots
RRT or hybrid-A* are the standard planners. Both must respect the kinematic constraint. The planning state is (x, y, θ) and not all motions are reachable — the planner expands neighbors using only feasible motion primitives (forward + steering arc, reverse + steering arc).
Common implementations: Dubins paths (forward-only) and Reeds-Shepp paths (forward + reverse). Both produce optimal-length paths from start pose to goal pose for a Ackermann robot.
What to know before implementing
- Measure your wheelbase, not the spec. Datasheet wheelbase is design intent; your robot's measured wheelbase differs by 1–3% after assembly. The bicycle model's accuracy is sensitive to this.
- Check your steering-angle convention. Some hardware reports center-zero with positive = left. Some report 0–π. Get this wrong and your robot will turn the opposite of what the controller commands.
- Linearize for low-speed control. The bicycle model has a
1/L · tan(δ)nonlinearity. For low speeds and small angles, linearize and use LQR or PID. - For high speed, switch to dynamic models. The bicycle model assumes no slip. Above ~10 m/s on a robot with non-zero mass, slip matters; use a "dynamic bicycle" with cornering stiffness.
Real-world examples
- F1tenth racing — the canonical hobby Ackermann platform. The whole stack (RL, MPC, optimal control) is published and reproducible.
- Most autonomous-driving research — uses bicycle-model dynamics for planning, dynamic bicycle for control.
- Mobile manipulators with steered front wheel (Toyota HSR style) — different drive but same kinematic class.
Exercise
Simulate a bicycle in Python: state (x, y, θ), inputs (v, δ), integrate Euler at 50 Hz. Drive forward at 1 m/s with constant δ = 0.3 rad for 10 seconds. The trajectory should be a near-circle. Compute the radius from the path; verify it matches L / tan(δ). Now add a steering-rate limit (|δ̇| ≤ 1 rad/s) and watch how the trajectory changes when you try to step-change the steering angle.
Next
Omnidirectional drive — mecanum and Swedish wheels — for when you want sideways motion without giving up reasonable mass.
Comments
Sign in to post a comment.