| |
| |
| |
| |
| |
| |
| |
|
|
| |
| static void outer( |
| const _float_t x[EKF_N], |
| const _float_t y[EKF_N], |
| _float_t a[EKF_N*EKF_N]) |
| { |
| for (int i=0; i<EKF_N; i++) { |
| for (int j=0; j<EKF_N; j++) { |
| a[i*EKF_N+j] = x[i] * y[j]; |
| } |
| } |
| } |
|
|
| |
| static _float_t dot(const _float_t x[EKF_N], const _float_t y[EKF_N]) |
| { |
| _float_t d = 0; |
|
|
| for (int k=0; k<EKF_N; k++) { |
| d += x[k] * y[k]; |
| } |
|
|
| return d; |
| } |
|
|
| |
| |
| |
| |
| |
| static void ekf_custom_multiply_covariance( |
| ekf_t * ekf, const _float_t A[EKF_N*EKF_N]) |
| { |
| _float_t AP[EKF_N*EKF_N] = {}; |
| _mulmat(A, ekf->P, AP, EKF_N, EKF_N, EKF_N); |
|
|
| _float_t At[EKF_N*EKF_N] = {}; |
| _transpose(A, At, EKF_N, EKF_N); |
|
|
| _mulmat(AP, At, ekf->P, EKF_N, EKF_N, EKF_N); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| static void ekf_custom_cleanup_covariance( |
| ekf_t * ekf, const float minval, const float maxval) |
| { |
|
|
| for (int i=0; i<EKF_N; i++) { |
|
|
| for (int j=i; j<EKF_N; j++) { |
|
|
| const _float_t pval = (ekf->P[i*EKF_N+j] + ekf->P[EKF_N*j+i]) / 2; |
|
|
| ekf->P[i*EKF_N+j] = ekf->P[j*EKF_N+i] = |
| pval > maxval ? maxval : |
| (i==j && pval < minval) ? minval : |
| pval; |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static void ekf_custom_scalar_update( |
| ekf_t * ekf, |
| const _float_t z, |
| const _float_t hx, |
| const _float_t h[EKF_N], |
| const _float_t r) |
| { |
| (void)ekf_update; |
|
|
| |
| _float_t ph[EKF_N] = {}; |
| _mulvec(ekf->P, h, ph, EKF_N, EKF_N); |
| const _float_t hphtr_inv = 1 / (r + dot(h, ph)); |
| _float_t g[EKF_N] = {}; |
| for (int i=0; i<EKF_N; ++i) { |
| g[i] = ph[i] * hphtr_inv; |
| } |
|
|
| |
| for (int i=0; i<EKF_N; ++i) { |
| ekf->x[i] += g[i] * (z - hx); |
| } |
|
|
| |
| _float_t GH[EKF_N*EKF_N]; |
| outer(g, h, GH); |
| ekf_update_step3(ekf, GH); |
|
|
| |
| for (int i=0; i<EKF_N; i++) { |
| for (int j=i; j<EKF_N; j++) { |
| ekf->P[i*EKF_N+j] += r * g[i] * g[j]; |
| } |
| } |
| } |
|
|