ACwing FC firmware
STM32WB55: attitude IEKF, altitude Kalman filter, flight core, protocol v2
Loading...
Searching...
No Matches
calib.c
Go to the documentation of this file.
1
5#include "calib.h"
6#include "so3.h"
7#include <string.h>
8#include <math.h>
9
10void calib_reset(calib_t *c) { memset(c, 0, sizeof *c); }
11
12uint32_t calib_count(const calib_t *c) { return c->n; }
13
14int calib_add(calib_t *c, const float acc[3], const float gyro[3], const float mag[3],
15 float gyro_still_thr)
16{
17 const float gn = vec3_norm(gyro);
18 if (gn > gyro_still_thr) return -1; /* it is moving */
19 if (c->n >= CALIB_MAX_SAMPLES) return 0;
20 memcpy(c->acc[c->n], acc, 3*sizeof(float));
21 memcpy(c->mag[c->n], mag, 3*sizeof(float));
22 for (int i = 0; i < 3; ++i) c->gyro_sum[i] += gyro[i];
23 if (gn > c->gyro_norm_max) c->gyro_norm_max = gn;
24 c->n++;
25 return 0;
26}
27
28/* 1:1 port of directionNoiseStd.m */
29float direction_noise_std(const float (*v)[3], uint32_t n)
30{
31 if (n < 2) return 0.0f;
32 float um[3] = { 0, 0, 0 };
33 for (uint32_t k = 0; k < n; ++k) {
34 const float nk = vec3_norm(v[k]);
35 if (nk < 1e-9f) continue;
36 for (int i = 0; i < 3; ++i) um[i] += v[k][i] / nk;
37 }
38 if (vec3_normalize(um)) return 0.0f;
39
40 float e = 0.0f;
41 for (uint32_t k = 0; k < n; ++k) {
42 const float nk = vec3_norm(v[k]);
43 if (nk < 1e-9f) continue;
44 float u[3] = { v[k][0]/nk, v[k][1]/nk, v[k][2]/nk };
45 const float d = vec3_dot(um, u);
46 float r[3] = { u[0] - d*um[0], u[1] - d*um[1], u[2] - d*um[2] };
47 e += vec3_dot(r, r);
48 }
49 return sqrtf((e / (float)n) / 2.0f); /* 2 tangent degrees of freedom */
50}
51
52int calib_finish(const calib_t *c, float sigma_min, calib_result_t *out)
53{
54 if (c->n < 10) return -1;
55 const float inv_n = 1.0f / (float)c->n;
56
57 float am[3] = { 0, 0, 0 }, mm[3] = { 0, 0, 0 };
58 float an = 0.0f, mn = 0.0f;
59 for (uint32_t k = 0; k < c->n; ++k) {
60 for (int i = 0; i < 3; ++i) { am[i] += c->acc[k][i]; mm[i] += c->mag[k][i]; }
61 an += vec3_norm(c->acc[k]);
62 mn += vec3_norm(c->mag[k]);
63 }
64 for (int i = 0; i < 3; ++i) { am[i] *= inv_n; mm[i] *= inv_n; }
65 if (vec3_normalize(am) || vec3_normalize(mm)) return -2;
66
67 /* TRIAD: world axes expressed in the body frame */
68 float z[3] = { am[0], am[1], am[2] }; /* up */
69 const float d = vec3_dot(mm, z);
70 float x[3] = { mm[0] - d*z[0], mm[1] - d*z[1], mm[2] - d*z[2] }; /* horiz. north */
71 if (vec3_normalize(x)) return -3; /* field ~ vertical */
72 float y[3];
73 vec3_cross(z, x, y); /* west */
74
75 iekf_seed_t *s = &out->seed;
76 /* R0 (body->world): rows = world axes in the body frame */
77 s->R0[0] = x[0]; s->R0[1] = x[1]; s->R0[2] = x[2];
78 s->R0[3] = y[0]; s->R0[4] = y[1]; s->R0[5] = y[2];
79 s->R0[6] = z[0]; s->R0[7] = z[1]; s->R0[8] = z[2];
80
81 mat3_vec(s->R0, am, s->g_ref); /* = [0 0 1] */
82 mat3_vec(s->R0, mm, s->m_ref); /* = [cos I, 0, -sin I] */
83 for (int i = 0; i < 3; ++i) s->b0[i] = c->gyro_sum[i] * inv_n;
84 s->nom_acc = an * inv_n;
85 s->nom_mag = mn * inv_n;
86
87 out->sigma_acc_raw = direction_noise_std((const float (*)[3])c->acc, c->n);
88 out->sigma_mag_raw = direction_noise_std((const float (*)[3])c->mag, c->n);
89 out->sigma_acc = fmaxf(out->sigma_acc_raw, sigma_min);
90 out->sigma_mag = fmaxf(out->sigma_mag_raw, sigma_min);
91 return 0;
92}
static batt_state_t s
Definition battery.c:21
void calib_reset(calib_t *c)
Definition calib.c:10
int calib_finish(const calib_t *c, float sigma_min, calib_result_t *out)
Definition calib.c:52
float direction_noise_std(const float(*v)[3], uint32_t n)
Definition calib.c:29
int calib_add(calib_t *c, const float acc[3], const float gyro[3], const float mag[3], float gyro_still_thr)
Returns 0 if the sample is compatible with "still", -1 if moving.
Definition calib.c:14
uint32_t calib_count(const calib_t *c)
Definition calib.c:12
Initial static window: references, noise and initial attitude.
#define CALIB_MAX_SAMPLES
Definition calib.h:19
uint32_t n
Definition calib_mgr.c:35
void mat3_vec(const float A[9], const float x[3], float y[3])
y = A*x
Definition so3.c:113
void vec3_cross(const float a[3], const float b[3], float c[3])
Definition so3.c:49
float vec3_norm(const float v[3])
Definition so3.c:47
float vec3_dot(const float a[3], const float b[3])
Definition so3.c:46
int vec3_normalize(float v[3])
0 = OK
Definition so3.c:56
Single-precision SO(3) Lie-group utilities (port of expSO3.m / skewSym.m + firmware helpers).
float sigma_acc_raw
measured values, for diagnostics
Definition calib.h:34
float sigma_mag
Definition calib.h:33
float sigma_acc
already lower-bounded by sigma_min
Definition calib.h:32
float sigma_mag_raw
Definition calib.h:35
iekf_seed_t seed
Definition calib.h:31
float mag[CALIB_MAX_SAMPLES][3]
Definition calib.h:25
float gyro_norm_max
Definition calib.h:27
float acc[CALIB_MAX_SAMPLES][3]
Definition calib.h:24
uint32_t n
Definition calib.h:23
float gyro_sum[3]
Definition calib.h:26
Initial conditions, typically from calib_finish()
Definition iekf.h:87