mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-04-14 10:07:39 +08:00
336 lines
10 KiB
C++
336 lines
10 KiB
C++
/****************************************************************************
|
|
*
|
|
* Copyright (c) 2019-2020 PX4 Development Team. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Neither the name PX4 nor the names of its contributors may be
|
|
* used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/**
|
|
* @file PreFlightCheck.cpp
|
|
*/
|
|
|
|
#include "PreFlightCheck.hpp"
|
|
|
|
#include <drivers/drv_hrt.h>
|
|
#include <HealthFlags.h>
|
|
#include <lib/parameters/param.h>
|
|
#include <systemlib/mavlink_log.h>
|
|
#include <uORB/Subscription.hpp>
|
|
#include <uORB/topics/subsystem_info.h>
|
|
|
|
using namespace time_literals;
|
|
|
|
static constexpr unsigned max_mandatory_gyro_count = 1;
|
|
static constexpr unsigned max_optional_gyro_count = 3;
|
|
static constexpr unsigned max_mandatory_accel_count = 1;
|
|
static constexpr unsigned max_optional_accel_count = 3;
|
|
static constexpr unsigned max_mandatory_mag_count = 1;
|
|
static constexpr unsigned max_optional_mag_count = 4;
|
|
static constexpr unsigned max_mandatory_baro_count = 1;
|
|
static constexpr unsigned max_optional_baro_count = 1;
|
|
|
|
bool PreFlightCheck::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)
|
|
{
|
|
const bool hil_enabled = (status.hil_state == vehicle_status_s::HIL_STATE_ON);
|
|
|
|
reportFailures = (reportFailures && status_flags.condition_system_hotplug_timeout
|
|
&& !status_flags.condition_calibration_enabled);
|
|
|
|
const bool checkSensors = !hil_enabled;
|
|
const bool checkRC = (status.rc_input_mode == vehicle_status_s::RC_IN_MODE_DEFAULT);
|
|
const bool checkDynamic = !hil_enabled;
|
|
const bool checkPower = (status_flags.condition_power_input_valid && !status_flags.circuit_breaker_engaged_power_check);
|
|
|
|
bool checkAirspeed = false;
|
|
|
|
/* Perform airspeed check only if circuit breaker is not
|
|
* engaged and it's not a rotary wing */
|
|
if (!status_flags.circuit_breaker_engaged_airspd_check &&
|
|
(status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING || status.is_vtol)) {
|
|
checkAirspeed = true;
|
|
}
|
|
|
|
bool failed = false;
|
|
|
|
/* ---- MAG ---- */
|
|
if (checkSensors) {
|
|
int32_t sys_has_mag = 1;
|
|
param_get(param_find("SYS_HAS_MAG"), &sys_has_mag);
|
|
|
|
if (sys_has_mag == 1) {
|
|
|
|
bool prime_found = false;
|
|
|
|
int32_t prime_id = -1;
|
|
param_get(param_find("CAL_MAG_PRIME"), &prime_id);
|
|
|
|
/* check all sensors individually, but fail only for mandatory ones */
|
|
for (unsigned i = 0; i < max_optional_mag_count; i++) {
|
|
const bool required = (i < max_mandatory_mag_count) && (sys_has_mag == 1);
|
|
const bool report_fail = (reportFailures);
|
|
|
|
int32_t device_id = -1;
|
|
|
|
if (magnetometerCheck(mavlink_log_pub, status, i, !required, device_id, report_fail)) {
|
|
|
|
if ((prime_id > 0) && (device_id == prime_id)) {
|
|
prime_found = true;
|
|
}
|
|
|
|
} else {
|
|
if (required) {
|
|
failed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* check if the primary device is present */
|
|
if (!prime_found && prime_id != 0) {
|
|
if (reportFailures) {
|
|
mavlink_log_critical(mavlink_log_pub, "Primary compass not found");
|
|
}
|
|
|
|
set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_MAG, false, true, false, status);
|
|
failed = true;
|
|
}
|
|
|
|
/* mag consistency checks (need to be performed after the individual checks) */
|
|
if (!magConsistencyCheck(mavlink_log_pub, status, (reportFailures))) {
|
|
failed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ---- ACCEL ---- */
|
|
if (checkSensors) {
|
|
bool prime_found = false;
|
|
int32_t prime_id = -1;
|
|
param_get(param_find("CAL_ACC_PRIME"), &prime_id);
|
|
|
|
/* check all sensors individually, but fail only for mandatory ones */
|
|
for (unsigned i = 0; i < max_optional_accel_count; i++) {
|
|
const bool required = (i < max_mandatory_accel_count);
|
|
const bool report_fail = (reportFailures);
|
|
|
|
int32_t device_id = -1;
|
|
|
|
if (accelerometerCheck(mavlink_log_pub, status, i, !required, checkDynamic, device_id, report_fail)) {
|
|
|
|
if ((prime_id > 0) && (device_id == prime_id)) {
|
|
prime_found = true;
|
|
}
|
|
|
|
} else {
|
|
if (required) {
|
|
failed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* check if the primary device is present */
|
|
if (!prime_found && prime_id != 0) {
|
|
if (reportFailures) {
|
|
mavlink_log_critical(mavlink_log_pub, "Primary accelerometer not found");
|
|
}
|
|
|
|
set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_ACC, false, true, false, status);
|
|
failed = true;
|
|
}
|
|
}
|
|
|
|
/* ---- GYRO ---- */
|
|
if (checkSensors) {
|
|
bool prime_found = false;
|
|
int32_t prime_id = -1;
|
|
param_get(param_find("CAL_GYRO_PRIME"), &prime_id);
|
|
|
|
/* check all sensors individually, but fail only for mandatory ones */
|
|
for (unsigned i = 0; i < max_optional_gyro_count; i++) {
|
|
const bool required = (i < max_mandatory_gyro_count);
|
|
int32_t device_id = -1;
|
|
|
|
if (gyroCheck(mavlink_log_pub, status, i, !required, device_id, reportFailures)) {
|
|
|
|
if ((prime_id > 0) && (device_id == prime_id)) {
|
|
prime_found = true;
|
|
}
|
|
|
|
} else {
|
|
if (required) {
|
|
failed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* check if the primary device is present */
|
|
if (!prime_found && prime_id != 0) {
|
|
if (reportFailures) {
|
|
mavlink_log_critical(mavlink_log_pub, "Primary gyro not found");
|
|
}
|
|
|
|
set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_GYRO, false, true, false, status);
|
|
failed = true;
|
|
}
|
|
}
|
|
|
|
/* ---- BARO ---- */
|
|
if (checkSensors) {
|
|
int32_t sys_has_baro = 1;
|
|
param_get(param_find("SYS_HAS_BARO"), &sys_has_baro);
|
|
|
|
bool baro_fail_reported = false;
|
|
|
|
/* check all sensors, but fail only for mandatory ones */
|
|
for (unsigned i = 0; i < max_optional_baro_count; i++) {
|
|
const bool required = (i < max_mandatory_baro_count) && (sys_has_baro == 1);
|
|
const bool report_fail = (reportFailures && !baro_fail_reported);
|
|
|
|
int32_t device_id = -1;
|
|
|
|
if (!baroCheck(mavlink_log_pub, status, i, !required, device_id, report_fail)) {
|
|
if (required) {
|
|
baro_fail_reported = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ---- IMU CONSISTENCY ---- */
|
|
// To be performed after the individual sensor checks have completed
|
|
if (checkSensors) {
|
|
if (!imuConsistencyCheck(mavlink_log_pub, status, reportFailures)) {
|
|
failed = true;
|
|
}
|
|
}
|
|
|
|
/* ---- AIRSPEED ---- */
|
|
if (checkAirspeed) {
|
|
int32_t optional = 0;
|
|
param_get(param_find("FW_ARSP_MODE"), &optional);
|
|
|
|
if (!airspeedCheck(mavlink_log_pub, status, (bool)optional, reportFailures, prearm) && !(bool)optional) {
|
|
failed = true;
|
|
}
|
|
}
|
|
|
|
/* ---- RC CALIBRATION ---- */
|
|
if (checkRC) {
|
|
if (rcCalibrationCheck(mavlink_log_pub, reportFailures, status.is_vtol) != OK) {
|
|
if (reportFailures) {
|
|
mavlink_log_critical(mavlink_log_pub, "RC calibration check failed");
|
|
}
|
|
|
|
failed = true;
|
|
|
|
set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_RCRECEIVER, status_flags.rc_signal_found_once, true, false, status);
|
|
status_flags.rc_calibration_valid = false;
|
|
|
|
} else {
|
|
// The calibration is fine, but only set the overall health state to true if the signal is not currently lost
|
|
status_flags.rc_calibration_valid = true;
|
|
set_health_flags(subsystem_info_s::SUBSYSTEM_TYPE_RCRECEIVER, status_flags.rc_signal_found_once, true,
|
|
!status.rc_signal_lost, status);
|
|
}
|
|
}
|
|
|
|
/* ---- SYSTEM POWER ---- */
|
|
if (checkPower) {
|
|
if (!powerCheck(mavlink_log_pub, status, reportFailures, prearm)) {
|
|
failed = true;
|
|
}
|
|
}
|
|
|
|
/* ---- Navigation EKF ---- */
|
|
// only check EKF2 data if EKF2 is selected as the estimator and GNSS checking is enabled
|
|
int32_t estimator_type = -1;
|
|
|
|
if (status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING && !status.is_vtol) {
|
|
param_get(param_find("SYS_MC_EST_GROUP"), &estimator_type);
|
|
|
|
} else {
|
|
// EKF2 is currently the only supported option for FW & VTOL
|
|
estimator_type = 2;
|
|
}
|
|
|
|
if (estimator_type == 2) {
|
|
// don't report ekf failures for the first 10 seconds to allow time for the filter to start
|
|
bool report_ekf_fail = (time_since_boot > 10_s);
|
|
|
|
if (!ekf2Check(mavlink_log_pub, status, false, reportFailures && report_ekf_fail, checkGNSS)) {
|
|
failed = true;
|
|
}
|
|
}
|
|
|
|
/* ---- Failure Detector ---- */
|
|
if (!failureDetectorCheck(mavlink_log_pub, status, reportFailures, prearm)) {
|
|
failed = true;
|
|
}
|
|
|
|
/* Report status */
|
|
return !failed;
|
|
}
|
|
|
|
bool PreFlightCheck::check_calibration(const char *param_template, const int32_t device_id)
|
|
{
|
|
bool calibration_found = false;
|
|
|
|
char s[20];
|
|
int instance = 0;
|
|
|
|
/* old style transition: check param values */
|
|
while (!calibration_found) {
|
|
sprintf(s, param_template, instance);
|
|
const param_t parm = param_find_no_notification(s);
|
|
|
|
/* if the calibration param is not present, abort */
|
|
if (parm == PARAM_INVALID) {
|
|
break;
|
|
}
|
|
|
|
/* if param get succeeds */
|
|
int32_t calibration_devid = -1;
|
|
|
|
if (param_get(parm, &calibration_devid) == PX4_OK) {
|
|
|
|
/* if the devid matches, exit early */
|
|
if (device_id == calibration_devid) {
|
|
calibration_found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
instance++;
|
|
}
|
|
|
|
return calibration_found;
|
|
}
|