Bumps and stalls
bumped(), stalls from velocity, back off and go round.
Do this lesson in the simulatorSensors do not see everything. The depth sensor looks level and over the top of anything low; the camera sees only ahead. Sooner or later the robot hits something it never saw, and it needs to know. Two senses tell it: the jolt, and the fact that it stopped moving.
bumped()
The accelerometer in the IMU feels the jolt of a collision. bumped() is true for a moment afterwards:
# 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)
# do this 60 times (tick counts from 0)
for tick in range(60):
if bumped():
print("bumped at", position(), "after", tick / 10, "seconds")
# leave the loop
break
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# all motors off
stop()
print("distance sensor says", distance(), "cm: it never saw the box")
The box is 2 cm tall. The depth sensor's level rows look straight over it, so distance() reports the far wall the whole time, and the first the robot knows is the bump.
Stalls
The other sign is a robot that is told to drive and does not move. The optical-flow sensor reports the real speed, so compare it with what you asked for:
# 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)
# do this 60 times (tick counts from 0)
for tick in range(60):
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# how fast I am moving: sideways and forward, cm/s
vx, vy = velocity()
if tick > 5 and vy < 2:
print("stalled at", position(), "with the motors at 60")
# leave the loop
break
# all motors off
stop()
Wheels would spin against a wall; vibration feet just buzz in place. Either way the flow sensor sees no motion. A stall check catches slow collisions the accelerometer misses, and things like driving off the edge of a table onto nothing.
Back off, go round
A bump is an event, and the response is a small behaviour that runs to completion, exactly like the avoid layer in lesson 5.4:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
state = "go"
ticks = 0
while position()[1] < 80:
if state == "go":
# drive forward at 60 (keeps going until the next command)
forward(60)
if bumped():
print("bumped")
state = "back"
ticks = 0
elif state == "back":
# drive backward at 50
backward(50)
ticks += 1
if ticks > 8:
state = "side"
ticks = 0
elif state == "side":
# slide right at 60
right(60)
ticks += 1
if ticks > 18:
state = "go"
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# all motors off
stop()
print("got to", position())
Back for 9 ticks, sideways for 19, then carry on (the counts start at 0 and move on once past 8 and 18). The numbers are the size of the thing you expect to hit; a general robot would sidestep until the way ahead is clear, then try again.
Wall or robot?
A wall stays where it is; a robot moves. After a bump, look: if a tag is right in front of you, or the thing you hit is gone a second later, it was a robot, and the polite response is to wait rather than shove.
Task: bump and back
Reach the green zone past a box the depth sensor cannot see, printing bumped when you hit it.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
while position()[1] < 80:
# drive forward at 60 (keeps going until the next command)
forward(60)
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# all motors off
stop()
Challenges
- Count the bumps and print the total at the end.
- Use the stall check instead of
bumped()and see which reacts first. - After the bump, sidestep only until
distance()in the level rows shows the way is clear.