1 /*
2 * Copyright (c) 2021 Marti Riba Pons
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdio.h>
8 #include <math.h>
9 #include <errno.h>
10 #include <zsl/orientation/fusion/fusion.h>
11 #include <zsl/orientation/fusion/saam.h>
12
13 static uint32_t zsl_fus_saam_freq;
14
zsl_fus_saam(struct zsl_vec * a,struct zsl_vec * m,struct zsl_quat * q)15 static int zsl_fus_saam(struct zsl_vec *a, struct zsl_vec *m,
16 struct zsl_quat *q)
17 {
18 int rc = 0;
19
20 #if CONFIG_ZSL_BOUNDS_CHECKS
21 /* Make sure that the input vectors are tridimensional. */
22 if (a->sz != 3 || m->sz != 3) {
23 rc = -EINVAL;
24 goto err;
25 }
26 #endif
27
28 /* Return an error if either of the data in the sensors is missing or
29 * zero. */
30 if ((m == NULL) || (ZSL_ABS(zsl_vec_norm(m)) < 1E-6) ||
31 (a == NULL) || (ZSL_ABS(zsl_vec_norm(a)) < 1E-6)) {
32 rc = -EINVAL;
33 goto err;
34 }
35
36 /* Normalize the acceleration vector. */
37 zsl_vec_to_unit(a);
38
39 /* Normalize the magnetic field vector. */
40 zsl_vec_to_unit(m);
41
42 /* Determine the x (north) and z (vertical) components of the magnetic
43 * field of the earth on the earth's reference frame. */
44 zsl_real_t bz;
45 zsl_vec_dot(a, m, &bz);
46 zsl_real_t bx = ZSL_SQRT(1.0 - bz * bz);
47
48 /* Calculate the orientation quaternion. */
49 q->r = -a->data[1] * (bx + m->data[0]) + a->data[0] * m->data[1];
50 q->i = (a->data[2] - 1.0) * (bx + m->data[0]) +
51 a->data[0] * (bz - m->data[2]);
52 q->j = (a->data[2] - 1.0) * m->data[1] + a->data[1] * (bz - m->data[2]);
53 q->k = a->data[2] * bz - a->data[0] * bx - m->data[2];
54
55 /* Normalize the output quaternion. */
56 zsl_quat_to_unit_d(q);
57
58 err:
59 return rc;
60 }
61
62
63
zsl_fus_saam_init(uint32_t freq,void * cfg)64 int zsl_fus_saam_init(uint32_t freq, void *cfg)
65 {
66 int rc = 0;
67
68 #if CONFIG_ZSL_BOUNDS_CHECKS
69 /* Make sure that the sample frequency is positive. */
70 if (freq <= 0.0) {
71 rc = -EINVAL;
72 goto err;
73 }
74 #endif
75
76 zsl_fus_saam_freq = freq;
77
78 err:
79 return rc;
80 }
81
zsl_fus_saam_feed(struct zsl_vec * a,struct zsl_vec * m,struct zsl_vec * g,zsl_real_t * incl,struct zsl_quat * q,void * cfg)82 int zsl_fus_saam_feed(struct zsl_vec *a, struct zsl_vec *m,
83 struct zsl_vec *g, zsl_real_t *incl, struct zsl_quat *q, void *cfg)
84 {
85 return zsl_fus_saam(a, m, q);
86 }
87
zsl_fus_saam_error(int error)88 void zsl_fus_saam_error(int error)
89 {
90 /* ToDo: Log error in default handler. */
91 }
92