Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ekf2: add terrain/dist_bottom reset deltas (vehicle_local_position/vehicle_global_position) #23403

Merged
merged 3 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions msg/VehicleGlobalPosition.msg
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ float32 alt # Altitude AMSL, (meters)
float32 alt_ellipsoid # Altitude above ellipsoid, (meters)

float32 delta_alt # Reset delta for altitude
float32 delta_terrain # Reset delta for terrain
uint8 lat_lon_reset_counter # Counter for reset events on horizontal position coordinates
uint8 alt_reset_counter # Counter for reset events on altitude
uint8 terrain_reset_counter # Counter for reset events on terrain

float32 eph # Standard deviation of horizontal position error, (metres)
float32 epv # Standard deviation of vertical position error, (metres)
Expand Down
6 changes: 5 additions & 1 deletion msg/VehicleLocalPosition.msg
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@ float64 ref_lon # Reference point longitude, (degrees)
float32 ref_alt # Reference altitude AMSL, (metres)

# Distance to surface
bool dist_bottom_valid # true if distance to bottom surface is valid
float32 dist_bottom # Distance from from bottom surface to ground, (metres)
float32 dist_bottom_var # terrain estimate variance (m^2)
bool dist_bottom_valid # true if distance to bottom surface is valid

float32 delta_dist_bottom # Amount of vertical shift of dist bottom estimate in latest reset [m]
uint8 dist_bottom_reset_counter # Index of latest dist bottom estimate reset

uint8 dist_bottom_sensor_bitfield # bitfield indicating what type of sensor is used to estimate dist_bottom
uint8 DIST_BOTTOM_SENSOR_NONE = 0
uint8 DIST_BOTTOM_SENSOR_RANGE = 1 # (1 << 0) a range sensor is used to estimate dist_bottom field
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,29 @@ void Ekf::resetFlowFusion()
void Ekf::resetTerrainToFlow()
{
ECL_INFO("reset hagl to flow");

// TODO: use the flow data
_state.terrain = fmaxf(0.0f, _state.pos(2));
const float new_terrain = fmaxf(0.0f, _state.pos(2));
const float delta_terrain = new_terrain - _state.terrain;
_state.terrain = new_terrain;
P.uncorrelateCovarianceSetVariance<State::terrain.dof>(State::terrain.idx, 100.f);
_terrain_vpos_reset_counter++;

resetAidSourceStatusZeroInnovation(_aid_src_optical_flow);

_innov_check_fail_status.flags.reject_optflow_X = false;
_innov_check_fail_status.flags.reject_optflow_Y = false;


// record the state change
if (_state_reset_status.reset_count.hagl == _state_reset_count_prev.hagl) {
_state_reset_status.hagl_change = delta_terrain;

} else {
// there's already a reset this update, accumulate total delta
_state_reset_status.hagl_change += delta_terrain;
}

_state_reset_status.reset_count.hagl++;
}

void Ekf::stopFlowFusion()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,23 @@ float Ekf::getRngVar() const

void Ekf::resetTerrainToRng(estimator_aid_source1d_s &aid_src)
{
_state.terrain = _state.pos(2) + aid_src.observation;
const float new_terrain = _state.pos(2) + aid_src.observation;
const float delta_terrain = new_terrain - _state.terrain;

_state.terrain = new_terrain;
P.uncorrelateCovarianceSetVariance<State::terrain.dof>(State::terrain.idx, aid_src.observation_variance);
_terrain_vpos_reset_counter++;

// record the state change
if (_state_reset_status.reset_count.hagl == _state_reset_count_prev.hagl) {
_state_reset_status.hagl_change = delta_terrain;

} else {
// there's already a reset this update, accumulate total delta
_state_reset_status.hagl_change += delta_terrain;
}

_state_reset_status.reset_count.hagl++;


aid_src.time_last_fuse = _time_delayed_us;
}
Expand Down
14 changes: 9 additions & 5 deletions src/modules/ekf2/EKF/ekf.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,6 @@ class Ekf final : public EstimatorInterface
float getTerrainVertPos() const { return _state.terrain; };
float getHagl() const { return _state.terrain - _state.pos(2); }

// get the number of times the vertical terrain position has been reset
uint8_t getTerrainVertPosResetCounter() const { return _terrain_vpos_reset_counter; };

// get the terrain variance
float getTerrainVariance() const { return P(State::terrain.idx, State::terrain.idx); }

Expand Down Expand Up @@ -358,6 +355,13 @@ class Ekf final : public EstimatorInterface
*counter = _state_reset_status.reset_count.posD;
}

uint8_t get_hagl_reset_count() const { return _state_reset_status.reset_count.hagl; }
void get_hagl_reset(float *delta, uint8_t *counter) const
{
*delta = _state_reset_status.hagl_change;
*counter = _state_reset_status.reset_count.hagl;
}

// return the amount the local vertical velocity changed in the last reset and the number of reset events
uint8_t get_velD_reset_count() const { return _state_reset_status.reset_count.velD; }
void get_velD_reset(float *delta, uint8_t *counter) const
Expand Down Expand Up @@ -551,6 +555,7 @@ class Ekf final : public EstimatorInterface
uint8_t posNE{0}; ///< number of horizontal position reset events (allow to wrap if count exceeds 255)
uint8_t posD{0}; ///< number of vertical position reset events (allow to wrap if count exceeds 255)
uint8_t quat{0}; ///< number of quaternion reset events (allow to wrap if count exceeds 255)
uint8_t hagl{0}; ///< number of height above ground level reset events (allow to wrap if count exceeds 255)
};

struct StateResets {
Expand All @@ -559,6 +564,7 @@ class Ekf final : public EstimatorInterface
Vector2f posNE_change; ///< North, East position change due to last reset (m)
float posD_change; ///< Down position change due to last reset (m)
Quatf quat_change; ///< quaternion delta due to last reset - multiply pre-reset quaternion by this to get post-reset quaternion
float hagl_change; ///< Height above ground level change due to last reset (m)

StateResetCounts reset_count{};
};
Expand Down Expand Up @@ -599,8 +605,6 @@ class Ekf final : public EstimatorInterface

#if defined(CONFIG_EKF2_TERRAIN)
// Terrain height state estimation
uint8_t _terrain_vpos_reset_counter{0}; ///< number of times _terrain_vpos has been reset

float _last_on_ground_posD{0.0f}; ///< last vertical position when the in_air status was false (m)
#endif // CONFIG_EKF2_TERRAIN

Expand Down
13 changes: 12 additions & 1 deletion src/modules/ekf2/EKF/position_fusion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,18 @@ void Ekf::resetVerticalPositionTo(const float new_vert_pos, float new_vert_pos_v

#if defined(CONFIG_EKF2_TERRAIN)
_state.terrain += delta_z;
#endif

// record the state change
if (_state_reset_status.reset_count.hagl == _state_reset_count_prev.hagl) {
_state_reset_status.hagl_change = delta_z;

} else {
// there's already a reset this update, accumulate total delta
_state_reset_status.hagl_change += delta_z;
}

_state_reset_status.reset_count.hagl++;
#endif // CONFIG_EKF2_TERRAIN

// Reset the timout timer
_time_last_hgt_fuse = _time_delayed_us;
Expand Down
6 changes: 5 additions & 1 deletion src/modules/ekf2/EKF2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,9 @@ void EKF2::PublishGlobalPosition(const hrt_abstime &timestamp)
global_pos.terrain_alt_valid = true;
}

float delta_hagl = 0.f;
_ekf.get_hagl_reset(&delta_hagl, &global_pos.terrain_reset_counter);
global_pos.delta_terrain = -delta_z;
#endif // CONFIG_EKF2_TERRAIN

global_pos.dead_reckoning = _ekf.control_status_flags().inertial_dead_reckoning
Expand Down Expand Up @@ -1619,9 +1622,10 @@ void EKF2::PublishLocalPosition(const hrt_abstime &timestamp)

#if defined(CONFIG_EKF2_TERRAIN)
// Distance to bottom surface (ground) in meters, must be positive
lpos.dist_bottom_valid = _ekf.isTerrainEstimateValid();
lpos.dist_bottom = math::max(_ekf.getHagl(), 0.f);
lpos.dist_bottom_var = _ekf.getTerrainVariance();
lpos.dist_bottom_valid = _ekf.isTerrainEstimateValid();
_ekf.get_hagl_reset(&lpos.delta_dist_bottom, &lpos.dist_bottom_reset_counter);

lpos.dist_bottom_sensor_bitfield = vehicle_local_position_s::DIST_BOTTOM_SENSOR_NONE;

Expand Down
25 changes: 25 additions & 0 deletions src/modules/ekf2/EKF2Selector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,18 +479,32 @@ void EKF2Selector::PublishVehicleLocalPosition()
_delta_heading_reset = matrix::wrap_pi(local_position.heading - _local_position_last.heading);
}

// HAGL (dist_bottom) reset
if (!instance_change
&& (local_position.dist_bottom_reset_counter == _local_position_last.dist_bottom_reset_counter + 1)) {
++_hagl_reset_counter;
_delta_hagl_reset = local_position.delta_dist_bottom;

} else if (instance_change
|| (local_position.dist_bottom_reset_counter != _local_position_last.dist_bottom_reset_counter)) {
++_hagl_reset_counter;
_delta_hagl_reset = local_position.dist_bottom - _local_position_last.dist_bottom;
}

} else {
_xy_reset_counter = local_position.xy_reset_counter;
_z_reset_counter = local_position.z_reset_counter;
_vxy_reset_counter = local_position.vxy_reset_counter;
_vz_reset_counter = local_position.vz_reset_counter;
_heading_reset_counter = local_position.heading_reset_counter;
_hagl_reset_counter = local_position.dist_bottom_reset_counter;

_delta_xy_reset = Vector2f{local_position.delta_xy};
_delta_z_reset = local_position.delta_z;
_delta_vxy_reset = Vector2f{local_position.delta_vxy};
_delta_vz_reset = local_position.delta_vz;
_delta_heading_reset = local_position.delta_heading;
_delta_hagl_reset = local_position.delta_dist_bottom;
}

bool publish = true;
Expand All @@ -513,6 +527,7 @@ void EKF2Selector::PublishVehicleLocalPosition()
local_position.vxy_reset_counter = _vxy_reset_counter;
local_position.vz_reset_counter = _vz_reset_counter;
local_position.heading_reset_counter = _heading_reset_counter;
local_position.dist_bottom_reset_counter = _hagl_reset_counter;

_delta_xy_reset.copyTo(local_position.delta_xy);
local_position.delta_z = _delta_z_reset;
Expand Down Expand Up @@ -612,6 +627,16 @@ void EKF2Selector::PublishVehicleGlobalPosition()
_delta_alt_reset = global_position.delta_alt - _global_position_last.delta_alt;
}

// terrain reset
if (!instance_change && (global_position.terrain_reset_counter == _global_position_last.terrain_reset_counter + 1)) {
++_terrain_reset_counter;
_delta_terrain_reset = global_position.delta_terrain;

} else if (instance_change || (global_position.terrain_reset_counter != _global_position_last.terrain_reset_counter)) {
++_terrain_reset_counter;
_delta_terrain_reset = global_position.delta_terrain - _global_position_last.delta_terrain;
}

} else {
_lat_lon_reset_counter = global_position.lat_lon_reset_counter;
_alt_reset_counter = global_position.alt_reset_counter;
Expand Down
6 changes: 6 additions & 0 deletions src/modules/ekf2/EKF2Selector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,14 @@ class EKF2Selector : public ModuleParams, public px4::ScheduledWorkItem
matrix::Vector2f _delta_vxy_reset{};
float _delta_vz_reset{0.f};
float _delta_heading_reset{0};
float _delta_hagl_reset{0.f};

uint8_t _xy_reset_counter{0};
uint8_t _z_reset_counter{0};
uint8_t _vxy_reset_counter{0};
uint8_t _vz_reset_counter{0};
uint8_t _heading_reset_counter{0};
uint8_t _hagl_reset_counter{0};

// vehicle_odometry
vehicle_odometry_s _odometry_last{};
Expand All @@ -217,8 +220,11 @@ class EKF2Selector : public ModuleParams, public px4::ScheduledWorkItem
double _delta_lat_reset{0};
double _delta_lon_reset{0};
float _delta_alt_reset{0.f};
float _delta_terrain_reset{0.f};

uint8_t _lat_lon_reset_counter{0};
uint8_t _alt_reset_counter{0};
uint8_t _terrain_reset_counter{0};

// wind estimate
wind_s _wind_last{};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ void FlightTask::_checkEkfResetCounters()
_reset_counters.z = _sub_vehicle_local_position.get().z_reset_counter;
}

if (_sub_vehicle_local_position.get().dist_bottom_reset_counter != _reset_counters.hagl) {
_ekfResetHandlerHagl(_sub_vehicle_local_position.get().delta_dist_bottom);
_reset_counters.hagl = _sub_vehicle_local_position.get().dist_bottom_reset_counter;
}

if (_sub_vehicle_local_position.get().vz_reset_counter != _reset_counters.vz) {
_ekfResetHandlerVelocityZ(_sub_vehicle_local_position.get().delta_vz);
_reset_counters.vz = _sub_vehicle_local_position.get().vz_reset_counter;
Expand Down Expand Up @@ -138,7 +143,7 @@ void FlightTask::_evaluateVehicleLocalPosition()
// distance to bottom
if (_sub_vehicle_local_position.get().dist_bottom_valid
&& PX4_ISFINITE(_sub_vehicle_local_position.get().dist_bottom)) {
_dist_to_bottom = _sub_vehicle_local_position.get().dist_bottom;
_dist_to_bottom = _sub_vehicle_local_position.get().dist_bottom;
}

// global frame reference coordinates to enable conversions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ struct ekf_reset_counters_s {
uint8_t z;
uint8_t vz;
uint8_t heading;
uint8_t hagl;
};

class FlightTask : public ModuleParams
Expand Down Expand Up @@ -191,6 +192,7 @@ class FlightTask : public ModuleParams
virtual void _ekfResetHandlerPositionXY(const matrix::Vector2f &delta_xy) {};
virtual void _ekfResetHandlerVelocityXY(const matrix::Vector2f &delta_vxy) {};
virtual void _ekfResetHandlerPositionZ(float delta_z) {};
virtual void _ekfResetHandlerHagl(float delta_hagl) {};
virtual void _ekfResetHandlerVelocityZ(float delta_vz) {};
virtual void _ekfResetHandlerHeading(float delta_psi) {};

Expand Down
Loading