PX4 Firmware
PX4 Autopilot Software http://px4.io
PreFlightCheck.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2019 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file PreFlightCheck.cpp
36  */
37 
38 #include "PreFlightCheck.hpp"
39 
40 #include <drivers/drv_hrt.h>
41 #include <HealthFlags.h>
42 #include <lib/parameters/param.h>
43 #include <systemlib/mavlink_log.h>
44 #include <uORB/Subscription.hpp>
46 
47 using namespace time_literals;
48 
49 static constexpr unsigned max_mandatory_gyro_count = 1;
50 static constexpr unsigned max_optional_gyro_count = 3;
51 static constexpr unsigned max_mandatory_accel_count = 1;
52 static constexpr unsigned max_optional_accel_count = 3;
53 static constexpr unsigned max_mandatory_mag_count = 1;
54 static constexpr unsigned max_optional_mag_count = 4;
55 static constexpr unsigned max_mandatory_baro_count = 1;
56 static constexpr unsigned max_optional_baro_count = 1;
57 
59  vehicle_status_flags_s &status_flags, const bool checkGNSS, bool reportFailures, const bool prearm,
60  const hrt_abstime &time_since_boot)
61 {
62  if (time_since_boot < 2_s) {
63  // the airspeed driver filter doesn't deliver the actual value yet
64  reportFailures = false;
65  }
66 
67  const bool hil_enabled = (status.hil_state == vehicle_status_s::HIL_STATE_ON);
68 
69  bool checkSensors = !hil_enabled;
70  const bool checkRC = (status.rc_input_mode == vehicle_status_s::RC_IN_MODE_DEFAULT);
71  const bool checkDynamic = !hil_enabled;
72  const bool checkPower = (status_flags.condition_power_input_valid && !status_flags.circuit_breaker_engaged_power_check);
73  const bool checkFailureDetector = true;
74 
75  bool checkAirspeed = false;
76 
77  /* Perform airspeed check only if circuit breaker is not
78  * engaged and it's not a rotary wing */
79  if (!status_flags.circuit_breaker_engaged_airspd_check &&
81  checkAirspeed = true;
82  }
83 
84  reportFailures = (reportFailures && status_flags.condition_system_hotplug_timeout
85  && !status_flags.condition_calibration_enabled);
86 
87  bool failed = false;
88 
89  /* ---- MAG ---- */
90  if (checkSensors) {
91  bool prime_found = false;
92 
93  int32_t prime_id = -1;
94  param_get(param_find("CAL_MAG_PRIME"), &prime_id);
95 
96  int32_t sys_has_mag = 1;
97  param_get(param_find("SYS_HAS_MAG"), &sys_has_mag);
98 
99  bool mag_fail_reported = false;
100 
101  /* check all sensors individually, but fail only for mandatory ones */
102  for (unsigned i = 0; i < max_optional_mag_count; i++) {
103  const bool required = (i < max_mandatory_mag_count) && (sys_has_mag == 1);
104  const bool report_fail = (reportFailures && !failed && !mag_fail_reported);
105 
106  int32_t device_id = -1;
107 
108  if (magnometerCheck(mavlink_log_pub, status, i, !required, device_id, report_fail)) {
109 
110  if ((prime_id > 0) && (device_id == prime_id)) {
111  prime_found = true;
112  }
113 
114  } else {
115  if (required) {
116  failed = true;
117  mag_fail_reported = true;
118  }
119  }
120  }
121 
122  if (sys_has_mag == 1) {
123  /* check if the primary device is present */
124  if (!prime_found) {
125  if (reportFailures && !failed) {
126  mavlink_log_critical(mavlink_log_pub, "Primary compass not found");
127  }
128 
129  set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_MAG, false, true, false, status);
130  failed = true;
131  }
132 
133  /* mag consistency checks (need to be performed after the individual checks) */
134  if (!magConsistencyCheck(mavlink_log_pub, status, (reportFailures && !failed))) {
135  failed = true;
136  }
137  }
138  }
139 
140  /* ---- ACCEL ---- */
141  if (checkSensors) {
142  bool prime_found = false;
143  int32_t prime_id = -1;
144  param_get(param_find("CAL_ACC_PRIME"), &prime_id);
145 
146  bool accel_fail_reported = false;
147 
148  /* check all sensors individually, but fail only for mandatory ones */
149  for (unsigned i = 0; i < max_optional_accel_count; i++) {
150  const bool required = (i < max_mandatory_accel_count);
151  const bool report_fail = (reportFailures && !failed && !accel_fail_reported);
152 
153  int32_t device_id = -1;
154 
155  if (accelerometerCheck(mavlink_log_pub, status, i, !required, checkDynamic, device_id, report_fail)) {
156 
157  if ((prime_id > 0) && (device_id == prime_id)) {
158  prime_found = true;
159  }
160 
161  } else {
162  if (required) {
163  failed = true;
164  accel_fail_reported = true;
165  }
166  }
167  }
168 
169  /* check if the primary device is present */
170  if (!prime_found) {
171  if (reportFailures && !failed) {
172  mavlink_log_critical(mavlink_log_pub, "Primary accelerometer not found");
173  }
174 
175  set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_ACC, false, true, false, status);
176  failed = true;
177  }
178  }
179 
180  /* ---- GYRO ---- */
181  if (checkSensors) {
182  bool prime_found = false;
183  int32_t prime_id = -1;
184  param_get(param_find("CAL_GYRO_PRIME"), &prime_id);
185 
186  bool gyro_fail_reported = false;
187 
188  /* check all sensors individually, but fail only for mandatory ones */
189  for (unsigned i = 0; i < max_optional_gyro_count; i++) {
190  const bool required = (i < max_mandatory_gyro_count);
191  const bool report_fail = (reportFailures && !failed && !gyro_fail_reported);
192 
193  int32_t device_id = -1;
194 
195  if (gyroCheck(mavlink_log_pub, status, i, !required, device_id, report_fail)) {
196 
197  if ((prime_id > 0) && (device_id == prime_id)) {
198  prime_found = true;
199  }
200 
201  } else {
202  if (required) {
203  failed = true;
204  gyro_fail_reported = true;
205  }
206  }
207  }
208 
209  /* check if the primary device is present */
210  if (!prime_found) {
211  if (reportFailures && !failed) {
212  mavlink_log_critical(mavlink_log_pub, "Primary gyro not found");
213  }
214 
215  set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_GYRO, false, true, false, status);
216  failed = true;
217  }
218  }
219 
220  /* ---- BARO ---- */
221  if (checkSensors) {
222  //bool prime_found = false;
223 
224  int32_t prime_id = -1;
225  param_get(param_find("CAL_BARO_PRIME"), &prime_id);
226 
227  int32_t sys_has_baro = 1;
228  param_get(param_find("SYS_HAS_BARO"), &sys_has_baro);
229 
230  bool baro_fail_reported = false;
231 
232  /* check all sensors, but fail only for mandatory ones */
233  for (unsigned i = 0; i < max_optional_baro_count; i++) {
234  const bool required = (i < max_mandatory_baro_count) && (sys_has_baro == 1);
235  const bool report_fail = (reportFailures && !failed && !baro_fail_reported);
236 
237  int32_t device_id = -1;
238 
239  if (baroCheck(mavlink_log_pub, status, i, !required, device_id, report_fail)) {
240  if ((prime_id > 0) && (device_id == prime_id)) {
241  //prime_found = true;
242  }
243 
244  } else {
245  if (required) {
246  failed = true;
247  baro_fail_reported = true;
248  }
249  }
250  }
251 
252  // TODO there is no logic in place to calibrate the primary baro yet
253  // // check if the primary device is present
254  // if (false) {
255  // if (reportFailures && !failed) {
256  // mavlink_log_critical(mavlink_log_pub, "Primary barometer not operational");
257  // }
258 
259  // set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_ABSPRESSURE, false, true, false, status);
260  // failed = true;
261  // }
262  }
263 
264  /* ---- IMU CONSISTENCY ---- */
265  // To be performed after the individual sensor checks have completed
266  if (checkSensors) {
267  if (!imuConsistencyCheck(mavlink_log_pub, status, (reportFailures && !failed))) {
268  failed = true;
269  }
270  }
271 
272  /* ---- AIRSPEED ---- */
273  if (checkAirspeed) {
274  int32_t optional = 0;
275  param_get(param_find("FW_ARSP_MODE"), &optional);
276 
277  if (!airspeedCheck(mavlink_log_pub, status, (bool)optional, reportFailures && !failed, prearm) && !(bool)optional) {
278  failed = true;
279  }
280  }
281 
282  /* ---- RC CALIBRATION ---- */
283  if (checkRC) {
284  if (rcCalibrationCheck(mavlink_log_pub, reportFailures && !failed, status.is_vtol) != OK) {
285  if (reportFailures) {
286  mavlink_log_critical(mavlink_log_pub, "RC calibration check failed");
287  }
288 
289  failed = true;
290 
291  set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_RCRECEIVER, status_flags.rc_signal_found_once, true, false, status);
292  status_flags.rc_calibration_valid = false;
293 
294  } else {
295  // The calibration is fine, but only set the overall health state to true if the signal is not currently lost
296  status_flags.rc_calibration_valid = true;
297  set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_RCRECEIVER, status_flags.rc_signal_found_once, true,
298  !status.rc_signal_lost, status);
299  }
300  }
301 
302  /* ---- SYSTEM POWER ---- */
303  if (checkPower) {
304  if (!powerCheck(mavlink_log_pub, status, (reportFailures && !failed), prearm)) {
305  failed = true;
306  }
307  }
308 
309  /* ---- Navigation EKF ---- */
310  // only check EKF2 data if EKF2 is selected as the estimator and GNSS checking is enabled
311  int32_t estimator_type = -1;
312 
313  if (status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING && !status.is_vtol) {
314  param_get(param_find("SYS_MC_EST_GROUP"), &estimator_type);
315 
316  } else {
317  // EKF2 is currently the only supported option for FW & VTOL
318  estimator_type = 2;
319  }
320 
321  if (estimator_type == 2) {
322  // don't report ekf failures for the first 10 seconds to allow time for the filter to start
323  bool report_ekf_fail = (time_since_boot > 10_s);
324 
325  if (!ekf2Check(mavlink_log_pub, status, false, reportFailures && report_ekf_fail && !failed, checkGNSS)) {
326  failed = true;
327  }
328  }
329 
330  /* ---- Failure Detector ---- */
331  if (checkFailureDetector) {
332  if (!failureDetectorCheck(mavlink_log_pub, status, (reportFailures && !failed), prearm)) {
333  failed = true;
334  }
335  }
336 
337  /* Report status */
338  return !failed;
339 }
340 
341 bool PreFlightCheck::check_calibration(const char *param_template, const int32_t device_id)
342 {
343  bool calibration_found = false;
344 
345  char s[20];
346  int instance = 0;
347 
348  /* old style transition: check param values */
349  while (!calibration_found) {
350  sprintf(s, param_template, instance);
351  const param_t parm = param_find_no_notification(s);
352 
353  /* if the calibration param is not present, abort */
354  if (parm == PARAM_INVALID) {
355  break;
356  }
357 
358  /* if param get succeeds */
359  int32_t calibration_devid = -1;
360 
361  if (param_get(parm, &calibration_devid) == PX4_OK) {
362 
363  /* if the devid matches, exit early */
364  if (device_id == calibration_devid) {
365  calibration_found = true;
366  break;
367  }
368  }
369 
370  instance++;
371  }
372 
373  return calibration_found;
374 }
__EXPORT param_t param_find_no_notification(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:376
#define VEHICLE_TYPE_FIXED_WING
#define PARAM_INVALID
Handle returned when a parameter cannot be found.
Definition: param.h:103
static orb_advert_t * mavlink_log_pub
static constexpr unsigned max_mandatory_accel_count
static constexpr unsigned max_optional_gyro_count
static struct vehicle_status_s status
Definition: Commander.cpp:138
__EXPORT int param_get(param_t param, void *val)
Copy the value of a parameter.
Definition: parameters.cpp:589
static struct vehicle_status_flags_s status_flags
Definition: Commander.cpp:155
LidarLite * instance
Definition: ll40ls.cpp:65
static int32_t device_id[max_accel_sens]
High-resolution timer with callouts and timekeeping.
void set_health_flags(uint64_t subsystem_type, bool present, bool enabled, bool ok, vehicle_status_s &status)
Definition: HealthFlags.cpp:44
Global flash based parameter store.
static bool preflightCheck(orb_advert_t *mavlink_log_pub, vehicle_status_s &status, vehicle_status_flags_s &status_flags, const bool checkGNSS, bool reportFailures, const bool prearm, const hrt_abstime &time_since_boot)
Runs a preflight check on all sensors to see if they are properly calibrated and healthy.
static constexpr unsigned max_mandatory_baro_count
static constexpr unsigned max_optional_baro_count
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:370
Contains helper functions to efficiently set the system health flags from commander and preflight che...
static constexpr unsigned max_mandatory_mag_count
static bool check_calibration(const char *param_template, const int32_t device_id)
static constexpr unsigned max_optional_accel_count
static constexpr unsigned max_mandatory_gyro_count
#define OK
Definition: uavcan_main.cpp:71
static constexpr unsigned max_optional_mag_count
Check if flight is safely possible if not prevent it and inform the user.
uint32_t param_t
Parameter handle.
Definition: param.h:98