Passing
Aim at a team mate's tag, judge the power from its distance.
Do this lesson in the simulatorA pass is a kick with an aim and a range. A kick always travels about 45 cm, so a pass means getting to about that distance from your team mate, turning until they are dead ahead, and kicking. Their tag gives you both numbers: the bearing and the distance.
Find the receiver
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
def bearing_of(cx):
return (cx - 160) * 120 / 320
# camera: the tag detector
set_cv("apriltag")
for tag in apriltags():
print(f"robot {tag[0]}: {tag[3]} cm away, bearing {round(bearing_of(tag[1]), 1)}")
Robot 101 is up and to the right, with a blue LED. Not straight ahead, so a kick now would miss.
Aim
Turn until the tag is centred, with the settle-and-check from lesson 4.2, holding the ball all the while:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
def bearing_of(cx):
return (cx - 160) * 120 / 320
# close the jaws (it waits while they move)
gripper("close")
# camera: the tag detector
set_cv("apriltag")
# do this 100 times (tick counts from 0)
for tick in range(100):
tags = [t for t in apriltags() if t[0] == 101]
if not tags:
# spin clockwise on the spot at 30
turn_right(30)
else:
error = bearing_of(tags[0][1])
if abs(error) < 1.5:
# all motors off
stop()
# pause 0.3 s (the robot keeps doing what it was told)
wait(0.3)
if abs(bearing_of(apriltags()[0][1])) < 1.5:
# leave the loop
break
else:
# forward, sideways, rotation: -100 to 100 each, until the next command
drive(0, 0, max(-30, min(30, error * 3)))
# pause 0.05 s (the robot keeps doing what it was told)
wait(0.05)
# all motors off
stop()
print("aimed at heading", round(heading()), "holding:", holding())
Range
The tag gives the distance. A kick goes about 45 cm, and the ball starts about 8 cm in front of your centre, so the ball stops about 53 cm from you: that is where the receiver has to be. Farther and the pass drops short, nearer and it rolls past. So carry the ball to the right distance first, then aim, then kick:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
def bearing_of(cx):
return (cx - 160) * 120 / 320
def aim_at(tag_id):
# turn until the tag is centred, with the settle-and-check from lesson 4.2
# do this 100 times (tick counts from 0)
for tick in range(100):
tags = [t for t in apriltags() if t[0] == tag_id]
if not tags:
# spin clockwise on the spot at 30
turn_right(30)
else:
error = bearing_of(tags[0][1])
if abs(error) < 1.5:
# all motors off
stop()
# pause 0.3 s (the robot keeps doing what it was told)
wait(0.3)
if abs(bearing_of(apriltags()[0][1])) < 1.5:
return
else:
# forward, sideways, rotation: -100 to 100 each, until the next command
drive(0, 0, max(-30, min(30, error * 3)))
# pause 0.05 s (the robot keeps doing what it was told)
wait(0.05)
# all motors off
stop()
# close the jaws (it waits while they move)
gripper("close")
# camera: the tag detector
set_cv("apriltag")
aim_at(101)
dist = [t for t in apriltags() if t[0] == 101][0][3]
print(f"receiver {dist} cm away")
if dist > 56:
# too far for a kick: carry the ball closer
forward(40, distance=dist - 53)
elif dist < 50:
# too close: back off
backward(40, distance=53 - dist)
# moving changes the bearing a little: aim again
aim_at(101)
# kick: one turn of the kicker winds the spring and lets it go
kick()
# pause 4 s (the robot keeps doing what it was told)
wait(4)
Receiving
The other half of a pass is the receiver: face the passer, wait, and close the jaws when the ball arrives in front of you. distance() dropping to a few centimetres is the moment. In the netball game the receiver is another program, and it has to be ready before the kick.
Task: pass to your partner
Grip the ball, get to kicking range of robot 101, aim, and kick so the ball stops within the square around it.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
# close the jaws (it waits while they move)
gripper("close")
# kick: one turn of the kicker winds the spring and lets it go
kick()
# pause 5 s (the robot keeps doing what it was told)
wait(5)
Challenges
- Pass to a partner who is moving: aim a little ahead of them.
- Make the pass bounce off the right wall on its way (aim at the wall, and think about the range).
- Write
pass_to(tag_id)that does the whole thing, and time it.