Hardware Academy
Robotics

Kinematics and motion

Differential-drive kinematics, odometry, and forward and inverse kinematics of a 2-link arm.

Day 8 · 50 min

After this lesson

  • You can compute a differential-drive robot's velocity and turn rate from wheel speeds.
  • You can integrate odometry and explain why it drifts.
  • You can solve forward and inverse kinematics for a two-link arm.

From wheel speeds to motion

Two frames and the unicycle model

Every mobile robot lives in two coordinate frames. The world frame is fixed to the floor: x east, y north, angles counter-clockwise. The body frame rides on the robot with its origin at the middle of the wheel axle, x pointing forward and y to the left (the ROS convention in REP 103). The pose is three numbers, (x, y, θ), where θ is the heading measured from the world x-axis. Sensors report in the body frame; maps and goals live in the world frame, and a rotation by θ converts between them.

A wheeled robot that cannot slide sideways obeys the unicycle model: ẋ = v·cos θ, ẏ = v·sin θ, θ̇ = ω. Its velocity in the body frame is always (v, 0). Zero sideways speed is a nonholonomic constraint: it limits how the robot can move at each instant, not where it can end up, which is why a car can still parallel park.

Differential drive: wheel speeds to v and ω

The course robot steers by running its two wheels at different speeds. With left and right wheel ground speeds vL and vR and a wheel base L between the wheel contact points:

  • v = (vR + vL) / 2: body speed is the average of the wheels.
  • ω = (vR − vL) / L: turn rate is the difference divided by the wheel base.
  • R = v / ω: distance from the robot center to the instantaneous center of curvature (ICC), which always lies on the axle line.

With L = 12 cm, vL = 15 cm/s and vR = 25 cm/s, the robot moves at 20 cm/s and turns at 0.83 rad/s (48°/s) around an ICC 24 cm to its left. Equal speeds put the ICC at infinity (a straight line); equal and opposite speeds put it at the center (spin in place); stopping one wheel puts it on that wheel (R = L/2). A planner that wants a given (v, ω) sends vR = v + ω·L/2 and vL = v − ω·L/2; if either exceeds the motor's top speed, scale both by the same factor so the curvature survives. Wheel speed comes from motor speed: an N20 gearmotor at 100 rpm on a 43 mm wheel gives 100/60 × π × 0.043 m = 0.225 m/s.

Odometry and why it drifts

Odometry turns encoder ticks into a pose. Every control period (10 ms at 100 Hz) convert the tick deltas into wheel distances ΔsL and ΔsR, then update: Δs = (ΔsR + ΔsL)/2, Δθ = (ΔsR − ΔsL)/L, x += Δs·cos(θ + Δθ/2), y += Δs·sin(θ + Δθ/2), θ += Δθ. Using the mid-step heading keeps integration error negligible at 100 Hz. The real problem is that nothing ever corrects the running sum.

Systematic errors repeat every run: unequal wheel diameters, and an effective wheel base that differs from the drawing because tires touch the floor across a patch, not a line. Non-systematic errors are random: slip, bumps, carpet seams, tick quantization. Heading errors hurt most because they turn every later meter into sideways error: 1° of heading error costs 17 mm per meter driven. On a 12 cm wheel base, a right wheel just 0.5% larger than the left curves a "straight" line with a 24 m radius, 8 cm off course after 2 m.

Borenstein and Feng's UMBmark (University of Michigan, 1996) measures the systematic part: drive a 4 m × 4 m square five times clockwise and five times counter-clockwise and record where the robot stops. Both directions are needed because a wheel-diameter error and a wheel-base error add up in one direction and cancel in the other. Their correction factors cut return error roughly tenfold; after that, fuse a gyro for heading and add absolute fixes such as floor markers, a map or GNSS.

Driving to a goal

The simplest go-to-goal controller steers on heading error. Compute the bearing α = atan2(yg − y, xg − x), the error e = α − θ wrapped into −π…π with atan2(sin e, cos e), then command ω = Kθ·e and v = min(vmax, Kρ·ρ)·max(0, cos e), where ρ is the distance to the goal. The cos e factor keeps the robot from driving away while it turns toward a goal behind it. Start with Kθ = 2 s⁻¹ and Kρ = 0.5 s⁻¹ and stop inside 2 cm, or it will circle the goal forever.

Smooth motion: trapezoidal profiles

Jumping straight to full speed spikes motor current and slips the wheels. A trapezoidal profile accelerates at a fixed limit, cruises, then decelerates. For a 1 m move with amax = 0.5 m/s² and vmax = 0.3 m/s, each ramp lasts 0.6 s and covers 9 cm, the cruise covers the other 82 cm, and the move takes 3.9 s. Moves shorter than vmax²/amax = 18 cm never reach cruise speed and become triangles. Industrial arms use S-curves that also limit jerk.

Arms: forward and inverse kinematics

A planar arm with links l1 and l2, shoulder angle θ1 and elbow angle θ2 (relative to link 1) has forward kinematics x = l1·cos θ1 + l2·cos(θ1 + θ2) and y = l1·sin θ1 + l2·sin(θ1 + θ2). Inverse kinematics runs the other way. The law of cosines on the base, elbow and tip triangle gives cos θ2 = (x² + y² − l1² − l2²) / (2·l1·l2). Outside −1…1 the target is unreachable; inside, θ2 = ±acos(…) gives two solutions, elbow down (θ2 > 0) and elbow up (θ2 < 0), and θ1 = atan2(y, x) − atan2(l2·sin θ2, l1 + l2·cos θ2). With l1 = 120 mm and l2 = 90 mm, the target (150, 103.9) mm gives cos θ2 = 0.5, so θ2 = ±60° and θ1 = 60° (elbow up) or 9.4° (elbow down).

That arm's workspace is an annulus from |l1 − l2| = 30 mm to l1 + l2 = 210 mm. On its edges the arm is fully stretched or folded, the two solutions merge, and the Jacobian determinant l1·l2·sin θ2 drops to zero: a singularity, where the tip cannot move radially and the joint speeds needed nearby blow up. Six-axis arms such as the Universal Robots UR5e (850 mm reach) have closed-form IK for their wrist geometry and plan around singular poses; general arms use numerical IK such as damped least squares.

Differential-drive geometry: wheel speeds, wheel base, heading and the instantaneous center of curvaturex worldy worldθx bodyy bodyvLvRLICCωRv = (vR + vL) / 2ω = (vR − vL) / LR = v / ωvR = 2·vL here, so the ICCsits 1.5·L from the center
Differential-drive geometry. The line through the tips of the wheel speed arrows (drawn to scale, vR = 2·vL) meets the axle line at the ICC; the robot center follows the dashed circle of radius R = v/ω.

Interactive: drive the robot, then move the arm

Differential drive: from wheel speeds to motion

Set the wheel speeds and watch the ICC and the path. Then add a small wheel-size or wheel-base error and compare the real path (cyan) with what odometry believes (amber, dashed).

Differential-drive robot with its instantaneous center of curvature and odometry trace50 cmreal pathodometry estimatestartICCvL arrow green · vR arrow orange · t = 0.0 s
Mode
v = 20.0 cm/sω = 0.83 rad/sR = 24.0 cmtrue pose: (100.0, 60.0) cm, 0.0°odometry: (100.0, 60.0) cm, 0.0°position error 0.0 cm · heading error 0.0°

Two-link arm: forward and inverse kinematics

Drag anywhere on the canvas (or focus it and use the arrow keys) to move the target; IK solves the joint angles. Move the joint sliders to drive the arm by forward kinematics instead.

Two-link arm reaching for a draggable target inside its reach envelopereach envelope: 30 mm to 210 mml1 = 120 mm, l2 = 90 mmθ1θ2target
θ1 = 60.0°θ2 = -60.0°target (150.0, 103.9) mm, r = 182.5 mmdet J = l1·l2·sin θ2 = -9353 mm²Reachable: two solutions, elbow up and elbow down

In practice

Practice

Update odometry from encoder ticks

The course robot has 43 mm wheels, encoders that give 1050 ticks per wheel revolution (7 pulses per motor turn × a 150:1 gearbox) and a 120 mm wheel base. It starts at (0, 0, 0°). In one 100 ms window the left encoder counts 140 ticks and the right encoder 160.

  1. Compute the new pose (x, y, θ).
  2. Compute v, ω and the turn radius R.
  3. The real effective wheel base is 125 mm, not 120. If the robot holds these wheel speeds for 10 s, how far off is the odometry heading?
odometry.cppcpp
// Called every 10 ms with the encoder tick deltas since the last call.
const float MM_PER_TICK = PI * 43.0f / 1050.0f;  // 0.12866 mm per tick
const float WHEEL_BASE  = 120.0f;                 // mm, calibrate with UMBmark

float x = 0, y = 0, theta = 0;                    // pose in the world frame

void updateOdometry(long dTicksL, long dTicksR) {
  float dsL = dTicksL * MM_PER_TICK;
  float dsR = dTicksR * MM_PER_TICK;
  float ds  = 0.5f * (dsR + dsL);
  float dth = (dsR - dsL) / WHEEL_BASE;
  x += ds * cosf(theta + 0.5f * dth);             // mid-step heading
  y += ds * sinf(theta + 0.5f * dth);
  theta = atan2f(sinf(theta + dth), cosf(theta + dth));  // wrap to (-π, π]
}

Answer

text
distance per tick = π × 43 mm / 1050          = 0.12866 mm
ΔsL = 140 × 0.12866 = 18.01 mm    ΔsR = 160 × 0.12866 = 20.59 mm
Δs  = (20.59 + 18.01) / 2                    = 19.30 mm
Δθ  = (20.59 − 18.01) / 120                  = 0.02144 rad = 1.23°

(a) x = 19.30 · cos(0.01072) = 19.30 mm
    y = 19.30 · sin(0.01072) =  0.21 mm
    θ = 1.23°
(b) v = 19.30 mm / 0.1 s = 19.3 cm/s
    ω = 0.02144 rad / 0.1 s = 0.214 rad/s
    R = v / ω = 90 cm (to the left)
(c) true Δθ = 2.573 / 125 = 0.02058 rad, so odometry over-counts 0.049° per step
    after 100 steps (10 s, 1.9 m of travel): heading off by 4.9°, position off by about 7.3 cm

Part (c) is the whole story of odometry drift: a 4% wheel-base error is invisible in one step and costs 5° in ten seconds.

Practice

Solve IK by hand, then check it in the viz

For the arm above (l1 = 120 mm, l2 = 90 mm), find both joint solutions for the target (60, 150) mm. Then drag the target there and toggle the elbow to check your numbers.

text
x² + y² = 60² + 150² = 26 100
cos θ2 = (26 100 − 120² − 90²) / (2 · 120 · 90) = 3 600 / 21 600 = 0.1667
θ2 = ±80.4°
atan2(150, 60) = 68.2°
elbow up   (θ2 = −80.4°): θ1 = 68.2° − atan2(90·sin(−80.4°), 120 + 90·cos(−80.4°)) = 68.2° + 33.3° = 101.5°
elbow down (θ2 = +80.4°): θ1 = 68.2° − 33.3° = 34.9°

Real-world scenario

Real-world scenario

Odometry is off by 1 m after one lap

A lab's indoor delivery robot (65 mm wheels, 2048-count encoders, 280 mm wheel base from CAD) drives a 24 m rectangular loop (8 m × 4 m) through the corridor using pure odometry between two charging docks. Clockwise laps end with the robot about 1 m from the dock even though its pose estimate says it is exactly on the marker, so the docking routine times out. The team has already swapped both encoders and rewritten the odometry code twice.

Symptoms

  • Commanding equal encoder counts for 8 m ends about 14 cm to the left of a tape line on the floor
  • Each commanded 90° turn measures about 88° with a protractor on the floor
  • Clockwise laps miss the dock by about 1 m, counter-clockwise laps by less than 10 cm
  • New encoders and a code rewrite left the error unchanged and repeatable from lap to lap

Interview questions

screenA differential-drive robot has a 12 cm wheel base. The left wheel runs at 15 cm/s and the right at 25 cm/s. What are v and ω, and what is it turning about?
Linear speed is the average of the wheels, (25 + 15)/2 = 20 cm/s. Turn rate is the difference over the wheel base, (25 − 15)/12 ≈ 0.83 rad/s, counter-clockwise because the right wheel is faster. The instantaneous center of curvature is on the axle line R = v/ω = 24 cm to the left of the robot center. Equal wheel speeds would put R at infinity (straight line) and equal-and-opposite speeds would put it at the center (spin in place). Before sending such a command to motors I would also check saturation and scale both wheels together so the curvature is preserved.
screenWhy does wheel odometry drift, and what would you do about it?
Odometry integrates wheel distances, so every small error is added up and nothing ever corrects it. Systematic errors come from unequal wheel diameters and an uncertain effective wheel base; non-systematic ones from slip, bumps and encoder quantization. Heading error is the dangerous one, because 1° of heading error becomes about 1.7 cm of sideways error for every meter driven afterwards. I would first calibrate the systematic part with a UMBmark square test in both directions, then fuse a gyro for heading, limit acceleration to reduce slip, and add absolute fixes such as markers, a map with lidar, or GNSS outdoors.
screenWhat is the difference between the body frame and the world frame, and where do people mix them up?
The world frame is fixed to the environment; the body frame rides on the robot with x forward and y to the left. Encoders, IMUs and range sensors report in the body frame, while maps, goals and other robots live in the world frame. A rotation by the heading θ converts between them, so a body speed v becomes (v·cos θ, v·sin θ) in the world. The classic bug is adding a sensor point to the map without rotating it by θ, which smears walls into arcs as the robot turns. ROS makes the convention explicit with the map, odom and base_link frames.
deepWalk me through inverse kinematics for a planar two-link arm, including when it fails.
With the base at the origin and the target at (x, y), the law of cosines gives cos θ2 = (x² + y² − l1² − l2²)/(2·l1·l2). If that value is outside −1 to 1 the target is out of reach. Otherwise θ2 = ±acos of it gives the elbow-down and elbow-up solutions, and θ1 = atan2(y, x) − atan2(l2·sin θ2, l1 + l2·cos θ2). The workspace is an annulus from |l1 − l2| to l1 + l2; on its edges the two solutions merge at a singularity where det J = l1·l2·sin θ2 = 0, so the arm cannot move radially and joint speeds blow up nearby. In practice I would also enforce joint limits, choose the solution closest to the current pose to avoid flips, and switch to damped least-squares IK for arms with more joints.
deepThe robot must stop exactly 1 m ahead without wheel slip. How do you generate the motion?
I would plan a trapezoidal velocity profile: accelerate at a fixed limit, cruise, then decelerate at the same limit. With a_max = 0.5 m/s² and v_max = 0.3 m/s each ramp takes 0.6 s and 9 cm, the cruise covers the remaining 82 cm, and the move takes about 3.9 s. If the distance were shorter than v_max²/a_max = 18 cm the profile becomes a triangle with peak speed √(a·d). The wheel speed loops track the profile, and an outer loop on the remaining distance trims the final error. If the payload is fragile I would use an S-curve that also limits jerk.

Quiz

1. A robot with wheel base L = 10 cm has vL = 20 cm/s and vR = 30 cm/s. What is its turn rate ω?
2. What happens when vL = −vR?
3. Why is a heading error more damaging to odometry than an equal-sized distance error?
4. A planar arm has l1 = 120 mm and l2 = 90 mm with free joints. Which distances r from the base can its tip reach?
5. At a singularity of a 2-link planar arm,
6. Why does UMBmark drive the square both clockwise and counter-clockwise?
7. A trapezoidal profile has a_max = 0.5 m/s² and v_max = 0.3 m/s. How far does the robot travel while accelerating?

References and further reading

Where the ideas in this lesson come from, and what to read next. Books are the standard texts; papers are the original sources; standards are what employers work to.

  1. Book

    Roland Siegwart, Illah R. Nourbakhsh and Davide Scaramuzza (2011). Introduction to Autonomous Mobile Robots. MIT Press, 2nd edition.

    Read: The kinematics chapter: differential drive and odometry.

  2. Paper

    Johann Borenstein and Liqiang Feng (1996). Measurement and Correction of Systematic Odometry Errors in Mobile Robots. IEEE Transactions on Robotics and Automation 12(6), 869-880.doi:10.1109/70.544770

    Read: The UMBmark method used in the lesson.

  3. Book

    John J. Craig (2018). Introduction to Robotics: Mechanics and Control. Pearson, 4th edition.

    Read: Chapters on forward and inverse kinematics.

  4. Bookfree online

    Kevin M. Lynch and Frank C. Park (2017). Modern Robotics: Mechanics, Planning, and Control. Cambridge University Press.

    Read: The free videos on kinematics.