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.
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 |
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.
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))
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.
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 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()
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.
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))
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.
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
- Turning and heading and Sideways: driving and turning, and the move a two wheeled robot cannot make.
- Two frames and The rotation matrix: the robot's own axes against the mat's.
- A drive that goes sideways: what holonomic means, and what it costs.
- Forward kinematics and Inverse kinematics: both directions, worked through.
- Go to a point: turning a target into a forward speed and a turn rate.
- Integrating velocity and Write your own odometry: running the kinematics backwards.
- Omni wheel kinematics: the same job for a robot with four wheels and no forward.
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.3 Turning and heading Driving, Robot club
- 1.4 Sideways Driving, Robot club
- U2.1 Two frames Kinematics and frames, University
- U2.2 The rotation matrix Kinematics and frames, University
- U2.3 A drive that goes sideways Kinematics and frames, University
- U2.4 Forward kinematics Kinematics and frames, University
- U2.5 Inverse kinematics Kinematics and frames, University
- U2.6 Go to a point Kinematics and frames, University
- U3.1 Integrating velocity Odometry and drift, University
- U3.2 Write your own odometry Odometry and drift, University
- U10.4 Pure pursuit Following a trajectory, University