아래는 1D Localization 측정 및 이동에 대한 코드입니다.
#Modify the previous code so that the robot senses red twice.
p=[0.2, 0.2, 0.2, 0.2, 0.2]
world=['green', 'red', 'red', 'green', 'green']
measurements = ['red', 'red']
motions = [1,1]
pHit = 0.6
pMiss = 0.2
pExact = 0.8
pOvershoot = 0.1
pUndershoot = 0.1
def sense(p, Z):
q=[]
for i in range(len(p)):
hit = (Z == world[i])
q.append(p[i] * (hit * pHit + (1-hit) * pMiss))
s = sum(q)
for i in range(len(q)):
q[i] = q[i] / s
return q
def move(p, U):
q = []
for i in range(len(p)):
s = pExact * p[(i-U) % len(p)]
s = s + pOvershoot * p[(i-U-1) % len(p)]
s = s + pUndershoot * p[(i-U+1) % len(p)]
q.append(s)
return q
for k in range(len(measurements)):
p = sense(p, measurements[k])
p = move(p, motions[k])
print p
1D 지도의 각 셀에 대한 확률 리스트 p
, 지도 world
, 측정 값 리스트 measurements
, 이동 리스트 motions
, 센서가 일치/불일치 할 확률 pHit
/pMiss
, 제대로 이동할 확률 pExact
, 한 칸 더 이동할 확률 pOvershoot
, 한 칸 덜 이동할 확률 pUndershoot
입니다. sense(p, Z)
함수는 측정 값에 따라 product를 수행하고 renormalize 합니다. move(p, U)
함수는 이동 방향으로 convolution 하며, 로봇은 측정 후 이동합니다.
이를 토대로 2D Localization을 만드는 게 이번 과제입니다. 다음은 2D Localization 코드 템플릿입니다.
# The function localize takes the following arguments:
#
# colors:
# 2D list, each entry either 'R' (for red cell) or 'G' (for green cell)
#
# measurements:
# list of measurements taken by the robot, each entry either 'R' or 'G'
#
# motions:
# list of actions taken by the robot, each entry of the form [dy,dx],
# where dx refers to the change in the x-direction (positive meaning
# movement to the right) and dy refers to the change in the y-direction
# (positive meaning movement downward)
# NOTE: the *first* coordinate is change in y; the *second* coordinate is
# change in x
#
# sensor_right:
# float between 0 and 1, giving the probability that any given
# measurement is correct; the probability that the measurement is
# incorrect is 1-sensor_right
#
# p_move:
# float between 0 and 1, giving the probability that any given movement
# command takes place; the probability that the movement command fails
# (and the robot remains still) is 1-p_move; the robot will NOT overshoot
# its destination in this exercise
#
# The function should RETURN (not just show or print) a 2D list (of the same
# dimensions as colors) that gives the probabilities that the robot occupies
# each cell in the world.
#
# Compute the probabilities by assuming the robot initially has a uniform
# probability of being in any cell.
#
# Also assume that at each step, the robot:
# 1) first makes a movement,
# 2) then takes a measurement.
#
# Motion:
# [0,0] - stay
# [0,1] - right
# [0,-1] - left
# [1,0] - down
# [-1,0] - up
def localize(colors,measurements,motions,sensor_right,p_move):
# initializes p to a uniform distribution over a grid of the same dimensions as colors
pinit = 1.0 / float(len(colors)) / float(len(colors[0]))
p = [[pinit for row in range(len(colors[0]))] for col in range(len(colors))]
# >>> Insert your code here <<<
return p
def show(p):
rows = ['[' + ','.join(map(lambda x: '{0:.5f}'.format(x),r)) + ']' for r in p]
print '[' + ',\n '.join(rows) + ']'
#############################################################
# For the following test case, your output should be
# [[0.01105, 0.02464, 0.06799, 0.04472, 0.02465],
# [0.00715, 0.01017, 0.08696, 0.07988, 0.00935],
# [0.00739, 0.00894, 0.11272, 0.35350, 0.04065],
# [0.00910, 0.00715, 0.01434, 0.04313, 0.03642]]
# (within a tolerance of +/- 0.001 for each entry)
colors = [['R','G','G','R','R'],
['R','R','G','R','R'],
['R','R','G','G','R'],
['R','R','R','R','R']]
measurements = ['G','G','G','G','G']
motions = [[0,0],[0,1],[1,0],[1,0],[0,1]]
p = localize(colors,measurements,motions,sensor_right = 0.7, p_move = 0.8)
show(p) # displays your answer
로봇은 1D와는 반대로 이동, 측정 순으로 움직이며, pHit
은 sensor_right
, pMiss
는 1 - sensor_right
으로 간소화 되었습니다. pExact
는 p_move
가 되었으며, 1 - p_move
의 확률에 over/undershoot이 발생하는 대신 이동 불가로 변경되었습니다. 마지막 측정을 마친 뒤 확률을 출력했을 때 테스트 케이스 아웃풋과 +-0.001의 오차 이내로 일치하는 것이 목표입니다.
추가 테스트 케이스는 다음과 같습니다. 제출하기를 누르면 추가 테스트 케이스까지 검사한 뒤, 모두 정답이어야만 통과할 수 있습니다.
# test 1
colors = [['G', 'G', 'G'],
['G', 'R', 'G'],
['G', 'G', 'G']]
measurements = ['R']
motions = [[0,0]]
sensor_right = 1.0
p_move = 1.0
p = localize(colors,measurements,motions,sensor_right,p_move)
correct_answer = (
[[0.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 0.0]])
# test 2
colors = [['G', 'G', 'G'],
['G', 'R', 'R'],
['G', 'G', 'G']]
measurements = ['R']
motions = [[0,0]]
sensor_right = 1.0
p_move = 1.0
p = localize(colors,measurements,motions,sensor_right,p_move)
correct_answer = (
[[0.0, 0.0, 0.0],
[0.0, 0.5, 0.5],
[0.0, 0.0, 0.0]])
# test 3
colors = [['G', 'G', 'G'],
['G', 'R', 'R'],
['G', 'G', 'G']]
measurements = ['R']
motions = [[0,0]]
sensor_right = 0.8
p_move = 1.0
p = localize(colors,measurements,motions,sensor_right,p_move)
correct_answer = (
[[0.06666666666, 0.06666666666, 0.06666666666],
[0.06666666666, 0.26666666666, 0.26666666666],
[0.06666666666, 0.06666666666, 0.06666666666]])
# test 4
colors = [['G', 'G', 'G'],
['G', 'R', 'R'],
['G', 'G', 'G']]
measurements = ['R', 'R']
motions = [[0,0], [0,1]]
sensor_right = 0.8
p_move = 1.0
p = localize(colors,measurements,motions,sensor_right,p_move)
correct_answer = (
[[0.03333333333, 0.03333333333, 0.03333333333],
[0.13333333333, 0.13333333333, 0.53333333333],
[0.03333333333, 0.03333333333, 0.03333333333]])
# test 5
colors = [['G', 'G', 'G'],
['G', 'R', 'R'],
['G', 'G', 'G']]
measurements = ['R', 'R']
motions = [[0,0], [0,1]]
sensor_right = 1.0
p_move = 1.0
p = localize(colors,measurements,motions,sensor_right,p_move)
correct_answer = (
[[0.0, 0.0, 0.0],
[0.0, 0.0, 1.0],
[0.0, 0.0, 0.0]])
# test 6
colors = [['G', 'G', 'G'],
['G', 'R', 'R'],
['G', 'G', 'G']]
measurements = ['R', 'R']
motions = [[0,0], [0,1]]
sensor_right = 0.8
p_move = 0.5
p = localize(colors,measurements,motions,sensor_right,p_move)
correct_answer = (
[[0.0289855072, 0.0289855072, 0.0289855072],
[0.0724637681, 0.2898550724, 0.4637681159],
[0.0289855072, 0.0289855072, 0.0289855072]])
# test 7
colors = [['G', 'G', 'G'],
['G', 'R', 'R'],
['G', 'G', 'G']]
measurements = ['R', 'R']
motions = [[0,0], [0,1]]
sensor_right = 1.0
p_move = 0.5
p = localize(colors,measurements,motions,sensor_right,p_move)
correct_answer = (
[[0.0, 0.0, 0.0],
[0.0, 0.33333333, 0.66666666],
[0.0, 0.0, 0.0]])
다음은 제가 작성한 코드입니다.
# h = length of colors
# w = length of colors[0]
# [dy, dx] from motions
def move(p, h, w, dy, dx, p_move):
q = []
for y in range(h):
q.append([])
for x in range(w):
# balancing
# q[y][x] = exact move rate * p[y-dy][x-dx] + no move rate * p[y][x]
val = p[(y-dy)%h][(x-dx)%w] * p_move
val += p[y][x] * (1 - p_move)
q[y].append(val)
return q
# measurement from measurements
def sense(p, h, w, colors, measurement, sensor_right):
q = []
sum_of_q = 0 # for renormalize
for y, row in enumerate(colors):
q.append([])
for x, cell in enumerate(row):
hit = measurement == cell
val = p[y][x]
val *= sensor_right if hit else (1 - sensor_right)
q[y].append(val)
sum_of_q += val
# renormalize
for y in range(h):
for x in range(w):
q[y][x] /= sum_of_q
return q
def localize(colors,measurements,motions,sensor_right,p_move):
# initializes p to a uniform distribution over a grid of the same dimensions as colors
h = len(colors)
w = len(colors[0])
pinit = 1.0 / h / w
p = [[pinit for _ in range(w)] for _ in range(h)]
for measurement, (dy, dx) in zip(measurements, motions):
# move
p = move(p, h, w, dy, dx, p_move)
# ... and measure
p = sense(p, h, w, colors, measurement, sensor_right)
return p
def show(p):
rows = ['[' + ','.join(map(lambda x: '{0:.5f}'.format(x),r)) + ']' for r in p]
print '[' + ',\n '.join(rows) + ']'
colors = [['R','G','G','R','R'],
['R','R','G','R','R'],
['R','R','G','G','R'],
['R','R','R','R','R']]
measurements = ['G','G','G','G','G']
motions = [[0,0],[0,1],[1,0],[1,0],[0,1]]
p = localize(colors,measurements,motions,sensor_right = 0.7, p_move = 0.8)
show(p) # displays your answer
차원이 늘어나면 for loop 하나 더 해주는 식입니다. 그래서 이러한 방식의 Localization은 메모리 크기가 지수적으로 상승한다는 단점이 있습니다.
'Robotics' 카테고리의 다른 글
39일차 - 2차원 Kalman Filter, Position과 Velocity의 상관관계 (0) | 2020.08.12 |
---|---|
38일차 - 칼만 필터 이동과 예측 알고리즘, 파이썬 코드 (0) | 2020.08.11 |
36일차 - 조건부확률, 베이즈 정리, 1D Localization (0) | 2020.08.06 |
35일차 - ROS에서 dynamixel_sdk include 하기 (0) | 2020.08.05 |
34일차 - navigation.launch summary (0) | 2020.08.04 |