The depth grid

64 readings, 8 columns: seeing left and right, not just ahead.

2.3SensingRobot club20 min

Do this lesson in the simulator

distance() is one number: straight ahead. The sensor actually measures 64 distances at once, in an 8 by 8 grid across a 45 degree view. That grid is how the robot sees left and right, and it is the raw material for finding gaps and avoiding things.

tof_grid()

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

# 64 distances, 8 rows of 8
grid = tof_grid()
print("readings:", len(grid))
print("row 3, level:", grid[24:32])
print("row 7, the mat:", grid[56:64])

Run this in the simulator

64 numbers in a list, in centimetres. They are arranged in 8 rows of 8, and the rows look up and down: row 0 is the top of the view, row 7 the bottom. The sensor sits 3 cm above the mat, so the bottom rows see the mat itself a few centimetres ahead, and the top rows look over most things and see nothing. Rows 2 and 3 look level, straight ahead. Column 0 is the left edge of the view, column 7 the right.

Seeing it as a picture

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

# 64 distances, 8 rows of 8
grid = tof_grid()
# do this 8 times (row counts from 0)
for row in range(8):
    line = ""
    # do this 8 times (col counts from 0)
    for col in range(8):
        d = grid[row * 8 + col]
        line += "#" if d < 40 else ("+" if d < 80 else ".")
    print(line)

Run this in the simulator

# is close, + medium, . far. The bottom rows are always #: that is the mat. The two blocks show up in the level rows, with the gap between them. Drive forward(60, distance=20) before the print and run again and watch the blocks fill more of the picture.

Columns are directions

Each column looks in a slightly different direction. Column 0 looks about 20 degrees left, column 7 about 20 degrees right, columns 3 and 4 straight ahead. Only the level rows are worth reading for this: the rows below them see the mat. distance() is the smallest reading in the middle columns of the level rows.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

# 64 distances, 8 rows of 8
grid = tof_grid()
# do this 8 times (col counts from 0)
for col in range(8):
    # the level rows
    nearest_in_col = min(grid[row * 8 + col] for row in (2, 3))
    print(f"column {col}: {nearest_in_col} cm")

Run this in the simulator

This is the useful form: one number per direction.

Left and right

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

# 64 distances, 8 rows of 8
grid = tof_grid()
left_side = min(grid[row * 8 + 0] for row in (2, 3))
right_side = min(grid[row * 8 + 7] for row in (2, 3))
print("left:", left_side, "right:", right_side)
if left_side < right_side:
    print("more room on the right")
else:
    print("more room on the left")

Run this in the simulator

Task: widest gap

There are two blocks ahead, one left and one right, with a gap between. Without moving, print clear: column <n> for the column with the largest reading in the level rows: that is the way through.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

# 64 distances, 8 rows of 8
grid = tof_grid()
best_col = 0
best = 0
# find the column whose reading in the level rows is the largest
print("clear: column", best_col)

Challenges

  1. Print the grid picture every half second while driving slowly forward.
  2. Write column_distances() that returns the 8 per-column numbers from the level rows as a list.
  3. Steer towards the widest gap: strafe left if it is in columns 0 to 3, right if 4 to 7, then drive forward.