Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
mag_calib_ukf.c
Go to the documentation of this file.
1/*
2 * Copyright (C) w.vlenterie
3 *
4 * This file is part of paparazzi
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
30
32#include "state.h"
33#include "modules/imu/imu.h"
34#include "modules/core/abi.h"
35#include "generated/airframe.h"
38#include "TRICAL.h"
39
40//
41// Try to print warnings to user for bad configuration
42//
43#if !defined AHRS_FC_MAG_ID && !defined AHRS_ICE_MAG_ID && !defined AHRS_MLKF_MAG_ID && !defined AHRS_FINV_MAG_ID && \
44 !defined AHRS_DCM_MAG_ID && !defined AHRS_ICQ_MAG_ID && !defined INS_FINV_MAG_ID
45#warning "your AHRS/INS configuration might be wrong to use onboard mag calibration, please refer to the documentation"
46#endif
47
48#if defined AHRS_FC_MAG_ID && (AHRS_FC_MAG_ID != MAG_CALIB_UKF_ID)
49#warning "your AHRS_FC_MAG_ID might by wrong please set to MAG_CALIB_UKF_ID to use onboard mag calibration"
50#endif
51
52#if defined AHRS_ICE_MAG_ID && (AHRS_ICE_MAG_ID != MAG_CALIB_UKF_ID)
53#warning "your AHRS_ICE_MAG_ID might by wrong please set to MAG_CALIB_UKF_ID to use onboard mag calibration"
54#endif
55
56#if defined AHRS_MLKF_MAG_ID && (AHRS_MLKF_MAG_ID != MAG_CALIB_UKF_ID)
57#warning "your AHRS_MLKF_MAG_ID might by wrong please set to MAG_CALIB_UKF_ID to use onboard mag calibration"
58#endif
59
60#if defined AHRS_FINV_MAG_ID && (AHRS_FINV_MAG_ID != MAG_CALIB_UKF_ID)
61#warning "your AHRS_FINV_MAG_ID might by wrong please set to MAG_CALIB_UKF_ID to use onboard mag calibration"
62#endif
63
64#if defined AHRS_DCM_MAG_ID && (AHRS_DCM_MAG_ID != MAG_CALIB_UKF_ID)
65#warning "your AHRS_DCM_MAG_ID might by wrong please set to MAG_CALIB_UKF_ID to use onboard mag calibration"
66#endif
67
68#if defined AHRS_ICQ_MAG_ID && (AHRS_ICQ_MAG_ID != MAG_CALIB_UKF_ID)
69#warning "your AHRS_ICQ_MAG_ID might by wrong please set to MAG_CALIB_UKF_ID to use onboard mag calibration"
70#endif
71
72#if defined INS_FINV_MAG_ID && (INS_FINV_MAG_ID != MAG_CALIB_UKF_ID)
73#warning "your INS_FINV_MAG_ID might by wrong please set to MAG_CALIB_UKF_ID to use onboard mag calibration"
74#endif
75
76// ABI callback declarations
79
80// Verbose mode is only available on Linux-based autopilots
81#ifndef MAG_CALIB_UKF_VERBOSE
82#define MAG_CALIB_UKF_VERBOSE FALSE
83#endif
84
85#if MAG_CALIB_UKF_VERBOSE
86#include <stdio.h>
87#define VERBOSE_PRINT(string,...) fprintf(stderr, "[CALIB_UKF->%s()] " string,__FUNCTION__ , ##__VA_ARGS__)
88#else
89#define VERBOSE_PRINT(...)
90#endif
92
93#ifndef MAG_CALIB_UKF_ABI_BIND_ID
94#define MAG_CALIB_UKF_ABI_BIND_ID ABI_BROADCAST
95#endif
97
98#ifndef MAG_CALIB_UKF_NORM
99#define MAG_CALIB_UKF_NORM 1.0f
100#endif
102
103#ifndef MAG_CALIB_UKF_NOISE_RMS
104#define MAG_CALIB_UKF_NOISE_RMS 2e-1f
105#endif
107
108// Hotstart is only available on Linux-based autopilots
109#ifndef MAG_CALIB_UKF_HOTSTART
110#define MAG_CALIB_UKF_HOTSTART FALSE
111#endif
113
114#ifndef MAG_CALIB_UKF_HOTSTART_SAVE_FILE
115#define MAG_CALIB_UKF_HOTSTART_SAVE_FILE /data/ftp/internal_000/mag_ukf_calib.txt
116#endif
118
122
126
127static struct FloatVect3 H = { .x = AHRS_H_X, .y = AHRS_H_Y, .z = AHRS_H_Z};
128
129#if MAG_CALIB_UKF_HOTSTART
130static FILE *fp;
131static char hotstart_file_name[512];
132#endif
133
147
151{
152 float measurement[3] = {0.0f, 0.0f, 0.0f};
153 float calibrated_measurement[3] = {0.0f, 0.0f, 0.0f};
154
160 }
164 }
166 if (mag->x != 0 || mag->y != 0 || mag->z != 0) {
173 measurement[0] = MAG_FLOAT_OF_BFP(mag->x);
174 measurement[1] = MAG_FLOAT_OF_BFP(mag->y);
175 measurement[2] = MAG_FLOAT_OF_BFP(mag->z);
182 imu.mag.x = calibrated_mag.x;
183 imu.mag.y = calibrated_mag.y;
184 imu.mag.z = calibrated_mag.z;
185
187 VERBOSE_PRINT("magnetometer measurement (x: %4.2f y: %4.2f z: %4.2f) norm: %4.2f\n", measurement[0], measurement[1], measurement[2], hypot(hypot(measurement[0], measurement[1]), measurement[2]));
188 VERBOSE_PRINT("magnetometer bias_f (x: %4.2f y: %4.2f z: %4.2f)\n", mag_calib.state[0], mag_calib.state[1], mag_calib.state[2]);
189 VERBOSE_PRINT("expected measurement (x: %4.2f y: %4.2f z: %4.2f) norm: %4.2f\n", expected_mag_field[0], expected_mag_field[1], expected_mag_field[2], hypot(hypot(expected_mag_field[0], expected_mag_field[1]), expected_mag_field[2]));
190 VERBOSE_PRINT("calibrated measurement (x: %4.2f y: %4.2f z: %4.2f) norm: %4.2f\n\n", calibrated_measurement[0], calibrated_measurement[1], calibrated_measurement[2], hypot(hypot(calibrated_measurement[0], calibrated_measurement[1]), calibrated_measurement[2]));
193 }
194 }
195}
196
200{
201 double n = float_vect3_norm(h);
202 if (n > 0.01) {
203 H.x = (float)(h->x / n);
204 H.y = (float)(h->y / n);
205 H.z = (float)(h->z / n);
206 VERBOSE_PRINT("Updating local magnetic field from geo_mag module (Hx: %4.2f, Hy: %4.2f, Hz: %4.2f)\n", H.x, H.y, H.z);
207 }
208}
209
214
216{
217#if MAG_CALIB_UKF_HOTSTART
220 if (fp != NULL) {
221 fread(mag_calib.state, sizeof(float), 12, fp);
222 fclose(fp);
223 VERBOSE_PRINT("Loaded initial state from disk:\n"
224 "bias {%4.2f, %4.2f, %4.2f}\n"
225 "scale {%4.2f, %4.2f, %4.2f}\n"
226 " {%4.2f, %4.2f, %4.2f}\n"
227 " {%4.2f, %4.2f, %4.2f}\n",
228 mag_calib.state[0], mag_calib.state[1], mag_calib.state[2],
229 mag_calib.state[3], mag_calib.state[4], mag_calib.state[5],
230 mag_calib.state[6], mag_calib.state[7], mag_calib.state[8],
231 mag_calib.state[9], mag_calib.state[10], mag_calib.state[11]
232 );
233 }
234#endif
235}
236
238{
239#if USE_MAGNETOMETER && MAG_CALIB_UKF_HOTSTART
241 if (fp != NULL) {
242 fwrite(mag_calib.state, sizeof(float), 12, fp);
243 fclose(fp);
244 VERBOSE_PRINT("Wrote current state to disk:\n"
245 "bias {%4.2f, %4.2f, %4.2f}\n"
246 "scale {%4.2f, %4.2f, %4.2f}\n"
247 " {%4.2f, %4.2f, %4.2f}\n"
248 " {%4.2f, %4.2f, %4.2f}\n",
249 mag_calib.state[0], mag_calib.state[1], mag_calib.state[2],
250 mag_calib.state[3], mag_calib.state[4], mag_calib.state[5],
251 mag_calib.state[6], mag_calib.state[7], mag_calib.state[8],
252 mag_calib.state[9], mag_calib.state[10], mag_calib.state[11]
253 );
254 }
255#endif
256}
static void h(const real32_T x[7], const real32_T q[4], real32_T y[6])
Main include for ABI (AirBorneInterface).
#define ABI_BROADCAST
Broadcast address.
Definition abi_common.h:58
Event structure to store callbacks in a linked list.
Definition abi_common.h:67
#define MAG_CALIB_UKF_ID
void float_quat_vmult(struct FloatVect3 *v_out, struct FloatQuat *q, const struct FloatVect3 *v_in)
rotate 3D vector by quaternion.
static float float_vect3_norm(struct FloatVect3 *v)
Roation quaternion.
#define MAG_BFP_OF_REAL(_af)
#define MAG_FLOAT_OF_BFP(_ai)
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition state.h:1294
struct Imu imu
global IMU state
Definition imu.c:422
Inertial Measurement Unit interface.
#define VERBOSE_PRINT(...)
void mag_calib_ukf_init(void)
void mag_calib_send_state(void)
bool mag_calib_ukf_send_state
#define MAG_CALIB_UKF_HOTSTART_SAVE_FILE
static abi_event mag_ev
static void mag_calib_update_field(uint8_t sender_id, struct FloatVect3 *h)
Callback function to update reference magnetic field from geo_mag module.
static struct FloatVect3 H
static abi_event h_ev
void mag_calib_hotstart_read(void)
bool mag_calib_ukf_reset_state
#define MAG_CALIB_UKF_ABI_BIND_ID
#define MAG_CALIB_UKF_VERBOSE
#define MAG_CALIB_UKF_HOTSTART
#define MAG_CALIB_UKF_NOISE_RMS
static TRICAL_instance_t mag_calib
struct Int32Vect3 calibrated_mag
static void mag_calib_ukf_run(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *mag)
Callback function run for every new mag measurement.
void mag_calib_hotstart_write(void)
#define MAG_CALIB_UKF_NORM
uint16_t foo
Definition main_demo5.c:58
#define false
Definition microrl.h:7
PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF)
Paparazzi double precision floating point algebra.
API to get/set the generic vehicle states.
Periodic telemetry system header (includes downlink utility and generated code).
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.