Skip to main content

Line following

Time: 11:05 AM to 11:35 AM
In this section you will build a program that makes your robot follow a dark line on a light surface without any human input. This is your first taste of autonomous behavior, but it is not AI — it uses simple if/else rules.

Set up the track

Place a strip of dark electrical tape on a light-colored surface. Include both straight sections and curves. The tape should be about 2 cm wide with strong contrast against the background.
Use the black electrical tape from your kit on a white table or light floor. The stronger the contrast, the better the robot tracks.

How the grayscale sensor works

The PiCar-X has three grayscale sensors underneath, arranged left-center-right. Each one returns an analog brightness value:
  • Low value (100–400) = dark surface (the tape)
  • High value (800–1400) = light surface (the background)
The px.get_line_status() method compares each sensor’s value against the line_reference you calibrated on Day 1 and returns a list of three values: So [0, 1, 1] means only the left sensor sees the line — the line is to the left.

Build the line follower

Step 1 — Setup

px_power is the motor speed (10% — slow and steady). offset is the steering angle when the line drifts to one side. last_state remembers which direction the robot was going before it lost the line.

Step 2 — Interpret the sensor

Write a function that converts the raw sensor status into a direction:
How to read this:
  • [0, 0, 0] — all sensors see dark. The line is lost (or the robot drove onto a fully dark area). Return 'stop'.
  • state[1] == 1 — center sensor sees background. The line is under the outer sensors, which means the robot is roughly centered. Return 'forward'.
  • state[0] == 1 — left sensor sees background (line is NOT under the left sensor). The line must be to the right, so return 'right' (steer right to follow it).
  • state[2] == 1 — right sensor sees background. The line is to the left, so return 'left'.

Step 3 — Backup recovery

This is the critical function that makes sharp turns work. When the robot loses the line, instead of driving forward off the track, it backs up while steering toward the last known direction:
The while True loop keeps backing up until a sensor picks up the line again (the state changes). This is what allows the robot to handle sharp turns — it reverses back onto the line instead of overshooting.

Step 4 — The main loop

Tie everything together. Read the sensors, decide which direction to go, and drive:
The key line: if gm_state != "stop": last_state = gm_state. This saves the last known direction so that if the line is lost, outHandle() knows which way to back up.

Step 5 — Live sensor view

Add a helper mode that shows sensor values without moving. This is useful for checking your calibration:

Step 6 — Menu and entry point

Run it

Start with option 1 to verify your sensors respond to the tape. Then place the robot on the track and select option 2.
If the line reference shows default values and the robot does not track well, re-run the grayscale calibration from Day 1:
Select option 3 and follow the prompts.

Final code: line_follower.py


Why this is not AI

The line follower uses explicit rules you wrote in get_status(). The robot cannot learn, adapt, or handle a track it was not programmed for. If you change the tape color or surface, you need to re-calibrate manually.AI replaces these hand-written rules with learned patterns. That is exactly what you will explore on Days 3 and 4.

Experiment

  1. Change the speed: edit px_power = 10 to 20 or 30. At what speed does the robot start losing the line?
  2. Widen the steering: change offset = 20 to 30. Does it handle sharper curves?
  3. 90° corners: make a right-angle turn in your tape. Can the robot handle it? Watch the backup recovery kick in.
Speed vs. tracking accuracy is a real engineering trade-off. Professional line-following robots use the same balance — faster means less time to react to sensor changes.