Lesson 7 · Obstacle Detection with the Rangefinder
Lesson 7 · Obstacle Detection
Teacher mode is on. Toggle it off (bottom-right) to preview the student view.
Until now you've typed the blocked list by hand. Now the robot discovers obstacles on its own, using the ultrasonic rangefinder. At each intersection it checks ahead, and if something's blocking the next node, it adds it to the blocked list and asks Dijkstra for a fresh path. The robot stops following a script and starts reacting to its world.
Learning Objectives
By the end of this lesson you will be able to:
- Initialize the XRP rangefinder and read a distance
- Explain how an ultrasonic rangefinder measures distance
- Use a threshold to decide whether the next intersection is blocked
- Work out which node is ahead from position and heading
- Run the check → detect → update → recompute → drive loop
The robot gets eyes
The ultrasonic rangefinder sends out a sound pulse — too high for us to hear — and times the echo bouncing back. The round-trip time tells it how far away an object is, returned in centimeters. Reading it takes three lines:
from XRPLib.rangefinder import Rangefinder
rangefinder = Rangefinder.get_default_rangefinder()
distance = rangefinder.distance() # float, in cm
print(f"Distance: {distance:.1f} cm")
The sensor does the physics internally; you just read a number.
How does an ultrasonic rangefinder measure distance?
Choosing a threshold
Sensor readings have noise and vary a little each time, so you don't check for an exact distance — you use a threshold. Measure with the next intersection blocked (say ~12 cm) and clear (say ~50 cm), then pick a cutoff between them:
OBSTACLE_THRESHOLD = 15 # cm — tune to your grid spacing
distance = rangefinder.distance()
if distance < OBSTACLE_THRESHOLD:
print("OBSTACLE DETECTED")
else:
print("Path is clear")
Why use a threshold instead of checking for an exact distance?
Which node is blocked?
The rangefinder says something's ahead — but which node? The blocked one is the intersection directly in front of the robot, and the robot already knows its position and heading (0=N, 1=E, 2=S, 3=W from Module 4):
NORTH, EAST, SOUTH, WEST = 0, 1, 2, 3
def get_next_intersection(current_pos, heading):
row, col = current_pos
if heading == NORTH: return (row - 1, col)
if heading == EAST: return (row, col + 1)
if heading == SOUTH: return (row + 1, col)
if heading == WEST: return (row, col - 1)
The obstacle is never the node the robot is on — it's the adjacent one the sensor points at.
The robot is at (2,1) facing NORTH and the rangefinder reads 8 cm (threshold 15). Which node is blocked?
The five-step loop
At each intersection, the robot runs the same cycle — the core of reactive robotics:
# 1. CHECK: read the rangefinder
distance = rangefinder.distance()
# 2. DETECT: is the next node blocked?
if distance < OBSTACLE_THRESHOLD:
blocked_node = get_next_intersection(current_pos, heading)
# 3. UPDATE: remember the obstacle
if blocked_node not in blocked_list:
blocked_list.append(blocked_node)
# 4. RECOMPUTE: fresh path from where we are now
pathfinder = Dijkstra(current_pos, blocked_list)
path = pathfinder.compute_path(destination)
# 5. DRIVE: follow the (possibly new) path to the next node
Every time a new obstacle turns up, you make a fresh Dijkstra with the updated blocked list and the robot's current position, and get a new path. Check → detect → update → recompute → drive, over and over.
When the robot detects a new obstacle, what does it do to reroute?
Activity · Test in simulation first
Before the robot, prove the logic works by faking the sensor — return a short distance when the next node is a pretend obstacle:
simulated_obstacles = [(1, 1), (2, 2)]
def simulate_rangefinder(next_pos):
return 8.0 if next_pos in simulated_obstacles else 50.0
Run the whole loop with this stand-in; confirm the path reroutes and the blocked list
grows. Then swap in the real rangefinder.distance(). Separating software bugs from
hardware bugs saves enormous frustration.
Why test with a simulated rangefinder before using the real one?
Real-world connections
Sense → decide → act is the loop behind every autonomous machine:
Self-driving
Radar and LIDAR detect obstacles; the planner reroutes in real time, just like this loop.
Fulfillment robots
Robots sense blocked aisles and replan paths on the fly to keep goods moving.
Mars rovers
Rovers scan the terrain ahead and reroute around rocks they can't cross.
Wrap-up
- What three lines read the rangefinder? (Import, get_default,
.distance().) - Which node does an obstacle reading refer to? (The next intersection ahead, from position + heading.)
- What are the five steps of the loop? (Check, detect, update, recompute, drive.)