refactor(gpsRedundancyCheck): address code review feedback

This commit is contained in:
gguidone
2026-04-10 14:56:57 +02:00
committed by Matthias Grob
parent f8915d055b
commit 46dd806211
4 changed files with 64 additions and 7 deletions
+5 -2
View File
@@ -138,11 +138,14 @@ parameters:
reboot_required: true
SYS_HAS_NUM_GNSS:
description:
short: Control if and how many GNSS receivers are expected
short: Control if and how many GNSS receivers are required
long: |-
0: Disable GNSS redundancy check (any number of GNSS receivers is acceptable).
0: No minimum receiver count required. Position divergence between two receivers
and loss of a GNSS receiver still produce a warning but never trigger the
COM_GPS_LOSS_ACT failsafe action.
1-N: Require the presence of N GNSS receivers for arming and during flight.
If the active count drops below this value in flight, COM_GPS_LOSS_ACT is triggered.
When set to 2, position divergence between the two receivers also triggers COM_GPS_LOSS_ACT.
type: int32
default: 0
min: 0
@@ -136,6 +136,20 @@ public:
& (uint64_t)events::px4::enums::health_component_t::gps) != 0;
}
// Runs one check cycle and returns true if gnss_lost was set (failsafe would trigger)
bool hasGnssLost(bool armed)
{
vehicle_status_s status{};
status.arming_state = armed
? vehicle_status_s::ARMING_STATE_ARMED
: vehicle_status_s::ARMING_STATE_DISARMED;
Context context{status};
failsafe_flags_s failsafe_flags{};
Report reporter{failsafe_flags, 0_s};
_check->checkAndReport(context, reporter);
return failsafe_flags.gnss_lost;
}
static orb_advert_t _pub0;
static orb_advert_t _pub1;
GpsRedundancyChecks *_check{nullptr};
@@ -198,6 +212,41 @@ TEST_F(GpsRedundancyCheckTest, FixTypeBelow3TreatedAsInactive)
EXPECT_FALSE(hasDivergenceWarning(false));
}
// Divergence with SYS_HAS_NUM_GNSS=2 and COM_GPS_LOSS_ACT>0 → gnss_lost set (failsafe fires)
TEST_F(GpsRedundancyCheckTest, DivergenceWithRedundancyRequiredSetsGnssLost)
{
int i = 2;
param_set(param_find("SYS_HAS_NUM_GNSS"), &i);
i = 1; // Return
param_set(param_find("COM_GPS_LOSS_ACT"), &i);
delete _check;
_check = new GpsRedundancyChecks();
sensor_gps_s gps0 = makeGps(BASE_LAT, BASE_LON);
sensor_gps_s gps1 = makeGps(DIVERGING_LAT, BASE_LON);
orb_publish(ORB_ID(sensor_gps), _pub0, &gps0);
orb_publish(ORB_ID(sensor_gps), _pub1, &gps1);
EXPECT_TRUE(hasGnssLost(false));
}
// Divergence with SYS_HAS_NUM_GNSS=0 and COM_GPS_LOSS_ACT>0 → warning only, gnss_lost not set
TEST_F(GpsRedundancyCheckTest, DivergenceWithoutRedundancyRequiredWarnsOnly)
{
int i = 0;
param_set(param_find("SYS_HAS_NUM_GNSS"), &i);
i = 1; // Return
param_set(param_find("COM_GPS_LOSS_ACT"), &i);
delete _check;
_check = new GpsRedundancyChecks();
sensor_gps_s gps0 = makeGps(BASE_LAT, BASE_LON);
sensor_gps_s gps1 = makeGps(DIVERGING_LAT, BASE_LON);
orb_publish(ORB_ID(sensor_gps), _pub0, &gps0);
orb_publish(ORB_ID(sensor_gps), _pub1, &gps1);
EXPECT_FALSE(hasGnssLost(false));
EXPECT_TRUE(hasDivergenceWarning(false));
}
// Divergence then recovery: timer resets and warning stops
TEST_F(GpsRedundancyCheckTest, DivergenceClearsAfterRecovery)
{
@@ -75,12 +75,16 @@ void GpsRedundancyChecks::checkAndReport(const Context &context, Report &reporte
}
}
const int required = _param_sys_has_num_gnss.get();
// Position divergence check: warn if two fixed receivers disagree beyond their combined
// uncertainty. The gate is: lever-arm separation + GNSS_DIVERGENCE_SIGMA * RMS(eph0, eph1).
// Using RMS(eph) means the gate tightens when both receivers are accurate and widens
// automatically when one degrades, avoiding false alarms without a hard-coded threshold.
// Pre-arm: warn immediately. In-flight: require GPS_DIVERGENCE_SUSTAIN to suppress
// transient multipath spikes.
// The failsafe action is only triggered when SYS_HAS_NUM_GNSS >= 2; otherwise divergence
// is reported as a warning only.
bool divergence_active = false;
if (fixed_count >= 2) {
@@ -106,8 +110,8 @@ void GpsRedundancyChecks::checkAndReport(const Context &context, Report &reporte
}
if (hrt_elapsed_time(&_divergence_since) >= sustain) {
divergence_active = true;
const bool act = (_param_com_gnss_loss_act.get() > 0);
const bool act = (_param_com_gnss_loss_act.get() > 0) && (required >= 2);
divergence_active = act;
/* EVENT
* @description
@@ -115,6 +119,7 @@ void GpsRedundancyChecks::checkAndReport(const Context &context, Report &reporte
*
* <profile name="dev">
* Configure the failsafe action with <param>COM_GPS_LOSS_ACT</param>.
* The failsafe action is only triggered when <param>SYS_HAS_NUM_GNSS</param> is set to 2.
* </profile>
*/
reporter.healthFailure<float, float>(act ? NavModes::All : NavModes::None,
@@ -135,7 +140,6 @@ void GpsRedundancyChecks::checkAndReport(const Context &context, Report &reporte
_peak_fixed_count = fixed_count;
}
const int required = _param_sys_has_num_gnss.get();
const bool below_required = (required > 0 && fixed_count < required);
const bool dropped_below_peak = (_peak_fixed_count > 1 && fixed_count < _peak_fixed_count);
+3 -2
View File
@@ -136,8 +136,9 @@ parameters:
short: GNSS loss failsafe mode
long: |-
Action the system takes when a GNSS failure is detected during flight.
Triggers when the active GNSS count drops below SYS_HAS_NUM_GNSS or when
two receivers report positions inconsistent with their reported accuracy.
Triggers when the active GNSS count drops below SYS_HAS_NUM_GNSS (disabled
when SYS_HAS_NUM_GNSS=0), or when two receivers report positions inconsistent
with their reported accuracy and SYS_HAS_NUM_GNSS=2 (otherwise warning only).
Any value above Warning also blocks arming.
type: enum
values: