|
|
|
@ -14,7 +14,6 @@ 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] |
|
|
|
|
else: |
|
|
|
|
return np.linalg.solve(a, b) |
|
|
|
@ -144,15 +143,8 @@ 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 |
|
|
|
|
"""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 |
|
|
|
@ -191,19 +183,24 @@ class EKF_sym(): |
|
|
|
|
# wrap all the sympy functions |
|
|
|
|
def wrap_1lists(name): |
|
|
|
|
func = eval("lib.%s" % name, {"lib": lib}) |
|
|
|
|
|
|
|
|
|
def ret(lst1, out): |
|
|
|
|
func(ffi.cast("double *", lst1.ctypes.data), |
|
|
|
|
ffi.cast("double *", out.ctypes.data)) |
|
|
|
|
return ret |
|
|
|
|
|
|
|
|
|
def wrap_2lists(name): |
|
|
|
|
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)) |
|
|
|
|
return ret |
|
|
|
|
|
|
|
|
|
def wrap_1list_1float(name): |
|
|
|
|
func = eval("lib.%s" % name, {"lib": lib}) |
|
|
|
|
|
|
|
|
|
def ret(lst1, fl, out): |
|
|
|
|
func(ffi.cast("double *", lst1.ctypes.data), |
|
|
|
|
ffi.cast("double", fl), |
|
|
|
@ -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), |
|
|
|
@ -261,7 +259,6 @@ class EKF_sym(): |
|
|
|
|
self._update = _update_blas |
|
|
|
|
# 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) |
|
|
|
@ -272,19 +269,19 @@ class EKF_sym(): |
|
|
|
|
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[-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 |
|
|
|
|