CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download
Project: test
Views: 91872
1
# -*- coding: utf-8 -*-
2
"""
3
Created on Sat Jun 27 19:45:45 2015
4
5
@author: Roger
6
"""
7
8
import numpy as np
9
import numpy.random
10
from numpy.random import randn, random, uniform
11
import scipy.stats
12
13
14
class RobotLocalizationParticleFilter(object):
15
16
def __init__(self, N, x_dim, y_dim, landmarks, measure_std_error):
17
self.particles = np.empty((N, 3)) # x, y, heading
18
self.N = N
19
self.x_dim = x_dim
20
self.y_dim = y_dim
21
self.landmarks = landmarks
22
self.R = measure_std_error
23
24
# distribute particles randomly with uniform weight
25
self.weights = np.empty(N)
26
#self.weights.fill(1./N)
27
self.particles[:, 0] = uniform(0, x_dim, size=N)
28
self.particles[:, 1] = uniform(0, y_dim, size=N)
29
self.particles[:, 2] = uniform(0, 2*np.pi, size=N)
30
31
32
def create_uniform_particles(self, x_range, y_range, hdg_range):
33
self.particles[:, 0] = uniform(x_range[0], x_range[1], size=N)
34
self.particles[:, 1] = uniform(y_range[0], y_range[1], size=N)
35
self.particles[:, 2] = uniform(hdg_range[0], hdg_range[1], size=N)
36
self.particles[:, 2] %= 2 * np.pi
37
38
def create_gaussian_particles(self, mean, var):
39
self.particles[:, 0] = mean[0] + randn(self.N)*var[0]
40
self.particles[:, 1] = mean[1] + randn(self.N)*var[1]
41
self.particles[:, 2] = mean[2] + randn(self.N)*var[2]
42
self.particles[:, 2] %= 2 * np.pi
43
44
45
def predict(self, u, std, dt=1.):
46
""" move according to control input u (heading change, velocity)
47
with noise std"""
48
49
self.particles[:, 2] += u[0] + randn(self.N) * std[0]
50
self.particles[:, 2] %= 2 * np.pi
51
52
d = u[1]*dt + randn(self.N) * std[1]
53
self.particles[:, 0] += np.cos(self.particles[:, 2]) * d
54
self.particles[:, 1] += np.sin(self.particles[:, 2]) * d
55
56
57
def update(self, z):
58
self.weights.fill(1.)
59
for i, landmark in enumerate(self.landmarks):
60
distance = np.linalg.norm(self.particles[:, 0:2] - landmark, axis=1)
61
self.weights *= scipy.stats.norm(distance, self.R).pdf(z[i])
62
#self.weights *= Gaussian(distance, self.R, z[i])
63
64
self.weights += 1.e-300
65
self.weights /= sum(self.weights) # normalize
66
67
68
def neff(self):
69
return 1. / np.sum(np.square(self.weights))
70
71
72
def resample(self):
73
cumulative_sum = np.cumsum(self.weights)
74
cumulative_sum[-1] = 1. # avoid round-off error
75
indexes = np.searchsorted(cumulative_sum, random(self.N))
76
77
# resample according to indexes
78
self.particles = self.particles[indexes]
79
self.weights = self.weights[indexes]
80
self.weights /= np.sum(self.weights) # normalize
81
82
83
def resample_from_index(self, indexes):
84
assert len(indexes) == self.N
85
86
self.particles = self.particles[indexes]
87
self.weights = self.weights[indexes]
88
self.weights /= np.sum(self.weights)
89
90
91
def estimate(self):
92
""" returns mean and variance """
93
pos = self.particles[:, 0:2]
94
mu = np.average(pos, weights=self.weights, axis=0)
95
var = np.average((pos - mu)**2, weights=self.weights, axis=0)
96
97
return mu, var
98
99
def mean(self):
100
""" returns weighted mean position"""
101
return np.average(self.particles[:, 0:2], weights=self.weights, axis=0)
102
103
104
105
def residual_resample(w):
106
107
N = len(w)
108
109
w_ints = np.floor(N*w).astype(int)
110
residual = w - w_ints
111
residual /= sum(residual)
112
113
indexes = np.zeros(N, 'i')
114
k = 0
115
for i in range(N):
116
for j in range(w_ints[i]):
117
indexes[k] = i
118
k += 1
119
cumsum = np.cumsum(residual)
120
cumsum[N-1] = 1.
121
for j in range(k, N):
122
indexes[j] = np.searchsorted(cumsum, random())
123
124
return indexes
125
126
127
128
def residual_resample2(w):
129
130
N = len(w)
131
132
w_ints =np.floor(N*w).astype(int)
133
134
R = np.sum(w_ints)
135
m_rdn = N - R
136
137
Ws = (N*w - w_ints)/ m_rdn
138
indexes = np.zeros(N, 'i')
139
i = 0
140
for j in range(N):
141
for k in range(w_ints[j]):
142
indexes[i] = j
143
i += 1
144
cumsum = np.cumsum(Ws)
145
cumsum[N-1] = 1 # just in case
146
147
for j in range(i, N):
148
indexes[j] = np.searchsorted(cumsum, random())
149
150
return indexes
151
152
153
154
def systemic_resample(w):
155
N = len(w)
156
Q = np.cumsum(w)
157
indexes = np.zeros(N)
158
t = np.linspace(0, 1-1/N, N) + random()/N
159
160
i, j = 0, 0
161
while i < N and j < N:
162
while Q[j] < t[i]:
163
j += 1
164
indexes[i] = j
165
i += 1
166
167
return indexes
168
169
170
171
172
173
def Gaussian(mu, sigma, x):
174
175
# calculates the probability of x for 1-dim Gaussian with mean mu and var. sigma
176
g = (np.exp(-((mu - x) ** 2) / (sigma ** 2) / 2.0) /
177
np.sqrt(2.0 * np.pi * (sigma ** 2)))
178
for i in range(len(g)):
179
g[i] = max(g[i], 1.e-229)
180
return g
181
182
if __name__ == '__main__':
183
184
DO_PLOT_PARTICLES = False
185
from numpy.random import seed
186
import matplotlib.pyplot as plt
187
188
#plt.figure()
189
190
seed(5)
191
for count in range(1):
192
print()
193
print(count)
194
#numpy.random.set_state(fail_state)
195
#if count == 12:
196
# #fail_state = numpy.random.get_state()
197
# DO_PLOT_PARTICLES = True
198
199
N = 4000
200
sensor_std_err = .1
201
landmarks = np.array([[-1, 2], [2,4], [10,6], [18,25]])
202
NL = len(landmarks)
203
204
#landmarks = [[-1, 2], [2,4]]
205
206
pf = RobotLocalizationParticleFilter(N, 20, 20, landmarks, sensor_std_err)
207
#pf.create_gaussian_particles([3, 2, 0], [5, 5, 2])
208
pf.create_uniform_particles((0,20), (0,20), (0, 6.28))
209
210
if DO_PLOT_PARTICLES:
211
plt.scatter(pf.particles[:, 0], pf.particles[:, 1], alpha=.2, color='g')
212
213
xs = []
214
for x in range(18):
215
zs = []
216
pos=(x+1, x+1)
217
218
for landmark in landmarks:
219
d = np.sqrt((landmark[0]-pos[0])**2 + (landmark[1]-pos[1])**2)
220
zs.append(d + randn()*sensor_std_err)
221
222
223
zs = np.linalg.norm(landmarks - pos, axis=1) + randn(NL)*sensor_std_err
224
225
226
# move diagonally forward to (x+1, x+1)
227
pf.predict((0.00, 1.414), (.2, .05))
228
pf.update(z=zs)
229
if x == 0:
230
print(max(pf.weights))
231
#while abs(pf.neff() -N) < .1:
232
# print('neffing')
233
# pf.create_uniform_particles((0,20), (0,20), (0, 6.28))
234
# pf.update(z=zs)
235
#print(pf.neff())
236
#indexes = residual_resample2(pf.weights)
237
indexes = systemic_resample(pf.weights)
238
239
pf.resample_from_index(indexes)
240
#pf.resample()
241
242
mu, var = pf.estimate()
243
xs.append(mu)
244
if DO_PLOT_PARTICLES:
245
plt.scatter(pf.particles[:, 0], pf.particles[:, 1], alpha=.2)
246
plt.scatter(pos[0], pos[1], marker='*', color='r')
247
plt.scatter(mu[0], mu[1], marker='s', color='r')
248
plt.pause(.01)
249
250
xs = np.array(xs)
251
plt.plot(xs[:, 0], xs[:, 1])
252
plt.show()
253
254