Differential drive kinematics explained

How two wheel speeds become a forward speed and a turn rate, where the instantaneous centre of curvature sits, and why a two wheeled robot has to turn before it can move across. Three demos work the kinematics out in the program, drive the arc on a real simulated robot and compare it with a sideways move only an omni robot can make.

Guidefree, runs in your browser

A differential drive is the simplest way to make a robot that can go anywhere on a floor: one driven wheel on the left, one on the right, and a castor or a ball to stop it tipping over. There is no steering. The robot turns by driving one wheel faster than the other, which is where the name comes from. Robot vacuums, most first competition robots, tracked diggers and tanks all work this way.

Kinematics is the arithmetic that turns two wheel speeds into a path across the floor, and back again. It is three lines long, and once you have it you can drive any shape you like. On this page a small robot on a 2 metre mat drives the motions those three lines work out, and each demo below is a real program you can change and run.

Two wheel speeds, two numbers

Call the left wheel's speed left and the right wheel's speed right, both in centimetres a second at the rim, and the distance between the wheels W. Then:

forward speed   v = (left + right) / 2
turn rate       w = (left - right) / W        radians a second, clockwise

That is the whole of forward kinematics for a differential drive. The forward speed is the average of the two wheels, which makes sense: if both wheels roll at 10 cm/s the robot goes at 10 cm/s. The turn rate is the difference divided by the wheelbase, which also makes sense: one wheel getting ahead of the other is exactly what swings the robot round, and wheels far apart need a bigger difference to swing it by the same amount.

Five cases cover everything a differential drive can do:

left right v w what happens
12 12 12 0 straight ahead
12 6 9 0.6 rad/s a curve to the right
12 0 6 1.2 rad/s pivots about the stopped right wheel
12 -12 0 2.4 rad/s spins on the spot
-12 -6 -9 -0.6 rad/s the same curve, driven backwards
Five pairs of wheel speeds and the path each one drivesstraightleft 12, right 12v = 12 cm/sw = 0.0 deg/scurve rightleft 12, right 6v = 9 cm/sw = 34.4 deg/spivotleft 12, right 0v = 6 cm/sw = 68.8 deg/sspinleft 12, right -12v = 0 cm/sw = 137.5 deg/sbackwardsleft -12, right -6v = -9 cm/sw = -34.4 deg/s
The same left wheel at 12 cm/s with a different right wheel each time, drawn over 1.4 seconds at the same scale. The faint robot is where it started and the red dot is the ICC. The turn rate is the difference between the wheels divided by the 10 cm between them, so 12 and 6 give 34.4 degrees a second, 12 and 0 give 68.8, and 12 and -12 give 137.5.

Going the other way, from the motion you want to the wheel speeds you need, is inverse kinematics:

left  = v + w × W / 2
right = v - w × W / 2

This is the pair a program actually uses. You decide how fast the robot should go and how fast it should turn, and these two lines tell the motors what to do.

Working the two wheel speeds out

The BugBot in the simulator is not a differential drive: it is holonomic, and the last demo on this page shows what that buys it. But it takes a forward speed and a turn rate, the same two numbers a differential drive produces, so the kinematics can be worked out in the program and then driven on this robot.

Its commands are percentages rather than speeds, so the program turns one into the other with the robot's top speeds: 20 cm/s forward and 120 degrees a second turning at full command.

left 12 and right 6 come to 9 cm/s forward and 34.4 degrees a second, and the robot goes right round in 11 seconds and comes back within 6 cm of where it started.
The program
from bugbot import *
import math
connect()

# change these three numbers and press Run
W = 10.0          # the wheels are 10 cm apart
LEFT = 12.0       # cm/s at the left wheel's rim
RIGHT = 6.0       # cm/s at the right wheel's rim

V_MAX, W_MAX = 20.0, 120.0    # this robot at full command

# forward kinematics: two wheel speeds to a forward speed and a turn rate
v = (LEFT + RIGHT) / 2
w = math.degrees((LEFT - RIGHT) / W)
print("forward", round(v, 2), "cm/s   turn", round(w, 1), "deg/s")

drive(100 * v / V_MAX, 0, 100 * w / W_MAX)
path = []
for tick in range(110):            # 11 seconds
    path.append(position())
    if tick % 3 == 0:
        draw("path", path, "blue", "line")
    plot("left cm/s", LEFT)
    plot("right cm/s", RIGHT)
    plot("turn rate deg/s", imu()[1])
    wait(0.1)
stop()
print("ended at", position(), " facing", round(heading(), 1))
Put this demo on your own site

Paste it into a school website, Moodle, Google Sites or a blog. More options on the embed page.

The two flat lines on the chart are the wheel speeds you chose. The third is the turn rate the robot's gyro actually measures, which climbs for the first quarter of a second while the drive gets going and then sits near the 34.4 degrees a second the arithmetic asked for.

Try some of the rows from the table. RIGHT = 12 drives straight. RIGHT = 0 pivots about the stopped wheel. RIGHT = -12 spins on the spot, and the path drawn on the mat shrinks to a dot. LEFT = -12 with RIGHT = -6 drives the same circle backwards, the other way round.

Try W = 20, a robot twice as wide, with the wheel speeds left alone. The forward speed does not change, but the turn rate halves and the circle comes out twice as big. A wide robot is harder to turn, which is why a long tracked vehicle needs its tracks to fight each other to spin.

The ICC: every motion is a circle

Whenever the two wheels are running at different but steady speeds, the robot goes round a circle. The centre of that circle is called the instantaneous centre of curvature, or ICC. It sits out to one side, on the line through both wheels, and its distance from the middle of the robot is:

R = v / w

with w in radians a second. The word instantaneous is there because the moment you change a wheel speed, the ICC jumps somewhere else. A path is a string of little arcs with the ICC moving between them, and a straight line is the special case where the wheels match, w is zero and the ICC is infinitely far away.

A differential drive turning: the two wheel speeds, the wheelbase, and the ICC it swings roundleft 12 cm/sright 6 cm/sICCW = 10 cmR = v / w = 15 cmforward kinematicsv = (12 + 6) / 2 = 9 cm/sw = (12 - 6) / 10 = 0.60 rad/s = 34.4 degrees a secondso R = v / w = 15 cmthe left wheel rolls round a 20 cm circleand the right one round a 10 cm circle20 / 10 = 2, and 12 / 6 = 2 too
With the left wheel at 12 cm/s and the right at 6, the middle of the robot goes at 9 cm/s and the whole thing swings round the ICC, 15 cm to its right. The outer wheel has to cover a 20 cm circle while the inner one covers a 10 cm circle, and 20 divided by 10 is 2, which is exactly the ratio of the two wheel speeds.

The ICC is not a thing the robot commands. It is where the motion says the robot is turning about, so the honest way to find it is to measure. This program drives the same arc, waits a second for it to settle, reads the real forward speed off the optical flow sensor and the real turn rate off the gyro, works out R from those two, and marks the ICC on the mat. Then it drives round and plots how far the robot is from that mark.

The arithmetic asks for a 15 cm circle and the robot really drives a 13.1 cm one, and once that is measured the robot stays between 11.9 and 13.3 cm from the marked ICC for the whole circle.
The program
from bugbot import *
import math
connect()

# change these three numbers and press Run
W = 10.0
LEFT = 12.0
RIGHT = 6.0

V_MAX, W_MAX = 20.0, 120.0

v = (LEFT + RIGHT) / 2
w = math.degrees((LEFT - RIGHT) / W)
print("radius asked for", round(v / math.radians(w), 1), "cm")

drive(100 * v / V_MAX, 0, 100 * w / W_MAX)
wait(1.0)                      # let the drive get up to speed

# measure what the robot is really doing, 20 readings averaged
mv = mw = 0.0
for i in range(20):
    mv = mv + flow()[1] / 20         # forward speed, cm/s
    mw = mw + imu()[1] / 20          # turn rate, deg/s
    wait(0.05)
R = mv / math.radians(mw)
print("measured", round(mv, 1), "cm/s and", round(mw, 1), "deg/s")
print("radius really driven", round(R, 1), "cm")

# the ICC is R to the right of the robot, square to the way it faces
th = math.radians(heading())
x, y = position()
icc = (x + R * math.cos(th), y - R * math.sin(th))
draw("ICC", [icc], "red", "dots", 8)

path = []
for tick in range(100):            # 10 seconds
    p = position()
    path.append(p)
    if tick % 3 == 0:
        draw("path", path, "blue", "line")
    plot("to the ICC cm", math.hypot(p[0] - icc[0], p[1] - icc[1]))
    plot("radius R cm", R)
    wait(0.1)
stop()
Put this demo on your own site

Paste it into a school website, Moodle, Google Sites or a blog. More options on the embed page.

The two lines on the chart lie on top of each other, within about a centimetre, all the way round. That is what going round a circle means: the distance to the centre does not change.

The gap between the 15 cm the arithmetic asked for and the 13.1 cm the robot drove is not a mistake in the kinematics. The kinematics is exact. The gap is in the two numbers used to turn speeds into percentages: this robot's real top speeds are not exactly 20 cm/s and 120 degrees a second, because no two motors are the same. Measuring them is what lesson Measuring your robot is for, and until you have it every path a program plans comes out slightly the wrong size.

You can also see why R = v / w puts the ICC in sensible places. With LEFT = 12 and RIGHT = 0 it works out at 5 cm, which is exactly the stopped right wheel: the robot swings round it. With RIGHT = -12 it is 0, the middle of the robot, and the robot spins on the spot. With the wheels equal it is infinite, and Python will tell you so by refusing to divide by zero.

Why a differential drive cannot slide sideways

A wheel rolls along the way it points, and it will not slide along its own axle. That is the whole reason. Both wheels on a differential drive point forwards, so the robot's sideways speed has to be zero at every instant. There is no wheel speed pair that gives it one: look at the two forward kinematics lines again and there is no sideways term in them to solve for.

This makes a differential drive non-holonomic: it has three things it might want to control on a floor, across, along and heading, and only two it can set. It can still reach any pose in the end. It just cannot go straight there. To end up 25 cm to its right, facing the same way, it has to turn, drive and turn back, which is the same shuffle a car does when parallel parking.

A robot that can move sideways is holonomic, and the BugBot is one. This program does the move both ways, one after the other, and draws both paths on the mat.

Turning, driving 25 cm and turning back takes 8.4 seconds and swings the heading up to 94 degrees. Sliding the same 25 cm back takes 4.0 seconds with the heading never leaving 2 degrees of straight.
The program
from bugbot import *
connect()

GAP = 25.0        # how far across to move, cm

path = []
def log():
    p = position()
    path.append(p)
    draw("path", path, "blue", "line")
    plot("sideways cm", p[0])
    plot("heading", (heading() + 180) % 360 - 180)

def until(fwd, lat, rot, test):
    # drive like this until the test comes true, logging as it goes
    drive(fwd, lat, rot)
    for tick in range(150):
        log()
        if test():
            break
        wait(0.1)
    stop()
    for i in range(4):             # let it come to rest
        log()
        wait(0.1)

# what a differential drive has to do: turn, drive, turn back
until(0, 0, 35, lambda: (heading() + 180) % 360 - 180 > 80)
until(50, 0, 0, lambda: position()[0] >= GAP)
until(0, 0, -35, lambda: (heading() + 180) % 360 - 180 < 10)
print("shuffled across in", clock(), "s")

# what only a holonomic robot can do: straight across, never turning
t0 = clock()
until(0, -50, 0, lambda: position()[0] <= 0)
print("slid back in", round(clock() - t0, 1), "s")
print("ended at", position(), " facing", round(heading(), 1))
Put this demo on your own site

Paste it into a school website, Moodle, Google Sites or a blog. More options on the embed page.

The chart tells the story better than the mat does. The heading line goes up to 94 degrees and back down again during the shuffle, and stays flat within 2 degrees during the slide. The sideways line gets to 25 cm both times, but the shuffle takes 8.4 seconds and the slide takes 4.0. The shuffle also needs room: the robot sweeps through a right angle twice, so it cannot do this in a slot it only just fits in.

Every turn also costs accuracy. The robot ends the shuffle 1.4 degrees off the heading it started at, because turns overshoot, and any error in a turn sends the drive that follows it off in the wrong direction.

A wheel rolls forwards and never sideways, so a two wheeled robot has to turn, drive and turn backone wheel, from aboverolls: freeslides along its axle: neverboth wheels point forwards,so the sideways speed is zeromoving 25 cm acrossturnturn backa differential drive: 8.4 sa holonomic robot: 4 ssame 25 cm, no turning at all
A wheel rolls the way it points and will not slide along its axle, so a differential drive has no sideways motion to command. To end up 25 cm to one side facing the same way it has to turn, drive and turn back, which took 8.4 seconds against 4 for sliding straight across.

None of this makes a differential drive a bad choice. It is cheap, it has two motors instead of four, it pushes hard, and it does not slide about when something shoves it. That is why almost every robot vacuum is one. It does mean a path planner has to respect it: you cannot hand a differential drive a path that steps sideways, which is why followers such as pure pursuit steer along arcs, and why potential fields and A star routes have to be turned into arcs before a two wheeled robot can drive them.

Odometry: kinematics run backwards

The same two lines run the other way give a robot its position. Wheel encoders count how far each wheel turned in the last moment, say dL and dR centimetres. Then:

forward step  = (dL + dR) / 2
turn          = (dL - dR) / W          radians
heading       = heading + turn
x             = x + forward step × sin(heading)
y             = y + forward step × cos(heading)

Add that up a few hundred times a second and you have dead reckoning for a two wheeled robot. It drifts, because a wheel that slips still turns, and because W is never known to better than a millimetre or two. The kinematics is exact and the measurements are not, which is the same gap the ICC demo showed from the other end.

Where this is taught

Questions

What is a differential drive robot?

A robot with one driven wheel on each side and no steering, balanced by a castor or a ball. It goes straight by running both wheels at the same speed and turns by running them at different speeds. Robot vacuums, most school and competition robots, tanks and tracked diggers are all differential drives.

What are the kinematics of a differential drive?

Forward: v = (left + right) / 2 and w = (left - right) / W, where W is the distance between the wheels and w is in radians a second. Inverse: left = v + w × W / 2 and right = v - w × W / 2. There is no sideways term in either pair, because the robot has no sideways motion to describe.

What is the ICC in robotics?

The instantaneous centre of curvature: the point the robot is turning about right now. It lies on the line through both wheels, R = v / w from the middle of the robot, and the robot's path curves round it. It is instantaneous because changing a wheel speed moves it at once. With both wheels equal it is infinitely far away and the path is straight.

How do you work out the turning radius of a differential drive?

R = v / w, which works out to R = W / 2 × (left + right) / (left - right). With the left wheel at 12 cm/s, the right at 6 and the wheels 10 cm apart, that is 15 cm. If one wheel is stopped, R is half the wheelbase and the robot swings about that wheel. If the wheels are equal and opposite, R is zero and it spins on the spot.

Why can a differential drive not move sideways?

Because a wheel rolls along the way it points and does not slide along its axle, and both wheels point forwards. The robot's sideways speed is therefore zero at every instant, and the kinematics has no sideways term to solve for. To end up beside where it started it has to turn, drive and turn back, which on this page took twice as long as sliding straight there.

What is the difference between holonomic and non-holonomic?

A holonomic robot can set all three of its floor motions independently: across, along and heading. A non-holonomic one cannot, usually because it is not allowed to slide sideways. A differential drive and a car are non-holonomic; a robot on omni or mecanum wheels is holonomic. Both can reach any pose in the end, but the non-holonomic one has to take a particular kind of path to get there.

What is the difference between a differential drive and a car?

A car steers its front wheels and cannot turn on the spot, so its turning circle has a minimum size set by how far the steering goes. A differential drive has no steering and can turn on the spot, so it has no minimum radius. Both are non-holonomic. The maths for a car is called the bicycle model rather than differential drive kinematics.

What is the difference between forward and inverse kinematics?

Forward kinematics starts with what the motors are doing and works out how the robot moves. Inverse kinematics starts with how you want the robot to move and works out what the motors have to do. A program uses inverse kinematics to drive and forward kinematics to work out where it has got to.

How do you write differential drive kinematics in Python?

Two lines each way. v = (left + right) / 2 and w = (left - right) / W going forwards, and left = v + w * W / 2 and right = v - w * W / 2 going back. Keep w in radians a second and use math.degrees only where a number is being printed or sent to something that wants degrees. The first demo on this page is a complete program that does it.

Is differential drive kinematics on the A level syllabus?

Not by name. No GCSE or A level computer science specification includes robot kinematics. The maths in it is GCSE and A level Maths: rearranging a pair of simultaneous equations, arc length and radians, and trigonometry for the odometry. It is a good A level programming project, because the kinematics, the odometry and a path follower fit together into a system with a clear specification.

Learn it step by step

These lessons build the same ideas one at a time, each with tasks the simulator marks.

  1. 1.3 Turning and heading Driving, Robot club
  2. 1.4 Sideways Driving, Robot club
  3. U2.1 Two frames Kinematics and frames, University
  4. U2.2 The rotation matrix Kinematics and frames, University
  5. U2.3 A drive that goes sideways Kinematics and frames, University
  6. U2.4 Forward kinematics Kinematics and frames, University
  7. U2.5 Inverse kinematics Kinematics and frames, University
  8. U2.6 Go to a point Kinematics and frames, University
  9. U3.1 Integrating velocity Odometry and drift, University
  10. U3.2 Write your own odometry Odometry and drift, University
  11. U10.4 Pure pursuit Following a trajectory, University
Open the lessons