Learning · Robot club · about 20 min
Learning a controller gain by trial: measure, change, keep the better.
[1 mark]What does this program print?
xs = [2, -4, 1, -1] errors = [abs(x) for x in xs] print(sum(errors) / len(errors))
2.0
Take the size of each error, ignoring its sign: 2, 4, 1 and 1. Their mean is 8 / 4 = 2.0.
[1 mark]A trial's score is the mean of abs(x). Gain 6 scores 2.2 and gain 12 scores 1.3. Which is better?
[1 mark]What does this program print?
def trial(gain):
return abs(gain - 10) + 1
gain, direction = 2.0, 1
best_gain, best_error = gain, 1e9
for t in range(5):
error = trial(gain)
if error < best_error:
best_gain, best_error = gain, error
else:
direction = -direction
gain = max(1.0, best_gain + direction * 4.0)
print(best_gain)10.0
It tries 2, 6 and 10, each better. 14 is worse, so it turns round and tries 6 from the best, also worse, then turns again. The best stays 10.0.
[1 mark]Why does a gain of 1 never steer this robot until it is 15 cm out?
[1 mark]Suppose a robot leaks 2 cm sideways every second, and the lane is 8 cm wide with the robot starting on the centre line. After how many seconds is it out of the lane?
[1 mark]In the hill climb, a trial scores worse than the best so far. What happens next?
[1 mark]The same measure, change, keep the best loop can tune which of these?
Tick every answer that is true.
Drive up and down the lane, trying gains and keeping the best. After 30 seconds the robot must stay inside the lane. Print best gain: <value> at the end.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
gain = 0.3
# do this 10 times (leg counts from 0)
for leg in range(10):
# do this 50 times (tick counts from 0)
for tick in range(50):
# where am I? (cm from where I started)
x, y = position()
# forward, sideways, rotation: -100 to 100 each, until the next command
drive(40 if leg % 2 == 0 else -40, -x * gain, 0)
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# all motors off
stop()
print(f'best gain: {gain:.1f}')The hint students can ask for: This robot leaks badly sideways. Drive up and down the lane, and let the program try different sideways gains, keeping whichever holds the lane best. After 30 seconds it must stay inside the lane. Print best gain: <value> at the end.
from bugbot import *
connect()
gain = 2.0
best_gain, best_error = gain, 1e9
direction = 1
for trial in range(5):
errors = []
for leg in range(2):
for tick in range(50):
x, y = position()
drive(40 if leg == 0 else -40, -x * gain, 0) # up 5 s, back 5 s, steering sideways from x
errors.append(abs(x))
wait(0.1)
error = sum(errors) / len(errors)
print(f"trial {trial}: gain {gain:.1f}, mean error {error:.1f}")
if error < best_error:
best_gain, best_error = gain, error
else:
direction = -direction # that was worse: try the other way
gain = max(1.0, best_gain + direction * 4.0)
stop()
print(f"best gain: {best_gain:.1f}")
Any program that meets the task's checks is marked correct in the simulator; this is one way, not the only way.