diff --git a/conf/File_input/Beidou/gnss-sdr_BDS_B1C_geb_if20k_fs18m_ibyte.conf b/conf/File_input/Beidou/gnss-sdr_BDS_B1C_geb_if20k_fs18m_ibyte.conf index 70e40e2da..0207b1347 100644 --- a/conf/File_input/Beidou/gnss-sdr_BDS_B1C_geb_if20k_fs18m_ibyte.conf +++ b/conf/File_input/Beidou/gnss-sdr_BDS_B1C_geb_if20k_fs18m_ibyte.conf @@ -1,6 +1,7 @@ ; BeiDou B1C (1D) file-input example (IF = +20 kHz, Fs = 18 MHz, ibyte) ; Test data: https://drive.google.com/drive/folders/1UkjJwOMlKEFZiXYUdK4HKzTASYHXMsHL ; SPDX-License-Identifier: GPL-3.0-or-later +; SPDX-FileCopyrightText: (C) 2010-2026 (see AUTHORS file for a list of contributors) ; ; Mixed B1I+B1C PVT policy (same PRN): ; - RTKLIB bands: B1I=0 (FREQ1_BDS), B1C/1D=1 (FREQ1), B3I=2 (FREQ3_BDS). diff --git a/src/algorithms/PVT/libs/rtklib_solver.cc b/src/algorithms/PVT/libs/rtklib_solver.cc index 2d71cad4a..d968cebca 100644 --- a/src/algorithms/PVT/libs/rtklib_solver.cc +++ b/src/algorithms/PVT/libs/rtklib_solver.cc @@ -1781,86 +1781,23 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ case 'C': { // BEIDOU B1I / B1C / B3I - // Prefer B1C when the same PRN has a usable CNAV1 ephemeris. - // If B1C is tracked but CNAV1 is missing/stale, keep B1I+DNAV. + // Prefer B1C when the same PRN has CNAV1 ephemeris and a B1C observation. + // If B1C is tracked but CNAV1 is missing, keep B1I+DNAV. const std::string sig_(gnss_observables_iter->second.Signal); const int bds_sat = static_cast(gnss_observables_iter->second.PRN + NSATGPS + NSATGLO + NSATGAL + NSATQZS); - auto bds_toe_age_ok = [](double obs_tow_gpst_s, double toe_bdt_s) -> bool { - const double toe_gpst_s = toe_bdt_s + static_cast(BEIDOU_DNAV_BDT2GPST_LEAP_SEC_OFFSET); - double toe_age_s = std::fabs(obs_tow_gpst_s - toe_gpst_s); - if (toe_age_s > 302400.0) - { - toe_age_s = 604800.0 - toe_age_s; - } - return toe_age_s <= MAXDTOE_BDS; - }; - // Absolute PR floor/ceiling alone is unreliable: RX TOW is the - // latest TX TOW, so common bias can make all PRs look "short". - // Reject only clearly impossible values here; relative outliers - // (e.g. C35 ~3e6 m vs peers ~15e6 m) are filtered below. - auto bds_pr_absolute_ok = [](double pr_m) -> bool { - return pr_m > 1.0e5 && pr_m < 1.0e8; - }; - auto dnav_eph_sane = [](const Beidou_Dnav_Ephemeris &eph) -> bool { - // ICD B1I Table 5-10: toe ∈ [0, 604792], sqrt(A) ∈ [0, 8192] - return eph.toe >= 0 && eph.toe <= static_cast(D1_TOE_MAX_S) && - eph.sqrtA >= D1_SQRT_A_MIN_SANE && eph.sqrtA <= D1_SQRT_A_MAX; - }; - - // Relative PR outlier vs other BeiDou obs in this epoch (~10 ms · c). - // Catches per-SV TOW desync (C35 B1I/B1C both ~3.18e6 m while peers ~15e6 m). - std::vector bds_prs; - bds_prs.reserve(gnss_observables_map.size()); - for (const auto &obs_pair : gnss_observables_map) - { - if (obs_pair.second.System == 'C' && bds_pr_absolute_ok(obs_pair.second.Pseudorange_m)) - { - bds_prs.push_back(obs_pair.second.Pseudorange_m); - } - } - double bds_pr_median = 0.0; - if (!bds_prs.empty()) - { - std::nth_element(bds_prs.begin(), bds_prs.begin() + static_cast(bds_prs.size() / 2), bds_prs.end()); - bds_pr_median = bds_prs[bds_prs.size() / 2]; - } - constexpr double bds_pr_outlier_m = 5.0e6; // ~16.7 ms · c - auto bds_pr_sane = [&](double pr_m) -> bool { - if (!bds_pr_absolute_ok(pr_m)) - { - return false; - } - if (bds_prs.size() >= 3 && bds_pr_median > 0.0 && - std::fabs(pr_m - bds_pr_median) > bds_pr_outlier_m) - { - return false; - } - return true; - }; if (sig_ == "B1") { - if (!bds_pr_sane(gnss_observables_iter->second.Pseudorange_m)) - { - DLOG(INFO) << "Skip B1I PRN " << gnss_observables_iter->second.PRN - << " (absurd/outlier pseudorange " << gnss_observables_iter->second.Pseudorange_m << " m)"; - break; - } bool prefer_b1c = false; for (const auto &obs_pair : gnss_observables_map) { if (obs_pair.second.System == 'C' && obs_pair.second.PRN == gnss_observables_iter->second.PRN && std::string(obs_pair.second.Signal, 2) == "1D" && - bds_pr_sane(obs_pair.second.Pseudorange_m)) + beidou_cnav1_ephemeris_map.find(obs_pair.second.PRN) != beidou_cnav1_ephemeris_map.cend()) { - const auto cnav1_it = beidou_cnav1_ephemeris_map.find(obs_pair.second.PRN); - if (cnav1_it != beidou_cnav1_ephemeris_map.cend() && - bds_toe_age_ok(obs_pair.second.RX_time, static_cast(cnav1_it->second.toe))) - { - prefer_b1c = true; - break; - } + prefer_b1c = true; + break; } } if (prefer_b1c) @@ -1872,21 +1809,6 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ beidou_ephemeris_iter = beidou_dnav_ephemeris_map.find(gnss_observables_iter->second.PRN); if (beidou_ephemeris_iter != beidou_dnav_ephemeris_map.cend()) { - if (!dnav_eph_sane(beidou_ephemeris_iter->second)) - { - DLOG(INFO) << "Skip corrupt DNAV ephemeris for SV " - << beidou_ephemeris_iter->second.PRN - << " toe=" << beidou_ephemeris_iter->second.toe - << " sqrtA=" << beidou_ephemeris_iter->second.sqrtA; - break; - } - if (!bds_toe_age_ok(gnss_observables_iter->second.RX_time, - static_cast(beidou_ephemeris_iter->second.toe))) - { - DLOG(INFO) << "Skip stale DNAV ephemeris for SV " - << beidou_ephemeris_iter->second.PRN; - break; - } eph_data[valid_obs] = eph_to_rtklib(beidou_ephemeris_iter->second); obsd_t newobs{}; d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs, @@ -1902,24 +1824,9 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ } if (sig_ == "1D") { - if (!bds_pr_sane(gnss_observables_iter->second.Pseudorange_m)) - { - DLOG(INFO) << "Skip B1C PRN " << gnss_observables_iter->second.PRN - << " (absurd/outlier pseudorange " << gnss_observables_iter->second.Pseudorange_m << " m)"; - break; - } const auto cnav1_iter = beidou_cnav1_ephemeris_map.find(gnss_observables_iter->second.PRN); if (cnav1_iter != beidou_cnav1_ephemeris_map.cend()) { - // Reject stale CNAV1 before it enters the epoch (MAXDTOE_BDS = 6 h). - // RX_time is GPST; CNAV1 toe is BDT (ICD §7.7) — convert before age check. - if (!bds_toe_age_ok(gnss_observables_iter->second.RX_time, - static_cast(cnav1_iter->second.toe))) - { - DLOG(INFO) << "Skip stale B-CNAV1 ephemeris for SV " - << cnav1_iter->second.PRN; - break; - } eph_data[valid_obs] = eph_to_rtklib(cnav1_iter->second); // Apply SF3 health (HS) when available const auto page_it = beidou_cnav1_page_data_map.find(cnav1_iter->second.PRN); @@ -1943,10 +1850,7 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ if (sig_ == "B3") { beidou_ephemeris_iter = beidou_dnav_ephemeris_map.find(gnss_observables_iter->second.PRN); - if (beidou_ephemeris_iter != beidou_dnav_ephemeris_map.cend() && - dnav_eph_sane(beidou_ephemeris_iter->second) && - bds_toe_age_ok(gnss_observables_iter->second.RX_time, - static_cast(beidou_ephemeris_iter->second.toe))) + if (beidou_ephemeris_iter != beidou_dnav_ephemeris_map.cend()) { bool found_B1I_obs = false; for (int i = 0; i < valid_obs; i++) @@ -2147,7 +2051,7 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ d_nav_data.utc_cmp[1] = beidou_cnav1_utc_model.A1; d_nav_data.utc_cmp[2] = static_cast(beidou_cnav1_utc_model.tot); d_nav_data.utc_cmp[3] = static_cast(beidou_cnav1_utc_model.WN_t); - d_nav_data.leaps = beidou_cnav1_utc_model.delta_t_LSF; + d_nav_data.leaps = beidou_cnav1_utc_model.delta_t_LS; } /* update carrier wave length using native function call in RTKlib */ @@ -2171,9 +2075,8 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ bool has_b1c = false; for (int k = 0; k < nobs_total; k++) { - for (int b = 0; b < NFREQ; b++) + for (const unsigned char cb : d_obs_data[k].code) { - const unsigned char cb = d_obs_data[k].code[b]; if (cb == CODE_L1D || cb == CODE_L1P) { has_b1c = true; diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index 01c994c0e..047a68a0f 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -8,15 +8,11 @@ set(ACQ_ADAPTER_SOURCES pcps_acquisition_adapter.cc pcps_acquisition_adapter_custom.cc - base_pcps_acquisition.cc - beidou_b1c_pcps_ambiguous_acquisition.cc ) set(ACQ_ADAPTER_HEADERS pcps_acquisition_adapter.h pcps_acquisition_adapter_custom.h - base_pcps_acquisition.h - beidou_b1c_pcps_ambiguous_acquisition.h ) if(ENABLE_FPGA) diff --git a/src/algorithms/acquisition/adapters/base_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/base_pcps_acquisition.cc deleted file mode 100644 index 79befc399..000000000 --- a/src/algorithms/acquisition/adapters/base_pcps_acquisition.cc +++ /dev/null @@ -1,222 +0,0 @@ -/*! - * \file base_ca_pcps_acquisition.h - * \brief Adapts a PCPS acquisition block to an AcquisitionInterface - * \authors
    - *
  • Mathieu Favreau, 2025. favreau.mathieu(at)hotmail.com - *
- * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2025 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - -#include "base_pcps_acquisition.h" -#include "acq_conf.h" -#include "configuration_interface.h" -#include "gnss_sdr_flags.h" - -#if USE_GLOG_AND_GFLAGS -#include -#else -#include -#endif - -#if HAS_STD_SPAN -#include -namespace own = std; -#else -#include -namespace own = gsl_lite; -#endif - -namespace -{ -Acq_Conf get_acq_conf(const ConfigurationInterface* configuration, const std::string& role, double chip_rate, double opt_freq, uint32_t ms_per_code) -{ - Acq_Conf acq_parameters; - acq_parameters.ms_per_code = ms_per_code; - acq_parameters.sampled_ms = ms_per_code; // Set as default value - acq_parameters.SetFromConfiguration(configuration, role, chip_rate, opt_freq); - -#if USE_GLOG_AND_GFLAGS - if (FLAGS_doppler_max != 0) - { - acq_parameters.doppler_max = FLAGS_doppler_max; - } - if (FLAGS_doppler_step != 0) - { - acq_parameters.doppler_step = FLAGS_doppler_step; - } -#else - if (absl::GetFlag(FLAGS_doppler_max) != 0) - { - acq_parameters.doppler_max = absl::GetFlag(FLAGS_doppler_max); - } - if (absl::GetFlag(FLAGS_doppler_step) != 0) - { - acq_parameters.doppler_step = absl::GetFlag(FLAGS_doppler_step); - } -#endif - - return acq_parameters; -} -} // namespace - -BasePcpsAcquisition::BasePcpsAcquisition( - const ConfigurationInterface* configuration, - const std::string& role, - unsigned int in_streams, - unsigned int out_streams, - double chip_rate, - double opt_freq, - double code_length_chips, - uint32_t ms_per_code) : acq_parameters_(get_acq_conf(configuration, role, chip_rate, opt_freq, ms_per_code)), - gnss_synchro_(nullptr), - role_(role), - vector_length_(std::floor(acq_parameters_.sampled_ms * acq_parameters_.samples_per_ms) * (acq_parameters_.bit_transition_flag ? 2.0 : 1.0)), - code_length_(static_cast(std::floor(static_cast(acq_parameters_.resampled_fs) / (chip_rate / code_length_chips)))), - code_(vector_length_), - acquisition_(pcps_make_acquisition(acq_parameters_)) -{ - DLOG(INFO) << "role " << role; - DLOG(INFO) << "acquisition(" << acquisition_->unique_id() << ")"; - - if (acq_parameters_.item_type == "cbyte") - { - cbyte_to_float_x2_ = make_complex_byte_to_float_x2(); - float_to_complex_ = gr::blocks::float_to_complex::make(); - } - - if (in_streams > 1) - { - LOG(ERROR) << "This implementation only supports one input stream"; - } - if (out_streams > 0) - { - LOG(ERROR) << "This implementation does not provide an output stream"; - } -} - - -void BasePcpsAcquisition::stop_acquisition() -{ - acquisition_->set_active(false); -} - - -void BasePcpsAcquisition::set_doppler_center(int doppler_center) -{ - acquisition_->set_doppler_center(doppler_center); -} - - -void BasePcpsAcquisition::set_gnss_synchro(Gnss_Synchro* gnss_synchro) -{ - gnss_synchro_ = gnss_synchro; - acquisition_->set_gnss_synchro(gnss_synchro_); -} - - -signed int BasePcpsAcquisition::mag() -{ - return acquisition_->mag(); -} - - -void BasePcpsAcquisition::reset() -{ - acquisition_->set_active(true); -} - - -void BasePcpsAcquisition::connect(gr::top_block_sptr top_block) -{ - if (acq_parameters_.item_type == "gr_complex" || acq_parameters_.item_type == "cshort") - { - // nothing to connect - } - else if (acq_parameters_.item_type == "cbyte") - { - // Since a byte-based acq implementation is not available, - // we just convert cshorts to gr_complex - top_block->connect(cbyte_to_float_x2_, 0, float_to_complex_, 0); - top_block->connect(cbyte_to_float_x2_, 1, float_to_complex_, 1); - top_block->connect(float_to_complex_, 0, acquisition_, 0); - } - else - { - LOG(WARNING) << acq_parameters_.item_type << " unknown acquisition item type"; - } -} - - -void BasePcpsAcquisition::disconnect(gr::top_block_sptr top_block) -{ - if (acq_parameters_.item_type == "gr_complex" || acq_parameters_.item_type == "cshort") - { - // nothing to disconnect - } - else if (acq_parameters_.item_type == "cbyte") - { - top_block->disconnect(cbyte_to_float_x2_, 0, float_to_complex_, 0); - top_block->disconnect(cbyte_to_float_x2_, 1, float_to_complex_, 1); - top_block->disconnect(float_to_complex_, 0, acquisition_, 0); - } - else - { - LOG(WARNING) << acq_parameters_.item_type << " unknown acquisition item type"; - } -} - - -gr::basic_block_sptr BasePcpsAcquisition::get_left_block() -{ - if (acq_parameters_.item_type == "gr_complex" || acq_parameters_.item_type == "cshort") - { - return acquisition_; - } - if (acq_parameters_.item_type == "cbyte") - { - return cbyte_to_float_x2_; - } - - LOG(WARNING) << acq_parameters_.item_type << " unknown acquisition item type"; - return nullptr; -} - - -gr::basic_block_sptr BasePcpsAcquisition::get_right_block() -{ - return acquisition_; -} - - -void BasePcpsAcquisition::set_resampler_latency(uint32_t latency_samples) -{ - acquisition_->set_resampler_latency(latency_samples); -} - - -void BasePcpsAcquisition::set_local_code() -{ - volk_gnsssdr::vector> code(code_length_); - - const auto sampling_freq = acq_parameters_.use_automatic_resampler ? acq_parameters_.resampled_fs : acq_parameters_.fs_in; - code_gen_complex_sampled(code, gnss_synchro_->PRN, sampling_freq); - - const auto num_codes = acq_parameters_.sampled_ms / acq_parameters_.ms_per_code; - - own::span code_span(code_.data(), vector_length_); - for (unsigned int i = 0; i < num_codes; i++) - { - std::copy_n(code.data(), code_length_, code_span.subspan(i * code_length_, code_length_).data()); - } - - acquisition_->set_local_code(code_.data()); -} diff --git a/src/algorithms/acquisition/adapters/base_pcps_acquisition.h b/src/algorithms/acquisition/adapters/base_pcps_acquisition.h deleted file mode 100644 index 6d4fd5906..000000000 --- a/src/algorithms/acquisition/adapters/base_pcps_acquisition.h +++ /dev/null @@ -1,146 +0,0 @@ -/*! - * \file base_ca_pcps_acquisition.h - * \brief Adapts a PCPS acquisition block to an AcquisitionInterface - * \authors
    - *
  • Mathieu Favreau, 2025. favreau.mathieu(at)hotmail.com - *
- * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2025 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_BASE_PCPS_ACQUISITION_H -#define GNSS_SDR_BASE_PCPS_ACQUISITION_H - -#include "acq_conf.h" -#include "channel_fsm.h" -#include "complex_byte_to_float_x2.h" -#include "gnss_synchro.h" -#include "pcps_acquisition.h" -#include -#include - -/** \addtogroup Acquisition - * Classes for GNSS signal acquisition - * \{ */ -/** \addtogroup Acq_adapters acquisition_adapters - * Wrap GNU Radio acquisition blocks with an AcquisitionInterface - * \{ */ - - -class ConfigurationInterface; - -/*! - * \brief This class adapts a PCPS acquisition block to an AcquisitionInterface - */ -class BasePcpsAcquisition : public AcquisitionInterface -{ -public: - BasePcpsAcquisition( - const ConfigurationInterface* configuration, - const std::string& role, - unsigned int in_streams, - unsigned int out_streams, - double chip_rate, - double opt_freq, - double code_length_chips, - uint32_t ms_per_code); - - ~BasePcpsAcquisition() override = default; - - inline std::string role() override - { - return role_; - } - - inline size_t item_size() override - { - return acq_parameters_.it_size; - } - - void connect(gr::top_block_sptr top_block) override; - void disconnect(gr::top_block_sptr top_block) override; - gr::basic_block_sptr get_left_block() override; - gr::basic_block_sptr get_right_block() override; - - /*! - * \brief Set acquisition/tracking common Gnss_Synchro object pointer - * to efficiently exchange synchronization data between acquisition and - * tracking blocks - */ - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; - - /*! - * \brief Set acquisition channel unique ID - */ - inline void set_channel(unsigned int channel) override - { - acquisition_->set_channel(channel); - } - - /*! - * \brief Set channel fsm associated to this acquisition instance - */ - inline void set_channel_fsm(std::weak_ptr channel_fsm) override - { - acquisition_->set_channel_fsm(std::move(channel_fsm)); - } - - /*! - * \brief Set Doppler center for the grid search - */ - void set_doppler_center(int doppler_center) override; - - /*! - * \brief Returns the maximum peak of grid search - */ - signed int mag() override; - - /*! - * \brief Restart acquisition algorithm - */ - void reset() override; - - /*! - * \brief Stop running acquisition - */ - void stop_acquisition() override; - - /*! - * \brief Sets the resampler latency to account it in the acquisition code delay estimation - */ - void set_resampler_latency(uint32_t latency_samples) override; - - /*! - * \brief Sets local code - */ - void set_local_code() override; - -private: - /*! - * \brief Generate code - */ - virtual void code_gen_complex_sampled(own::span> dest, uint32_t prn, int32_t sampling_freq) = 0; - - const Acq_Conf acq_parameters_; - gr::blocks::float_to_complex::sptr float_to_complex_; - complex_byte_to_float_x2_sptr cbyte_to_float_x2_; - Gnss_Synchro* gnss_synchro_; - const std::string role_; - const unsigned int vector_length_; - const unsigned int code_length_; - volk_gnsssdr::vector> code_; - pcps_acquisition_sptr acquisition_; -}; - - -/** \} */ -/** \} */ -#endif // GNSS_SDR_BASE_PCPS_ACQUISITION_H diff --git a/src/algorithms/acquisition/adapters/beidou_b1c_pcps_ambiguous_acquisition.cc b/src/algorithms/acquisition/adapters/beidou_b1c_pcps_ambiguous_acquisition.cc deleted file mode 100644 index 456195c20..000000000 --- a/src/algorithms/acquisition/adapters/beidou_b1c_pcps_ambiguous_acquisition.cc +++ /dev/null @@ -1,64 +0,0 @@ -/*! - * \file beidou_b1c_pcps_ambiguous_acquisition.cc - * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for - * BeiDou B1C Signals - * \author GNSS-SDR contributors - * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - -#include "beidou_b1c_pcps_ambiguous_acquisition.h" -#include "Beidou_B1C.h" -#include "beidou_b1c_signal_replica.h" - -BeidouB1cPcpsAmbiguousAcquisition::BeidouB1cPcpsAmbiguousAcquisition( - const ConfigurationInterface* configuration, - const std::string& role, - unsigned int in_streams, - unsigned int out_streams) - : BasePcpsAcquisition(configuration, - role, - in_streams, - out_streams, - BEIDOU_B1C_CODE_RATE_CPS, - BEIDOU_B1C_OPT_ACQ_FS_SPS, - BEIDOU_B1C_CODE_LENGTH_CHIPS, - BEIDOU_B1C_CODE_PERIOD_MS), - acquire_pilot_(configuration->property(role + ".acquire_pilot", true)), - qmboc_(configuration->property(role + ".qmboc", true)), - gnss_synchro_(nullptr) -{ -} - - -void BeidouB1cPcpsAmbiguousAcquisition::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) -{ - gnss_synchro_ = p_gnss_synchro; - BasePcpsAcquisition::set_gnss_synchro(p_gnss_synchro); -} - - -void BeidouB1cPcpsAmbiguousAcquisition::code_gen_complex_sampled(own::span> dest, uint32_t prn, int32_t sampling_freq) -{ - if (acquire_pilot_) - { - const std::array pilot_signal = {{'1', 'P', '\0'}}; - beidou_b1c_code_gen_complex_sampled(dest, pilot_signal, qmboc_, prn, sampling_freq, 0, false); - } - else - { - std::array signal_id{}; - signal_id[0] = gnss_synchro_->Signal[0]; - signal_id[1] = gnss_synchro_->Signal[1]; - signal_id[2] = '\0'; - beidou_b1c_code_gen_complex_sampled(dest, signal_id, qmboc_, prn, sampling_freq, 0, false); - } -} diff --git a/src/algorithms/acquisition/adapters/beidou_b1c_pcps_ambiguous_acquisition.h b/src/algorithms/acquisition/adapters/beidou_b1c_pcps_ambiguous_acquisition.h deleted file mode 100644 index 5dbde5879..000000000 --- a/src/algorithms/acquisition/adapters/beidou_b1c_pcps_ambiguous_acquisition.h +++ /dev/null @@ -1,56 +0,0 @@ -/*! - * \file beidou_b1c_pcps_ambiguous_acquisition.h - * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for - * BeiDou B1C Signals - * \author GNSS-SDR contributors - * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_BEIDOU_B1C_PCPS_AMBIGUOUS_ACQUISITION_H -#define GNSS_SDR_BEIDOU_B1C_PCPS_AMBIGUOUS_ACQUISITION_H - -#include "base_pcps_acquisition.h" - -/** \addtogroup Acquisition - * \{ */ -/** \addtogroup Acq_adapters - * \{ */ - -class BeidouB1cPcpsAmbiguousAcquisition : public BasePcpsAcquisition -{ -public: - BeidouB1cPcpsAmbiguousAcquisition( - const ConfigurationInterface* configuration, - const std::string& role, - unsigned int in_streams, - unsigned int out_streams); - - ~BeidouB1cPcpsAmbiguousAcquisition() override = default; - - inline std::string implementation() override - { - return "BEIDOU_B1C_PCPS_Ambiguous_Acquisition"; - } - - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; - -private: - void code_gen_complex_sampled(own::span> dest, uint32_t prn, int32_t sampling_freq) override; - - const bool acquire_pilot_; - const bool qmboc_; - Gnss_Synchro* gnss_synchro_; -}; - -/** \} */ -/** \} */ -#endif // GNSS_SDR_BEIDOU_B1C_PCPS_AMBIGUOUS_ACQUISITION_H diff --git a/src/algorithms/acquisition/adapters/pcps_acquisition_adapter.cc b/src/algorithms/acquisition/adapters/pcps_acquisition_adapter.cc index 4aa99d0ff..3591fc4f3 100644 --- a/src/algorithms/acquisition/adapters/pcps_acquisition_adapter.cc +++ b/src/algorithms/acquisition/adapters/pcps_acquisition_adapter.cc @@ -1,5 +1,5 @@ /*! - * \file base_ca_pcps_acquisition.h + * \file pcps_acquisition_adapter.cc * \brief Adapts a PCPS acquisition block to an AcquisitionInterface * \authors
    *
  • Mathieu Favreau, 2025. favreau.mathieu(at)hotmail.com @@ -17,6 +17,7 @@ */ #include "pcps_acquisition_adapter.h" +#include "Beidou_B1C.h" #include "Beidou_B1I.h" #include "Beidou_B3I.h" #include "GLONASS_L1_L2_CA.h" @@ -28,6 +29,7 @@ #include "Galileo_E5b.h" #include "Galileo_E6.h" #include "acq_conf.h" +#include "beidou_b1c_signal_replica.h" #include "beidou_b1i_signal_replica.h" #include "beidou_b3i_signal_replica.h" #include "configuration_interface.h" @@ -96,6 +98,8 @@ signal_info get_signal_info(signal_flag sig_flag) return {BEIDOU_B1I_CODE_RATE_CPS, BEIDOU_B1I_OPT_ACQ_FS_SPS, BEIDOU_B1I_CODE_LENGTH_CHIPS, BEIDOU_B1I_CODE_PERIOD_MS}; case BDS_B3: return {BEIDOU_B3I_CODE_RATE_CPS, BEIDOU_B3I_OPT_ACQ_FS_SPS, BEIDOU_B3I_CODE_LENGTH_CHIPS, BEIDOU_B3I_CODE_PERIOD_MS}; + case BDS_B1C: + return {BEIDOU_B1C_CODE_RATE_CPS, BEIDOU_B1C_OPT_ACQ_FS_SPS, BEIDOU_B1C_CODE_LENGTH_CHIPS, BEIDOU_B1C_CODE_PERIOD_MS}; case QZS_J1: return {QZSS_L1_CHIP_RATE, QZSS_L1_OPT_ACQ_FS_SPS, QZSS_L1_CODE_LENGTH, QZSS_L1_PERIOD_MS}; case QZS_J5: @@ -174,6 +178,12 @@ void code_gen_complex_sampled(signal_flag sig_flag, const Acq_Conf& conf, const case BDS_B3: beidou_b3i_code_gen_complex_sampled(dest, gnss_synchro.PRN, sampling_freq, 0); break; + case BDS_B1C: + { + const auto sig = conf.acquire_pilot ? std::array{'1', 'P', '\0'} : std::array{gnss_synchro.Signal[0], gnss_synchro.Signal[1], '\0'}; + beidou_b1c_code_gen_complex_sampled(dest, sig, conf.qmboc, gnss_synchro.PRN, sampling_freq, 0, false); + } + break; case QZS_J1: qzss_l1_code_gen_complex_sampled(dest, gnss_synchro.PRN, sampling_freq); break; @@ -207,6 +217,12 @@ Acq_Conf get_acq_conf(const ConfigurationInterface* configuration, const std::st acq_parameters.acquire_iq = configuration->property(role + ".acquire_iq", acq_parameters.acquire_iq); } + if (sig_flag == BDS_B1C) + { + acq_parameters.acquire_pilot = configuration->property(role + ".acquire_pilot", true); + acq_parameters.qmboc = configuration->property(role + ".qmboc", true); + } + #if USE_GLOG_AND_GFLAGS if (FLAGS_doppler_max != 0) { diff --git a/src/algorithms/acquisition/libs/acq_conf.h b/src/algorithms/acquisition/libs/acq_conf.h index 2d8b0e2c7..ed79988b4 100644 --- a/src/algorithms/acquisition/libs/acq_conf.h +++ b/src/algorithms/acquisition/libs/acq_conf.h @@ -79,6 +79,7 @@ public: bool acquire_pilot{false}; bool acquire_iq{false}; bool cboc{false}; + bool qmboc{false}; int zero_padding{0}; uint32_t folding_factor{0}; diff --git a/src/algorithms/libs/beidou_b1c_signal_replica.cc b/src/algorithms/libs/beidou_b1c_signal_replica.cc index 9833b19c7..8e1dc1aff 100644 --- a/src/algorithms/libs/beidou_b1c_signal_replica.cc +++ b/src/algorithms/libs/beidou_b1c_signal_replica.cc @@ -1,7 +1,7 @@ /*! * \file beidou_b1c_signal_replica.cc * \brief Library for BeiDou B1C signal replica generation - * \author GNSS-SDR contributors + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn * * Primary codes loaded from precomputed hex tables (Galileo E1 style). * Pilot secondary codes from per-PRN binary strings (Galileo E5a-Q style). @@ -12,12 +12,11 @@ * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * - * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- */ - #include "beidou_b1c_signal_replica.h" #include "Beidou_B1C.h" #include "gnss_signal_replica.h" diff --git a/src/algorithms/libs/beidou_b1c_signal_replica.h b/src/algorithms/libs/beidou_b1c_signal_replica.h index 8ee1ca601..8f61f2f04 100644 --- a/src/algorithms/libs/beidou_b1c_signal_replica.h +++ b/src/algorithms/libs/beidou_b1c_signal_replica.h @@ -1,19 +1,18 @@ /*! * \file beidou_b1c_signal_replica.h * \brief Library for BeiDou B1C signal replica generation - * \author GNSS-SDR contributors + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn * * ----------------------------------------------------------------------------- * * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * - * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- */ - #ifndef GNSS_SDR_BEIDOU_B1C_SIGNAL_REPLICA_H #define GNSS_SDR_BEIDOU_B1C_SIGNAL_REPLICA_H diff --git a/src/algorithms/libs/rtklib/rtklib_conversions.cc b/src/algorithms/libs/rtklib/rtklib_conversions.cc index 9de123945..3cd780e75 100644 --- a/src/algorithms/libs/rtklib/rtklib_conversions.cc +++ b/src/algorithms/libs/rtklib/rtklib_conversions.cc @@ -754,6 +754,7 @@ eph_t eph_to_rtklib(const Beidou_Cnav1_Ephemeris& bei_eph) rtklib_sat.f0 = bei_eph.af0; rtklib_sat.f1 = bei_eph.af1; rtklib_sat.f2 = bei_eph.af2; + /* ICD §7.6 → gettgd(): tgd[0]=TGD_B1Cp, tgd[1]=TGD_B2ap, tgd[2]=ISC_B1Cd */ rtklib_sat.tgd[0] = bei_eph.TGD_B1Cp; rtklib_sat.tgd[1] = bei_eph.TGD_B2ap; rtklib_sat.tgd[2] = bei_eph.ISC_B1Cd; diff --git a/src/algorithms/libs/rtklib/rtklib_ephemeris.cc b/src/algorithms/libs/rtklib/rtklib_ephemeris.cc index 4b76878c7..080e09e33 100644 --- a/src/algorithms/libs/rtklib/rtklib_ephemeris.cc +++ b/src/algorithms/libs/rtklib/rtklib_ephemeris.cc @@ -405,6 +405,7 @@ void eph2pos(gtime_t time, const eph_t *eph, double *rs, double *dts, omge = GNSS_OMEGA_EARTH_DOT; break; } + const int is_bds_cnav1 = (sys == SYS_BDS && eph->code == 7) ? 1 : 0; Ak = eph->A + eph->Adot * tk; delta_na = eph->deln + 0.5 * eph->ndot * tk; na = sqrt(mu / (eph->A * eph->A * eph->A)) + delta_na; @@ -437,8 +438,8 @@ void eph2pos(gtime_t time, const eph_t *eph, double *rs, double *dts, y = r * sin(u); cosi = cos(i); - /* beidou geo satellite (ref [9]) */ - if (sys == SYS_BDS && (prn <= 5 || prn > 58)) + /* BeiDou GEO 5° transform is DNAV-only (B1I ICD). B-CNAV1 Table 7-9 is MEO/IGSO only */ + if (sys == SYS_BDS && !is_bds_cnav1 && (prn <= 5 || prn > 58)) { O = eph->OMG0 + eph->OMGd * tk - omge * eph->toes; sinO = sin(O); @@ -554,7 +555,10 @@ void eph2pos(gtime_t time, const eph_t *eph, double *rs, double *dts, } else { - *dts -= 2.0 * sqrt(mu * A) * eph->e * sinE / (SPEED_OF_LIGHT_M_S * SPEED_OF_LIGHT_M_S); + /* ICD B1C (7-3): Δtr = F·e·√A0·sin(Ek); F = -2√μ/c². + * Use reference semi-major axis A0 for B-CNAV1 (not Ak). */ + const double A_rel = is_bds_cnav1 ? A0 : A; + *dts -= 2.0 * sqrt(mu * A_rel) * eph->e * sinE / (SPEED_OF_LIGHT_M_S * SPEED_OF_LIGHT_M_S); } /* position and clock error variance */ diff --git a/src/algorithms/libs/rtklib/rtklib_pntpos.cc b/src/algorithms/libs/rtklib/rtklib_pntpos.cc index cdb7184c2..ff46eb3f7 100644 --- a/src/algorithms/libs/rtklib/rtklib_pntpos.cc +++ b/src/algorithms/libs/rtklib/rtklib_pntpos.cc @@ -112,45 +112,49 @@ double gettgd(int sat, const nav_t *nav) /* get tgd parameter (m) ----------------------------------------------------- - * BDS DNAV: tgd[0]=TGD1 - * BDS CNAV1 (code==7): tgd[0]=TGD_B1Cp, tgd[2]=ISC_B1Cd (ICD B1C §7.6) - * For B1C data (CODE_L1D) apply TGD_B1Cp+ISC_B1Cd; for pilot (CODE_L1P) TGD_B1Cp only. + * GPS/QZS/GAL: return c·tgd[0] from the first matching ephemeris (classic RTKLIB). + * BDS DNAV (eph.code!=7): tgd[0]=TGD1 (B1I vs B3I timing reference) + * BDS CNAV1 (eph.code==7), stored by eph_to_rtklib(Beidou_Cnav1_Ephemeris): + * tgd[0]=TGD_B1Cp, tgd[1]=TGD_B2ap, tgd[2]=ISC_B1Cd (ICD B1C §7.6) + * BDS user algorithm (applied in prange as PC = P - c·Δt_TGD): + * B1C pilot CODE_L1P: (Δtsv)_B1Cp = Δtsv - TGD_B1Cp → (7-4) + * B1C data CODE_L1D: (Δtsv)_B1Cd = Δtsv - TGD_B1Cp - ISC_B1Cd → (7-5) + * B1I (CODE_L2I/L1I): use DNAV TGD1; B3I skips TGD in prange. + * NOTE: CODE_L1P is also GPS/GLO L1P in RINEX — CNAV1 selection is SYS_BDS only. + * Do not fall back across DNAV↔CNAV1: TGD1 and TGD_B1Cp are different quantities. *-----------------------------------------------------------------------------*/ double gettgd(int sat, const nav_t *nav, unsigned char obs_code) { int i; - const int prefer_cnav1 = (obs_code == CODE_L1D || obs_code == CODE_L1P) ? 1 : 0; - int fallback = -1; + int prn = 0; + const int sys = satsys(sat, &prn); + const int is_b1c_obs = (obs_code == CODE_L1D || obs_code == CODE_L1P) ? 1 : 0; + for (i = 0; i < nav->n; i++) { if (nav->eph[i].sat != sat) { continue; } - const int is_cnav1 = (nav->eph[i].code == 7) ? 1 : 0; - if (prefer_cnav1 != is_cnav1) + + if (sys == SYS_BDS) { - if (fallback < 0) + const int is_cnav1 = (nav->eph[i].code == 7) ? 1 : 0; + /* B1C obs ↔ CNAV1 eph; B1I/other ↔ DNAV eph */ + if (is_b1c_obs != is_cnav1) { - fallback = i; + continue; } - continue; + double tgd_s = nav->eph[i].tgd[0]; + if (is_cnav1 && obs_code == CODE_L1D) + { + tgd_s += nav->eph[i].tgd[2]; + } + return SPEED_OF_LIGHT_M_S * tgd_s; } - double tgd_s = nav->eph[i].tgd[0]; - if (is_cnav1 && obs_code == CODE_L1D) - { - tgd_s += nav->eph[i].tgd[2]; - } - return SPEED_OF_LIGHT_M_S * tgd_s; - } - if (fallback >= 0) - { - double tgd_s = nav->eph[fallback].tgd[0]; - if (nav->eph[fallback].code == 7 && obs_code == CODE_L1D) - { - tgd_s += nav->eph[fallback].tgd[2]; - } - return SPEED_OF_LIGHT_M_S * tgd_s; + + /* GPS/GAL/QZS/... : first ephemeris for this sat */ + return SPEED_OF_LIGHT_M_S * nav->eph[i].tgd[0]; } return 0.0; } diff --git a/src/algorithms/observables/adapters/hybrid_observables.cc b/src/algorithms/observables/adapters/hybrid_observables.cc index a08ecaea1..d466b5a3a 100644 --- a/src/algorithms/observables/adapters/hybrid_observables.cc +++ b/src/algorithms/observables/adapters/hybrid_observables.cc @@ -51,6 +51,7 @@ HybridObservables::HybridObservables(const ConfigurationInterface* configuration conf.always_output_gs = configuration->property("PVT.an_output_enabled", conf.always_output_gs) || configuration->property(role + ".always_output_gs", conf.always_output_gs); conf.enable_E6 = configuration->property(role + ".enable_E6", conf.enable_E6); conf.enable_monitor = configuration->property("Monitor.enable_monitor", conf.enable_monitor); + conf.reject_outlier_pseudoranges = configuration->property(role + ".reject_outlier_pseudoranges", conf.reject_outlier_pseudoranges); #if USE_GLOG_AND_GFLAGS if (FLAGS_carrier_smoothing_factor == DEFAULT_CARRIER_SMOOTHING_FACTOR) diff --git a/src/algorithms/observables/gnuradio_blocks/hybrid_observables_gs.cc b/src/algorithms/observables/gnuradio_blocks/hybrid_observables_gs.cc index ee4df9cb4..7964d4036 100644 --- a/src/algorithms/observables/gnuradio_blocks/hybrid_observables_gs.cc +++ b/src/algorithms/observables/gnuradio_blocks/hybrid_observables_gs.cc @@ -598,11 +598,8 @@ void hybrid_observables_gs::compute_pranges(std::vector &data) con std::vector::iterator it; const auto current_T_rx_TOW_ms = static_cast(d_T_rx_TOW_ms); const double current_T_rx_TOW_s = current_T_rx_TOW_ms / 1000.0; - // RX TOW is initialized from the latest satellite transmit TOW, so absolute - // travel times are often far below the physical ~60–90 ms (common bias → clock). - // Only reject clearly impossible values (negative / multi-second). - constexpr double min_travel_ms = 1.0; - constexpr double max_travel_ms = 500.0; + double min_abs = 1e30; + double min_pseudorange = 0.0; for (it = data.begin(); it != data.end(); it++) { if (it->Flag_valid_word) @@ -613,18 +610,12 @@ void hybrid_observables_gs::compute_pranges(std::vector &data) con traveltime_ms = 604800000.0 + current_T_rx_TOW_ms - it->interp_TOW_ms; } it->RX_time = current_T_rx_TOW_s; - if (traveltime_ms >= min_travel_ms && traveltime_ms <= max_travel_ms) + it->Pseudorange_m = traveltime_ms * SPEED_OF_LIGHT_M_MS; + it->Flag_valid_pseudorange = true; + if (d_conf.reject_outlier_pseudoranges && (std::abs(it->Pseudorange_m) < min_abs)) { - it->Pseudorange_m = traveltime_ms * SPEED_OF_LIGHT_M_MS; - it->Flag_valid_pseudorange = true; - } - else - { - it->Pseudorange_m = 0.0; - it->Flag_valid_pseudorange = false; - DLOG(INFO) << "Reject absurd travel time " << traveltime_ms - << " ms on ch " << it->Channel_ID << " PRN " << it->PRN - << " Signal " << it->Signal; + min_pseudorange = it->Pseudorange_m; + min_abs = std::abs(it->Pseudorange_m); } // debug code // std::cout << "[" << it->Channel_ID << "] interp_TOW_ms: " << it->interp_TOW_ms << '\n'; @@ -635,6 +626,17 @@ void hybrid_observables_gs::compute_pranges(std::vector &data) con it->RX_time = current_T_rx_TOW_s; } } + if (d_conf.reject_outlier_pseudoranges) + { + // Reject satellites whose pseudorange differs from the nearest-to-zero + for (it = data.begin(); it != data.end(); it++) + { + if (it->Flag_valid_pseudorange && (std::abs(it->Pseudorange_m - min_pseudorange) > 1e8)) + { + it->Flag_valid_pseudorange = false; + } + } + } } diff --git a/src/algorithms/observables/libs/obs_conf.h b/src/algorithms/observables/libs/obs_conf.h index f177da077..84605d0e6 100644 --- a/src/algorithms/observables/libs/obs_conf.h +++ b/src/algorithms/observables/libs/obs_conf.h @@ -43,6 +43,7 @@ public: bool dump_mat{false}; bool enable_E6{true}; bool enable_monitor{false}; + bool reject_outlier_pseudoranges{true}; }; /** \} */ diff --git a/src/algorithms/telemetry_decoder/adapters/CMakeLists.txt b/src/algorithms/telemetry_decoder/adapters/CMakeLists.txt index 71e1d30a3..bd198243e 100644 --- a/src/algorithms/telemetry_decoder/adapters/CMakeLists.txt +++ b/src/algorithms/telemetry_decoder/adapters/CMakeLists.txt @@ -7,14 +7,10 @@ set(TELEMETRY_DECODER_ADAPTER_SOURCES telemetry_decoder_adapter.cc - telemetry_decoder_adapter_base.cc - beidou_b1c_telemetry_decoder.cc ) set(TELEMETRY_DECODER_ADAPTER_HEADERS telemetry_decoder_adapter.h - telemetry_decoder_adapter_base.h - beidou_b1c_telemetry_decoder.h ) list(SORT TELEMETRY_DECODER_ADAPTER_HEADERS) diff --git a/src/algorithms/telemetry_decoder/adapters/beidou_b1c_telemetry_decoder.cc b/src/algorithms/telemetry_decoder/adapters/beidou_b1c_telemetry_decoder.cc deleted file mode 100644 index fd6c9336f..000000000 --- a/src/algorithms/telemetry_decoder/adapters/beidou_b1c_telemetry_decoder.cc +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * \file beidou_b1c_telemetry_decoder.cc - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -#include "beidou_b1c_telemetry_decoder.h" -#include "beidou_b1c_telemetry_decoder_gs.h" - -BeidouB1cTelemetryDecoder::BeidouB1cTelemetryDecoder( - const ConfigurationInterface* configuration, - const std::string& role, - unsigned int in_streams, - unsigned int out_streams) - : TelemetryDecoderAdapterBase(configuration, role, in_streams, out_streams) -{ - InitializeDecoder(beidou_b1c_make_telemetry_decoder_gs(satellite(), tlm_parameters_)); -} diff --git a/src/algorithms/telemetry_decoder/adapters/beidou_b1c_telemetry_decoder.h b/src/algorithms/telemetry_decoder/adapters/beidou_b1c_telemetry_decoder.h deleted file mode 100644 index 9e81b5536..000000000 --- a/src/algorithms/telemetry_decoder/adapters/beidou_b1c_telemetry_decoder.h +++ /dev/null @@ -1,25 +0,0 @@ -/*! - * \file beidou_b1c_telemetry_decoder.h - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -#ifndef GNSS_SDR_BEIDOU_B1C_TELEMETRY_DECODER_H -#define GNSS_SDR_BEIDOU_B1C_TELEMETRY_DECODER_H - -#include "telemetry_decoder_adapter_base.h" - -class BeidouB1cTelemetryDecoder : public TelemetryDecoderAdapterBase -{ -public: - BeidouB1cTelemetryDecoder(const ConfigurationInterface* configuration, - const std::string& role, - unsigned int in_streams, - unsigned int out_streams); - - inline std::string implementation() override - { - return "BEIDOU_B1C_Telemetry_Decoder"; - } -}; - -#endif diff --git a/src/algorithms/telemetry_decoder/adapters/telemetry_decoder_adapter_base.cc b/src/algorithms/telemetry_decoder/adapters/telemetry_decoder_adapter_base.cc deleted file mode 100644 index 1832efd86..000000000 --- a/src/algorithms/telemetry_decoder/adapters/telemetry_decoder_adapter_base.cc +++ /dev/null @@ -1,135 +0,0 @@ -/*! - * \file telemetry_decoder_adapter_base.cc - * \brief Common functionality for telemetry decoder adapters - * \author Carles Fernandez-Prades, 2025 cfernandez@cttc.es - * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2025 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - - -#include "telemetry_decoder_adapter_base.h" -#include - -#if USE_GLOG_AND_GFLAGS -#include -#else -#include -#endif - - -TelemetryDecoderAdapterBase::TelemetryDecoderAdapterBase(const ConfigurationInterface* configuration, - const std::string& role, - unsigned int in_streams, - unsigned int out_streams) : role_(role), - in_streams_(in_streams), - out_streams_(out_streams) -{ - DLOG(INFO) << "role " << role_; - if (configuration != nullptr) - { - tlm_parameters_.SetFromConfiguration(configuration, role_); - } - if (in_streams_ > 1) - { - LOG(ERROR) << "This implementation only supports one input stream (" - << in_streams_ << " provided)"; - } - if (out_streams_ > 1) - { - LOG(ERROR) << "This implementation only supports one output stream (" - << out_streams_ << " provided)"; - } -} - - -void TelemetryDecoderAdapterBase::InitializeDecoder(telemetry_impl_interface_sptr decoder) -{ - telemetry_decoder_ = std::move(decoder); - DLOG(INFO) << "telemetry_decoder(" << telemetry_decoder_->unique_id() << ")"; -} - - -void TelemetryDecoderAdapterBase::connect(gr::top_block_sptr top_block) -{ - if (top_block) - { - /* top_block is not null */ - } - DLOG(INFO) << "nothing to connect internally"; -} - - -void TelemetryDecoderAdapterBase::disconnect(gr::top_block_sptr top_block) -{ - if (top_block) - { - /* top_block is not null */ - } -} - - -gr::basic_block_sptr TelemetryDecoderAdapterBase::get_left_block() -{ - return telemetry_decoder_; -} - - -gr::basic_block_sptr TelemetryDecoderAdapterBase::get_right_block() -{ - return telemetry_decoder_; -} - - -void TelemetryDecoderAdapterBase::set_satellite(const Gnss_Satellite& satellite) -{ - satellite_ = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); - if (telemetry_decoder_) - { - telemetry_decoder_->set_satellite(satellite_); - DLOG(INFO) << "TELEMETRY DECODER: satellite set to " << satellite_; - } -} - - -std::string TelemetryDecoderAdapterBase::role() -{ - return role_; -} - - -void TelemetryDecoderAdapterBase::set_channel(int channel) -{ - if (telemetry_decoder_) - { - telemetry_decoder_->set_channel(channel); - } -} - - -void TelemetryDecoderAdapterBase::reset() -{ - if (telemetry_decoder_) - { - telemetry_decoder_->reset(); - } -} - - -size_t TelemetryDecoderAdapterBase::item_size() -{ - return sizeof(Gnss_Synchro); -} - - -const Gnss_Satellite& TelemetryDecoderAdapterBase::satellite() const -{ - return satellite_; -} \ No newline at end of file diff --git a/src/algorithms/telemetry_decoder/adapters/telemetry_decoder_adapter_base.h b/src/algorithms/telemetry_decoder/adapters/telemetry_decoder_adapter_base.h deleted file mode 100644 index 20edfad7f..000000000 --- a/src/algorithms/telemetry_decoder/adapters/telemetry_decoder_adapter_base.h +++ /dev/null @@ -1,88 +0,0 @@ -/*! - * \file telemetry_decoder_adapter_base.h - * \brief Common functionality for telemetry decoder adapters - * \author Carles Fernandez-Prades, 2025 cfernandez@cttc.es - * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2025 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_TELEMETRY_DECODER_ADAPTER_BASE_CLASS_H -#define GNSS_SDR_TELEMETRY_DECODER_ADAPTER_BASE_CLASS_H - -#include "configuration_interface.h" -#include "gnss_satellite.h" -#include "gnss_synchro.h" -#include "telemetry_decoder_interface.h" -#include "telemetry_impl_interface.h" -#include "tlm_conf.h" -#include -#include -#include - -class ConfigurationInterface; - -/** \addtogroup Telemetry_Decoder - * \{ - */ -/** \addtogroup Telemetry_Decoder_adapters - * \{ - */ - -/*! - * \brief Base class for Telemetry Decoder adapters - */ -class TelemetryDecoderAdapterBase : public TelemetryDecoderInterface -{ -public: - TelemetryDecoderAdapterBase(const ConfigurationInterface* configuration, - const std::string& role, - unsigned int in_streams, - unsigned int out_streams); - - ~TelemetryDecoderAdapterBase() override = default; - - void connect(gr::top_block_sptr top_block) override; - - void disconnect(gr::top_block_sptr top_block) override; - - gr::basic_block_sptr get_left_block() override; - - gr::basic_block_sptr get_right_block() override; - - void set_satellite(const Gnss_Satellite& satellite) override; - - std::string role() override; - - void set_channel(int channel) override; - - void reset() override; - - size_t item_size() override; - -protected: - void InitializeDecoder(telemetry_impl_interface_sptr decoder); - - const Gnss_Satellite& satellite() const; - - Tlm_Conf tlm_parameters_; - -private: - telemetry_impl_interface_sptr telemetry_decoder_; - Gnss_Satellite satellite_; - std::string role_; - unsigned int in_streams_ = 0; - unsigned int out_streams_ = 0; -}; - -/** \} */ -/** \} */ - -#endif // GNSS_SDR_TELEMETRY_DECODER_ADAPTER_BASE_CLASS_H diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b1c_telemetry_decoder_gs.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b1c_telemetry_decoder_gs.cc index 0305d50b5..4b9db94a2 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b1c_telemetry_decoder_gs.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b1c_telemetry_decoder_gs.cc @@ -1,9 +1,18 @@ /*! * \file beidou_b1c_telemetry_decoder_gs.cc * \brief BeiDou B1C B-CNAV1 telemetry decoder block + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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 "beidou_b1c_telemetry_decoder_gs.h" #include "Beidou_B1C.h" #include "Beidou_B1C_codes.h" @@ -138,18 +147,18 @@ bool apply_llr_scale_and_decode( { const int32_t n = BEIDOU_CNAV1_FRAME_SYMBOLS; double rms_acc = 0.0; - for (size_t i = 0; i < frame.size(); ++i) + for (float sample : frame) { - const double v = static_cast(frame[i]); + const auto v = static_cast(sample); rms_acc += v * v; } const double rms = std::sqrt(rms_acc / static_cast(n)) + 1e-6; const double cn0_linear = std::pow(10.0, static_cast(cn0_db_hz) / 10.0); const double snr_sym = std::max(cn0_linear * (BEIDOU_B1C_CODE_PERIOD_MS * 1e-3), 1e-4); const double llr_scale = std::min(std::max(std::sqrt(snr_sym) / rms, 0.05), 50.0); - for (size_t i = 0; i < frame.size(); ++i) + for (float& sample : frame) { - frame[i] = static_cast(static_cast(frame[i]) * llr_scale); + sample = static_cast(static_cast(sample) * llr_scale); } return nav.decode_frame_symbols(frame.data(), BEIDOU_CNAV1_FRAME_SYMBOLS, expected_prn, fail_stage); } @@ -469,9 +478,8 @@ int beidou_b1c_telemetry_decoder_gs::general_work( if (!candidate_offsets.empty()) { - for (size_t cidx = 0; cidx < candidate_offsets.size(); ++cidx) + for (int32_t candidate_offset : candidate_offsets) { - const int32_t candidate_offset = candidate_offsets[cidx]; for (int32_t delta = -local_offset_span; delta <= local_offset_span; delta++) { const int32_t start_offset = diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b1c_telemetry_decoder_gs.h b/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b1c_telemetry_decoder_gs.h index cd76809f9..10dbb1a5d 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b1c_telemetry_decoder_gs.h +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b1c_telemetry_decoder_gs.h @@ -1,9 +1,18 @@ /*! * \file beidou_b1c_telemetry_decoder_gs.h * \brief BeiDou B1C B-CNAV1 telemetry decoder block + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_B1C_TELEMETRY_DECODER_GS_H #define GNSS_SDR_BEIDOU_B1C_TELEMETRY_DECODER_GS_H diff --git a/src/algorithms/tracking/adapters/CMakeLists.txt b/src/algorithms/tracking/adapters/CMakeLists.txt index 449dc723b..97ee94048 100644 --- a/src/algorithms/tracking/adapters/CMakeLists.txt +++ b/src/algorithms/tracking/adapters/CMakeLists.txt @@ -28,8 +28,6 @@ endif() set(TRACKING_ADAPTER_SOURCES dll_pll_tracking_adapter.cc - base_dll_pll_tracking.cc - beidou_b1c_dll_pll_veml_tracking.cc galileo_e1_tcp_connector_tracking.cc gps_l1_ca_tcp_connector_tracking.cc gps_l1_ca_gaussian_tracking.cc @@ -39,8 +37,6 @@ set(TRACKING_ADAPTER_SOURCES set(TRACKING_ADAPTER_HEADERS dll_pll_tracking_adapter.h - base_dll_pll_tracking.h - beidou_b1c_dll_pll_veml_tracking.h galileo_e1_tcp_connector_tracking.h gps_l1_ca_tcp_connector_tracking.h gps_l1_ca_gaussian_tracking.h diff --git a/src/algorithms/tracking/adapters/base_dll_pll_tracking.cc b/src/algorithms/tracking/adapters/base_dll_pll_tracking.cc deleted file mode 100644 index 957d3b968..000000000 --- a/src/algorithms/tracking/adapters/base_dll_pll_tracking.cc +++ /dev/null @@ -1,98 +0,0 @@ -/*! - * \file base_dll_pll_tracking.cc - * \brief Base class providing shared logic for DLL+PLL VEML tracking adapters. - * \authors Carles Fernandez, 2025. carles.fernandez(at)cttc.cat - * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2025 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - -#include "base_dll_pll_tracking.h" -#include "configuration_interface.h" - -#if USE_GLOG_AND_GFLAGS -#include -#else -#include -#endif - -BaseDllPllTracking::BaseDllPllTracking( - const ConfigurationInterface* configuration, - std::string role, - unsigned int in_streams, - unsigned int out_streams) - : role_(std::move(role)), - item_size_(sizeof(gr_complex)) -{ - trk_params_.SetFromConfiguration(configuration, role_); - - if (in_streams > 1) - { - LOG(ERROR) << "Only one input stream is supported."; - } - if (out_streams > 1) - { - LOG(ERROR) << "Only one output stream is supported."; - } - - DLOG(INFO) << "role " << role_; -} - - -void BaseDllPllTracking::connect(gr::top_block_sptr top_block) -{ - if (top_block) - { /* no connection needed */ - } -} - - -void BaseDllPllTracking::disconnect(gr::top_block_sptr top_block) -{ - if (top_block) - { /* no disconnection needed */ - } -} - - -gr::basic_block_sptr BaseDllPllTracking::get_left_block() -{ - return tracking_sptr_; -} - - -gr::basic_block_sptr BaseDllPllTracking::get_right_block() -{ - return tracking_sptr_; -} - - -void BaseDllPllTracking::set_channel(unsigned int channel) -{ - tracking_sptr_->set_channel(channel); -} - - -void BaseDllPllTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) -{ - tracking_sptr_->set_gnss_synchro(p_gnss_synchro); -} - - -void BaseDllPllTracking::start_tracking() -{ - tracking_sptr_->start_tracking(); -} - - -void BaseDllPllTracking::stop_tracking() -{ - tracking_sptr_->stop_tracking(); -} diff --git a/src/algorithms/tracking/adapters/base_dll_pll_tracking.h b/src/algorithms/tracking/adapters/base_dll_pll_tracking.h deleted file mode 100644 index f7890ed5a..000000000 --- a/src/algorithms/tracking/adapters/base_dll_pll_tracking.h +++ /dev/null @@ -1,126 +0,0 @@ -/*! - * \file base_dll_pll_tracking.h - * \brief Base class providing shared logic for DLL+PLL VEML tracking adapters. - * \authors Carles Fernandez, 2025. carles.fernandez(at)cttc.cat - * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2025 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_BASE_DLL_PLL_TRACKING_H -#define GNSS_SDR_BASE_DLL_PLL_TRACKING_H - -#include "dll_pll_conf.h" -#include "dll_pll_veml_tracking.h" -#include "tracking_interface.h" -#include -#include - -/** \addtogroup Tracking - * Classes for GNSS signal tracking. - * \{ */ -/** \addtogroup Tracking_adapters tracking_adapters - * Wrap GNU Radio blocks for GNSS signal tracking with a TrackingInterface - * \{ */ - -class ConfigurationInterface; - -/*! - * \brief Base class providing shared logic for DLL+PLL tracking loop adapters - * for GNSS signals. - */ -class BaseDllPllTracking : public TrackingInterface -{ -public: - /*! - * \brief Base constructor of a Tracking block adapter - */ - explicit BaseDllPllTracking(const ConfigurationInterface* configuration, - std::string role, - unsigned int in_streams, - unsigned int out_streams); - - /*! - * \brief Default destructor of the Tracking block adapter - */ - ~BaseDllPllTracking() override = default; - - /*! - * \brief Get role from the Tracking block adapter - */ - inline std::string role() final { return role_; } - - /*! - * \brief Get item_size from the Tracking block adapter - */ - inline size_t item_size() final { return item_size_; } - - /*! - * \brief Connect the Tracking block adapter - */ - void connect(gr::top_block_sptr top_block) final; - - /*! - * \brief Disconnect the sTracking block adapter - */ - void disconnect(gr::top_block_sptr top_block) final; - - /*! - * \brief Get left block from the Tracking block adapter - */ - gr::basic_block_sptr get_left_block() final; - - /*! - * \brief Get right block from the Tracking block adapter - */ - gr::basic_block_sptr get_right_block() final; - - /*! - * \brief Set tracking channel unique ID - */ - void set_channel(unsigned int channel) final; - - /*! - * \brief Set acquisition Gnss_Synchro object pointer - * to exchange synchronization data between acquisition and tracking blocks - */ - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) final; - - /*! - * \brief Start the Tracking block - */ - void start_tracking() final; - - /*! - * \brief Stop the Tracking block - */ - void stop_tracking() final; - -protected: - // Can be used by each derived class - inline Dll_Pll_Conf& config_params() { return trk_params_; } - inline const Dll_Pll_Conf& config_params() const { return trk_params_; } - inline void set_item_size(size_t item_size) { item_size_ = item_size; } - - // Must be implemented / filled by each derived class - virtual void configure_tracking_parameters(const ConfigurationInterface* configuration) = 0; - virtual void create_tracking_block() = 0; - dll_pll_veml_tracking_sptr tracking_sptr_; - -private: - // Managed by the base class - Dll_Pll_Conf trk_params_; - const std::string role_; - size_t item_size_; -}; - -/** \} */ -/** \} */ -#endif // GNSS_SDR_BASE_DLL_PLL_TRACKING_H diff --git a/src/algorithms/tracking/adapters/beidou_b1c_dll_pll_veml_tracking.cc b/src/algorithms/tracking/adapters/beidou_b1c_dll_pll_veml_tracking.cc deleted file mode 100644 index 5cfc8f362..000000000 --- a/src/algorithms/tracking/adapters/beidou_b1c_dll_pll_veml_tracking.cc +++ /dev/null @@ -1,101 +0,0 @@ -/*! - * \file beidou_b1c_dll_pll_veml_tracking.cc - * \brief Adapts a DLL+PLL VEML tracking loop block to a TrackingInterface - * for BeiDou B1C signals - * \author GNSS-SDR contributors - * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - -#include "beidou_b1c_dll_pll_veml_tracking.h" -#include "Beidou_B1C.h" -#include "configuration_interface.h" -#include "display.h" -#include -#include - -#if USE_GLOG_AND_GFLAGS -#include -#else -#include -#endif - -BeidouB1cDllPllVemlTracking::BeidouB1cDllPllVemlTracking( - const ConfigurationInterface* configuration, - const std::string& role, - unsigned int in_streams, - unsigned int out_streams) - : BaseDllPllTracking(configuration, role, in_streams, out_streams) -{ - configure_tracking_parameters(configuration); - create_tracking_block(); -} - - -void BeidouB1cDllPllVemlTracking::configure_tracking_parameters( - const ConfigurationInterface* configuration [[maybe_unused]]) -{ - config_params().vector_length = static_cast(std::round( - config_params().fs_in / (BEIDOU_B1C_CODE_RATE_CPS / BEIDOU_B1C_CODE_LENGTH_CHIPS))); - config_params().system = 'C'; - const std::array sig{'1', 'D', '\0'}; - std::copy_n(sig.data(), 3, config_params().signal); - const bool acq_qmboc = configuration->property("Acquisition_1D.qmboc", config_params().b1c_qmboc_tracking); - // Keep tracking-side local replica modulation aligned with acquisition by default. - config_params().b1c_qmboc_tracking = configuration->property(role() + ".b1c_qmboc_tracking", acq_qmboc); - - if (config_params().extend_correlation_symbols < 1) - { - config_params().extend_correlation_symbols = 1; - std::cout << TEXT_RED << "WARNING: BeiDou B1C. extend_correlation_symbols must be bigger than 0. Coherent integration has been set to 1 symbol (10 ms)" << TEXT_RESET << '\n'; - } - else if (!config_params().track_pilot && config_params().extend_correlation_symbols > 1) - { - config_params().extend_correlation_symbols = 1; - std::cout << TEXT_RED << "WARNING: BeiDou B1C. Extended coherent integration is not allowed when tracking the data component. Coherent integration has been set to 10 ms (1 symbol)" << TEXT_RESET << '\n'; - } - - // B1C pilot: 1800-chip secondary sync spans one B-CNAV1 frame (18 s). - // Keep coherent integration at 1 symbol (10 ms); extended correlator is not used. - if (config_params().track_pilot) - { - config_params().extend_correlation_symbols = 1; - const auto min_bit_sync_limit_s = static_cast( - BEIDOU_B1C_FRAME_PERIOD_S + 30); - if (config_params().bit_synchronization_time_limit_s < min_bit_sync_limit_s) - { - config_params().bit_synchronization_time_limit_s = min_bit_sync_limit_s; - } - } - - if ((config_params().extend_correlation_symbols > 1) && - (config_params().pll_bw_narrow_hz > config_params().pll_bw_hz || - config_params().dll_bw_narrow_hz > config_params().dll_bw_hz)) - { - std::cout << TEXT_RED << "WARNING: BeiDou B1C. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << '\n'; - } -} - - -void BeidouB1cDllPllVemlTracking::create_tracking_block() -{ - if (config_params().item_type == "gr_complex") - { - tracking_sptr_ = dll_pll_veml_make_tracking(config_params()); - DLOG(INFO) << "tracking(" << tracking_sptr_->unique_id() << ")"; - } - else - { - set_item_size(0); - tracking_sptr_ = nullptr; - LOG(WARNING) << config_params().item_type << " unknown tracking item type."; - } -} diff --git a/src/algorithms/tracking/adapters/beidou_b1c_dll_pll_veml_tracking.h b/src/algorithms/tracking/adapters/beidou_b1c_dll_pll_veml_tracking.h deleted file mode 100644 index 144abc335..000000000 --- a/src/algorithms/tracking/adapters/beidou_b1c_dll_pll_veml_tracking.h +++ /dev/null @@ -1,41 +0,0 @@ -/*! - * \file beidou_b1c_dll_pll_veml_tracking.h - * \brief Adapts a DLL+PLL VEML tracking loop block to a TrackingInterface - * for BeiDou B1C signals - * \author GNSS-SDR contributors - * - * ----------------------------------------------------------------------------- - * - * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. - * This file is part of GNSS-SDR. - * - * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) - * SPDX-License-Identifier: GPL-3.0-or-later - * - * ----------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_BEIDOU_B1C_DLL_PLL_VEML_TRACKING_H -#define GNSS_SDR_BEIDOU_B1C_DLL_PLL_VEML_TRACKING_H - -#include "base_dll_pll_tracking.h" - -class BeidouB1cDllPllVemlTracking : public BaseDllPllTracking -{ -public: - BeidouB1cDllPllVemlTracking(const ConfigurationInterface* configuration, - const std::string& role, - unsigned int in_streams, - unsigned int out_streams); - - inline std::string implementation() override - { - return "BEIDOU_B1C_DLL_PLL_VEML_Tracking"; - } - -private: - void configure_tracking_parameters(const ConfigurationInterface* configuration) override; - void create_tracking_block() override; -}; - -#endif // GNSS_SDR_BEIDOU_B1C_DLL_PLL_VEML_TRACKING_H diff --git a/src/algorithms/tracking/adapters/dll_pll_tracking_adapter.cc b/src/algorithms/tracking/adapters/dll_pll_tracking_adapter.cc index 12e40bf69..1f6168993 100644 --- a/src/algorithms/tracking/adapters/dll_pll_tracking_adapter.cc +++ b/src/algorithms/tracking/adapters/dll_pll_tracking_adapter.cc @@ -15,6 +15,7 @@ */ #include "dll_pll_tracking_adapter.h" +#include "Beidou_B1C.h" #include "Beidou_B1I.h" #include "Beidou_B3I.h" #include "GLONASS_L1_L2_CA.h" @@ -28,6 +29,7 @@ #include "configuration_interface.h" #include "display.h" #include "qzss.h" +#include "signal_flag.h" #if USE_GLOG_AND_GFLAGS #include @@ -76,6 +78,8 @@ signal_info get_signal_info(signal_flag sig_flag) return {'C', {'B', '1', '\0'}, "BEIDOU B1I", BEIDOU_B1I_CODE_RATE_CPS, BEIDOU_B1I_CODE_LENGTH_CHIPS, 20, false, true}; case BDS_B3: return {'C', {'B', '3', '\0'}, "BEIDOU B3I", BEIDOU_B3I_CODE_RATE_CPS, BEIDOU_B3I_CODE_LENGTH_CHIPS, 20, false, false}; // Does false, false make sense? + case BDS_B1C: + return {'C', {'1', 'D', '\0'}, "BeiDou B1C", BEIDOU_B1C_CODE_RATE_CPS, BEIDOU_B1C_CODE_LENGTH_CHIPS, 1, true, false}; case QZS_J1: return {'J', {'J', '1', '\0'}, "QZSS L1 C/A", QZSS_L1_CHIP_RATE, QZSS_L1_CODE_LENGTH, 20, false, true}; case QZS_J5: @@ -87,7 +91,7 @@ signal_info get_signal_info(signal_flag sig_flag) return {}; } -void check_and_configure_trk_params(const ConfigurationInterface* configuration, const std::string& role, const signal_info& sig_info, Dll_Pll_Conf& trk_params) +void check_and_configure_trk_params(const ConfigurationInterface* configuration, const std::string& role, signal_flag sig_flag, const signal_info& sig_info, Dll_Pll_Conf& trk_params) { trk_params.SetFromConfiguration(configuration, role); trk_params.vector_length = static_cast(std::round(trk_params.fs_in / (sig_info.code_chip_rate / sig_info.code_length_chips))); @@ -145,6 +149,24 @@ void check_and_configure_trk_params(const ConfigurationInterface* configuration, { std::cout << TEXT_RED << "WARNING: " << sig_info.sig_name << ". PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << '\n'; } + + if (sig_flag == BDS_B1C) + { + // Keep tracking-side local replica modulation aligned with acquisition by default. + const bool acq_qmboc = configuration->property("Acquisition_1D.qmboc", trk_params.b1c_qmboc_tracking); + trk_params.b1c_qmboc_tracking = configuration->property(role + ".b1c_qmboc_tracking", acq_qmboc); + + // B1C pilot secondary sync spans one B-CNAV1 frame (18 s); keep coherent integration at 1 symbol. + if (trk_params.track_pilot) + { + trk_params.extend_correlation_symbols = 1; + const auto min_bit_sync_limit_s = static_cast(BEIDOU_B1C_FRAME_PERIOD_S + 30); + if (trk_params.bit_synchronization_time_limit_s < min_bit_sync_limit_s) + { + trk_params.bit_synchronization_time_limit_s = min_bit_sync_limit_s; + } + } + } } } // namespace @@ -166,7 +188,7 @@ DllPllTrackingAdapter::DllPllTrackingAdapter( if (!sig_info.sig_name.empty()) { - check_and_configure_trk_params(configuration, role_, sig_info, trk_params_); + check_and_configure_trk_params(configuration, role_, sig_flag, sig_info, trk_params_); if (trk_params_.item_type == "gr_complex") { diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index c2c83c81e..7e8941d5c 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -28,9 +28,6 @@ #include "acquisition_interface.h" #include "array_signal_conditioner.h" #include "beamformer_filter.h" -#include "beidou_b1c_dll_pll_veml_tracking.h" -#include "beidou_b1c_pcps_ambiguous_acquisition.h" -#include "beidou_b1c_telemetry_decoder.h" #include "beidou_b1c_telemetry_decoder_gs.h" #include "beidou_dnav_telemetry_decoder_gs.h" #include "byte_to_short.h" @@ -499,7 +496,7 @@ std::unique_ptr get_acq_block( } else if (implementation == "BEIDOU_B1C_PCPS_Ambiguous_Acquisition") { - return std::make_unique(configuration, role, in_streams, out_streams); + return std::make_unique(configuration, role, implementation, in_streams, out_streams, BDS_B1C); } else if (implementation == "BEIDOU_B3I_PCPS_Acquisition") { @@ -615,7 +612,7 @@ std::unique_ptr get_trk_block( } else if (implementation == "BEIDOU_B1C_DLL_PLL_VEML_Tracking") { - return std::make_unique(configuration, role, in_streams, out_streams); + return std::make_unique(configuration, role, implementation, in_streams, out_streams, BDS_B1C); } else if (implementation == "BEIDOU_B3I_DLL_PLL_Tracking") { @@ -696,14 +693,13 @@ std::unique_ptr get_tlm_block( unsigned int in_streams, unsigned int out_streams) { - if (implementation == "BEIDOU_B1C_Telemetry_Decoder") - { - return std::make_unique(configuration, role, in_streams, out_streams); - } - telemetry_impl_interface_sptr telemetry; - if (implementation == "GPS_L1_CA_Telemetry_Decoder") + if (implementation == "BEIDOU_B1C_Telemetry_Decoder") + { + telemetry = beidou_b1c_make_telemetry_decoder_gs(Gnss_Satellite{}, get_tlm_conf(configuration, role)); + } + else if (implementation == "GPS_L1_CA_Telemetry_Decoder") { telemetry = gps_l1_ca_make_telemetry_decoder_gs(get_tlm_conf(configuration, role)); } diff --git a/src/core/system_parameters/Beidou_B1C.h b/src/core/system_parameters/Beidou_B1C.h index 1cc241ea1..fb70cb08b 100644 --- a/src/core/system_parameters/Beidou_B1C.h +++ b/src/core/system_parameters/Beidou_B1C.h @@ -1,7 +1,7 @@ /*! * \file Beidou_B1C.h - * \brief Defines system parameters for BeiDou B1C open service signal - * \author GNSS-SDR contributors + * \brief Defines system parameters for BeiDou B1C open service signal + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn * * Parameter values from BDS-SIS-ICD-B1C-1.0 (2017-12). * @@ -10,12 +10,11 @@ * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * - * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- */ - #ifndef GNSS_SDR_BEIDOU_B1C_H #define GNSS_SDR_BEIDOU_B1C_H diff --git a/src/core/system_parameters/Beidou_B1C_codes.h b/src/core/system_parameters/Beidou_B1C_codes.h index c2d81b6d9..478197afc 100644 --- a/src/core/system_parameters/Beidou_B1C_codes.h +++ b/src/core/system_parameters/Beidou_B1C_codes.h @@ -1,4 +1,20 @@ -/* Auto-generated by generate_beidou_b1c_codes.py. Do not edit manually. */ +/*! + * \file Beidou_B1C_codes.h + * \brief Precomputed BeiDou B1C primary and secondary codes + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * Auto-generated by generate_beidou_b1c_codes.py. Do not edit manually. + * + * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_B1C_CODES_H #define GNSS_SDR_BEIDOU_B1C_CODES_H diff --git a/src/core/system_parameters/Beidou_B1C_prn.h b/src/core/system_parameters/Beidou_B1C_prn.h index 24be1015a..92394915a 100644 --- a/src/core/system_parameters/Beidou_B1C_prn.h +++ b/src/core/system_parameters/Beidou_B1C_prn.h @@ -1,10 +1,16 @@ /*! * \file Beidou_B1C_prn.h - * \brief B1C PRN Weil code parameters from BDS-SIS-ICD-B1C-1.0 Table 5-2/5-3/5-4 - * \author GNSS-SDR contributors + * \brief B1C PRN Weil code parameters from BDS-SIS-ICD-B1C-1.0 Table 5-2/5-3/5-4 + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn * * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_B1C_PRN_H diff --git a/src/core/system_parameters/Beidou_CNAV1.h b/src/core/system_parameters/Beidou_CNAV1.h index f9984e447..c931b4c73 100644 --- a/src/core/system_parameters/Beidou_CNAV1.h +++ b/src/core/system_parameters/Beidou_CNAV1.h @@ -1,9 +1,18 @@ /*! * \file Beidou_CNAV1.h * \brief B-CNAV1 navigation message constants (BDS-SIS-ICD-B1C-1.0 §6.2, §7) + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_CNAV1_H #define GNSS_SDR_BEIDOU_CNAV1_H @@ -28,18 +37,27 @@ constexpr double GNSS_SDR_TWO_N32 = 2.3283064365386963e-10; #ifndef GNSS_SDR_TWO_N34 constexpr double GNSS_SDR_TWO_N34 = 5.820766091346741e-11; #endif +#ifndef GNSS_SDR_TWO_N35 +constexpr double GNSS_SDR_TWO_N35 = 2.910383045673370e-11; +#endif #ifndef GNSS_SDR_TWO_N44 constexpr double GNSS_SDR_TWO_N44 = 5.684341886080802e-14; #endif #ifndef GNSS_SDR_TWO_N50 constexpr double GNSS_SDR_TWO_N50 = 8.881784197001252e-16; #endif +#ifndef GNSS_SDR_TWO_N51 +constexpr double GNSS_SDR_TWO_N51 = 4.440892098500626e-16; +#endif #ifndef GNSS_SDR_TWO_N57 constexpr double GNSS_SDR_TWO_N57 = 6.938893903907228e-18; #endif #ifndef GNSS_SDR_TWO_N66 constexpr double GNSS_SDR_TWO_N66 = 1.3552527156068805e-20; #endif +#ifndef GNSS_SDR_TWO_N68 +constexpr double GNSS_SDR_TWO_N68 = 3.3881317890172013e-21; +#endif constexpr int32_t BEIDOU_CNAV1_FRAME_SYMBOLS = 1800; constexpr int32_t BEIDOU_CNAV1_FRAME_PERIOD_S = 18; diff --git a/src/core/system_parameters/beidou_bdgim.cc b/src/core/system_parameters/beidou_bdgim.cc index 82b8c747b..8b5d77404 100644 --- a/src/core/system_parameters/beidou_bdgim.cc +++ b/src/core/system_parameters/beidou_bdgim.cc @@ -1,9 +1,18 @@ /*! * \file beidou_bdgim.cc * \brief BeiDou Global Ionospheric delay Model (BDGIM), BDS-SIS-ICD-B1C-1.0 §7.8 + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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 "beidou_bdgim.h" #include "MATH_CONSTANTS.h" #include diff --git a/src/core/system_parameters/beidou_bdgim.h b/src/core/system_parameters/beidou_bdgim.h index bf45573b5..422d7f65c 100644 --- a/src/core/system_parameters/beidou_bdgim.h +++ b/src/core/system_parameters/beidou_bdgim.h @@ -1,9 +1,18 @@ /*! * \file beidou_bdgim.h * \brief BeiDou Global Ionospheric delay Model (BDGIM), BDS-SIS-ICD-B1C-1.0 §7.8 + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_BDGIM_H #define GNSS_SDR_BEIDOU_BDGIM_H diff --git a/src/core/system_parameters/beidou_cnav1_ephemeris.cc b/src/core/system_parameters/beidou_cnav1_ephemeris.cc index e66da80eb..5cb00d0e9 100644 --- a/src/core/system_parameters/beidou_cnav1_ephemeris.cc +++ b/src/core/system_parameters/beidou_cnav1_ephemeris.cc @@ -1 +1,16 @@ +/*! + * \file beidou_cnav1_ephemeris.cc + * \brief BeiDou B-CNAV1 ephemeris storage (BDS-SIS-ICD-B1C-1.0 §7) + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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 "beidou_cnav1_ephemeris.h" diff --git a/src/core/system_parameters/beidou_cnav1_ephemeris.h b/src/core/system_parameters/beidou_cnav1_ephemeris.h index 8830c8a27..c21704739 100644 --- a/src/core/system_parameters/beidou_cnav1_ephemeris.h +++ b/src/core/system_parameters/beidou_cnav1_ephemeris.h @@ -1,13 +1,18 @@ /*! * \file beidou_cnav1_ephemeris.h * \brief BeiDou B-CNAV1 ephemeris storage (BDS-SIS-ICD-B1C-1.0 §7) - * \author GNSS-SDR contributors + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn * * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_CNAV1_EPHEMERIS_H #define GNSS_SDR_BEIDOU_CNAV1_EPHEMERIS_H diff --git a/src/core/system_parameters/beidou_cnav1_iono.h b/src/core/system_parameters/beidou_cnav1_iono.h index 0e0cf0e83..e35be9448 100644 --- a/src/core/system_parameters/beidou_cnav1_iono.h +++ b/src/core/system_parameters/beidou_cnav1_iono.h @@ -1,9 +1,18 @@ /*! * \file beidou_cnav1_iono.h * \brief BeiDou B-CNAV1 ionospheric model (§7.8) + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_CNAV1_IONO_H #define GNSS_SDR_BEIDOU_CNAV1_IONO_H diff --git a/src/core/system_parameters/beidou_cnav1_ldpc.cc b/src/core/system_parameters/beidou_cnav1_ldpc.cc index ce2d647cd..95f7fc712 100644 --- a/src/core/system_parameters/beidou_cnav1_ldpc.cc +++ b/src/core/system_parameters/beidou_cnav1_ldpc.cc @@ -1,9 +1,18 @@ /*! * \file beidou_cnav1_ldpc.cc * \brief B-CNAV1 LDPC graph and non-binary BP decoder over GF(64) + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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 "beidou_cnav1_ldpc.h" #include #include diff --git a/src/core/system_parameters/beidou_cnav1_ldpc.h b/src/core/system_parameters/beidou_cnav1_ldpc.h index 9558e7a6c..28a3bbf22 100644 --- a/src/core/system_parameters/beidou_cnav1_ldpc.h +++ b/src/core/system_parameters/beidou_cnav1_ldpc.h @@ -1,9 +1,18 @@ /*! * \file beidou_cnav1_ldpc.h * \brief B-CNAV1 NB-LDPC decoder (BDS-SIS-ICD-B1C-1.0 §6.2.2, Appendix) + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_CNAV1_LDPC_DECODER_H #define GNSS_SDR_BEIDOU_CNAV1_LDPC_DECODER_H diff --git a/src/core/system_parameters/beidou_cnav1_navigation_message.cc b/src/core/system_parameters/beidou_cnav1_navigation_message.cc index 2914f99b3..b72a81eb5 100644 --- a/src/core/system_parameters/beidou_cnav1_navigation_message.cc +++ b/src/core/system_parameters/beidou_cnav1_navigation_message.cc @@ -1,9 +1,18 @@ /*! * \file beidou_cnav1_navigation_message.cc * \brief B-CNAV1 navigation message parser (BDS-SIS-ICD-B1C-1.0 §6.2) + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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 "beidou_cnav1_navigation_message.h" #include "Beidou_B1C.h" #include "Beidou_CNAV1.h" @@ -469,15 +478,16 @@ void parse_page1( { int32_t offset = 0; parse_page_common(bits, true, true, page_data, offset); - iono.alpha1 = static_cast(read_signed(bits, offset, 10)) * 0.125; + // ICD Table 7-10 + iono.alpha1 = static_cast(read_unsigned(bits, offset, 10)) * 0.125; offset += 10; iono.alpha2 = static_cast(read_signed(bits, offset, 8)) * 0.125; offset += 8; - iono.alpha3 = static_cast(read_signed(bits, offset, 8)) * 0.125; + iono.alpha3 = static_cast(read_unsigned(bits, offset, 8)) * 0.125; offset += 8; - iono.alpha4 = static_cast(read_signed(bits, offset, 8)) * 0.125; + iono.alpha4 = static_cast(read_unsigned(bits, offset, 8)) * 0.125; offset += 8; - iono.alpha5 = static_cast(read_signed(bits, offset, 8)) * 0.125; + iono.alpha5 = static_cast(read_unsigned(bits, offset, 8)) * 0.125; offset += 8; iono.alpha6 = static_cast(read_signed(bits, offset, 8)) * 0.125; offset += 8; @@ -488,15 +498,16 @@ void parse_page1( iono.alpha9 = static_cast(read_signed(bits, offset, 8)) * 0.125; offset += 8; - utc.A0 = static_cast(read_signed(bits, offset, 16)) * GNSS_SDR_TWO_N34; + // ICD Table 7-20 / Figure 6-17 + utc.A0 = static_cast(read_signed(bits, offset, 16)) * GNSS_SDR_TWO_N35; offset += 16; - utc.A1 = static_cast(read_signed(bits, offset, 13)) * GNSS_SDR_TWO_N50; + utc.A1 = static_cast(read_signed(bits, offset, 13)) * GNSS_SDR_TWO_N51; offset += 13; - utc.A2 = static_cast(read_signed(bits, offset, 7)) * GNSS_SDR_TWO_N66; + utc.A2 = static_cast(read_signed(bits, offset, 7)) * GNSS_SDR_TWO_N68; offset += 7; - utc.delta_t_LSF = static_cast(read_signed(bits, offset, 8)); + utc.delta_t_LS = static_cast(read_signed(bits, offset, 8)); offset += 8; - utc.tot = static_cast(read_unsigned(bits, offset, 16)); + utc.tot = static_cast(read_unsigned(bits, offset, 16)) * 16; // scale 2^4 offset += 16; utc.WN_t = static_cast(read_unsigned(bits, offset, 13)); offset += 13; @@ -504,7 +515,7 @@ void parse_page1( offset += 13; utc.DN = static_cast(read_unsigned(bits, offset, 3)); offset += 3; - (void)read_signed(bits, offset, 8); + utc.delta_t_LSF = static_cast(read_signed(bits, offset, 8)); } void parse_page2(const uint8_t* bits, Bds3_B1c_PageData& page_data) @@ -628,13 +639,12 @@ bool Beidou_Cnav1_Navigation_Message::decode_frame( // Reverse bit order within each 6-LLR GF(64) symbol; inv applies the same polarity flip. for (int32_t symbol = 0; symbol < BEIDOU_CNAV1_SUBFRAME2_SYMBOLS / 6; symbol++) { - const int32_t base = symbol * 6; + const auto base = static_cast(symbol) * 6U; for (int32_t bit = 0; bit < 6; bit++) { - sf2_llr_bitrev[static_cast(base + bit)] = - sf2_llr[static_cast(base + (5 - bit))]; - sf2_llr_bitrev_inv[static_cast(base + bit)] = - -sf2_llr_bitrev[static_cast(base + bit)]; + const auto bit_u = static_cast(bit); + sf2_llr_bitrev[base + bit_u] = sf2_llr[base + (5U - bit_u)]; + sf2_llr_bitrev_inv[base + bit_u] = -sf2_llr_bitrev[base + bit_u]; } } // SF3: same four LLR variants as SF2. @@ -644,13 +654,12 @@ bool Beidou_Cnav1_Navigation_Message::decode_frame( } for (int32_t symbol = 0; symbol < BEIDOU_CNAV1_SUBFRAME3_SYMBOLS / 6; symbol++) { - const int32_t base = symbol * 6; + const auto base = static_cast(symbol) * 6U; for (int32_t bit = 0; bit < 6; bit++) { - sf3_llr_bitrev[static_cast(base + bit)] = - sf3_llr[static_cast(base + (5 - bit))]; - sf3_llr_bitrev_inv[static_cast(base + bit)] = - -sf3_llr_bitrev[static_cast(base + bit)]; + const auto bit_u = static_cast(bit); + sf3_llr_bitrev[base + bit_u] = sf3_llr[base + (5U - bit_u)]; + sf3_llr_bitrev_inv[base + bit_u] = -sf3_llr_bitrev[base + bit_u]; } } @@ -742,17 +751,23 @@ bool Beidou_Cnav1_Navigation_Message::decode_frame( return false; } - parse_subframe2(sf2_data.data(), ephemeris_, soh_seconds); -#if 0 - if (ephemeris_.sqrtA < 5000.0 || ephemeris_.sqrtA > 6700.0) + // Parse SF2 into a candidate so a mismatched IODE/IODC pair cannot overwrite a good set. + Beidou_Cnav1_Ephemeris candidate{}; + parse_subframe2(sf2_data.data(), candidate, soh_seconds); + candidate.PRN = static_cast(prn); + // ICD B1C §7.4.3: usable only when IODE equals IODC low 8 bits. + const auto iode = static_cast(candidate.IODE); + const auto iodc_lo = static_cast(candidate.IODC) & 0xFFU; + tow_s_ = static_cast(candidate.tow); + if (iode != iodc_lo) { - set_fail(7); - return false; + // Frame CRC is OK; do not publish unmatched eph/clock (keep prior ephemeris_). + } + else + { + ephemeris_ = candidate; + flag_new_ephemeris_ = true; } -#endif - ephemeris_.PRN = static_cast(prn); - tow_s_ = static_cast(ephemeris_.tow); - flag_new_ephemeris_ = true; if (sf3_crc_ok) { diff --git a/src/core/system_parameters/beidou_cnav1_navigation_message.h b/src/core/system_parameters/beidou_cnav1_navigation_message.h index bccf530e2..cfd2cb489 100644 --- a/src/core/system_parameters/beidou_cnav1_navigation_message.h +++ b/src/core/system_parameters/beidou_cnav1_navigation_message.h @@ -1,9 +1,18 @@ /*! * \file beidou_cnav1_navigation_message.h * \brief B-CNAV1 navigation message parser (§6.2) + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_CNAV1_NAVIGATION_MESSAGE_H #define GNSS_SDR_BEIDOU_CNAV1_NAVIGATION_MESSAGE_H diff --git a/src/core/system_parameters/beidou_cnav1_utc_model.h b/src/core/system_parameters/beidou_cnav1_utc_model.h index fe4f88886..497233a0a 100644 --- a/src/core/system_parameters/beidou_cnav1_utc_model.h +++ b/src/core/system_parameters/beidou_cnav1_utc_model.h @@ -1,12 +1,23 @@ /*! * \file beidou_cnav1_utc_model.h - * \brief BeiDou B-CNAV1 UTC model (§7.12) + * \brief BeiDou B-CNAV1 UTC model (BDS-SIS-ICD-B1C-1.0 §7.12) + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_CNAV1_UTC_MODEL_H #define GNSS_SDR_BEIDOU_CNAV1_UTC_MODEL_H +#include + class Beidou_Cnav1_Utc_Model { public: @@ -17,7 +28,8 @@ public: int32_t WN_t{}; int32_t WN_LSF{}; int32_t DN{}; - int32_t delta_t_LSF{}; + int32_t delta_t_LS{}; //!< Table 7-20: leap seconds before new leap effective [s] + int32_t delta_t_LSF{}; //!< Table 7-20: leap seconds after new leap effective [s] bool valid{}; }; diff --git a/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b1c_pcps_acquisition_test.cc b/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b1c_pcps_acquisition_test.cc index f22ddab85..fc920667b 100644 --- a/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b1c_pcps_acquisition_test.cc +++ b/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b1c_pcps_acquisition_test.cc @@ -1,21 +1,19 @@ /*! * \file beidou_b1c_pcps_acquisition_test.cc - * \brief Unit tests for BeidouB1cPcpsAmbiguousAcquisition - * \author GNSS-SDR contributors + * \brief Unit tests for BeiDou B1C PCPS acquisition via PcpsAcquisitionAdapter + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn * * ----------------------------------------------------------------------------- * * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * - * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- */ - #include "acquisition_interface.h" -#include "beidou_b1c_pcps_ambiguous_acquisition.h" #include "gnss_block_factory.h" #include "gnss_block_interface.h" #include "in_memory_configuration.h" diff --git a/tests/unit-tests/signal-processing-blocks/libs/beidou_b1c_signal_replica_test.cc b/tests/unit-tests/signal-processing-blocks/libs/beidou_b1c_signal_replica_test.cc index 739a8723c..4ce3171f0 100644 --- a/tests/unit-tests/signal-processing-blocks/libs/beidou_b1c_signal_replica_test.cc +++ b/tests/unit-tests/signal-processing-blocks/libs/beidou_b1c_signal_replica_test.cc @@ -1,19 +1,18 @@ /*! * \file beidou_b1c_signal_replica_test.cc * \brief Unit tests for BeiDou B1C signal replica generation - * \author GNSS-SDR contributors + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn * * ----------------------------------------------------------------------------- * * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * - * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- */ - #include "Beidou_B1C.h" #include "beidou_b1c_signal_replica.h" #include diff --git a/tests/unit-tests/signal-processing-blocks/tracking/beidou_b1c_dll_pll_veml_tracking_test.cc b/tests/unit-tests/signal-processing-blocks/tracking/beidou_b1c_dll_pll_veml_tracking_test.cc index 435f7c041..ea3b63ddc 100644 --- a/tests/unit-tests/signal-processing-blocks/tracking/beidou_b1c_dll_pll_veml_tracking_test.cc +++ b/tests/unit-tests/signal-processing-blocks/tracking/beidou_b1c_dll_pll_veml_tracking_test.cc @@ -1,9 +1,18 @@ /*! * \file beidou_b1c_dll_pll_veml_tracking_test.cc + * \brief Unit tests for BeiDou B1C DLL+PLL VEML tracking via DllPllTrackingAdapter + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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 "beidou_b1c_dll_pll_veml_tracking.h" #include "gnss_block_factory.h" #include "gnss_block_interface.h" #include "in_memory_configuration.h" diff --git a/tests/unit-tests/system-parameters/beidou_b1c_pvt_helpers_test.cc b/tests/unit-tests/system-parameters/beidou_b1c_pvt_helpers_test.cc index 562d7b02d..9804835fb 100644 --- a/tests/unit-tests/system-parameters/beidou_b1c_pvt_helpers_test.cc +++ b/tests/unit-tests/system-parameters/beidou_b1c_pvt_helpers_test.cc @@ -1,9 +1,18 @@ /*! * \file beidou_b1c_pvt_helpers_test.cc * \brief Unit tests for B1C PVT helpers (TGD/ISC, seleph, band/wavelength map) + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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 "MATH_CONSTANTS.h" #include "gnss_frequencies.h" #include "gnss_obs_codes.h" @@ -164,3 +173,43 @@ TEST(BeidouB1cPvtHelpersTest, GettgdPrefersMatchingEphTypeWhenBothPresent) EXPECT_NEAR(tgd_b1c, SPEED_OF_LIGHT_M_S * 3.0e-9, 1.0e-6); EXPECT_NEAR(tgd_b1i, SPEED_OF_LIGHT_M_S * 5.0e-9, 1.0e-6); } + +TEST(BeidouB1cPvtHelpersTest, GettgdReturnsZeroWhenOnlyWrongEphFamilyPresent) +{ + const int sat = NSATGPS + NSATGLO + NSATGAL + NSATQZS + 22; + const double ep[] = {2021, 3, 1, 0, 0, 0}; + const gtime_t t0 = epoch2time(ep); + std::vector ephs; + ephs.push_back(make_bds_eph(sat, 1, 5.0e-9, 0.0, t0)); /* DNAV only */ + nav_t nav; + std::memset(&nav, 0, sizeof(nav)); + nav.eph = ephs.data(); + nav.n = 1; + + /* B1C obs must not fall back to DNAV TGD1 */ + EXPECT_DOUBLE_EQ(gettgd(sat, &nav, static_cast(CODE_L1D)), 0.0); + EXPECT_DOUBLE_EQ(gettgd(sat, &nav, static_cast(CODE_L1P)), 0.0); +} + +/* CODE_L1P is shared with GPS L1P — CNAV1 filtering must be SYS_BDS-only. */ +TEST(BeidouB1cPvtHelpersTest, GettgdGpsIgnoresB1cCodeSelection) +{ + const int sat = satno(SYS_GPS, 5); + const double ep[] = {2020, 1, 1, 0, 0, 0}; + const gtime_t t0 = epoch2time(ep); + eph_t e{}; + std::memset(&e, 0, sizeof(e)); + e.sat = sat; + e.code = 0; /* LNAV, not CNAV1 */ + e.tgd[0] = 4.0e-9; + e.toe = t0; + e.toc = t0; + nav_t nav; + std::memset(&nav, 0, sizeof(nav)); + nav.eph = &e; + nav.n = 1; + + EXPECT_NEAR(gettgd(sat, &nav, static_cast(CODE_L1C)), SPEED_OF_LIGHT_M_S * 4.0e-9, 1.0e-6); + /* Must still return GPS TGD even though CODE_L1P is also used for B1C pilot */ + EXPECT_NEAR(gettgd(sat, &nav, static_cast(CODE_L1P)), SPEED_OF_LIGHT_M_S * 4.0e-9, 1.0e-6); +} diff --git a/tests/unit-tests/system-parameters/beidou_bdgim_test.cc b/tests/unit-tests/system-parameters/beidou_bdgim_test.cc index 831974a57..e4016b359 100644 --- a/tests/unit-tests/system-parameters/beidou_bdgim_test.cc +++ b/tests/unit-tests/system-parameters/beidou_bdgim_test.cc @@ -1,9 +1,18 @@ /*! * \file beidou_bdgim_test.cc * \brief Smoke tests for BDGIM ionospheric model + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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 "MATH_CONSTANTS.h" #include "beidou_bdgim.h" #include "gnss_frequencies.h" diff --git a/tests/unit-tests/system-parameters/beidou_cnav1_ldpc_test.cc b/tests/unit-tests/system-parameters/beidou_cnav1_ldpc_test.cc index 44ef45a45..bcf7e825f 100644 --- a/tests/unit-tests/system-parameters/beidou_cnav1_ldpc_test.cc +++ b/tests/unit-tests/system-parameters/beidou_cnav1_ldpc_test.cc @@ -1,9 +1,18 @@ /*! * \file beidou_cnav1_ldpc_test.cc * \brief Unit tests for B-CNAV1 NB-LDPC decoder + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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 "Beidou_CNAV1.h" #include "beidou_cnav1_ldpc.h" #include diff --git a/tests/unit-tests/system-parameters/beidou_cnav1_navigation_message_test.cc b/tests/unit-tests/system-parameters/beidou_cnav1_navigation_message_test.cc index 43fd5473a..0747419b6 100644 --- a/tests/unit-tests/system-parameters/beidou_cnav1_navigation_message_test.cc +++ b/tests/unit-tests/system-parameters/beidou_cnav1_navigation_message_test.cc @@ -1,9 +1,18 @@ /*! * \file beidou_cnav1_navigation_message_test.cc * \brief Unit tests for B-CNAV1 navigation message parser + * \author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * ----------------------------------------------------------------------------- + * + * 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 "Beidou_CNAV1.h" #include "beidou_cnav1_navigation_message.h" #include "rtklib_conversions.h" @@ -164,5 +173,67 @@ TEST(BeidouCnav1NavigationMessageTest, DecodeEphemerisFromZeroSf2Payload) EXPECT_EQ(rtklib_eph.code, 7); /* Adot/ndot retained through parse → RTKLIB conversion (may be zero in synthetic frame) */ EXPECT_DOUBLE_EQ(rtklib_eph.Adot, nav.get_ephemeris().Adot); - EXPECT_DOUBLE_EQ(rtklib_eph.ndot, nav.get_ephemeris().delta_n_dot); + EXPECT_DOUBLE_EQ(rtklib_eph.ndot, nav.get_ephemeris().delta_n0dot); +} + +TEST(BeidouCnav1NavigationMessageTest, RejectsEphemerisWhenIodeIodcMismatch) +{ + // Build SF2 with IODC=0x101 (low 8 = 0x01) and IODE=0x02 → §7.4.3 mismatch. + std::vector sf2_bits(static_cast(BEIDOU_CNAV1_SUBFRAME2_SYMBOLS), 0U); + // WN=0, HOW=0 already zero; set IODC at bit 21 (13+8), 10 bits = 0x101 + const int32_t iodc_offset = 13 + 8; + const uint32_t iodc = 0x101U; + for (int32_t b = 0; b < 10; b++) + { + sf2_bits[static_cast(iodc_offset + b)] = static_cast((iodc >> static_cast(9 - b)) & 1U); + } + // IODE at bit 31, 8 bits = 0x02 + const int32_t iode_offset = iodc_offset + 10; + const uint32_t iode = 0x02U; + for (int32_t b = 0; b < 8; b++) + { + sf2_bits[static_cast(iode_offset + b)] = static_cast((iode >> static_cast(7 - b)) & 1U); + } + // SatType MEO = 0b11 at toe(11)+offset after IODE + const int32_t sat_type_offset = iode_offset + 8 + 11; + sf2_bits[static_cast(sat_type_offset)] = 1U; + sf2_bits[static_cast(sat_type_offset + 1)] = 1U; + + // Append valid CRC24Q over first 576 bits (zeros+fields above) — use decoder's CRC by + // zeroing CRC field and computing via a local copy of the same polynomial as the parser. + auto crc24q_bits = [](const uint8_t* bits, int32_t num_bits) -> uint32_t { + uint32_t crc = 0; + const uint32_t POLY = 0x864CFBU; + for (int32_t i = 0; i < num_bits; i++) + { + uint32_t msb = (crc >> 23) & 1U; + uint32_t bit = (bits[i] != 0U) ? 1U : 0U; + crc = (crc << 1) & 0xFFFFFFU; + if (msb ^ bit) + { + crc ^= POLY; + } + } + return crc; + }; + const uint32_t crc = crc24q_bits(sf2_bits.data(), BEIDOU_CNAV1_SF2_DATA_BITS - BEIDOU_CNAV1_CRC_BITS); + for (int32_t b = 0; b < BEIDOU_CNAV1_CRC_BITS; b++) + { + sf2_bits[static_cast(BEIDOU_CNAV1_SF2_DATA_BITS - BEIDOU_CNAV1_CRC_BITS + b)] = + static_cast((crc >> static_cast(23 - b)) & 1U); + } + + const auto sf2_llr = encode_bits_to_llr(sf2_bits); + const auto sf3_llr = encode_bits_to_llr(std::vector(BEIDOU_CNAV1_SUBFRAME3_SYMBOLS, 0U)); + std::vector interleaved; + deinterleave_like_icd(sf2_llr, sf3_llr, interleaved); + + std::vector frame; + append_bch21_6(frame, 19U); + append_bch51_8(frame, 1U); + frame.insert(frame.end(), interleaved.begin(), interleaved.end()); + + Beidou_Cnav1_Navigation_Message nav; + ASSERT_TRUE(nav.decode_frame_symbols(frame.data(), BEIDOU_CNAV1_FRAME_SYMBOLS, 19)); + EXPECT_FALSE(nav.have_new_ephemeris()); } diff --git a/utils/generate_beidou_b1c_codes.py b/utils/generate_beidou_b1c_codes.py index cc13741bb..61252cae6 100644 --- a/utils/generate_beidou_b1c_codes.py +++ b/utils/generate_beidou_b1c_codes.py @@ -1,5 +1,19 @@ #!/usr/bin/env python3 -"""Generate Beidou_B1C_codes.h from ICD Weil parameters in Beidou_B1C_prn.h.""" +""" +Generate Beidou_B1C_codes.h from ICD Weil parameters in Beidou_B1C_prn.h. + + ----------------------------------------------------------------------------- + + 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 + + Author: Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + + ----------------------------------------------------------------------------- +""" from __future__ import annotations @@ -78,7 +92,23 @@ def main() -> None: expected = "101011111111011001001110" assert "".join(str(b) for b in weil_code(L10243, 10243, data_w[0], data_p[0], 10230)[:24]) == expected - header = f"""/* Auto-generated by {Path(__file__).name}. Do not edit manually. */ + header = f"""/*! + * \\file Beidou_B1C_codes.h + * \\brief Precomputed BeiDou B1C primary and secondary codes + * \\author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + * + * Auto-generated by {Path(__file__).name}. Do not edit manually. + * + * ----------------------------------------------------------------------------- + * + * 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_BEIDOU_B1C_CODES_H #define GNSS_SDR_BEIDOU_B1C_CODES_H diff --git a/utils/generate_beidou_cnav1_ldpc.py b/utils/generate_beidou_cnav1_ldpc.py index 5ac36bec3..e348b236f 100644 --- a/utils/generate_beidou_cnav1_ldpc.py +++ b/utils/generate_beidou_cnav1_ldpc.py @@ -1,5 +1,19 @@ #!/usr/bin/env python3 -"""Generate Beidou_CNAV1_ldpc.h from BDS-SIS-ICD-B1C-1.0 PDF text.""" +""" +Generate Beidou_CNAV1_ldpc.h from BDS-SIS-ICD-B1C-1.0 PDF text. + + ----------------------------------------------------------------------------- + + 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 + + Author: Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn + + ----------------------------------------------------------------------------- +""" from __future__ import annotations @@ -110,7 +124,23 @@ def main() -> None: exp, log = gf64_tables() header: list[str] = [ - "/* Auto-generated by utils/generate_beidou_cnav1_ldpc.py. Do not edit manually. */", + "/*!", + " * \\file Beidou_CNAV1_ldpc.h", + " * \\brief Precomputed B-CNAV1 NB-LDPC matrices and GF(64) LUTs", + " * \\author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn", + " *", + " * Auto-generated by utils/generate_beidou_cnav1_ldpc.py. Do not edit manually.", + " *", + " * -----------------------------------------------------------------------------", + " *", + " * 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_BEIDOU_CNAV1_LDPC_MATRICES_H", "#define GNSS_SDR_BEIDOU_CNAV1_LDPC_MATRICES_H", "#include ",