Odometry and drift · University · about 45 min
Two metres of driving, one landmark, and an estimate that has to stay honest.
[1 mark]Put the long lap program in order.
Number the lines 1 to 5 to put them in the right order.
Stop in the home zone and keep updating while stoppedSteer towards (0, 0) in your own estimated frame, still updating every tickDrive the outward part of the lap, updating the odometry every tickStand still and average the gyro rate to learn the biasPrint my x and my yStand still and average the gyro rate to learn the bias Drive the outward part of the lap, updating the odometry every tick Steer towards (0, 0) in your own estimated frame, still updating every tick Stop in the home zone and keep updating while stopped Print my x and my y
Calibration comes first, because without it the rest does not matter. The odometry runs throughout, and the way home is steered on the estimate itself.
[1 mark]The example program calls step(4) after stop(). Why keep updating the odometry while the robot is stopped?
[1 mark]The lap is marked to within 10 cm after 200 cm of driving. If heading error were the only source, what is the largest heading error you could afford, in degrees to one decimal place?
[1 mark]An uncalibrated gyro has a bias of 0.4 deg/s. How many seconds does it take to build up a 2.9 degree heading error, to one decimal place?
[1 mark]Which of the steps in the lesson is optional?
[1 mark]The same lap driven in the other direction ends with a noticeably different error. What is the most likely cause?
Two metres of driving, back into the home zone under your own navigation, with my x: and my y: printed at the end and within 10 cm of the truth.
from bugbot import * import math connect() DT = 0.1 # calibrate, then drive the lap, updating every tick
The hint students can ask for: Two metres of driving, then home on your own estimate: steer towards (0, 0) in your estimated frame with the inverse kinematics from U2. If the estimate is good you arrive; if it is not, you do not, which is the test. Calibrate the gyro before you move: it costs five seconds and buys most of the accuracy.
from bugbot import *
import math
connect()
DT = 0.1
V_MAX, V_LAT = 20.0, 15.0
rates = []
for i in range(40):
rates.append(imu()[1])
wait(DT)
bias = sum(rates) / len(rates)
x = y = h = 0.0
def step(n=1):
global x, y, h
for i in range(n):
vx, vy = flow()
rate = imu()[1] - bias
a = math.radians(h + 0.5 * rate * DT)
x += (vx * math.cos(a) + vy * math.sin(a)) * DT
y += (-vx * math.sin(a) + vy * math.cos(a)) * DT
h += rate * DT
plot("x", x)
plot("y", y)
wait(DT)
def leg(ticks):
forward(75)
step(ticks)
stop()
step(4)
def turn_to(target):
"""Turn until our own estimate says we are facing the target heading."""
drive(0, 0, 55)
while abs((h - target + 180) % 360 - 180) > 4:
step()
stop()
step(4)
def go_to(tx, ty):
"""Home in on a point in our own estimated frame, through the inverse kinematics."""
for tick in range(300):
dx, dy = tx - x, ty - y
gap = math.hypot(dx, dy)
if gap < 4:
break
speed = min(13.0, 0.6 * gap)
wx, wy = speed * dx / gap, speed * dy / gap
a = math.radians(h)
drive(100 * (wx * math.sin(a) + wy * math.cos(a)) / V_MAX,
100 * (wx * math.cos(a) - wy * math.sin(a)) / V_LAT, 0)
step()
stop()
step(4)
leg(45)
turn_to(180)
leg(45)
turn_to(360)
h -= 360
leg(45)
turn_to(180)
leg(30)
# home on the estimate, not on the truth
go_to(0.0, 0.0)
print("my x:", round(x, 1))
print("my y:", round(y, 1))
Any program that meets the task's checks is marked correct in the simulator; this is one way, not the only way.