|
9 | 9 | import numpy as np |
10 | 10 | import math |
11 | 11 | import copy |
| 12 | +import itertools |
12 | 13 | import matplotlib.pyplot as plt |
13 | 14 |
|
14 | 15 |
|
15 | | -# EKF state covariance |
16 | | -Cx = np.diag([0.5, 0.5, math.radians(30.0)])**2 |
17 | | - |
18 | 16 | # Simulation parameter |
19 | 17 | Qsim = np.diag([0.2, math.radians(1.0)])**2 |
20 | 18 | Rsim = np.diag([1.0, math.radians(10.0)])**2 |
|
31 | 29 | show_animation = True |
32 | 30 |
|
33 | 31 |
|
| 32 | +class Edge(): |
| 33 | + |
| 34 | + def __init__(self): |
| 35 | + self.e = np.zeros((3, 1)) |
| 36 | + |
| 37 | + |
| 38 | +def calc_edges(xlist, zlist): |
| 39 | + |
| 40 | + edges = [] |
| 41 | + zids = list(itertools.combinations(range(len(zlist)), 2)) |
| 42 | + # print(zids) |
| 43 | + |
| 44 | + for (t, td) in zids: |
| 45 | + xt = xlist[0, t] |
| 46 | + yt = xlist[1, t] |
| 47 | + yawt = xlist[2, t] |
| 48 | + xtd = xlist[0, td] |
| 49 | + ytd = xlist[1, td] |
| 50 | + yawtd = xlist[2, td] |
| 51 | + |
| 52 | + dt = zlist[t][0, 0] |
| 53 | + anglet = zlist[t][1, 0] |
| 54 | + phit = zlist[t][2, 0] |
| 55 | + |
| 56 | + dtd = zlist[td][0, 0] |
| 57 | + angletd = zlist[td][0, 0] |
| 58 | + phitd = zlist[td][2, 0] |
| 59 | + |
| 60 | + edge = Edge() |
| 61 | + |
| 62 | + t1 = dt * math.cos(yawt + anglet) |
| 63 | + t2 = dtd * math.cos(yawtd + angletd) |
| 64 | + t3 = dt * math.sin(yawt + anglet) |
| 65 | + t4 = dtd * math.sin(yawtd + angletd) |
| 66 | + |
| 67 | + edge.e[0, 0] = xtd - xt - t1 + t2 |
| 68 | + edge.e[1, 0] = ytd - yt - t3 + t4 |
| 69 | + edge.e[2, 0] = yawtd - yawt - phit + phitd |
| 70 | + |
| 71 | + edges.append(edge) |
| 72 | + |
| 73 | + return edges |
| 74 | + |
| 75 | + |
34 | 76 | def graph_based_slam(xEst, PEst, u, z, hxDR, hz): |
35 | 77 |
|
36 | 78 | x_opt = copy.deepcopy(hxDR) |
37 | 79 |
|
38 | 80 | for itr in range(20): |
39 | | - # pos_edges = [] |
40 | | - |
41 | | - # # このfor文では、HalfEdgeからグラフの辺を作っていきます。 |
42 | | - # for i in range(len(actual_landmarks.positions)): # ランドマークごとにHalfEdgeからEdgeを作る |
43 | | - # es = list(filter(lambda e: e.landmark_id == i, obs_edges)) # 同じランドマークIDを持つHalfEdgeの抽出 |
44 | | - # ps = list(itertools.combinations(es,2)) # esの要素のペアを全通り作る |
45 | | - # for p in ps: |
46 | | - # pos_edges.append(Edge(p[0],p[1])) # エッジを登録 |
| 81 | + edges = calc_edges(x_opt, hz) |
| 82 | + print("nedges:", len(edges)) |
47 | 83 |
|
48 | 84 | n = len(hz) * 3 |
49 | 85 | H = np.zeros((n, n)) |
@@ -87,18 +123,19 @@ def observation(xTrue, xd, u, RFID): |
87 | 123 | xTrue = motion_model(xTrue, u) |
88 | 124 |
|
89 | 125 | # add noise to gps x-y |
90 | | - z = np.matrix(np.zeros((0, 3))) |
| 126 | + z = np.matrix(np.zeros((0, 4))) |
91 | 127 |
|
92 | 128 | for i in range(len(RFID[:, 0])): |
93 | 129 |
|
94 | 130 | dx = RFID[i, 0] - xTrue[0, 0] |
95 | 131 | dy = RFID[i, 1] - xTrue[1, 0] |
96 | 132 | d = math.sqrt(dx**2 + dy**2) |
97 | | - angle = pi_2_pi(math.atan2(dy, dx)) |
| 133 | + angle = pi_2_pi(math.atan2(dy, dx)) - xTrue[2, 0] |
| 134 | + phi = angle - xTrue[2, 0] |
98 | 135 | if d <= MAX_RANGE: |
99 | 136 | dn = d + np.random.randn() * Qsim[0, 0] # add noise |
100 | 137 | anglen = angle + np.random.randn() * Qsim[1, 1] # add noise |
101 | | - zi = np.matrix([dn, anglen, i]) |
| 138 | + zi = np.matrix([dn, anglen, phi, i]) |
102 | 139 | z = np.vstack((z, zi)) |
103 | 140 |
|
104 | 141 | # add noise to input |
@@ -141,11 +178,11 @@ def main(): |
141 | 178 |
|
142 | 179 | time = 0.0 |
143 | 180 |
|
144 | | - # RFID positions [x, y] |
145 | | - RFID = np.array([[10.0, -2.0], |
146 | | - [15.0, 10.0], |
147 | | - [3.0, 15.0], |
148 | | - [-5.0, 20.0]]) |
| 181 | + # RFID positions [x, y, yaw] |
| 182 | + RFID = np.array([[10.0, -2.0, 0.0], |
| 183 | + [15.0, 10.0, 0.0], |
| 184 | + [3.0, 15.0, 0.0], |
| 185 | + [-5.0, 20.0, 0.0]]) |
149 | 186 |
|
150 | 187 | # State Vector [x y yaw v]' |
151 | 188 | xEst = np.matrix(np.zeros((STATE_SIZE, 1))) |
|
0 commit comments