The loop
Look, decide, act, wait, repeat. One action per tick. Counting ticks.
Do this lesson in the simulatorEvery program so far was a script: do this, then this, then stop. Real robots do not stop. A vacuum cleaner, a delivery robot and a Mars rover all run the same thing forever: look, decide, act, wait, repeat. This module is about programs shaped like that, called behaviours, and it ends with a robot that decides for itself what to do next.
Scripts block; behaviours tick
forward(60, distance=20) blocks: your program stops until the move is done, and nothing else can happen. A behaviour never blocks. Every tick it looks at the sensors, chooses one action, sends it with a non-blocking call, and waits one tick:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
# do this 50 times (tick counts from 0)
for tick in range(50):
if distance() < 25:
# something close: turn away
turn_right(60)
else:
# clear: go
forward(60)
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# all motors off
stop()
print("still alive after 5 seconds")
That is a complete behaviour: wander. Nothing in it says how far to go or when to turn. The world decides that, tick by tick.
Why the wait matters
Without wait(0.1) the loop would ask the sensors thousands of times a second with no time passing, and the simulator would stop it. On the real robot the radio would choke. Ten ticks a second is plenty for a robot this size; the safety timer needs to hear from you at least twice a second anyway.
One action per tick
A tick chooses one thing. Two drive calls in a tick and only the last one counts. That is a feature: the decision is always a single if / elif / else and the robot does exactly one thing until it looks again.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
# do this 100 times (tick counts from 0)
for tick in range(100):
# cm to the nearest thing ahead
d = distance()
if d < 15:
# drive backward at 40
backward(40)
elif d < 30:
# spin clockwise on the spot at 60
turn_right(60)
else:
# drive forward at 70 (keeps going until the next command)
forward(70)
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# all motors off
stop()
print("ended at", position())
Counting ticks
Behaviours need a clock. You have one: the tick counter.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
# do this 60 times (tick counts from 0)
for tick in range(60):
# 10 ticks on, 10 ticks off
if tick % 20 < 10:
# the LED: green
led("green")
else:
# the LED: off
led("off")
# drive forward at 40 (keeps going until the next command)
forward(40)
if distance() < 25:
# spin clockwise on the spot at 60
turn_right(60)
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# all motors off
stop()
Ten ticks is a second. tick % 20 < 10 is true for the first second of every two. This is how a behaviour does two things at once: it does not, it just alternates fast.
Task: wander
Keep moving for the whole twenty seconds, at least 120 cm in total, without touching a box or the edge of the mat.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
# drive forward at 60 (keeps going until the next command)
forward(60)
# pause 5 s (the robot keeps doing what it was told)
wait(5)
# all motors off
stop()
Challenges
- Wander for 20 seconds and print how many times you turned.
- Turn left or right depending on which side of the depth grid has more room.
- Slow down when something is between 30 and 50 cm away instead of waiting until 25.