From 05cf7e7aed5d0ef5fb5a92965f2760b06786a758 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 16 Jul 2026 11:14:12 +0200 Subject: [PATCH 1/5] Fix double PVT solve and dump when Rx clock correction is disabled --- .../PVT/gnuradio_blocks/rtklib_pvt_gs.cc | 21 +++++++++++++++---- src/algorithms/PVT/libs/rtklib_solver.cc | 4 ++-- src/algorithms/PVT/libs/rtklib_solver.h | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc index 93ed39c4f..4d623ede1 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc @@ -2198,8 +2198,17 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item // LOG(INFO) << "diff raw obs time: " << d_gnss_observables_map.cbegin()->second.RX_time * 1000.0 - old_time_debug; // old_time_debug = d_gnss_observables_map.cbegin()->second.RX_time * 1000.0; uint32_t current_RX_time_ms = 0; + // If the Rx clock correction is disabled, d_internal_pvt_solver and d_user_pvt_solver + // are the same object and this is its only get_PVT call, executed at the observables + // rate; restrict dumping to epochs aligned with the configured output rate + bool dump_this_epoch = false; + if (d_enable_rx_clock_correction == false) + { + const auto rx_time_ms = static_cast(d_gnss_observables_map.cbegin()->second.RX_time * 1000.0); + dump_this_epoch = (rx_time_ms % d_output_rate_ms == 0); + } // #### solve PVT and store the corrected observable set - if (d_internal_pvt_solver->get_PVT(d_gnss_observables_map, d_observable_interval_ms / 1000.0, *d_sensor_data_aggregator)) + if (d_internal_pvt_solver->get_PVT(d_gnss_observables_map, d_observable_interval_ms / 1000.0, *d_sensor_data_aggregator, dump_this_epoch)) { d_pvt_errors_counter = 0; // Reset consecutive PVT error counter const double Rx_clock_offset_s = d_internal_pvt_solver->get_time_offset_s(); @@ -2310,10 +2319,14 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item } } - // compute on the fly PVT solution - if (flag_compute_pvt_output == true) + // compute on the fly PVT solution at the output rate, on the clock-corrected + // and interpolated observables. If the Rx clock correction is disabled, the user + // solver is the same object as the internal one and already holds this epoch's + // solution (flag_pvt_valid was set above), so solving again would feed the same + // epoch twice to the solver and duplicate the dump record + if (flag_compute_pvt_output == true && d_enable_rx_clock_correction == true) { - flag_pvt_valid = d_user_pvt_solver->get_PVT(d_gnss_observables_map, d_output_rate_ms / 1000.0, *d_sensor_data_aggregator); + flag_pvt_valid = d_user_pvt_solver->get_PVT(d_gnss_observables_map, d_output_rate_ms / 1000.0, *d_sensor_data_aggregator, true); } if (flag_pvt_valid == true) diff --git a/src/algorithms/PVT/libs/rtklib_solver.cc b/src/algorithms/PVT/libs/rtklib_solver.cc index db9f055ad..8a43404e0 100644 --- a/src/algorithms/PVT/libs/rtklib_solver.cc +++ b/src/algorithms/PVT/libs/rtklib_solver.cc @@ -1147,7 +1147,7 @@ void Rtklib_Solver::clear_applied_has_phase_bias_discontinuity(const HAS_obs_cor } -bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_map, double kf_update_interval_s, const SensorDataAggregator &sensor_data_aggregator) +bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_map, double kf_update_interval_s, const SensorDataAggregator &sensor_data_aggregator, bool dump_this_epoch) { std::map::const_iterator gnss_observables_iter; std::map::const_iterator galileo_ephemeris_iter; @@ -1939,7 +1939,7 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ d_monitor_pvt.utc_time = stream.str(); // ######## LOG FILE ######### - if (d_flag_dump_enabled == true) + if (d_flag_dump_enabled == true && dump_this_epoch == true) { // MULTIPLEXED FILE RECORDING - Record results to file try diff --git a/src/algorithms/PVT/libs/rtklib_solver.h b/src/algorithms/PVT/libs/rtklib_solver.h index bc7561543..439745459 100644 --- a/src/algorithms/PVT/libs/rtklib_solver.h +++ b/src/algorithms/PVT/libs/rtklib_solver.h @@ -91,7 +91,7 @@ public: ~Rtklib_Solver() noexcept override; - bool get_PVT(const std::map& gnss_observables_map, double kf_update_interval_s, const SensorDataAggregator& sensor_data_aggregator); + bool get_PVT(const std::map& gnss_observables_map, double kf_update_interval_s, const SensorDataAggregator& sensor_data_aggregator, bool dump_this_epoch = true); double get_hdop() const override; double get_vdop() const override; From f25af397ed048dcffd34e8a644693fb8d423150a Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 16 Jul 2026 12:31:00 +0200 Subject: [PATCH 2/5] Revive broken RTKLibSolverTest --- tests/data/rtklib_test/eph_GPS_L1CA_test1.xml | 860 +++++++++--------- .../eph_GPS_L1CA_test1.xml.license | 2 + tests/data/rtklib_test/obs_test1.xml | 102 ++- tests/data/rtklib_test/obs_test1.xml.license | 2 + .../pvt/rtklib_solver_test.cc | 17 +- 5 files changed, 517 insertions(+), 466 deletions(-) create mode 100644 tests/data/rtklib_test/eph_GPS_L1CA_test1.xml.license create mode 100644 tests/data/rtklib_test/obs_test1.xml.license diff --git a/tests/data/rtklib_test/eph_GPS_L1CA_test1.xml b/tests/data/rtklib_test/eph_GPS_L1CA_test1.xml index 0c5dcbc4d..13bd6e799 100644 --- a/tests/data/rtklib_test/eph_GPS_L1CA_test1.xml +++ b/tests/data/rtklib_test/eph_GPS_L1CA_test1.xml @@ -1,6 +1,4 @@ - - @@ -9,474 +7,496 @@ 1 - 1 - 5.18448000000000000e+05 - 9.20000000000000000e+01 - 9.20000000000000000e+01 - 1.83125000000000000e+01 - 4.86413118201646669e-09 - 2.06468198930943725e+00 - 9.42498445510864258e-07 - 3.73082922305911736e-03 - 5.76488673686981201e-06 - 5.15366174697875977e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - -5.40167093276977539e-08 - 9.52167247599200905e-01 - 1.86264514923095703e-08 - 9.61377026423456127e-01 - 2.66968750000000000e+02 - 4.44935333708291858e-01 - -8.14641075927847669e-09 - 4.15017287135849497e-10 - 0 - 799 - 0 - 2 - 0 - 5.12227416038513184e-09 - 9.20000000000000000e+01 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - -1.09937973320484161e-05 - 3.41060513164847988e-13 - 0.00000000000000000e+00 - 0 - 0 - 0 + 1 + 2.06468198930943725e+00 + 4.86413118201646669e-09 + 3.73082922305911736e-03 + 5.15366174697875977e+03 + 9.52167247599200905e-01 + 9.61377026423456127e-01 + 4.44935333708291858e-01 + -8.14641075927847669e-09 + 4.15017287135849497e-10 + 9.42498445510864258e-07 + 5.76488673686981201e-06 + 2.66968750000000000e+02 + 1.83125000000000000e+01 + -5.40167093276977539e-08 + 1.86264514923095703e-08 + 518400 + 518400 + -1.09937973320484161e-05 + 3.41060513164847988e-13 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 92 + 92 + 0 + 0 + 2 + 0 + 5.12227416038513184e-09 + 92 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 2 - 2 - 5.18448000000000000e+05 - 5.50000000000000000e+01 - 5.50000000000000000e+01 - 2.22812500000000000e+01 - 5.12771358985317661e-09 - 2.75926302782053146e+00 - 1.10082328319549561e-06 - 1.40569622162729484e-02 - 6.26407563686370850e-06 - 5.15372654151916504e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - -1.86264514923095703e-08 - 9.18037446344556307e-01 - -2.16066837310791016e-07 - 9.39991586696909520e-01 - 2.45468750000000000e+02 - -2.35598690357981555e+00 - -8.07140763509730069e-09 - 5.25736184736635464e-10 - 0 - 799 - 0 - 2 - 0 - -2.00234353542327881e-08 - 5.50000000000000000e+01 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - 5.36850653588771820e-04 - 2.16004991671070416e-12 - 0.00000000000000000e+00 - 0 - 0 - 0 + 2 + 2.75926302782053146e+00 + 5.12771358985317661e-09 + 1.40569622162729484e-02 + 5.15372654151916504e+03 + 9.18037446344556307e-01 + 9.39991586696909520e-01 + -2.35598690357981555e+00 + -8.07140763509730069e-09 + 5.25736184736635464e-10 + 1.10082328319549561e-06 + 6.26407563686370850e-06 + 2.45468750000000000e+02 + 2.22812500000000000e+01 + -1.86264514923095703e-08 + -2.16066837310791016e-07 + 518400 + 518400 + 5.36850653588771820e-04 + 2.16004991671070416e-12 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 55 + 55 + 0 + 0 + 2 + 0 + -2.00234353542327881e-08 + 55 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 3 - 3 - 5.18448000000000000e+05 - 7.00000000000000000e+01 - 7.00000000000000000e+01 - -2.04375000000000000e+01 - 4.75769817722603366e-09 - -1.78871492992227910e+00 - -1.30012631416320801e-06 - 9.70319728367030512e-04 - 8.26455652713775635e-06 - 5.15378153991699219e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - 7.82310962677001953e-08 - 1.99297660614955263e+00 - -1.11758708953857422e-08 - 9.59058451948379909e-01 - 2.19593750000000000e+02 - -3.00536842405812843e+00 - -8.02712007605698577e-09 - -5.17164399115929480e-10 - 0 - 799 - 0 - 2 - 0 - 5.12227416038513184e-09 - 7.00000000000000000e+01 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - 8.80691222846508026e-05 - 2.89901436190120811e-11 - 0.00000000000000000e+00 - 0 - 0 - 0 + 3 + -1.78871492992227910e+00 + 4.75769817722603366e-09 + 9.70319728367030512e-04 + 5.15378153991699219e+03 + 1.99297660614955263e+00 + 9.59058451948379909e-01 + -3.00536842405812843e+00 + -8.02712007605698577e-09 + -5.17164399115929480e-10 + -1.30012631416320801e-06 + 8.26455652713775635e-06 + 2.19593750000000000e+02 + -2.04375000000000000e+01 + 7.82310962677001953e-08 + -1.11758708953857422e-08 + 518400 + 518400 + 8.80691222846508026e-05 + 2.89901436190120811e-11 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 70 + 70 + 0 + 0 + 2 + 0 + 5.12227416038513184e-09 + 70 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 6 - 6 - 5.18448000000000000e+05 - 2.30000000000000000e+01 - 2.30000000000000000e+01 - 1.63750000000000000e+01 - 4.76305554323897445e-09 - -1.28531071631616522e+00 - 9.12696123123168945e-07 - 5.50022465176880251e-04 - 6.24358654022216797e-06 - 5.15365166282653809e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - -1.30385160446166992e-08 - 9.43624288779246867e-01 - -1.86264514923095703e-09 - 9.61292940818096020e-01 - 2.58406250000000000e+02 - 2.29191014519991665e+00 - -8.08069373618639861e-09 - 4.79305679291144535e-10 - 0 - 799 - 0 - 2 - 0 - 4.65661287307739258e-09 - 2.30000000000000000e+01 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - 3.07881273329257965e-05 - 8.18545231595635253e-12 - 0.00000000000000000e+00 - 0 - 0 - 0 + 6 + -1.28531071631616522e+00 + 4.76305554323897445e-09 + 5.50022465176880251e-04 + 5.15365166282653809e+03 + 9.43624288779246867e-01 + 9.61292940818096020e-01 + 2.29191014519991665e+00 + -8.08069373618639861e-09 + 4.79305679291144535e-10 + 9.12696123123168945e-07 + 6.24358654022216797e-06 + 2.58406250000000000e+02 + 1.63750000000000000e+01 + -1.30385160446166992e-08 + -1.86264514923095703e-09 + 518400 + 518400 + 3.07881273329257965e-05 + 8.18545231595635253e-12 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 23 + 23 + 0 + 0 + 2 + 0 + 4.65661287307739258e-09 + 23 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 9 - 9 - 5.18448000000000000e+05 - 4.70000000000000000e+01 - 4.70000000000000000e+01 - 1.12906250000000000e+02 - 4.37911097897818463e-09 - -2.75253879947800195e+00 - 5.85243105888366699e-06 - 2.16206186451017829e-04 - 1.16303563117980957e-05 - 5.15369471168518066e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - 1.67638063430786133e-08 - 3.03742251571970812e+00 - -1.11758708953857422e-08 - 9.59160503650671514e-01 - 1.56125000000000000e+02 - 2.60662251530764344e+00 - -7.85854162551643464e-09 - -3.46443002170201364e-11 - 0 - 799 - 0 - 2 - 0 - 4.65661287307739258e-10 - 4.70000000000000000e+01 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - -3.18535603582859039e-05 - -9.66338120633736091e-12 - 0.00000000000000000e+00 - 0 - 0 - 0 + 9 + -2.75253879947800195e+00 + 4.37911097897818463e-09 + 2.16206186451017829e-04 + 5.15369471168518066e+03 + 3.03742251571970812e+00 + 9.59160503650671514e-01 + 2.60662251530764344e+00 + -7.85854162551643464e-09 + -3.46443002170201364e-11 + 5.85243105888366699e-06 + 1.16303563117980957e-05 + 1.56125000000000000e+02 + 1.12906250000000000e+02 + 1.67638063430786133e-08 + -1.11758708953857422e-08 + 518400 + 518400 + -3.18535603582859039e-05 + -9.66338120633736091e-12 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 47 + 47 + 0 + 0 + 2 + 0 + 4.65661287307739258e-10 + 47 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 10 - 10 - 5.18448000000000000e+05 - 5.80000000000000000e+01 - 5.80000000000000000e+01 - -2.72500000000000000e+01 - 5.27093384126580581e-09 - -8.86982818851813737e-01 - -1.17719173431396484e-06 - 1.44534236751496774e-02 - 7.90506601333618164e-06 - 5.15363725471496582e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - 1.45286321640014648e-07 - 2.00408517949479270e+00 - 2.40281224250793457e-07 - 9.41160112993577269e-01 - 2.15406250000000000e+02 - 9.09732121011562200e-01 - -8.42213653007785350e-09 - -5.42879755978047536e-10 - 0 - 799 - 0 - 2 - 0 - -2.79396772384643555e-09 - 5.80000000000000000e+01 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - -1.54968351125717163e-04 - -1.59161572810262401e-12 - 0.00000000000000000e+00 - 0 - 0 - 0 + 10 + -8.86982818851813737e-01 + 5.27093384126580581e-09 + 1.44534236751496774e-02 + 5.15363725471496582e+03 + 2.00408517949479270e+00 + 9.41160112993577269e-01 + 9.09732121011562200e-01 + -8.42213653007785350e-09 + -5.42879755978047536e-10 + -1.17719173431396484e-06 + 7.90506601333618164e-06 + 2.15406250000000000e+02 + -2.72500000000000000e+01 + 1.45286321640014648e-07 + 2.40281224250793457e-07 + 518400 + 518400 + -1.54968351125717163e-04 + -1.59161572810262401e-12 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 58 + 58 + 0 + 0 + 2 + 0 + -2.79396772384643555e-09 + 58 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 12 - 12 - 5.18448000000000000e+05 - 1.06000000000000000e+02 - 1.06000000000000000e+02 - -1.17468750000000000e+02 - 3.94516433192994276e-09 - 1.11631735294997192e+00 - -6.15417957305908203e-06 - 5.05860964767634782e-03 - 4.52436506748199463e-06 - 5.15376680946350098e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - -5.40167093276977539e-08 - -1.10425023618040785e+00 - 4.09781932830810547e-08 - 9.88803748742243305e-01 - 3.07187500000000000e+02 - 5.00154452274795935e-01 - -7.97176062725659211e-09 - -4.18231706743614228e-10 - 0 - 799 - 0 - 2 - 0 - -1.16415321826934814e-08 - 1.06000000000000000e+02 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - 2.54871323704719543e-04 - 2.72848410531878391e-12 - 0.00000000000000000e+00 - 0 - 0 - 0 + 12 + 1.11631735294997192e+00 + 3.94516433192994276e-09 + 5.05860964767634782e-03 + 5.15376680946350098e+03 + -1.10425023618040785e+00 + 9.88803748742243305e-01 + 5.00154452274795935e-01 + -7.97176062725659211e-09 + -4.18231706743614228e-10 + -6.15417957305908203e-06 + 4.52436506748199463e-06 + 3.07187500000000000e+02 + -1.17468750000000000e+02 + -5.40167093276977539e-08 + 4.09781932830810547e-08 + 518400 + 518400 + 2.54871323704719543e-04 + 2.72848410531878391e-12 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 106 + 106 + 0 + 0 + 2 + 0 + -1.16415321826934814e-08 + 106 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 17 - 17 - 5.18448000000000000e+05 - 2.60000000000000000e+01 - 2.60000000000000000e+01 - -5.91250000000000000e+01 - 3.88194741297723567e-09 - -1.94252959218893162e+00 - -3.04728746414184570e-06 - 9.88844956737011498e-03 - 1.18296593427658081e-05 - 5.15369299888610840e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - 2.03028321266174316e-07 - -5.68690999805671268e-02 - -7.63684511184692383e-08 - 9.71201777972365177e-01 - 1.56531250000000000e+02 - -2.06928329237789344e+00 - -7.44602444251995675e-09 - 4.40375486263771432e-10 - 0 - 799 - 0 - 2 - 0 - -1.07102096080780029e-08 - 2.60000000000000000e+01 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - -1.44933816045522690e-04 - -2.27373675443232019e-12 - 0.00000000000000000e+00 - 0 - 0 - 0 + 17 + -1.94252959218893162e+00 + 3.88194741297723567e-09 + 9.88844956737011498e-03 + 5.15369299888610840e+03 + -5.68690999805671268e-02 + 9.71201777972365177e-01 + -2.06928329237789344e+00 + -7.44602444251995675e-09 + 4.40375486263771432e-10 + -3.04728746414184570e-06 + 1.18296593427658081e-05 + 1.56531250000000000e+02 + -5.91250000000000000e+01 + 2.03028321266174316e-07 + -7.63684511184692383e-08 + 518400 + 518400 + -1.44933816045522690e-04 + -2.27373675443232019e-12 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 26 + 26 + 0 + 0 + 2 + 0 + -1.07102096080780029e-08 + 26 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 20 - 20 - 5.18448000000000000e+05 - 1.17000000000000000e+02 - 1.17000000000000000e+02 - -2.58437500000000000e+01 - 5.60380484953655626e-09 - 1.28625710142833249e-01 - -1.52923166751861572e-06 - 5.80669869668781671e-03 - 7.51018524169921875e-06 - 5.15578671264648438e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - -2.23517417907714844e-08 - 1.92543994118208528e+00 - 4.65661287307739258e-08 - 9.26021286652122910e-01 - 2.18031250000000000e+02 - 1.23365536128043107e+00 - -8.54892752571746483e-09 - -5.16450083647537340e-10 - 0 - 799 - 0 - 2 - 0 - -8.38190317153930664e-09 - 1.17000000000000000e+02 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - 2.69209500402212143e-04 - 4.20641299569979229e-12 - 0.00000000000000000e+00 - 0 - 0 - 0 + 20 + 1.28625710142833249e-01 + 5.60380484953655626e-09 + 5.80669869668781671e-03 + 5.15578671264648438e+03 + 1.92543994118208528e+00 + 9.26021286652122910e-01 + 1.23365536128043107e+00 + -8.54892752571746483e-09 + -5.16450083647537340e-10 + -1.52923166751861572e-06 + 7.51018524169921875e-06 + 2.18031250000000000e+02 + -2.58437500000000000e+01 + -2.23517417907714844e-08 + 4.65661287307739258e-08 + 518400 + 518400 + 2.69209500402212143e-04 + 4.20641299569979229e-12 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 117 + 117 + 0 + 0 + 2 + 0 + -8.38190317153930664e-09 + 117 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 23 - 23 - 5.18448000000000000e+05 - 4.10000000000000000e+01 - 4.10000000000000000e+01 - 1.20250000000000000e+02 - 4.45161399901998963e-09 - 3.04794581942897569e+00 - 6.13741576671600342e-06 - 9.67817602213471954e-03 - 1.14180147647857666e-05 - 5.15370163154602051e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - -6.14672899246215820e-08 - 3.04748172476042711e+00 - -1.04308128356933594e-07 - 9.50229191282804808e-01 - 1.56000000000000000e+02 - -2.71676891930177256e+00 - -7.78032408172749087e-09 - -2.75011455330984601e-11 - 0 - 799 - 0 - 2 - 0 - -1.95577740669250488e-08 - 4.10000000000000000e+01 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - -7.56788067519664764e-05 - -2.72848410531878391e-12 - 0.00000000000000000e+00 - 0 - 0 - 0 + 23 + 3.04794581942897569e+00 + 4.45161399901998963e-09 + 9.67817602213471954e-03 + 5.15370163154602051e+03 + 3.04748172476042711e+00 + 9.50229191282804808e-01 + -2.71676891930177256e+00 + -7.78032408172749087e-09 + -2.75011455330984601e-11 + 6.13741576671600342e-06 + 1.14180147647857666e-05 + 1.56000000000000000e+02 + 1.20250000000000000e+02 + -6.14672899246215820e-08 + -1.04308128356933594e-07 + 518400 + 518400 + -7.56788067519664764e-05 + -2.72848410531878391e-12 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 41 + 41 + 0 + 0 + 2 + 0 + -1.95577740669250488e-08 + 41 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 28 - 28 - 5.18448000000000000e+05 - 3.30000000000000000e+01 - 3.30000000000000000e+01 - -1.27750000000000000e+02 - 4.04302555109966970e-09 - -1.16607683198628931e+00 - -6.37024641036987305e-06 - 1.97223023278638686e-02 - 5.66989183425903320e-06 - 5.15368548965454102e+03 - 5.18400000000000000e+05 - 5.18400000000000000e+05 - -1.37835741043090820e-07 - -1.08006546321039543e+00 - 4.35858964920043945e-07 - 9.87961552655681530e-01 - 2.84718750000000000e+02 - -1.69047108635756738e+00 - -8.17855495535612472e-09 - -4.44661379074124424e-10 - 0 - 799 - 0 - 2 - 0 - -1.11758708953857422e-08 - 3.30000000000000000e+01 - 27900 - 0 - 0.00000000000000000e+00 - 0.00000000000000000e+00 - 4.06486913561820984e-04 - 2.61479726759716828e-12 - 0.00000000000000000e+00 - 0 - 0 - 0 + 28 + -1.16607683198628931e+00 + 4.04302555109966970e-09 + 1.97223023278638686e-02 + 5.15368548965454102e+03 + -1.08006546321039543e+00 + 9.87961552655681530e-01 + -1.69047108635756738e+00 + -8.17855495535612472e-09 + -4.44661379074124424e-10 + -6.37024641036987305e-06 + 5.66989183425903320e-06 + 2.84718750000000000e+02 + -1.27750000000000000e+02 + -1.37835741043090820e-07 + 4.35858964920043945e-07 + 518400 + 518400 + 4.06486913561820984e-04 + 2.61479726759716828e-12 + 0.00000000000000000e+00 + 799 + 518448 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 33 + 33 + 0 + 0 + 2 + 0 + -1.11758708953857422e-08 + 33 + 27900 + 0 + 0.00000000000000000e+00 + 0.00000000000000000e+00 + 0 + 0 + 0 diff --git a/tests/data/rtklib_test/eph_GPS_L1CA_test1.xml.license b/tests/data/rtklib_test/eph_GPS_L1CA_test1.xml.license new file mode 100644 index 000000000..dc15f4512 --- /dev/null +++ b/tests/data/rtklib_test/eph_GPS_L1CA_test1.xml.license @@ -0,0 +1,2 @@ +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: 2018 Javier Arribas diff --git a/tests/data/rtklib_test/obs_test1.xml b/tests/data/rtklib_test/obs_test1.xml index db34cdef9..3cadf5e21 100644 --- a/tests/data/rtklib_test/obs_test1.xml +++ b/tests/data/rtklib_test/obs_test1.xml @@ -1,6 +1,4 @@ - - @@ -22,7 +20,6 @@ -2.50000000000000000e+03 10791 0 - 0 2600000 -3.85959140625000000e+04 -9.03592163085937500e+02 @@ -31,14 +28,17 @@ 8.35350813421410858e+05 3.31084377635761484e-01 133923691 - 1 1 - 1 518451424 2.28178186234515086e+07 5.18451500000000000e+05 - 1 5.18451423887949765e+08 + 0 + 1 + 1 + 1 + 0 + 0 @@ -57,7 +57,6 @@ -3.00000000000000000e+03 68450858 0 - 0 2600000 -4.34972734375000000e+04 4.21364685058593750e+02 @@ -66,14 +65,17 @@ 4.93910706686261110e+05 7.36033200862493686e-01 133923971 - 1 1 - 1 518451431 2.07516033774388395e+07 5.18451500000000000e+05 - 1 5.18451430780101955e+08 + 0 + 1 + 1 + 1 + 0 + 0 @@ -92,7 +94,6 @@ -3.00000000000000000e+03 1350770 0 - 0 2600000 4.46268046875000000e+04 -3.98811938476562500e+03 @@ -101,14 +102,17 @@ 9.35704822809229488e+05 9.30327007595224131e-01 133923941 - 1 1 - 1 518451436 1.92492043561209217e+07 5.18451500000000000e+05 - 1 5.18451435791565657e+08 + 0 + 1 + 1 + 1 + 0 + 0 @@ -127,7 +131,6 @@ 1.00000000000000000e+03 994247 0 - 0 2600000 3.98655546875000000e+04 -8.63781860351562500e+02 @@ -136,14 +139,17 @@ -3.54128275530727289e+05 4.08304036132904002e-01 133922883 - 1 1 - 1 518451429 2.12256989876578376e+07 5.18451500000000000e+05 - 1 5.18451429198689222e+08 + 0 + 1 + 1 + 1 + 0 + 0 @@ -162,7 +168,6 @@ 1.75000000000000000e+03 4917751 0 - 0 2600000 -4.72456406250000000e+04 -2.63723022460937500e+02 @@ -171,14 +176,17 @@ -5.72184006019302527e+05 5.89544135488722532e-01 133922337 - 1 1 - 1 518451430 2.08629709015843943e+07 5.18451500000000000e+05 - 1 5.18451430408619881e+08 + 0 + 1 + 1 + 1 + 0 + 0 @@ -197,7 +205,6 @@ 2.50000000000000000e+02 514377 0 - 0 2600000 4.27717460937500000e+04 -9.45822082519531250e+02 @@ -206,14 +213,17 @@ -9.09813659855529113e+04 6.57473345280777721e-01 133923172 - 1 1 - 1 518451440 1.79613337841309197e+07 5.18451500000000000e+05 - 1 5.18451440087439477e+08 + 0 + 1 + 1 + 1 + 0 + 0 @@ -232,7 +242,6 @@ 2.25000000000000000e+03 7365787 0 - 0 2600000 -3.96159960937500000e+04 -5.03847460937500000e+03 @@ -241,14 +250,17 @@ -7.04913853936602012e+05 3.21518194999043772e-01 133922169 - 1 1 - 1 518451430 2.08435687343175523e+07 5.18451500000000000e+05 - 1 5.18451430473338544e+08 + 0 + 1 + 1 + 1 + 0 + 0 @@ -267,7 +279,6 @@ 2.75000000000000000e+03 2173576 0 - 0 2600000 4.00322539062500000e+04 -3.88590087890625000e+02 @@ -276,14 +287,17 @@ -8.99142229977656389e+05 1.02370741655249731e-01 133922664 - 1 1 - 1 518451438 1.85022797143675610e+07 5.18451500000000000e+05 - 1 5.18451438283038080e+08 + 0 + 1 + 1 + 1 + 0 + 0 @@ -302,7 +316,6 @@ 3.00000000000000000e+03 7464974 0 - 0 2600000 -4.03654140625000000e+04 3.92351245117187500e+03 @@ -311,14 +324,17 @@ -9.28340507655202877e+05 5.73995602361264901e-01 133923741 - 1 1 - 1 518451427 2.19242346189941987e+07 5.18451500000000000e+05 - 1 5.18451426868625164e+08 + 0 + 1 + 1 + 1 + 0 + 0 @@ -337,7 +353,6 @@ 5.00000000000000000e+02 1859813 0 - 0 2600000 3.87814335937500000e+04 2.13637329101562500e+03 @@ -346,14 +361,17 @@ -1.78723083774703584e+05 3.47952294631795667e-01 133924211 - 1 1 - 1 518451439 1.83808922785463184e+07 5.18451500000000000e+05 - 1 5.18451438687942982e+08 + 0 + 1 + 1 + 1 + 0 + 0 diff --git a/tests/data/rtklib_test/obs_test1.xml.license b/tests/data/rtklib_test/obs_test1.xml.license new file mode 100644 index 000000000..dc15f4512 --- /dev/null +++ b/tests/data/rtklib_test/obs_test1.xml.license @@ -0,0 +1,2 @@ +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: 2018 Javier Arribas diff --git a/tests/unit-tests/signal-processing-blocks/pvt/rtklib_solver_test.cc b/tests/unit-tests/signal-processing-blocks/pvt/rtklib_solver_test.cc index cebd4615c..966f4805a 100644 --- a/tests/unit-tests/signal-processing-blocks/pvt/rtklib_solver_test.cc +++ b/tests/unit-tests/signal-processing-blocks/pvt/rtklib_solver_test.cc @@ -20,6 +20,9 @@ #include "in_memory_configuration.h" #include "pvt_conf.h" #include "rtklib_solver.h" +#include "sensor_data/sensor_data_aggregator.h" +#include "sensor_data/sensor_data_source_configuration.h" +#include "signal_flag.h" #include #include #include @@ -378,7 +381,6 @@ TEST(RTKLibSolverTest, test1) { // test case #1: GPS L1 CA simulated with gnss-sim std::string path = std::string(TEST_PATH); - int nchannels = 8; std::string dump_filename = ".rtklib_solver_dump.dat"; bool flag_dump_to_file = false; bool save_to_mat = false; @@ -386,8 +388,15 @@ TEST(RTKLibSolverTest, test1) Pvt_Conf conf; conf.use_e6_for_pvt = false; - auto d_ls_pvt = std::make_unique(rtk, conf, nchannels, dump_filename, 1, flag_dump_to_file, save_to_mat); - d_ls_pvt->set_averaging_depth(1); + auto d_ls_pvt = std::make_unique(rtk, conf, dump_filename, GPS_1C, flag_dump_to_file, save_to_mat); + // the scenario was simulated in December 2014 (GPS week 1823, transmitted mod-1024 + // week 799), so the week rollover must be resolved to the 1999-2019 era + d_ls_pvt->set_pre_2009_file(true); + + // sensor data aggregator with no external sensors + auto sensor_configuration = std::make_shared(); + const SensorDataSourceConfiguration sensor_data_source_configuration(sensor_configuration.get()); + const SensorDataAggregator sensor_data_aggregator(sensor_data_source_configuration, {}); // load ephemeris std::string eph_xml_filename = path + "data/rtklib_test/eph_GPS_L1CA_test1.xml"; @@ -443,7 +452,7 @@ TEST(RTKLibSolverTest, test1) // solve bool pvt_valid = false; - if (d_ls_pvt->get_PVT(gnss_synchro_map, false)) + if (d_ls_pvt->get_PVT(gnss_synchro_map, 0.02, sensor_data_aggregator)) { // DEBUG MESSAGE: Display position in console output if (d_ls_pvt->is_valid_position()) From 93967135ff42c22f2d248607ad7f1dad7c819e82 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 16 Jul 2026 13:41:00 +0200 Subject: [PATCH 3/5] Fix date in old files processing --- docs/CHANGELOG.md | 14 +++ src/algorithms/PVT/adapters/rtklib_pvt.cc | 8 +- src/algorithms/PVT/adapters/rtklib_pvt.h | 3 +- .../PVT/gnuradio_blocks/rtklib_pvt_gs.cc | 8 +- src/algorithms/PVT/libs/pvt_conf.h | 2 +- src/algorithms/PVT/libs/pvt_solution.cc | 8 +- src/algorithms/PVT/libs/pvt_solution.h | 10 ++- src/algorithms/PVT/libs/rinex_printer.cc | 72 +++++++-------- src/algorithms/PVT/libs/rinex_printer.h | 6 +- src/algorithms/PVT/libs/rtklib_solver.cc | 8 +- .../libs/rtklib/rtklib_conversions.cc | 20 ++--- .../libs/rtklib/rtklib_conversions.h | 10 +-- src/algorithms/libs/rtklib/rtklib_rtcm2.cc | 8 +- src/algorithms/libs/rtklib/rtklib_rtcm2.h | 4 +- src/algorithms/libs/rtklib/rtklib_rtcm3.cc | 8 +- src/algorithms/libs/rtklib/rtklib_rtcm3.h | 4 +- src/algorithms/libs/rtklib/rtklib_rtkcmn.cc | 40 ++++----- src/algorithms/libs/rtklib/rtklib_rtkcmn.h | 2 +- src/core/receiver/control_thread.cc | 10 ++- src/core/receiver/control_thread.h | 4 +- src/core/system_parameters/CMakeLists.txt | 2 + .../system_parameters/gps_week_rollover.cc | 87 +++++++++++++++++++ .../system_parameters/gps_week_rollover.h | 53 +++++++++++ .../pvt/rtklib_solver_test.cc | 6 +- 24 files changed, 280 insertions(+), 117 deletions(-) create mode 100644 src/core/system_parameters/gps_week_rollover.cc create mode 100644 src/core/system_parameters/gps_week_rollover.h diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 4a1cd97ee..bfc28b1d7 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -136,6 +136,20 @@ All notable changes to GNSS-SDR will be documented in this file. ### Improvements in Usability: +- A new global parameter `GNSS-SDR.observation_date` allows specifying the + approximate date of the signal capture, in `YYYY-MM-DD` or `YYYY` format + (e.g., `GNSS-SDR.observation_date=2014-12-20`), when post-processing recorded + signal files. It is used to resolve the GPS mod-1024 week-number rollover: + each broadcast week number is expanded to the 1024-week era closest to the + given date. This works for recordings from any era, including files captured + after the April 2019 rollover replayed far in the future, and also fixes the + applied leap-second offset, which is derived from the resolved date. If the + parameter is not set, the era is derived from the system clock, as before, + which is the right choice for live operation. The `GNSS-SDR.pre_2009_file` + flag, which could only select the August 1999 - April 2019 era, is now + deprecated: it keeps working exactly as before, but the receiver prints a + notice suggesting `GNSS-SDR.observation_date` instead, and it is ignored if + the new parameter is also set. - Added Galileo System Time (GST) annotations to HAS outputs when GST is decoded from an I/NAV channel, enabling the HAS Time of Hour (TOH) to be associated with an absolute UTC timestamp. diff --git a/src/algorithms/PVT/adapters/rtklib_pvt.cc b/src/algorithms/PVT/adapters/rtklib_pvt.cc index 47ba31fc8..0242d9875 100644 --- a/src/algorithms/PVT/adapters/rtklib_pvt.cc +++ b/src/algorithms/PVT/adapters/rtklib_pvt.cc @@ -24,6 +24,7 @@ #include "gnss_sdr_string_literals.h" // for std::string_literals in C++11 #include "gps_almanac.h" // for Gps_Almanac #include "gps_ephemeris.h" // for Gps_Ephemeris +#include "gps_week_rollover.h" // for gps_ref_week_from_config #include "pvt_conf.h" // for Pvt_Conf #include "rtklib_rtkpos.h" // for rtkfree, rtkinit #include "signal_enabled_flags.h" // for signal_enabled_flags @@ -68,8 +69,11 @@ Rtklib_Pvt::Rtklib_Pvt(const ConfigurationInterface* configuration, pvt_output_parameters.rtk_trace_level = configuration->property(role + ".rtk_trace_level"s, 0); - // Flag to postprocess old gnss records (older than 2009) and avoid wrong week rollover - pvt_output_parameters.pre_2009_file = configuration->property("GNSS-SDR.pre_2009_file", false); + // Approximate date of the signal capture, used to resolve the GPS mod-1024 + // week-number rollover when post-processing recorded files + pvt_output_parameters.ref_gps_week = gps_ref_week_from_config( + configuration->property("GNSS-SDR.observation_date", std::string("")), + configuration->property("GNSS-SDR.pre_2009_file", false)); // output rate pvt_output_parameters.observable_interval_ms = configuration->property("GNSS-SDR.observable_interval_ms", pvt_output_parameters.observable_interval_ms); diff --git a/src/algorithms/PVT/adapters/rtklib_pvt.h b/src/algorithms/PVT/adapters/rtklib_pvt.h index 57fb22c4c..b58ac0026 100644 --- a/src/algorithms/PVT/adapters/rtklib_pvt.h +++ b/src/algorithms/PVT/adapters/rtklib_pvt.h @@ -47,7 +47,8 @@ class Gps_Ephemeris; * * Global configuration options used: * - * GNSS-SDR.pre_2009_file - flag indicating a file older than 2009 rollover should be processed (false) + * GNSS-SDR.observation_date - approximate date of the signal capture in YYYY-MM-DD or YYYY format, used to resolve the GPS mod-1024 week-number rollover when post-processing recorded files (empty: derive it from the system clock) + * GNSS-SDR.pre_2009_file - deprecated, use GNSS-SDR.observation_date instead; flag indicating a file captured in the Aug 1999 - Apr 2019 week-number era (false) * GNSS-SDR.observable_interval_ms - (20) * * It supports the following configuration options: diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc index 4d623ede1..ad43f764b 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc @@ -414,7 +414,7 @@ rtklib_pvt_gs::rtklib_pvt_gs(uint32_t nchannels, // initialize RINEX printer if (d_rinex_output_enabled) { - d_rp = std::make_unique(d_signal_enabled_flags, d_rinex_version, conf_.rinex_output_path, conf_.rinex_name, conf_.pre_2009_file); + d_rp = std::make_unique(d_signal_enabled_flags, d_rinex_version, conf_.rinex_output_path, conf_.rinex_name, conf_.ref_gps_week); } else { @@ -578,19 +578,19 @@ rtklib_pvt_gs::rtklib_pvt_gs(uint32_t nchannels, // setup two PVT solvers: internal solver for rx clock and user solver // user PVT solver d_user_pvt_solver = std::make_shared(rtk, conf_, dump_ls_pvt_filename, d_signal_enabled_flags, d_dump, d_dump_mat); - d_user_pvt_solver->set_pre_2009_file(conf_.pre_2009_file); + d_user_pvt_solver->set_ref_gps_week(conf_.ref_gps_week); // internal PVT solver, mainly used to estimate the receiver clock rtk_t internal_rtk = rtk; internal_rtk.opt.mode = PMODE_SINGLE; // use single positioning mode in internal PVT solver d_internal_pvt_solver = std::make_shared(internal_rtk, conf_, dump_ls_pvt_filename, d_signal_enabled_flags, false, false); - d_internal_pvt_solver->set_pre_2009_file(conf_.pre_2009_file); + d_internal_pvt_solver->set_ref_gps_week(conf_.ref_gps_week); } else { // only one solver, customized by the user options d_internal_pvt_solver = std::make_shared(rtk, conf_, dump_ls_pvt_filename, d_signal_enabled_flags, d_dump, d_dump_mat); - d_internal_pvt_solver->set_pre_2009_file(conf_.pre_2009_file); + d_internal_pvt_solver->set_ref_gps_week(conf_.ref_gps_week); d_user_pvt_solver = d_internal_pvt_solver; } diff --git a/src/algorithms/PVT/libs/pvt_conf.h b/src/algorithms/PVT/libs/pvt_conf.h index 315637b21..012214b28 100644 --- a/src/algorithms/PVT/libs/pvt_conf.h +++ b/src/algorithms/PVT/libs/pvt_conf.h @@ -65,6 +65,7 @@ public: int32_t rinexobs_rate_ms = 0; int32_t an_rate_ms = 20; int32_t max_obs_block_rx_clock_offset_ms = 40; + int32_t ref_gps_week = 0; // reference GPS week to resolve the mod-1024 week rollover in post-processing (0: use system clock) int udp_eph_port = 0; int rtk_trace_level = 0; @@ -88,7 +89,6 @@ public: bool protobuf_enabled = true; bool enable_rx_clock_correction = true; bool show_local_time_zone = false; - bool pre_2009_file = false; bool dump = false; bool dump_mat = true; bool log_source_timetag = false; diff --git a/src/algorithms/PVT/libs/pvt_solution.cc b/src/algorithms/PVT/libs/pvt_solution.cc index da14f8be4..46c687e81 100644 --- a/src/algorithms/PVT/libs/pvt_solution.cc +++ b/src/algorithms/PVT/libs/pvt_solution.cc @@ -200,13 +200,13 @@ void Pvt_Solution::set_num_valid_observations(int num) } -void Pvt_Solution::set_pre_2009_file(bool pre_2009_file) +void Pvt_Solution::set_ref_gps_week(int32_t ref_week) { - d_pre_2009_file = pre_2009_file; + d_ref_gps_week = ref_week; } -bool Pvt_Solution::is_pre_2009() const +int32_t Pvt_Solution::get_ref_gps_week() const { - return d_pre_2009_file; + return d_ref_gps_week; } diff --git a/src/algorithms/PVT/libs/pvt_solution.h b/src/algorithms/PVT/libs/pvt_solution.h index bd00208bf..323128f31 100644 --- a/src/algorithms/PVT/libs/pvt_solution.h +++ b/src/algorithms/PVT/libs/pvt_solution.h @@ -20,6 +20,7 @@ #include #include +#include /** \addtogroup PVT * \{ */ @@ -53,7 +54,7 @@ public: double get_speed_over_ground() const; //!< Get RX speed over ground [m/s] double get_course_over_ground() const; //!< Get RX course over ground [deg] int get_num_valid_observations() const; //!< Get the number of valid pseudorange observations (valid satellites) - bool is_pre_2009() const; + int32_t get_ref_gps_week() const; //!< Get the reference GPS week used to resolve the mod-1024 week rollover (0 if unset) bool is_valid_position() const; void set_rx_pos(const std::array &pos); //!< Set position: X, Y, Z in Cartesian ECEF coordinates [m] @@ -64,8 +65,8 @@ public: void set_speed_over_ground(double speed_m_s); //!< Set RX speed over ground [m/s] void set_course_over_ground(double cog_deg); //!< Set RX course over ground [deg] void set_valid_position(bool is_valid); - void set_num_valid_observations(int num); //!< Set the number of valid pseudorange observations (valid satellites) - void set_pre_2009_file(bool pre_2009_file); //!< Flag for the week rollover computation in post processing mode for signals older than 2009 + void set_num_valid_observations(int num); //!< Set the number of valid pseudorange observations (valid satellites) + void set_ref_gps_week(int32_t ref_week); //!< Set the reference GPS week (e.g., derived from the date of signal capture) used to resolve the mod-1024 week rollover in post-processing mode private: /* @@ -99,7 +100,8 @@ private: int d_valid_observations{0}; // Number of valid observations in this epoch - bool d_pre_2009_file{false}; // Flag to correct week rollover in post processing mode for signals older than 2009 + int32_t d_ref_gps_week{0}; // Reference GPS week to correct the mod-1024 week rollover in post-processing mode (0: use system clock) + bool d_valid_position{false}; }; diff --git a/src/algorithms/PVT/libs/rinex_printer.cc b/src/algorithms/PVT/libs/rinex_printer.cc index c69081d66..92fc7f0e3 100644 --- a/src/algorithms/PVT/libs/rinex_printer.cc +++ b/src/algorithms/PVT/libs/rinex_printer.cc @@ -161,7 +161,7 @@ boost::posix_time::ptime gps_time_to_ptime(int32_t gps_week, double tow_s) } -int32_t expand_lnav_utc_week(int32_t utc_week, int32_t ephemeris_week, bool pre_2009_file) +int32_t expand_lnav_utc_week(int32_t utc_week, int32_t ephemeris_week, int32_t ref_gps_week) { constexpr int32_t LNAV_UTC_WEEK_MODULUS = 256; constexpr int32_t LNAV_UTC_WEEK_HALF_MODULUS = LNAV_UTC_WEEK_MODULUS / 2; @@ -172,10 +172,10 @@ int32_t expand_lnav_utc_week(int32_t utc_week, int32_t ephemeris_week, bool pre_ } if (utc_week > 255) { - return adjgpsweek(utc_week, pre_2009_file); + return adjgpsweek(utc_week, ref_gps_week); } - const int32_t reference_week = adjgpsweek(ephemeris_week, pre_2009_file); + const int32_t reference_week = adjgpsweek(ephemeris_week, ref_gps_week); int32_t expanded_week = utc_week; while ((expanded_week - reference_week) < -LNAV_UTC_WEEK_HALF_MODULUS) { @@ -1277,7 +1277,7 @@ std::string get_gps_iono_beta_line_v2(const Gps_Iono& iono) } -std::string get_delta_utc_line_v2(const Gps_Utc_Model& utc_model, const Gps_Ephemeris& eph, bool pre_2009_file) +std::string get_delta_utc_line_v2(const Gps_Utc_Model& utc_model, const Gps_Ephemeris& eph, int32_t ref_gps_week) { std::string line; @@ -1286,7 +1286,7 @@ std::string get_delta_utc_line_v2(const Gps_Utc_Model& utc_model, const Gps_Ephe line += rightJustify(doub2for(utc_model.A1, 18, 2), 19); line += rightJustify(std::to_string(utc_model.tot), 9); - const int32_t WN_T = expand_lnav_utc_week(utc_model.WN_T, eph.WN, pre_2009_file); + const int32_t WN_T = expand_lnav_utc_week(utc_model.WN_T, eph.WN, ref_gps_week); line += rightJustify(std::to_string(WN_T), 9); line += std::string(1, ' '); @@ -1394,9 +1394,9 @@ std::string get_beidou_iono_beta_line(const Beidou_Dnav_Iono& iono) } -std::string get_gps_time_corr_line(const Gps_Utc_Model& utc_model, const Gps_Ephemeris& gps_eph, bool pre_2009_file) +std::string get_gps_time_corr_line(const Gps_Utc_Model& utc_model, const Gps_Ephemeris& gps_eph, int32_t ref_gps_week) { - int32_t WN_T = expand_lnav_utc_week(utc_model.WN_T, gps_eph.WN, pre_2009_file); + int32_t WN_T = expand_lnav_utc_week(utc_model.WN_T, gps_eph.WN, ref_gps_week); return get_time_corr_line("GPUT", utc_model.A0, utc_model.A1, &utc_model.tot, &WN_T); } @@ -1473,9 +1473,9 @@ std::string get_leap_second_line_v2(const Gps_Utc_Model& utc_model) } -std::string get_leap_second_line(const Gps_Utc_Model& utc_model, const Gps_Ephemeris& gps_eph, bool pre_2009_file) +std::string get_leap_second_line(const Gps_Utc_Model& utc_model, const Gps_Ephemeris& gps_eph, int32_t ref_gps_week) { - const int32_t WN_LSF = expand_lnav_utc_week(utc_model.WN_LSF, gps_eph.WN, pre_2009_file); + const int32_t WN_LSF = expand_lnav_utc_week(utc_model.WN_LSF, gps_eph.WN, ref_gps_week); return get_leap_second_line(utc_model.DeltaT_LS, utc_model.DeltaT_LSF, WN_LSF, utc_model.DN); } @@ -2157,7 +2157,7 @@ Rinex_Printer::Rinex_Printer(uint32_t signal_enabled_flags, int version, const std::string& base_path, const std::string& base_name, - bool pre_2009_file) : Rinex_Printer(signal_enabled_flags, base_name, getAndCreateBaseRinexPath(base_path), version, pre_2009_file) + int32_t ref_gps_week) : Rinex_Printer(signal_enabled_flags, base_name, getAndCreateBaseRinexPath(base_path), version, ref_gps_week) { } @@ -2166,23 +2166,23 @@ Rinex_Printer::Rinex_Printer(uint32_t signal_enabled_flags, const std::string& base_name, const std::string& base_rinex_path, int version, - bool pre_2009_file) : observationType(getObservationTypes()), - observationCode(getObservationCodes()), - d_flags(signal_enabled_flags), - d_version(get_version(d_flags, version)), - d_stringVersion(d_version == 2 ? "2.11" : "3.02"), // Only version 2.11 and 3.02 - d_fake_cnav_iode(1), - d_rinex_header_updated(false), - d_rinex_header_gps_updated(!d_flags.has_gps), - d_rinex_header_galileo_updated(!d_flags.has_galileo), - d_rinex_header_glonass_updated(!d_flags.has_glonass), - d_rinex_header_beidou_updated(!d_flags.has_beidou), - d_rinex_header_written(false), - d_pre_2009_file(pre_2009_file), - navfilename(getNavFilePath(d_flags, d_version, base_name, base_rinex_path)), - obsfilename(getFilePath("RINEX_FILE_TYPE_OBS", base_name, base_rinex_path)), - navGlofilename(getFilePath("RINEX_FILE_TYPE_GLO_NAV", base_name, base_rinex_path)), - output_navfilename({navfilename}) + int32_t ref_gps_week) : observationType(getObservationTypes()), + observationCode(getObservationCodes()), + d_flags(signal_enabled_flags), + d_version(get_version(d_flags, version)), + d_stringVersion(d_version == 2 ? "2.11" : "3.02"), // Only version 2.11 and 3.02 + d_fake_cnav_iode(1), + d_rinex_header_updated(false), + d_rinex_header_gps_updated(!d_flags.has_gps), + d_rinex_header_galileo_updated(!d_flags.has_galileo), + d_rinex_header_glonass_updated(!d_flags.has_glonass), + d_rinex_header_beidou_updated(!d_flags.has_beidou), + d_rinex_header_written(false), + d_ref_gps_week(ref_gps_week), + navfilename(getNavFilePath(d_flags, d_version, base_name, base_rinex_path)), + obsfilename(getFilePath("RINEX_FILE_TYPE_OBS", base_name, base_rinex_path)), + navGlofilename(getFilePath("RINEX_FILE_TYPE_GLO_NAV", base_name, base_rinex_path)), + output_navfilename({navfilename}) { std::map fileMap = { {navfilename, navFile}, @@ -2370,15 +2370,15 @@ void Rinex_Printer::print_rinex_annotation(const Rtklib_Solver* pvt_solver, { iono_lines.emplace_back(get_gps_iono_alpha_line_v2(pvt_solver->gps_iono)); iono_lines.emplace_back(get_gps_iono_beta_line_v2(pvt_solver->gps_iono)); - time_corr_lines.emplace_back(get_delta_utc_line_v2(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_pre_2009_file)); + time_corr_lines.emplace_back(get_delta_utc_line_v2(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_ref_gps_week)); leap_second_line = get_leap_second_line_v2(pvt_solver->gps_utc_model); } else { iono_lines.emplace_back(get_gps_iono_alpha_line(pvt_solver->gps_iono)); iono_lines.emplace_back(get_gps_iono_beta_line(pvt_solver->gps_iono)); - time_corr_lines.emplace_back(get_gps_time_corr_line(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_pre_2009_file)); - leap_second_line = get_leap_second_line(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_pre_2009_file); + time_corr_lines.emplace_back(get_gps_time_corr_line(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_ref_gps_week)); + leap_second_line = get_leap_second_line(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_ref_gps_week); } } else if (d_flags.check_any_enabled(GPS_2S, GPS_L5)) @@ -2482,15 +2482,15 @@ void Rinex_Printer::print_rinex_annotation(const Rtklib_Solver* pvt_solver, { nav_header_info.emplace_back("", "ION ALPHA", get_gps_iono_alpha_line_v2(pvt_solver->gps_iono)); nav_header_info.emplace_back("", "ION BETA", get_gps_iono_beta_line_v2(pvt_solver->gps_iono)); - nav_header_info.emplace_back("", "DELTA-UTC", get_delta_utc_line_v2(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_pre_2009_file)); + nav_header_info.emplace_back("", "DELTA-UTC", get_delta_utc_line_v2(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_ref_gps_week)); leap_second_line = get_leap_second_line_v2(pvt_solver->gps_utc_model); } else { nav_header_info.emplace_back("GPSA", "IONOSPHERIC CORR", get_gps_iono_alpha_line(pvt_solver->gps_iono)); nav_header_info.emplace_back("GPSB", "IONOSPHERIC CORR", get_gps_iono_beta_line(pvt_solver->gps_iono)); - nav_header_info.emplace_back("GPUT", "TIME SYSTEM CORR", get_gps_time_corr_line(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_pre_2009_file)); - leap_second_line = get_leap_second_line(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_pre_2009_file); + nav_header_info.emplace_back("GPUT", "TIME SYSTEM CORR", get_gps_time_corr_line(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_ref_gps_week)); + leap_second_line = get_leap_second_line(pvt_solver->gps_utc_model, gps_ephemeris_iter->second, d_ref_gps_week); } d_rinex_header_gps_updated = true; } @@ -2624,7 +2624,7 @@ void Rinex_Printer::log_rinex_nav_gps_nav(const std::map // -------- BROADCAST ORBIT - 5 - auto GPS_week_continuous_number = static_cast(adjgpsweek(eph.WN, d_pre_2009_file)); + auto GPS_week_continuous_number = static_cast(adjgpsweek(eph.WN, d_ref_gps_week)); // This week goes with Toe. This is different from the GPS week in the original satellite message! if (eph.toe < 7200.0) { @@ -3231,7 +3231,7 @@ boost::posix_time::ptime Rinex_Printer::compute_UTC_time(const Gps_Navigation_Me // if we are processing a file -> wait to leap second to resolve the ambiguity else take the week from the local system time // idea: resolve the ambiguity with the leap second const double utc_t = nav_msg.utc_time(nav_msg.get_TOW()); - return gps_time_to_ptime(adjgpsweek(nav_msg.get_GPS_week(), d_pre_2009_file), utc_t); + return gps_time_to_ptime(adjgpsweek(nav_msg.get_GPS_week(), d_ref_gps_week), utc_t); } @@ -3254,7 +3254,7 @@ boost::posix_time::ptime Rinex_Printer::compute_GPS_time(const Gps_Ephemeris& ep // (see Section 3 in ftp://igs.org/pub/data/format/rinex211.txt) // (see Pag. 17 in ftp://igs.org/pub/data/format/rinex300.pdf) // No time correction here, since it will be done in the PVT processor - int32_t gps_week = adjgpsweek(eph.WN, d_pre_2009_file); + int32_t gps_week = adjgpsweek(eph.WN, d_ref_gps_week); // Handle TOW rollover if (obs_time < 18.0) { diff --git a/src/algorithms/PVT/libs/rinex_printer.h b/src/algorithms/PVT/libs/rinex_printer.h index dfda30a9a..1f2924171 100644 --- a/src/algorithms/PVT/libs/rinex_printer.h +++ b/src/algorithms/PVT/libs/rinex_printer.h @@ -89,7 +89,7 @@ public: int version = 3, const std::string& base_path = ".", const std::string& base_name = "-", - bool pre_2009_file = false); + int32_t ref_gps_week = 0); /*! * \brief Destructor. Removes created files if empty. @@ -165,7 +165,7 @@ private: const std::string& base_name, const std::string& base_rinex_path, int version, - bool pre_2009_file); + int32_t ref_gps_week); /* * Generates the GPS Observation data header @@ -250,7 +250,7 @@ private: bool d_rinex_header_glonass_updated; bool d_rinex_header_beidou_updated; bool d_rinex_header_written; - const bool d_pre_2009_file; + const int32_t d_ref_gps_week; const std::string navfilename; // Name of RINEX navigation file const std::string obsfilename; // Name of RINEX observation file diff --git a/src/algorithms/PVT/libs/rtklib_solver.cc b/src/algorithms/PVT/libs/rtklib_solver.cc index 8a43404e0..3a78745d7 100644 --- a/src/algorithms/PVT/libs/rtklib_solver.cc +++ b/src/algorithms/PVT/libs/rtklib_solver.cc @@ -1392,7 +1392,7 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ eph_data[valid_obs] = eph_to_rtklib(gps_ephemeris_iter->second, this->d_has_orbit_corrections_store_map[gnss_str], this->d_has_clock_corrections_store_map[gnss_str], - this->is_pre_2009()); + this->get_ref_gps_week()); // convert observation from GNSS-SDR class to RTKLIB structure obsd_t newobs{}; const HAS_obs_corrections *applied_has_correction = nullptr; @@ -1402,7 +1402,7 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ gps_ephemeris_iter->second.WN, d_rtklib_band_index[rtklib_sig], &applied_has_correction, - this->is_pre_2009()); + this->get_ref_gps_week()); clear_applied_has_phase_bias_discontinuity(applied_has_correction, prn); valid_obs++; } @@ -1855,7 +1855,7 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ // TOW d_monitor_pvt.TOW_at_current_symbol_ms = gnss_observables_map.cbegin()->second.TOW_at_current_symbol_ms; // WEEK - d_monitor_pvt.week = adjgpsweek(d_nav_data.eph[0].week, this->is_pre_2009()); + d_monitor_pvt.week = adjgpsweek(d_nav_data.eph[0].week, this->get_ref_gps_week()); // PVT GPS time d_monitor_pvt.RX_time = gnss_observables_map.cbegin()->second.RX_time; // User clock offset [s] @@ -1950,7 +1950,7 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ tmp_uint32 = gnss_observables_map.cbegin()->second.TOW_at_current_symbol_ms; d_dump_file.write(reinterpret_cast(&tmp_uint32), sizeof(uint32_t)); // WEEK - tmp_uint32 = adjgpsweek(d_nav_data.eph[0].week, this->is_pre_2009()); + tmp_uint32 = adjgpsweek(d_nav_data.eph[0].week, this->get_ref_gps_week()); d_dump_file.write(reinterpret_cast(&tmp_uint32), sizeof(uint32_t)); // PVT GPS time tmp_double = gnss_observables_map.cbegin()->second.RX_time; diff --git a/src/algorithms/libs/rtklib/rtklib_conversions.cc b/src/algorithms/libs/rtklib/rtklib_conversions.cc index 9aae76e68..e5c0afbd1 100644 --- a/src/algorithms/libs/rtklib/rtklib_conversions.cc +++ b/src/algorithms/libs/rtklib/rtklib_conversions.cc @@ -154,7 +154,7 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, int week, int band, const HAS_obs_corrections** applied_has_correction, - bool pre_2009_file) + int ref_week) { if (applied_has_correction != nullptr) { @@ -254,7 +254,7 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, } else { - rtklib_obs.time = gpst2time(adjgpsweek(week, pre_2009_file), gnss_synchro.RX_time); + rtklib_obs.time = gpst2time(adjgpsweek(week, ref_week), gnss_synchro.RX_time); } // account for the TOW crossover transitory in the first 18 seconds where the week is not yet updated! if (gnss_synchro.RX_time < 18.0) @@ -341,7 +341,7 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const std::map>& has_obs_corr, int week, int band, - bool pre_2009_file) + int ref_week) { return insert_obs_to_rtklib(rtklib_obs, gnss_synchro, @@ -349,7 +349,7 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, week, band, static_cast(nullptr), - pre_2009_file); + ref_week); } @@ -357,7 +357,7 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro, int week, int band, - bool pre_2009_file) + int ref_week) { std::map> empty_map; return insert_obs_to_rtklib(rtklib_obs, @@ -365,7 +365,7 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, empty_map, week, band, - pre_2009_file); + ref_week); } @@ -520,18 +520,18 @@ eph_t eph_to_rtklib(const Galileo_Ephemeris& gal_eph, } -eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, bool pre_2009_file) +eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, int ref_week) { std::map empty_orbit_map; std::map empty_clock_map; - return eph_to_rtklib(gps_eph, empty_orbit_map, empty_clock_map, pre_2009_file); + return eph_to_rtklib(gps_eph, empty_orbit_map, empty_clock_map, ref_week); } eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, const std::map& orbit_correction_map, const std::map& clock_correction_map, - bool pre_2009_file) + int ref_week) { eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false, 0, 0, 0, 0, 0.0, -1, 0}; @@ -549,7 +549,7 @@ eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, rtklib_sat.Adot = 0; // only in CNAV; rtklib_sat.ndot = 0; // only in CNAV; - rtklib_sat.week = adjgpsweek(gps_eph.WN, pre_2009_file); /* week of tow */ + rtklib_sat.week = adjgpsweek(gps_eph.WN, ref_week); /* week of tow */ rtklib_sat.cic = gps_eph.Cic; rtklib_sat.cis = gps_eph.Cis; rtklib_sat.cuc = gps_eph.Cuc; diff --git a/src/algorithms/libs/rtklib/rtklib_conversions.h b/src/algorithms/libs/rtklib/rtklib_conversions.h index d7be3af6a..c39509a1c 100644 --- a/src/algorithms/libs/rtklib/rtklib_conversions.h +++ b/src/algorithms/libs/rtklib/rtklib_conversions.h @@ -91,12 +91,12 @@ eph_t eph_to_rtklib(const Galileo_Ephemeris& gal_eph, const std::map& clock_correction_map); eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, - bool pre_2009_file = false); + int ref_week = 0); eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, const std::map& orbit_correction_map, const std::map& clock_correction_map, - bool pre_2009_file = false); + int ref_week = 0); eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris& gps_cnav_eph); @@ -121,16 +121,16 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, int week, int band, const HAS_obs_corrections** applied_has_correction, - bool pre_2009_file); + int ref_week); obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro, const std::map>& has_obs_corr, int week, int band, - bool pre_2009_file = false); + int ref_week = 0); -obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro, int week, int band, bool pre_2009_file = false); +obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro, int week, int band, int ref_week = 0); /** \} */ diff --git a/src/algorithms/libs/rtklib/rtklib_rtcm2.cc b/src/algorithms/libs/rtklib/rtklib_rtcm2.cc index 75d82ae04..80a6a9ff8 100644 --- a/src/algorithms/libs/rtklib/rtklib_rtcm2.cc +++ b/src/algorithms/libs/rtklib/rtklib_rtcm2.cc @@ -172,7 +172,7 @@ int decode_type3(rtcm_t *rtcm) /* decode type 14: gps time of week ------------------------------------------*/ -int decode_type14(rtcm_t *rtcm, bool pre_2009_file) +int decode_type14(rtcm_t *rtcm, int ref_week) { double zcnt; int i = 48; @@ -196,7 +196,7 @@ int decode_type14(rtcm_t *rtcm, bool pre_2009_file) trace(2, "rtcm2 14 length error: len=%d\n", rtcm->len); return -1; } - week = adjgpsweek(week, pre_2009_file); + week = adjgpsweek(week, ref_week); rtcm->time = gpst2time(week, hour * 3600.0 + zcnt * 0.6); rtcm->nav.leaps = leaps; return 6; @@ -224,7 +224,7 @@ int decode_type16(rtcm_t *rtcm) /* decode type 17: gps ephemerides -------------------------------------------*/ -int decode_type17(rtcm_t *rtcm, bool pre_2009_file) +int decode_type17(rtcm_t *rtcm, int ref_week) { eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, @@ -309,7 +309,7 @@ int decode_type17(rtcm_t *rtcm, bool pre_2009_file) } sat = satno(SYS_GPS, prn); eph.sat = sat; - eph.week = adjgpsweek(week, pre_2009_file); + eph.week = adjgpsweek(week, ref_week); eph.toe = gpst2time(eph.week, eph.toes); eph.toc = gpst2time(eph.week, toc); eph.ttr = rtcm->time; diff --git a/src/algorithms/libs/rtklib/rtklib_rtcm2.h b/src/algorithms/libs/rtklib/rtklib_rtcm2.h index 5c5d724e4..a199bf217 100644 --- a/src/algorithms/libs/rtklib/rtklib_rtcm2.h +++ b/src/algorithms/libs/rtklib/rtklib_rtcm2.h @@ -41,9 +41,9 @@ void adjhour(rtcm_t *rtcm, double zcnt); int obsindex(obs_t *obs, gtime_t time, int sat); int decode_type1(rtcm_t *rtcm); int decode_type3(rtcm_t *rtcm); -int decode_type14(rtcm_t *rtcm, bool pre_2009_file = false); +int decode_type14(rtcm_t *rtcm, int ref_week = 0); int decode_type16(rtcm_t *rtcm); -int decode_type17(rtcm_t *rtcm, bool pre_2009_file = false); +int decode_type17(rtcm_t *rtcm, int ref_week = 0); int decode_type18(rtcm_t *rtcm); int decode_type19(rtcm_t *rtcm); int decode_type22(rtcm_t *rtcm); diff --git a/src/algorithms/libs/rtklib/rtklib_rtcm3.cc b/src/algorithms/libs/rtklib/rtklib_rtcm3.cc index f20d59a33..972299c83 100644 --- a/src/algorithms/libs/rtklib/rtklib_rtcm3.cc +++ b/src/algorithms/libs/rtklib/rtklib_rtcm3.cc @@ -1015,7 +1015,7 @@ int decode_type1013(rtcm_t *rtcm __attribute__((unused))) /* decode type 1019: gps ephemerides -----------------------------------------*/ -int decode_type1019(rtcm_t *rtcm, bool pre_2009_file) +int decode_type1019(rtcm_t *rtcm, int ref_week) { eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, @@ -1115,7 +1115,7 @@ int decode_type1019(rtcm_t *rtcm, bool pre_2009_file) return -1; } eph.sat = sat; - eph.week = adjgpsweek(week, pre_2009_file); + eph.week = adjgpsweek(week, ref_week); eph.toe = gpst2time(eph.week, eph.toes); eph.toc = gpst2time(eph.week, toc); eph.ttr = rtcm->time; @@ -1514,7 +1514,7 @@ int decode_type1039(rtcm_t *rtcm __attribute__((unused))) /* decode type 1044: qzss ephemerides (ref [15]) -----------------------------*/ -int decode_type1044(rtcm_t *rtcm, bool pre_2009_file) +int decode_type1044(rtcm_t *rtcm, int ref_week) { eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, @@ -1607,7 +1607,7 @@ int decode_type1044(rtcm_t *rtcm, bool pre_2009_file) return -1; } eph.sat = sat; - eph.week = adjgpsweek(week, pre_2009_file); + eph.week = adjgpsweek(week, ref_week); eph.toe = gpst2time(eph.week, eph.toes); eph.toc = gpst2time(eph.week, toc); eph.ttr = rtcm->time; diff --git a/src/algorithms/libs/rtklib/rtklib_rtcm3.h b/src/algorithms/libs/rtklib/rtklib_rtcm3.h index aede7519e..5b17f8185 100644 --- a/src/algorithms/libs/rtklib/rtklib_rtcm3.h +++ b/src/algorithms/libs/rtklib/rtklib_rtcm3.h @@ -129,7 +129,7 @@ int decode_type1012(rtcm_t *rtcm); int decode_type1013(rtcm_t *rtcm); -int decode_type1019(rtcm_t *rtcm, bool pre_2009_file = false); +int decode_type1019(rtcm_t *rtcm, int ref_week = 0); int decode_type1020(rtcm_t *rtcm); @@ -167,7 +167,7 @@ int decode_type1038(rtcm_t *rtcm); int decode_type1039(rtcm_t *rtcm); -int decode_type1044(rtcm_t *rtcm, bool pre_2009_file = false); +int decode_type1044(rtcm_t *rtcm, int ref_week = 0); int decode_type1045(rtcm_t *rtcm); diff --git a/src/algorithms/libs/rtklib/rtklib_rtkcmn.cc b/src/algorithms/libs/rtklib/rtklib_rtkcmn.cc index 3a8dcd982..025f8fce0 100644 --- a/src/algorithms/libs/rtklib/rtklib_rtkcmn.cc +++ b/src/algorithms/libs/rtklib/rtklib_rtkcmn.cc @@ -2114,43 +2114,35 @@ double time2doy(gtime_t t) /* adjust gps week number ------------------------------------------------------ - * adjust gps week number using cpu time - * args : int week I not-adjusted gps week number + * adjust gps week number using a reference week or cpu time + * args : int week I not-adjusted (mod-1024) gps week number + * int ref_week I full gps week number used as reference to + * resolve the mod-1024 rollover, e.g. derived + * from the approximate date of signal capture + * when post-processing recorded files + * (0: use cpu time) * return : adjusted gps week number *-----------------------------------------------------------------------------*/ -int adjgpsweek(int week, bool pre_2009_file) +int adjgpsweek(int week, int ref_week) { - // int w; - // if (week < 512) - // { - // //assume receiver date > 7 april 2019 - // w = week + 2048; //add weeks from 6-january-1980 to week rollover in 6 april 2019 - // } - // else - // { - // //assume receiver date < 7 april 2019 - // w = week + 1024; //add weeks from 6-january-1980 to week rollover in 21 august 1999 - // } int w; if (week > 1023) { return week; } - if (pre_2009_file == false) + if (ref_week > 0) { - (void)time2gpst(utc2gpst(timeget()), &w); - if (w < 1560) - { - w = 1560; /* use 2009/12/1 if time is earlier than 2009/12/1 */ - } - return week + (w - week + 512) / 1024 * 1024; + /* pick the 1024-week era that places the output closest to ref_week */ + return week + (ref_week - week + 512) / 1024 * 1024; } - else + + (void)time2gpst(utc2gpst(timeget()), &w); + if (w < 1560) { - w = week + 1024; // add weeks from 6-january-1980 to week rollover in 21 august 1999 - return w; + w = 1560; /* use 2009/12/1 if time is earlier than 2009/12/1 */ } + return week + (w - week + 512) / 1024 * 1024; } diff --git a/src/algorithms/libs/rtklib/rtklib_rtkcmn.h b/src/algorithms/libs/rtklib/rtklib_rtkcmn.h index 14caedd99..c1437936b 100644 --- a/src/algorithms/libs/rtklib/rtklib_rtkcmn.h +++ b/src/algorithms/libs/rtklib/rtklib_rtkcmn.h @@ -188,7 +188,7 @@ double utc2gmst(gtime_t t, double ut1_utc); void time2str(gtime_t t, char *s, int n); char *time_str(gtime_t t, int n); double time2doy(gtime_t t); -int adjgpsweek(int week, bool pre_2009_file = false); +int adjgpsweek(int week, int ref_week = 0); unsigned int tickget(); void sleepms(int ms); void deg2dms(double deg, double *dms, int ndec); diff --git a/src/core/receiver/control_thread.cc b/src/core/receiver/control_thread.cc index 9a265254d..d2756c8f4 100644 --- a/src/core/receiver/control_thread.cc +++ b/src/core/receiver/control_thread.cc @@ -44,6 +44,7 @@ #include "gps_ephemeris.h" // for Gps_Ephemeris #include "gps_iono.h" // for Gps_Iono #include "gps_utc_model.h" // for Gps_Utc_Model +#include "gps_week_rollover.h" // for gps_ref_week_from_config #include "pvt_interface.h" // for PvtInterface #include "rtklib.h" // for gtime_t, alm_t #include "rtklib_conversions.h" // for alm_to_rtklib @@ -169,8 +170,11 @@ ControlThread::ControlThread(std::shared_ptr configurati void ControlThread::init() { telecommand_enabled_ = configuration_->property("GNSS-SDR.telecommand_enabled", false); - // OPTIONAL: specify a custom year to override the system time in order to postprocess old gnss records and avoid wrong week rollover - pre_2009_file_ = configuration_->property("GNSS-SDR.pre_2009_file", false); + // OPTIONAL: approximate date of the signal capture, used to resolve the GPS + // mod-1024 week-number rollover when post-processing old gnss records + ref_gps_week_ = gps_ref_week_from_config( + configuration_->property("GNSS-SDR.observation_date", std::string("")), + configuration_->property("GNSS-SDR.pre_2009_file", false)); // Instantiates a control queue, a GNSS flowgraph, and a control message factory control_queue_ = std::make_shared>(); cmd_interface_.set_msg_queue(control_queue_); // set also the queue pointer for the telecommand thread @@ -1055,7 +1059,7 @@ std::vector> ControlThread::get_visible_sats(time const std::map gps_eph_map = pvt_ptr->get_gps_ephemeris(); for (const auto &it : gps_eph_map) { - const eph_t rtklib_eph = eph_to_rtklib(it.second, pre_2009_file_); + const eph_t rtklib_eph = eph_to_rtklib(it.second, ref_gps_week_); std::array r_sat{}; double clock_bias_s; double sat_pos_variance_m2; diff --git a/src/core/receiver/control_thread.h b/src/core/receiver/control_thread.h index e1b29dcb6..a8c388f49 100644 --- a/src/core/receiver/control_thread.h +++ b/src/core/receiver/control_thread.h @@ -31,6 +31,7 @@ #include #include // for array #include // for size_t +#include // for int32_t #include // for shared_ptr #include // for string #include // for std::thread @@ -223,7 +224,8 @@ private: bool stop_; bool restart_; bool telecommand_enabled_; - bool pre_2009_file_; // to override the system time to postprocess old gnss records and avoid wrong week rollover + + int32_t ref_gps_week_; // reference GPS week to resolve the mod-1024 week rollover when post-processing old gnss records (0: use system clock) }; diff --git a/src/core/system_parameters/CMakeLists.txt b/src/core/system_parameters/CMakeLists.txt index a8e038353..06bfa0116 100644 --- a/src/core/system_parameters/CMakeLists.txt +++ b/src/core/system_parameters/CMakeLists.txt @@ -12,6 +12,7 @@ set(SYSTEM_PARAMETERS_SOURCES gnss_signal.cc gps_navigation_message.cc gps_ephemeris.cc + gps_week_rollover.cc galileo_utc_model.cc galileo_ephemeris.cc galileo_almanac_helper.cc @@ -43,6 +44,7 @@ set(SYSTEM_PARAMETERS_HEADERS gps_iono.h gps_almanac.h gps_utc_model.h + gps_week_rollover.h gps_acq_assist.h agnss_ref_time.h agnss_ref_location.h diff --git a/src/core/system_parameters/gps_week_rollover.cc b/src/core/system_parameters/gps_week_rollover.cc new file mode 100644 index 000000000..85bd38187 --- /dev/null +++ b/src/core/system_parameters/gps_week_rollover.cc @@ -0,0 +1,87 @@ +/*! + * \file gps_week_rollover.cc + * \brief Resolution of the GPS mod-1024 week-number rollover from the + * receiver configuration + * \author Carles Fernandez-Prades, 2026. cfernandez(at)cttc.es + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + + +#include "gps_week_rollover.h" +#include +#include +#include +#include + +namespace +{ +// Parses "YYYY-MM-DD" or "YYYY" ("YYYY" maps to July 1 of that year). +// Returns a not_a_date_time value if the string cannot be parsed. +boost::gregorian::date parse_observation_date(const std::string& date_str) +{ + try + { + if (date_str.size() == 4 && std::all_of(date_str.begin(), date_str.end(), [](char c) { return c >= '0' && c <= '9'; })) + { + return boost::gregorian::date(static_cast(std::stoi(date_str)), 7, 1); + } + return boost::gregorian::from_simple_string(date_str); + } + catch (const std::exception& e) + { + return boost::gregorian::date(boost::gregorian::not_a_date_time); + } +} +} // namespace + + +int32_t gps_ref_week_from_config(const std::string& observation_date, bool pre_2009_file) +{ + const boost::gregorian::date gps_epoch(1980, 1, 6); + if (!observation_date.empty()) + { + const boost::gregorian::date date = parse_observation_date(observation_date); + if (date.is_not_a_date()) + { + std::cout << "Warning: could not parse GNSS-SDR.observation_date=" << observation_date + << " (expected YYYY-MM-DD or YYYY format), ignoring it.\n"; + } + else if (date < gps_epoch) + { + std::cout << "Warning: GNSS-SDR.observation_date=" << observation_date + << " is earlier than the GPS epoch (1980-01-06), ignoring it.\n"; + } + else + { + if (pre_2009_file) + { + std::cout << "Warning: the deprecated GNSS-SDR.pre_2009_file flag is ignored because GNSS-SDR.observation_date is set.\n"; + } + return static_cast((date - gps_epoch).days() / 7); + } + } + if (pre_2009_file) + { + static bool notice_printed = false; + if (!notice_printed) + { + std::cout << "Warning: GNSS-SDR.pre_2009_file is deprecated. Please set GNSS-SDR.observation_date=YYYY-MM-DD\n" + << "(the approximate date of the signal capture) instead, which also works for files\n" + << "recorded after the April 2019 week rollover.\n"; + notice_printed = true; + } + // Mid-point of the Aug 1999 - Apr 2019 era: reproduces the legacy + // fixed +1024 week adjustment for every mod-1024 week number + return 1535; + } + return 0; +} diff --git a/src/core/system_parameters/gps_week_rollover.h b/src/core/system_parameters/gps_week_rollover.h new file mode 100644 index 000000000..7ec30f205 --- /dev/null +++ b/src/core/system_parameters/gps_week_rollover.h @@ -0,0 +1,53 @@ +/*! + * \file gps_week_rollover.h + * \brief Resolution of the GPS mod-1024 week-number rollover from the + * receiver configuration + * \author Carles Fernandez-Prades, 2026. cfernandez(at)cttc.es + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + + +#ifndef GNSS_SDR_GPS_WEEK_ROLLOVER_H +#define GNSS_SDR_GPS_WEEK_ROLLOVER_H + +#include +#include + +/** \addtogroup Core + * \{ */ +/** \addtogroup System_Parameters + * \{ */ + + +/*! + * \brief Derives the reference GPS week number used to resolve the GPS + * mod-1024 week-number rollover when post-processing recorded signal files. + * + * \param observation_date Value of the GNSS-SDR.observation_date + * configuration option: approximate date of the signal capture, in + * "YYYY-MM-DD" or "YYYY" format. An empty string means "not set". + * \param pre_2009_file Value of the deprecated GNSS-SDR.pre_2009_file flag. + * + * \returns The full GPS week number of the observation date. Each mod-1024 + * broadcast week number is then resolved to the 1024-week era that places it + * closest to this reference week (see adjgpsweek()). Returns 0 if neither + * option is set, which keeps the default behavior of deriving the era from + * the system clock. If only the deprecated flag is set, it returns week 1535 + * (mid-point of the 1999-2019 era), which reproduces the legacy fixed +1024 + * week adjustment, and a one-time deprecation notice is printed. + */ +int32_t gps_ref_week_from_config(const std::string& observation_date, bool pre_2009_file); + + +/** \} */ +/** \} */ +#endif // GNSS_SDR_GPS_WEEK_ROLLOVER_H diff --git a/tests/unit-tests/signal-processing-blocks/pvt/rtklib_solver_test.cc b/tests/unit-tests/signal-processing-blocks/pvt/rtklib_solver_test.cc index 966f4805a..f7fa41e42 100644 --- a/tests/unit-tests/signal-processing-blocks/pvt/rtklib_solver_test.cc +++ b/tests/unit-tests/signal-processing-blocks/pvt/rtklib_solver_test.cc @@ -17,6 +17,7 @@ #include "geofunctions.h" #include "gnss_sdr_make_unique.h" #include "gnss_sdr_supl_client.h" +#include "gps_week_rollover.h" #include "in_memory_configuration.h" #include "pvt_conf.h" #include "rtklib_solver.h" @@ -390,8 +391,9 @@ TEST(RTKLibSolverTest, test1) conf.use_e6_for_pvt = false; auto d_ls_pvt = std::make_unique(rtk, conf, dump_filename, GPS_1C, flag_dump_to_file, save_to_mat); // the scenario was simulated in December 2014 (GPS week 1823, transmitted mod-1024 - // week 799), so the week rollover must be resolved to the 1999-2019 era - d_ls_pvt->set_pre_2009_file(true); + // week 799); the approximate capture date resolves the week rollover, as the + // GNSS-SDR.observation_date configuration option does in the full receiver + d_ls_pvt->set_ref_gps_week(gps_ref_week_from_config("2014-12-20", false)); // sensor data aggregator with no external sensors auto sensor_configuration = std::make_shared(); From fea1ab82d6de23f91641bd4dbaf7147f45363475 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 16 Jul 2026 14:17:24 +0200 Subject: [PATCH 4/5] Fix date in default example --- tests/system-tests/position_test.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/system-tests/position_test.cc b/tests/system-tests/position_test.cc index 850d72352..0d30c1e8a 100644 --- a/tests/system-tests/position_test.cc +++ b/tests/system-tests/position_test.cc @@ -298,6 +298,17 @@ int PositionSystemTest::configure_receiver() { config->set_property("GNSS-SDR.use_acquisition_resampler", "true"); } +#if USE_GLOG_AND_GFLAGS + if (FLAGS_rinex_nav_file == std::string(DEFAULT_RINEX_NAV)) +#else + if (absl::GetFlag(FLAGS_rinex_nav_file) == std::string(DEFAULT_RINEX_NAV)) +#endif + { + // The signal is generated from the default RINEX nav file + // (brdc3540.14n, dated December 20, 2014), so set the observation + // date accordingly to resolve the GPS week rollover to that era + config->set_property("GNSS-SDR.observation_date", "2014-12-20"); + } config->set_property("GNSS-SDR.GPS_banned_prns", std::to_string(1)); // Set the assistance system parameters config->set_property("GNSS-SDR.SUPL_read_gps_assistance_xml", "false"); From 7bcaab8e57d6100be25449bc2b71e80863ce03e8 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 16 Jul 2026 14:45:41 +0200 Subject: [PATCH 5/5] Make clang-tidy happy --- src/core/system_parameters/gps_week_rollover.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/system_parameters/gps_week_rollover.cc b/src/core/system_parameters/gps_week_rollover.cc index 85bd38187..315a13f7b 100644 --- a/src/core/system_parameters/gps_week_rollover.cc +++ b/src/core/system_parameters/gps_week_rollover.cc @@ -32,7 +32,7 @@ boost::gregorian::date parse_observation_date(const std::string& date_str) { if (date_str.size() == 4 && std::all_of(date_str.begin(), date_str.end(), [](char c) { return c >= '0' && c <= '9'; })) { - return boost::gregorian::date(static_cast(std::stoi(date_str)), 7, 1); + return {static_cast(std::stoi(date_str)), 7, 1}; } return boost::gregorian::from_simple_string(date_str); }