@@ -40,12 +40,18 @@ using namespace time_literals;
4040// eph is firmware-dependent and not a rigorous 1-sigma, so 3 is a heuristic consistency gate
4141// rather than a precise statistical claim. It relaxes the gate automatically when receivers degrade.
4242static constexpr float GPS_DIVERGENCE_SIGMA = 3 .0f ;
43- static constexpr uint64_t GPS_DIVERGENCE_SUSTAIN = 2_s; // must be sustained before warning
43+
44+ // Matches the 1 s staleness threshold used by other sensor checks in this framework.
45+ static constexpr uint64_t GNSS_ONLINE_TIMEOUT = 1_s;
46+
47+ // Multipath spikes typically resolve within 1 s; 2 s filters these out while still
48+ // detecting real receiver faults promptly.
49+ static constexpr uint64_t GNSS_DIVERGENCE_SUSTAIN = 2_s;
4450
4551void GpsRedundancyChecks::checkAndReport (const Context &context, Report &reporter)
4652{
4753 // Always reset — will be set below only when the condition is active
48- reporter.failsafeFlags ().gps_redundancy_lost = false ;
54+ reporter.failsafeFlags ().gnss_lost = false ;
4955
5056 // Separate "online" (present + fresh data) from "fixed" (online + 3D fix).
5157 // online_count tracks receivers that are communicating; fixed_count tracks those
@@ -60,7 +66,7 @@ void GpsRedundancyChecks::checkAndReport(const Context &context, Report &reporte
6066
6167 if (_sensor_gps_sub[i].copy (&gps)
6268 && (gps.device_id != 0 )
63- && (hrt_elapsed_time (&gps.timestamp ) < 2_s )) {
69+ && (hrt_elapsed_time (&gps.timestamp ) < GNSS_ONLINE_TIMEOUT )) {
6470 online_count++;
6571
6672 if (gps.fix_type >= 3 ) {
@@ -92,7 +98,7 @@ void GpsRedundancyChecks::checkAndReport(const Context &context, Report &reporte
9298
9399 // Pre-arm: trigger immediately so the operator can decide before takeoff.
94100 // In-flight: require sustained divergence to avoid false alarms from transient multipath.
95- const uint64_t sustain = context.isArmed () ? GPS_DIVERGENCE_SUSTAIN : 0_s;
101+ const uint64_t sustain = context.isArmed () ? GNSS_DIVERGENCE_SUSTAIN : 0_s;
96102
97103 if (divergence_m > gate_m) {
98104 if (_divergence_since == 0 ) {
@@ -124,58 +130,52 @@ void GpsRedundancyChecks::checkAndReport(const Context &context, Report &reporte
124130 }
125131 }
126132
127- // Track the highest fixed count seen — used to detect any GPS loss regardless of SYS_HAS_NUM_GPS
133+ // Track the highest fixed count seen — used to detect any GPS loss regardless of SYS_HAS_NUM_GNSS
128134 if (fixed_count > _peak_fixed_count) {
129135 _peak_fixed_count = fixed_count;
130136 }
131137
132- const int required = _param_sys_has_num_gps .get ();
138+ const int required = _param_sys_has_num_gnss .get ();
133139 const bool below_required = (required > 0 && fixed_count < required);
134140 const bool dropped_below_peak = (_peak_fixed_count > 1 && fixed_count < _peak_fixed_count);
135141
136- if (!below_required && !dropped_below_peak && !divergence_active) {
137- return ;
138- }
139-
140- reporter.failsafeFlags ().gps_redundancy_lost = below_required || divergence_active;
142+ reporter.failsafeFlags ().gnss_lost = below_required || divergence_active;
143+
144+ if (below_required || dropped_below_peak) {
145+ // act==0: warn only, never blocks arming; act>0: blocks arming and shows red
146+ const bool block_arming = below_required && (_param_com_gps_loss_act.get () > 0 );
147+ const NavModes nav_modes = block_arming ? NavModes::All : NavModes::None;
148+ const events::Log log_level = block_arming ? events::Log::Error : events::Log::Warning;
149+ const uint8_t expected = below_required ? (uint8_t )required : (uint8_t )_peak_fixed_count;
150+
151+ // Differentiate: if online_count is also low the receiver is offline; otherwise it lost fix.
152+ if (online_count < fixed_count || online_count < required) {
153+ /* EVENT
154+ * @description
155+ * <profile name="dev">
156+ * Configure the minimum required GPS count with <param>SYS_HAS_NUM_GNSS</param>.
157+ * Configure the failsafe action with <param>COM_GPS_LOSS_ACT</param>.
158+ * </profile>
159+ */
160+ reporter.healthFailure <uint8_t , uint8_t >(nav_modes, health_component_t ::gps,
161+ events::ID (" check_gps_redundancy_offline" ),
162+ log_level,
163+ " GPS receiver offline: {1} of {2} online" ,
164+ (uint8_t )online_count, expected);
141165
142- if (!below_required && !dropped_below_peak) {
143- return ;
144- }
145-
146- // act==0: warn only, never blocks arming; act>0: blocks arming and shows red
147- const bool block_arming = below_required && (_param_com_gps_loss_act.get () > 0 );
148- const NavModes nav_modes = block_arming ? NavModes::All : NavModes::None;
149- const events::Log log_level = block_arming ? events::Log::Error : events::Log::Warning;
150- const uint8_t expected = below_required ? (uint8_t )required : (uint8_t )_peak_fixed_count;
151-
152- // Differentiate: if online_count is also low the receiver is offline; otherwise it lost fix.
153- if (online_count < fixed_count || online_count < required) {
154- /* EVENT
155- * @description
156- * <profile name="dev">
157- * Configure the minimum required GPS count with <param>SYS_HAS_NUM_GPS</param>.
158- * Configure the failsafe action with <param>COM_GPS_LOSS_ACT</param>.
159- * </profile>
160- */
161- reporter.healthFailure <uint8_t , uint8_t >(nav_modes, health_component_t ::gps,
162- events::ID (" check_gps_redundancy_offline" ),
163- log_level,
164- " GPS receiver offline: {1} of {2} online" ,
165- (uint8_t )online_count, expected);
166-
167- } else {
168- /* EVENT
169- * @description
170- * <profile name="dev">
171- * Configure the minimum required GPS count with <param>SYS_HAS_NUM_GPS</param>.
172- * Configure the failsafe action with <param>COM_GPS_LOSS_ACT</param>.
173- * </profile>
174- */
175- reporter.healthFailure <uint8_t , uint8_t >(nav_modes, health_component_t ::gps,
176- events::ID (" check_gps_redundancy_no_fix" ),
177- log_level,
178- " GPS receiver lost 3D fix: {1} of {2} fixed" ,
179- (uint8_t )fixed_count, expected);
166+ } else {
167+ /* EVENT
168+ * @description
169+ * <profile name="dev">
170+ * Configure the minimum required GPS count with <param>SYS_HAS_NUM_GNSS</param>.
171+ * Configure the failsafe action with <param>COM_GPS_LOSS_ACT</param>.
172+ * </profile>
173+ */
174+ reporter.healthFailure <uint8_t , uint8_t >(nav_modes, health_component_t ::gps,
175+ events::ID (" check_gps_redundancy_no_fix" ),
176+ log_level,
177+ " GPS receiver lost 3D fix: {1} of {2} fixed" ,
178+ (uint8_t )fixed_count, expected);
179+ }
180180 }
181181}
0 commit comments