FixTheRobot Explore Robotics / Systems Engineering / Engineering Guides / Module 14

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.

  • Intermediate
  • Module 14: Motion Control & Actuator Integration
  • Written for ROS 2 Jazzy where ROS 2 is used
  • Sources checked 2026-11-06

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.

Overview
TestProcedureResult
Straight lineDrive a measured distance (for example 5 m) several times and compare with the odometryradius_true = radius_nominal × (true distance ÷ odometric distance)
In-place rotationRotate several full turns, using a mark or a reference heading, and compare with the odometric angleseparation_true = separation_nominal × (odometric angle ÷ true angle)
Left/right differenceStraight line drift of a long runAdjust left or right radius multiplier
Encoder scaleCount ticks per known wheel turnTicks 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 ─▶ odometry

7. Implementation

  1. Measure a straight line with a tape and mark a rotation reference.
  2. Run the tests several times in both directions.
  3. Compute the corrections (below).
  4. Enter them as the multipliers and repeat the tests.
  5. 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 odometry

Reading 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

  1. If straight runs are right and turns are wrong, check separation.
  2. If both are wrong, check the encoder scale and units.
  3. 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

Related on FixTheRobot