ekf2: add kconfig option to enable/disable external vision fusion

This commit is contained in:
Daniel Agar 2023-03-14 16:31:26 -04:00
parent d47f96f1a5
commit 4363b09421
17 changed files with 209 additions and 68 deletions

View File

@ -26,6 +26,7 @@ CONFIG_MODULES_EKF2=y
# CONFIG_EKF2_AUXVEL is not set
# CONFIG_EKF2_BARO_COMPENSATION is not set
# CONFIG_EKF2_DRAG_FUSION is not set
# CONFIG_EKF2_EXTERNAL_VISION is not set
# CONFIG_EKF2_GNSS_YAW is not set
# CONFIG_EKF2_SIDESLIP is not set
CONFIG_MODULES_FLIGHT_MODE_MANAGER=y

View File

@ -76,11 +76,6 @@ list(APPEND EKF_SRCS
EKF/ekf_helper.cpp
EKF/EKFGSF_yaw.cpp
EKF/estimator_interface.cpp
EKF/ev_control.cpp
EKF/ev_height_control.cpp
EKF/ev_pos_control.cpp
EKF/ev_vel_control.cpp
EKF/ev_yaw_control.cpp
EKF/fake_height_control.cpp
EKF/fake_pos_control.cpp
EKF/gnss_height_control.cpp
@ -115,6 +110,16 @@ if(CONFIG_EKF2_DRAG_FUSION)
list(APPEND EKF_SRCS EKF/drag_fusion.cpp)
endif()
if(CONFIG_EKF2_EXTERNAL_VISION)
list(APPEND EKF_SRCS
EKF/ev_control.cpp
EKF/ev_height_control.cpp
EKF/ev_pos_control.cpp
EKF/ev_vel_control.cpp
EKF/ev_yaw_control.cpp
)
endif()
if(CONFIG_EKF2_GNSS_YAW)
list(APPEND EKF_SRCS EKF/gps_yaw_fusion.cpp)
endif()

View File

@ -41,11 +41,6 @@ list(APPEND EKF_SRCS
ekf_helper.cpp
EKFGSF_yaw.cpp
estimator_interface.cpp
ev_control.cpp
ev_height_control.cpp
ev_pos_control.cpp
ev_vel_control.cpp
ev_yaw_control.cpp
fake_height_control.cpp
fake_pos_control.cpp
gnss_height_control.cpp
@ -80,6 +75,17 @@ if(CONFIG_EKF2_DRAG_FUSION)
list(APPEND EKF_SRCS drag_fusion.cpp)
endif()
if(CONFIG_EKF2_EXTERNAL_VISION)
list(APPEND EKF_SRCS
ev_control.cpp
ev_height_control.cpp
ev_pos_control.cpp
ev_vel_control.cpp
ev_yaw_control.cpp
)
endif()
if(CONFIG_EKF2_GNSS_YAW)
list(APPEND EKF_SRCS gps_yaw_fusion.cpp)
endif()

View File

@ -238,6 +238,7 @@ struct flowSample {
uint8_t quality{}; ///< quality indicator between 0 and 255
};
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
struct extVisionSample {
uint64_t time_us{}; ///< timestamp of the measurement (uSec)
Vector3f pos{}; ///< XYZ position in external vision's local reference frame (m) - Z must be aligned with down axis
@ -251,6 +252,7 @@ struct extVisionSample {
uint8_t reset_counter{};
int8_t quality{}; ///< quality indicator between 0 and 100
};
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_DRAG_FUSION)
struct dragSample {
@ -299,7 +301,6 @@ struct parameters {
int32_t baro_ctrl{1};
int32_t gnss_ctrl{GnssCtrl::HPOS | GnssCtrl::VEL};
int32_t rng_ctrl{RngCtrl::CONDITIONAL};
int32_t ev_ctrl{0};
int32_t terrain_fusion_mode{TerrainFusionMask::TerrainFuseRangeFinder |
TerrainFusionMask::TerrainFuseOpticalFlow}; ///< aiding source(s) selection bitmask for the terrain estimator
@ -311,7 +312,6 @@ struct parameters {
float gps_delay_ms{110.0f}; ///< GPS measurement delay relative to the IMU (mSec)
float flow_delay_ms{5.0f}; ///< optical flow measurement delay relative to the IMU (mSec) - this is to the middle of the optical flow integration interval
float range_delay_ms{5.0f}; ///< range finder measurement delay relative to the IMU (mSec)
float ev_delay_ms{175.0f}; ///< off-board vision measurement delay relative to the IMU (mSec)
// input noise
float gyro_noise{1.5e-2f}; ///< IMU angular rate noise used for covariance prediction (rad/sec)
@ -395,7 +395,11 @@ struct parameters {
float range_cos_max_tilt{0.7071f}; ///< cosine of the maximum tilt angle from the vertical that permits use of range finder and flow data
float range_kin_consistency_gate{1.0f}; ///< gate size used by the range finder kinematic consistency check
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
// vision position fusion
int32_t ev_ctrl{0};
float ev_delay_ms{175.0f}; ///< off-board vision measurement delay relative to the IMU (mSec)
float ev_vel_noise{0.1f}; ///< minimum allowed observation noise for EV velocity fusion (m/sec)
float ev_pos_noise{0.1f}; ///< minimum allowed observation noise for EV position fusion (m)
float ev_att_noise{0.1f}; ///< minimum allowed observation noise for EV attitude fusion (rad/sec)
@ -403,6 +407,7 @@ struct parameters {
float ev_vel_innov_gate{3.0f}; ///< vision velocity fusion innovation consistency gate size (STD)
float ev_pos_innov_gate{5.0f}; ///< vision position fusion innovation consistency gate size (STD)
float ev_hgt_bias_nsd{0.13f}; ///< process noise for vision height bias estimation (m/s/sqrt(Hz))
#endif // CONFIG_EKF2_EXTERNAL_VISION
// gravity fusion
float gravity_noise{1.0f}; ///< accelerometer measurement gaussian noise (m/s**2)

View File

@ -122,8 +122,10 @@ void Ekf::controlFusionModes(const imuSample &imu_delayed)
controlHeightFusion(imu_delayed);
controlGravityFusion(imu_delayed);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
// Additional data odometry data from an external estimator can be fused.
controlExternalVisionFusion();
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_AUXVEL)
// Additional horizontal velocity data from an auxiliary sensor can be fused

View File

@ -444,14 +444,22 @@ void Ekf::fixCovarianceErrors(bool force_symmetry)
if (fabsf(down_dvel_bias) > dVel_bias_lim) {
bool bad_vz_gps = _control_status.flags.gps && (down_dvel_bias * _aid_src_gnss_vel.innovation[2] < 0.0f);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
bool bad_vz_ev = _control_status.flags.ev_vel && (down_dvel_bias * _aid_src_ev_vel.innovation[2] < 0.0f);
#else
bool bad_vz_ev = false;
#endif // CONFIG_EKF2_EXTERNAL_VISION
if (bad_vz_gps || bad_vz_ev) {
bool bad_z_baro = _control_status.flags.baro_hgt && (down_dvel_bias * _aid_src_baro_hgt.innovation < 0.0f);
bool bad_z_gps = _control_status.flags.gps_hgt && (down_dvel_bias * _aid_src_gnss_hgt.innovation < 0.0f);
bool bad_z_rng = _control_status.flags.rng_hgt && (down_dvel_bias * _aid_src_rng_hgt.innovation < 0.0f);
bool bad_z_ev = _control_status.flags.ev_hgt && (down_dvel_bias * _aid_src_ev_hgt.innovation < 0.0f);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
bool bad_z_ev = _control_status.flags.ev_hgt && (down_dvel_bias * _aid_src_ev_hgt.innovation < 0.0f);
#else
bool bad_z_ev = false;
#endif // CONFIG_EKF2_EXTERNAL_VISION
if (bad_z_baro || bad_z_gps || bad_z_rng || bad_z_ev) {
bad_acc_bias = true;

View File

@ -126,10 +126,12 @@ void Ekf::reset()
resetEstimatorAidStatus(_aid_src_fake_pos);
resetEstimatorAidStatus(_aid_src_fake_hgt);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
resetEstimatorAidStatus(_aid_src_ev_hgt);
resetEstimatorAidStatus(_aid_src_ev_pos);
resetEstimatorAidStatus(_aid_src_ev_vel);
resetEstimatorAidStatus(_aid_src_ev_yaw);
#endif // CONFIG_EKF2_EXTERNAL_VISION
resetEstimatorAidStatus(_aid_src_gnss_hgt);
resetEstimatorAidStatus(_aid_src_gnss_pos);

View File

@ -86,9 +86,11 @@ public:
void getGpsVelPosInnovVar(float hvel[2], float &vvel, float hpos[2], float &vpos) const;
void getGpsVelPosInnovRatio(float &hvel, float &vvel, float &hpos, float &vpos) const;
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
void getEvVelPosInnov(float hvel[2], float &vvel, float hpos[2], float &vpos) const;
void getEvVelPosInnovVar(float hvel[2], float &vvel, float hpos[2], float &vpos) const;
void getEvVelPosInnovRatio(float &hvel, float &vvel, float &hpos, float &vpos) const;
#endif // CONFIG_EKF2_EXTERNAL_VISION
void getBaroHgtInnov(float &baro_hgt_innov) const { baro_hgt_innov = _aid_src_baro_hgt.innovation; }
void getBaroHgtInnovVar(float &baro_hgt_innov_var) const { baro_hgt_innov_var = _aid_src_baro_hgt.innovation_variance; }
@ -140,10 +142,12 @@ public:
}
#endif // CONFIG_EKF2_GNSS_YAW
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_yaw) {
heading_innov = _aid_src_ev_yaw.innovation;
return;
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
}
void getHeadingInnovVar(float &heading_innov_var) const
@ -165,10 +169,12 @@ public:
}
#endif // CONFIG_EKF2_GNSS_YAW
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_yaw) {
heading_innov_var = _aid_src_ev_yaw.innovation_variance;
return;
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
}
void getHeadingInnovRatio(float &heading_innov_ratio) const
@ -190,10 +196,12 @@ public:
}
#endif // CONFIG_EKF2_GNSS_YAW
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_yaw) {
heading_innov_ratio = _aid_src_ev_yaw.test_ratio;
return;
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
}
void getMagInnov(float mag_innov[3]) const { memcpy(mag_innov, _aid_src_mag.innovation, sizeof(_aid_src_mag.innovation)); }
@ -443,9 +451,11 @@ public:
const BiasEstimator::status &getBaroBiasEstimatorStatus() const { return _baro_b_est.getStatus(); }
const BiasEstimator::status &getGpsHgtBiasEstimatorStatus() const { return _gps_hgt_b_est.getStatus(); }
const BiasEstimator::status &getRngHgtBiasEstimatorStatus() const { return _rng_hgt_b_est.getStatus(); }
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
const BiasEstimator::status &getEvHgtBiasEstimatorStatus() const { return _ev_hgt_b_est.getStatus(); }
const BiasEstimator::status &getEvPosBiasEstimatorStatus(int i) const { return _ev_pos_b_est.getStatus(i); }
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_AIRSPEED)
const auto &aid_src_airspeed() const { return _aid_src_airspeed; }
@ -461,10 +471,12 @@ public:
const auto &aid_src_fake_hgt() const { return _aid_src_fake_hgt; }
const auto &aid_src_fake_pos() const { return _aid_src_fake_pos; }
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
const auto &aid_src_ev_hgt() const { return _aid_src_ev_hgt; }
const auto &aid_src_ev_pos() const { return _aid_src_ev_pos; }
const auto &aid_src_ev_vel() const { return _aid_src_ev_vel; }
const auto &aid_src_ev_yaw() const { return _aid_src_ev_yaw; }
#endif // CONFIG_EKF2_EXTERNAL_VISION
const auto &aid_src_gnss_hgt() const { return _aid_src_gnss_hgt; }
const auto &aid_src_gnss_pos() const { return _aid_src_gnss_pos; }
@ -525,9 +537,6 @@ private:
bool _filter_initialised{false}; ///< true when the EKF sttes and covariances been initialised
float _ev_yaw_pred_prev{}; ///< previous value of yaw state used by odometry fusion (m)
bool _inhibit_ev_yaw_use{false}; ///< true when the vision yaw data should not be used (e.g.: NE fusion requires true North)
// booleans true when fresh sensor data is available at the fusion time horizon
bool _gps_data_ready{false}; ///< true when new GPS data has fallen behind the fusion time horizon and is available to be fused
bool _flow_data_ready{false}; ///< true when the leading edge of the optical flow integration period has fallen behind the fusion time horizon
@ -547,10 +556,6 @@ private:
uint64_t _time_last_zero_velocity_fuse{0}; ///< last time of zero velocity update (uSec)
uint64_t _time_last_healthy_rng_data{0};
uint8_t _nb_ev_pos_reset_available{0};
uint8_t _nb_ev_vel_reset_available{0};
uint8_t _nb_ev_yaw_reset_available{0};
Vector3f _last_known_pos{}; ///< last known local position vector (m)
uint64_t _time_acc_bias_check{0}; ///< last time the accel bias check passed (uSec)
@ -609,11 +614,20 @@ private:
estimator_aid_source2d_s _aid_src_fake_pos{};
estimator_aid_source1d_s _aid_src_fake_hgt{};
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
estimator_aid_source1d_s _aid_src_ev_hgt{};
estimator_aid_source2d_s _aid_src_ev_pos{};
estimator_aid_source3d_s _aid_src_ev_vel{};
estimator_aid_source1d_s _aid_src_ev_yaw{};
float _ev_yaw_pred_prev{}; ///< previous value of yaw state used by odometry fusion (m)
uint8_t _nb_ev_pos_reset_available{0};
uint8_t _nb_ev_vel_reset_available{0};
uint8_t _nb_ev_yaw_reset_available{0};
#endif // CONFIG_EKF2_EXTERNAL_VISION
bool _inhibit_ev_yaw_use{false}; ///< true when the vision yaw data should not be used (e.g.: NE fusion requires true North)
estimator_aid_source1d_s _aid_src_gnss_hgt{};
estimator_aid_source2d_s _aid_src_gnss_pos{};
estimator_aid_source3d_s _aid_src_gnss_vel{};
@ -946,18 +960,21 @@ private:
// Control the filter fusion modes
void controlFusionModes(const imuSample &imu_delayed);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
// control fusion of external vision observations
void controlExternalVisionFusion();
void controlEvHeightFusion(const extVisionSample &ev_sample, const bool common_starting_conditions_passing, const bool ev_reset, const bool quality_sufficient, estimator_aid_source1d_s &aid_src);
void controlEvPosFusion(const extVisionSample &ev_sample, const bool common_starting_conditions_passing, const bool ev_reset, const bool quality_sufficient, estimator_aid_source2d_s &aid_src);
void controlEvVelFusion(const extVisionSample &ev_sample, const bool common_starting_conditions_passing, const bool ev_reset, const bool quality_sufficient, estimator_aid_source3d_s &aid_src);
void controlEvYawFusion(const extVisionSample &ev_sample, const bool common_starting_conditions_passing, const bool ev_reset, const bool quality_sufficient, estimator_aid_source1d_s &aid_src);
void startEvPosFusion(const Vector2f &measurement, const Vector2f &measurement_var, estimator_aid_source2d_s &aid_src);
void updateEvPosFusion(const Vector2f &measurement, const Vector2f &measurement_var, bool quality_sufficient, bool reset, estimator_aid_source2d_s &aid_src);
void stopEvPosFusion();
void controlEvVelFusion(const extVisionSample &ev_sample, const bool common_starting_conditions_passing, const bool ev_reset, const bool quality_sufficient, estimator_aid_source3d_s &aid_src);
void controlEvYawFusion(const extVisionSample &ev_sample, const bool common_starting_conditions_passing, const bool ev_reset, const bool quality_sufficient, estimator_aid_source1d_s &aid_src);
void stopEvHgtFusion();
void stopEvVelFusion();
void stopEvYawFusion();
#endif // CONFIG_EKF2_EXTERNAL_VISION
// control fusion of optical flow observations
void controlOpticalFlowFusion(const imuSample &imu_delayed);
@ -1029,7 +1046,6 @@ private:
void stopBaroHgtFusion();
void stopGpsHgtFusion();
void stopRngHgtFusion();
void stopEvHgtFusion();
void updateGroundEffect();
@ -1095,9 +1111,6 @@ private:
void stopGpsPosFusion();
void stopGpsVelFusion();
void stopEvVelFusion();
void stopEvYawFusion();
void stopFlowFusion();
void resetFakePosFusion();
@ -1121,8 +1134,11 @@ private:
HeightBiasEstimator _baro_b_est{HeightSensor::BARO, _height_sensor_ref};
HeightBiasEstimator _gps_hgt_b_est{HeightSensor::GNSS, _height_sensor_ref};
HeightBiasEstimator _rng_hgt_b_est{HeightSensor::RANGE, _height_sensor_ref};
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
HeightBiasEstimator _ev_hgt_b_est{HeightSensor::EV, _height_sensor_ref};
PositionBiasEstimator _ev_pos_b_est{static_cast<uint8_t>(PositionSensor::EV), _position_sensor_ref};
#endif // CONFIG_EKF2_EXTERNAL_VISION
// Resets the main Nav EKf yaw to the estimator from the EKF-GSF yaw estimator
// Resets the horizontal velocity and position to the default navigation sensor

View File

@ -150,7 +150,9 @@ void Ekf::resetHorizontalPositionTo(const Vector2f &new_horz_pos, const Vector2f
_state_reset_status.reset_count.posNE++;
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
_ev_pos_b_est.setBias(_ev_pos_b_est.getBias() - _state_reset_status.posNE_change);
#endif // CONFIG_EKF2_EXTERNAL_VISION
//_gps_pos_b_est.setBias(_gps_pos_b_est.getBias() + _state_reset_status.posNE_change);
// Reset the timout timer
@ -196,7 +198,9 @@ void Ekf::resetVerticalPositionTo(const float new_vert_pos, float new_vert_pos_v
_state_reset_status.reset_count.posD++;
_baro_b_est.setBias(_baro_b_est.getBias() + delta_z);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
_ev_hgt_b_est.setBias(_ev_hgt_b_est.getBias() - delta_z);
#endif // CONFIG_EKF2_EXTERNAL_VISION
_gps_hgt_b_est.setBias(_gps_hgt_b_est.getBias() + delta_z);
_rng_hgt_b_est.setBias(_rng_hgt_b_est.getBias() + delta_z);
@ -304,6 +308,7 @@ void Ekf::getGpsVelPosInnovRatio(float &hvel, float &vvel, float &hpos, float &v
vpos = _aid_src_gnss_hgt.test_ratio;
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
void Ekf::getEvVelPosInnov(float hvel[2], float &vvel, float hpos[2], float &vpos) const
{
hvel[0] = _aid_src_ev_vel.innovation[0];
@ -334,6 +339,7 @@ void Ekf::getEvVelPosInnovRatio(float &hvel, float &vvel, float &hpos, float &vp
hpos = fmaxf(_aid_src_ev_pos.test_ratio[0], _aid_src_ev_pos.test_ratio[1]);
vpos = _aid_src_ev_hgt.test_ratio;
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_AUXVEL)
void Ekf::getAuxVelInnov(float aux_vel_innov[2]) const
@ -466,9 +472,11 @@ void Ekf::get_ekf_gpos_accuracy(float *ekf_eph, float *ekf_epv) const
hpos_err = math::max(hpos_err, Vector2f(_aid_src_gnss_pos.innovation).norm());
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_pos) {
hpos_err = math::max(hpos_err, Vector2f(_aid_src_ev_pos.innovation).norm());
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
}
*ekf_eph = hpos_err;
@ -489,9 +497,11 @@ void Ekf::get_ekf_lpos_accuracy(float *ekf_eph, float *ekf_epv) const
hpos_err = math::max(hpos_err, Vector2f(_aid_src_gnss_pos.innovation).norm());
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_pos) {
hpos_err = math::max(hpos_err, Vector2f(_aid_src_ev_pos.innovation).norm());
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
}
*ekf_eph = hpos_err;
@ -516,14 +526,17 @@ void Ekf::get_ekf_vel_accuracy(float *ekf_evh, float *ekf_evv) const
if (_control_status.flags.gps) {
vel_err_conservative = math::max(vel_err_conservative, Vector2f(_aid_src_gnss_pos.innovation).norm());
}
} else if (_control_status.flags.ev_pos) {
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_pos) {
vel_err_conservative = math::max(vel_err_conservative, Vector2f(_aid_src_ev_pos.innovation).norm());
}
if (_control_status.flags.ev_vel) {
vel_err_conservative = math::max(vel_err_conservative, Vector2f(_aid_src_ev_vel.innovation).norm());
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
hvel_err = math::max(hvel_err, vel_err_conservative);
}
@ -637,6 +650,12 @@ void Ekf::get_innovation_test_status(uint16_t &status, float &mag, float &vel, f
}
#endif // CONFIG_EKF2_GNSS_YAW
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_yaw) {
mag = math::max(mag, sqrtf(_aid_src_ev_yaw.test_ratio));
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
// return the largest velocity and position innovation test ratio
vel = NAN;
pos = NAN;
@ -649,6 +668,7 @@ void Ekf::get_innovation_test_status(uint16_t &status, float &mag, float &vel, f
pos = math::max(gps_pos, FLT_MIN);
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_vel) {
float ev_vel = sqrtf(Vector3f(_aid_src_ev_vel.test_ratio).max());
vel = math::max(vel, ev_vel, FLT_MIN);
@ -658,6 +678,7 @@ void Ekf::get_innovation_test_status(uint16_t &status, float &mag, float &vel, f
float ev_pos = sqrtf(Vector2f(_aid_src_ev_pos.test_ratio).max());
pos = math::max(pos, ev_pos, FLT_MIN);
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
if (isOnlyActiveSourceOfHorizontalAiding(_control_status.flags.opt_flow)) {
float of_vel = sqrtf(Vector2f(_aid_src_optical_flow.test_ratio).max());
@ -683,10 +704,12 @@ void Ekf::get_innovation_test_status(uint16_t &status, float &mag, float &vel, f
n_hgt_sources++;
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_hgt) {
hgt_sum += sqrtf(_aid_src_ev_hgt.test_ratio);
n_hgt_sources++;
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
if (n_hgt_sources > 0) {
hgt = math::max(hgt_sum / static_cast<float>(n_hgt_sources), FLT_MIN);
@ -1136,9 +1159,12 @@ bool Ekf::resetYawToEKFGSF()
_control_status.flags.gps_yaw_fault = true;
_warning_events.flags.emergency_yaw_reset_gps_yaw_stopped = true;
} else if (_control_status.flags.ev_yaw) {
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_yaw) {
_inhibit_ev_yaw_use = true;
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
return true;
}

View File

@ -54,7 +54,9 @@ EstimatorInterface::~EstimatorInterface()
delete _airspeed_buffer;
#endif // CONFIG_EKF2_AIRSPEED
delete _flow_buffer;
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
delete _ext_vision_buffer;
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_DRAG_FUSION)
delete _drag_buffer;
#endif // CONFIG_EKF2_DRAG_FUSION
@ -355,7 +357,7 @@ void EstimatorInterface::setOpticalFlowData(const flowSample &flow)
}
}
// set attitude and position data derived from an external vision system
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
void EstimatorInterface::setExtVisionData(const extVisionSample &evdata)
{
if (!_initialised) {
@ -392,6 +394,7 @@ void EstimatorInterface::setExtVisionData(const extVisionSample &evdata)
ECL_WARN("EV data too fast %" PRIi64 " < %" PRIu64 " + %d", time_us, _ext_vision_buffer->get_newest().time_us, _min_obs_interval_us);
}
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_AUXVEL)
void EstimatorInterface::setAuxVelData(const auxVelSample &auxvel_sample)
@ -561,9 +564,11 @@ bool EstimatorInterface::initialise_interface(uint64_t timestamp)
max_time_delay_ms = math::max(_params.flow_delay_ms, max_time_delay_ms);
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_params.ev_ctrl > 0) {
max_time_delay_ms = math::max(_params.ev_delay_ms, max_time_delay_ms);
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
const float filter_update_period_ms = _params.filter_update_interval_us / 1000.f;
@ -703,9 +708,11 @@ void EstimatorInterface::print_status()
printf("flow buffer: %d/%d (%d Bytes)\n", _flow_buffer->entries(), _flow_buffer->get_length(), _flow_buffer->get_total_size());
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_ext_vision_buffer) {
printf("vision buffer: %d/%d (%d Bytes)\n", _ext_vision_buffer->entries(), _ext_vision_buffer->get_length(), _ext_vision_buffer->get_total_size());
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_DRAG_FUSION)
if (_drag_buffer) {

View File

@ -99,8 +99,10 @@ public:
// if optical flow sensor gyro delta angles are not available, set gyro_xyz vector fields to NaN and the EKF will use its internal delta angle data instead
void setOpticalFlowData(const flowSample &flow);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
// set external vision position and attitude data
void setExtVisionData(const extVisionSample &evdata);
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_AUXVEL)
void setAuxVelData(const auxVelSample &auxvel_sample);
@ -295,11 +297,17 @@ protected:
// measurement samples capturing measurements on the delayed time horizon
gpsSample _gps_sample_delayed{};
sensor::SensorRangeFinder _range_sensor{};
#if defined(CONFIG_EKF2_AIRSPEED)
airspeedSample _airspeed_sample_delayed{};
#endif // CONFIG_EKF2_AIRSPEED
flowSample _flow_sample_delayed{};
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
extVisionSample _ev_sample_prev{};
#endif // CONFIG_EKF2_EXTERNAL_VISION
RangeFinderConsistencyCheck _rng_consistency_check;
float _air_density{CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C}; // air density (kg/m**3)
@ -358,7 +366,11 @@ protected:
RingBuffer<airspeedSample> *_airspeed_buffer{nullptr};
#endif // CONFIG_EKF2_AIRSPEED
RingBuffer<flowSample> *_flow_buffer{nullptr};
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
RingBuffer<extVisionSample> *_ext_vision_buffer{nullptr};
uint64_t _time_last_ext_vision_buffer_push{0};
#endif // CONFIG_EKF2_EXTERNAL_VISION
#if defined(CONFIG_EKF2_AUXVEL)
RingBuffer<auxVelSample> *_auxvel_buffer{nullptr};
#endif // CONFIG_EKF2_AUXVEL
@ -368,7 +380,6 @@ protected:
uint64_t _time_last_mag_buffer_push{0};
uint64_t _time_last_baro_buffer_push{0};
uint64_t _time_last_range_buffer_push{0};
uint64_t _time_last_ext_vision_buffer_push{0};
uint64_t _time_last_gnd_effect_on{0};

View File

@ -178,9 +178,11 @@ void Ekf::controlEvYawFusion(const extVisionSample &ev_sample, const bool common
void Ekf::stopEvYawFusion()
{
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_yaw) {
resetEstimatorAidStatus(_aid_src_ev_yaw);
_control_status.flags.ev_yaw = false;
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
}

View File

@ -119,6 +119,7 @@ void Ekf::controlGpsFusion(const imuSample &imu_delayed)
_aid_src_gnss_pos);
_aid_src_gnss_pos.fusion_enabled = (_params.gnss_ctrl & GnssCtrl::HPOS);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
// if GPS is otherwise ready to go, but yaw_align is blocked by EV give mag a chance to start
if (_control_status.flags.tilt_align && _NED_origin_initialised
&& gps_checks_passing && !gps_checks_failing) {
@ -139,7 +140,7 @@ void Ekf::controlGpsFusion(const imuSample &imu_delayed)
}
}
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
// Determine if we should use GPS aiding for velocity and horizontal position
// To start using GPS we need angular alignment completed, the local NED origin set and GPS data that has not failed checks recently
@ -202,6 +203,7 @@ void Ekf::controlGpsFusion(const imuSample &imu_delayed)
} else {
if (starting_conditions_passing) {
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
// Do not use external vision for yaw if using GPS because yaw needs to be
// defined relative to an NED reference frame
if (_control_status.flags.ev_yaw) {
@ -209,6 +211,7 @@ void Ekf::controlGpsFusion(const imuSample &imu_delayed)
stopEvYawFusion();
_inhibit_ev_yaw_use = true;
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
ECL_INFO("starting GPS fusion");
_information_events.flags.starting_gps_fusion = true;
@ -396,7 +399,7 @@ void Ekf::startGpsYawFusion(const gpsSample &gps_sample)
ECL_INFO("starting GPS yaw fusion");
_control_status.flags.yaw_align = true;
_control_status.flags.mag_dec = false;
stopEvYawFusion();
stopMagHdgFusion();
stopMag3DFusion();
_control_status.flags.gps_yaw = true;

View File

@ -166,11 +166,11 @@ Likelihood Ekf::estimateInertialNavFallingLikelihood() const
enum class ReferenceType { PRESSURE, GNSS, GROUND };
struct {
ReferenceType ref_type;
float innov;
float innov_var;
bool failed_min;
bool failed_lim;
ReferenceType ref_type{};
float innov{0.f};
float innov_var{0.f};
bool failed_min{false};
bool failed_lim{false};
} checks[6] {};
if (_control_status.flags.baro_hgt) {
@ -189,6 +189,7 @@ Likelihood Ekf::estimateInertialNavFallingLikelihood() const
checks[3] = {ReferenceType::GROUND, _aid_src_rng_hgt.innovation, _aid_src_rng_hgt.innovation_variance};
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if (_control_status.flags.ev_hgt) {
checks[4] = {ReferenceType::GROUND, _aid_src_ev_hgt.innovation, _aid_src_ev_hgt.innovation_variance};
}
@ -196,6 +197,7 @@ Likelihood Ekf::estimateInertialNavFallingLikelihood() const
if (_control_status.flags.ev_vel) {
checks[5] = {ReferenceType::GROUND, _aid_src_ev_vel.innovation[2], _aid_src_ev_vel.innovation_variance[2]};
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
// Compute the check based on innovation ratio for all the sources
for (unsigned i = 0; i < 6; i++) {

View File

@ -65,7 +65,6 @@ EKF2::EKF2(bool multi_mode, const px4::wq_config_t &config, bool replay_mode):
_param_ekf2_gps_delay(_params->gps_delay_ms),
_param_ekf2_of_delay(_params->flow_delay_ms),
_param_ekf2_rng_delay(_params->range_delay_ms),
_param_ekf2_ev_delay(_params->ev_delay_ms),
#if defined(CONFIG_EKF2_AUXVEL)
_param_ekf2_avel_delay(_params->auxvel_delay_ms),
#endif // CONFIG_EKF2_AUXVEL
@ -132,6 +131,8 @@ EKF2::EKF2(bool multi_mode, const px4::wq_config_t &config, bool replay_mode):
_param_ekf2_rng_a_igate(_params->range_aid_innov_gate),
_param_ekf2_rng_qlty_t(_params->range_valid_quality_s),
_param_ekf2_rng_k_gate(_params->range_kin_consistency_gate),
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
_param_ekf2_ev_delay(_params->ev_delay_ms),
_param_ekf2_ev_ctrl(_params->ev_ctrl),
_param_ekf2_ev_qmin(_params->ev_quality_minimum),
_param_ekf2_evp_noise(_params->ev_pos_noise),
@ -139,6 +140,10 @@ EKF2::EKF2(bool multi_mode, const px4::wq_config_t &config, bool replay_mode):
_param_ekf2_eva_noise(_params->ev_att_noise),
_param_ekf2_evv_gate(_params->ev_vel_innov_gate),
_param_ekf2_evp_gate(_params->ev_pos_innov_gate),
_param_ekf2_ev_pos_x(_params->ev_pos_body(0)),
_param_ekf2_ev_pos_y(_params->ev_pos_body(1)),
_param_ekf2_ev_pos_z(_params->ev_pos_body(2)),
#endif // CONFIG_EKF2_EXTERNAL_VISION
_param_ekf2_grav_noise(_params->gravity_noise),
_param_ekf2_of_n_min(_params->flow_noise),
_param_ekf2_of_n_max(_params->flow_noise_qual_min),
@ -156,9 +161,6 @@ EKF2::EKF2(bool multi_mode, const px4::wq_config_t &config, bool replay_mode):
_param_ekf2_of_pos_x(_params->flow_pos_body(0)),
_param_ekf2_of_pos_y(_params->flow_pos_body(1)),
_param_ekf2_of_pos_z(_params->flow_pos_body(2)),
_param_ekf2_ev_pos_x(_params->ev_pos_body(0)),
_param_ekf2_ev_pos_y(_params->ev_pos_body(1)),
_param_ekf2_ev_pos_z(_params->ev_pos_body(2)),
_param_ekf2_gbias_init(_params->switch_on_gyro_bias),
_param_ekf2_abias_init(_params->switch_on_accel_bias),
_param_ekf2_angerr_init(_params->initial_tilt_err),
@ -240,6 +242,8 @@ bool EKF2::multi_init(int imu, int mag)
_estimator_baro_bias_pub.advertise();
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
// EV advertise
if (_param_ekf2_ev_ctrl.get() & static_cast<int32_t>(EvCtrl::VPOS)) {
_estimator_aid_src_ev_hgt_pub.advertise();
@ -259,6 +263,8 @@ bool EKF2::multi_init(int imu, int mag)
_estimator_aid_src_ev_yaw_pub.advertise();
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
// GNSS advertise
if (_param_ekf2_gps_ctrl.get() & static_cast<int32_t>(GnssCtrl::VPOS)) {
_estimator_aid_src_gnss_hgt_pub.advertise();
@ -636,7 +642,9 @@ void EKF2::Run()
UpdateAuxVelSample(ekf2_timestamps);
#endif // CONFIG_EKF2_AUXVEL
UpdateBaroSample(ekf2_timestamps);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
UpdateExtVisionSample(ekf2_timestamps);
#endif // CONFIG_EKF2_EXTERNAL_VISION
UpdateFlowSample(ekf2_timestamps);
UpdateGpsSample(ekf2_timestamps);
UpdateMagSample(ekf2_timestamps);
@ -658,7 +666,9 @@ void EKF2::Run()
PublishBaroBias(now);
PublishGnssHgtBias(now);
PublishRngHgtBias(now);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
PublishEvPosBias(now);
#endif // CONFIG_EKF2_EXTERNAL_VISION
PublishEventFlags(now);
PublishGpsStatus(now);
PublishInnovations(now);
@ -749,6 +759,8 @@ void EKF2::VerifyParams()
"GPS enabled by EKF2_HGT_REF", _param_ekf2_gps_ctrl.get());
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
if ((_param_ekf2_hgt_ref.get() == HeightSensor::EV)
&& !(_param_ekf2_ev_ctrl.get() & static_cast<int32_t>(EvCtrl::VPOS))) {
_param_ekf2_ev_ctrl.set(_param_ekf2_ev_ctrl.get() | static_cast<int32_t>(EvCtrl::VPOS));
@ -798,6 +810,7 @@ void EKF2::VerifyParams()
"Use EKF2_EV_CTRL instead", _param_ekf2_aid_mask.get());
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
// IMU EKF2_AID_MASK -> EKF2_IMU_CTRL (2023-01-31)
if (_param_ekf2_aid_mask.get() & SensorFusionMask::DEPRECATED_INHIBIT_ACC_BIAS) {
@ -840,11 +853,13 @@ void EKF2::PublishAidSourceStatus(const hrt_abstime &timestamp)
PublishAidSourceStatus(_ekf.aid_src_fake_pos(), _status_fake_pos_pub_last, _estimator_aid_src_fake_pos_pub);
PublishAidSourceStatus(_ekf.aid_src_fake_hgt(), _status_fake_hgt_pub_last, _estimator_aid_src_fake_hgt_pub);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
// external vision (EV) hgt/pos/vel/yaw
PublishAidSourceStatus(_ekf.aid_src_ev_hgt(), _status_ev_hgt_pub_last, _estimator_aid_src_ev_hgt_pub);
PublishAidSourceStatus(_ekf.aid_src_ev_pos(), _status_ev_pos_pub_last, _estimator_aid_src_ev_pos_pub);
PublishAidSourceStatus(_ekf.aid_src_ev_vel(), _status_ev_vel_pub_last, _estimator_aid_src_ev_vel_pub);
PublishAidSourceStatus(_ekf.aid_src_ev_yaw(), _status_ev_yaw_pub_last, _estimator_aid_src_ev_yaw_pub);
#endif // CONFIG_EKF2_EXTERNAL_VISION
// GNSS hgt/pos/vel/yaw
PublishAidSourceStatus(_ekf.aid_src_gnss_hgt(), _status_gnss_hgt_pub_last, _estimator_aid_src_gnss_hgt_pub);
@ -934,6 +949,7 @@ void EKF2::PublishRngHgtBias(const hrt_abstime &timestamp)
}
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
void EKF2::PublishEvPosBias(const hrt_abstime &timestamp)
{
if (_ekf.aid_src_ev_hgt().timestamp_sample) {
@ -966,6 +982,7 @@ void EKF2::PublishEvPosBias(const hrt_abstime &timestamp)
}
}
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
estimator_bias_s EKF2::fillEstimatorBiasMsg(const BiasEstimator::status &status, uint64_t timestamp_sample_us,
uint64_t timestamp, uint32_t device_id)
@ -1146,7 +1163,9 @@ void EKF2::PublishInnovations(const hrt_abstime &timestamp)
estimator_innovations_s innovations{};
innovations.timestamp_sample = _ekf.time_delayed_us();
_ekf.getGpsVelPosInnov(innovations.gps_hvel, innovations.gps_vvel, innovations.gps_hpos, innovations.gps_vpos);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
_ekf.getEvVelPosInnov(innovations.ev_hvel, innovations.ev_vvel, innovations.ev_hpos, innovations.ev_vpos);
#endif // CONFIG_EKF2_EXTERNAL_VISION
_ekf.getBaroHgtInnov(innovations.baro_vpos);
_ekf.getRngHgtInnov(innovations.rng_vpos);
#if defined(CONFIG_EKF2_AUXVEL)
@ -1184,13 +1203,16 @@ void EKF2::PublishInnovations(const hrt_abstime &timestamp)
// TODO: move to run before publications
_preflt_checker.setUsingGpsAiding(_ekf.control_status_flags().gps);
_preflt_checker.setUsingFlowAiding(_ekf.control_status_flags().opt_flow);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
_preflt_checker.setUsingEvPosAiding(_ekf.control_status_flags().ev_pos);
_preflt_checker.setUsingEvVelAiding(_ekf.control_status_flags().ev_vel);
_preflt_checker.setUsingEvHgtAiding(_ekf.control_status_flags().ev_hgt);
#endif // CONFIG_EKF2_EXTERNAL_VISION
_preflt_checker.setUsingBaroHgtAiding(_ekf.control_status_flags().baro_hgt);
_preflt_checker.setUsingGpsHgtAiding(_ekf.control_status_flags().gps_hgt);
_preflt_checker.setUsingRngHgtAiding(_ekf.control_status_flags().rng_hgt);
_preflt_checker.setUsingEvHgtAiding(_ekf.control_status_flags().ev_hgt);
_preflt_checker.setVehicleCanObserveHeadingInFlight(_ekf.control_status_flags().fixed_wing);
@ -1205,7 +1227,9 @@ void EKF2::PublishInnovationTestRatios(const hrt_abstime &timestamp)
test_ratios.timestamp_sample = _ekf.time_delayed_us();
_ekf.getGpsVelPosInnovRatio(test_ratios.gps_hvel[0], test_ratios.gps_vvel, test_ratios.gps_hpos[0],
test_ratios.gps_vpos);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
_ekf.getEvVelPosInnovRatio(test_ratios.ev_hvel[0], test_ratios.ev_vvel, test_ratios.ev_hpos[0], test_ratios.ev_vpos);
#endif // CONFIG_EKF2_EXTERNAL_VISION
_ekf.getBaroHgtInnovRatio(test_ratios.baro_vpos);
_ekf.getRngHgtInnovRatio(test_ratios.rng_vpos);
#if defined(CONFIG_EKF2_AUXVEL)
@ -1240,7 +1264,9 @@ void EKF2::PublishInnovationVariances(const hrt_abstime &timestamp)
estimator_innovations_s variances{};
variances.timestamp_sample = _ekf.time_delayed_us();
_ekf.getGpsVelPosInnovVar(variances.gps_hvel, variances.gps_vvel, variances.gps_hpos, variances.gps_vpos);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
_ekf.getEvVelPosInnovVar(variances.ev_hvel, variances.ev_vvel, variances.ev_hpos, variances.ev_vpos);
#endif // CONFIG_EKF2_EXTERNAL_VISION
_ekf.getBaroHgtInnovVar(variances.baro_vpos);
_ekf.getRngHgtInnovVar(variances.rng_vpos);
#if defined(CONFIG_EKF2_AUXVEL)
@ -1873,6 +1899,7 @@ void EKF2::UpdateBaroSample(ekf2_timestamps_s &ekf2_timestamps)
}
}
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
bool EKF2::UpdateExtVisionSample(ekf2_timestamps_s &ekf2_timestamps)
{
// EKF external vision sample
@ -2026,6 +2053,7 @@ bool EKF2::UpdateExtVisionSample(ekf2_timestamps_s &ekf2_timestamps)
return new_ev_odom;
}
#endif // CONFIG_EKF2_EXTERNAL_VISION
bool EKF2::UpdateFlowSample(ekf2_timestamps_s &ekf2_timestamps)
{

View File

@ -151,7 +151,10 @@ private:
void PublishBaroBias(const hrt_abstime &timestamp);
void PublishGnssHgtBias(const hrt_abstime &timestamp);
void PublishRngHgtBias(const hrt_abstime &timestamp);
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
void PublishEvPosBias(const hrt_abstime &timestamp);
#endif // CONFIG_EKF2_EXTERNAL_VISION
estimator_bias_s fillEstimatorBiasMsg(const BiasEstimator::status &status, uint64_t timestamp_sample_us,
uint64_t timestamp, uint32_t device_id = 0);
void PublishEventFlags(const hrt_abstime &timestamp);
@ -278,11 +281,23 @@ private:
hrt_abstime _status_fake_hgt_pub_last{0};
hrt_abstime _status_fake_pos_pub_last{0};
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
uORB::PublicationMulti<estimator_aid_source1d_s> _estimator_aid_src_ev_hgt_pub {ORB_ID(estimator_aid_src_ev_hgt)};
uORB::PublicationMulti<estimator_aid_source2d_s> _estimator_aid_src_ev_pos_pub{ORB_ID(estimator_aid_src_ev_pos)};
uORB::PublicationMulti<estimator_aid_source3d_s> _estimator_aid_src_ev_vel_pub{ORB_ID(estimator_aid_src_ev_vel)};
uORB::PublicationMulti<estimator_aid_source1d_s> _estimator_aid_src_ev_yaw_pub{ORB_ID(estimator_aid_src_ev_yaw)};
hrt_abstime _status_ev_hgt_pub_last{0};
hrt_abstime _status_ev_pos_pub_last{0};
hrt_abstime _status_ev_vel_pub_last{0};
hrt_abstime _status_ev_yaw_pub_last{0};
matrix::Vector3f _last_ev_bias_published{};
uORB::Subscription _ev_odom_sub{ORB_ID(vehicle_visual_odometry)};
uORB::PublicationMulti<estimator_bias3d_s> _estimator_ev_pos_bias_pub{ORB_ID(estimator_ev_pos_bias)};
#endif // CONFIG_EKF2_EXTERNAL_VISION
hrt_abstime _status_gnss_hgt_pub_last{0};
hrt_abstime _status_gnss_pos_pub_last{0};
hrt_abstime _status_gnss_vel_pub_last{0};
@ -310,7 +325,6 @@ private:
float _last_baro_bias_published{};
float _last_gnss_hgt_bias_published{};
float _last_rng_hgt_bias_published{};
matrix::Vector3f _last_ev_bias_published{};
#if defined(CONFIG_EKF2_AIRSPEED)
uORB::Subscription _airspeed_sub {ORB_ID(airspeed)};
@ -336,7 +350,6 @@ private:
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
uORB::Subscription _airdata_sub{ORB_ID(vehicle_air_data)};
uORB::Subscription _ev_odom_sub{ORB_ID(vehicle_visual_odometry)};
uORB::Subscription _magnetometer_sub{ORB_ID(vehicle_magnetometer)};
uORB::Subscription _sensor_selection_sub{ORB_ID(sensor_selection)};
uORB::Subscription _status_sub{ORB_ID(vehicle_status)};
@ -372,7 +385,6 @@ private:
uORB::PublicationMulti<estimator_bias_s> _estimator_baro_bias_pub{ORB_ID(estimator_baro_bias)};
uORB::PublicationMulti<estimator_bias_s> _estimator_gnss_hgt_bias_pub{ORB_ID(estimator_gnss_hgt_bias)};
uORB::PublicationMulti<estimator_bias_s> _estimator_rng_hgt_bias_pub{ORB_ID(estimator_rng_hgt_bias)};
uORB::PublicationMulti<estimator_bias3d_s> _estimator_ev_pos_bias_pub{ORB_ID(estimator_ev_pos_bias)};
uORB::PublicationMultiData<estimator_event_flags_s> _estimator_event_flags_pub{ORB_ID(estimator_event_flags)};
uORB::PublicationMulti<estimator_gps_status_s> _estimator_gps_status_pub{ORB_ID(estimator_gps_status)};
uORB::PublicationMulti<estimator_innovations_s> _estimator_innovation_test_ratios_pub{ORB_ID(estimator_innovation_test_ratios)};
@ -391,11 +403,6 @@ private:
uORB::PublicationMulti<estimator_aid_source1d_s> _estimator_aid_src_fake_hgt_pub{ORB_ID(estimator_aid_src_fake_hgt)};
uORB::PublicationMulti<estimator_aid_source2d_s> _estimator_aid_src_fake_pos_pub{ORB_ID(estimator_aid_src_fake_pos)};
uORB::PublicationMulti<estimator_aid_source1d_s> _estimator_aid_src_ev_hgt_pub{ORB_ID(estimator_aid_src_ev_hgt)};
uORB::PublicationMulti<estimator_aid_source2d_s> _estimator_aid_src_ev_pos_pub{ORB_ID(estimator_aid_src_ev_pos)};
uORB::PublicationMulti<estimator_aid_source3d_s> _estimator_aid_src_ev_vel_pub{ORB_ID(estimator_aid_src_ev_vel)};
uORB::PublicationMulti<estimator_aid_source1d_s> _estimator_aid_src_ev_yaw_pub{ORB_ID(estimator_aid_src_ev_yaw)};
uORB::PublicationMulti<estimator_aid_source1d_s> _estimator_aid_src_gnss_hgt_pub{ORB_ID(estimator_aid_src_gnss_hgt)};
uORB::PublicationMulti<estimator_aid_source2d_s> _estimator_aid_src_gnss_pos_pub{ORB_ID(estimator_aid_src_gnss_pos)};
uORB::PublicationMulti<estimator_aid_source3d_s> _estimator_aid_src_gnss_vel_pub{ORB_ID(estimator_aid_src_gnss_vel)};
@ -439,8 +446,6 @@ private:
_param_ekf2_of_delay, ///< optical flow measurement delay relative to the IMU (mSec) - this is to the middle of the optical flow integration interval
(ParamExtFloat<px4::params::EKF2_RNG_DELAY>)
_param_ekf2_rng_delay, ///< range finder measurement delay relative to the IMU (mSec)
(ParamExtFloat<px4::params::EKF2_EV_DELAY>)
_param_ekf2_ev_delay, ///< off-board vision measurement delay relative to the IMU (mSec)
#if defined(CONFIG_EKF2_AUXVEL)
(ParamExtFloat<px4::params::EKF2_AVEL_DELAY>)
@ -571,21 +576,32 @@ private:
(ParamExtFloat<px4::params::EKF2_RNG_K_GATE>)
_param_ekf2_rng_k_gate, ///< range finder kinematic consistency gate size (STD)
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
// vision estimate fusion
(ParamExtFloat<px4::params::EKF2_EV_DELAY>)
_param_ekf2_ev_delay, ///< off-board vision measurement delay relative to the IMU (mSec)
(ParamExtInt<px4::params::EKF2_EV_CTRL>) _param_ekf2_ev_ctrl, ///< external vision (EV) control selection
(ParamInt<px4::params::EKF2_EV_NOISE_MD>)
_param_ekf2_ev_noise_md, ///< determine source of vision observation noise
(ParamInt<px4::params::EKF2_EV_NOISE_MD>) _param_ekf2_ev_noise_md, ///< determine source of vision observation noise
(ParamExtInt<px4::params::EKF2_EV_QMIN>) _param_ekf2_ev_qmin,
(ParamExtFloat<px4::params::EKF2_EVP_NOISE>)
_param_ekf2_evp_noise, ///< default position observation noise for exernal vision measurements (m)
_param_ekf2_evp_noise, ///< default position observation noise for exernal vision measurements (m)
(ParamExtFloat<px4::params::EKF2_EVV_NOISE>)
_param_ekf2_evv_noise, ///< default velocity observation noise for exernal vision measurements (m/s)
_param_ekf2_evv_noise, ///< default velocity observation noise for exernal vision measurements (m/s)
(ParamExtFloat<px4::params::EKF2_EVA_NOISE>)
_param_ekf2_eva_noise, ///< default angular observation noise for exernal vision measurements (rad)
_param_ekf2_eva_noise, ///< default angular observation noise for exernal vision measurements (rad)
(ParamExtFloat<px4::params::EKF2_EVV_GATE>)
_param_ekf2_evv_gate, ///< external vision velocity innovation consistency gate size (STD)
_param_ekf2_evv_gate, ///< external vision velocity innovation consistency gate size (STD)
(ParamExtFloat<px4::params::EKF2_EVP_GATE>)
_param_ekf2_evp_gate, ///< external vision position innovation consistency gate size (STD)
_param_ekf2_evp_gate, ///< external vision position innovation consistency gate size (STD)
(ParamExtFloat<px4::params::EKF2_EV_POS_X>)
_param_ekf2_ev_pos_x, ///< X position of VI sensor focal point in body frame (m)
(ParamExtFloat<px4::params::EKF2_EV_POS_Y>)
_param_ekf2_ev_pos_y, ///< Y position of VI sensor focal point in body frame (m)
(ParamExtFloat<px4::params::EKF2_EV_POS_Z>)
_param_ekf2_ev_pos_z, ///< Z position of VI sensor focal point in body frame (m)
#endif // CONFIG_EKF2_EXTERNAL_VISION
(ParamExtFloat<px4::params::EKF2_GRAV_NOISE>)
_param_ekf2_grav_noise, ///< default accelerometer noise for gravity fusion measurements (m/s**2)
@ -616,12 +632,6 @@ private:
_param_ekf2_of_pos_y, ///< Y position of optical flow sensor focal point in body frame (m)
(ParamExtFloat<px4::params::EKF2_OF_POS_Z>)
_param_ekf2_of_pos_z, ///< Z position of optical flow sensor focal point in body frame (m)
(ParamExtFloat<px4::params::EKF2_EV_POS_X>)
_param_ekf2_ev_pos_x, ///< X position of VI sensor focal point in body frame (m)
(ParamExtFloat<px4::params::EKF2_EV_POS_Y>)
_param_ekf2_ev_pos_y, ///< Y position of VI sensor focal point in body frame (m)
(ParamExtFloat<px4::params::EKF2_EV_POS_Z>)
_param_ekf2_ev_pos_z, ///< Z position of VI sensor focal point in body frame (m)
// output predictor filter time constants
(ParamFloat<px4::params::EKF2_TAU_VEL>)

View File

@ -42,6 +42,13 @@ depends on MODULES_EKF2
---help---
EKF2 drag fusion support.
menuconfig EKF2_EXTERNAL_VISION
depends on MODULES_EKF2
bool "external vision (EV) fusion support"
default y
---help---
EKF2 external vision (EV) fusion support.
menuconfig EKF2_GNSS_YAW
depends on MODULES_EKF2
bool "GNSS yaw fusion support"