Skip to main content

Lesson 5 · Proportional Control

Module 2 · Line Tracking

Lesson 5 · Proportional Control

60+ minControl loopsFirst real line following
👩‍🏫

Teacher mode is on. Toggle it off (bottom-right) to preview the student view.

Bouncing kept the robot inside the circle, but it never actually followed the line. This lesson is the real thing: the robot smoothly tracks the edge of the line by making tiny, constant steering adjustments — the same way you'd steer a car around a gentle curve. It's your first control loop, and one of the most important ideas in the whole course.

Learning Objectives

By the end of this lesson you will be able to:

  • Explain a setpoint and why the line's edge (~0.5) is ours
  • Compute error as setpoint − sensor_reading, and read its sign
  • Turn error into a steering correction with a gain Kp
  • Steer continuously with arcade() inside a while True loop
  • Tune Kp by watching the robot and adjusting

Steer while you drive: arcade()

Bounce driving reacted after hitting the line. Following means constantly adjusting so you never leave it — like nudging the wheel around a curve instead of stopping to turn.

For that you need to steer without stopping. arcade(speed, turn) does exactly this — it sets a forward speed and a steering amount in one non-blocking call:

drivetrain.arcade(speed, turn)
# is the same as:
drivetrain.set_effort(speed + turn, speed - turn)

So arcade(0.3, 0.15) speeds up the left wheel and slows the right — the robot curves. A positive turn steers one way, negative the other, and zero drives straight.

Knowledge Check

With base speed 0.3, what does `arcade(0.3, 0.15)` set the two motors to?

Setpoint and error

The setpoint is the reading we want the sensor to hold. Following the edge of the line, that's about 0.5 — halfway between white and black. Error is how far off we are:

error = setpoint − sensor_reading

The sign tells us which way we've drifted; the size tells us how far:

Where the robot isreadingerror = 0.5 − readingMeaning
On the edge (perfect)0.50.0no correction
Drifted onto white0.2+0.3steer toward the line
Drifted onto black0.8−0.3steer back off the line
Far onto white0.1+0.4steer hard toward the line
🖼️
Diagram — sensor drifting onto white (positive error) vs onto black (negative error), with steering arrows
Add a src to drop in your image
Positive error means steer one way, negative the other. The controller figures out direction automatically from the sign.
Knowledge Check

Setpoint is 0.5 and the sensor reads 0.2. What is the error?

From error to steering: the gain Kp

We don't feed raw error to the motors — we scale it by a proportional gain, Kp, to set how strongly the robot reacts:

correction = error × Kp

With Kp = 0.5, an error of +0.3 gives a correction of +0.15. Then we steer with that correction:

drivetrain.arcade(base_effort, correction)

Bigger error → bigger correction → sharper steer. When the robot is right on the edge (error 0), the correction is 0 and it drives straight. Notice there's no if/else — the math handles left vs. right on its own, through the sign.

Knowledge Check

If Kp = 0.6 and error = 0.3, what is the correction?

The complete control loop

Every pass: read the sensor, compute error, compute correction, steer. Hundreds of times a second.

from XRPLib.differential_drive import DifferentialDrive
from XRPLib.reflectance import Reflectance
from XRPLib.board import Board
import time

drivetrain = DifferentialDrive.get_default_differential_drive()
reflectance = Reflectance.get_default_reflectance()
board = Board.get_default_board()

setpoint = 0.5 # target: the edge of the line
Kp = 0.5 # proportional gain — tune this!
base_effort = 0.3 # forward speed

board.wait_for_button()

while True:
sensor_value = reflectance.get_left()
error = setpoint - sensor_value
correction = error * Kp
drivetrain.arcade(base_effort, correction)
time.sleep(0.01)

Activity · Tuning Kp

Kp is yours to tune by watching the robot:

  • Too high → the robot over-corrects and oscillates, weaving rapidly.
  • Too low → it reacts sluggishly and drifts off the line.
  • Just right → smooth tracking with small corrections.
Knowledge Check

Your robot follows the line but weaves back and forth rapidly, never settling. What should you do to Kp?

Print your values while you tune (every 50th pass keeps the console readable):

if loop_count % 50 == 0:
print(f"sensor={sensor_value:.2f} error={error:.2f} correction={correction:.2f}")

Real-world connections

Proportional control (and its bigger sibling, PID) runs an enormous amount of the physical world:

Cars

Cruise control

The further you are below the set speed, the harder it presses the throttle — error × gain.

Flight

Drone stabilization

Drones hold level by constantly correcting in proportion to how far they've tilted.

Driving

Lane-keeping

Self-driving lane assist steers in proportion to how far the car has drifted from center.

Wrap-up

  • What's the setpoint for edge-following, and why? (~0.5 — the boundary between white and black.)
  • What do the sign and size of the error each tell you? (Sign = which way to steer; size = how hard.)
  • The robot oscillates — too high or too low Kp? (Too high; decrease it.)

Resources