From a80b973fa97b15e7c15a17fb90b7cbe0fdcb7d31 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sun, 13 Sep 2026 14:14:35 +0200 Subject: [PATCH] Forget stalled data in GLONASS GNAV --- .../glonass_gnav_navigation_message.cc | 49 +++++++++++++++++-- .../glonass_gnav_navigation_message.h | 8 +++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/core/system_parameters/glonass_gnav_navigation_message.cc b/src/core/system_parameters/glonass_gnav_navigation_message.cc index a60a748e4..2172de28e 100644 --- a/src/core/system_parameters/glonass_gnav_navigation_message.cc +++ b/src/core/system_parameters/glonass_gnav_navigation_message.cc @@ -517,8 +517,14 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame // Make sure a valid frame_ID or satellite slot number is returned if (d_frame_ID == 0 || i_alm_satellite_slot_number == 0 || i_alm_satellite_slot_number > GLONASS_CA_NBR_SATS) { + // Discard a half-received pair so the paired odd string cannot + // complete a stale or foreign slot with this string's data + flag_almanac_str_6 = false; return 0; } + // Remember the validated slot so the paired odd string writes to the + // same satellite even if i_alm_satellite_slot_number changes meanwhile + d_alm_slot_str_6 = i_alm_satellite_slot_number; gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = read_navigation_bool(string_bits, C_N); gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); @@ -534,8 +540,10 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame case 7: // --- It is string 7 ---------------------------------------------- - if (flag_almanac_str_6 == true && i_alm_satellite_slot_number > 0 && i_alm_satellite_slot_number <= GLONASS_CA_NBR_SATS) + if (flag_almanac_str_6 == true && d_alm_slot_str_6 > 0 && d_alm_slot_str_6 <= GLONASS_CA_NBR_SATS) { + // Complete the pair opened by string 6, using the slot it validated + i_alm_satellite_slot_number = d_alm_slot_str_6; gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GNSS_PI; gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; @@ -562,8 +570,14 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame // Make sure a valid frame_ID or satellite slot number is returned if (d_frame_ID == 0 || i_alm_satellite_slot_number == 0 || i_alm_satellite_slot_number > GLONASS_CA_NBR_SATS) { + // Discard a half-received pair so the paired odd string cannot + // complete a stale or foreign slot with this string's data + flag_almanac_str_8 = false; return 0; } + // Remember the validated slot so the paired odd string writes to the + // same satellite even if i_alm_satellite_slot_number changes meanwhile + d_alm_slot_str_8 = i_alm_satellite_slot_number; gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = read_navigation_bool(string_bits, C_N); gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); @@ -579,8 +593,10 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame case 9: // --- It is string 9 ---------------------------------------------- - if (flag_almanac_str_8 == true && i_alm_satellite_slot_number > 0 && i_alm_satellite_slot_number <= GLONASS_CA_NBR_SATS) + if (flag_almanac_str_8 == true && d_alm_slot_str_8 > 0 && d_alm_slot_str_8 <= GLONASS_CA_NBR_SATS) { + // Complete the pair opened by string 8, using the slot it validated + i_alm_satellite_slot_number = d_alm_slot_str_8; gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GNSS_PI; gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; @@ -602,8 +618,14 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame // Make sure a valid frame_ID or satellite slot number is returned if (d_frame_ID == 0 || i_alm_satellite_slot_number == 0 || i_alm_satellite_slot_number > GLONASS_CA_NBR_SATS) { + // Discard a half-received pair so the paired odd string cannot + // complete a stale or foreign slot with this string's data + flag_almanac_str_10 = false; return 0; } + // Remember the validated slot so the paired odd string writes to the + // same satellite even if i_alm_satellite_slot_number changes meanwhile + d_alm_slot_str_10 = i_alm_satellite_slot_number; gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = read_navigation_bool(string_bits, C_N); gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); @@ -619,8 +641,10 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame case 11: // --- It is string 11 --------------------------------------------- - if (flag_almanac_str_10 == true && i_alm_satellite_slot_number > 0 && i_alm_satellite_slot_number <= GLONASS_CA_NBR_SATS) + if (flag_almanac_str_10 == true && d_alm_slot_str_10 > 0 && d_alm_slot_str_10 <= GLONASS_CA_NBR_SATS) { + // Complete the pair opened by string 10, using the slot it validated + i_alm_satellite_slot_number = d_alm_slot_str_10; gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GNSS_PI; gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; @@ -642,8 +666,14 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame // Make sure a valid frame_ID or satellite slot number is returned if (d_frame_ID == 0 || i_alm_satellite_slot_number == 0 || i_alm_satellite_slot_number > GLONASS_CA_NBR_SATS) { + // Discard a half-received pair so the paired odd string cannot + // complete a stale or foreign slot with this string's data + flag_almanac_str_12 = false; return 0; } + // Remember the validated slot so the paired odd string writes to the + // same satellite even if i_alm_satellite_slot_number changes meanwhile + d_alm_slot_str_12 = i_alm_satellite_slot_number; gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = read_navigation_bool(string_bits, C_N); gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, N_A)); @@ -658,8 +688,10 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame case 13: // --- It is string 13 --------------------------------------------- - if (flag_almanac_str_12 == true && i_alm_satellite_slot_number > 0 && i_alm_satellite_slot_number <= GLONASS_CA_NBR_SATS) + if (flag_almanac_str_12 == true && d_alm_slot_str_12 > 0 && d_alm_slot_str_12 <= GLONASS_CA_NBR_SATS) { + // Complete the pair opened by string 12, using the slot it validated + i_alm_satellite_slot_number = d_alm_slot_str_12; gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GNSS_PI; gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; @@ -695,8 +727,13 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame // assigned to the frame being received if (get_frame_number(i_alm_satellite_slot_number) != d_frame_ID || i_alm_satellite_slot_number == 0 || i_alm_satellite_slot_number > GLONASS_CA_NBR_SATS) { + // Discard a half-received pair so string 15 cannot complete + // a stale or foreign slot with this string's data + flag_almanac_str_14 = false; return 0; } + // Remember the validated slot for the paired string 15 + d_alm_slot_str_14 = i_alm_satellite_slot_number; gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = read_navigation_bool(string_bits, C_N); gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, N_A)); @@ -711,8 +748,10 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame case 15: // --- It is string 15 ---------------------------------------------- - if (d_frame_ID >= 1 && d_frame_ID <= 4 && flag_almanac_str_14 == true && i_alm_satellite_slot_number > 0 && i_alm_satellite_slot_number <= GLONASS_CA_NBR_SATS) + if (d_frame_ID >= 1 && d_frame_ID <= 4 && flag_almanac_str_14 == true && d_alm_slot_str_14 > 0 && d_alm_slot_str_14 <= GLONASS_CA_NBR_SATS) { + // Complete the pair opened by string 14, using the slot it validated + i_alm_satellite_slot_number = d_alm_slot_str_14; gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GNSS_PI; gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; diff --git a/src/core/system_parameters/glonass_gnav_navigation_message.h b/src/core/system_parameters/glonass_gnav_navigation_message.h index 1d9041ab2..98c20728f 100644 --- a/src/core/system_parameters/glonass_gnav_navigation_message.h +++ b/src/core/system_parameters/glonass_gnav_navigation_message.h @@ -195,6 +195,14 @@ private: uint32_t d_frame_ID{}; uint32_t d_string_ID{}; uint32_t i_alm_satellite_slot_number{}; // SV Orbit Slot Number + // Satellite slot number validated by an even almanac string (6/8/10/12/14) + // and consumed by its paired odd string (7/9/11/13/15). Kept per pair so a + // stale flag can never complete an almanac with a slot from another pair. + uint32_t d_alm_slot_str_6{}; + uint32_t d_alm_slot_str_8{}; + uint32_t d_alm_slot_str_10{}; + uint32_t d_alm_slot_str_12{}; + uint32_t d_alm_slot_str_14{}; int32_t d_kp_announced_leap_s{}; // UTC correction announced by KP (+1 or -1 s), 0 if not armed