PaceDynamics Documentation Open the app
Contents

Suspension

Steering axis and Ackermann

The line a front wheel steers about, where it meets the road, and how far each wheel turns for the rack.

Model as of 0.338Figures from the Formula Student single-car templateOctave check Exact

A front wheel steers about the line through its two ball joints, the steering axis or kingpin axis. How that line leans, and where it meets the road against the contact patch, decide what the driver feels through the wheel and what steering does to the tyre. The rack and the tie rods decide how far each wheel turns.

The axis

The axis runs from the lower ball joint up through the upper one. Its lean back in side view is the caster, its lean inboard in front view the kingpin inclination (KPI):

Show the equations with
ν=arctan⁡−kxkz,λ=arctan⁡−kykz(1)
ν=2.468∘,λ=4.436∘(1)
𝐤
the unit vector from the lower ball joint to the upper, in the corner's own frame: x forward, y outboard, z up
ν
caster, positive with the axis leaning back at the top
λ
kingpin inclination, positive with the axis leaning inboard at the top
The front-left upright to scale in front view and in side view: the steering axis through the ball joints, where it meets the road, and the contact patchλ35.2 mmrsFront view: KPI 4.44°ν8.8 mmtmSide view: caster 2.47°The front-left upright to scale, at rest; the dimensions at the road are its offsets
Steering axis, and the contact patchWhere the axis meets the road
Fig. 1
The axis through the ball joints meets the road inboard of the patch and just ahead of it: the scrub radius and the trail.
Measured

Scrub radius and trail

Followed down, the axis meets the road at a point 𝐆. The contact patch 𝐊 is rarely there:

Show the equations with
𝐆=𝐏lbj+𝐤Kz−Plbj,zkz,rs=Ky−Gy,tm=Gx−Kx(2)
rs=35.2 mm,tm=8.8 mm(2)
rs
the scrub radius, positive with the patch outboard of the axis
tm
the mechanical trail, positive with the patch behind the axis

The trail is the lever the tyre's side force pulls on to turn the wheel back straight. The tyre adds its own, the pneumatic trail: it makes its side force behind the middle of its patch. Together they are most of what the driver feels. The scrub radius is the lever for the forces along the wheel: a braking force at a positive scrub radius pulls the wheel outward, and two front wheels braking unequally pull the steering.

The same two offsets at the wheel centre's height are the kingpin offset, 48.5 mm with the wheel centre outboard of the axis, and the caster offset, −0.74 mm: the template's axis passes 0.74 mm behind its wheel centres. The steering arm is the tie rod's ball's distance from the axis, square to it, 80.8 mm: the lever the rack turns the wheel with.

What steering does to the wheel

The upright turns about the axis, and the wheel and its patch turn with it. A wheel steered as the outside wheel of a turn, toe-in on its own corner, is tipped by the caster: its top leans into the turn, which is the camber the outside tyre wants. And because the patch sits off the axis, it moves up or down as it swings, and lifts or drops that corner of the car. To first order:

Show the equations with
dγdδ≈−tan⁡ν,dzdδ≈−(rstan⁡ν+tmtan⁡λ)(3)
dγdδ≈−0.0431,dzdδ≈−0.0384 mm/∘(3)
δ
this wheel's steer, positive toe-in, so positive for the outside wheel of a turn
γ
camber, negative with the top of the wheel in
z
the corner of the body's rise, with the tyre on the road; dz/dδ per radian, or per degree as in the second line

The app reads −0.0430 and −0.0384 mm/° from the linkage itself. On the template the outside wheel's corner drops as the wheel steers and the inside wheel's rises, by the same amount to first order: the body is jacked across its diagonal. The KPI adds a lift on both sides that grows with the square of the angle, which a slope at straight ahead does not show; the Analysis tab draws it through the lock.

The app takes these two with the lower wishbone held still and the rack moved 2 mm either way, as a wheel turns with the car standing on it. Held at the wheel centre's height instead, the linkage would swallow the lift.

The steering-wheel moment

The driver holds the steering wheel against everything the tyres do to the wheels it steers. Turn the steering wheel a little, δφ, and each tyre's force moves with its patch and its aligning torque with its wheel. The work the driver does is the work done against the tyres:

Mswδφ=∑front wheels(−𝐅⋅δ𝐊−Mzδψ)(4)
Msw
the moment the driver holds the steering wheel with
𝐅,Mz
the tyre's force at its patch and its aligning torque
δ𝐊,δψ
how far the patch moves and the wheel turns, for δφ of the steering wheel

Each term has a lever from this page: the side force acts through the trail, the force along the wheel through the scrub radius, the load through the jacking. The Vehicle Dynamics tool works the moment out this way along a manoeuvre; the check below does not cover it.

Ackermann

In a slow turn every wheel should roll about one point, on the line of the rear axle. The inside front wheel then steers more than the outside one, by a fixed rule:

Show the equations with
cot⁡δo−cot⁡δi=tL,Ackermann=100cot⁡δo−cot⁡δit/L %(5)
tL=12001600=0.750,100cot⁡21.48∘−cot⁡22.09∘0.750=10.4 %(5)
δi,δo
the inside and outside wheels' steer from straight ahead, both positive into the turn
t,L
the front track and the wheelbase

At 100 % the two wheels follow the rule; at 0 % they steer alike, parallel steer; below zero the outside wheel steers more. The template's rack steers it close to parallel:

rack steering wheel inside wheel outside wheel Ackermann ratio
10 mm 65.5° 7.13° 7.07° 8.4 % 9.22 : 1
20 mm 130.9° 14.44° 14.20° 9.1 % 9.14 : 1
30 mm 196.4° 22.09° 21.48° 10.4 % 9.01 : 1

The steering wheel's angle is the rack's travel over the rack ratio, 55 mm a turn; the ratio is that angle over the mean of the two wheels'. Ackermann is about slow corners. At speed the tyres run slip angles larger than these differences, and the inside wheel carries less load, so how much to run is a question of the tyre.

Plan view of a car in a slow left turn: each wheel square to the line from it to one turn centre on the line of the rear axleturn centreδiδoLtPlan view, front to the right, a slow left turn; not to scale
Fig. 2
Ackermann: the inside wheel steers more, so that both front wheels roll about one turn centre on the rear axle’s line.
Schematic
The outside front wheel’s steer against the inside wheel’s through the rack’s travel, against parallel steer and the Ackermann rule051015202530051015202530Inside wheel’s steer (°)Outside wheel’s steer (°)parallel steer, 0 %Ackermann, 100 %
The templateParallel steerThe Ackermann rule
Fig. 3
The template steers close to parallel: 13 % of Ackermann at full rack.
Measured

What the model assumes

  • The axis runs through the two ball joints; on a strut it runs from the lower ball joint to the top mount.
  • On the rig, every angle on this page is read against the chassis. In a load case the Kinematics tool reads caster, KPI, scrub and trail against the road the car leans over.
  • The rack slides straight across the car and moves both tie rods.
  • Ackermann is taken with the wheel centres held at the static ride.

In the app

Kinematics, in the readout rail: "Kingpin axis" gives caster, kingpin inclination, scrub radius, mechanical trail, the two offsets at the hub and the steering arm; "Per degree of steer" gives the camber and the corner's rise.

Kinematics › Analysis › Steering draws Ackermann, the two wheels' angles, scrub and trail through the rack's travel.

Vehicle Dynamics plots the steering-wheel moment along a manoeuvre, under "Steering effort".

Check it yourself

The script reads the axis off the ball joints, steers the front-left wheel with its lower wishbone held, and solves both front wheels at three rack positions for Ackermann.

steering_axis.mwith example_suspension.m, pd_corner.m, pd_upright.m, pd_metrics.m, pd_compare.mExact: agrees to machine precision
>> steering_axis

  Quantity                                This script   PaceDynamics       Diff
  -----------------------------------------------------------------------------
  Caster, front [deg]                         2.46812        2.46812   6.7e-13% 
  KPI, front [deg]                            4.43647        4.43647         0% 
  Scrub radius, front [mm]                    35.2047        35.2047         0% 
  Mechanical trail, front [mm]                8.81375        8.81375   7.1e-13% 
  Kingpin offset, front [mm]                  48.5345        48.5345         0% 
  Caster offset, front [mm]                 -0.741379      -0.741379   2.4e-13% 
  Caster, rear [deg]                          2.44705        2.44705   1.8e-14% 
  KPI, rear [deg]                             4.39871        4.39871     2e-14% 
  Scrub radius, rear [mm]                     40.9493        40.9493   2.8e-13% 
  Mechanical trail, rear [mm]                 10.9075        10.9075         0% 
  Kingpin offset, rear [mm]                   52.1538        52.1538         0% 
  Caster offset, rear [mm]                    1.47009        1.47009   4.5e-14% 
  Steering arm, front [mm]                    80.8223        80.8223   1.8e-14% 
  Camber per steer [deg/deg]               -0.0430423     -0.0430423   2.6e-11% 
  Steer jacking [mm/deg]                   -0.0383608     -0.0383608   5.4e-11% 
  Inside wheel at 10 mm rack [deg]            7.12824        7.12824   6.7e-13% 
  Outside wheel at 10 mm rack [deg]           7.07334        7.07334   4.8e-13% 
  Ackermann at 10 mm rack [%]                  8.3604         8.3604   2.5e-11% 
  Inside wheel at 20 mm rack [deg]            14.4365        14.4365   1.7e-13% 
  Outside wheel at 20 mm rack [deg]           14.1979        14.1979   7.5e-14% 
  Ackermann at 20 mm rack [%]                  9.0796         9.0796   1.6e-11% 
  Inside wheel at 30 mm rack [deg]             22.094         22.094   4.5e-13% 
  Outside wheel at 30 mm rack [deg]           21.4762        21.4762   1.3e-13% 
  Ackermann at 30 mm rack [%]                 10.4391        10.4391     2e-11% 

  All 24 quantities agree with PaceDynamics (largest difference 5.4e-11 %).
The script
%% Steering axis and Ackermann: the line a wheel steers about, and how far each wheel steers
%
% Companion to the documentation page "Steering axis and Ackermann". Runs unchanged in
% GNU Octave (7 or later) and MATLAB. Edit the car in example_suspension.m, or type your
% own hardpoints from the Kinematics tool, and run:
%
%   >> steering_axis
%
% What this computes:
%
% 1. The steering axis, through the two ball joints, at the static ride (pd_metrics):
%    its caster and inclination, where it meets the road against the contact patch
%    (scrub radius and mechanical trail), and against the wheel centre at hub height.
% 2. What steering does to the wheel. The lower wishbone is held still and the rack moved
%    2 mm either way, as a wheel turns with the car standing on it: camber per degree of
%    steer, and how far the patch drops, which lifts the car (jacking).
% 3. Ackermann. Each front wheel's steer at a rack position, the wheel centre held at the
%    static ride. The inside wheel of a turn should steer more: with both wheels rolling
%    about one point on the rear axle's line,
%        cot(outer) - cot(inner) = track / wheelbase,
%    and the app's percentage is the left side over the right. The app finds the static
%    ride at each rack position by a search that stops within 1e-4 mm of it; the script
%    solves where it stopped (example_suspension.m gives it), so the two agree to their
%    last digits. Solved at the ride itself, the 10 mm row moves in its sixth digit.
%
% Part of the PaceDynamics documentation, https://pacedyn.dev/docs
% SPDX-License-Identifier: MIT

[car, app] = example_suspension();
g = 9.81;
Fz = car.massTotal * g * [car.frontMassFrac, 1 - car.frontMassFrac] / 2;   % N, per wheel
R0 = car.tyreFreeRadius - Fz / car.tyreRate;                  % mm, the radius each axle stands on

axles = {pd_corner(car.front), pd_corner(car.rear)};
read = @(a, p, R) pd_metrics(p.at(a.ubj), p.at(a.lbj), p.at(a.C), p.n, p.at(a.tieOuter), R);
for ax = 1:2
  a = axles{ax};
  s(ax) = read(a, pd_upright(a, 'travel', 0), R0(ax));
end

% Steering with the lower wishbone held where it stands (its angle 0), rack 2 mm each way.
f = axles{1};
lo = read(f, pd_upright(f, 'beta', 0, -2), R0(1));
hi = read(f, pd_upright(f, 'beta', 0,  2), R0(1));
camberPerSteer = (hi.camber - lo.camber) / (hi.toe - lo.toe);
jacking = -(hi.patch(3) - lo.patch(3)) / (hi.toe - lo.toe);   % mm per degree, + = the car rises

% Ackermann. The rack moves the left tie rod inboard as it moves the right one outboard;
% each corner's own frame has y outboard, so the left wheel sees -rack and the right +rack.
% A wheel steering left turns its spin axis toe-out on the left and toe-in on the right.
track = 2 * abs(car.front.wheelCentre(2));
ideal = track / car.wheelbase;
cotd_ = @(x) 1 ./ tand(x);
for i = 1:numel(app.steering.ackermann.rack)
  r = app.steering.ackermann.rack(i);
  pl = pd_upright(f, 'travel', app.steering.ackermann.travelInner(i), -r);
  pr = pd_upright(f, 'travel', app.steering.ackermann.travelOuter(i),  r);
  ml = read(f, pl, R0(1));  mr = read(f, pr, R0(1));
  left  = -(ml.toe - s(1).toe);                   % deg into a left turn
  right =   mr.toe - s(1).toe;
  inner(i) = left;  outer(i) = right;             % turning left: the left wheel is inside
  pct(i) = 100 * (cotd_(outer(i)) - cotd_(inner(i))) / ideal;
end

%% Against the app
ax = {'front', 'rear'};
for k = 1:2
  A = app.steering.(ax{k});
  pd_compare(['Caster, ' ax{k} ' [deg]'],             s(k).caster,        A.caster);
  pd_compare(['KPI, ' ax{k} ' [deg]'],                s(k).kpi,           A.kpi);
  pd_compare(['Scrub radius, ' ax{k} ' [mm]'],        s(k).scrub,         A.scrubRadius);
  pd_compare(['Mechanical trail, ' ax{k} ' [mm]'],    s(k).trail,         A.mechanicalTrail);
  pd_compare(['Kingpin offset, ' ax{k} ' [mm]'],      s(k).kingpinOffset, A.kingpinOffset);
  pd_compare(['Caster offset, ' ax{k} ' [mm]'],       s(k).casterOffset,  A.casterOffset);
end
pd_compare('Steering arm, front [mm]',                s(1).steeringArm,   app.steering.front.steeringArm);
pd_compare('Camber per steer [deg/deg]',              camberPerSteer,     app.steering.front.camberPerSteer);
pd_compare('Steer jacking [mm/deg]',                  jacking,            app.steering.front.steerJacking);
for i = 1:numel(app.steering.ackermann.rack)
  r = app.steering.ackermann.rack(i);
  pd_compare(sprintf('Inside wheel at %g mm rack [deg]', r),  inner(i), app.steering.ackermann.inner(i));
  pd_compare(sprintf('Outside wheel at %g mm rack [deg]', r), outer(i), app.steering.ackermann.outer(i));
  pd_compare(sprintf('Ackermann at %g mm rack [%%]', r),      pct(i),   app.steering.ackermann.percent(i));
end
pd_compare();

Download: steering_axis.m · example_suspension.m · pd_corner.m · pd_upright.m · pd_metrics.m · pd_compare.m. The scripts are MIT licensed.

Further reading

  • W. F. Milliken and D. L. Milliken, Race Car Vehicle Dynamics (SAE, 1995), ch. 19, on steering systems.
  • J. C. Dixon, Suspension Geometry and Computation (Wiley, 2009), on steering axis geometry and Ackermann.
  • T. D. Gillespie, Fundamentals of Vehicle Dynamics (SAE, 1992), ch. 8.
ChapterSteering axis and Ackermann
PartSuspension
Model as of0.338
Example carthe Formula Student single-car template