mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-24 06:43:33 +08:00
ekf2: pos/vel reset helpers pass new variance
- optical flow velocity reset use already computed _flow_vel_ne
This commit is contained in:
@@ -695,20 +695,20 @@ private:
|
||||
// fuse single velocity and position measurement
|
||||
bool fuseVelPosHeight(const float innov, const float innov_var, const int obs_index);
|
||||
|
||||
void resetVelocityTo(const Vector3f &vel);
|
||||
void resetHorizontalVelocityTo(const Vector2f &new_horz_vel);
|
||||
void resetVerticalVelocityTo(float new_vert_vel, float new_vert_vel_var = NAN);
|
||||
void resetVelocityTo(const Vector3f &vel, const Vector3f &new_vel_var);
|
||||
|
||||
void resetHorizontalVelocityTo(const Vector2f &new_horz_vel, const Vector2f &new_horz_vel_var);
|
||||
void resetHorizontalVelocityTo(const Vector2f &new_horz_vel, float vel_var) { resetHorizontalVelocityTo(new_horz_vel, Vector2f(vel_var, vel_var)); }
|
||||
|
||||
void resetVelocityToGps(const gpsSample &gps_sample);
|
||||
void resetHorizontalVelocityToOpticalFlow(const flowSample &flow_sample);
|
||||
void resetVelocityToVision();
|
||||
void resetHorizontalVelocityToZero();
|
||||
|
||||
void resetHorizontalPositionToGps(const gpsSample &gps_sample);
|
||||
void resetVerticalVelocityTo(float new_vert_vel, float new_vert_vel_var);
|
||||
void resetHorizontalPositionToVision();
|
||||
void resetHorizontalPositionToOpticalFlow();
|
||||
void resetHorizontalPositionToLastKnown();
|
||||
void resetHorizontalPositionTo(const Vector2f &new_horz_pos);
|
||||
|
||||
void resetHorizontalPositionTo(const Vector2f &new_horz_pos, const Vector2f &new_horz_pos_var);
|
||||
void resetHorizontalPositionTo(const Vector2f &new_horz_pos, const float pos_var = NAN) { resetHorizontalPositionTo(new_horz_pos, Vector2f(pos_var, pos_var)); }
|
||||
|
||||
bool isHeightResetRequired() const;
|
||||
|
||||
@@ -1025,7 +1025,6 @@ private:
|
||||
void startAirspeedFusion();
|
||||
void stopAirspeedFusion();
|
||||
|
||||
void startGpsFusion(const gpsSample &gps_sample);
|
||||
void stopGpsFusion();
|
||||
void stopGpsPosFusion();
|
||||
void stopGpsVelFusion();
|
||||
|
||||
@@ -44,51 +44,11 @@
|
||||
#include <mathlib/mathlib.h>
|
||||
#include <cstdlib>
|
||||
|
||||
void Ekf::resetVelocityToGps(const gpsSample &gps_sample)
|
||||
{
|
||||
_information_events.flags.reset_vel_to_gps = true;
|
||||
ECL_INFO("reset velocity to GPS");
|
||||
resetVelocityTo(gps_sample.vel);
|
||||
P.uncorrelateCovarianceSetVariance<3>(4, sq(gps_sample.sacc));
|
||||
}
|
||||
|
||||
void Ekf::resetHorizontalVelocityToOpticalFlow(const flowSample &flow_sample)
|
||||
{
|
||||
_information_events.flags.reset_vel_to_flow = true;
|
||||
ECL_INFO("reset velocity to flow");
|
||||
// constrain height above ground to be above minimum possible
|
||||
const float heightAboveGndEst = fmaxf((_terrain_vpos - _state.pos(2)), _params.rng_gnd_clearance);
|
||||
|
||||
// calculate absolute distance from focal point to centre of frame assuming a flat earth
|
||||
const float range = heightAboveGndEst / _range_sensor.getCosTilt();
|
||||
|
||||
if ((range - _params.rng_gnd_clearance) > 0.3f) {
|
||||
// we should have reliable OF measurements so
|
||||
// calculate X and Y body relative velocities from OF measurements
|
||||
Vector3f vel_optflow_body;
|
||||
vel_optflow_body(0) = - range * _flow_compensated_XY_rad(1) / flow_sample.dt;
|
||||
vel_optflow_body(1) = range * _flow_compensated_XY_rad(0) / flow_sample.dt;
|
||||
vel_optflow_body(2) = 0.0f;
|
||||
|
||||
// rotate from body to earth frame
|
||||
const Vector3f vel_optflow_earth = _R_to_earth * vel_optflow_body;
|
||||
|
||||
resetHorizontalVelocityTo(Vector2f(vel_optflow_earth));
|
||||
|
||||
} else {
|
||||
resetHorizontalVelocityTo(Vector2f{0.f, 0.f});
|
||||
}
|
||||
|
||||
// reset the horizontal velocity variance using the optical flow noise variance
|
||||
P.uncorrelateCovarianceSetVariance<2>(4, sq(range) * calcOptFlowMeasVar(flow_sample));
|
||||
}
|
||||
|
||||
void Ekf::resetVelocityToVision()
|
||||
{
|
||||
_information_events.flags.reset_vel_to_vision = true;
|
||||
ECL_INFO("reset to vision velocity");
|
||||
resetVelocityTo(getVisionVelocityInEkfFrame());
|
||||
P.uncorrelateCovarianceSetVariance<3>(4, getVisionVelocityVarianceInEkfFrame());
|
||||
resetVelocityTo(getVisionVelocityInEkfFrame(), getVisionVelocityVarianceInEkfFrame());
|
||||
}
|
||||
|
||||
void Ekf::resetHorizontalVelocityToZero()
|
||||
@@ -96,21 +56,28 @@ void Ekf::resetHorizontalVelocityToZero()
|
||||
_information_events.flags.reset_vel_to_zero = true;
|
||||
ECL_INFO("reset velocity to zero");
|
||||
// Used when falling back to non-aiding mode of operation
|
||||
resetHorizontalVelocityTo(Vector2f{0.f, 0.f});
|
||||
P.uncorrelateCovarianceSetVariance<2>(4, 25.0f);
|
||||
resetHorizontalVelocityTo(Vector2f{0.f, 0.f}, 25.f);
|
||||
}
|
||||
|
||||
void Ekf::resetVelocityTo(const Vector3f &new_vel)
|
||||
void Ekf::resetVelocityTo(const Vector3f &new_vel, const Vector3f &new_vel_var)
|
||||
{
|
||||
resetHorizontalVelocityTo(Vector2f(new_vel));
|
||||
resetVerticalVelocityTo(new_vel(2));
|
||||
resetHorizontalVelocityTo(Vector2f(new_vel), Vector2f(new_vel_var(0), new_vel_var(1)));
|
||||
resetVerticalVelocityTo(new_vel(2), new_vel_var(2));
|
||||
}
|
||||
|
||||
void Ekf::resetHorizontalVelocityTo(const Vector2f &new_horz_vel)
|
||||
void Ekf::resetHorizontalVelocityTo(const Vector2f &new_horz_vel, const Vector2f &new_horz_vel_var)
|
||||
{
|
||||
const Vector2f delta_horz_vel = new_horz_vel - Vector2f(_state.vel);
|
||||
_state.vel.xy() = new_horz_vel;
|
||||
|
||||
if (PX4_ISFINITE(new_horz_vel_var(0))) {
|
||||
P.uncorrelateCovarianceSetVariance<1>(4, math::max(sq(0.01f), new_horz_vel_var(0)));
|
||||
}
|
||||
|
||||
if (PX4_ISFINITE(new_horz_vel_var(1))) {
|
||||
P.uncorrelateCovarianceSetVariance<1>(5, math::max(sq(0.01f), new_horz_vel_var(1)));
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < _output_buffer.get_length(); index++) {
|
||||
_output_buffer[index].vel.xy() += delta_horz_vel;
|
||||
}
|
||||
@@ -148,14 +115,6 @@ void Ekf::resetVerticalVelocityTo(float new_vert_vel, float new_vert_vel_var)
|
||||
_time_last_ver_vel_fuse = _imu_sample_delayed.time_us;
|
||||
}
|
||||
|
||||
void Ekf::resetHorizontalPositionToGps(const gpsSample &gps_sample)
|
||||
{
|
||||
_information_events.flags.reset_pos_to_gps = true;
|
||||
ECL_INFO("reset position to GPS");
|
||||
resetHorizontalPositionTo(gps_sample.pos);
|
||||
P.uncorrelateCovarianceSetVariance<2>(7, sq(gps_sample.hacc));
|
||||
}
|
||||
|
||||
void Ekf::resetHorizontalPositionToVision()
|
||||
{
|
||||
_information_events.flags.reset_pos_to_vision = true;
|
||||
@@ -166,45 +125,33 @@ void Ekf::resetHorizontalPositionToVision()
|
||||
_ev_pos = _R_ev_to_ekf * _ev_sample_delayed.pos;
|
||||
}
|
||||
|
||||
resetHorizontalPositionTo(Vector2f(_ev_pos));
|
||||
P.uncorrelateCovarianceSetVariance<2>(7, _ev_sample_delayed.posVar.slice<2, 1>(0, 0));
|
||||
resetHorizontalPositionTo(Vector2f(_ev_pos), _ev_sample_delayed.posVar.slice<2, 1>(0, 0));
|
||||
|
||||
// let the next odometry update know that the previous value of states cannot be used to calculate the change in position
|
||||
_hpos_prev_available = false;
|
||||
}
|
||||
|
||||
void Ekf::resetHorizontalPositionToOpticalFlow()
|
||||
{
|
||||
_information_events.flags.reset_pos_to_last_known = true;
|
||||
|
||||
if (!_control_status.flags.in_air) {
|
||||
ECL_INFO("reset horizontal position to (0, 0)");
|
||||
// we are likely starting OF for the first time so reset the horizontal position
|
||||
resetHorizontalPositionTo(Vector2f(0.f, 0.f));
|
||||
|
||||
} else {
|
||||
ECL_INFO("reset horizontal position to last known");
|
||||
resetHorizontalPositionTo(_last_known_pos.xy());
|
||||
}
|
||||
|
||||
// estimate is relative to initial position in this mode, so we start with zero error.
|
||||
P.uncorrelateCovarianceSetVariance<2>(7, 0.0f);
|
||||
}
|
||||
|
||||
void Ekf::resetHorizontalPositionToLastKnown()
|
||||
{
|
||||
_information_events.flags.reset_pos_to_last_known = true;
|
||||
ECL_INFO("reset position to last known position");
|
||||
// Used when falling back to non-aiding mode of operation
|
||||
resetHorizontalPositionTo(_last_known_pos.xy());
|
||||
P.uncorrelateCovarianceSetVariance<2>(7, sq(_params.pos_noaid_noise));
|
||||
resetHorizontalPositionTo(_last_known_pos.xy(), sq(_params.pos_noaid_noise));
|
||||
}
|
||||
|
||||
void Ekf::resetHorizontalPositionTo(const Vector2f &new_horz_pos)
|
||||
void Ekf::resetHorizontalPositionTo(const Vector2f &new_horz_pos, const Vector2f &new_horz_pos_var)
|
||||
{
|
||||
const Vector2f delta_horz_pos{new_horz_pos - Vector2f{_state.pos}};
|
||||
_state.pos.xy() = new_horz_pos;
|
||||
|
||||
if (PX4_ISFINITE(new_horz_pos_var(0))) {
|
||||
P.uncorrelateCovarianceSetVariance<1>(7, math::max(sq(0.01f), new_horz_pos_var(0)));
|
||||
}
|
||||
|
||||
if (PX4_ISFINITE(new_horz_pos_var(1))) {
|
||||
P.uncorrelateCovarianceSetVariance<1>(8, math::max(sq(0.01f), new_horz_pos_var(1)));
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < _output_buffer.get_length(); index++) {
|
||||
_output_buffer[index].pos.xy() += delta_horz_pos;
|
||||
}
|
||||
@@ -1356,22 +1303,6 @@ void Ekf::stopAirspeedFusion()
|
||||
_control_status.flags.fuse_aspd = false;
|
||||
}
|
||||
|
||||
void Ekf::startGpsFusion(const gpsSample &gps_sample)
|
||||
{
|
||||
if (!_control_status.flags.gps) {
|
||||
resetHorizontalPositionToGps(gps_sample);
|
||||
|
||||
// when already using another velocity source velocity reset is not necessary
|
||||
if (!_control_status.flags.opt_flow && !_control_status.flags.ev_vel) {
|
||||
resetVelocityToGps(gps_sample);
|
||||
}
|
||||
|
||||
_information_events.flags.starting_gps_fusion = true;
|
||||
ECL_INFO("starting GPS fusion");
|
||||
_control_status.flags.gps = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Ekf::stopGpsFusion()
|
||||
{
|
||||
if (_control_status.flags.gps) {
|
||||
|
||||
@@ -59,10 +59,11 @@ void Ekf::controlGpsFusion()
|
||||
controlGpsYawFusion(gps_sample, gps_checks_passing, gps_checks_failing);
|
||||
|
||||
// GNSS velocity
|
||||
const float vel_obs_var = sq(math::max(gps_sample.sacc, _params.gps_vel_noise));
|
||||
const float vel_var = sq(math::max(gps_sample.sacc, _params.gps_vel_noise));
|
||||
const Vector3f vel_obs_var(vel_var, vel_var, vel_var * sq(1.5f));
|
||||
updateVelocityAidSrcStatus(gps_sample.time_us,
|
||||
gps_sample.vel, // observation
|
||||
Vector3f(vel_obs_var, vel_obs_var, vel_obs_var * sq(1.5f)), // observation variance
|
||||
vel_obs_var, // observation variance
|
||||
math::max(_params.gps_vel_innov_gate, 1.f), // innovation gate
|
||||
_aid_src_gnss_vel);
|
||||
_aid_src_gnss_vel.fusion_enabled = (_params.gnss_ctrl & GnssCtrl::VEL);
|
||||
@@ -79,10 +80,11 @@ void Ekf::controlGpsFusion()
|
||||
}
|
||||
}
|
||||
|
||||
const float pos_obs_var = sq(pos_noise);
|
||||
const float pos_var = sq(pos_noise);
|
||||
const Vector2f pos_obs_var(pos_var, pos_var);
|
||||
updateHorizontalPositionAidSrcStatus(gps_sample.time_us,
|
||||
gps_sample.pos, // observation
|
||||
Vector2f(pos_obs_var, pos_obs_var), // observation variance
|
||||
pos_obs_var, // observation variance
|
||||
math::max(_params.gps_pos_innov_gate, 1.f), // innovation gate
|
||||
_aid_src_gnss_pos);
|
||||
_aid_src_gnss_pos.fusion_enabled = (_params.gnss_ctrl & GnssCtrl::HPOS);
|
||||
@@ -129,9 +131,11 @@ void Ekf::controlGpsFusion()
|
||||
}
|
||||
}
|
||||
|
||||
ECL_WARN("GPS fusion timeout - resetting");
|
||||
resetVelocityToGps(gps_sample);
|
||||
resetHorizontalPositionToGps(gps_sample);
|
||||
ECL_WARN("GPS fusion timeout, resetting velocity and position");
|
||||
_information_events.flags.reset_vel_to_gps = true;
|
||||
_information_events.flags.reset_pos_to_gps = true;
|
||||
resetVelocityTo(gps_sample.vel, vel_obs_var);
|
||||
resetHorizontalPositionTo(gps_sample.pos, pos_obs_var);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -165,7 +169,20 @@ void Ekf::controlGpsFusion()
|
||||
_inhibit_ev_yaw_use = true;
|
||||
|
||||
} else {
|
||||
startGpsFusion(gps_sample);
|
||||
ECL_INFO("starting GPS fusion");
|
||||
_information_events.flags.starting_gps_fusion = true;
|
||||
|
||||
// reset position
|
||||
_information_events.flags.reset_pos_to_gps = true;
|
||||
resetHorizontalPositionTo(gps_sample.pos, pos_obs_var);
|
||||
|
||||
// when already using another velocity source velocity reset is not necessary
|
||||
if (!isHorizontalAidingActive()) {
|
||||
_information_events.flags.reset_vel_to_gps = true;
|
||||
resetVelocityTo(gps_sample.vel, vel_obs_var);
|
||||
}
|
||||
|
||||
_control_status.flags.gps = true;
|
||||
}
|
||||
|
||||
} else if (gps_checks_passing && !_control_status.flags.yaw_align && (_params.mag_fusion_type == MagFuseType::NONE)) {
|
||||
@@ -173,8 +190,12 @@ void Ekf::controlGpsFusion()
|
||||
if (resetYawToEKFGSF()) {
|
||||
_information_events.flags.yaw_aligned_to_imu_gps = true;
|
||||
ECL_INFO("Yaw aligned using IMU and GPS");
|
||||
resetVelocityToGps(gps_sample);
|
||||
resetHorizontalPositionToGps(gps_sample);
|
||||
|
||||
ECL_INFO("reset velocity and position to GPS");
|
||||
_information_events.flags.reset_vel_to_gps = true;
|
||||
_information_events.flags.reset_pos_to_gps = true;
|
||||
resetVelocityTo(gps_sample.vel, vel_obs_var);
|
||||
resetHorizontalPositionTo(gps_sample.pos, pos_obs_var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,11 +77,12 @@ void Ekf::controlOpticalFlowFusion()
|
||||
_delta_time_of = _imu_sample_delayed.delta_ang_dt;
|
||||
|
||||
is_delta_time_good = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_quality_good && !is_delta_time_good) {
|
||||
ECL_DEBUG("Optical flow: bad delta time: OF dt %.6f s (min: %.3f, max: %.3f), IMU dt %.6f s",
|
||||
(double)_flow_sample_delayed.dt, (double)delta_time_min, (double)delta_time_max, (double)_imu_sample_delayed.delta_ang_dt);
|
||||
(double)_flow_sample_delayed.dt, (double)delta_time_min, (double)delta_time_max,
|
||||
(double)_imu_sample_delayed.delta_ang_dt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,12 +167,25 @@ void Ekf::controlOpticalFlowFusion()
|
||||
|
||||
// if we are not using GPS or external vision aiding, then the velocity and position states and covariances need to be set
|
||||
if (!isHorizontalAidingActive()) {
|
||||
resetHorizontalVelocityToOpticalFlow(_flow_sample_delayed);
|
||||
resetHorizontalPositionToOpticalFlow();
|
||||
ECL_INFO("reset velocity to flow");
|
||||
_information_events.flags.reset_vel_to_flow = true;
|
||||
resetHorizontalVelocityTo(_flow_vel_ne, calcOptFlowMeasVar(_flow_sample_delayed));
|
||||
|
||||
// reset position, estimate is relative to initial position in this mode, so we start with zero error
|
||||
if (!_control_status.flags.in_air) {
|
||||
ECL_INFO("reset position to zero");
|
||||
resetHorizontalPositionTo(Vector2f(0.f, 0.f), 0.f);
|
||||
_last_known_pos.xy() = _state.pos.xy();
|
||||
|
||||
} else {
|
||||
_information_events.flags.reset_pos_to_last_known = true;
|
||||
ECL_INFO("reset position to last known position");
|
||||
resetHorizontalPositionTo(_last_known_pos.xy(), 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
_control_status.flags.opt_flow = true;
|
||||
_aid_src_optical_flow.time_last_fuse = _imu_sample_delayed.time_us;
|
||||
_control_status.flags.opt_flow = true;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -190,11 +204,19 @@ void Ekf::controlOpticalFlowFusion()
|
||||
}
|
||||
|
||||
// handle the case when we have optical flow, are reliant on it, but have not been using it for an extended period
|
||||
if (isTimedOut(_aid_src_optical_flow.time_last_fuse, _params.reset_timeout_max)
|
||||
if (isTimedOut(_aid_src_optical_flow.time_last_fuse, _params.no_aid_timeout_max)
|
||||
&& !isOtherSourceOfHorizontalAidingThan(_control_status.flags.opt_flow)) {
|
||||
|
||||
resetHorizontalVelocityToOpticalFlow(_flow_sample_delayed);
|
||||
resetHorizontalPositionToOpticalFlow();
|
||||
ECL_INFO("reset velocity to flow");
|
||||
_information_events.flags.reset_vel_to_flow = true;
|
||||
resetHorizontalVelocityTo(_flow_vel_ne, calcOptFlowMeasVar(_flow_sample_delayed));
|
||||
|
||||
// reset position, estimate is relative to initial position in this mode, so we start with zero error
|
||||
ECL_INFO("reset position to last known");
|
||||
_information_events.flags.reset_pos_to_last_known = true;
|
||||
resetHorizontalPositionTo(_last_known_pos.xy(), 0.f);
|
||||
|
||||
_aid_src_optical_flow.time_last_fuse = _imu_sample_delayed.time_us;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user