forked from Archive/PX4-Autopilot
estimated IMU bias preflight checks
- commander preflightcheck use estimator_sensor_bias message instead of EKF state index magic number - ekf2 publish estimated bias limits in estimator_sensor_bias - preflightcheck only error if bias estimate exceeds half of configured limit (delete COM_ARM_EKF_AB and COM_ARM_EKF_GB parameters)
This commit is contained in:
parent
7c95e99156
commit
48f125f150
|
@ -98,7 +98,6 @@ then
|
||||||
param set BAT_V_DIV 10.14
|
param set BAT_V_DIV 10.14
|
||||||
param set BAT_A_PER_V 18.18
|
param set BAT_A_PER_V 18.18
|
||||||
#param set CBRK_IO_SAFETY 22027
|
#param set CBRK_IO_SAFETY 22027
|
||||||
param set COM_ARM_EKF_AB 0.005
|
|
||||||
param set COM_DISARM_LAND 2
|
param set COM_DISARM_LAND 2
|
||||||
|
|
||||||
# Filter settings
|
# Filter settings
|
||||||
|
|
|
@ -77,7 +77,6 @@ then
|
||||||
|
|
||||||
param set BAT_SOURCE 0
|
param set BAT_SOURCE 0
|
||||||
param set CBRK_IO_SAFETY 22027
|
param set CBRK_IO_SAFETY 22027
|
||||||
#param set COM_ARM_EKF_AB 0.005
|
|
||||||
#param set COM_DISARM_LAND 3
|
#param set COM_DISARM_LAND 3
|
||||||
|
|
||||||
# Filter settings
|
# Filter settings
|
||||||
|
|
|
@ -107,7 +107,6 @@ then
|
||||||
param set BAT_V_DIV 10.14
|
param set BAT_V_DIV 10.14
|
||||||
param set BAT_A_PER_V 18.18
|
param set BAT_A_PER_V 18.18
|
||||||
#param set CBRK_IO_SAFETY 22027
|
#param set CBRK_IO_SAFETY 22027
|
||||||
param set COM_ARM_EKF_AB 0.005
|
|
||||||
param set COM_DISARM_LAND 2
|
param set COM_DISARM_LAND 2
|
||||||
|
|
||||||
# Filter settings
|
# Filter settings
|
||||||
|
|
|
@ -49,7 +49,6 @@ then
|
||||||
# sensor calibration
|
# sensor calibration
|
||||||
param set CAL_MAG_SIDES 63
|
param set CAL_MAG_SIDES 63
|
||||||
param set SENS_BOARD_ROT 0
|
param set SENS_BOARD_ROT 0
|
||||||
param set COM_ARM_EKF_AB 0.0032
|
|
||||||
|
|
||||||
# circuit breakers
|
# circuit breakers
|
||||||
param set CBRK_IO_SAFETY 22027
|
param set CBRK_IO_SAFETY 22027
|
||||||
|
|
|
@ -10,15 +10,18 @@ uint64 timestamp_sample # the timestamp of the raw data (microseconds)
|
||||||
|
|
||||||
uint32 gyro_device_id # unique device ID for the sensor that does not change between power cycles
|
uint32 gyro_device_id # unique device ID for the sensor that does not change between power cycles
|
||||||
float32[3] gyro_bias # gyroscope in-run bias in body frame (rad/s)
|
float32[3] gyro_bias # gyroscope in-run bias in body frame (rad/s)
|
||||||
|
float32 gyro_bias_limit # magnitude of maximum gyroscope in-run bias in body frame (rad/s)
|
||||||
float32[3] gyro_bias_variance
|
float32[3] gyro_bias_variance
|
||||||
bool gyro_bias_valid
|
bool gyro_bias_valid
|
||||||
|
|
||||||
uint32 accel_device_id # unique device ID for the sensor that does not change between power cycles
|
uint32 accel_device_id # unique device ID for the sensor that does not change between power cycles
|
||||||
float32[3] accel_bias # accelerometer in-run bias in body frame (m/s^2)
|
float32[3] accel_bias # accelerometer in-run bias in body frame (m/s^2)
|
||||||
|
float32 accel_bias_limit # magnitude of maximum accelerometer in-run bias in body frame (m/s^2)
|
||||||
float32[3] accel_bias_variance
|
float32[3] accel_bias_variance
|
||||||
bool accel_bias_valid
|
bool accel_bias_valid
|
||||||
|
|
||||||
uint32 mag_device_id # unique device ID for the sensor that does not change between power cycles
|
uint32 mag_device_id # unique device ID for the sensor that does not change between power cycles
|
||||||
float32[3] mag_bias # magnetometer in-run bias in body frame (Gauss)
|
float32[3] mag_bias # magnetometer in-run bias in body frame (Gauss)
|
||||||
|
float32 mag_bias_limit # magnitude of maximum magnetometer in-run bias in body frame (Gauss)
|
||||||
float32[3] mag_bias_variance
|
float32[3] mag_bias_variance
|
||||||
bool mag_bias_valid
|
bool mag_bias_valid
|
||||||
|
|
|
@ -232,7 +232,7 @@ bool PreFlightCheck::preflightCheck(orb_advert_t *mavlink_log_pub, vehicle_statu
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ekf2CheckStates(mavlink_log_pub, report_failures && report_ekf_fail)) {
|
if (!ekf2CheckSensorBias(mavlink_log_pub, report_failures && report_ekf_fail)) {
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ private:
|
||||||
static bool ekf2Check(orb_advert_t *mavlink_log_pub, vehicle_status_s &vehicle_status, const bool optional,
|
static bool ekf2Check(orb_advert_t *mavlink_log_pub, vehicle_status_s &vehicle_status, const bool optional,
|
||||||
const bool report_fail, const bool enforce_gps_required);
|
const bool report_fail, const bool enforce_gps_required);
|
||||||
|
|
||||||
static bool ekf2CheckStates(orb_advert_t *mavlink_log_pub, const bool report_fail);
|
static bool ekf2CheckSensorBias(orb_advert_t *mavlink_log_pub, const bool report_fail);
|
||||||
|
|
||||||
static bool failureDetectorCheck(orb_advert_t *mavlink_log_pub, const vehicle_status_s &status, const bool report_fail,
|
static bool failureDetectorCheck(orb_advert_t *mavlink_log_pub, const vehicle_status_s &status, const bool report_fail,
|
||||||
const bool prearm);
|
const bool prearm);
|
||||||
|
|
|
@ -39,9 +39,11 @@
|
||||||
#include <systemlib/mavlink_log.h>
|
#include <systemlib/mavlink_log.h>
|
||||||
#include <uORB/Subscription.hpp>
|
#include <uORB/Subscription.hpp>
|
||||||
#include <uORB/topics/estimator_selector_status.h>
|
#include <uORB/topics/estimator_selector_status.h>
|
||||||
#include <uORB/topics/estimator_states.h>
|
#include <uORB/topics/estimator_sensor_bias.h>
|
||||||
#include <uORB/topics/estimator_status.h>
|
#include <uORB/topics/estimator_status.h>
|
||||||
|
|
||||||
|
using namespace time_literals;
|
||||||
|
|
||||||
bool PreFlightCheck::ekf2Check(orb_advert_t *mavlink_log_pub, vehicle_status_s &vehicle_status, const bool optional,
|
bool PreFlightCheck::ekf2Check(orb_advert_t *mavlink_log_pub, vehicle_status_s &vehicle_status, const bool optional,
|
||||||
const bool report_fail, const bool enforce_gps_required)
|
const bool report_fail, const bool enforce_gps_required)
|
||||||
{
|
{
|
||||||
|
@ -69,7 +71,6 @@ bool PreFlightCheck::ekf2Check(orb_advert_t *mavlink_log_pub, vehicle_status_s &
|
||||||
// Get estimator status data if available and exit with a fail recorded if not
|
// Get estimator status data if available and exit with a fail recorded if not
|
||||||
uORB::SubscriptionData<estimator_selector_status_s> estimator_selector_status_sub{ORB_ID(estimator_selector_status)};
|
uORB::SubscriptionData<estimator_selector_status_s> estimator_selector_status_sub{ORB_ID(estimator_selector_status)};
|
||||||
uORB::SubscriptionData<estimator_status_s> status_sub{ORB_ID(estimator_status), estimator_selector_status_sub.get().primary_instance};
|
uORB::SubscriptionData<estimator_status_s> status_sub{ORB_ID(estimator_status), estimator_selector_status_sub.get().primary_instance};
|
||||||
status_sub.update();
|
|
||||||
const estimator_status_s &status = status_sub.get();
|
const estimator_status_s &status = status_sub.get();
|
||||||
|
|
||||||
if (status.timestamp == 0) {
|
if (status.timestamp == 0) {
|
||||||
|
@ -231,54 +232,57 @@ out:
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PreFlightCheck::ekf2CheckStates(orb_advert_t *mavlink_log_pub, const bool report_fail)
|
bool PreFlightCheck::ekf2CheckSensorBias(orb_advert_t *mavlink_log_pub, const bool report_fail)
|
||||||
{
|
{
|
||||||
float ekf_ab_test_limit = 1.0f; // pass limit re-used for each test
|
|
||||||
param_get(param_find("COM_ARM_EKF_AB"), &ekf_ab_test_limit);
|
|
||||||
|
|
||||||
float ekf_gb_test_limit = 1.0f; // pass limit re-used for each test
|
|
||||||
param_get(param_find("COM_ARM_EKF_GB"), &ekf_gb_test_limit);
|
|
||||||
|
|
||||||
// Get estimator states data if available and exit with a fail recorded if not
|
// Get estimator states data if available and exit with a fail recorded if not
|
||||||
uORB::SubscriptionData<estimator_selector_status_s> estimator_selector_status_sub{ORB_ID(estimator_selector_status)};
|
uORB::SubscriptionData<estimator_selector_status_s> estimator_selector_status_sub{ORB_ID(estimator_selector_status)};
|
||||||
uORB::Subscription states_sub{ORB_ID(estimator_states), estimator_selector_status_sub.get().primary_instance};
|
uORB::SubscriptionData<estimator_sensor_bias_s> estimator_sensor_bias_sub{ORB_ID(estimator_sensor_bias), estimator_selector_status_sub.get().primary_instance};
|
||||||
|
const estimator_sensor_bias_s &bias = estimator_sensor_bias_sub.get();
|
||||||
|
|
||||||
estimator_states_s states;
|
if (hrt_elapsed_time(&bias.timestamp) < 30_s) {
|
||||||
|
|
||||||
if (states_sub.copy(&states)) {
|
// check accelerometer bias estimates
|
||||||
|
if (bias.accel_bias_valid) {
|
||||||
|
const float ekf_ab_test_limit = 0.5f * bias.accel_bias_limit;
|
||||||
|
|
||||||
// check accelerometer delta velocity bias estimates
|
for (uint8_t axis_index = 0; axis_index < 3; axis_index++) {
|
||||||
for (uint8_t index = 13; index < 16; index++) {
|
|
||||||
// allow for higher uncertainty in estimates for axes that are less observable to prevent false positives
|
// allow for higher uncertainty in estimates for axes that are less observable to prevent false positives
|
||||||
// adjust test threshold by 3-sigma
|
// adjust test threshold by 3-sigma
|
||||||
float test_uncertainty = 3.0f * sqrtf(fmaxf(states.covariances[index], 0.0f));
|
const float test_uncertainty = 3.0f * sqrtf(fmaxf(bias.accel_bias_variance[axis_index], 0.0f));
|
||||||
|
|
||||||
if (fabsf(states.states[index]) > ekf_ab_test_limit + test_uncertainty) {
|
|
||||||
|
|
||||||
|
if (fabsf(bias.accel_bias[axis_index]) > ekf_ab_test_limit + test_uncertainty) {
|
||||||
if (report_fail) {
|
if (report_fail) {
|
||||||
PX4_ERR("state %d: |%.8f| > %.8f + %.8f", index, (double)states.states[index], (double)ekf_ab_test_limit,
|
PX4_ERR("accel bias (axis %d): |%.8f| > %.8f + %.8f", axis_index,
|
||||||
(double)test_uncertainty);
|
(double)bias.accel_bias[axis_index], (double)ekf_ab_test_limit, (double)test_uncertainty);
|
||||||
mavlink_log_critical(mavlink_log_pub, "Preflight Fail: High Accelerometer Bias");
|
mavlink_log_critical(mavlink_log_pub, "Preflight Fail: High Accelerometer Bias");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check gyro delta angle bias estimates
|
// check gyro bias estimates
|
||||||
|
if (bias.gyro_bias_valid) {
|
||||||
|
const float ekf_gb_test_limit = 0.5f * bias.gyro_bias_limit;
|
||||||
|
|
||||||
|
for (uint8_t axis_index = 0; axis_index < 3; axis_index++) {
|
||||||
|
// allow for higher uncertainty in estimates for axes that are less observable to prevent false positives
|
||||||
|
// adjust test threshold by 3-sigma
|
||||||
|
const float test_uncertainty = 3.0f * sqrtf(fmaxf(bias.gyro_bias_variance[axis_index], 0.0f));
|
||||||
|
|
||||||
if (fabsf(states.states[10]) > ekf_gb_test_limit
|
if (fabsf(bias.gyro_bias[axis_index]) > ekf_gb_test_limit + test_uncertainty) {
|
||||||
|| fabsf(states.states[11]) > ekf_gb_test_limit
|
|
||||||
|| fabsf(states.states[12]) > ekf_gb_test_limit) {
|
|
||||||
|
|
||||||
if (report_fail) {
|
if (report_fail) {
|
||||||
|
PX4_ERR("gyro bias (axis %d): |%.8f| > %.8f + %.8f", axis_index,
|
||||||
|
(double)bias.gyro_bias[axis_index], (double)ekf_gb_test_limit, (double)test_uncertainty);
|
||||||
mavlink_log_critical(mavlink_log_pub, "Preflight Fail: High Gyro Bias");
|
mavlink_log_critical(mavlink_log_pub, "Preflight Fail: High Gyro Bias");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -556,31 +556,6 @@ PARAM_DEFINE_FLOAT(COM_ARM_EKF_HGT, 1.0f);
|
||||||
*/
|
*/
|
||||||
PARAM_DEFINE_FLOAT(COM_ARM_EKF_YAW, 0.5f);
|
PARAM_DEFINE_FLOAT(COM_ARM_EKF_YAW, 0.5f);
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum value of EKF accelerometer delta velocity bias estimate that will allow arming.
|
|
||||||
* Note: ekf2 will limit the delta velocity bias estimate magnitude to be less than EKF2_ABL_LIM * FILTER_UPDATE_PERIOD_MS * 0.001 so this parameter must be less than that to be useful.
|
|
||||||
*
|
|
||||||
* @group Commander
|
|
||||||
* @unit m/s
|
|
||||||
* @min 0.001
|
|
||||||
* @max 0.01
|
|
||||||
* @decimal 4
|
|
||||||
* @increment 0.0001
|
|
||||||
*/
|
|
||||||
PARAM_DEFINE_FLOAT(COM_ARM_EKF_AB, 0.0022f);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum value of EKF gyro delta angle bias estimate that will allow arming
|
|
||||||
*
|
|
||||||
* @group Commander
|
|
||||||
* @unit rad
|
|
||||||
* @min 0.0001
|
|
||||||
* @max 0.0017
|
|
||||||
* @decimal 4
|
|
||||||
* @increment 0.0001
|
|
||||||
*/
|
|
||||||
PARAM_DEFINE_FLOAT(COM_ARM_EKF_GB, 0.0011f);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum accelerometer inconsistency between IMU units that will allow arming
|
* Maximum accelerometer inconsistency between IMU units that will allow arming
|
||||||
*
|
*
|
||||||
|
|
|
@ -884,6 +884,7 @@ void EKF2::PublishSensorBias(const hrt_abstime ×tamp)
|
||||||
if (_device_id_gyro != 0) {
|
if (_device_id_gyro != 0) {
|
||||||
bias.gyro_device_id = _device_id_gyro;
|
bias.gyro_device_id = _device_id_gyro;
|
||||||
gyro_bias.copyTo(bias.gyro_bias);
|
gyro_bias.copyTo(bias.gyro_bias);
|
||||||
|
bias.gyro_bias_limit = math::radians(20.f); // 20 degrees/s see Ekf::constrainStates()
|
||||||
_ekf.getGyroBiasVariance().copyTo(bias.gyro_bias_variance);
|
_ekf.getGyroBiasVariance().copyTo(bias.gyro_bias_variance);
|
||||||
bias.gyro_bias_valid = true;
|
bias.gyro_bias_valid = true;
|
||||||
|
|
||||||
|
@ -893,6 +894,7 @@ void EKF2::PublishSensorBias(const hrt_abstime ×tamp)
|
||||||
if ((_device_id_accel != 0) && !(_param_ekf2_aid_mask.get() & MASK_INHIBIT_ACC_BIAS)) {
|
if ((_device_id_accel != 0) && !(_param_ekf2_aid_mask.get() & MASK_INHIBIT_ACC_BIAS)) {
|
||||||
bias.accel_device_id = _device_id_accel;
|
bias.accel_device_id = _device_id_accel;
|
||||||
accel_bias.copyTo(bias.accel_bias);
|
accel_bias.copyTo(bias.accel_bias);
|
||||||
|
bias.accel_bias_limit = _params->acc_bias_lim;
|
||||||
_ekf.getAccelBiasVariance().copyTo(bias.accel_bias_variance);
|
_ekf.getAccelBiasVariance().copyTo(bias.accel_bias_variance);
|
||||||
bias.accel_bias_valid = !_ekf.fault_status_flags().bad_acc_bias;
|
bias.accel_bias_valid = !_ekf.fault_status_flags().bad_acc_bias;
|
||||||
|
|
||||||
|
@ -902,6 +904,7 @@ void EKF2::PublishSensorBias(const hrt_abstime ×tamp)
|
||||||
if (_device_id_mag != 0) {
|
if (_device_id_mag != 0) {
|
||||||
bias.mag_device_id = _device_id_mag;
|
bias.mag_device_id = _device_id_mag;
|
||||||
mag_bias.copyTo(bias.mag_bias);
|
mag_bias.copyTo(bias.mag_bias);
|
||||||
|
bias.mag_bias_limit = 0.5f; // 0.5 Gauss see Ekf::constrainStates()
|
||||||
_mag_cal_last_bias_variance.copyTo(bias.mag_bias_variance);
|
_mag_cal_last_bias_variance.copyTo(bias.mag_bias_variance);
|
||||||
bias.mag_bias_valid = _mag_cal_available;
|
bias.mag_bias_valid = _mag_cal_available;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue