How Eigenride works

Eigenride compares bikes by how they are likely to behave for you, not just by their geometry numbers. This page explains the model behind every number on the compare page: what it captures, what it assumes, where each default comes from and where it stops being useful.

The short version: we turn a published geometry chart, a typical build and your body measurements into the 25 parameters of the linearised Carvallo-Whipple bicycle model (Meijaard et al. 2007), then study that model's hands-free stability and steady-turn steering. Everything that is estimated rather than measured is labelled as an estimate, and we show how much the headline results move when the estimates are wrong.

Every default number quoted below lives in one file, engine/src/bikedyn/constants.json. Both engines (the Python reference and the TypeScript engine that runs in your browser) read that same file, so this page, the reference engine and the site cannot drift apart. If a value here and a value in constants.json ever disagree, constants.json is right and this page is out of date.

1. The model

The Whipple bicycle

The Carvallo-Whipple model treats a bicycle as four rigid bodies joined by two hinges:

Body What it contains in Eigenride
R, rear wheel Rim, tyre, sealant or tube, spokes, rear hub, rotor
B, rear frame Frame, seatpost, saddle, crankset and pedals, chain, cassette, rear derailleur, rear brake, and the whole rider
H, front frame Fork, headset, stem, bar, levers or brakes and shifters, front brake, any front load
F, front wheel As the rear wheel, with the front hub

The wheels are knife-edged discs that roll without slipping on flat, level ground. The rider is rigidly attached to the rear frame and does not touch the bars: this is a hands-free model. Linearising about straight-ahead, upright running at constant speed v gives two coupled equations in lean angle phi and steer angle delta:

M q'' + v C1 q' + (g K0 + v^2 K2) q = f,     q = [phi, delta]

M, C1, K0 and K2 are 2 by 2 matrices built from the 25 benchmark parameters (wheelbase w, trail c, steer axis tilt lambda, gravity g, and the mass, centre of mass and inertia of each body). Eigenride uses the formulas published by Meijaard, Papadopoulos, Ruina and Schwab (2007) exactly as written. For their benchmark bicycle both engines reproduce the published matrices to 14 digits and give a weave speed of 4.2923825 m/s and a capsize speed of 6.0242620 m/s, within 1e-9 m/s of the same speeds computed independently in 40-digit arithmetic.

What we compute from it

Eigenvalues and modes. For each speed we compute the four eigenvalues of the state matrix. A negative real part means that motion dies away; a positive one means it grows. The modes are named from the eigenvalues at each speed:

Charts colour modes consistently across speed by following each eigenvalue from one speed to the next (the matching that moves them the least), not by re-sorting at every speed.

Stability window. The speeds at which every mode is stable: from the weave speed up to the capsize speed. We sweep 0 to 15 m/s (0 to 54 km/h) in 0.05 m/s steps and then refine each crossing to about 1e-12 m/s with Brent's method. The capsize speed is cross-checked with the closed-form speed at which det(g K0 + v^2 K2) = 0.

Mode detail at evaluation speeds. Weave frequency (Hz) and damping ratio, capsize time constant (1 / real part, shown only when capsize is unstable) and castering time constant. Default evaluation speeds are 15, 30 and 45 km/h for road bikes, 12, 25 and 40 km/h for gravel bikes and 8, 15 and 30 km/h for mountain bikes. When bikes of different families are compared, the first bike's speeds are used for all of them, so that everything is judged at the same speeds. The "mid speed" is the middle evaluation speed.

Steady-turn steering. In a steady turn at small lean with no lean torque from the rider, the model gives two ratios:

2. From a geometry chart to model parameters

Frame placement

We place the frame in a side view with the bottom bracket (BB) at the origin, x forward and z up, using the numbers manufacturers publish:

Changes to the build and pitch correction

Build changes are applied to the frame first, then the whole bike is rotated about the BB until the ground line touches both tyres again ("pitch correction"). All reported angles, trail, wheelbase, front and rear centre and BB height come from the rotated points. A positive pitch change means nose up (slacker).

Examples the tests check: a 73 degree head angle, 45 mm offset and 339 mm wheel radius give 56.6 mm of trail; fitting a 27.5 inch rear wheel to a 29er of about 1250 mm wheelbase slackens the head angle by about 1 degree (0.8 to 1.1) and lowers the BB by about 12 mm (10 to 14).

Static geometry metrics

Metric Definition
Trail (rF sin(lambda) - offset) / cos(lambda), lambda = 90 degrees - head angle, after pitch correction
Mechanical trail trail x cos(lambda) (perpendicular distance from the contact patch to the steer axis)
Wheel flop trail x sin(head angle) x cos(head angle)
Wheelbase, front centre, rear centre horizontal axle-to-axle, BB-to-front-axle and BB-to-rear-axle distances
BB height ground to BB centre with the fitted tyres
Front load share the share of the total weight (bike plus rider) carried by the front wheel
Seat angle at your saddle height angle from horizontal of the line from the BB to your saddle point
Saddle-to-bar reach and drop horizontal and vertical distance from your saddle point to the bar clamp centre
Pedal strike lean lean angle at which the lowest pedal touches flat ground (cranks vertical)
Toe overlap distance from your shoe toe (forward crank horizontal) to the front tyre's outline in side view; negative means overlap

Pedal strike assumes a pedal edge 55 mm outboard of the crank and 10 mm below the spindle, and a half Q-factor of 75 mm (road, gravel) or 85 mm (mountain). It ignores the tyre rolling onto its shoulder, so real clearance is a little smaller. Toe overlap needs your shoe size: foot length = 6.67 x EU size - 15 mm, ball of the foot over the spindle (72% of foot length from the heel), a 10 mm toe box, and the toe 20 mm above the spindle.

Data checks

When a chart publishes wheelbase, front centre, trail or both BB drop and BB height, we compare them with what the other numbers imply and flag differences of more than 5 mm (wheelbase, front centre, BB height) or 3 mm (trail). We also flag values outside plausible ranges (for example head angle 60 to 76 degrees, chainstay 370 to 480 mm; the full list is validation.ranges) and missing fields the dynamics need (stack, reach, head angle, fork offset, chainstay).

3. The rider

You are 85 to 90% of the total mass, so where your mass sits matters more than most frame numbers. Eigenride builds you from 16 rigid segments (head, upper, middle and lower trunk, and left and right upper arm, forearm, hand, thigh, shank and foot) using the segment masses, centre of mass positions and radii of gyration of de Leva (1996). The rider panel's body model picks the table: male (the default; reference stature 1741 mm) or female (reference stature 1735 mm). Segment lengths scale with your height; arm segments are further scaled to your arm length. Leg segments are scaled to your inseam in the same way for both tables: thigh plus shank is the same multiple of the inseam (1.046, the male table's at the default inseam), and the female table only changes how that length splits between thigh and shank. Segment masses scale with your mass and always add up to it exactly.

Compared with the male table, the female one puts more of the mass in the thighs, hips and lower trunk and less in the upper trunk, arms and head, with a shorter upper trunk, forearm, hand and foot. For the same height, mass and bike this moves the rider's centre of mass a little forward and changes the trunk and arm inertia; the effect on the stable speed range is small (about a tenth of a km/h for a typical road bike).

The female numbers are de Leva's Table 4, female column, cross-checked against two independent reproductions (the Visual3D documentation of the table and the biobuddy biomechanics library). The model also needs the heights of two landmarks, the suprasternale (top of the breastbone) and the shoulder joint centres, which place the neck and the shoulders on the trunk. For both tables they come from de Leva's own Tables 2 and 3: suprasternale 0.8079 x height and shoulder joints 0.7985 x height for men, 0.8092 and 0.7911 for women. These reproduce the paper's hip-to-suprasternale and hip-to-shoulder trunk lengths for each sex. (Before engine 0.4.0 the male ratios were 0.8363 and 0.7982, of unrecorded origin; they gave a hip-to-shoulder trunk about 10% shorter than de Leva's and a longer neck gap.)

Defaults when you leave a measurement blank

Input Default
Inseam 0.47 x height
Arm length (shoulder joint to wrist) de Leva upper arm plus forearm: 0.3163 x height (male), 0.3109 x height (female)
Shoulder width 0.226 x height
Saddle height (BB centre to saddle top, along the seat post) 0.883 x inseam, lowered by any crank length above 170 mm
Saddle setback on the frame's seat line at your saddle height
Hand position hoods for drop bars, grips for flat bars
Crank length the frame's stock crank, else 172.5 mm (road, gravel), 175 mm (XC), 170 mm (trail, enduro), 165 mm (DH)

Saddle setback here means the horizontal distance from the BB to the point where saddle height is measured (roughly the middle of the saddle), not to the saddle nose. All defaults are starting points for a generic adult and are listed as defaults on the page.

Only the arm length default depends on the body model, because it comes straight from the de Leva tables. The inseam, shoulder width and saddle height ratios, and the hip and shoulder spacing below, are the same for both: we have no source for sex-specific values that fits this model, so if yours differ, enter your own measurements.

Pose

  1. Pelvis on the saddle: the hip joints sit 0.040 x height above and 0.020 x height ahead of the saddle point, 0.049 x height either side of the centreline.
  2. Feet on the pedals, cranks horizontal (right pedal forward), ball of the foot over the spindle, a 15 mm sole and pedal stack. Knees come from two-link inverse kinematics.
  3. Hands on the bars. Hand contact relative to the bar clamp centre (forward, up): hoods (75, 15) mm, drops (35, -115) mm, tops (0, 0) mm, grips (-40, 25) mm. Hands are spaced at the bar width (hoods, drops), 120 mm either side of the stem (tops) or 70 mm in from the bar ends (grips). Default bar widths: 400 mm (road race), 420 mm (endurance), 440 mm (gravel), 760 to 800 mm (mountain).
  4. Trunk angle is solved so that your arms reach the hands with a 15 degree elbow bend. If the bars are out of reach the arms are modelled straighter; if they are unusually close, the trunk is set to 80 degrees. Both cases are flagged.
  5. Head in line with the trunk, raised to at least 65 degrees from horizontal so the eyes look forward.

Each segment's inertia is built about its own axes, rotated into the bike's axes and added to the rear frame with the parallel axis theorem. The model is symmetric left to right, so the small products of inertia from the horizontal cranks are dropped.

4. Component masses

Component masses are category presets (components.by_category and wheels.by_category in constants.json), always listed as estimates. You can enter your own frame, fork and wheel masses; entered values are not perturbed in the uncertainty runs.

Category Frame Fork Wheel (front / rear, 700c or 29)
Road race 0.95 kg 0.40 kg about 1.05 / 1.2 kg
Road endurance 1.10 kg 0.45 kg about 1.2 / 1.35 kg
Gravel 1.20 kg 0.50 kg about 1.4 / 1.55 kg
XC 1.90 kg 1.50 kg about 1.6 / 1.75 kg
Trail 2.90 kg 2.00 kg about 2.1 / 2.25 kg
Enduro 3.30 kg 2.40 kg about 2.4 / 2.6 kg
DH 4.20 kg 2.90 kg about 2.7 / 2.9 kg

5. Uncertainty, sensitivity and the summary

Uncertainty ranges

Masses and the rider's exact position are estimates, so every analysis is repeated at the four corners of: all estimated component masses and inertias x 0.8 or x 1.2, and the whole rider moved 30 mm forward or back. Each headline metric (weave and capsize speed, window width, front load share, and steer torque and steer-to-lean ratio at the mid speed) is shown with the range over the nominal run and these four.

Speeds are only found inside the analysed speed range (0 to 54 km/h by default). When a run's capsize speed lies above the top of that range, it counts as the top of the range and the range is marked open-ended there ("beyond"); likewise a weave speed below the bottom of the range. A stable window that runs into either end of the range has a width that is only a lower bound, so its range is also marked open-ended. A run with no stable window at all counts as a width of zero. Open-ended ranges are never narrower than what the runs show; the true spread can be wider.

What moves this bike

For each bike we change one adjustable input at a time and report the change in weave and capsize speed, trail, front load share and mid-speed steer torque per step: +1 degree head angle, +5 mm fork offset, +10 mm stem, +10 mm spacers, +2 mm tyre width (front and rear) and +1 kg front load. We use central differences (half the difference between one step up and one step down), except for front load when there is none to remove, where we use one step up against the nominal. The head angle is changed with an angle-set, and the frame's pitch takes back part of each step (see above: a 1 degree angle-set moves the head angle on the ground by only about 0.75 degrees), so those effects are divided by the head angle change that actually results. The row is per degree of the head angle we report.

Plain-language summary

The summary is generated by fixed rules, never by a language model. Each bike is compared with Bike A. A difference is reported only if it is at least a threshold (trail 3 mm, weave or capsize speed 1 km/h, window width 1.5 km/h, front load share 2 percentage points, steer torque 15% or, when percentages make no sense, 0.3 N m per g) and larger than the uncertainty range of either bike. Otherwise the bikes are called similar. At most three differences are listed, in this order: trail, weave speed, window width, capsize speed, steer torque, front load share.

If only one of the two bikes has a hands-free stable speed range, the summary says so first and never calls the bikes similar. A speed beyond the analysed range is a bound rather than a value (a capsize speed "beyond 54 km/h", a window width that is "at least" its analysed part), so a difference that involves one is reported as "at least" that much, and only when the bound makes its direction certain; otherwise that metric is left out of the comparison.

6. Limitations

Be clear about what the numbers are and are not.

7. How the engines are kept honest

The Python reference engine (engine/, package bikedyn) holds the verbatim benchmark formulas and golden tests against Meijaard et al. (2007). It also generates a conformance fixture with full outputs for over 100 cases: the benchmark bicycle, road, endurance, gravel, low-trail 650b, XC, trail, enduro, mullet and DH frames, every seed frame in the curated dataset, and varied riders and what-ifs. The TypeScript engine that runs in your browser must reproduce every number in that fixture to a relative or absolute tolerance of 1e-6, and every label, warning and summary sentence exactly, or the build fails. Rules that could otherwise differ between the two engines are pinned down in code and tests: eigenvalues are put in a canonical order and tracked by a fixed matching rule, roots are found with the same Brent algorithm, speed grids are computed the same way, and numbers in text are rounded half away from zero.

Each result carries an engine_version and a param_hash: a SHA-256 hash of the normalised inputs plus the engine version, so identical inputs give identical results and cached results are never reused across engine changes.

References

Benchmark check

The benchmark bicycle from Meijaard et al. (2007), run through this site's engine in your browser and compared with the same speeds computed from the paper's matrices in 40-digit arithmetic.

Benchmark bicycleReference (m/s)This browser (m/s)Difference
Weave speed4.2923825…
Capsize speed6.0242620…