|  |  |  | @ -14,16 +14,15 @@ from selfdrive.locationd.kalman.helpers.chi2_lookup import chi2_ppf | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def solve(a, b): | 
			
		
	
		
			
				
					|  |  |  |  |   if a.shape[0] == 1 and a.shape[1] == 1: | 
			
		
	
		
			
				
					|  |  |  |  |     #assert np.allclose(b/a[0][0], np.linalg.solve(a, b)) | 
			
		
	
		
			
				
					|  |  |  |  |     return b/a[0][0] | 
			
		
	
		
			
				
					|  |  |  |  |     return b / a[0][0] | 
			
		
	
		
			
				
					|  |  |  |  |   else: | 
			
		
	
		
			
				
					|  |  |  |  |     return np.linalg.solve(a, b) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def null(H, eps=1e-12): | 
			
		
	
		
			
				
					|  |  |  |  |   u, s, vh = np.linalg.svd(H) | 
			
		
	
		
			
				
					|  |  |  |  |   padding = max(0,np.shape(H)[1]-np.shape(s)[0]) | 
			
		
	
		
			
				
					|  |  |  |  |   null_mask = np.concatenate(((s <= eps), np.ones((padding,),dtype=bool)),axis=0) | 
			
		
	
		
			
				
					|  |  |  |  |   padding = max(0, np.shape(H)[1] - np.shape(s)[0]) | 
			
		
	
		
			
				
					|  |  |  |  |   null_mask = np.concatenate(((s <= eps), np.ones((padding,), dtype=bool)), axis=0) | 
			
		
	
		
			
				
					|  |  |  |  |   null_space = np.compress(null_mask, vh, axis=0) | 
			
		
	
		
			
				
					|  |  |  |  |   return np.transpose(null_space) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -41,9 +40,9 @@ def gen_code(name, f_sym, dt_sym, x_sym, obs_eqs, dim_x, dim_err, eskf_params=No | 
			
		
	
		
			
				
					|  |  |  |  |     f_err_sym = eskf_params[3] | 
			
		
	
		
			
				
					|  |  |  |  |     x_err_sym = eskf_params[4] | 
			
		
	
		
			
				
					|  |  |  |  |   else: | 
			
		
	
		
			
				
					|  |  |  |  |     nom_x = sp.MatrixSymbol('nom_x',dim_x,1) | 
			
		
	
		
			
				
					|  |  |  |  |     true_x = sp.MatrixSymbol('true_x',dim_x,1) | 
			
		
	
		
			
				
					|  |  |  |  |     delta_x = sp.MatrixSymbol('delta_x',dim_x,1) | 
			
		
	
		
			
				
					|  |  |  |  |     nom_x = sp.MatrixSymbol('nom_x', dim_x, 1) | 
			
		
	
		
			
				
					|  |  |  |  |     true_x = sp.MatrixSymbol('true_x', dim_x, 1) | 
			
		
	
		
			
				
					|  |  |  |  |     delta_x = sp.MatrixSymbol('delta_x', dim_x, 1) | 
			
		
	
		
			
				
					|  |  |  |  |     err_function_sym = sp.Matrix(nom_x + delta_x) | 
			
		
	
		
			
				
					|  |  |  |  |     inv_err_function_sym = sp.Matrix(true_x - nom_x) | 
			
		
	
		
			
				
					|  |  |  |  |     err_eqs = [err_function_sym, nom_x, delta_x] | 
			
		
	
	
		
			
				
					|  |  |  | @ -63,8 +62,8 @@ def gen_code(name, f_sym, dt_sym, x_sym, obs_eqs, dim_x, dim_err, eskf_params=No | 
			
		
	
		
			
				
					|  |  |  |  |     dim_augment_err = msckf_params[3] | 
			
		
	
		
			
				
					|  |  |  |  |     N = msckf_params[4] | 
			
		
	
		
			
				
					|  |  |  |  |     feature_track_kinds = msckf_params[5] | 
			
		
	
		
			
				
					|  |  |  |  |     assert dim_main + dim_augment*N == dim_x | 
			
		
	
		
			
				
					|  |  |  |  |     assert dim_main_err + dim_augment_err*N == dim_err | 
			
		
	
		
			
				
					|  |  |  |  |     assert dim_main + dim_augment * N == dim_x | 
			
		
	
		
			
				
					|  |  |  |  |     assert dim_main_err + dim_augment_err * N == dim_err | 
			
		
	
		
			
				
					|  |  |  |  |   else: | 
			
		
	
		
			
				
					|  |  |  |  |     msckf = False | 
			
		
	
		
			
				
					|  |  |  |  |     dim_main = dim_x | 
			
		
	
	
		
			
				
					|  |  |  | @ -123,7 +122,7 @@ def gen_code(name, f_sym, dt_sym, x_sym, obs_eqs, dim_x, dim_err, eskf_params=No | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |       He_str = 'NULL' | 
			
		
	
		
			
				
					|  |  |  |  |       # ea_dim = 1 # not really dim of ea but makes c function work | 
			
		
	
		
			
				
					|  |  |  |  |     maha_thresh = chi2_ppf(0.95, int(h_sym.shape[0])) # mahalanobis distance for outlier detection | 
			
		
	
		
			
				
					|  |  |  |  |     maha_thresh = chi2_ppf(0.95, int(h_sym.shape[0]))  # mahalanobis distance for outlier detection | 
			
		
	
		
			
				
					|  |  |  |  |     maha_test = kind in maha_test_kinds | 
			
		
	
		
			
				
					|  |  |  |  |     extra_post += """ | 
			
		
	
		
			
				
					|  |  |  |  |       void update_%d(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -143,16 +142,9 @@ def gen_code(name, f_sym, dt_sym, x_sym, obs_eqs, dim_x, dim_err, eskf_params=No | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  |   def __init__(self, name, Q, x_initial, P_initial, dim_main, dim_main_err, | 
			
		
	
		
			
				
					|  |  |  |  |                      N=0, dim_augment=0, dim_augment_err=0, maha_test_kinds=[]): | 
			
		
	
		
			
				
					|  |  |  |  |     ''' | 
			
		
	
		
			
				
					|  |  |  |  |     Generates process function and all | 
			
		
	
		
			
				
					|  |  |  |  |     observation functions for the kalman | 
			
		
	
		
			
				
					|  |  |  |  |     filter. | 
			
		
	
		
			
				
					|  |  |  |  |     ''' | 
			
		
	
		
			
				
					|  |  |  |  |     if N > 0: | 
			
		
	
		
			
				
					|  |  |  |  |       self.msckf = True | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |       self.msckf = False | 
			
		
	
		
			
				
					|  |  |  |  |                N=0, dim_augment=0, dim_augment_err=0, maha_test_kinds=[]): | 
			
		
	
		
			
				
					|  |  |  |  |     """Generates process function and all observation functions for the kalman filter.""" | 
			
		
	
		
			
				
					|  |  |  |  |     self.msckf = N > 0 | 
			
		
	
		
			
				
					|  |  |  |  |     self.N = N | 
			
		
	
		
			
				
					|  |  |  |  |     self.dim_augment = dim_augment | 
			
		
	
		
			
				
					|  |  |  |  |     self.dim_augment_err = dim_augment_err | 
			
		
	
	
		
			
				
					|  |  |  | @ -163,8 +155,8 @@ class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  |     x_initial = x_initial.reshape((-1, 1)) | 
			
		
	
		
			
				
					|  |  |  |  |     self.dim_x = x_initial.shape[0] | 
			
		
	
		
			
				
					|  |  |  |  |     self.dim_err = P_initial.shape[0] | 
			
		
	
		
			
				
					|  |  |  |  |     assert dim_main + dim_augment*N == self.dim_x | 
			
		
	
		
			
				
					|  |  |  |  |     assert dim_main_err + dim_augment_err*N == self.dim_err | 
			
		
	
		
			
				
					|  |  |  |  |     assert dim_main + dim_augment * N == self.dim_x | 
			
		
	
		
			
				
					|  |  |  |  |     assert dim_main_err + dim_augment_err * N == self.dim_err | 
			
		
	
		
			
				
					|  |  |  |  |     assert Q.shape == P_initial.shape | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # kinds that should get mahalanobis distance | 
			
		
	
	
		
			
				
					|  |  |  | @ -190,24 +182,29 @@ class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # wrap all the sympy functions | 
			
		
	
		
			
				
					|  |  |  |  |     def wrap_1lists(name): | 
			
		
	
		
			
				
					|  |  |  |  |       func = eval("lib.%s" % name, {"lib":lib}) | 
			
		
	
		
			
				
					|  |  |  |  |       func = eval("lib.%s" % name, {"lib": lib}) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       def ret(lst1, out): | 
			
		
	
		
			
				
					|  |  |  |  |         func(ffi.cast("double *", lst1.ctypes.data), | 
			
		
	
		
			
				
					|  |  |  |  |           ffi.cast("double *", out.ctypes.data)) | 
			
		
	
		
			
				
					|  |  |  |  |              ffi.cast("double *", out.ctypes.data)) | 
			
		
	
		
			
				
					|  |  |  |  |       return ret | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def wrap_2lists(name): | 
			
		
	
		
			
				
					|  |  |  |  |       func = eval("lib.%s" % name, {"lib":lib}) | 
			
		
	
		
			
				
					|  |  |  |  |       func = eval("lib.%s" % name, {"lib": lib}) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       def ret(lst1, lst2, out): | 
			
		
	
		
			
				
					|  |  |  |  |         func(ffi.cast("double *", lst1.ctypes.data), | 
			
		
	
		
			
				
					|  |  |  |  |           ffi.cast("double *", lst2.ctypes.data), | 
			
		
	
		
			
				
					|  |  |  |  |           ffi.cast("double *", out.ctypes.data)) | 
			
		
	
		
			
				
					|  |  |  |  |              ffi.cast("double *", lst2.ctypes.data), | 
			
		
	
		
			
				
					|  |  |  |  |              ffi.cast("double *", out.ctypes.data)) | 
			
		
	
		
			
				
					|  |  |  |  |       return ret | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def wrap_1list_1float(name): | 
			
		
	
		
			
				
					|  |  |  |  |       func = eval("lib.%s" % name, {"lib":lib}) | 
			
		
	
		
			
				
					|  |  |  |  |       func = eval("lib.%s" % name, {"lib": lib}) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       def ret(lst1, fl, out): | 
			
		
	
		
			
				
					|  |  |  |  |         func(ffi.cast("double *", lst1.ctypes.data), | 
			
		
	
		
			
				
					|  |  |  |  |           ffi.cast("double", fl), | 
			
		
	
		
			
				
					|  |  |  |  |           ffi.cast("double *", out.ctypes.data)) | 
			
		
	
		
			
				
					|  |  |  |  |              ffi.cast("double", fl), | 
			
		
	
		
			
				
					|  |  |  |  |              ffi.cast("double *", out.ctypes.data)) | 
			
		
	
		
			
				
					|  |  |  |  |       return ret | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     self.f = wrap_1list_1float("f_fun") | 
			
		
	
	
		
			
				
					|  |  |  | @ -221,7 +218,7 @@ class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  |     for kind in kinds: | 
			
		
	
		
			
				
					|  |  |  |  |       self.hs[kind] = wrap_2lists("h_%d" % kind) | 
			
		
	
		
			
				
					|  |  |  |  |       self.Hs[kind] = wrap_2lists("H_%d" % kind) | 
			
		
	
		
			
				
					|  |  |  |  |       if self.msckf  and kind in self.feature_track_kinds: | 
			
		
	
		
			
				
					|  |  |  |  |       if self.msckf and kind in self.feature_track_kinds: | 
			
		
	
		
			
				
					|  |  |  |  |         self.Hes[kind] = wrap_2lists("He_%d" % kind) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # wrap the C++ predict function | 
			
		
	
	
		
			
				
					|  |  |  | @ -235,6 +232,7 @@ class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  |     # wrap the C++ update function | 
			
		
	
		
			
				
					|  |  |  |  |     def fun_wrapper(f, kind): | 
			
		
	
		
			
				
					|  |  |  |  |       f = eval("lib.%s" % f, {"lib": lib}) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       def _update_inner_blas(x, P, z, R, extra_args): | 
			
		
	
		
			
				
					|  |  |  |  |         f(ffi.cast("double *", x.ctypes.data), | 
			
		
	
		
			
				
					|  |  |  |  |           ffi.cast("double *", P.ctypes.data), | 
			
		
	
	
		
			
				
					|  |  |  | @ -257,43 +255,42 @@ class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # assign the functions | 
			
		
	
		
			
				
					|  |  |  |  |     self._predict = _predict_blas | 
			
		
	
		
			
				
					|  |  |  |  |     #self._predict = self._predict_python | 
			
		
	
		
			
				
					|  |  |  |  |     # self._predict = self._predict_python | 
			
		
	
		
			
				
					|  |  |  |  |     self._update = _update_blas | 
			
		
	
		
			
				
					|  |  |  |  |     #self._update = self._update_python | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # self._update = self._update_python | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   def init_state(self, state, covs, filter_time): | 
			
		
	
		
			
				
					|  |  |  |  |     self.x = np.array(state.reshape((-1, 1))).astype(np.float64) | 
			
		
	
		
			
				
					|  |  |  |  |     self.P = np.array(covs).astype(np.float64) | 
			
		
	
		
			
				
					|  |  |  |  |     self.filter_time = filter_time | 
			
		
	
		
			
				
					|  |  |  |  |     self.augment_times = [0]*self.N | 
			
		
	
		
			
				
					|  |  |  |  |     self.augment_times = [0] * self.N | 
			
		
	
		
			
				
					|  |  |  |  |     self.rewind_obscache = [] | 
			
		
	
		
			
				
					|  |  |  |  |     self.rewind_t = [] | 
			
		
	
		
			
				
					|  |  |  |  |     self.rewind_states = [] | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   def augment(self): | 
			
		
	
		
			
				
					|  |  |  |  |     # TODO this is not a generalized way of doing | 
			
		
	
		
			
				
					|  |  |  |  |     # this and implies that the augmented states | 
			
		
	
		
			
				
					|  |  |  |  |     # are simply the first (dim_augment_state) | 
			
		
	
		
			
				
					|  |  |  |  |     # elements of the main state. | 
			
		
	
		
			
				
					|  |  |  |  |     # TODO this is not a generalized way of doing this and implies that the augmented states | 
			
		
	
		
			
				
					|  |  |  |  |     # are simply the first (dim_augment_state) elements of the main state. | 
			
		
	
		
			
				
					|  |  |  |  |     assert self.msckf | 
			
		
	
		
			
				
					|  |  |  |  |     d1 = self.dim_main | 
			
		
	
		
			
				
					|  |  |  |  |     d2 = self.dim_main_err | 
			
		
	
		
			
				
					|  |  |  |  |     d3 = self.dim_augment | 
			
		
	
		
			
				
					|  |  |  |  |     d4 = self.dim_augment_err | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # push through augmented states | 
			
		
	
		
			
				
					|  |  |  |  |     self.x[d1:-d3] = self.x[d1+d3:] | 
			
		
	
		
			
				
					|  |  |  |  |     self.x[d1:-d3] = self.x[d1 + d3:] | 
			
		
	
		
			
				
					|  |  |  |  |     self.x[-d3:] = self.x[:d3] | 
			
		
	
		
			
				
					|  |  |  |  |     assert self.x.shape == (self.dim_x, 1) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # push through augmented covs | 
			
		
	
		
			
				
					|  |  |  |  |     assert self.P.shape == (self.dim_err, self.dim_err) | 
			
		
	
		
			
				
					|  |  |  |  |     P_reduced = self.P | 
			
		
	
		
			
				
					|  |  |  |  |     P_reduced = np.delete(P_reduced, np.s_[d2:d2+d4], axis=1) | 
			
		
	
		
			
				
					|  |  |  |  |     P_reduced = np.delete(P_reduced, np.s_[d2:d2+d4], axis=0) | 
			
		
	
		
			
				
					|  |  |  |  |     assert P_reduced.shape == (self.dim_err -d4, self.dim_err -d4) | 
			
		
	
		
			
				
					|  |  |  |  |     P_reduced = np.delete(P_reduced, np.s_[d2:d2 + d4], axis=1) | 
			
		
	
		
			
				
					|  |  |  |  |     P_reduced = np.delete(P_reduced, np.s_[d2:d2 + d4], axis=0) | 
			
		
	
		
			
				
					|  |  |  |  |     assert P_reduced.shape == (self.dim_err - d4, self.dim_err - d4) | 
			
		
	
		
			
				
					|  |  |  |  |     to_mult = np.zeros((self.dim_err, self.dim_err - d4)) | 
			
		
	
		
			
				
					|  |  |  |  |     to_mult[:-d4,:] = np.eye(self.dim_err - d4) | 
			
		
	
		
			
				
					|  |  |  |  |     to_mult[-d4:,:d4] = np.eye(d4) | 
			
		
	
		
			
				
					|  |  |  |  |     to_mult[:-d4, :] = np.eye(self.dim_err - d4) | 
			
		
	
		
			
				
					|  |  |  |  |     to_mult[-d4:, :d4] = np.eye(d4) | 
			
		
	
		
			
				
					|  |  |  |  |     self.P = to_mult.dot(P_reduced.dot(to_mult.T)) | 
			
		
	
		
			
				
					|  |  |  |  |     self.augment_times = self.augment_times[1:] | 
			
		
	
		
			
				
					|  |  |  |  |     self.augment_times.append(self.filter_time) | 
			
		
	
	
		
			
				
					|  |  |  | @ -308,13 +305,13 @@ class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  |   def rewind(self, t): | 
			
		
	
		
			
				
					|  |  |  |  |     # find where we are rewinding to | 
			
		
	
		
			
				
					|  |  |  |  |     idx = bisect_right(self.rewind_t, t) | 
			
		
	
		
			
				
					|  |  |  |  |     assert self.rewind_t[idx-1] <= t | 
			
		
	
		
			
				
					|  |  |  |  |     assert self.rewind_t[idx - 1] <= t | 
			
		
	
		
			
				
					|  |  |  |  |     assert self.rewind_t[idx] > t    # must be true, or rewind wouldn't be called | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # set the state to the time right before that | 
			
		
	
		
			
				
					|  |  |  |  |     self.filter_time = self.rewind_t[idx-1] | 
			
		
	
		
			
				
					|  |  |  |  |     self.x[:] = self.rewind_states[idx-1][0] | 
			
		
	
		
			
				
					|  |  |  |  |     self.P[:] = self.rewind_states[idx-1][1] | 
			
		
	
		
			
				
					|  |  |  |  |     self.filter_time = self.rewind_t[idx - 1] | 
			
		
	
		
			
				
					|  |  |  |  |     self.x[:] = self.rewind_states[idx - 1][0] | 
			
		
	
		
			
				
					|  |  |  |  |     self.P[:] = self.rewind_states[idx - 1][1] | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # return the observations we rewound over for fast forwarding | 
			
		
	
		
			
				
					|  |  |  |  |     ret = self.rewind_obscache[idx:] | 
			
		
	
	
		
			
				
					|  |  |  | @ -344,7 +341,7 @@ class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # rewind | 
			
		
	
		
			
				
					|  |  |  |  |     if self.filter_time is not None and t < self.filter_time: | 
			
		
	
		
			
				
					|  |  |  |  |       if len(self.rewind_t) == 0 or t < self.rewind_t[0] or t < self.rewind_t[-1] -1.0: | 
			
		
	
		
			
				
					|  |  |  |  |       if len(self.rewind_t) == 0 or t < self.rewind_t[0] or t < self.rewind_t[-1] - 1.0: | 
			
		
	
		
			
				
					|  |  |  |  |         print("observation too old at %.3f with filter at %.3f, ignoring" % (t, self.filter_time)) | 
			
		
	
		
			
				
					|  |  |  |  |         return None | 
			
		
	
		
			
				
					|  |  |  |  |       rewound = self.rewind(t) | 
			
		
	
	
		
			
				
					|  |  |  | @ -430,7 +427,7 @@ class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  |       P[:d2, d2:] = F_curr.dot(P[:d2, d2:]) | 
			
		
	
		
			
				
					|  |  |  |  |       P[d2:, :d2] = P[d2:, :d2].dot(F_curr.T) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     P += dt*self.Q | 
			
		
	
		
			
				
					|  |  |  |  |     P += dt * self.Q | 
			
		
	
		
			
				
					|  |  |  |  |     return x_new, P | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   def _update_python(self, x, P, kind, z, R, extra_args=[]): | 
			
		
	
	
		
			
				
					|  |  |  | @ -477,15 +474,15 @@ class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  |       a = np.linalg.inv(H.dot(P).dot(H.T) + R) | 
			
		
	
		
			
				
					|  |  |  |  |       maha_dist = y.T.dot(a.dot(y)) | 
			
		
	
		
			
				
					|  |  |  |  |       if maha_dist > chi2_ppf(0.95, y.shape[0]): | 
			
		
	
		
			
				
					|  |  |  |  |         R = 10e16*R | 
			
		
	
		
			
				
					|  |  |  |  |         R = 10e16 * R | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # *** same below this line *** | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # Outlier resilient weighting as described in: | 
			
		
	
		
			
				
					|  |  |  |  |     # "A Kalman Filter for Robust Outlier Detection - Jo-Anne Ting, ..." | 
			
		
	
		
			
				
					|  |  |  |  |     weight = 1 #(1.5)/(1 + np.sum(y**2)/np.sum(R)) | 
			
		
	
		
			
				
					|  |  |  |  |     weight = 1  # (1.5)/(1 + np.sum(y**2)/np.sum(R)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     S = dot(dot(H, P), H.T) + R/weight | 
			
		
	
		
			
				
					|  |  |  |  |     S = dot(dot(H, P), H.T) + R / weight | 
			
		
	
		
			
				
					|  |  |  |  |     K = solve(S, dot(H, P.T)).T | 
			
		
	
		
			
				
					|  |  |  |  |     I_KH = np.eye(P.shape[0]) - dot(K, H) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -550,16 +547,16 @@ class EKF_sym(): | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       d1 = self.dim_main | 
			
		
	
		
			
				
					|  |  |  |  |       d2 = self.dim_main_err | 
			
		
	
		
			
				
					|  |  |  |  |       Ck = np.linalg.solve(Pk1_k[:d2,:d2], Fk_1[:d2,:d2].dot(Pk_k[:d2,:d2].T)).T | 
			
		
	
		
			
				
					|  |  |  |  |       Ck = np.linalg.solve(Pk1_k[:d2, :d2], Fk_1[:d2, :d2].dot(Pk_k[:d2, :d2].T)).T | 
			
		
	
		
			
				
					|  |  |  |  |       xk_n = xk_k | 
			
		
	
		
			
				
					|  |  |  |  |       delta_x = np.zeros((Pk_n.shape[0], 1), dtype=np.float64) | 
			
		
	
		
			
				
					|  |  |  |  |       self.inv_err_function(xk1_k, xk1_n, delta_x) | 
			
		
	
		
			
				
					|  |  |  |  |       delta_x[:d2] = Ck.dot(delta_x[:d2]) | 
			
		
	
		
			
				
					|  |  |  |  |       x_new = np.zeros((xk_n.shape[0], 1), dtype=np.float64) | 
			
		
	
		
			
				
					|  |  |  |  |       self.err_function(xk_k, delta_x, x_new) | 
			
		
	
		
			
				
					|  |  |  |  |       xk_n[:d1] = x_new[:d1,0] | 
			
		
	
		
			
				
					|  |  |  |  |       xk_n[:d1] = x_new[:d1, 0] | 
			
		
	
		
			
				
					|  |  |  |  |       Pk_n = Pk_k | 
			
		
	
		
			
				
					|  |  |  |  |       Pk_n[:d2,:d2] = Pk_k[:d2,:d2] + Ck.dot(Pk1_n[:d2,:d2] - Pk1_k[:d2,:d2]).dot(Ck.T) | 
			
		
	
		
			
				
					|  |  |  |  |       Pk_n[:d2, :d2] = Pk_k[:d2, :d2] + Ck.dot(Pk1_n[:d2, :d2] - Pk1_k[:d2, :d2]).dot(Ck.T) | 
			
		
	
		
			
				
					|  |  |  |  |       states_smoothed.append(xk_n) | 
			
		
	
		
			
				
					|  |  |  |  |       covs_smoothed.append(Pk_n) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | 
 |