Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
imu.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2008-2022 The Paparazzi Team
3 * Freek van Tienen <freek.v.tienen@gmail.com>
4 *
5 * This file is part of paparazzi.
6 *
7 * paparazzi is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * paparazzi is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with paparazzi; see the file COPYING. If not, write to
19 * the Free Software Foundation, 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
28#ifdef BOARD_CONFIG
29#include BOARD_CONFIG
30#endif
31
32#include "modules/imu/imu.h"
33#include "state.h"
34#include "modules/core/abi.h"
36
38#ifndef IMU_INTEGRATION
39#define IMU_INTEGRATION false
40#endif
41
43#if defined(IMU_GYRO_CALIB) && (defined(IMU_GYRO_P_SIGN) || defined(IMU_GYRO_Q_SIGN) || defined(IMU_GYRO_R_SIGN))
44#warning "The IMU_GYRO_?_SIGN's aren't compatible with the IMU_GYRO_CALIB define in the airframe"
45#endif
46#ifndef IMU_GYRO_P_SIGN
47#define IMU_GYRO_P_SIGN 1
48#endif
49#ifndef IMU_GYRO_Q_SIGN
50#define IMU_GYRO_Q_SIGN 1
51#endif
52#ifndef IMU_GYRO_R_SIGN
53#define IMU_GYRO_R_SIGN 1
54#endif
55
57#if defined(IMU_GYRO_P_NEUTRAL) || defined(IMU_GYRO_Q_NEUTRAL) || defined(IMU_GYRO_R_NEUTRAL)
58#define GYRO_NEUTRAL {IMU_GYRO_P_NEUTRAL, IMU_GYRO_Q_NEUTRAL, IMU_GYRO_R_NEUTRAL}
59PRINT_CONFIG_MSG("Using single IMU gyro neutral calibration")
60#endif
61
62#if defined(IMU_GYRO_P_SENS) || defined(IMU_GYRO_Q_SENS) || defined(IMU_GYRO_R_SENS)
63#define GYRO_SCALE {{IMU_GYRO_P_SIGN*IMU_GYRO_P_SENS_NUM, IMU_GYRO_Q_SIGN*IMU_GYRO_Q_SENS_NUM, IMU_GYRO_R_SIGN*IMU_GYRO_R_SENS_NUM}, {IMU_GYRO_P_SENS_DEN, IMU_GYRO_Q_SENS_DEN, IMU_GYRO_R_SENS_DEN}}
64PRINT_CONFIG_MSG("Using single IMU gyro sensitivity calibration")
65#endif
66
67#if defined(GYRO_NEUTRAL) && defined(GYRO_SCALE)
68#define IMU_GYRO_CALIB {{.abi_id=ABI_BROADCAST, .calibrated={.neutral=true, .scale=true}, .neutral=GYRO_NEUTRAL, .scale=GYRO_SCALE}}
69#elif defined(GYRO_NEUTRAL)
70#define IMU_GYRO_CALIB {{.abi_id=ABI_BROADCAST, .calibrated={.neutral=true}, .neutral=GYRO_NEUTRAL}}
71#elif defined(GYRO_SCALE)
72#define IMU_GYRO_CALIB {{.abi_id=ABI_BROADCAST, .calibrated={.scale=true}, .scale=GYRO_SCALE}}
73#elif !defined(IMU_GYRO_CALIB)
74#define IMU_GYRO_CALIB {}
75#endif
76
77#if defined(IMU_IMU_ACCEL_CALIB)
78#error IMU_IMU_ACCEL_CALIB defined. Rename it "ACCEL_CALIB" if your calibration is in a section with the "IMU_" prefix.
79#endif
80
82#if defined(IMU_ACCEL_CALIB) && (defined(IMU_ACCEL_X_SIGN) || defined(IMU_ACCEL_Y_SIGN) || defined(IMU_ACCEL_Z_SIGN))
83#warning "The IMU_ACCEL_?_SIGN's aren't compatible with the IMU_ACCEL_CALIB define in the airframe"
84#endif
85#ifndef IMU_ACCEL_X_SIGN
86#define IMU_ACCEL_X_SIGN 1
87#endif
88#ifndef IMU_ACCEL_Y_SIGN
89#define IMU_ACCEL_Y_SIGN 1
90#endif
91#ifndef IMU_ACCEL_Z_SIGN
92#define IMU_ACCEL_Z_SIGN 1
93#endif
94
96#if defined(IMU_ACCEL_X_NEUTRAL) || defined(IMU_ACCEL_Y_NEUTRAL) || defined(IMU_ACCEL_Z_NEUTRAL)
97#define ACCEL_NEUTRAL {IMU_ACCEL_X_NEUTRAL, IMU_ACCEL_Y_NEUTRAL, IMU_ACCEL_Z_NEUTRAL}
98PRINT_CONFIG_MSG("Using single IMU accel neutral calibration")
99#endif
100
101#if defined(IMU_ACCEL_X_SENS) || defined(IMU_ACCEL_Y_SENS) || defined(IMU_ACCEL_Z_SENS)
102#define ACCEL_SCALE {{IMU_ACCEL_X_SIGN*IMU_ACCEL_X_SENS_NUM, IMU_ACCEL_Y_SIGN*IMU_ACCEL_Y_SENS_NUM, IMU_ACCEL_Z_SIGN*IMU_ACCEL_Z_SENS_NUM}, {IMU_ACCEL_X_SENS_DEN, IMU_ACCEL_Y_SENS_DEN, IMU_ACCEL_Z_SENS_DEN}}
103PRINT_CONFIG_MSG("Using single IMU accel sensitivity calibration")
104#endif
105
106#if defined(ACCEL_NEUTRAL) && defined(ACCEL_SCALE)
107#define IMU_ACCEL_CALIB {{.abi_id=ABI_BROADCAST, .calibrated={.neutral=true, .scale=true}, .neutral=ACCEL_NEUTRAL, .scale=ACCEL_SCALE}}
108#elif defined(ACCEL_NEUTRAL)
109#define IMU_ACCEL_CALIB {{.abi_id=ABI_BROADCAST, .calibrated={.neutral=true}, .neutral=ACCEL_NEUTRAL}}
110#elif defined(ACCEL_SCALE)
111#define IMU_ACCEL_CALIB {{.abi_id=ABI_BROADCAST, .calibrated={.scale=true}, .scale=ACCEL_SCALE}}
112#elif !defined(IMU_ACCEL_CALIB)
113#define IMU_ACCEL_CALIB {}
114#endif
115
117#if defined(IMU_MAG_CALIB) && (defined(IMU_MAG_X_SIGN) || defined(IMU_MAG_Y_SIGN) || defined(IMU_MAG_Z_SIGN))
118#warning "The IMU_MAG_?_SIGN's aren't compatible with the IMU_MAG_CALIB define in the airframe"
119#endif
120#ifndef IMU_MAG_X_SIGN
121#define IMU_MAG_X_SIGN 1
122#endif
123#ifndef IMU_MAG_Y_SIGN
124#define IMU_MAG_Y_SIGN 1
125#endif
126#ifndef IMU_MAG_Z_SIGN
127#define IMU_MAG_Z_SIGN 1
128#endif
129
131#if defined(IMU_MAG_X_NEUTRAL) || defined(IMU_MAG_Y_NEUTRAL) || defined(IMU_MAG_Z_NEUTRAL)
132#define MAG_NEUTRAL {IMU_MAG_X_NEUTRAL, IMU_MAG_Y_NEUTRAL, IMU_MAG_Z_NEUTRAL}
133PRINT_CONFIG_MSG("Using single IMU mag neutral calibration")
134#endif
135
136#if defined(IMU_MAG_X_SENS) || defined(IMU_MAG_Y_SENS) || defined(IMU_MAG_Z_SENS)
137#define MAG_SCALE {{IMU_MAG_X_SIGN*IMU_MAG_X_SENS_NUM, IMU_MAG_Y_SIGN*IMU_MAG_Y_SENS_NUM, IMU_MAG_Z_SIGN*IMU_MAG_Z_SENS_NUM}, {IMU_MAG_X_SENS_DEN, IMU_MAG_Y_SENS_DEN, IMU_MAG_Z_SENS_DEN}}
138PRINT_CONFIG_MSG("Using single IMU mag sensitivity calibration")
139#endif
140
141#if defined(MAG_NEUTRAL) && defined(MAG_SCALE)
142#define IMU_MAG_CALIB {{.abi_id=ABI_BROADCAST, .calibrated={.neutral=true, .scale=true}, .neutral=MAG_NEUTRAL, .scale=MAG_SCALE}}
143#elif defined(MAG_NEUTRAL)
144#define IMU_MAG_CALIB {{.abi_id=ABI_BROADCAST, .calibrated={.neutral=true}, .neutral=MAG_NEUTRAL}}
145#elif defined(MAG_SCALE)
146#define IMU_MAG_CALIB {{.abi_id=ABI_BROADCAST, .calibrated={.scale=true}, .scale=MAG_SCALE}}
147#elif !defined(IMU_MAG_CALIB)
148#define IMU_MAG_CALIB {}
149#endif
150
151
153#if !defined(IMU_BODY_TO_IMU_PHI) && !defined(IMU_BODY_TO_IMU_THETA) && !defined(IMU_BODY_TO_IMU_PSI)
154#define IMU_BODY_TO_IMU_PHI 0
155#define IMU_BODY_TO_IMU_THETA 0
156#define IMU_BODY_TO_IMU_PSI 0
157#endif
161
162
163#ifndef IMU_GYRO_ABI_SEND_ID
164#define IMU_GYRO_ABI_SEND_ID ABI_BROADCAST
165#endif
167
168
169#ifndef IMU_ACCEL_ABI_SEND_ID
170#define IMU_ACCEL_ABI_SEND_ID ABI_BROADCAST
171#endif
173
174
175#ifndef IMU_MAG_ABI_SEND_ID
176#define IMU_MAG_ABI_SEND_ID ABI_BROADCAST
177#endif
179
180
181#ifndef IMU_LOG_HIGHSPEED_DEVICE
182#define IMU_LOG_HIGHSPEED_DEVICE flightrecorder_sdlog
183#endif
184
185
186#if PERIODIC_TELEMETRY
188
189static void send_accel_raw(struct transport_tx *trans, struct link_device *dev)
190{
192 return;
193 static uint8_t id = 0;
197 return;
198 id++;
199 if(id >= IMU_MAX_SENSORS || imu.accels[id].abi_id == ABI_DISABLE)
200 id = 0;
201}
202
203static void send_accel_scaled(struct transport_tx *trans, struct link_device *dev)
204{
206 return;
207 static uint8_t id = 0;
209 &imu.accels[id].scaled.x, &imu.accels[id].scaled.y, &imu.accels[id].scaled.z);
211 return;
212 id++;
213 if(id >= IMU_MAX_SENSORS || imu.accels[id].abi_id == ABI_DISABLE)
214 id = 0;
215}
216
217static void send_accel(struct transport_tx *trans, struct link_device *dev)
218{
220 return;
221 static uint8_t id = 0;
222 struct FloatVect3 accel_float;
227 return;
228 id++;
229 if(id >= IMU_MAX_SENSORS || imu.accels[id].abi_id == ABI_DISABLE)
230 id = 0;
231}
232
233static void send_gyro_raw(struct transport_tx *trans, struct link_device *dev)
234{
236 return;
237 static uint8_t id = 0;
239 &imu.gyros[id].unscaled.p, &imu.gyros[id].unscaled.q, &imu.gyros[id].unscaled.r);
241 return;
242 id++;
243 if(id >= IMU_MAX_SENSORS || imu.gyros[id].abi_id == ABI_DISABLE)
244 id = 0;
245}
246
247static void send_gyro_scaled(struct transport_tx *trans, struct link_device *dev)
248{
250 return;
251 static uint8_t id = 0;
253 &imu.gyros[id].scaled.p, &imu.gyros[id].scaled.q, &imu.gyros[id].scaled.r);
255 return;
256 id++;
257 if(id >= IMU_MAX_SENSORS || imu.gyros[id].abi_id == ABI_DISABLE)
258 id = 0;
259}
260
261static void send_gyro(struct transport_tx *trans, struct link_device *dev)
262{
264 return;
265 static uint8_t id = 0;
266 struct FloatRates gyro_float;
269 &gyro_float.p, &gyro_float.q, &gyro_float.r);
271 return;
272 id++;
273 if(id >= IMU_MAX_SENSORS || imu.gyros[id].abi_id == ABI_DISABLE)
274 id = 0;
275}
276
277static void send_mag_raw(struct transport_tx *trans, struct link_device *dev)
278{
280 return;
281 static uint8_t id = 0;
283 &imu.mags[id].unscaled.x, &imu.mags[id].unscaled.y, &imu.mags[id].unscaled.z);
285 return;
286 id++;
287 if(id >= IMU_MAX_SENSORS || imu.mags[id].abi_id == ABI_DISABLE)
288 id = 0;
289}
290
291static void send_mag_scaled(struct transport_tx *trans, struct link_device *dev)
292{
294 return;
295 static uint8_t id = 0;
297 &imu.mags[id].scaled.x, &imu.mags[id].scaled.y, &imu.mags[id].scaled.z);
299 return;
300 id++;
301 if(id >= IMU_MAX_SENSORS || imu.mags[id].abi_id == ABI_DISABLE)
302 id = 0;
303}
304
305static void send_mag(struct transport_tx *trans, struct link_device *dev)
306{
308 return;
309 static uint8_t id = 0;
310 struct FloatVect3 mag_float;
315 return;
316 id++;
317 if(id >= IMU_MAX_SENSORS || imu.mags[id].abi_id == ABI_DISABLE)
318 id = 0;
319}
320
321static void send_mag_current(struct transport_tx *trans, struct link_device *dev)
322{
324 return;
325 static uint8_t id = 0;
327 &imu.mags[id].abi_id,
328 &imu.mags[id].unscaled.x,
329 &imu.mags[id].unscaled.y,
330 &imu.mags[id].unscaled.z,
333 return;
334 id++;
335 if(id >= IMU_MAX_SENSORS || imu.mags[id].abi_id == ABI_DISABLE)
336 id = 0;
337}
338
339#endif /* PERIODIC_TELEMETRY */
340
341#if USE_SHELL
342#include "modules/core/shell.h"
343#include "printf.h"
344#include "string.h"
345
346static void show_calibrated(shell_stream_t *sh, struct imu_calib_t *calibrated) {
347 chprintf(sh, " calibrated: neutral %d, scale %d, rotation %d, current %d, filter %d\r\n",
348 calibrated->neutral, calibrated->scale_f, calibrated->rotation, calibrated->current, calibrated->filter);
349}
350
351static void show_vect3(shell_stream_t *sh, char* name, struct Int32Vect3 *v) {
352 chprintf(sh, " %s: %ld, %ld, %ld\r\n", name, v->x, v->y, v->z);
353}
354
355static void show_vect3f(shell_stream_t *sh, char* name, struct FloatVect3 *v) {
356 chprintf(sh, " %s: %f, %f, %f\r\n", name, v->x, v->y, v->z);
357}
358
359static void show_rates(shell_stream_t *sh, char* name, struct Int32Rates *r) {
360 chprintf(sh, " %s: %ld, %ld, %ld\r\n", name, r->p, r->q, r->r);
361}
362
363static void show_ratesf(shell_stream_t *sh, char* name, struct FloatRates *r) {
364 chprintf(sh, " %s: %f, %f, %f\r\n", name, r->p, r->q, r->r);
365}
366
367
368static void show_matrix(shell_stream_t *sh, char* name, struct Int32RMat *m) {
369 chprintf(sh, " %s:\r\n", name);
370 chprintf(sh, " %ld, %ld, %ld\r\n", MAT33_ELMT(*m, 0, 0), MAT33_ELMT(*m, 0, 1), MAT33_ELMT(*m, 0, 2));
371 chprintf(sh, " %ld, %ld, %ld\r\n", MAT33_ELMT(*m, 1, 0), MAT33_ELMT(*m, 1, 1), MAT33_ELMT(*m, 1, 2));
372 chprintf(sh, " %ld, %ld, %ld\r\n", MAT33_ELMT(*m, 2, 0), MAT33_ELMT(*m, 2, 1), MAT33_ELMT(*m, 2, 2));
373}
374
375static void cmd_imu(shell_stream_t *sh, int argc, const char *const argv[])
376{
377 (void) argv;
378 int i = 0;
379 if (argc > 0) {
380 chprintf(sh, "Usage: imu\r\n");
381 return;
382 }
383 chprintf(sh, "GYRO IMU data\r\n");
384 for (i = 0; i < IMU_MAX_SENSORS; i++) {
385 if (imu.gyros[i].abi_id != 0) {
386 chprintf(sh, " Gyro id: %u, time %lu\r\n", imu.gyros[i].abi_id, imu.gyros[i].last_stamp);
388 show_rates(sh, "neutral", &imu.gyros[i].neutral);
389 show_ratesf(sh, "scale", &imu.gyros[i].scale_f);
390 show_matrix(sh, "body_to_sensor", &imu.gyros[i].body_to_sensor);
391 show_rates(sh, "unscaled", &imu.gyros[i].unscaled);
392 show_rates(sh, "scaled", &imu.gyros[i].scaled);
393 struct FloatRates gf;
395 chprintf(sh, " -> gyro (rad/s): %.3f, %.3f, %.3f\r\n", gf.p, gf.q, gf.r);
396 }
397 }
398 chprintf(sh, "ACCEL IMU data\r\n");
399 for (i = 0; i < IMU_MAX_SENSORS; i++) {
400 if (imu.accels[i].abi_id != 0) {
401 chprintf(sh, " Accel id: %u, time %lu\r\n", imu.accels[i].abi_id, imu.accels[i].last_stamp);
403 show_vect3(sh, "neutral", &imu.accels[i].neutral);
404 show_vect3f(sh, "scale", &imu.accels[i].scale_f);
405 show_matrix(sh, "body_to_sensor", &imu.accels[i].body_to_sensor);
406 show_vect3(sh, "unscaled", &imu.accels[i].unscaled);
407 show_vect3(sh, "scaled", &imu.accels[i].scaled);
408 struct FloatVect3 af;
410 chprintf(sh, " -> accel (m/s2): %.3f, %.3f, %.3f\r\n", af.x, af.y, af.z);
411 }
412 }
413 chprintf(sh, "MAG IMU data\r\n");
414 for (i = 0; i < IMU_MAX_SENSORS; i++) {
415 if (imu.mags[i].abi_id != 0) {
416 chprintf(sh, " Mag id: %u\r\n", imu.mags[i].abi_id);
418 show_vect3(sh, "neutral", &imu.mags[i].neutral);
419 show_vect3f(sh, "scale", &imu.mags[i].scale_f);
420 show_matrix(sh, "body_to_sensor", &imu.mags[i].body_to_sensor);
421 show_vect3(sh, "unscaled", &imu.mags[i].unscaled);
422 show_vect3(sh, "scaled", &imu.mags[i].scaled);
423 struct FloatVect3 mf;
425 chprintf(sh, " -> mag (unit): %.3f, %.3f, %.3f\r\n", mf.x, mf.y, mf.z);
426 }
427 }
428}
429
430#endif
431
432struct Imu imu = {0};
434static void imu_gyro_raw_cb(uint8_t sender_id, uint32_t stamp, struct Int32Rates *data, uint8_t samples, float rate, float temp);
435static void imu_accel_raw_cb(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *data, uint8_t samples, float rate, float temp);
436static void imu_mag_raw_cb(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *data);
438
439void imu_init(void)
440{
441 // Set the Body to IMU rotation
444 struct Int32RMat *body_to_imu_rmat = orientationGetRMat_i(&imu.body_to_imu);
445
446
447 // Set the calibrated sensors
448 struct Int32RMat body_to_sensor;
449 const struct imu_gyro_t gyro_calib[] = IMU_GYRO_CALIB;
450 const struct imu_accel_t accel_calib[] = IMU_ACCEL_CALIB;
451 const struct imu_mag_t mag_calib[] = IMU_MAG_CALIB;
452 const uint8_t gyro_calib_len = sizeof(gyro_calib) / sizeof(struct imu_gyro_t);
453 const uint8_t accel_calib_len = sizeof(accel_calib) / sizeof(struct imu_accel_t);
454 const uint8_t mag_calib_len = sizeof(mag_calib) / sizeof(struct imu_mag_t);
455
456 // Initialize the sensors to default values
457 for(uint8_t i = 0; i < IMU_MAX_SENSORS; i++) {
458 /* Copy gyro calibration if needed */
459 if(i >= gyro_calib_len) {
461 imu.gyros[i].calibrated.neutral = false;
462 imu.gyros[i].calibrated.scale = false;
463 imu.gyros[i].calibrated.scale_f = false;
464 imu.gyros[i].calibrated.rotation = false;
465 imu.gyros[i].calibrated.rot_euler = false;
466 imu.gyros[i].calibrated.filter = false;
467 } else {
468 imu.gyros[i] = gyro_calib[i];
469 }
470
471 // Set the default safe values if not calibrated
472 if(!imu.gyros[i].calibrated.neutral) {
474 }
475
476 if(!imu.gyros[i].calibrated.scale_f) {
477 if(imu.gyros[i].calibrated.scale) {
478 imu.gyros[i].scale_f.p = (float)imu.gyros[i].scale[0].p / (float)imu.gyros[i].scale[1].p;
479 imu.gyros[i].scale_f.q = (float)imu.gyros[i].scale[0].q / (float)imu.gyros[i].scale[1].q;
480 imu.gyros[i].scale_f.r = (float)imu.gyros[i].scale[0].r / (float)imu.gyros[i].scale[1].r;
481 imu.gyros[i].calibrated.scale_f = true;
482 } else {
484 }
485 }
486
487 if(!imu.gyros[i].calibrated.rotation) {
488 if (imu.gyros[i].calibrated.rot_euler) {
489 struct Int32Eulers eulers_i;
492 imu.gyros[i].calibrated.rotation = true;
493 } else {
495 }
496 }
497 imu.gyros[i].last_stamp = 0;
498 int32_rmat_comp(&body_to_sensor, body_to_imu_rmat, &imu.gyros[i].body_to_sensor);
499 RMAT_COPY(imu.gyros[i].body_to_sensor, body_to_sensor);
500
501 if(imu.gyros[i].calibrated.filter) {
502 float tau = 1.0 / (2.0 * M_PI * imu.gyros[i].filter_freq);
504 for(uint8_t j = 0; j < 3; j++)
506 }
507
508 /* Copy accel calibration if needed */
509 if(i >= accel_calib_len) {
511 imu.accels[i].calibrated.neutral = false;
512 imu.accels[i].calibrated.scale = false;
513 imu.accels[i].calibrated.scale_f = false;
514 imu.accels[i].calibrated.rotation = false;
515 imu.accels[i].calibrated.rot_euler = false;
516 imu.accels[i].calibrated.filter = false;
517 } else {
518 imu.accels[i] = accel_calib[i];
519 }
520
521 // Set the default safe values if not calibrated
522 if(!imu.accels[i].calibrated.neutral) {
524 }
525
526 if(!imu.accels[i].calibrated.scale_f) {
527 if(imu.accels[i].calibrated.scale) {
528 imu.accels[i].scale_f.x = (float)imu.accels[i].scale[0].x / (float)imu.accels[i].scale[1].x;
529 imu.accels[i].scale_f.y = (float)imu.accels[i].scale[0].y / (float)imu.accels[i].scale[1].y;
530 imu.accels[i].scale_f.z = (float)imu.accels[i].scale[0].z / (float)imu.accels[i].scale[1].z;
531 imu.accels[i].calibrated.scale_f = true;
532 } else {
534 }
535 }
536
537 if(!imu.accels[i].calibrated.rotation) {
539 struct Int32Eulers eulers_i;
542 imu.accels[i].calibrated.rotation = true;
543 } else {
545 }
546 }
547 imu.accels[i].last_stamp = 0;
548 int32_rmat_comp(&body_to_sensor, body_to_imu_rmat, &imu.accels[i].body_to_sensor);
549 RMAT_COPY(imu.accels[i].body_to_sensor, body_to_sensor);
550
551 if(imu.accels[i].calibrated.filter) {
552 float tau = 1.0 / (2.0 * M_PI * imu.accels[i].filter_freq);
554 for(uint8_t j = 0; j < 3; j++)
556 }
557
558 /* Copy mag calibrated if needed */
559 if(i >= mag_calib_len) {
561 imu.mags[i].calibrated.neutral = false;
562 imu.mags[i].calibrated.scale = false;
563 imu.mags[i].calibrated.scale_f = false;
564 imu.mags[i].calibrated.rotation = false;
565 imu.mags[i].calibrated.rot_euler = false;
566 imu.mags[i].calibrated.current = false;
567 } else {
568 imu.mags[i] = mag_calib[i];
569 }
570
571 // Set the default safe values if not calibrated
572 if(!imu.mags[i].calibrated.neutral) {
574 }
575
576 if(!imu.mags[i].calibrated.scale_f) {
577 if(imu.mags[i].calibrated.scale) {
578 imu.mags[i].scale_f.x = (float)imu.mags[i].scale[0].x / (float)imu.mags[i].scale[1].x;
579 imu.mags[i].scale_f.y = (float)imu.mags[i].scale[0].y / (float)imu.mags[i].scale[1].y;
580 imu.mags[i].scale_f.z = (float)imu.mags[i].scale[0].z / (float)imu.mags[i].scale[1].z;
581 imu.mags[i].calibrated.scale_f = true;
582 }else {
584 }
585 }
586 if(!imu.mags[i].calibrated.rotation) {
587 if (imu.mags[i].calibrated.rot_euler) {
588 struct Int32Eulers eulers_i;
591 imu.mags[i].calibrated.rotation = true;
592 } else {
594 }
595 }
596 if(!imu.mags[i].calibrated.current) {
598 }
599 int32_rmat_comp(&body_to_sensor, body_to_imu_rmat, &imu.mags[i].body_to_sensor);
600 RMAT_COPY(imu.mags[i].body_to_sensor, body_to_sensor);
601 }
602
603 // Bind to raw measurements
607
608#if PERIODIC_TELEMETRY
619#endif // DOWNLINK
620
621#if USE_SHELL
622 shell_add_entry("imu", cmd_imu);
623#endif
624
625 // Set defaults
629 imu.initialized = true;
630}
631
640void imu_set_defaults_gyro(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Rates *neutral, const struct FloatRates *scale_f)
641{
642 // Find the correct gyro
643 struct imu_gyro_t *gyro = imu_get_gyro(abi_id, true);
644 if(gyro == NULL)
645 return;
646
647 // Copy the defaults
648 if(imu_to_sensor != NULL && !gyro->calibrated.rotation) {
649 struct Int32RMat body_to_sensor;
650 struct Int32RMat *body_to_imu = orientationGetRMat_i(&imu.body_to_imu);
651 int32_rmat_comp(&body_to_sensor, body_to_imu, imu_to_sensor);
652 RMAT_COPY(gyro->body_to_sensor, body_to_sensor);
653 }
654 if(neutral != NULL && !gyro->calibrated.neutral)
655 RATES_COPY(gyro->neutral, *neutral);
656 if(scale_f != NULL && !gyro->calibrated.scale_f) {
657 RATES_ASSIGN(gyro->scale_f, IMU_GYRO_P_SIGN*scale_f->p, IMU_GYRO_Q_SIGN*scale_f->q, IMU_GYRO_R_SIGN*scale_f->r);
658 }
659}
660
669void imu_set_defaults_accel(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Vect3 *neutral, const struct FloatVect3 *scale_f)
670{
671 // Find the correct accel
672 struct imu_accel_t *accel = imu_get_accel(abi_id, true);
673 if(accel == NULL)
674 return;
675
676 // Copy the defaults
677 if(imu_to_sensor != NULL && !accel->calibrated.rotation) {
678 struct Int32RMat body_to_sensor;
679 struct Int32RMat *body_to_imu = orientationGetRMat_i(&imu.body_to_imu);
680 int32_rmat_comp(&body_to_sensor, body_to_imu, imu_to_sensor);
681 RMAT_COPY(accel->body_to_sensor, body_to_sensor);
682 }
683 if(neutral != NULL && !accel->calibrated.neutral)
684 VECT3_COPY(accel->neutral, *neutral);
685 if(scale_f != NULL && !accel->calibrated.scale_f) {
686 VECT3_ASSIGN(accel->scale_f, IMU_ACCEL_X_SIGN*scale_f->x, IMU_ACCEL_Y_SIGN*scale_f->y, IMU_ACCEL_Z_SIGN*scale_f->z);
687 }
688}
689
698void imu_set_defaults_mag(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Vect3 *neutral, const struct FloatVect3 *scale_f)
699{
700 // Find the correct mag
701 struct imu_mag_t *mag = imu_get_mag(abi_id, true);
702 if(mag == NULL)
703 return;
704
705 // Copy the defaults
706 if(imu_to_sensor != NULL && !mag->calibrated.rotation) {
707 struct Int32RMat body_to_sensor;
708 struct Int32RMat *body_to_imu = orientationGetRMat_i(&imu.body_to_imu);
709 int32_rmat_comp(&body_to_sensor, body_to_imu, imu_to_sensor);
710 RMAT_COPY(mag->body_to_sensor, body_to_sensor);
711 }
712 if(neutral != NULL && !mag->calibrated.neutral)
713 VECT3_COPY(mag->neutral, *neutral);
714 if(scale_f != NULL && !mag->calibrated.scale_f) {
715 VECT3_ASSIGN(mag->scale_f, IMU_MAG_X_SIGN*scale_f->x, IMU_MAG_Y_SIGN*scale_f->y, IMU_MAG_Z_SIGN*scale_f->z);
716 }
717}
718
719static void imu_gyro_raw_cb(uint8_t sender_id, uint32_t stamp, struct Int32Rates *data, uint8_t samples, float rate, float temp)
720{
721 // Find the correct gyro
722 struct imu_gyro_t *gyro = imu_get_gyro(sender_id, true);
723 if(gyro == NULL || samples < 1)
724 return;
725
726 // Filter the gyro
728 if(gyro->calibrated.filter) {
729 for(uint8_t i = 0; i < samples; i++) {
730 data_filtered[i].p = update_butterworth_2_low_pass(&gyro->filter[0], data[i].p);
731 data_filtered[i].q = update_butterworth_2_low_pass(&gyro->filter[1], data[i].q);
732 data_filtered[i].r = update_butterworth_2_low_pass(&gyro->filter[2], data[i].r);
733 }
734 data = data_filtered;
735 }
736
737 // Copy last sample as unscaled
738 RATES_COPY(gyro->unscaled, data[samples-1]);
739
740 // Scale the gyro
741 struct Int32Rates scaled, scaled_rot;
742 scaled.p = (gyro->unscaled.p - gyro->neutral.p) * gyro->scale_f.p;
743 scaled.q = (gyro->unscaled.q - gyro->neutral.q) * gyro->scale_f.q;
744 scaled.r = (gyro->unscaled.r - gyro->neutral.r) * gyro->scale_f.r;
745
746 // Rotate the sensor
748
749#if IMU_INTEGRATION
750 // Only integrate if we have gotten a previous measurement and didn't overflow the timer
751 if(!isnan(rate) && gyro->last_stamp > 0 && stamp > gyro->last_stamp) {
752 struct FloatRates integrated;
753
754 // Trapezoidal integration (TODO: coning correction)
755 integrated.p = RATE_FLOAT_OF_BFP(gyro->scaled.p + scaled_rot.p) * 0.5f;
756 integrated.q = RATE_FLOAT_OF_BFP(gyro->scaled.q + scaled_rot.q) * 0.5f;
757 integrated.r = RATE_FLOAT_OF_BFP(gyro->scaled.r + scaled_rot.r) * 0.5f;
758
759 // Only perform multiple integrations in sensor frame if needed
760 if(samples > 1) {
762 struct FloatRMat body_to_sensor;
763 // Rotate back to sensor frame
764 RMAT_FLOAT_OF_BFP(body_to_sensor, gyro->body_to_sensor);
765 float_rmat_ratemult(&integrated_sensor, &body_to_sensor, &integrated);
766
767 // Add all the other samples
768 for(uint8_t i = 0; i < samples-1; i++) {
769 struct FloatRates f_sample;
770 f_sample.p = RATE_FLOAT_OF_BFP((data[i].p - gyro->neutral.p) * gyro->scale_f.p);
771 f_sample.q = RATE_FLOAT_OF_BFP((data[i].q - gyro->neutral.q) * gyro->scale_f.q);
772 f_sample.r = RATE_FLOAT_OF_BFP((data[i].r - gyro->neutral.r) * gyro->scale_f.r);
773
774
775#if IMU_LOG_HIGHSPEED
777#endif
778
782 }
783
784 // Rotate to body frame
785 float_rmat_transp_ratemult(&integrated, &body_to_sensor, &integrated_sensor);
786 }
787
788 // Divide by the time of the collected samples
789 integrated.p = integrated.p * (1.f / rate);
790 integrated.q = integrated.q * (1.f / rate);
791 integrated.r = integrated.r * (1.f / rate);
792
793 // Send the integrated values
794 uint16_t dt = (1e6 / rate) * samples;
795 AbiSendMsgIMU_GYRO_INT(sender_id, stamp, &integrated, dt);
796 }
797#else
798 (void)rate; // Surpress compile warning not used
799#endif
800
801#if IMU_LOG_HIGHSPEED
802 struct FloatRates f_sample;
805#endif
806
807 // Copy and send
808 gyro->temperature = temp;
811 gyro->last_stamp = stamp;
812}
813
814static void imu_accel_raw_cb(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *data, uint8_t samples, float rate, float temp)
815{
816 // Find the correct accel
817 struct imu_accel_t *accel = imu_get_accel(sender_id, true);
818 if(accel == NULL || samples < 1)
819 return;
820
821 // Filter the accel
823 if(accel->calibrated.filter) {
824 for(uint8_t i = 0; i < samples; i++) {
825 data_filtered[i].x = update_butterworth_2_low_pass(&accel->filter[0], data[i].x);
826 data_filtered[i].y = update_butterworth_2_low_pass(&accel->filter[1], data[i].y);
827 data_filtered[i].z = update_butterworth_2_low_pass(&accel->filter[2], data[i].z);
828 }
829 data = data_filtered;
830 }
831
832 // Copy last sample as unscaled
833 VECT3_COPY(accel->unscaled, data[samples-1]);
834
835 // Scale the accel
836 struct Int32Vect3 scaled, scaled_rot;
837 scaled.x = (accel->unscaled.x - accel->neutral.x) * accel->scale_f.x;
838 scaled.y = (accel->unscaled.y - accel->neutral.y) * accel->scale_f.y;
839 scaled.z = (accel->unscaled.z - accel->neutral.z) * accel->scale_f.z;
840
841
842 // Rotate the sensor
844
845#if IMU_INTEGRATION
846 // Only integrate if we have gotten a previous measurement and didn't overflow the timer
847 if(!isnan(rate) && accel->last_stamp > 0 && stamp > accel->last_stamp) {
848 struct FloatVect3 integrated;
849
850 // Trapezoidal integration
851 integrated.x = ACCEL_FLOAT_OF_BFP(accel->scaled.x + scaled_rot.x) * 0.5f;
852 integrated.y = ACCEL_FLOAT_OF_BFP(accel->scaled.y + scaled_rot.y) * 0.5f;
853 integrated.z = ACCEL_FLOAT_OF_BFP(accel->scaled.z + scaled_rot.z) * 0.5f;
854
855 // Only perform multiple integrations in sensor frame if needed
856 if(samples > 1) {
858 struct FloatRMat body_to_sensor;
859 // Rotate back to sensor frame
860 RMAT_FLOAT_OF_BFP(body_to_sensor, accel->body_to_sensor);
861 float_rmat_vmult(&integrated_sensor, &body_to_sensor, &integrated);
862
863 // Add all the other samples
864 for(uint8_t i = 0; i < samples-1; i++) {
865 struct FloatVect3 f_sample;
866 f_sample.x = ACCEL_FLOAT_OF_BFP((data[i].x - accel->neutral.x) * accel->scale_f.x);
867 f_sample.y = ACCEL_FLOAT_OF_BFP((data[i].y - accel->neutral.y) * accel->scale_f.y);
868 f_sample.z = ACCEL_FLOAT_OF_BFP((data[i].z - accel->neutral.z) * accel->scale_f.z);
869
870
871#if IMU_LOG_HIGHSPEED
873#endif
874
878 }
879
880 // Rotate to body frame
881 float_rmat_transp_vmult(&integrated, &body_to_sensor, &integrated_sensor);
882 }
883
884 // Divide by the time of the collected samples
885 integrated.x = integrated.x * (1.f / rate);
886 integrated.y = integrated.y * (1.f / rate);
887 integrated.z = integrated.z * (1.f / rate);
888
889 // Send the integrated values
890 uint16_t dt = (1e6 / rate) * samples;
891 AbiSendMsgIMU_ACCEL_INT(sender_id, stamp, &integrated, dt);
892 }
893#else
894 (void)rate; // Surpress compile warning not used
895#endif
896
897#if IMU_LOG_HIGHSPEED
898 struct FloatVect3 f_sample;
901#endif
902
903 // Copy and send
904 accel->temperature = temp;
907 accel->last_stamp = stamp;
908}
909
911{
912 // Find the correct mag
913 struct imu_mag_t *mag = imu_get_mag(sender_id, true);
914 if(mag == NULL)
915 return;
916
917 // Calculate current compensation
922
923 // Copy last sample as unscaled
924 VECT3_COPY(mag->unscaled, *data);
925
926 // Scale the mag
927 struct Int32Vect3 scaled;
928 scaled.x = (mag->unscaled.x - mag_correction.x - mag->neutral.x) * mag->scale_f.x;
929 scaled.y = (mag->unscaled.y - mag_correction.y - mag->neutral.y) * mag->scale_f.y;
930 scaled.z = (mag->unscaled.z - mag_correction.z - mag->neutral.z) * mag->scale_f.z;
931
932
933 // Rotate the sensor
934 int32_rmat_transp_vmult(&mag->scaled, &mag->body_to_sensor, &scaled);
936}
937
946 // Find the correct gyro or create index
947 // If abi_id was set to broadcast (assuming a single IMU case), the first request takes the index for himself
948 struct imu_gyro_t *gyro = NULL;
949 for(uint8_t i = 0; i < IMU_MAX_SENSORS; i++) {
950 if(imu.gyros[i].abi_id == sender_id || (create && (imu.gyros[i].abi_id == ABI_BROADCAST || imu.gyros[i].abi_id == ABI_DISABLE))) {
951 gyro = &imu.gyros[i];
952 gyro->abi_id = sender_id;
953 break;
954 } else if(sender_id == ABI_BROADCAST && imu.gyros[i].abi_id != ABI_DISABLE) {
955 gyro = &imu.gyros[i];
956 }
957 }
958 return gyro;
959}
960
969 // Find the correct accel
970 // If abi_id was set to broadcast (assuming a single IMU case), the first request takes the index for himself
971 struct imu_accel_t *accel = NULL;
972 for(uint8_t i = 0; i < IMU_MAX_SENSORS; i++) {
974 accel = &imu.accels[i];
975 accel->abi_id = sender_id;
976 break;
977 } else if(sender_id == ABI_BROADCAST && imu.accels[i].abi_id != ABI_DISABLE) {
978 accel = &imu.accels[i];
979 }
980 }
981
982 return accel;
983}
984
993 // Find the correct mag
994 // If abi_id was set to broadcast (assuming a single IMU case), the first request takes the index for himself
995 struct imu_mag_t *mag = NULL;
996 for(uint8_t i = 0; i < IMU_MAX_SENSORS; i++) {
997 if(imu.mags[i].abi_id == sender_id || (create && (imu.mags[i].abi_id == ABI_BROADCAST || imu.mags[i].abi_id == ABI_DISABLE))) {
998 mag = &imu.mags[i];
999 mag->abi_id = sender_id;
1000 break;
1001 } else if(sender_id == ABI_BROADCAST && imu.mags[i].abi_id != ABI_DISABLE) {
1002 mag = &imu.mags[i];
1003 }
1004 }
1005
1006 return mag;
1007}
1008
1042
1050
1058
1066
1068{
1069 imu.b2i_set_current = set;
1070
1071 if (imu.b2i_set_current) {
1072 // adjust imu_to_body roll and pitch by current NedToBody roll and pitch
1075 if (stateIsAttitudeValid()) {
1076 // adjust imu_to_body roll and pitch by current NedToBody roll and pitch
1080 } else {
1081 // indicate that we couldn't set to current roll/pitch
1082 imu.b2i_set_current = false;
1083 }
1084 } else {
1085 // reset to BODY_TO_IMU as defined in airframe file
1088 }
1089}
1090
Main include for ABI (AirBorneInterface).
#define ABI_DISABLE
Reserved ABI ID to disable callback.
Definition abi_common.h:65
#define ABI_BROADCAST
Broadcast address.
Definition abi_common.h:59
Event structure to store callbacks in a linked list.
Definition abi_common.h:68
struct FloatVect3 accel_float
struct FloatVect3 mag_float
static struct uart_periph * dev
struct Electrical electrical
Definition electrical.c:92
Interface for electrical status: supply voltage, current, battery status, etc.
float current
current in A
Definition electrical.h:47
void chprintf(BaseSequentialStream *lchp, const char *fmt,...)
Definition printf.c:395
float q
in rad/s
float phi
in radians
float p
in rad/s
float r
in rad/s
float theta
in radians
float psi
in radians
void float_rmat_transp_ratemult(struct FloatRates *rb, const struct FloatRMat *m_b2a, const struct FloatRates *ra)
rotate anglular rates by transposed rotation matrix.
void float_rmat_vmult(struct FloatVect3 *vb, const struct FloatRMat *m_a2b, const struct FloatVect3 *va)
rotate 3D vector by rotation matrix.
void float_rmat_ratemult(struct FloatRates *rb, const struct FloatRMat *m_a2b, const struct FloatRates *ra)
rotate anglular rates by rotation matrix.
void float_rmat_transp_vmult(struct FloatVect3 *vb, const struct FloatRMat *m_b2a, const struct FloatVect3 *va)
rotate 3D vector by transposed rotation matrix.
euler angles
rotation matrix
angular rates
#define MAGS_FLOAT_OF_BFP(_ef, _ei)
#define RATES_COPY(_a, _b)
#define RATES_ASSIGN(_ra, _p, _q, _r)
#define EULERS_BFP_OF_REAL(_ei, _ef)
#define RMAT_FLOAT_OF_BFP(_ef, _ei)
#define RMAT_COPY(_o, _i)
#define VECT3_ASSIGN(_a, _x, _y, _z)
#define VECT3_COPY(_a, _b)
#define RATES_FLOAT_OF_BFP(_rf, _ri)
#define MAT33_ELMT(_m, _row, _col)
#define ACCELS_FLOAT_OF_BFP(_ef, _ei)
int32_t p
in rad/s with INT32_RATE_FRAC
int32_t r
in rad/s with INT32_RATE_FRAC
int32_t q
in rad/s with INT32_RATE_FRAC
#define INT_RATES_ZERO(_e)
#define int32_rmat_of_eulers
Rotation matrix from Euler angles.
#define RATE_FLOAT_OF_BFP(_ai)
void int32_rmat_comp_inv(struct Int32RMat *m_a2b, const struct Int32RMat *m_a2c, const struct Int32RMat *m_b2c)
Composition (multiplication) of two rotation matrices.
void int32_rmat_transp_ratemult(struct Int32Rates *rb, struct Int32RMat *m_b2a, struct Int32Rates *ra)
rotate anglular rates by transposed rotation matrix.
#define INT_VECT3_ZERO(_v)
void int32_rmat_transp_vmult(struct Int32Vect3 *vb, struct Int32RMat *m_b2a, struct Int32Vect3 *va)
rotate 3D vector by transposed rotation matrix.
void int32_rmat_comp(struct Int32RMat *m_a2c, const struct Int32RMat *m_a2b, const struct Int32RMat *m_b2c)
Composition (multiplication) of two rotation matrices.
static void int32_rmat_identity(struct Int32RMat *rm)
initialises a rotation matrix to identity
#define ACCEL_FLOAT_OF_BFP(_ai)
euler angles
rotation matrix
angular rates
static void orientationSetEulers_f(struct OrientationReps *orientation, struct FloatEulers *eulers)
Set vehicle body attitude from euler angles (float).
static struct Int32RMat * orientationGetRMat_i(struct OrientationReps *orientation)
Get vehicle body attitude rotation matrix (int).
static struct FloatEulers * orientationGetEulers_f(struct OrientationReps *orientation)
Get vehicle body attitude euler angles (float).
static bool stateIsAttitudeValid(void)
Test if attitudes are valid.
Definition state.h:1232
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition state.h:1314
#define IMU_MAG_ABI_SEND_ID
Which mag measurements to send over telemetry/logging.
Definition imu.c:176
#define IMU_GYRO_ABI_SEND_ID
Which gyro measurements to send over telemetry/logging.
Definition imu.c:164
#define IMU_MAG_CALIB
Default mag calibration is for single IMU with old format.
Definition imu.c:148
static void imu_gyro_raw_cb(uint8_t sender_id, uint32_t stamp, struct Int32Rates *data, uint8_t samples, float rate, float temp)
Definition imu.c:719
#define IMU_MAG_Y_SIGN
Definition imu.c:124
#define IMU_BODY_TO_IMU_THETA
Definition imu.c:155
static void send_mag_raw(struct transport_tx *trans, struct link_device *dev)
Definition imu.c:277
#define IMU_GYRO_P_SIGN
By default gyro signs are positive for single IMU with old format or defaults.
Definition imu.c:47
#define IMU_ACCEL_Y_SIGN
Definition imu.c:89
void imu_set_defaults_gyro(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Rates *neutral, const struct FloatRates *scale_f)
Set the defaults for a gyro sensor WARNING: Should be called before sensor is publishing messages to ...
Definition imu.c:640
struct imu_gyro_t * imu_get_gyro(uint8_t sender_id, bool create)
Find or create the gyro in the imu structure.
Definition imu.c:945
static abi_event imu_accel_raw_ev
Definition imu.c:433
static abi_event imu_mag_raw_ev
Definition imu.c:433
#define IMU_MAG_X_SIGN
By default mag signs are positive for single IMU with old format and defaults.
Definition imu.c:121
struct imu_accel_t * imu_get_accel(uint8_t sender_id, bool create)
Find or create the accel in the imu structure.
Definition imu.c:968
void imu_SetBodyToImuTheta(float theta)
Definition imu.c:1051
#define IMU_ACCEL_X_SIGN
By default accel signs are positive for single IMU with old format and defaults.
Definition imu.c:86
#define IMU_BODY_TO_IMU_PHI
Default body to imu is 0 (radians)
Definition imu.c:154
static void imu_accel_raw_cb(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *data, uint8_t samples, float rate, float temp)
Definition imu.c:814
void imu_set_defaults_accel(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Vect3 *neutral, const struct FloatVect3 *scale_f)
Set the defaults for a accel sensor WARNING: Should be called before sensor is publishing messages to...
Definition imu.c:669
#define IMU_ACCEL_CALIB
Default accel calibration is for single IMU with old format.
Definition imu.c:113
#define IMU_LOG_HIGHSPEED_DEVICE
By default log highspeed on the flightrecorder.
Definition imu.c:182
static void imu_set_body_to_imu_eulers(struct FloatEulers *body_to_imu_eulers)
Set the body to IMU rotation in eulers This will update all the sensor values.
Definition imu.c:1014
static void send_mag_scaled(struct transport_tx *trans, struct link_device *dev)
Definition imu.c:291
static void send_mag_current(struct transport_tx *trans, struct link_device *dev)
Definition imu.c:321
struct Imu imu
global IMU state
Definition imu.c:432
#define IMU_BODY_TO_IMU_PSI
Definition imu.c:156
#define IMU_GYRO_CALIB
Default gyro calibration is for single IMU with old format.
Definition imu.c:74
#define IMU_MAG_Z_SIGN
Definition imu.c:127
void imu_init(void)
External functions.
Definition imu.c:439
void imu_SetBodyToImuPsi(float psi)
Definition imu.c:1059
static abi_event imu_gyro_raw_ev
Definition imu.c:433
static void send_accel_raw(struct transport_tx *trans, struct link_device *dev)
Definition imu.c:189
#define IMU_GYRO_R_SIGN
Definition imu.c:53
void imu_SetBodyToImuCurrent(float set)
Definition imu.c:1067
struct imu_mag_t * imu_get_mag(uint8_t sender_id, bool create)
Find or create the mag in the imu structure.
Definition imu.c:992
static void send_gyro_scaled(struct transport_tx *trans, struct link_device *dev)
Definition imu.c:247
static void send_gyro(struct transport_tx *trans, struct link_device *dev)
Definition imu.c:261
void imu_SetBodyToImuPhi(float phi)
Definition imu.c:1043
static void send_accel(struct transport_tx *trans, struct link_device *dev)
Definition imu.c:217
static void imu_mag_raw_cb(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *data)
Definition imu.c:910
#define IMU_ACCEL_Z_SIGN
Definition imu.c:92
static void send_accel_scaled(struct transport_tx *trans, struct link_device *dev)
Definition imu.c:203
static void send_mag(struct transport_tx *trans, struct link_device *dev)
Definition imu.c:305
static void send_gyro_raw(struct transport_tx *trans, struct link_device *dev)
Definition imu.c:233
#define IMU_ACCEL_ABI_SEND_ID
Which accel measurements to send over telemetry/logging.
Definition imu.c:170
void imu_set_defaults_mag(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Vect3 *neutral, const struct FloatVect3 *scale_f)
Set the defaults for a mag sensor WARNING: Should be called before sensor is publishing messages to e...
Definition imu.c:698
#define IMU_GYRO_Q_SIGN
Definition imu.c:50
Inertial Measurement Unit interface.
uint32_t last_stamp
Last measurement timestamp for integration.
Definition imu.h:53
struct Int32Rates scaled
Last scaled values in body frame.
Definition imu.h:55
struct Int32RMat body_to_sensor
Rotation from body to sensor frame (body to imu combined with imu to sensor)
Definition imu.h:78
struct imu_calib_t calibrated
Calibration bitmask.
Definition imu.h:87
struct FloatVect3 current_scale
Current scaling multiplying.
Definition imu.h:93
struct imu_accel_t accels[IMU_MAX_SENSORS]
The accelerometer sensors.
Definition imu.h:103
struct FloatEulers body_to_sensor_f
Rotation from body to sensor frame (with floating points eulers)
Definition imu.h:79
uint8_t abi_id
ABI sensor ID.
Definition imu.h:52
bool scale
Scale calibrated.
Definition imu.h:43
float temperature
Temperature in degrees celcius.
Definition imu.h:57
Butterworth2LowPass filter[3]
Lowpass filter optional.
Definition imu.h:82
float filter_freq
Lowpass filter frequency (Hz)
Definition imu.h:80
struct FloatRates scale_f
Scaling.
Definition imu.h:60
uint32_t last_stamp
Last measurement timestamp for integration.
Definition imu.h:70
float filter_sample_freq
Lowpass filter sample frequency (Hz)
Definition imu.h:64
struct FloatVect3 scale_f
Scaling.
Definition imu.h:92
struct Int32Vect3 neutral
Neutral values, compensation on unscaled->scaled.
Definition imu.h:90
uint8_t mag_abi_send_id
Filter out and send only a specific ABI id in telemetry for the magnetometer.
Definition imu.h:108
struct OrientationReps body_to_imu
Rotation from body to imu (all sensors) frame.
Definition imu.h:105
bool filter
Enable the lowpass filter.
Definition imu.h:48
struct Int32Vect3 unscaled
Last unscaled values in sensor frame.
Definition imu.h:73
bool rot_euler
Rotation calibrated with floating point eulers.
Definition imu.h:46
float temperature
Temperature in degrees celcius.
Definition imu.h:74
struct Int32Rates neutral
Neutral values, compensation on unscaled->scaled.
Definition imu.h:58
bool current
Current calibrated.
Definition imu.h:47
struct Int32RMat body_to_sensor
Rotation from body to sensor frame (body to imu combined with imu to sensor)
Definition imu.h:94
bool initialized
Check if the IMU is initialized.
Definition imu.h:101
struct FloatEulers body_to_sensor_f
Rotation from body to sensor frame (with floating points eulers)
Definition imu.h:95
Butterworth2LowPass filter[3]
Lowpass filter optional.
Definition imu.h:65
struct imu_calib_t calibrated
Calibration bitmask.
Definition imu.h:71
struct FloatVect3 scale_f
Scaling.
Definition imu.h:77
struct Int32Vect3 scale[2]
Scaling, first is numerator and second denominator.
Definition imu.h:91
bool scale_f
Scale calibrated with floating point.
Definition imu.h:44
struct Int32Rates scale[2]
Scaling, first is numerator and second denominator.
Definition imu.h:59
float filter_sample_freq
Lowpass filter sample frequency (Hz)
Definition imu.h:81
struct Int32Vect3 scaled
Last scaled values in body frame.
Definition imu.h:72
struct imu_gyro_t gyros[IMU_MAX_SENSORS]
The gyro sensors.
Definition imu.h:102
struct Int32RMat body_to_sensor
Rotation from body to sensor frame (body to imu combined with imu to sensor)
Definition imu.h:61
struct Int32Rates unscaled
Last unscaled values in sensor frame.
Definition imu.h:56
uint8_t abi_id
ABI sensor ID.
Definition imu.h:86
struct imu_mag_t mags[IMU_MAX_SENSORS]
The magnetometer sensors.
Definition imu.h:104
struct Int32Vect3 scale[2]
Scaling, first is numerator and second denominator.
Definition imu.h:76
bool neutral
Neutral values calibrated.
Definition imu.h:42
bool b2i_set_current
flag for adjusting body_to_imu via settings.
Definition imu.h:113
struct FloatEulers body_to_sensor_f
Rotation from body to sensor frame (with floating points eulers)
Definition imu.h:62
struct Int32Vect3 neutral
Neutral values, compensation on unscaled->scaled.
Definition imu.h:75
struct Int32Vect3 unscaled
Last unscaled values in sensor frame.
Definition imu.h:89
float filter_freq
Filter frequency.
Definition imu.h:63
#define IMU_MAX_SENSORS
Definition imu.h:38
struct imu_calib_t calibrated
Calibration bitmask.
Definition imu.h:54
uint8_t accel_abi_send_id
Filter out and send only a specific ABI id in telemetry for the accelerometer.
Definition imu.h:107
struct Int32Vect3 scaled
Last scaled values in body frame.
Definition imu.h:88
bool rotation
Rotation calibrated.
Definition imu.h:45
uint8_t gyro_abi_send_id
Filter out and send only a specific ABI id in telemetry for the gyro.
Definition imu.h:106
uint8_t abi_id
ABI sensor ID.
Definition imu.h:69
abstract IMU interface providing fixed point interface
Definition imu.h:100
static float p[2][2]
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
static void init_butterworth_2_low_pass(Butterworth2LowPass *filter, const float tau, const float sample_time, const float value)
Init a second order Butterworth filter.
static float update_butterworth_2_low_pass(Butterworth2LowPass *filter, const float value)
Update second order Butterworth low pass filter state with a new value.
static TRICAL_instance_t mag_calib
uint16_t foo
Definition main_demo5.c:58
PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF)
struct pprzlog_transport pprzlog_tp
PPRZLOG transport structure.
Definition pprzlog_tp.c:29
Mini printf-like functionality.
void shell_add_entry(char *cmd_name, shell_cmd_t *cmd)
Add dynamic entry.
Definition shell_arch.c:91
BaseSequentialStream shell_stream_t
Definition shell_arch.h:31
API to get/set the generic vehicle states.
int16_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint16_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition telemetry.h:66
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
int int32_t
Typedef defining 32 bit int type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.