2 ******************************************************************************
3 * @addtogroup OpenPilot System OpenPilot System
5 * @addtogroup OpenPilot Libraries OpenPilot System Libraries
8 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
9 * @brief Utilities to validate a flight configuration
10 * @see The GNU Public License (GPL) Version 3
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <openpilot.h>
30 #include <pios_board_info.h>
33 #include "inc/sanitycheck.h"
36 #include <manualcontrolsettings.h>
37 #include <flightmodesettings.h>
38 #include <systemsettings.h>
39 #include <stabilizationsettings.h>
40 #include <systemalarms.h>
41 #include <revosettings.h>
42 #include <positionstate.h>
45 // a number of useful macros
46 #define ADDSEVERITY(check) severity = (severity != SYSTEMALARMS_ALARM_OK ? severity : ((check) ? SYSTEMALARMS_ALARM_OK : SYSTEMALARMS_ALARM_CRITICAL))
47 #define ADDEXTENDEDALARMSTATUS(error_code, error_substatus) if ((severity != SYSTEMALARMS_ALARM_OK) && (alarmstatus == SYSTEMALARMS_EXTENDEDALARMSTATUS_NONE)) { alarmstatus = (error_code); alarmsubstatus = (error_substatus); }
50 typedef struct SANITYCHECK_CustomHookInstance
{
51 SANITYCHECK_CustomHook_function
*hook
;
52 struct SANITYCHECK_CustomHookInstance
*next
;
54 } SANITYCHECK_CustomHookInstance
;
56 // ! Check a stabilization mode switch position for safety
57 static bool check_stabilization_settings(int index
, bool multirotor
, bool coptercontrol
, bool gpsassisted
);
59 SANITYCHECK_CustomHookInstance
*hooks
= 0;
62 * Run a preflight check over the hardware configuration
63 * and currently active modules
65 int32_t configuration_check()
67 int32_t severity
= SYSTEMALARMS_ALARM_OK
;
68 SystemAlarmsExtendedAlarmStatusOptions alarmstatus
= SYSTEMALARMS_EXTENDEDALARMSTATUS_NONE
;
69 uint8_t alarmsubstatus
= 0;
71 const struct pios_board_info
*bdinfo
= &pios_board_info_blob
;
72 bool coptercontrol
= bdinfo
->board_type
== 0x04;
74 // Classify navigation capability
76 RevoSettingsInitialize();
77 RevoSettingsFusionAlgorithmOptions revoFusion
;
78 RevoSettingsFusionAlgorithmGet(&revoFusion
);
79 bool navCapableFusion
;
81 case REVOSETTINGS_FUSIONALGORITHM_COMPLEMENTARYMAGGPSOUTDOOR
:
82 case REVOSETTINGS_FUSIONALGORITHM_GPSNAVIGATIONINS13
:
83 navCapableFusion
= true;
86 navCapableFusion
= false;
87 // check for hitl. hitl allows to feed position and velocity state via
88 // telemetry, this makes nav possible even with an unsuited algorithm
89 if (PositionStateHandle()) {
90 if (PositionStateReadOnly()) {
91 navCapableFusion
= true;
96 const bool navCapableFusion
= false;
97 #endif /* ifdef REVOLUTION */
100 // Classify airframe type
101 bool multirotor
= (GetCurrentFrameType() == FRAME_TYPE_MULTIROTOR
);
104 // For each available flight mode position sanity check the available
107 FlightModeSettingsFlightModePositionOptions modes
[FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_NUMELEM
];
108 StabilizationSettingsFlightModeAssistMapOptions FlightModeAssistMap
[STABILIZATIONSETTINGS_FLIGHTMODEASSISTMAP_NUMELEM
];
109 ManualControlSettingsFlightModeNumberGet(&num_modes
);
110 StabilizationSettingsFlightModeAssistMapGet(FlightModeAssistMap
);
111 FlightModeSettingsFlightModePositionGet(modes
);
113 for (uint32_t i
= 0; i
< num_modes
; i
++) {
114 uint8_t gps_assisted
= FlightModeAssistMap
[i
];
116 ADDSEVERITY(!coptercontrol
);
117 ADDSEVERITY(multirotor
);
118 ADDSEVERITY(navCapableFusion
);
121 switch ((FlightModeSettingsFlightModePositionOptions
)modes
[i
]) {
122 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_MANUAL
:
123 ADDSEVERITY(!gps_assisted
);
124 ADDSEVERITY(!multirotor
);
126 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_STABILIZED1
:
127 ADDSEVERITY(check_stabilization_settings(1, multirotor
, coptercontrol
, gps_assisted
));
129 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_STABILIZED2
:
130 ADDSEVERITY(check_stabilization_settings(2, multirotor
, coptercontrol
, gps_assisted
));
132 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_STABILIZED3
:
133 ADDSEVERITY(check_stabilization_settings(3, multirotor
, coptercontrol
, gps_assisted
));
135 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_STABILIZED4
:
136 ADDSEVERITY(check_stabilization_settings(4, multirotor
, coptercontrol
, gps_assisted
));
138 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_STABILIZED5
:
139 ADDSEVERITY(check_stabilization_settings(5, multirotor
, coptercontrol
, gps_assisted
));
141 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_STABILIZED6
:
142 ADDSEVERITY(check_stabilization_settings(6, multirotor
, coptercontrol
, gps_assisted
));
144 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_PATHPLANNER
:
146 ADDSEVERITY(!gps_assisted
);
148 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_POSITIONHOLD
:
149 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_VELOCITYROAM
:
150 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_LAND
:
151 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_AUTOTAKEOFF
:
152 ADDSEVERITY(!coptercontrol
);
153 ADDSEVERITY(navCapableFusion
);
156 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_COURSELOCK
:
157 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_HOMELEASH
:
158 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_ABSOLUTEPOSITION
:
159 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_POI
:
160 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_RETURNTOBASE
:
161 case FLIGHTMODESETTINGS_FLIGHTMODEPOSITION_AUTOCRUISE
:
162 ADDSEVERITY(!gps_assisted
);
163 ADDSEVERITY(!coptercontrol
);
164 ADDSEVERITY(navCapableFusion
);
167 // Uncovered modes are automatically an error
170 // mark the first encountered erroneous setting in status and substatus
171 if ((severity
!= SYSTEMALARMS_ALARM_OK
) && (alarmstatus
== SYSTEMALARMS_EXTENDEDALARMSTATUS_NONE
)) {
172 alarmstatus
= SYSTEMALARMS_EXTENDEDALARMSTATUS_FLIGHTMODE
;
178 // Check throttle/collective channel range for valid configuration of input for critical control
179 SystemSettingsThrustControlOptions thrustType
;
180 SystemSettingsThrustControlGet(&thrustType
);
181 ManualControlSettingsChannelMinData channelMin
;
182 ManualControlSettingsChannelMaxData channelMax
;
183 ManualControlSettingsChannelMinGet(&channelMin
);
184 ManualControlSettingsChannelMaxGet(&channelMax
);
185 switch (thrustType
) {
186 case SYSTEMSETTINGS_THRUSTCONTROL_THROTTLE
:
187 ADDSEVERITY(fabsf(channelMax
.Throttle
- channelMin
.Throttle
) > 300.0f
);
188 ADDEXTENDEDALARMSTATUS(SYSTEMALARMS_EXTENDEDALARMSTATUS_BADTHROTTLEORCOLLECTIVEINPUTRANGE
, 0);
190 case SYSTEMSETTINGS_THRUSTCONTROL_COLLECTIVE
:
191 ADDSEVERITY(fabsf(channelMax
.Collective
- channelMin
.Collective
) > 300.0f
);
192 ADDEXTENDEDALARMSTATUS(SYSTEMALARMS_EXTENDEDALARMSTATUS_BADTHROTTLEORCOLLECTIVEINPUTRANGE
, 0);
198 // query sanity check hooks
199 if (severity
< SYSTEMALARMS_ALARM_CRITICAL
) {
200 SANITYCHECK_CustomHookInstance
*instance
= NULL
;
201 LL_FOREACH(hooks
, instance
) {
202 if (instance
->enabled
) {
203 alarmstatus
= instance
->hook();
204 if (alarmstatus
!= SYSTEMALARMS_EXTENDEDALARMSTATUS_NONE
) {
205 severity
= SYSTEMALARMS_ALARM_CRITICAL
;
212 FlightModeSettingsDisableSanityChecksOptions checks_disabled
;
213 FlightModeSettingsDisableSanityChecksGet(&checks_disabled
);
214 if (checks_disabled
== FLIGHTMODESETTINGS_DISABLESANITYCHECKS_TRUE
) {
215 severity
= SYSTEMALARMS_ALARM_WARNING
;
218 if (severity
!= SYSTEMALARMS_ALARM_OK
) {
219 ExtendedAlarmsSet(SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION
, severity
, alarmstatus
, alarmsubstatus
);
221 AlarmsClear(SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION
);
228 * Checks the stabiliation settings for a paritcular mode and makes
229 * sure it is appropriate for the airframe
230 * @param[in] index Which stabilization mode to check
231 * @returns true or false
233 static bool check_stabilization_settings(int index
, bool multirotor
, bool coptercontrol
, bool gpsassisted
)
235 uint8_t modes
[FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_NUMELEM
];
237 // Get the different axis modes for this switch position
240 FlightModeSettingsStabilization1SettingsArrayGet((FlightModeSettingsStabilization1SettingsOptions
*)modes
);
243 FlightModeSettingsStabilization2SettingsArrayGet((FlightModeSettingsStabilization2SettingsOptions
*)modes
);
246 FlightModeSettingsStabilization3SettingsArrayGet((FlightModeSettingsStabilization3SettingsOptions
*)modes
);
249 FlightModeSettingsStabilization4SettingsArrayGet((FlightModeSettingsStabilization4SettingsOptions
*)modes
);
252 FlightModeSettingsStabilization5SettingsArrayGet((FlightModeSettingsStabilization5SettingsOptions
*)modes
);
255 FlightModeSettingsStabilization6SettingsArrayGet((FlightModeSettingsStabilization6SettingsOptions
*)modes
);
261 // For multirotors verify that roll/pitch/yaw are not set to "none"
262 // (why not? might be fun to test ones reactions ;) if you dare, set your frame to "custom"!
264 for (uint32_t i
= 0; i
< FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_THRUST
; i
++) {
265 if (modes
[i
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_MANUAL
) {
272 // For multirotors verify that roll/pitch are either attitude or rattitude
273 for (uint32_t i
= 0; i
< FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_YAW
; i
++) {
274 if (!(modes
[i
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_ATTITUDE
||
275 modes
[i
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_RATTITUDE
)) {
282 // coptercontrol cannot do altitude holding
284 if (modes
[FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_THRUST
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_ALTITUDEHOLD
285 || modes
[FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_THRUST
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_ALTITUDEVARIO
291 // check that thrust modes are only set to thrust axis
292 for (uint32_t i
= 0; i
< FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_THRUST
; i
++) {
293 if (modes
[i
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_ALTITUDEHOLD
294 || modes
[i
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_ALTITUDEVARIO
299 if (!(modes
[FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_THRUST
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_MANUAL
300 || modes
[FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_THRUST
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_ALTITUDEHOLD
301 || modes
[FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_THRUST
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_ALTITUDEVARIO
302 || modes
[FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_THRUST
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_CRUISECONTROL
308 // if cruise control, ensure rate or acro are not set
309 if (modes
[FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_THRUST
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_CRUISECONTROL
) {
310 for (uint32_t i
= 0; i
< FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_YAW
; i
++) {
311 if ((modes
[i
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_RATE
||
312 modes
[i
] == FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_ACRO
)) {
318 // Warning: This assumes that certain conditions in the XML file are met. That
319 // FLIGHTMODESETTINGS_STABILIZATION1SETTINGS_MANUAL has the same numeric value for each channel
320 // and is the same for STABILIZATIONDESIRED_STABILIZATIONMODE_MANUAL
321 // (this is checked at compile time by static constraint manualcontrol.h)
327 FrameType_t
GetCurrentFrameType()
329 SystemSettingsAirframeTypeOptions airframe_type
;
331 SystemSettingsAirframeTypeGet(&airframe_type
);
332 switch ((SystemSettingsAirframeTypeOptions
)airframe_type
) {
333 case SYSTEMSETTINGS_AIRFRAMETYPE_QUADX
:
334 case SYSTEMSETTINGS_AIRFRAMETYPE_QUADP
:
335 case SYSTEMSETTINGS_AIRFRAMETYPE_HEXA
:
336 case SYSTEMSETTINGS_AIRFRAMETYPE_OCTO
:
337 case SYSTEMSETTINGS_AIRFRAMETYPE_OCTOX
:
338 case SYSTEMSETTINGS_AIRFRAMETYPE_HEXAX
:
339 case SYSTEMSETTINGS_AIRFRAMETYPE_HEXAH
:
340 case SYSTEMSETTINGS_AIRFRAMETYPE_OCTOV
:
341 case SYSTEMSETTINGS_AIRFRAMETYPE_OCTOCOAXP
:
342 case SYSTEMSETTINGS_AIRFRAMETYPE_HEXACOAX
:
343 case SYSTEMSETTINGS_AIRFRAMETYPE_TRI
:
344 case SYSTEMSETTINGS_AIRFRAMETYPE_OCTOCOAXX
:
345 return FRAME_TYPE_MULTIROTOR
;
347 case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWING
:
348 case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGELEVON
:
349 case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGVTAIL
:
350 return FRAME_TYPE_FIXED_WING
;
352 case SYSTEMSETTINGS_AIRFRAMETYPE_HELICP
:
353 return FRAME_TYPE_HELI
;
355 case SYSTEMSETTINGS_AIRFRAMETYPE_GROUNDVEHICLECAR
:
356 case SYSTEMSETTINGS_AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL
:
357 case SYSTEMSETTINGS_AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE
:
358 return FRAME_TYPE_GROUND
;
360 case SYSTEMSETTINGS_AIRFRAMETYPE_VTOL
:
361 case SYSTEMSETTINGS_AIRFRAMETYPE_CUSTOM
:
362 return FRAME_TYPE_CUSTOM
;
364 // anyway it should not reach here
365 return FRAME_TYPE_CUSTOM
;
368 void SANITYCHECK_AttachHook(SANITYCHECK_CustomHook_function
*hook
)
371 SANITYCHECK_CustomHookInstance
*instance
= NULL
;
373 // Check whether there is an existing instance and enable it
374 LL_FOREACH(hooks
, instance
) {
375 if (instance
->hook
== hook
) {
376 instance
->enabled
= true;
381 // No existing instance found, attach this new one
382 instance
= (SANITYCHECK_CustomHookInstance
*)pios_malloc(sizeof(SANITYCHECK_CustomHookInstance
));
383 PIOS_Assert(instance
);
384 instance
->hook
= hook
;
385 instance
->next
= NULL
;
386 instance
->enabled
= true;
387 LL_APPEND(hooks
, instance
);
390 void SANITYCHECK_DetachHook(SANITYCHECK_CustomHook_function
*hook
)
395 SANITYCHECK_CustomHookInstance
*instance
= NULL
;
396 LL_FOREACH(hooks
, instance
) {
397 if (instance
->hook
== hook
) {
398 instance
->enabled
= false;