1111import matplotlib .pyplot as plt
1212
1313Cx = np .diag ([1.0 , 1.0 , math .radians (30.0 )])** 2
14+ Cz = np .diag ([1.0 , 1.0 ])** 2
15+
1416
1517# Simulation parameter
1618Qsim = np .diag ([0.2 ])** 2
@@ -110,7 +112,7 @@ def calc_LM_Pos(x, z):
110112 return zp
111113
112114
113- def calc_mahalanobis_dist (xAug , PAug ):
115+ def calc_mahalanobis_dist (xAug , PAug , z , iz ):
114116
115117 nLM = calc_n_LM (xAug )
116118
@@ -123,21 +125,50 @@ def calc_mahalanobis_dist(xAug, PAug):
123125 else :
124126 lm = xAug [POSE_SIZE + LM_SIZE *
125127 i : POSE_SIZE + LM_SIZE * (i + 1 ), :]
126- # y, S, H = calc_innovation(lm, xAug, PAug, z[iz, 0:2], il )
127- # mdist=[mdist y'* inv(S)*y];%マハラノビス距離の計算
128+ y , S , H = calc_innovation (lm , xAug , PAug , z [iz , 0 :2 ], i )
129+ mdist . append ( y . T * np . linalg . inv (S ) * y )
128130
129131 return mdist
130132
131- # function [y,S,H]=CalcInnovation(lm,xEst,PEst,z,LMId)
132- # %対応付け結果からイノベーションを計算する関数
133- # global Q;
134- # delta=lm-xEst(1:2);
135- # q=delta'*delta;
136- # zangle=atan2(delta(2),delta(1))-xEst(3);
137- # zp=[sqrt(q) PI2PI(zangle)];%観測値の予測
138- # y=(z-zp)';
139- # H=jacobH(q,delta,xEst,LMId);
140- # S=H*PEst*H'+Q;
133+
134+ def calc_innovation (lm , xEst , PEst , z , LMid ):
135+ delta = lm - xEst [0 :2 ]
136+ q = (delta .T * delta )[0 , 0 ]
137+ zangle = math .atan2 (delta [1 ], delta [0 ]) - xEst [2 ]
138+ zp = [math .sqrt (q ), pi_2_pi (zangle )]
139+ y = (z - zp ).T
140+ H = jacobH (q , delta , xEst , LMid + 1 )
141+ S = H * PEst * H .T + Cz
142+
143+ return y , S , H
144+
145+
146+ def jacobH (q , delta , x , i ):
147+ sq = math .sqrt (q )
148+ G = np .matrix ([[- sq * delta [0 , 0 ], - sq * delta [1 , 0 ], 0 , sq * delta [0 , 0 ], sq * delta [1 , 0 ]],
149+ [delta [1 , 0 ], - delta [0 , 0 ], - 1.0 , - delta [1 , 0 ], delta [0 , 0 ]]])
150+
151+ G = G / q
152+ nLM = calc_n_LM (x )
153+ F1 = np .hstack ((np .eye (3 ), np .zeros ((3 , 2 * nLM ))))
154+ F2 = np .hstack ((np .zeros ((2 , 3 )), np .zeros ((2 , 2 * (i - 1 ))),
155+ np .eye (2 ), np .zeros ((2 , 2 * nLM - 2 * i ))))
156+
157+ F = np .vstack ((F1 , F2 ))
158+
159+ H = G * F
160+
161+ return H
162+
163+
164+ def pi_2_pi (angle ):
165+ while (angle > math .pi ):
166+ angle = angle - 2.0 * math .pi
167+
168+ while (angle < - math .pi ):
169+ angle = angle + 2.0 * math .pi
170+
171+ return angle
141172
142173
143174def ekf_slam (xEst , PEst , u , z ):
@@ -159,7 +190,7 @@ def ekf_slam(xEst, PEst, u, z):
159190 PAug = np .vstack ((np .hstack ((PEst , np .zeros ((len (xEst ), LM_SIZE )))),
160191 np .hstack ((np .zeros ((LM_SIZE , len (xEst ))), initP ))))
161192
162- mah_dists = calc_mahalanobis_dist (xAug , PAug )
193+ mah_dists = calc_mahalanobis_dist (xAug , PAug , z , iz )
163194 minid = mah_dists .index (min (mah_dists ))
164195 # print(minid)
165196
@@ -171,18 +202,16 @@ def ekf_slam(xEst, PEst, u, z):
171202 else :
172203 print ("Old LM" )
173204
174- # print("DB LM")
175- # lm=xEst(4+2*(I-1):5+2*(I-1));%対応付けられたランドマークデータの取得
176- # %イノベーションの計算
177- # [y,S,H]=CalcInnovation(lm,xEst,PEst,z(iz,1:2),I);
178- # K = PEst*H'*inv(S);
179- # xEst = xEst + K*y;
180- # PEst = (eye(size(xEst,1)) - K*H)*PEst;
181- # end
205+ lm = xEst [POSE_SIZE + LM_SIZE *
206+ iz : POSE_SIZE + LM_SIZE * (iz + 1 ), :]
207+ y , S , H = calc_innovation (lm , xEst , PEst , z [iz , 0 :2 ], iz )
208+
209+ K = PEst * H .T * np .linalg .inv (S )
210+ xEst = xEst + K * y
211+ PEst = (np .eye (len (xEst )) - K * H ) * PEst
182212
183- # xEst(3)=PI2PI( xEst(3));%角度補正
213+ xEst [ 2 ] = pi_2_pi ( xEst [ 2 ])
184214
185- print (len (xEst ))
186215 return xEst , PEst
187216
188217
0 commit comments