Mapping · University · about 30 min
Why the cells hold a log odds and not a probability, and what the clamp is for.
[1 mark]What does this program print?
import math p = 0.7 l = math.log(p / (1 - p)) print(round(l, 2)) print(round(1.0 / (1.0 + math.exp(-l)), 2))
0.85 0.7
The odds are 0.7 / 0.3 = 7/3, and log(7/3) = 0.85, which is L_OCC. The logistic function turns it back into 0.7.
[1 mark]What does this program print?
import math
L_OCC, L_FREE, L_MAX = 0.85, -0.4, 10.0
l = 0.0
for update in (L_OCC, L_OCC, L_FREE, L_OCC, L_FREE):
l = max(-L_MAX, min(L_MAX, l + update))
print(round(l, 2), round(1.0 / (1.0 + math.exp(-l)), 3))
1.75 0.852
Three hits and two pass-throughs add to 3 x 0.85 - 2 x 0.4 = 1.75, and 1 / (1 + exp(-1.75)) = 0.852. No multiplication and no normaliser.
[1 mark]Why do occupancy grids store log odds rather than probabilities?
[1 mark]Why is |L_OCC| larger than |L_FREE| in almost every implementation?
[1 mark]A mapper steps along each beam in half cells and adds L_FREE = -0.4 at every step. What is one beam passing through a cell really worth?
[1 mark]What is the main purpose of clamping each cell's log odds to plus or minus 10?
[1 mark]A cell starts unknown at log odds 0 and receives only hits of +0.85, with a clamp at 10. How many hits does it take to reach the clamp?
[1 mark]The function log(p / (1 - p)) has another standard name, the inverse of the logistic function. What is it?
Print p one:, the probability a cell is occupied after one hit starting from an empty map. Then take 25 readings, updating a grid in log odds with a clamp at 10 and each cell changed at most once per reading, and print wall l: and wall p: for the cell the wall is in.
from bugbot import * import math connect() CELL = 5.0 L_OCC, L_FREE, L_MAX = 0.85, -0.4, 10.0 X0, Y0 = 100.0, 50.0
The hint students can ask for: Each hit adds 0.85 to the cell's log odds and each pass-through subtracts 0.4, and the total is held between -10 and +10. Turning a log odds back into a probability is the logistic function; one hit from an empty map is that function of 0.85.
from bugbot import *
import math
connect()
CELL = 5.0
L_OCC, L_FREE, L_MAX = 0.85, -0.4, 10.0
X0, Y0 = 100.0, 50.0
def p_of(l):
return 1.0 / (1.0 + math.exp(-l))
print("p one:", round(p_of(L_OCC), 4))
grid = {}
def bump(key, amount):
grid[key] = max(-L_MAX, min(L_MAX, grid.get(key, 0.0) + amount))
for i in range(25):
d = distance()
free = set() # each cell the ray crosses, once
r = 0.0
while r < d - CELL:
free.add((int(X0 / CELL), int((Y0 + r) / CELL)))
r += CELL / 2
for key in free:
bump(key, L_FREE)
bump((int(X0 / CELL), int((Y0 + d) / CELL)), L_OCC)
wait(0.1)
wall = grid[(int(X0 / CELL), 30)]
print("wall l:", round(wall, 2))
print("wall p:", round(p_of(wall), 5))
Any program that meets the task's checks is marked correct in the simulator; this is one way, not the only way.