dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sanitycheck.c
Go to the documentation of this file.
1 
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, see <http://www.gnu.org/licenses/>
27  *
28  * Additional note on redistribution: The copyright and license notices above
29  * must be maintained in each individual source file that is a derivative work
30  * of this source file; otherwise redistribution is prohibited.
31  */
32 
33 #include "openpilot.h"
34 #include "taskmonitor.h"
35 #include <pios_board_info.h>
36 #include "flightstatus.h"
37 #include "sanitycheck.h"
38 #include "manualcontrolsettings.h"
39 #include "stabilizationsettings.h"
40 #include "stateestimation.h"
41 #include "systemalarms.h"
42 #include "systemsettings.h"
43 #include "systemident.h"
44 
45 #include "pios_sensors.h"
46 
47 /****************************
48  * Current checks:
49  * 1. If a flight mode switch allows autotune and autotune module not running
50  * 2. If airframe is a multirotor and either manual is available or a stabilization mode uses "none"
51  ****************************/
52 
54 static int32_t check_safe_to_arm();
55 
57 static int32_t check_stabilization_settings(int index, bool multirotor);
58 
60 static int32_t check_stabilization_rates();
61 
63 static int32_t check_safe_autonomous();
64 
66 {
67  if (SystemIdentHandle()) {
68  SystemIdentData si;
69  SystemIdentGet(&si);
70 
71  if (si.Beta[SYSTEMIDENT_BETA_ROLL] < 6 || si.Tau[SYSTEMIDENT_TAU_ROLL] < 0.001f ||
72  si.Beta[SYSTEMIDENT_BETA_PITCH] < 6 || si.Tau[SYSTEMIDENT_TAU_PITCH] < 0.001f ||
73  si.Beta[SYSTEMIDENT_BETA_YAW] < 6 || si.Tau[SYSTEMIDENT_TAU_YAW] < 0.001f) {
74  return false;
75  }
76  }
77  return true;
78 }
79 
85 {
86  SystemAlarmsConfigErrorOptions error_code = SYSTEMALARMS_CONFIGERROR_NONE;
87 
88  // For when modules are not running we should explicitly check the objects are
89  // valid
90  if (ManualControlSettingsHandle() == NULL ||
91  SystemSettingsHandle() == NULL) {
92  AlarmsSet(SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION, SYSTEMALARMS_ALARM_CRITICAL);
93  return 0;
94  }
95 
96  // Classify airframe type
97  bool multirotor = true;
98  uint8_t airframe_type;
99  SystemSettingsAirframeTypeGet(&airframe_type);
100  switch(airframe_type) {
101  case SYSTEMSETTINGS_AIRFRAMETYPE_QUADX:
102  case SYSTEMSETTINGS_AIRFRAMETYPE_QUADP:
103  case SYSTEMSETTINGS_AIRFRAMETYPE_HEXA:
104  case SYSTEMSETTINGS_AIRFRAMETYPE_OCTO:
105  case SYSTEMSETTINGS_AIRFRAMETYPE_HEXAX:
106  case SYSTEMSETTINGS_AIRFRAMETYPE_OCTOV:
107  case SYSTEMSETTINGS_AIRFRAMETYPE_OCTOCOAXP:
108  case SYSTEMSETTINGS_AIRFRAMETYPE_HEXACOAX:
109  case SYSTEMSETTINGS_AIRFRAMETYPE_TRI:
110  multirotor = true;
111  break;
112  default:
113  multirotor = false;
114  }
115 
116  // For each available flight mode position sanity check the available
117  // modes
118  uint8_t num_modes;
119  uint8_t modes[MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_NUMELEM];
120  ManualControlSettingsFlightModeNumberGet(&num_modes);
121  ManualControlSettingsFlightModePositionGet(modes);
122 
123  for(uint32_t i = 0; i < num_modes; i++) {
124  switch(modes[i]) {
125  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_MANUAL:
126  if (multirotor) {
127  error_code = SYSTEMALARMS_CONFIGERROR_STABILIZATION;
128  }
129  break;
130  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_ACRO:
131  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_ACROPLUS:
132  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_ACRODYNE:
133  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_LEVELING:
134  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_HORIZON:
135  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_AXISLOCK:
136  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_VIRTUALBAR:
137  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_FLIPREVERSED:
138  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_FAILSAFE:
139  // always ok
140  break;
141  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_LQG:
142  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_LQGLEVELING:
143  if (!lqg_sysident_check()) {
144  error_code = SYSTEMALARMS_CONFIGERROR_LQG;
145  }
146  break;
147  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_STABILIZED1:
148  error_code = (error_code == SYSTEMALARMS_CONFIGERROR_NONE) ? check_stabilization_settings(1, multirotor) : error_code;
149  break;
150  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_STABILIZED2:
151  error_code = (error_code == SYSTEMALARMS_CONFIGERROR_NONE) ? check_stabilization_settings(2, multirotor) : error_code;
152  break;
153  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_STABILIZED3:
154  error_code = (error_code == SYSTEMALARMS_CONFIGERROR_NONE) ? check_stabilization_settings(3, multirotor) : error_code;
155  break;
156  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_AUTOTUNE:
158  error_code = SYSTEMALARMS_CONFIGERROR_AUTOTUNE;
159  }
160  break;
161  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_ALTITUDEHOLD:
163  error_code = SYSTEMALARMS_CONFIGERROR_ALTITUDEHOLD;
164  }
165  break;
166  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_POSITIONHOLD:
167  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_RETURNTOHOME:
168  if (!TaskMonitorQueryRunning(TASKINFO_RUNNING_PATHFOLLOWER)) {
169  error_code = SYSTEMALARMS_CONFIGERROR_PATHPLANNER;
170  } else {
171  error_code = check_safe_autonomous();
172  }
173  break;
174  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_PATHPLANNER:
175  case MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_TABLETCONTROL:
176  if (!TaskMonitorQueryRunning(TASKINFO_RUNNING_PATHFOLLOWER) ||
177  !TaskMonitorQueryRunning(TASKINFO_RUNNING_PATHPLANNER)) {
178  error_code = SYSTEMALARMS_CONFIGERROR_PATHPLANNER;
179  } else {
180  error_code = check_safe_autonomous();
181  }
182  break;
183  default:
184  // Uncovered modes are automatically an error
185  error_code = SYSTEMALARMS_CONFIGERROR_UNDEFINED;
186  }
187  }
188 
189  // Check the stabilization rates are within what the sensors can track
190  error_code = (error_code == SYSTEMALARMS_CONFIGERROR_NONE) ? check_stabilization_rates() : error_code;
191 
192  // Only check safe to arm if no other errors exist
193  error_code = (error_code == SYSTEMALARMS_CONFIGERROR_NONE) ? check_safe_to_arm() : error_code;
194 
195  set_config_error(error_code);
196 
197  return 0;
198 }
199 
200 
201 DONT_BUILD_IF(MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_NUMELEM != MANUALCONTROLSETTINGS_STABILIZATION2SETTINGS_NUMELEM, StabSettingsNumElem);
202 DONT_BUILD_IF(MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_NUMELEM != MANUALCONTROLSETTINGS_STABILIZATION3SETTINGS_NUMELEM, StabSettingsNumElem2);
203 
210 static int32_t check_stabilization_settings(int index, bool multirotor)
211 {
212  uint8_t modes[MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_NUMELEM];
213  uint8_t thrust_mode;
214 
215  // Get the different axis modes for this switch position
216  switch(index) {
217  case 1:
218  ManualControlSettingsStabilization1SettingsGet(modes);
219  ManualControlSettingsStabilization1ThrustGet(&thrust_mode);
220  break;
221  case 2:
222  ManualControlSettingsStabilization2SettingsGet(modes);
223  ManualControlSettingsStabilization2ThrustGet(&thrust_mode);
224  break;
225  case 3:
226  ManualControlSettingsStabilization3SettingsGet(modes);
227  ManualControlSettingsStabilization3ThrustGet(&thrust_mode);
228  break;
229  default:
230  return SYSTEMALARMS_CONFIGERROR_NONE;
231  }
232 
233  // For multirotors verify that nothing is set to "disabled" or "manual"
234  if (multirotor &&
235  (thrust_mode != MANUALCONTROLSETTINGS_STABILIZATION1THRUST_FLIPOVERMODE) &&
236  (thrust_mode != MANUALCONTROLSETTINGS_STABILIZATION1THRUST_FLIPOVERMODETHRUSTREVERSED)) {
237  for(uint32_t i = 0; i < NELEMENTS(modes); i++) {
238  if ((modes[i] == MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_DISABLED || modes[i] == MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_MANUAL))
239  return SYSTEMALARMS_CONFIGERROR_MULTIROTOR;
240  }
241  }
242 
243  if ((thrust_mode == SHAREDDEFS_THRUSTMODESTABBANK_ALTITUDEWITHSTICKSCALING) &&
245  return SYSTEMALARMS_CONFIGERROR_ALTITUDEHOLD;
246  }
247 
248  for(uint32_t i = 0; i < NELEMENTS(modes); i++) {
249  // If this axis allows enabling an autotune behavior without the module
250  // running then set an alarm now that aututune module initializes the
251  // appropriate objects
252  if ((modes[i] == MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_SYSTEMIDENT) &&
254  return SYSTEMALARMS_CONFIGERROR_AUTOTUNE;
255  }
256 
257  /* Throw an error if LQG modes are configured without system identification data. */
258  if (modes[i] == MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_LQG ||
259  modes[i] == MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_ATTITUDELQG) {
260  if (!lqg_sysident_check())
261  return SYSTEMALARMS_CONFIGERROR_LQG;
262  }
263  }
264 
265  // POI mode is only valid for YAW in the case it is enabled and camera stab is running
266  if (modes[MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_ROLL] == MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_POI ||
267  modes[MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_PITCH] == MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_POI)
268  return SYSTEMALARMS_CONFIGERROR_STABILIZATION;
269  if (modes[MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_YAW] == MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_POI) {
270 #if !defined(CAMERASTAB_POI_MODE)
271  return SYSTEMALARMS_CONFIGERROR_STABILIZATION;
272 #endif
273  // TODO: Need to check camera stab is actually running
274  }
275 
276 
277  // Warning: This assumes that certain conditions in the XML file are met. That
278  // MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_DISABLED has the same numeric value for each channel
279  // and is the same for STABILIZATIONDESIRED_STABILIZATIONMODE_DISABLED
280 
281  return SYSTEMALARMS_CONFIGERROR_NONE;
282 }
283 
293 static int32_t check_safe_to_arm()
294 {
295  FlightStatusData flightStatus;
296  FlightStatusGet(&flightStatus);
297 
298  // Only arm in traditional modes where pilot has control
299  if (flightStatus.Armed != FLIGHTSTATUS_ARMED_ARMED) {
300  switch (flightStatus.FlightMode) {
301  case FLIGHTSTATUS_FLIGHTMODE_MANUAL:
302  case FLIGHTSTATUS_FLIGHTMODE_ACRO:
303  case FLIGHTSTATUS_FLIGHTMODE_ACROPLUS:
304  case FLIGHTSTATUS_FLIGHTMODE_ACRODYNE:
305  case FLIGHTSTATUS_FLIGHTMODE_LEVELING:
306  case FLIGHTSTATUS_FLIGHTMODE_HORIZON:
307  case FLIGHTSTATUS_FLIGHTMODE_AXISLOCK:
308  case FLIGHTSTATUS_FLIGHTMODE_VIRTUALBAR:
309  case FLIGHTSTATUS_FLIGHTMODE_STABILIZED1:
310  case FLIGHTSTATUS_FLIGHTMODE_STABILIZED2:
311  case FLIGHTSTATUS_FLIGHTMODE_STABILIZED3:
312  case FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD:
313  case FLIGHTSTATUS_FLIGHTMODE_FLIPREVERSED:
314  break;
315  case FLIGHTSTATUS_FLIGHTMODE_LQG:
316  case FLIGHTSTATUS_FLIGHTMODE_LQGLEVELING:
317  if (!lqg_sysident_check()) {
318  return SYSTEMALARMS_CONFIGERROR_LQG;
319  }
320  break;
321 
322  case FLIGHTSTATUS_FLIGHTMODE_FAILSAFE:
323  /* for failsafe, we don't want to prevent
324  * arming here because it makes an ugly looking
325  * GCS config error.
326  */
327  break;
328  default:
329  // Any mode not specifically allowed prevents arming
330  return SYSTEMALARMS_CONFIGERROR_UNSAFETOARM;
331  }
332  }
333 
334  return SYSTEMALARMS_CONFIGERROR_NONE;
335 }
336 
341 static int32_t check_safe_autonomous()
342 {
343  // The current filter combinations are safe for navigation
344  // Attitude | Navigation
345  // Comp | Raw (not recommended)
346  // Comp | INS (recommmended)
347  // Anything | None (unsafe)
348  // INSOutdoor | INS
349  // INSIndoor | INS (unsafe)
350 
351  StateEstimationData stateEstimation;
352  StateEstimationGet(&stateEstimation);
353 
354  if (stateEstimation.AttitudeFilter == STATEESTIMATION_ATTITUDEFILTER_INSINDOOR)
355  return SYSTEMALARMS_CONFIGERROR_NAVFILTER;
356 
357  // Anything not allowed is invalid, safe default
358  if (stateEstimation.NavigationFilter != STATEESTIMATION_NAVIGATIONFILTER_INS &&
359  stateEstimation.NavigationFilter != STATEESTIMATION_NAVIGATIONFILTER_RAW)
360  return SYSTEMALARMS_CONFIGERROR_NAVFILTER;
361 
362  return SYSTEMALARMS_CONFIGERROR_NONE;
363 }
364 
371 {
372  const float MAXIMUM_SAFE_FRACTIONAL_RATE = 0.85;
373  int32_t max_safe_rate = PIOS_SENSORS_GetMaxGyro() * MAXIMUM_SAFE_FRACTIONAL_RATE;
374  float rates[3];
375 
376  StabilizationSettingsManualRateGet(rates);
377  if (rates[0] > max_safe_rate || rates[1] > max_safe_rate || rates[2] > max_safe_rate)
378  return SYSTEMALARMS_CONFIGERROR_STABILIZATION;
379 
380  StabilizationSettingsMaximumRateGet(rates);
381  if (rates[0] > max_safe_rate || rates[1] > max_safe_rate || rates[2] > max_safe_rate)
382  return SYSTEMALARMS_CONFIGERROR_STABILIZATION;
383 
384  return SYSTEMALARMS_CONFIGERROR_NONE;
385 }
386 
391 void set_config_error(SystemAlarmsConfigErrorOptions error_code)
392 {
393  // Get the severity of the alarm given the error code
394  SystemAlarmsAlarmOptions severity;
395 
396  static bool sticky = false;
397 
398  /* Once a sticky error occurs, never change the error code */
399  if (sticky) return;
400 
401  switch (error_code) {
402  case SYSTEMALARMS_CONFIGERROR_NONE:
403  severity = SYSTEMALARMS_ALARM_OK;
404  break;
405  default:
406  error_code = SYSTEMALARMS_CONFIGERROR_UNDEFINED;
407  /* and fall through */
408 
409  case SYSTEMALARMS_CONFIGERROR_DUPLICATEPORTCFG:
410  sticky = true;
411  /* and fall through */
412  case SYSTEMALARMS_CONFIGERROR_AUTOTUNE:
413  case SYSTEMALARMS_CONFIGERROR_ALTITUDEHOLD:
414  case SYSTEMALARMS_CONFIGERROR_MULTIROTOR:
415  case SYSTEMALARMS_CONFIGERROR_NAVFILTER:
416  case SYSTEMALARMS_CONFIGERROR_PATHPLANNER:
417  case SYSTEMALARMS_CONFIGERROR_POSITIONHOLD:
418  case SYSTEMALARMS_CONFIGERROR_STABILIZATION:
419  case SYSTEMALARMS_CONFIGERROR_UNDEFINED:
420  case SYSTEMALARMS_CONFIGERROR_UNSAFETOARM:
421  case SYSTEMALARMS_CONFIGERROR_LQG:
422  severity = SYSTEMALARMS_ALARM_ERROR;
423  break;
424  }
425 
426  // Make sure not to set the error code if it didn't change
427  SystemAlarmsConfigErrorOptions current_error_code;
428  SystemAlarmsConfigErrorGet((uint8_t *) &current_error_code);
429  if (current_error_code != error_code) {
430  SystemAlarmsConfigErrorSet((uint8_t *) &error_code);
431  }
432 
433  // AlarmSet checks only updates on toggle
434  AlarmsSet(SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION, (uint8_t) severity);
435 }
436 
bool TaskMonitorQueryRunning(TaskInfoRunningElem task)
Definition: taskmonitor.c:105
int32_t PIOS_SENSORS_GetMaxGyro()
Get the maximum gyro rate in deg/s.
Definition: pios_sensors.c:167
#define NELEMENTS(x)
Definition: pios.h:192
DONT_BUILD_IF(MANUALCONTROLSETTINGS_STABILIZATION1SETTINGS_NUMELEM!=MANUALCONTROLSETTINGS_STABILIZATION2SETTINGS_NUMELEM, StabSettingsNumElem)
bool PIOS_Modules_IsEnabled(enum pios_modules module)
Definition: pios_modules.c:41
static int32_t check_safe_autonomous()
Check the system is safe for autonomous flight.
Definition: sanitycheck.c:341
static StateEstimationData stateEstimation
Definition: attitude.c:149
static int32_t check_stabilization_settings(int index, bool multirotor)
Check a stabilization mode switch position for safety.
Definition: sanitycheck.c:210
int32_t AlarmsSet(SystemAlarmsAlarmElem alarm, SystemAlarmsAlarmOptions severity)
Definition: alarms.c:97
void set_config_error(SystemAlarmsConfigErrorOptions error_code)
Definition: sanitycheck.c:391
Task monitoring library.
Utilities to validate a flight configuration.
static int32_t check_stabilization_rates()
Check a stabilization mode switch position for safety.
Definition: sanitycheck.c:370
bool PIOS_SENSORS_IsRegistered(enum pios_sensor_type type)
Checks if a sensor type is registered with the PIOS_SENSORS interface.
Definition: pios_sensors.c:88
int32_t configuration_check()
Definition: sanitycheck.c:84
uint8_t i
Definition: msp_messages.h:97
bool lqg_sysident_check()
Definition: sanitycheck.c:65
static int32_t check_safe_to_arm()
Check it is safe to arm in this position.
Definition: sanitycheck.c:293
static SystemSettingsAirframeTypeOptions airframe_type
Definition: actuator.c:103
Includes PiOS and core architecture components.
Generic interface for sensors.