Vision · Robot club · about 15 min
Pixels to degrees, and a controller that turns to face a tag.
[1 mark]Using bearing = (cx - 160) * 120 / 320, what is the bearing in degrees of a tag at cx = 240?
[1 mark]Using bearing = (cx - 160) * 120 / 320, where is a tag at cx = 100?
[1 mark]What does this program print?
def bearing_of(cx):
return (cx - 160) * 120 / 320
for cx in [0, 160, 320]:
print(bearing_of(cx))-60.0 0.0 60.0
The edges of the picture are 60 degrees either side of straight ahead, because the camera sees 120 degrees in total.
[1 mark]The loop runs drive(0, 0, bearing_of(cx) * 3) and the tag is at cx = 220. What does the robot do?
[1 mark]A student writes error = (160 - cx) * 120 / 320 and uses drive(0, 0, error * 3). What happens?
cx the wrong way round flips the sign, so the controller pushes the tag further off-centre instead of pulling it in.[1 mark]Once the error is under 1.5 degrees, the program stops, waits 0.3 s and checks again. Why check again?
Turn until marker 3 is in the middle of the picture, then print centred. Do not drive.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
# camera: the tag detector
set_cv("apriltag")
print(apriltags())The hint students can ask for: Marker 3 is off to the right of the picture. Turn until it sits in the middle (cx near 160), then print centred. Do not drive.
from bugbot import *
connect()
def bearing_of(cx):
return (cx - 160) * 120 / 320 # pixels to degrees, 120 degree view across 320 pixels
set_cv('apriltag')
while True:
tags = apriltags()
if not tags:
turn_right(30)
wait(0.1)
continue
error = bearing_of(tags[0][1])
if abs(error) < 1.5:
stop()
wait(0.3) # settle, then look again
if abs(bearing_of(apriltags()[0][1])) < 1.5:
break
continue
drive(0, 0, max(-30, min(30, error * 3)))
wait(0.05)
stop()
print('centred')
Any program that meets the task's checks is marked correct in the simulator; this is one way, not the only way.