Skip to content

Commit 2917dc2

Browse files
committed
almost done but needs code cleaning
1 parent da306a9 commit 2917dc2

File tree

1 file changed

+86
-42
lines changed

1 file changed

+86
-42
lines changed

Localization/histogram_filter/histogram_filter.py

Lines changed: 86 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
33
Histogram Filter 2D localization example
44
5+
6+
In this simulation, x,y are unknown, yaw is known.
7+
8+
Initial position is not needed.
9+
510
author: Atsushi Sakai (@Atsushi_twi)
611
712
"""
@@ -11,29 +16,59 @@
1116
import matplotlib.pyplot as plt
1217
import copy
1318
from scipy.stats import norm
19+
from scipy.ndimage import gaussian_filter
20+
21+
# Parameters
22+
NOISE_RANGE = 2.0 # [m] 1σ range noise parameter
23+
NOISE_SPEED = 0.5 # [m/s] 1σ speed noise parameter
1424

1525
EXTEND_AREA = 10.0 # [m] grid map extention length
1626
SIM_TIME = 50.0 # simulation time [s]
1727
DT = 0.1 # time tick [s]
1828
MAX_RANGE = 10.0 # maximum observation range
29+
MOTION_STD = 1.0
30+
RANGE_STD = 3.0 # standard diviation for gaussian distribution
1931

2032
show_animation = True
2133

2234

23-
def observation_update(gmap, z, std, xyreso, minx, miny):
35+
class grid_map():
36+
37+
def __init__(self):
38+
self.data = None
39+
self.xyreso = None
40+
self.minx = None
41+
self.miny = None
42+
self.maxx = None
43+
self.maxx = None
44+
45+
46+
def histogram_filter_localization(gmap, u, z, yaw, dx, dy):
47+
48+
gmap, dx, dy = motion_update(gmap, u, yaw, dx, dy)
49+
50+
gmap = observation_update(gmap, z, RANGE_STD)
51+
52+
return gmap.data, dx, dy
53+
54+
55+
def observation_update(gmap, z, std):
2456

2557
for iz in range(z.shape[0]):
26-
for ix in range(len(gmap)):
27-
for iy in range(len(gmap[ix])):
58+
for ix in range(len(gmap.data)):
59+
for iy in range(len(gmap.data[ix])):
2860

61+
# observation range
2962
zr = z[iz, 0]
30-
x = ix * xyreso + minx
31-
y = iy * xyreso + miny
3263

64+
# predicted range
65+
x = ix * gmap.xyreso + gmap.minx
66+
y = iy * gmap.xyreso + gmap.miny
3367
d = math.sqrt((x - z[iz, 1])**2 + (y - z[iz, 2])**2)
3468

69+
# likelihood
3570
pdf = (1.0 - norm.cdf(abs(d - zr), 0.0, std))
36-
gmap[ix][iy] *= pdf
71+
gmap.data[ix][iy] *= pdf
3772

3873
gmap = normalize_probability(gmap)
3974

@@ -64,20 +99,16 @@ def motion_model(x, u):
6499
return x
65100

66101

67-
def draw_heatmap(data, minx, maxx, miny, maxy, xyreso):
68-
x, y = np.mgrid[slice(minx - xyreso / 2.0, maxx + xyreso / 2.0, xyreso),
69-
slice(miny - xyreso / 2.0, maxy + xyreso / 2.0, xyreso)]
70-
102+
def draw_heatmap(data, mx, my):
71103
maxp = max([max(igmap) for igmap in data])
72-
plt.pcolor(x, y, data, vmax=maxp, cmap=plt.cm.Blues)
104+
plt.pcolor(mx, my, data, vmax=maxp, cmap=plt.cm.Blues)
73105
plt.axis("equal")
74106

75107

76108
def observation(xTrue, u, RFID):
77109

78110
xTrue = motion_model(xTrue, u)
79111

80-
# add noise to gps x-y
81112
z = np.matrix(np.zeros((0, 3)))
82113

83114
for i in range(len(RFID[:, 0])):
@@ -86,69 +117,79 @@ def observation(xTrue, u, RFID):
86117
dy = xTrue[1, 0] - RFID[i, 1]
87118
d = math.sqrt(dx**2 + dy**2)
88119
if d <= MAX_RANGE:
89-
dn = d
120+
# add noise to range observation
121+
dn = d + np.random.randn() * NOISE_RANGE
90122
zi = np.matrix([dn, RFID[i, 0], RFID[i, 1]])
91123
z = np.vstack((z, zi))
92124

93-
return xTrue, z
125+
# add noise to speed
126+
ud = u[:, :]
127+
ud[0] += np.random.randn() * NOISE_SPEED
128+
129+
return xTrue, z, ud
94130

95131

96132
def normalize_probability(gmap):
97133

98-
sump = sum([sum(igmap) for igmap in gmap])
134+
sump = sum([sum(igmap) for igmap in gmap.data])
99135

100-
for i in range(len(gmap)):
101-
for ii in range(len(gmap[i])):
102-
gmap[i][ii] /= sump
136+
for i in range(len(gmap.data)):
137+
for ii in range(len(gmap.data[i])):
138+
gmap.data[i][ii] /= sump
103139

104140
return gmap
105141

106142

107143
def init_gmap(xyreso):
108144

109-
minx = -15.0
110-
miny = -5.0
111-
maxx = 15.0
112-
maxy = 25.0
113-
xw = int(round((maxx - minx) / xyreso))
114-
yw = int(round((maxy - miny) / xyreso))
145+
gmap = grid_map()
115146

116-
gmap = [[1.0 for i in range(yw)] for i in range(xw)]
147+
gmap.xyreso = xyreso
148+
gmap.minx = -15.0
149+
gmap.miny = -5.0
150+
gmap.maxx = 15.0
151+
gmap.maxy = 25.0
152+
gmap.xw = int(round((gmap.maxx - gmap.minx) / gmap.xyreso))
153+
gmap.yw = int(round((gmap.maxy - gmap.miny) / gmap.xyreso))
154+
155+
gmap.data = [[1.0 for i in range(gmap.yw)] for i in range(gmap.xw)]
117156
gmap = normalize_probability(gmap)
118157

119-
return gmap, minx, maxx, miny, maxy,
158+
return gmap
120159

121160

122161
def map_shift(gmap, xshift, yshift):
123162

124-
tgmap = copy.deepcopy(gmap)
163+
tgmap = copy.deepcopy(gmap.data)
125164

126-
lenx = len(gmap)
127-
leny = len(gmap[0])
165+
lenx = len(gmap.data)
166+
leny = len(gmap.data[0])
128167

129168
for ix in range(lenx):
130169
for iy in range(leny):
131170
nix = ix + xshift
132171
niy = iy + yshift
133172

134173
if nix >= 0 and nix < lenx and niy >= 0 and niy < leny:
135-
gmap[ix + xshift][iy + yshift] = tgmap[ix][iy]
174+
gmap.data[ix + xshift][iy + yshift] = tgmap[ix][iy]
136175

137176
return gmap
138177

139178

140-
def motion_update(gmap, u, yaw, dx, dy, xyreso, minx, miny):
179+
def motion_update(gmap, u, yaw, dx, dy):
141180

142181
dx += DT * math.cos(yaw) * u[0]
143182
dy += DT * math.sin(yaw) * u[0]
144183

145-
xshift = dx // xyreso
146-
yshift = dy // xyreso
184+
xshift = dx // gmap.xyreso
185+
yshift = dy // gmap.xyreso
147186

148187
if abs(xshift) >= 1.0 or abs(yshift) >= 1.0:
149188
gmap = map_shift(gmap, int(xshift), int(yshift))
150-
dx -= xshift * xyreso
151-
dy -= yshift * xyreso
189+
dx -= xshift * gmap.xyreso
190+
dy -= yshift * gmap.xyreso
191+
192+
gmap.data = gaussian_filter(gmap.data, sigma=MOTION_STD)
152193

153194
return gmap, dx, dy
154195

@@ -157,7 +198,6 @@ def main():
157198
print(__file__ + " start!!")
158199

159200
xyreso = 0.5 # xy grid resolution
160-
STD = 1.0 # standard diviation for gaussian distribution
161201

162202
# RFID positions [x, y]
163203
RFID = np.array([[10.0, 0.0],
@@ -169,24 +209,28 @@ def main():
169209

170210
xTrue = np.matrix(np.zeros((4, 1)))
171211

172-
gmap, minx, maxx, miny, maxy = init_gmap(xyreso)
212+
gmap = init_gmap(xyreso)
173213

174214
dx, dy = 0.0, 0.0
175215

216+
mx, my = np.mgrid[slice(gmap.minx - gmap.xyreso / 2.0, gmap.maxx + gmap.xyreso / 2.0, gmap.xyreso),
217+
slice(gmap.miny - gmap.xyreso / 2.0, gmap.maxy + gmap.xyreso / 2.0, gmap.xyreso)]
218+
176219
while SIM_TIME >= time:
177220
time += DT
178221

179222
u = calc_input()
180-
xTrue, z = observation(xTrue, u, RFID)
181223

182-
gmap, dx, dy = motion_update(
183-
gmap, u, xTrue[2, 0], dx, dy, xyreso, minx, miny)
224+
# Orientation is known in this simulation
225+
yaw = xTrue[2, 0]
226+
xTrue, z, ud = observation(xTrue, u, RFID)
184227

185-
gmap = observation_update(gmap, z, STD, xyreso, minx, miny)
228+
gmap.data, dx, dy = histogram_filter_localization(
229+
gmap, u, z, yaw, dx, dy)
186230

187231
if show_animation:
188232
plt.cla()
189-
draw_heatmap(gmap, minx, maxx, miny, maxy, xyreso)
233+
draw_heatmap(gmap.data, mx, my)
190234
plt.plot(xTrue[0, :], xTrue[1, :], "xr")
191235
plt.plot(RFID[:, 0], RFID[:, 1], ".k")
192236
for i in range(z.shape[0]):

0 commit comments

Comments
 (0)