Engineering Guides · Module 14
Calibrating wheel radius, separation and encoders
Radius errors show up as distance errors; separation errors show up as heading errors. Measure each with its own test.
Assumptions: Numbers in the examples are illustrative and the code is executed by the site’s tests. Facts taken from a cited source are marked; other statements are general engineering knowledge and must be confirmed on the datasheet of the part you use.
1. Engineering problem
Wheel odometry is the foundation of local motion estimates. A wheel radius off by 2 % gives a 2 % error in every distance, and a wheel separation off by 3 % gives a 3 % error in every turn. The diff_drive controller exposes the right knobs; the numbers come from two simple tests.
2. When is this needed?
- Commissioning a differential-drive robot.
- When odometry over- or under-estimates distance or rotation.
- After changing wheels, tyres or load.
3. Selection and design decisions
From the diff_drive_controller parameter file (ros2_controllers, jazzy, read 2026-11-06): wheel_separation is the “shortest distance between the left and right wheels”, and “if this parameter is wrong, the robot will not behave correctly in curves”; wheel_radius is used for the transformation of linear velocity into wheel rotations, and “if this parameter is wrong the robot will move faster or slower than expected”. Correction factors are provided: wheel_separation_multiplier, left_wheel_radius_multiplier and right_wheel_radius_multiplier (all default 1.0). Both nominal values must be greater than zero.
| Test | Procedure | Result |
|---|---|---|
| Straight line | Drive a measured distance (for example 5 m) several times and compare with the odometry | radius_true = radius_nominal × (true distance ÷ odometric distance) |
| In-place rotation | Rotate several full turns, using a mark or a reference heading, and compare with the odometric angle | separation_true = separation_nominal × (odometric angle ÷ true angle) |
| Left/right difference | Straight line drift of a long run | Adjust left or right radius multiplier |
| Encoder scale | Count ticks per known wheel turn | Ticks per revolution (check the datasheet value) |
4. Advantages and disadvantages
- Longer tests average out slip and measurement error and take more time.
- Floor and tyre pressure change the effective radius: calibrate on the surface you use.
- Calibrating at one payload is wrong at another when tyres compress.
5. Requirements and constraints
- The reference distance and angle are measured better than the error you correct.
- Tests are repeated in both directions and averaged.
- The calibration is stored in the configuration with the date and the conditions.
6. Architecture
straight test ─▶ radius multiplier
spin test ─▶ separation multiplier ─▶ diff_drive_controller parameters ─▶ odometry7. Implementation
- Measure a straight line with a tape and mark a rotation reference.
- Run the tests several times in both directions.
- Compute the corrections (below).
- Enter them as the multipliers and repeat the tests.
- Re-test with load and on the working floor.
def calibrate(r_nom, L_nom, d_true, d_odom, spin_true_deg, spin_odom_deg):
r = r_nom * d_true / d_odom # distance travelled scales with the radius
L = L_nom * spin_odom_deg / spin_true_deg # odometric angle scales with 1 / separation
return r, L
r, L = calibrate(0.100, 0.400, 5.00, 5.10, 360.0, 372.0)
print(f"wheel radius {r * 1000:.1f} mm (multiplier {r / 0.100:.4f}), wheel separation {L * 1000:.1f} mm (multiplier {L / 0.400:.4f})")
ticks_per_rev = 4096
print(f"distance per tick: {2 * 3.141592653589793 * r / ticks_per_rev * 1e6:.1f} micrometres")
print(f"if the radius were not corrected, a 20 m run would end {20 * (5.10 / 5.00 - 1):.2f} m too far in the odometry")Printed (checked by the site’s tests):
wheel radius 98.0 mm (multiplier 0.9804), wheel separation 413.3 mm (multiplier 1.0333)
distance per tick: 150.4 micrometres
if the radius were not corrected, a 20 m run would end 0.40 m too far in the odometryReading it: driving 5.00 m while the odometry says 5.10 m means the radius is 2 % too large: the corrected radius is 98.0 mm (multiplier 0.9804). Spinning 360° while the odometry says 372° means the separation is 3.3 % too small: 413.3 mm (multiplier 1.0333). At 4096 ticks per revolution each tick is 150.4 µm of travel. Without the radius correction a 20 m run would end 0.40 m too far in the odometry. The measurements are illustrative.
8. Real examples
- Indoor AMR: radius and separation multipliers recalibrated after a tyre change; odometry error over 20 m reduced.
9. Failure scenarios
- Calibrating with a slipping wheel and building the slip into the radius.
- One calibration for both loaded and unloaded states.
- Using the wheel diameter where the radius is expected.
10. Troubleshooting
- If straight runs are right and turns are wrong, check separation.
- If both are wrong, check the encoder scale and units.
- If the error differs by direction, check left/right and backlash.
11. Validation
- The calculation prints the lines shown (executed by the site tests).
- After correction the odometry error over the test distances is below the requirement.
12. Engineering checklist
13. Further references
- diff_drive_controller parameters (ros2_controllers, jazzy branch): diff_drive_controller_parameter.yaml, read 2026-11-06.