LP-500 HoTT Telemetry added device definitions
[librepilot.git] / flight / modules / StateEstimation / stateestimation.c
blobad06cba0e49ec94471d4ef4a3318ab1c9582bbdd
1 /**
2 ******************************************************************************
3 * @addtogroup OpenPilotModules OpenPilot Modules
4 * @{
5 * @addtogroup State Estimation
6 * @brief Acquires sensor data and computes state estimate
7 * @{
9 * @file stateestimation.c
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
11 * @brief Module to handle all comms to the AHRS on a periodic basis.
13 * @see The GNU Public License (GPL) Version 3
15 ******************************************************************************/
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 3 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 * for more details.
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "inc/stateestimation.h"
34 #include <callbackinfo.h>
36 #include <gyrosensor.h>
37 #include <accelsensor.h>
38 #include <magsensor.h>
39 #include <barosensor.h>
40 #include <airspeedsensor.h>
41 #include <gpspositionsensor.h>
42 #include <gpsvelocitysensor.h>
43 #include <homelocation.h>
44 #include <auxmagsensor.h>
45 #include <auxmagsettings.h>
47 #include <gyrostate.h>
48 #include <accelstate.h>
49 #include <magstate.h>
50 #include <airspeedstate.h>
51 #include <attitudestate.h>
52 #include <positionstate.h>
53 #include <velocitystate.h>
55 #include "revosettings.h"
56 #include "flightstatus.h"
58 #include "CoordinateConversions.h"
60 // Private constants
61 #define STACK_SIZE_BYTES 256
62 #define CALLBACK_PRIORITY CALLBACK_PRIORITY_REGULAR
63 #define TASK_PRIORITY CALLBACK_TASK_FLIGHTCONTROL
64 #define TIMEOUT_MS 10
66 // Private filter init const
67 #define FILTER_INIT_FORCE -1
68 #define FILTER_INIT_IF_POSSIBLE -2
70 // local macros, ONLY to be used in the middle of StateEstimationCb in section RUNSTATE_LOAD after the update of states updated!
71 #define FETCH_SENSOR_FROM_UAVOBJECT_CHECK_AND_LOAD_TO_STATE_3_DIMENSIONS(sensorname, shortname, a1, a2, a3) \
72 if (IS_SET(states.updated, SENSORUPDATES_##shortname)) { \
73 sensorname##Data s; \
74 sensorname##Get(&s); \
75 if (IS_REAL(s.a1) && IS_REAL(s.a2) && IS_REAL(s.a3)) { \
76 states.shortname[0] = s.a1; \
77 states.shortname[1] = s.a2; \
78 states.shortname[2] = s.a3; \
79 } \
80 else { \
81 UNSET_MASK(states.updated, SENSORUPDATES_##shortname); \
82 } \
85 #define FETCH_SENSOR_FROM_UAVOBJECT_CHECK_AND_LOAD_TO_STATE_1_DIMENSION_WITH_CUSTOM_EXTRA_CHECK(sensorname, shortname, a1, EXTRACHECK) \
86 if (IS_SET(states.updated, SENSORUPDATES_##shortname)) { \
87 sensorname##Data s; \
88 sensorname##Get(&s); \
89 if (IS_REAL(s.a1) && EXTRACHECK) { \
90 states.shortname[0] = s.a1; \
91 } \
92 else { \
93 UNSET_MASK(states.updated, SENSORUPDATES_##shortname); \
94 } \
97 #define FETCH_SENSOR_FROM_UAVOBJECT_CHECK_AND_LOAD_TO_STATE_2_DIMENSION_WITH_CUSTOM_EXTRA_CHECK(sensorname, shortname, a1, a2, EXTRACHECK) \
98 if (IS_SET(states.updated, SENSORUPDATES_##shortname)) { \
99 sensorname##Data s; \
100 sensorname##Get(&s); \
101 if (IS_REAL(s.a1) && IS_REAL(s.a2) && EXTRACHECK) { \
102 states.shortname[0] = s.a1; \
103 states.shortname[1] = s.a2; \
105 else { \
106 UNSET_MASK(states.updated, SENSORUPDATES_##shortname); \
110 // local macros, ONLY to be used in the middle of StateEstimationCb in section RUNSTATE_SAVE before the check of alarms!
111 #define EXPORT_STATE_TO_UAVOBJECT_IF_UPDATED_3_DIMENSIONS(statename, shortname, a1, a2, a3) \
112 if (IS_SET(states.updated, SENSORUPDATES_##shortname)) { \
113 statename##Data s; \
114 statename##Get(&s); \
115 s.a1 = states.shortname[0]; \
116 s.a2 = states.shortname[1]; \
117 s.a3 = states.shortname[2]; \
118 statename##Set(&s); \
121 #define EXPORT_STATE_TO_UAVOBJECT_IF_UPDATED_2_DIMENSIONS(statename, shortname, a1, a2) \
122 if (IS_SET(states.updated, SENSORUPDATES_##shortname)) { \
123 statename##Data s; \
124 statename##Get(&s); \
125 s.a1 = states.shortname[0]; \
126 s.a2 = states.shortname[1]; \
127 statename##Set(&s); \
131 // Private types
132 struct filterPipelineStruct;
134 typedef const struct filterPipelineStruct {
135 const stateFilter *filter;
136 const struct filterPipelineStruct *next;
137 } filterPipeline;
139 // Private variables
140 static DelayedCallbackInfo *stateEstimationCallback;
142 static volatile RevoSettingsData revoSettings;
143 static volatile sensorUpdates updatedSensors;
144 static volatile int32_t fusionAlgorithm = -1;
145 static const filterPipeline *filterChain = NULL;
147 // different filters available to state estimation
148 static stateFilter magFilter;
149 static stateFilter baroFilter;
150 static stateFilter baroiFilter;
151 static stateFilter velocityFilter;
152 static stateFilter altitudeFilter;
153 static stateFilter airFilter;
154 static stateFilter stationaryFilter;
155 static stateFilter llaFilter;
156 static stateFilter cfFilter;
157 static stateFilter cfmFilter;
158 static stateFilter ekf13iFilter;
159 static stateFilter ekf13Filter;
160 static stateFilter ekf13iNavFilter;
161 static stateFilter ekf13NavFilter;
163 // this is a hack to provide a computational shortcut for faster gyro state progression
164 static float gyroRaw[3];
165 static float gyroDelta[3];
167 // preconfigured filter chains selectable via revoSettings.FusionAlgorithm
168 static const filterPipeline *cfQueue = &(filterPipeline) {
169 .filter = &airFilter,
170 .next = &(filterPipeline) {
171 .filter = &baroiFilter,
172 .next = &(filterPipeline) {
173 .filter = &altitudeFilter,
174 .next = &(filterPipeline) {
175 .filter = &cfFilter,
176 .next = NULL,
181 static const filterPipeline *cfmiQueue = &(filterPipeline) {
182 .filter = &magFilter,
183 .next = &(filterPipeline) {
184 .filter = &airFilter,
185 .next = &(filterPipeline) {
186 .filter = &baroiFilter,
187 .next = &(filterPipeline) {
188 .filter = &altitudeFilter,
189 .next = &(filterPipeline) {
190 .filter = &cfmFilter,
191 .next = NULL,
197 static const filterPipeline *cfmQueue = &(filterPipeline) {
198 .filter = &magFilter,
199 .next = &(filterPipeline) {
200 .filter = &airFilter,
201 .next = &(filterPipeline) {
202 .filter = &llaFilter,
203 .next = &(filterPipeline) {
204 .filter = &baroFilter,
205 .next = &(filterPipeline) {
206 .filter = &altitudeFilter,
207 .next = &(filterPipeline) {
208 .filter = &cfmFilter,
209 .next = NULL,
216 static const filterPipeline *ekf13iQueue = &(filterPipeline) {
217 .filter = &magFilter,
218 .next = &(filterPipeline) {
219 .filter = &airFilter,
220 .next = &(filterPipeline) {
221 .filter = &baroiFilter,
222 .next = &(filterPipeline) {
223 .filter = &stationaryFilter,
224 .next = &(filterPipeline) {
225 .filter = &ekf13iFilter,
226 .next = &(filterPipeline) {
227 .filter = &velocityFilter,
228 .next = NULL,
236 static const filterPipeline *ekf13Queue = &(filterPipeline) {
237 .filter = &magFilter,
238 .next = &(filterPipeline) {
239 .filter = &airFilter,
240 .next = &(filterPipeline) {
241 .filter = &llaFilter,
242 .next = &(filterPipeline) {
243 .filter = &baroFilter,
244 .next = &(filterPipeline) {
245 .filter = &ekf13Filter,
246 .next = &(filterPipeline) {
247 .filter = &velocityFilter,
248 .next = NULL,
256 static const filterPipeline *ekf13NavCFAttQueue = &(filterPipeline) {
257 .filter = &magFilter,
258 .next = &(filterPipeline) {
259 .filter = &airFilter,
260 .next = &(filterPipeline) {
261 .filter = &llaFilter,
262 .next = &(filterPipeline) {
263 .filter = &baroFilter,
264 .next = &(filterPipeline) {
265 .filter = &ekf13NavFilter,
266 .next = &(filterPipeline) {
267 .filter = &velocityFilter,
268 .next = &(filterPipeline) {
269 .filter = &cfmFilter,
270 .next = NULL,
279 static const filterPipeline *ekf13iNavCFAttQueue = &(filterPipeline) {
280 .filter = &magFilter,
281 .next = &(filterPipeline) {
282 .filter = &airFilter,
283 .next = &(filterPipeline) {
284 .filter = &baroiFilter,
285 .next = &(filterPipeline) {
286 .filter = &stationaryFilter,
287 .next = &(filterPipeline) {
288 .filter = &ekf13iNavFilter,
289 .next = &(filterPipeline) {
290 .filter = &velocityFilter,
291 .next = &(filterPipeline) {
292 .filter = &cfmFilter,
293 .next = NULL,
302 // Private functions
304 static void settingsUpdatedCb(UAVObjEvent *objEv);
305 static void sensorUpdatedCb(UAVObjEvent *objEv);
306 static void criticalConfigUpdatedCb(UAVObjEvent *objEv);
307 static void StateEstimationCb(void);
309 static inline int32_t maxint32_t(int32_t a, int32_t b)
311 if (a > b) {
312 return a;
314 return b;
318 * Initialise the module. Called before the start function
319 * \returns 0 on success or -1 if initialisation failed
321 int32_t StateEstimationInitialize(void)
323 RevoSettingsInitialize();
325 GyroSensorInitialize();
326 MagSensorInitialize();
327 AuxMagSensorInitialize();
328 BaroSensorInitialize();
329 AirspeedSensorInitialize();
330 GPSVelocitySensorInitialize();
331 GPSPositionSensorInitialize();
333 HomeLocationInitialize();
335 GyroStateInitialize();
336 AccelStateInitialize();
337 MagStateInitialize();
338 AirspeedStateInitialize();
339 PositionStateInitialize();
340 VelocityStateInitialize();
341 AuxMagSettingsInitialize();
343 RevoSettingsConnectCallback(&settingsUpdatedCb);
345 HomeLocationConnectCallback(&criticalConfigUpdatedCb);
346 AuxMagSettingsConnectCallback(&criticalConfigUpdatedCb);
348 GyroSensorConnectCallback(&sensorUpdatedCb);
349 AccelSensorConnectCallback(&sensorUpdatedCb);
350 MagSensorConnectCallback(&sensorUpdatedCb);
351 BaroSensorConnectCallback(&sensorUpdatedCb);
352 AirspeedSensorConnectCallback(&sensorUpdatedCb);
353 AuxMagSensorConnectCallback(&sensorUpdatedCb);
354 GPSVelocitySensorConnectCallback(&sensorUpdatedCb);
355 GPSPositionSensorConnectCallback(&sensorUpdatedCb);
357 uint32_t stack_required = STACK_SIZE_BYTES;
358 // Initialize Filters
359 stack_required = maxint32_t(stack_required, filterMagInitialize(&magFilter));
360 stack_required = maxint32_t(stack_required, filterBaroiInitialize(&baroiFilter));
361 stack_required = maxint32_t(stack_required, filterBaroInitialize(&baroFilter));
362 stack_required = maxint32_t(stack_required, filterVelocityInitialize(&velocityFilter));
363 stack_required = maxint32_t(stack_required, filterAltitudeInitialize(&altitudeFilter));
364 stack_required = maxint32_t(stack_required, filterAirInitialize(&airFilter));
365 stack_required = maxint32_t(stack_required, filterStationaryInitialize(&stationaryFilter));
366 stack_required = maxint32_t(stack_required, filterLLAInitialize(&llaFilter));
367 stack_required = maxint32_t(stack_required, filterCFInitialize(&cfFilter));
368 stack_required = maxint32_t(stack_required, filterCFMInitialize(&cfmFilter));
369 stack_required = maxint32_t(stack_required, filterEKF13iInitialize(&ekf13iFilter));
370 stack_required = maxint32_t(stack_required, filterEKF13Initialize(&ekf13Filter));
371 stack_required = maxint32_t(stack_required, filterEKF13NavOnlyInitialize(&ekf13NavFilter));
372 stack_required = maxint32_t(stack_required, filterEKF13iNavOnlyInitialize(&ekf13iNavFilter));
374 stateEstimationCallback = PIOS_CALLBACKSCHEDULER_Create(&StateEstimationCb, CALLBACK_PRIORITY, TASK_PRIORITY, CALLBACKINFO_RUNNING_STATEESTIMATION, stack_required);
376 return 0;
380 * Start the task. Expects all objects to be initialized by this point.
381 * \returns 0 on success or -1 if initialisation failed
383 int32_t StateEstimationStart(void)
385 RevoSettingsConnectCallback(&settingsUpdatedCb);
387 // Force settings update to make sure rotation loaded
388 settingsUpdatedCb(NULL);
390 return 0;
393 MODULE_INITCALL(StateEstimationInitialize, StateEstimationStart);
397 * Module callback
399 static void StateEstimationCb(void)
401 static filterResult alarm = FILTERRESULT_OK;
402 static filterResult lastAlarm = FILTERRESULT_UNINITIALISED;
403 static bool lastNavStatus = false;
404 static uint16_t alarmcounter = 0;
405 static uint16_t navstatuscounter = 0;
406 static const filterPipeline *current;
407 static stateEstimation states;
408 static uint32_t last_time;
409 static uint16_t bootDelay = 64;
411 // after system startup, first few sensor readings might be messed up, delay until everything has settled
412 if (bootDelay) {
413 bootDelay--;
414 PIOS_CALLBACKSCHEDULER_Schedule(stateEstimationCallback, TIMEOUT_MS, CALLBACK_UPDATEMODE_SOONER);
415 return;
418 alarm = FILTERRESULT_OK;
420 // set alarm to warning if called through timeout
421 if (updatedSensors == 0) {
422 if (PIOS_DELAY_DiffuS(last_time) > 1000 * TIMEOUT_MS) {
423 alarm = FILTERRESULT_WARNING;
425 } else {
426 last_time = PIOS_DELAY_GetRaw();
428 FlightStatusArmedOptions fsarmed;
429 FlightStatusArmedGet(&fsarmed);
430 states.armed = fsarmed != FLIGHTSTATUS_ARMED_DISARMED;
432 // check if a new filter chain should be initialized
433 if (fusionAlgorithm != revoSettings.FusionAlgorithm) {
434 if (fsarmed == FLIGHTSTATUS_ARMED_DISARMED || fusionAlgorithm == FILTER_INIT_FORCE) {
435 const filterPipeline *newFilterChain;
436 switch ((RevoSettingsFusionAlgorithmOptions)revoSettings.FusionAlgorithm) {
437 case REVOSETTINGS_FUSIONALGORITHM_BASICCOMPLEMENTARY:
438 newFilterChain = cfQueue;
439 // reinit Mag alarm
440 AlarmsSet(SYSTEMALARMS_ALARM_MAGNETOMETER, SYSTEMALARMS_ALARM_UNINITIALISED);
441 break;
442 case REVOSETTINGS_FUSIONALGORITHM_COMPLEMENTARYMAG:
443 newFilterChain = cfmiQueue;
444 break;
445 case REVOSETTINGS_FUSIONALGORITHM_COMPLEMENTARYMAGGPSOUTDOOR:
446 newFilterChain = cfmQueue;
447 break;
448 case REVOSETTINGS_FUSIONALGORITHM_INS13INDOOR:
449 newFilterChain = ekf13iQueue;
450 break;
451 case REVOSETTINGS_FUSIONALGORITHM_GPSNAVIGATIONINS13:
452 newFilterChain = ekf13Queue;
453 break;
454 case REVOSETTINGS_FUSIONALGORITHM_GPSNAVIGATIONINS13CF:
455 newFilterChain = ekf13NavCFAttQueue;
456 break;
457 case REVOSETTINGS_FUSIONALGORITHM_TESTINGINSINDOORCF:
458 newFilterChain = ekf13iNavCFAttQueue;
459 break;
460 default:
461 newFilterChain = NULL;
463 // initialize filters in chain
464 current = newFilterChain;
465 bool error = 0;
466 states.debugNavYaw = 0;
467 states.navOk = false;
468 states.navUsed = false;
469 while (current != NULL) {
470 int32_t result = current->filter->init((stateFilter *)current->filter);
471 if (result != 0) {
472 error = 1;
473 break;
475 current = current->next;
477 if (error) {
478 AlarmsSet(SYSTEMALARMS_ALARM_ATTITUDE, SYSTEMALARMS_ALARM_ERROR);
479 return;
480 } else {
481 // set new fusion algorithm
482 filterChain = newFilterChain;
483 fusionAlgorithm = revoSettings.FusionAlgorithm;
488 // read updated sensor UAVObjects and set initial state
489 states.updated = updatedSensors;
490 updatedSensors = 0;
492 // fetch sensors, check values, and load into state struct
493 FETCH_SENSOR_FROM_UAVOBJECT_CHECK_AND_LOAD_TO_STATE_3_DIMENSIONS(GyroSensor, gyro, x, y, z);
494 if (IS_SET(states.updated, SENSORUPDATES_gyro)) {
495 gyroRaw[0] = states.gyro[0];
496 gyroRaw[1] = states.gyro[1];
497 gyroRaw[2] = states.gyro[2];
499 FETCH_SENSOR_FROM_UAVOBJECT_CHECK_AND_LOAD_TO_STATE_3_DIMENSIONS(AccelSensor, accel, x, y, z);
500 FETCH_SENSOR_FROM_UAVOBJECT_CHECK_AND_LOAD_TO_STATE_3_DIMENSIONS(MagSensor, boardMag, x, y, z);
501 FETCH_SENSOR_FROM_UAVOBJECT_CHECK_AND_LOAD_TO_STATE_3_DIMENSIONS(AuxMagSensor, auxMag, x, y, z);
502 FETCH_SENSOR_FROM_UAVOBJECT_CHECK_AND_LOAD_TO_STATE_3_DIMENSIONS(GPSVelocitySensor, vel, North, East, Down);
503 FETCH_SENSOR_FROM_UAVOBJECT_CHECK_AND_LOAD_TO_STATE_1_DIMENSION_WITH_CUSTOM_EXTRA_CHECK(BaroSensor, baro, Altitude, true);
504 FETCH_SENSOR_FROM_UAVOBJECT_CHECK_AND_LOAD_TO_STATE_2_DIMENSION_WITH_CUSTOM_EXTRA_CHECK(AirspeedSensor, airspeed, CalibratedAirspeed, TrueAirspeed, s.SensorConnected == AIRSPEEDSENSOR_SENSORCONNECTED_TRUE);
506 // GPS position data (LLA) is not fetched here since it does not contain floats. The filter must do all checks itself
508 // at this point sensor state is stored in "states" with some rudimentary filtering applied
510 // apply all filters in the current filter chain
511 current = filterChain;
513 // we are not done, re-dispatch self execution
515 while (current) {
516 filterResult result = current->filter->filter((stateFilter *)current->filter, &states);
517 if (result > alarm) {
518 alarm = result;
520 current = current->next;
523 // the final output of filters is saved in state variables
524 // EXPORT_STATE_TO_UAVOBJECT_IF_UPDATED_3_DIMENSIONS(GyroState, gyro, x, y, z) // replaced by performance shortcut
525 if (IS_SET(states.updated, SENSORUPDATES_gyro)) {
526 gyroDelta[0] = states.gyro[0] - gyroRaw[0];
527 gyroDelta[1] = states.gyro[1] - gyroRaw[1];
528 gyroDelta[2] = states.gyro[2] - gyroRaw[2];
530 EXPORT_STATE_TO_UAVOBJECT_IF_UPDATED_3_DIMENSIONS(AccelState, accel, x, y, z);
531 if (IS_SET(states.updated, SENSORUPDATES_mag)) {
532 MagStateData s;
534 MagStateGet(&s);
535 s.x = states.mag[0];
536 s.y = states.mag[1];
537 s.z = states.mag[2];
538 switch (states.magStatus) {
539 case MAGSTATUS_OK:
540 s.Source = MAGSTATE_SOURCE_ONBOARD;
541 break;
542 case MAGSTATUS_AUX:
543 s.Source = MAGSTATE_SOURCE_AUX;
544 break;
545 default:
546 s.Source = MAGSTATE_SOURCE_INVALID;
548 MagStateSet(&s);
551 EXPORT_STATE_TO_UAVOBJECT_IF_UPDATED_3_DIMENSIONS(PositionState, pos, North, East, Down);
552 EXPORT_STATE_TO_UAVOBJECT_IF_UPDATED_3_DIMENSIONS(VelocityState, vel, North, East, Down);
553 EXPORT_STATE_TO_UAVOBJECT_IF_UPDATED_2_DIMENSIONS(AirspeedState, airspeed, CalibratedAirspeed, TrueAirspeed);
554 // attitude nees manual conversion from quaternion to euler
555 if (IS_SET(states.updated, SENSORUPDATES_attitude)) { \
556 AttitudeStateData s;
557 AttitudeStateGet(&s);
558 s.q1 = states.attitude[0];
559 s.q2 = states.attitude[1];
560 s.q3 = states.attitude[2];
561 s.q4 = states.attitude[3];
562 Quaternion2RPY(&s.q1, &s.Roll);
563 s.NavYaw = states.debugNavYaw;
564 AttitudeStateSet(&s);
566 // throttle alarms, raise alarm flags immediately
567 // but require system to run for a while before decreasing
568 // to prevent alarm flapping
569 if (alarm >= lastAlarm) {
570 lastAlarm = alarm;
571 alarmcounter = 0;
572 } else {
573 if (alarmcounter < 100) {
574 alarmcounter++;
575 } else {
576 lastAlarm = alarm;
577 alarmcounter = 0;
581 if (lastNavStatus < states.navOk) {
582 lastNavStatus = states.navOk;
583 navstatuscounter = 0;
584 } else {
585 if (navstatuscounter < 100) {
586 navstatuscounter++;
587 } else {
588 lastNavStatus = states.navOk;
589 navstatuscounter = 0;
593 // clear alarms if everything is alright, then schedule callback execution after timeout
594 if (lastAlarm == FILTERRESULT_WARNING) {
595 AlarmsSet(SYSTEMALARMS_ALARM_ATTITUDE, SYSTEMALARMS_ALARM_WARNING);
596 } else if (lastAlarm == FILTERRESULT_CRITICAL) {
597 AlarmsSet(SYSTEMALARMS_ALARM_ATTITUDE, SYSTEMALARMS_ALARM_CRITICAL);
598 } else if (lastAlarm >= FILTERRESULT_ERROR) {
599 AlarmsSet(SYSTEMALARMS_ALARM_ATTITUDE, SYSTEMALARMS_ALARM_ERROR);
600 } else {
601 AlarmsClear(SYSTEMALARMS_ALARM_ATTITUDE);
604 if (!states.navUsed) {
605 AlarmsSet(SYSTEMALARMS_ALARM_NAV, SYSTEMALARMS_ALARM_UNINITIALISED);
606 } else {
607 if (states.navOk) {
608 AlarmsClear(SYSTEMALARMS_ALARM_NAV);
609 } else {
610 AlarmsSet(SYSTEMALARMS_ALARM_NAV, SYSTEMALARMS_ALARM_CRITICAL);
614 if (updatedSensors) {
615 PIOS_CALLBACKSCHEDULER_Dispatch(stateEstimationCallback);
616 } else {
617 PIOS_CALLBACKSCHEDULER_Schedule(stateEstimationCallback, TIMEOUT_MS, CALLBACK_UPDATEMODE_SOONER);
623 * Callback for eventdispatcher when RevoSettings has been updated
625 static void settingsUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
627 RevoSettingsGet((RevoSettingsData *)&revoSettings);
631 * Callback for eventdispatcher when HomeLocation or other critical configs (auxmagsettings, ...) has been updated
633 static void criticalConfigUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
635 // Ask for a filter init (necessary for LLA filter)
636 // Only possible if disarmed
637 fusionAlgorithm = FILTER_INIT_IF_POSSIBLE;
642 * Callback for eventdispatcher when any sensor UAVObject has been updated
643 * updates the list of "recently updated UAVObjects" and dispatches the state estimator callback
645 static void sensorUpdatedCb(UAVObjEvent *ev)
647 if (!ev) {
648 return;
651 if (ev->obj == GyroSensorHandle()) {
652 updatedSensors |= SENSORUPDATES_gyro;
653 // shortcut - update GyroState right away
654 GyroSensorData s;
655 GyroStateData t;
656 GyroSensorGet(&s);
657 t.x = s.x + gyroDelta[0];
658 t.y = s.y + gyroDelta[1];
659 t.z = s.z + gyroDelta[2];
660 t.SensorReadTimestamp = s.SensorReadTimestamp;
661 GyroStateSet(&t);
664 if (ev->obj == AccelSensorHandle()) {
665 updatedSensors |= SENSORUPDATES_accel;
668 if (ev->obj == MagSensorHandle()) {
669 updatedSensors |= SENSORUPDATES_boardMag;
672 if (ev->obj == AuxMagSensorHandle()) {
673 updatedSensors |= SENSORUPDATES_auxMag;
676 if (ev->obj == GPSPositionSensorHandle()) {
677 updatedSensors |= SENSORUPDATES_lla;
680 if (ev->obj == GPSVelocitySensorHandle()) {
681 updatedSensors |= SENSORUPDATES_vel;
684 if (ev->obj == BaroSensorHandle()) {
685 updatedSensors |= SENSORUPDATES_baro;
688 if (ev->obj == AirspeedSensorHandle()) {
689 updatedSensors |= SENSORUPDATES_airspeed;
692 PIOS_CALLBACKSCHEDULER_Dispatch(stateEstimationCallback);
697 * @}
698 * @}