Contents
Suspension
Wishbones and struts
How the links carry a wheel through its travel, and what that does to its camber, its toe and the spring it works.
A wheel's upright is held by links. On a double wishbone there are five: the two legs of each wishbone and the tie rod, which is a toe link on a rear axle. As the wheel rises, each link swings about its chassis end and the upright goes with them. It tilts, it steers a little, and its contact patch slides sideways. The Kinematics tool computes all of that from the hardpoints, and this page shows how.
The upright through its travel
A link keeps its length, so its outer end stays on a sphere about its chassis end. Five such spheres leave the upright one way to move, and the wheel centre's height picks the position along it. The app solves the six conditions together, by Newton's method from the static ride:
- link 's chassis and upright ends, as drawn
- the upright's turn about its wheel centre , and its shift
- link 's length, from the hardpoints
- the wheel travel: the wheel centre's rise from the static ride, positive in bump
The turn carries the wheel's spin axis with it, and the alignment is read off that axis: camber is its tilt in front view, toe its turn in plan (Axes, signs and units gives the signs). The contact patch is a loaded radius below the wheel centre, in the wheel's plane.
Every number below is the change of one of these with : a gain. The app takes each one by solving the pose half a millimetre above and below the static ride and differencing the two.
Camber gain
Seen from the front, the upright turns about its instant centre, the point where the two wishbones' lines cross (Roll and pitch centres). A millimetre of rise at the patch, a swing arm's length from that point, turns the wheel by one swing-arm length's worth of radians. With the instant centre inboard, the top of the wheel tips in:
- camber, negative with the top of the wheel in
- the front-view swing arm: the patch's distance from the instant centre
On the template the links give β0.01165 Β°/mm at the front, within a part in a thousand of the rule. The arms are close to parallel, so the swing arm is long, 4921 mm, and the gain small: over the Β±40 mm of the Analysis tab's ride sweep the front camber runs from β0.67Β° in droop to β1.60Β° in bump.
A shorter swing arm gains camber faster. It also moves the instant centre and with it the roll centre, which is why the two are designed together.
Bump steer
The tie rod is a sixth link on the same upright, and it steers the wheel unless its outer end moves as the upright would carry it. In front view the rule for a wishbone corner is that the tie rod's line passes through the wheel's instant centre, and its inner end lies on the line through the wishbones' inner pivots. Off that line the rod pushes or pulls the steering arm as the wheel rises, and the wheel toes in or out. The toe change per millimetre is the bump steer.
The template's front wheel toes out in bump, β0.0133 Β°/mm: β0.57Β° at +40 mm, 0.50Β° at β40. On the outside front wheel of a corner, which the body rolls onto, toe-out steers it away from the turn: roll understeer. The rear's toe link sits almost on the line, and its bump steer is 0.00012 Β°/mm.
Track scrub
The patch also slides sideways as the wheel rises, 0.0053 mm per millimetre at the front and 0.0044 at the rear, outboard in bump. Over a bump the tyre is pushed across the road for nothing, and it has to make a side force to do it. A roll centre above the road always comes with some: the patch moves square to its force line, and that line is not horizontal.
The motion ratio
The spring is driven through the linkage, so it does not see the wheel's travel. The motion ratio is how far it moves per millimetre the wheel does. The template's axles are decoupled. A pushrod from each lower wishbone turns a rocker, and one heave element spans the two rockers: in heave both rockers turn alike and the element shortens; in roll they turn opposite ways and it barely moves, which leaves roll to the roll element (Ride and roll rates).
With both wheels at the same travel the two pickups are mirror images, so the element's length is twice its pickup's distance from the centre-line. Its ratio is the change in that length per millimetre of travel of both wheels, 1.211 at the front and 1.193 at the rear. Its rate reaches each wheel by virtual work: a force in the element moving does the work of two wheels each moving , so
- the heave element's spring rate, at the element
- the element's travel per millimetre of travel of both wheels
- its rate at each wheel, halved because one element carries two
The ratio is itself a gain and changes through the stroke. The app takes it across a sweep's two samples 4 mm either side of the static ride. A ratio that grows in bump hands more of the spring's force to the wheel the further it goes, and the wheel rate rises above equation (3); one that falls, as the template's does, softens it. Kinematics and compliance works out by how much.
Struts
A McPherson strut keeps the lower wishbone and replaces the upper one by the damper itself: its body is clamped to the upright and its rod slides through a top mount on the chassis. The upright may slide along the strut and turn about it, so the top mount is a line where an upper ball joint was a sphere: two conditions where the wishbone gave two. The steering axis runs from the lower ball joint to the top mount. Its instant centre is where the lower wishbone's line meets the line through the top mount square to the strut, and it moves out fast as the wheel rises, so a strut's camber gain fades in bump.
The app solves a strut the same way, and every readout on this page is computed for it. The template has none.
Axles given by their curves
A team with camber, toe and motion-ratio curves from a rig, a supplier or another program can give an axle by those instead of by hardpoints. The Kinematics tool's source switch, Hardpoints | Curves, fills the curves from the current hardpoints when it is first turned on, so nothing changes at the switch. A curve set has no linkage to derive a track, a roll-centre height or a spring rate from, so it states them, and it has no steering linkage at all.
What the model assumes
- The links are rigid and the joints are points. How far they give under load is on Kinematics and compliance.
- The rack is held still: bump steer is the toe change with the steering wheel held.
- The heave element's ratio is taken with both wheels at one travel; in roll the element sees almost nothing.
- The right-hand corner is the left one's mirror image.
In the app
Kinematics, in the readout rail: "At the wheel" gives camber and toe; "Rate of change here" gives camber gain, bump steer and track scrub; "Elements" gives the heave element ratio, and "Rates" the heave element at the wheel. Each moves with the state.
Kinematics βΊ Analysis βΊ Travel draws camber, toe and their gains through the travel; Springs & tyre follows the spring to the road.
Check it yourself
The script solves the upright at the static ride, half a millimetre either side, and at the travels the Analysis tab's sweep landed on, as the app does; it finds the rocker's turn for each and the heave element's length from it.
>> wishbones Quantity This script PaceDynamics Diff ----------------------------------------------------------------------------- Static camber, front [deg] -1 -1 4.4e-14% Static camber, rear [deg] -1.5 -1.5 2.1e-13% Camber gain, front [deg/mm] -0.0116519 -0.0116519 1.4e-08% Camber gain, rear [deg/mm] -0.0104213 -0.0104213 2.6e-08% Bump steer, front [deg/mm] -0.0132504 -0.0132504 1.1e-08% Bump steer, rear [deg/mm] 0.000119853 0.000119853 2e-07% Track scrub, front [mm/mm] 0.00532844 0.00532844 1.2e-07% Track scrub, rear [mm/mm] 0.00442282 0.00442282 1.9e-07% Camber at -40 mm, front [deg] -0.665389 -0.665389 1.8e-13% Toe at -40 mm, front [deg] 0.496239 0.496239 7.3e-12% Camber at -20 mm, front [deg] -0.799906 -0.799906 4.2e-12% Toe at -20 mm, front [deg] 0.256315 0.256315 1.1e-11% Camber at +20 mm, front [deg] -1.26665 -1.26665 2.4e-12% Toe at +20 mm, front [deg] -0.274219 -0.274219 2.2e-11% Camber at +40 mm, front [deg] -1.60287 -1.60287 1.1e-12% Toe at +40 mm, front [deg] -0.567943 -0.567943 8e-12% Heave motion ratio, front [-] 1.21096 1.21096 5.9e-13% Heave motion ratio, rear [-] 1.19288 1.19288 6e-13% Heave rate at wheel, front [N/mm] 34.929 34.929 1.2e-12% Heave rate at wheel, rear [N/mm] 38.7348 38.7348 1.2e-12% Rule of thumb, front: -180/pi / FVSA = -0.011643 deg/mm against -0.011652 from the links. All 20 quantities agree with PaceDynamics (largest difference 2e-07 %).
The script
%% Wishbones and struts: how the links steer and tilt a wheel as it rises % % Companion to the documentation page "Wishbones and struts". 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: % % >> wishbones % % What this computes, for the front-left and rear-left wheels: % % 1. The upright's pose at a given wheel travel (pd_upright): five links of fixed length, % and the wheel centre's height. Camber and toe are read off the spin axis the pose % turns; the contact patch is a loaded radius below the wheel centre (pd_metrics). % 2. The gains at the static ride: camber, toe and the patch's sideways position at % 0.5 mm above and below it, differenced. That is the app's step, so the gains agree % with its readouts to their last digits. % 3. The ride sweep the Analysis tab draws, at the travels its samples landed on. % 4. The heave element. The pushrod's outer end turns with the lower wishbone; the rocker % turns until the pushrod is its own length again; the element runs between the two % rockers, so in heave it is twice its pickup's distance from the centreline (pd_heave). % Its motion ratio is the change in that length per millimetre of wheel travel, taken % across the two travels the app takes it between, and its rate at the wheel is % k_wheel = k_element * MR^2 / 2, % halved because one element carries both wheels. % % 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)}; names = {'front', 'rear'}; step = 0.5; % mm, the app's half-step for ax = 1:2 a = axles{ax}; at = @(t) pd_upright(a, 'travel', t); read = @(p) pd_metrics(p.at(a.ubj), p.at(a.lbj), p.at(a.C), p.n, p.at(a.tieOuter), R0(ax)); m0 = read(at(0)); lo = read(at(-step)); hi = read(at(step)); w.(names{ax}).camber = m0.camber; w.(names{ax}).toe = m0.toe; w.(names{ax}).camberGain = (hi.camber - lo.camber) / (2 * step); w.(names{ax}).bumpSteer = (hi.toe - lo.toe) / (2 * step); w.(names{ax}).scrubRate = (hi.patch(2) - lo.patch(2)) / (2 * step); % The heave element's length, both rockers turned alike. h = app.wishbones.heave.(names{ax}); w.(names{ax}).ratio = (pd_heave(a, h.chord(1)) - pd_heave(a, h.chord(2))) / (h.chord(2) - h.chord(1)); w.(names{ax}).wheelRate = car.(names{ax}).heaveRate * w.(names{ax}).ratio^2 / 2; end % The ride sweep, front left. a = axles{1}; for i = 1:numel(app.wishbones.sweep.travel) p = pd_upright(a, 'travel', app.wishbones.sweep.travel(i)); m = pd_metrics(p.at(a.ubj), p.at(a.lbj), p.at(a.C), p.n, p.at(a.tieOuter), R0(1)); sweep.camber(i) = m.camber; sweep.toe(i) = m.toe; end %% Against the app pd_compare('Static camber, front [deg]', w.front.camber, app.wishbones.front.camber); pd_compare('Static camber, rear [deg]', w.rear.camber, app.wishbones.rear.camber); pd_compare('Camber gain, front [deg/mm]', w.front.camberGain, app.wishbones.front.camberGain); pd_compare('Camber gain, rear [deg/mm]', w.rear.camberGain, app.wishbones.rear.camberGain); pd_compare('Bump steer, front [deg/mm]', w.front.bumpSteer, app.wishbones.front.bumpSteer); pd_compare('Bump steer, rear [deg/mm]', w.rear.bumpSteer, app.wishbones.rear.bumpSteer); pd_compare('Track scrub, front [mm/mm]', w.front.scrubRate, app.wishbones.front.trackScrubRate); pd_compare('Track scrub, rear [mm/mm]', w.rear.scrubRate, app.wishbones.rear.trackScrubRate); for i = 1:numel(app.wishbones.sweep.travel) pd_compare(sprintf('Camber at %+.0f mm, front [deg]', app.wishbones.sweep.travel(i)), sweep.camber(i), app.wishbones.sweep.camber(i)); pd_compare(sprintf('Toe at %+.0f mm, front [deg]', app.wishbones.sweep.travel(i)), sweep.toe(i), app.wishbones.sweep.toe(i)); end pd_compare('Heave motion ratio, front [-]', w.front.ratio, app.wishbones.heave.front.ratio); pd_compare('Heave motion ratio, rear [-]', w.rear.ratio, app.wishbones.heave.rear.ratio); pd_compare('Heave rate at wheel, front [N/mm]', w.front.wheelRate, app.wishbones.heave.front.wheelRate); pd_compare('Heave rate at wheel, rear [N/mm]', w.rear.wheelRate, app.wishbones.heave.rear.wheelRate); % The rule of thumb the page gives: camber gain is about one radian over the swing arm. fprintf('\n Rule of thumb, front: -180/pi / FVSA = %.6f deg/mm against %.6f from the links.\n', ... -180 / pi / app.front.fvsa, w.front.camberGain); pd_compare();
Download: wishbones.m Β· example_suspension.m Β· pd_corner.m Β· pd_upright.m Β· pd_metrics.m Β· pd_heave.m Β· pd_rocker.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. 17, on camber gain, bump steer and swing arms.
- J. C. Dixon, Suspension Geometry and Computation (Wiley, 2009), on solving a linkage's position and on motion ratios.
- J. Reimpell, H. Stoll and J. W. Betzler, The Automotive Chassis: Engineering Principles (Butterworth-Heinemann, 2001), on struts.