From 63b19692e7b762b06d51537f99b4a679e44296c6 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Wed, 5 Dec 2018 16:50:32 +0100 Subject: [PATCH] Completing the smart acquisition resampler --- ...alileo_e1_pcps_8ms_ambiguous_acquisition.h | 3 + .../galileo_e1_pcps_ambiguous_acquisition.cc | 73 +++++----- .../galileo_e1_pcps_ambiguous_acquisition.h | 7 + ...lileo_e1_pcps_ambiguous_acquisition_fpga.h | 2 + ...leo_e1_pcps_cccwsr_ambiguous_acquisition.h | 2 + ..._e1_pcps_quicksync_ambiguous_acquisition.h | 2 + ...lileo_e1_pcps_tong_ambiguous_acquisition.h | 2 + ...lileo_e5a_noncoherent_iq_acquisition_caf.h | 2 + .../adapters/galileo_e5a_pcps_acquisition.cc | 89 +++++++++--- .../adapters/galileo_e5a_pcps_acquisition.h | 8 +- .../galileo_e5a_pcps_acquisition_fpga.h | 2 + .../adapters/glonass_l1_ca_pcps_acquisition.h | 2 + .../adapters/glonass_l2_ca_pcps_acquisition.h | 2 + .../adapters/gps_l1_ca_pcps_acquisition.cc | 42 +++--- .../adapters/gps_l1_ca_pcps_acquisition.h | 7 + .../gps_l1_ca_pcps_acquisition_fine_doppler.h | 2 + .../gps_l1_ca_pcps_acquisition_fpga.h | 2 + .../gps_l1_ca_pcps_assisted_acquisition.h | 2 + .../gps_l1_ca_pcps_opencl_acquisition.h | 2 + .../gps_l1_ca_pcps_quicksync_acquisition.h | 2 + .../gps_l1_ca_pcps_tong_acquisition.h | 2 + .../adapters/gps_l2_m_pcps_acquisition.cc | 99 +++++++++---- .../adapters/gps_l2_m_pcps_acquisition.h | 8 ++ .../adapters/gps_l2_m_pcps_acquisition_fpga.h | 2 + .../adapters/gps_l5i_pcps_acquisition.cc | 98 +++++++++---- .../adapters/gps_l5i_pcps_acquisition.h | 7 + .../adapters/gps_l5i_pcps_acquisition_fpga.h | 2 + .../gnuradio_blocks/pcps_acquisition.cc | 8 ++ .../gnuradio_blocks/pcps_acquisition.h | 2 + src/algorithms/acquisition/libs/acq_conf.cc | 1 + src/algorithms/acquisition/libs/acq_conf.h | 1 + src/core/interfaces/acquisition_interface.h | 1 + src/core/receiver/gnss_flowgraph.cc | 94 ++++++++----- src/core/system_parameters/GPS_L1_CA.h | 2 +- src/core/system_parameters/GPS_L2C.h | 2 +- src/core/system_parameters/GPS_L5.h | 2 +- src/core/system_parameters/Galileo_E1.h | 2 +- src/core/system_parameters/Galileo_E5a.h | 2 +- src/tests/system-tests/position_test.cc | 6 + .../observables/hybrid_observables_test.cc | 132 ++++++++++++++++-- .../tracking/tracking_pull-in_test.cc | 71 +++++----- 41 files changed, 579 insertions(+), 220 deletions(-) diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_8ms_ambiguous_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_8ms_ambiguous_acquisition.h index 59cd5c649..92bb24be4 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_8ms_ambiguous_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_8ms_ambiguous_acquisition.h @@ -131,6 +131,9 @@ public: void set_state(int state __attribute__((unused))) override{}; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + + private: ConfigurationInterface* configuration_; galileo_pcps_8ms_acquisition_cc_sptr acquisition_cc_; diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc index e7a48ff9b..93dfa80eb 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc @@ -50,7 +50,6 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( in_streams_(in_streams), out_streams_(out_streams) { - Acq_Conf acq_parameters; configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./acquisition.mat"; @@ -61,33 +60,32 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( int64_t fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 4000000); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); - acq_parameters.fs_in = fs_in_; - acq_parameters.samples_per_chip = static_cast(ceil((1.0 / Galileo_E1_CODE_CHIP_RATE_HZ) * static_cast(acq_parameters.fs_in))); + acq_parameters_.fs_in = fs_in_; doppler_max_ = configuration_->property(role + ".doppler_max", 5000); if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; - acq_parameters.doppler_max = doppler_max_; - acq_parameters.ms_per_code = 4; - sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", acq_parameters.ms_per_code); - acq_parameters.sampled_ms = sampled_ms_; - if ((acq_parameters.sampled_ms % acq_parameters.ms_per_code) != 0) + acq_parameters_.doppler_max = doppler_max_; + acq_parameters_.ms_per_code = 4; + sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", acq_parameters_.ms_per_code); + acq_parameters_.sampled_ms = sampled_ms_; + if ((acq_parameters_.sampled_ms % acq_parameters_.ms_per_code) != 0) { LOG(WARNING) << "Parameter coherent_integration_time_ms should be a multiple of 4. Setting it to 4"; - acq_parameters.sampled_ms = acq_parameters.ms_per_code; + acq_parameters_.sampled_ms = acq_parameters_.ms_per_code; } bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); - acq_parameters.bit_transition_flag = bit_transition_flag_; + acq_parameters_.bit_transition_flag = bit_transition_flag_; use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions - acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; + acq_parameters_.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; acquire_pilot_ = configuration_->property(role + ".acquire_pilot", false); //will be true in future versions max_dwells_ = configuration_->property(role + ".max_dwells", 1); - acq_parameters.max_dwells = max_dwells_; + acq_parameters_.max_dwells = max_dwells_; dump_ = configuration_->property(role + ".dump", false); - acq_parameters.dump = dump_; - acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0); + acq_parameters_.dump = dump_; + acq_parameters_.dump_channel = configuration_->property(role + ".dump_channel", 0); blocking_ = configuration_->property(role + ".blocking", true); - acq_parameters.blocking = blocking_; + acq_parameters_.blocking = blocking_; dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); - acq_parameters.dump_filename = dump_filename_; + acq_parameters_.dump_filename = dump_filename_; acq_parameters_.use_automatic_resampler = configuration_->property("GNSS-SDR.use_acquisition_resampler", false); if (acq_parameters_.use_automatic_resampler == true and item_type_.compare("gr_complex") != 0) @@ -99,26 +97,30 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( { if (acq_parameters_.fs_in > Galileo_E1_OPT_ACQ_FS_HZ) { - acq_parameters_.resampled_fs = Galileo_E1_OPT_ACQ_FS_HZ; - acq_parameters_.resampler_ratio = static_cast(acq_parameters_.fs_in) / static_cast(acq_parameters_.resampled_fs); + acq_parameters_.resampler_ratio = floor(static_cast(acq_parameters_.fs_in) / Galileo_E1_OPT_ACQ_FS_HZ); + uint32_t decimation = acq_parameters_.fs_in / Galileo_E1_OPT_ACQ_FS_HZ; + while (acq_parameters_.fs_in % decimation > 0) + { + decimation--; + }; + acq_parameters_.resampler_ratio = decimation; + acq_parameters_.resampled_fs = acq_parameters_.fs_in / static_cast(acq_parameters_.resampler_ratio); } - //--- Find number of samples per spreading code (4 ms) ----------------- code_length_ = static_cast(std::floor(static_cast(acq_parameters_.resampled_fs) / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS))); - float samples_per_ms = static_cast(acq_parameters_.resampled_fs) * 0.001; - acq_parameters_.samples_per_ms = samples_per_ms; - acq_parameters_.samples_per_code = acq_parameters_.samples_per_ms * static_cast(Galileo_E1_CODE_PERIOD_MS); - vector_length_ = sampled_ms_ * samples_per_ms; + acq_parameters_.samples_per_ms = static_cast(acq_parameters_.resampled_fs) * 0.001; + acq_parameters_.samples_per_chip = static_cast(ceil((1.0 / Galileo_E1_CODE_CHIP_RATE_HZ) * static_cast(acq_parameters_.resampled_fs))); } else { //--- Find number of samples per spreading code (4 ms) ----------------- code_length_ = static_cast(std::floor(static_cast(fs_in_) / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS))); - float samples_per_ms = static_cast(fs_in_) * 0.001; - acq_parameters_.samples_per_ms = samples_per_ms; - acq_parameters_.samples_per_code = acq_parameters_.samples_per_ms * static_cast(Galileo_E1_CODE_PERIOD_MS); - vector_length_ = sampled_ms_ * samples_per_ms; + acq_parameters_.samples_per_ms = static_cast(fs_in_) * 0.001; + acq_parameters_.samples_per_chip = static_cast(ceil((1.0 / Galileo_E1_CODE_CHIP_RATE_HZ) * static_cast(acq_parameters_.fs_in))); } + + acq_parameters_.samples_per_code = acq_parameters_.samples_per_ms * static_cast(Galileo_E1_CODE_PERIOD_MS); + vector_length_ = sampled_ms_ * acq_parameters_.samples_per_ms; if (bit_transition_flag_) { vector_length_ *= 2; @@ -134,12 +136,12 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( { item_size_ = sizeof(gr_complex); } - acq_parameters.it_size = item_size_; - acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); - acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); - acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); - acq_parameters.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); - acquisition_ = pcps_make_acquisition(acq_parameters); + acq_parameters_.it_size = item_size_; + acq_parameters_.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); + acq_parameters_.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); + acq_parameters_.make_2_steps = configuration_->property(role + ".make_two_steps", false); + acq_parameters_.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); + acquisition_ = pcps_make_acquisition(acq_parameters_); DLOG(INFO) << "acquisition(" << acquisition_->unique_id() << ")"; if (item_type_ == "cbyte") @@ -393,3 +395,8 @@ gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisition::get_right_block() { return acquisition_; } + +void GalileoE1PcpsAmbiguousAcquisition::set_resampler_latency(uint32_t latency_samples) +{ + acquisition_->set_resampler_latency(latency_samples); +} diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h index 8e7859556..095f92357 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h @@ -138,6 +138,13 @@ public: */ 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; + + private: ConfigurationInterface* configuration_; Acq_Conf acq_parameters_; diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h index 8ea13f0e4..06d55cea1 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h @@ -142,6 +142,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; //pcps_acquisition_sptr acquisition_; diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_cccwsr_ambiguous_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_cccwsr_ambiguous_acquisition.h index 9fde5d723..c1cc69e2d 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_cccwsr_ambiguous_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_cccwsr_ambiguous_acquisition.h @@ -131,6 +131,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; pcps_cccwsr_acquisition_cc_sptr acquisition_cc_; diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_quicksync_ambiguous_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_quicksync_ambiguous_acquisition.h index 844856260..87aa38de2 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_quicksync_ambiguous_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_quicksync_ambiguous_acquisition.h @@ -135,6 +135,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; pcps_quicksync_acquisition_cc_sptr acquisition_cc_; diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_tong_ambiguous_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_tong_ambiguous_acquisition.h index 8e56c4044..b603e53a0 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_tong_ambiguous_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_tong_ambiguous_acquisition.h @@ -134,6 +134,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; pcps_tong_acquisition_cc_sptr acquisition_cc_; diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_noncoherent_iq_acquisition_caf.h b/src/algorithms/acquisition/adapters/galileo_e5a_noncoherent_iq_acquisition_caf.h index 4175a0741..b1280d63e 100644 --- a/src/algorithms/acquisition/adapters/galileo_e5a_noncoherent_iq_acquisition_caf.h +++ b/src/algorithms/acquisition/adapters/galileo_e5a_noncoherent_iq_acquisition_caf.h @@ -137,6 +137,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; galileo_e5a_noncoherentIQ_acquisition_caf_cc_sptr acquisition_cc_; diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc index e18e2e0a3..7f1f6e321 100644 --- a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc @@ -49,7 +49,6 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con in_streams_(in_streams), out_streams_(out_streams) { - Acq_Conf acq_parameters = Acq_Conf(); configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./acquisition.mat"; @@ -60,8 +59,7 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con int64_t fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 32000000); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); - acq_parameters.fs_in = fs_in_; - acq_parameters.samples_per_chip = static_cast(ceil((1.0 / Galileo_E5a_CODE_CHIP_RATE_HZ) * static_cast(acq_parameters.fs_in))); + acq_parameters_.fs_in = fs_in_; acq_pilot_ = configuration_->property(role + ".acquire_pilot", false); acq_iq_ = configuration_->property(role + ".acquire_iq", false); if (acq_iq_) @@ -69,22 +67,58 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con acq_pilot_ = false; } dump_ = configuration_->property(role + ".dump", false); - acq_parameters.dump = dump_; - acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0); + acq_parameters_.dump = dump_; + acq_parameters_.dump_channel = configuration_->property(role + ".dump_channel", 0); doppler_max_ = configuration_->property(role + ".doppler_max", 5000); if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; - acq_parameters.doppler_max = doppler_max_; + acq_parameters_.doppler_max = doppler_max_; sampled_ms_ = 1; max_dwells_ = configuration_->property(role + ".max_dwells", 1); - acq_parameters.max_dwells = max_dwells_; + acq_parameters_.max_dwells = max_dwells_; dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); - acq_parameters.dump_filename = dump_filename_; + acq_parameters_.dump_filename = dump_filename_; bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); - acq_parameters.bit_transition_flag = bit_transition_flag_; + acq_parameters_.bit_transition_flag = bit_transition_flag_; use_CFAR_ = configuration_->property(role + ".use_CFAR_algorithm", false); - acq_parameters.use_CFAR_algorithm_flag = use_CFAR_; + acq_parameters_.use_CFAR_algorithm_flag = use_CFAR_; blocking_ = configuration_->property(role + ".blocking", true); - acq_parameters.blocking = blocking_; + acq_parameters_.blocking = blocking_; + + + acq_parameters_.use_automatic_resampler = configuration_->property("GNSS-SDR.use_acquisition_resampler", false); + if (acq_parameters_.use_automatic_resampler == true and item_type_.compare("gr_complex") != 0) + { + LOG(WARNING) << "Galileo E5a acquisition disabled the automatic resampler feature because its item_type is not set to gr_complex"; + acq_parameters_.use_automatic_resampler = false; + } + if (acq_parameters_.use_automatic_resampler) + { + if (acq_parameters_.fs_in > Galileo_E5a_OPT_ACQ_FS_HZ) + { + acq_parameters_.resampler_ratio = floor(static_cast(acq_parameters_.fs_in) / Galileo_E5a_OPT_ACQ_FS_HZ); + uint32_t decimation = acq_parameters_.fs_in / Galileo_E5a_OPT_ACQ_FS_HZ; + while (acq_parameters_.fs_in % decimation > 0) + { + decimation--; + }; + acq_parameters_.resampler_ratio = decimation; + acq_parameters_.resampled_fs = acq_parameters_.fs_in / static_cast(acq_parameters_.resampler_ratio); + } + + //--- Find number of samples per spreading code ------------------------- + code_length_ = static_cast(std::floor(static_cast(acq_parameters_.resampled_fs) / (Galileo_E5a_CODE_CHIP_RATE_HZ / Galileo_E5a_CODE_LENGTH_CHIPS))); + acq_parameters_.samples_per_ms = static_cast(acq_parameters_.resampled_fs) * 0.001; + acq_parameters_.samples_per_chip = static_cast(ceil((1.0 / Galileo_E5a_CODE_CHIP_RATE_HZ) * static_cast(acq_parameters_.resampled_fs))); + } + else + { + acq_parameters_.resampled_fs = fs_in_; + //--- Find number of samples per spreading code ------------------------- + code_length_ = static_cast(std::floor(static_cast(fs_in_) / (Galileo_E5a_CODE_CHIP_RATE_HZ / Galileo_E5a_CODE_LENGTH_CHIPS))); + acq_parameters_.samples_per_ms = static_cast(fs_in_) * 0.001; + acq_parameters_.samples_per_chip = static_cast(ceil((1.0 / Galileo_E5a_CODE_CHIP_RATE_HZ) * static_cast(acq_parameters_.fs_in))); + } + //--- Find number of samples per spreading code (1ms)------------------------- code_length_ = static_cast(std::round(static_cast(fs_in_) / Galileo_E5a_CODE_CHIP_RATE_HZ * static_cast(Galileo_E5a_CODE_LENGTH_CHIPS))); vector_length_ = code_length_ * sampled_ms_; @@ -104,16 +138,15 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con item_size_ = sizeof(gr_complex); LOG(WARNING) << item_type_ << " unknown acquisition item type"; } - acq_parameters.it_size = item_size_; - acq_parameters.samples_per_ms = static_cast(fs_in_) * 0.001; - acq_parameters.sampled_ms = sampled_ms_; - acq_parameters.ms_per_code = 1; - acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast(GALILEO_E5a_CODE_PERIOD_MS); - acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); - acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); - acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); - acq_parameters.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); - acquisition_ = pcps_make_acquisition(acq_parameters); + acq_parameters_.it_size = item_size_; + acq_parameters_.sampled_ms = sampled_ms_; + acq_parameters_.ms_per_code = 1; + acq_parameters_.samples_per_code = acq_parameters_.samples_per_ms * static_cast(GALILEO_E5a_CODE_PERIOD_MS); + acq_parameters_.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); + acq_parameters_.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); + acq_parameters_.make_2_steps = configuration_->property(role + ".make_two_steps", false); + acq_parameters_.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); + acquisition_ = pcps_make_acquisition(acq_parameters_); channel_ = 0; threshold_ = 0.0; @@ -224,7 +257,14 @@ void GalileoE5aPcpsAcquisition::set_local_code() strcpy(signal_, "5I"); } - galileo_e5_a_code_gen_complex_sampled(code, signal_, gnss_synchro_->PRN, fs_in_, 0); + if (acq_parameters_.use_automatic_resampler) + { + galileo_e5_a_code_gen_complex_sampled(code, signal_, gnss_synchro_->PRN, acq_parameters_.resampled_fs, 0); + } + else + { + galileo_e5_a_code_gen_complex_sampled(code, signal_, gnss_synchro_->PRN, fs_in_, 0); + } for (unsigned int i = 0; i < sampled_ms_; i++) { @@ -311,3 +351,8 @@ gr::basic_block_sptr GalileoE5aPcpsAcquisition::get_right_block() { return acquisition_; } + +void GalileoE5aPcpsAcquisition::set_resampler_latency(uint32_t latency_samples) +{ + acquisition_->set_resampler_latency(latency_samples); +} diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h index 063c79ff2..5a4d71fc1 100644 --- a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h @@ -128,13 +128,19 @@ public: */ 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; + private: float calculate_threshold(float pfa); ConfigurationInterface* configuration_; pcps_acquisition_sptr acquisition_; - + Acq_Conf acq_parameters_; size_t item_size_; std::string item_type_; diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.h index 91788c733..79f0d2836 100644 --- a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.h @@ -130,6 +130,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: //float calculate_threshold(float pfa); diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h index 3c0c14ab1..7abf3df91 100644 --- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h @@ -137,6 +137,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; pcps_acquisition_sptr acquisition_; diff --git a/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.h b/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.h index 3c093c5cd..060cd8f10 100644 --- a/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.h @@ -136,6 +136,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; pcps_acquisition_sptr acquisition_; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc index 8f0d930c2..1729aa979 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc @@ -54,7 +54,6 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( in_streams_(in_streams), out_streams_(out_streams) { - Acq_Conf acq_parameters = Acq_Conf(); configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./acquisition.mat"; @@ -64,25 +63,24 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( item_type_ = configuration_->property(role + ".item_type", default_item_type); int64_t fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); - acq_parameters.fs_in = fs_in_; - acq_parameters.samples_per_chip = static_cast(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast(acq_parameters.fs_in))); + acq_parameters_.fs_in = fs_in_; dump_ = configuration_->property(role + ".dump", false); - acq_parameters.dump = dump_; - acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0); + acq_parameters_.dump = dump_; + acq_parameters_.dump_channel = configuration_->property(role + ".dump_channel", 0); blocking_ = configuration_->property(role + ".blocking", true); - acq_parameters.blocking = blocking_; + acq_parameters_.blocking = blocking_; doppler_max_ = configuration_->property(role + ".doppler_max", 5000); if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; - acq_parameters.doppler_max = doppler_max_; + acq_parameters_.doppler_max = doppler_max_; sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1); - acq_parameters.sampled_ms = sampled_ms_; - acq_parameters.ms_per_code = 1; + acq_parameters_.sampled_ms = sampled_ms_; + acq_parameters_.ms_per_code = 1; bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); - acq_parameters.bit_transition_flag = bit_transition_flag_; + acq_parameters_.bit_transition_flag = bit_transition_flag_; use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions - acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; + acq_parameters_.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; max_dwells_ = configuration_->property(role + ".max_dwells", 1); - acq_parameters.max_dwells = max_dwells_; + acq_parameters_.max_dwells = max_dwells_; dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); acq_parameters_.dump_filename = dump_filename_; acq_parameters_.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); @@ -110,8 +108,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( //--- Find number of samples per spreading code ------------------------- code_length_ = static_cast(std::floor(static_cast(acq_parameters_.resampled_fs) / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS))); acq_parameters_.samples_per_ms = static_cast(acq_parameters_.resampled_fs) * 0.001; - acq_parameters_.samples_per_code = acq_parameters_.samples_per_ms * static_cast(GPS_L1_CA_CODE_PERIOD * 1000.0); - vector_length_ = std::floor(acq_parameters_.sampled_ms * acq_parameters_.samples_per_ms) * (acq_parameters_.bit_transition_flag ? 2 : 1); + acq_parameters_.samples_per_chip = static_cast(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast(acq_parameters_.resampled_fs))); } else { @@ -119,9 +116,11 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( //--- Find number of samples per spreading code ------------------------- code_length_ = static_cast(std::floor(static_cast(fs_in_) / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS))); acq_parameters_.samples_per_ms = static_cast(fs_in_) * 0.001; - acq_parameters_.samples_per_code = acq_parameters_.samples_per_ms * static_cast(GPS_L1_CA_CODE_PERIOD * 1000.0); - vector_length_ = std::floor(acq_parameters_.sampled_ms * acq_parameters_.samples_per_ms) * (acq_parameters_.bit_transition_flag ? 2 : 1); + acq_parameters_.samples_per_chip = static_cast(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast(acq_parameters_.fs_in))); } + + acq_parameters_.samples_per_code = acq_parameters_.samples_per_ms * static_cast(GPS_L1_CA_CODE_PERIOD * 1000.0); + vector_length_ = std::floor(acq_parameters_.sampled_ms * acq_parameters_.samples_per_ms) * (acq_parameters_.bit_transition_flag ? 2 : 1); code_ = new gr_complex[vector_length_]; if (item_type_ == "cshort") @@ -133,9 +132,9 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( item_size_ = sizeof(gr_complex); } - acq_parameters.it_size = item_size_; - acq_parameters.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); - acquisition_ = pcps_make_acquisition(acq_parameters); + acq_parameters_.it_size = item_size_; + acq_parameters_.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); + acquisition_ = pcps_make_acquisition(acq_parameters_); DLOG(INFO) << "acquisition(" << acquisition_->unique_id() << ")"; if (item_type_ == "cbyte") @@ -361,3 +360,8 @@ gr::basic_block_sptr GpsL1CaPcpsAcquisition::get_right_block() { return acquisition_; } + +void GpsL1CaPcpsAcquisition::set_resampler_latency(uint32_t latency_samples) +{ + acquisition_->set_resampler_latency(latency_samples); +} diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h index e5d8c4719..ebc8ec24b 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h @@ -142,6 +142,13 @@ public: */ 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; + + private: ConfigurationInterface* configuration_; pcps_acquisition_sptr acquisition_; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h index 4a4bb9a19..ce6860db5 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h @@ -132,6 +132,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: pcps_acquisition_fine_doppler_cc_sptr acquisition_cc_; size_t item_size_; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h index 4d0d7339f..015de1d39 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h @@ -140,6 +140,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; pcps_acquisition_fpga_sptr acquisition_fpga_; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h index 1f6094b6d..c3a21492a 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h @@ -128,6 +128,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: pcps_assisted_acquisition_cc_sptr acquisition_cc_; size_t item_size_; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_opencl_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_opencl_acquisition.h index 60c78b2e0..7e833ff89 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_opencl_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_opencl_acquisition.h @@ -130,6 +130,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; pcps_opencl_acquisition_cc_sptr acquisition_cc_; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_quicksync_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_quicksync_acquisition.h index e18fb1704..d032bf837 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_quicksync_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_quicksync_acquisition.h @@ -136,6 +136,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; pcps_quicksync_acquisition_cc_sptr acquisition_cc_; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_tong_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_tong_acquisition.h index 76cf2b8e0..1f342c31a 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_tong_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_tong_acquisition.h @@ -135,6 +135,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; pcps_tong_acquisition_cc_sptr acquisition_cc_; diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc index acf415635..8d914c3e5 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc @@ -52,7 +52,6 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( in_streams_(in_streams), out_streams_(out_streams) { - Acq_Conf acq_parameters = Acq_Conf(); configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./acquisition.mat"; @@ -60,42 +59,73 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( LOG(INFO) << "role " << role; item_type_ = configuration_->property(role + ".item_type", default_item_type); - //float pfa = configuration_->property(role + ".pfa", 0.0); - int64_t fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); - acq_parameters.fs_in = fs_in_; - acq_parameters.samples_per_chip = static_cast(ceil((1.0 / GPS_L2_M_CODE_RATE_HZ) * static_cast(acq_parameters.fs_in))); + acq_parameters_.fs_in = fs_in_; dump_ = configuration_->property(role + ".dump", false); - acq_parameters.dump = dump_; - acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0); + acq_parameters_.dump = dump_; + acq_parameters_.dump_channel = configuration_->property(role + ".dump_channel", 0); blocking_ = configuration_->property(role + ".blocking", true); - acq_parameters.blocking = blocking_; + acq_parameters_.blocking = blocking_; doppler_max_ = configuration->property(role + ".doppler_max", 5000); if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; - acq_parameters.doppler_max = doppler_max_; + acq_parameters_.doppler_max = doppler_max_; bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); - acq_parameters.bit_transition_flag = bit_transition_flag_; + acq_parameters_.bit_transition_flag = bit_transition_flag_; use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions - acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; + acq_parameters_.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; max_dwells_ = configuration_->property(role + ".max_dwells", 1); - acq_parameters.max_dwells = max_dwells_; + acq_parameters_.max_dwells = max_dwells_; dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); - acq_parameters.dump_filename = dump_filename_; - //--- Find number of samples per spreading code ------------------------- - acq_parameters.samples_per_ms = static_cast(fs_in_) * 0.001; - acq_parameters.ms_per_code = 20; - acq_parameters.sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", acq_parameters.ms_per_code); - if ((acq_parameters.sampled_ms % acq_parameters.ms_per_code) != 0) + acq_parameters_.dump_filename = dump_filename_; + acq_parameters_.ms_per_code = 20; + acq_parameters_.sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", acq_parameters_.ms_per_code); + if ((acq_parameters_.sampled_ms % acq_parameters_.ms_per_code) != 0) { LOG(WARNING) << "Parameter coherent_integration_time_ms should be a multiple of 20. Setting it to 20"; - acq_parameters.sampled_ms = acq_parameters.ms_per_code; + acq_parameters_.sampled_ms = acq_parameters_.ms_per_code; } - code_length_ = acq_parameters.ms_per_code * acq_parameters.samples_per_ms; + acq_parameters_.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); + acq_parameters_.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); + acq_parameters_.make_2_steps = configuration_->property(role + ".make_two_steps", false); + acq_parameters_.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); + acq_parameters_.use_automatic_resampler = configuration_->property("GNSS-SDR.use_acquisition_resampler", false); + if (acq_parameters_.use_automatic_resampler == true and item_type_.compare("gr_complex") != 0) + { + LOG(WARNING) << "GPS L2CM acquisition disabled the automatic resampler feature because its item_type is not set to gr_complex"; + acq_parameters_.use_automatic_resampler = false; + } + if (acq_parameters_.use_automatic_resampler) + { + if (acq_parameters_.fs_in > GPS_L2C_OPT_ACQ_FS_HZ) + { + acq_parameters_.resampler_ratio = floor(static_cast(acq_parameters_.fs_in) / GPS_L2C_OPT_ACQ_FS_HZ); + uint32_t decimation = acq_parameters_.fs_in / GPS_L2C_OPT_ACQ_FS_HZ; + while (acq_parameters_.fs_in % decimation > 0) + { + decimation--; + }; + acq_parameters_.resampler_ratio = decimation; + acq_parameters_.resampled_fs = acq_parameters_.fs_in / static_cast(acq_parameters_.resampler_ratio); + } - vector_length_ = acq_parameters.sampled_ms * acq_parameters.samples_per_ms * (acq_parameters.bit_transition_flag ? 2 : 1); + //--- Find number of samples per spreading code ------------------------- + code_length_ = static_cast(std::floor(static_cast(acq_parameters_.resampled_fs) / (GPS_L2_M_CODE_RATE_HZ / GPS_L2_M_CODE_LENGTH_CHIPS))); + acq_parameters_.samples_per_ms = static_cast(acq_parameters_.resampled_fs) * 0.001; + acq_parameters_.samples_per_chip = static_cast(ceil((1.0 / GPS_L2_M_CODE_RATE_HZ) * static_cast(acq_parameters_.resampled_fs))); + } + else + { + acq_parameters_.resampled_fs = fs_in_; + //--- Find number of samples per spreading code ------------------------- + code_length_ = static_cast(std::floor(static_cast(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / GPS_L2_M_CODE_LENGTH_CHIPS))); + acq_parameters_.samples_per_ms = static_cast(fs_in_) * 0.001; + acq_parameters_.samples_per_chip = static_cast(ceil((1.0 / GPS_L2_M_CODE_RATE_HZ) * static_cast(acq_parameters_.fs_in))); + } + acq_parameters_.samples_per_code = acq_parameters_.samples_per_ms * static_cast(GPS_L2_M_PERIOD * 1000.0); + vector_length_ = acq_parameters_.sampled_ms * acq_parameters_.samples_per_ms * (acq_parameters_.bit_transition_flag ? 2 : 1); code_ = new gr_complex[vector_length_]; if (item_type_ == "cshort") @@ -107,14 +137,8 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( item_size_ = sizeof(gr_complex); } - acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast(GPS_L2_M_PERIOD * 1000.0); - acq_parameters.it_size = item_size_; - - acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); - acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); - acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); - acq_parameters.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); - acquisition_ = pcps_make_acquisition(acq_parameters); + acq_parameters_.it_size = item_size_; + acquisition_ = pcps_make_acquisition(acq_parameters_); DLOG(INFO) << "acquisition(" << acquisition_->unique_id() << ")"; if (item_type_ == "cbyte") @@ -127,7 +151,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( threshold_ = 0.0; doppler_step_ = 0; gnss_synchro_ = nullptr; - num_codes_ = acq_parameters.sampled_ms / acq_parameters.ms_per_code; + num_codes_ = acq_parameters_.sampled_ms / acq_parameters_.ms_per_code; if (in_streams_ > 1) { LOG(ERROR) << "This implementation only supports one input stream"; @@ -223,7 +247,16 @@ void GpsL2MPcpsAcquisition::set_local_code() { auto* code = new std::complex[code_length_]; - gps_l2c_m_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_); + + if (acq_parameters_.use_automatic_resampler) + { + gps_l2c_m_code_gen_complex_sampled(code, gnss_synchro_->PRN, acq_parameters_.resampled_fs); + } + else + { + gps_l2c_m_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_); + } + for (unsigned int i = 0; i < num_codes_; i++) { @@ -341,3 +374,7 @@ gr::basic_block_sptr GpsL2MPcpsAcquisition::get_right_block() { return acquisition_; } +void GpsL2MPcpsAcquisition::set_resampler_latency(uint32_t latency_samples) +{ + acquisition_->set_resampler_latency(latency_samples); +} diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h index 4a0c96c60..a874a3585 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h @@ -139,9 +139,17 @@ public: */ 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; + + private: ConfigurationInterface* configuration_; pcps_acquisition_sptr acquisition_; + Acq_Conf acq_parameters_; gr::blocks::float_to_complex::sptr float_to_complex_; complex_byte_to_float_x2_sptr cbyte_to_float_x2_; size_t item_size_; diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h index 7effb0cf6..f60117a56 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h @@ -140,6 +140,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; //pcps_acquisition_sptr acquisition_; diff --git a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc index 16066ebaa..b74f33355 100644 --- a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc @@ -52,7 +52,6 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition( in_streams_(in_streams), out_streams_(out_streams) { - Acq_Conf acq_parameters = Acq_Conf(); configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./acquisition.mat"; @@ -63,32 +62,24 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition( int64_t fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); - acq_parameters.fs_in = fs_in_; - acq_parameters.samples_per_chip = static_cast(ceil((1.0 / GPS_L5i_CODE_RATE_HZ) * static_cast(acq_parameters.fs_in))); + acq_parameters_.fs_in = fs_in_; dump_ = configuration_->property(role + ".dump", false); - acq_parameters.dump = dump_; - acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0); + acq_parameters_.dump = dump_; + acq_parameters_.dump_channel = configuration_->property(role + ".dump_channel", 0); blocking_ = configuration_->property(role + ".blocking", true); - acq_parameters.blocking = blocking_; + acq_parameters_.blocking = blocking_; doppler_max_ = configuration->property(role + ".doppler_max", 5000); if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; - acq_parameters.doppler_max = doppler_max_; + acq_parameters_.doppler_max = doppler_max_; bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); - acq_parameters.bit_transition_flag = bit_transition_flag_; + acq_parameters_.bit_transition_flag = bit_transition_flag_; use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions - acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; + acq_parameters_.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; max_dwells_ = configuration_->property(role + ".max_dwells", 1); - acq_parameters.max_dwells = max_dwells_; + acq_parameters_.max_dwells = max_dwells_; dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); - acq_parameters.dump_filename = dump_filename_; - acq_parameters.sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1); - //--- Find number of samples per spreading code ------------------------- - code_length_ = static_cast(std::floor(static_cast(fs_in_) / (GPS_L5i_CODE_RATE_HZ / GPS_L5i_CODE_LENGTH_CHIPS))); - acq_parameters.samples_per_ms = static_cast(fs_in_) * 0.001; - acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast(GPS_L5i_PERIOD * 1000.0); - - vector_length_ = std::floor(acq_parameters.sampled_ms * acq_parameters.samples_per_ms) * (acq_parameters.bit_transition_flag ? 2 : 1); - code_ = new gr_complex[vector_length_]; + acq_parameters_.dump_filename = dump_filename_; + acq_parameters_.sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1); if (item_type_ == "cshort") { @@ -99,14 +90,51 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition( item_size_ = sizeof(gr_complex); } - acq_parameters.ms_per_code = 1; - acq_parameters.it_size = item_size_; - num_codes_ = acq_parameters.sampled_ms; - acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); - acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); - acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); - acq_parameters.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); - acquisition_ = pcps_make_acquisition(acq_parameters); + acq_parameters_.ms_per_code = 1; + acq_parameters_.it_size = item_size_; + num_codes_ = acq_parameters_.sampled_ms; + acq_parameters_.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); + acq_parameters_.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); + acq_parameters_.make_2_steps = configuration_->property(role + ".make_two_steps", false); + acq_parameters_.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); + acq_parameters_.use_automatic_resampler = configuration_->property("GNSS-SDR.use_acquisition_resampler", false); + if (acq_parameters_.use_automatic_resampler == true and item_type_.compare("gr_complex") != 0) + { + LOG(WARNING) << "GPS L5 acquisition disabled the automatic resampler feature because its item_type is not set to gr_complex"; + acq_parameters_.use_automatic_resampler = false; + } + if (acq_parameters_.use_automatic_resampler) + { + if (acq_parameters_.fs_in > GPS_L5_OPT_ACQ_FS_HZ) + { + acq_parameters_.resampler_ratio = floor(static_cast(acq_parameters_.fs_in) / GPS_L5_OPT_ACQ_FS_HZ); + uint32_t decimation = acq_parameters_.fs_in / GPS_L5_OPT_ACQ_FS_HZ; + while (acq_parameters_.fs_in % decimation > 0) + { + decimation--; + }; + acq_parameters_.resampler_ratio = decimation; + acq_parameters_.resampled_fs = acq_parameters_.fs_in / static_cast(acq_parameters_.resampler_ratio); + } + + //--- Find number of samples per spreading code ------------------------- + code_length_ = static_cast(std::floor(static_cast(acq_parameters_.resampled_fs) / (GPS_L5i_CODE_RATE_HZ / GPS_L5i_CODE_LENGTH_CHIPS))); + acq_parameters_.samples_per_ms = static_cast(acq_parameters_.resampled_fs) * 0.001; + acq_parameters_.samples_per_chip = static_cast(ceil((1.0 / GPS_L5i_CODE_RATE_HZ) * static_cast(acq_parameters_.resampled_fs))); + } + else + { + acq_parameters_.resampled_fs = fs_in_; + //--- Find number of samples per spreading code ------------------------- + code_length_ = static_cast(std::floor(static_cast(fs_in_) / (GPS_L5i_CODE_RATE_HZ / GPS_L5i_CODE_LENGTH_CHIPS))); + acq_parameters_.samples_per_ms = static_cast(fs_in_) * 0.001; + acq_parameters_.samples_per_chip = static_cast(ceil((1.0 / GPS_L5i_CODE_RATE_HZ) * static_cast(acq_parameters_.fs_in))); + } + + acq_parameters_.samples_per_code = acq_parameters_.samples_per_ms * static_cast(GPS_L5i_PERIOD * 1000.0); + vector_length_ = std::floor(acq_parameters_.sampled_ms * acq_parameters_.samples_per_ms) * (acq_parameters_.bit_transition_flag ? 2 : 1); + code_ = new gr_complex[vector_length_]; + acquisition_ = pcps_make_acquisition(acq_parameters_); DLOG(INFO) << "acquisition(" << acquisition_->unique_id() << ")"; if (item_type_ == "cbyte") @@ -114,6 +142,7 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition( cbyte_to_float_x2_ = make_complex_byte_to_float_x2(); float_to_complex_ = gr::blocks::float_to_complex::make(); } + channel_ = 0; threshold_ = 0.0; doppler_step_ = 0; @@ -211,7 +240,15 @@ void GpsL5iPcpsAcquisition::set_local_code() { auto* code = new std::complex[code_length_]; - gps_l5i_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_); + + if (acq_parameters_.use_automatic_resampler) + { + gps_l5i_code_gen_complex_sampled(code, gnss_synchro_->PRN, acq_parameters_.resampled_fs); + } + else + { + gps_l5i_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_); + } for (unsigned int i = 0; i < num_codes_; i++) { @@ -329,3 +366,8 @@ gr::basic_block_sptr GpsL5iPcpsAcquisition::get_right_block() { return acquisition_; } + +void GpsL5iPcpsAcquisition::set_resampler_latency(uint32_t latency_samples) +{ + acquisition_->set_resampler_latency(latency_samples); +} diff --git a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.h b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.h index c9f1cd95d..f3cf863f3 100644 --- a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.h @@ -139,9 +139,16 @@ public: */ 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; + private: ConfigurationInterface* configuration_; pcps_acquisition_sptr acquisition_; + Acq_Conf acq_parameters_; gr::blocks::float_to_complex::sptr float_to_complex_; complex_byte_to_float_x2_sptr cbyte_to_float_x2_; size_t item_size_; diff --git a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h index 571f01193..a7d45db10 100644 --- a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h @@ -140,6 +140,8 @@ public: */ void stop_acquisition() override; + void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{}; + private: ConfigurationInterface* configuration_; //pcps_acquisition_sptr acquisition_; diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc index 7e666d0b3..a08bd05f2 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc @@ -221,6 +221,12 @@ pcps_acquisition::~pcps_acquisition() } +void pcps_acquisition::set_resampler_latency(uint32_t latency_samples) +{ + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler + acq_parameters.resampler_latency_samples = latency_samples; +} + void pcps_acquisition::set_local_code(std::complex* code) { // reset the intermediate frequency @@ -731,6 +737,7 @@ void pcps_acquisition::acquisition_core(uint64_t samp_count) { //take into account the acquisition resampler ratio d_gnss_synchro->Acq_delay_samples = static_cast(std::fmod(static_cast(indext), acq_parameters.samples_per_code)) * acq_parameters.resampler_ratio; + d_gnss_synchro->Acq_delay_samples -= static_cast(acq_parameters.resampler_latency_samples); //account the resampler filter latency d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); d_gnss_synchro->Acq_samplestamp_samples = rint(static_cast(samp_count) * acq_parameters.resampler_ratio); } @@ -788,6 +795,7 @@ void pcps_acquisition::acquisition_core(uint64_t samp_count) { //take into account the acquisition resampler ratio d_gnss_synchro->Acq_delay_samples = static_cast(std::fmod(static_cast(indext), acq_parameters.samples_per_code)) * acq_parameters.resampler_ratio; + d_gnss_synchro->Acq_delay_samples -= static_cast(acq_parameters.resampler_latency_samples); //account the resampler filter latency d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); d_gnss_synchro->Acq_samplestamp_samples = rint(static_cast(samp_count) * acq_parameters.resampler_ratio); d_gnss_synchro->Acq_doppler_step = acq_parameters.doppler_step2; diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h index 392332e46..f7089412b 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h @@ -237,6 +237,8 @@ public: } + void set_resampler_latency(uint32_t latency_samples); + /*! * \brief Parallel Code Phase Search Acquisition signal processing. */ diff --git a/src/algorithms/acquisition/libs/acq_conf.cc b/src/algorithms/acquisition/libs/acq_conf.cc index 0640153cf..8e8d48d5e 100644 --- a/src/algorithms/acquisition/libs/acq_conf.cc +++ b/src/algorithms/acquisition/libs/acq_conf.cc @@ -56,4 +56,5 @@ Acq_Conf::Acq_Conf() use_automatic_resampler = false; resampler_ratio = 1.0; resampled_fs = 0LL; + resampler_latency_samples = 0U; } diff --git a/src/algorithms/acquisition/libs/acq_conf.h b/src/algorithms/acquisition/libs/acq_conf.h index 7582ec9a3..af81d8806 100644 --- a/src/algorithms/acquisition/libs/acq_conf.h +++ b/src/algorithms/acquisition/libs/acq_conf.h @@ -59,6 +59,7 @@ public: bool use_automatic_resampler; float resampler_ratio; int64_t resampled_fs; + uint32_t resampler_latency_samples; std::string dump_filename; uint32_t dump_channel; size_t it_size; diff --git a/src/core/interfaces/acquisition_interface.h b/src/core/interfaces/acquisition_interface.h index d76e79bfc..794748175 100644 --- a/src/core/interfaces/acquisition_interface.h +++ b/src/core/interfaces/acquisition_interface.h @@ -65,6 +65,7 @@ public: virtual signed int mag() = 0; virtual void reset() = 0; virtual void stop_acquisition() = 0; + virtual void set_resampler_latency(uint32_t latency_samples) = 0; }; #endif /* GNSS_SDR_ACQUISITION_INTERFACE */ diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index 96d6f565a..dcb3b4c48 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -43,11 +43,13 @@ #include "gnss_block_interface.h" #include "channel_interface.h" #include "gnss_block_factory.h" +#include "channel.h" #ifdef GR_GREATER_38 -#include +#include #else -#include +#include #endif +#include #include #include #include @@ -354,7 +356,7 @@ void GNSSFlowgraph::connect() // Signal conditioner (selected_signal_source) >> channels (i) (dependent of their associated SignalSource_ID) int selected_signal_conditioner_ID = 0; bool use_acq_resampler = configuration_->property("GNSS-SDR.use_acquisition_resampler", false); - double fs = static_cast(configuration_->property("GNSS-SDR.internal_fs_sps", 0)); + uint32_t fs = configuration_->property("GNSS-SDR.internal_fs_sps", 0); for (unsigned int i = 0; i < channels_count_; i++) { if (FPGA_enabled == false) @@ -369,9 +371,6 @@ void GNSSFlowgraph::connect() } try { - // top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, - // channels_.at(i)->get_left_block(), 0); - // Enable automatic resampler for the acquisition, if required if (use_acq_resampler == true) { @@ -397,7 +396,7 @@ void GNSSFlowgraph::connect() acq_fs = Galileo_E1_OPT_ACQ_FS_HZ; break; case evGAL_5X: - acq_fs = fs; + acq_fs = Galileo_E5a_OPT_ACQ_FS_HZ; break; case evGLO_1G: acq_fs = fs; @@ -406,47 +405,72 @@ void GNSSFlowgraph::connect() acq_fs = fs; break; } + if (acq_fs < fs) { //check if the resampler is already created for the channel system/signal and for the specific RF Channel std::string map_key = channels_.at(i)->implementation() + std::to_string(selected_signal_conditioner_ID); - - resampler_ratio = fs / acq_fs; - - gr::basic_block_sptr tmp_blk; -#ifdef GR_GREATER_38 - tmp_blk = gr::filter::mmse_resampler_cc::make(0.0, resampler_ratio); -#else - tmp_blk = gr::filter::fractional_resampler_cc::make(0.0, resampler_ratio); -#endif - - std::pair::iterator, bool> ret; - ret = acq_resamplers_.insert(std::pair(map_key, tmp_blk)); - if (ret.second == true) + resampler_ratio = static_cast(fs) / acq_fs; + int decimation = floor(resampler_ratio); + while (fs % decimation > 0) { + decimation--; + }; + double acq_fs = fs / decimation; + + if (decimation > 1) + { + //create a FIR low pass filter + std::vector taps; + taps = gr::filter::firdes::low_pass(1.0, + fs, + acq_fs / 2.1, + acq_fs / 10, + gr::filter::firdes::win_type::WIN_HAMMING); + + gr::basic_block_sptr fir_filter_ccf_ = gr::filter::fir_filter_ccf::make(decimation, taps); + + std::pair::iterator, bool> ret; + ret = acq_resamplers_.insert(std::pair(map_key, fir_filter_ccf_)); + if (ret.second == true) + { + top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, + acq_resamplers_.at(map_key), 0); + LOG(INFO) << "Created " + << channels_.at(i)->implementation() + << " acquisition resampler for RF channel " << std::to_string(signal_conditioner_ID) << " with " << taps.size() << " taps and decimation factor of " << decimation; + } + else + { + LOG(INFO) << "Found existing " + << channels_.at(i)->implementation() + << " acquisition resampler for RF channel " << std::to_string(signal_conditioner_ID) << " with " << taps.size() << " taps and decimation factor of " << decimation; + } + + + top_block_->connect(acq_resamplers_.at(map_key), 0, + channels_.at(i)->get_left_block_acq(), 0); + top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, - acq_resamplers_.at(map_key), 0); - LOG(INFO) << "Created " - << channels_.at(i)->implementation() - << " acquisition resampler for RF channel " << std::to_string(signal_conditioner_ID) << " with ratio " << resampler_ratio; + channels_.at(i)->get_left_block_trk(), 0); + + std::shared_ptr channel_ptr; + channel_ptr = std::dynamic_pointer_cast(channels_.at(i)); + channel_ptr->acquisition()->set_resampler_latency((taps.size() - 1) / 2); } else { - LOG(INFO) << "Found " - << channels_.at(i)->implementation() - << " acquisition resampler for RF channel " << std::to_string(signal_conditioner_ID) << " with ratio " << resampler_ratio; + LOG(INFO) << "Disabled acquisition resampler because the input sampling frequency is too low"; + //resampler not required! + top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, + channels_.at(i)->get_left_block_acq(), 0); + top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, + channels_.at(i)->get_left_block_trk(), 0); } - - - top_block_->connect(acq_resamplers_.at(map_key), 0, - channels_.at(i)->get_left_block_acq(), 0); - - top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, - channels_.at(i)->get_left_block_trk(), 0); } else { - //resampler not required! + LOG(INFO) << "Disabled acquisition resampler because the input sampling frequency is too low"; top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, channels_.at(i)->get_left_block_acq(), 0); top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, diff --git a/src/core/system_parameters/GPS_L1_CA.h b/src/core/system_parameters/GPS_L1_CA.h index f14b9f2f2..8388e825a 100644 --- a/src/core/system_parameters/GPS_L1_CA.h +++ b/src/core/system_parameters/GPS_L1_CA.h @@ -58,7 +58,7 @@ const uint32_t GPS_L1_CA_CODE_PERIOD_MS = 1U; //!< GPS L1 C/A code period const double GPS_L1_CA_CHIP_PERIOD = 9.7752e-07; //!< GPS L1 C/A chip period [seconds] //optimum parameters -const uint32_t GPS_L1_CA_OPT_ACQ_FS_HZ = 2000000; //!< Sampling frequncy that maximizes the acquisition SNR while using a non-multiple of chip rate +const uint32_t GPS_L1_CA_OPT_ACQ_FS_HZ = 1000000; //!< Sampling frequncy that maximizes the acquisition SNR while using a non-multiple of chip rate /*! * \brief Maximum Time-Of-Arrival (TOA) difference between satellites for a receiver operated on Earth surface is 20 ms diff --git a/src/core/system_parameters/GPS_L2C.h b/src/core/system_parameters/GPS_L2C.h index 28257a204..1a148fed2 100644 --- a/src/core/system_parameters/GPS_L2C.h +++ b/src/core/system_parameters/GPS_L2C.h @@ -64,7 +64,7 @@ const double GPS_L2_L_PERIOD = 1.5; //!< GPS L2 L code period [s const int32_t GPS_L2C_HISTORY_DEEP = 5; //optimum parameters -const uint32_t GPS_L2C_OPT_ACQ_FS_HZ = 2000000; //!< Sampling frequncy that maximizes the acquisition SNR while using a non-multiple of chip rate +const uint32_t GPS_L2C_OPT_ACQ_FS_HZ = 1000000; //!< Sampling frequncy that maximizes the acquisition SNR while using a non-multiple of chip rate const int32_t GPS_L2C_M_INIT_REG[115] = diff --git a/src/core/system_parameters/GPS_L5.h b/src/core/system_parameters/GPS_L5.h index f12c0c14a..a78b07143 100644 --- a/src/core/system_parameters/GPS_L5.h +++ b/src/core/system_parameters/GPS_L5.h @@ -65,7 +65,7 @@ const double GPS_L5q_PERIOD = 0.001; //!< GPS L5 code period [secon const int32_t GPS_L5_HISTORY_DEEP = 5; //optimum parameters -const uint32_t GPS_L5_OPT_ACQ_FS_HZ = 10000000; +const uint32_t GPS_L5_OPT_ACQ_FS_HZ = 10000000; //!< Sampling frequncy that maximizes the acquisition SNR while using a non-multiple of chip rate const int32_t GPS_L5i_INIT_REG[210] = {266, 365, 804, 1138, diff --git a/src/core/system_parameters/Galileo_E1.h b/src/core/system_parameters/Galileo_E1.h index 333877ac3..0c4c93b7a 100644 --- a/src/core/system_parameters/Galileo_E1.h +++ b/src/core/system_parameters/Galileo_E1.h @@ -65,7 +65,7 @@ const int32_t Galileo_E1_NUMBER_OF_CODES = 50; //optimum parameters -const uint32_t Galileo_E1_OPT_ACQ_FS_HZ = 4000000; //!< Sampling frequncy that maximizes the acquisition SNR while using a non-multiple of chip rate +const uint32_t Galileo_E1_OPT_ACQ_FS_HZ = 2000000; //!< Sampling frequncy that maximizes the acquisition SNR while using a non-multiple of chip rate const double GALILEO_STARTOFFSET_ms = 68.802; //[ms] Initial sign. travel time (this cannot go here) diff --git a/src/core/system_parameters/Galileo_E5a.h b/src/core/system_parameters/Galileo_E5a.h index 6e37cde77..7499a0d08 100644 --- a/src/core/system_parameters/Galileo_E5a.h +++ b/src/core/system_parameters/Galileo_E5a.h @@ -58,7 +58,7 @@ const int32_t GALILEO_E5A_HISTORY_DEEP = 20; const int32_t GALILEO_E5A_CRC_ERROR_LIMIT = 6; //optimum parameters -const uint32_t Galileo_E5A_OPT_ACQ_FS_HZ = 10000000; +const uint32_t Galileo_E5a_OPT_ACQ_FS_HZ = 10000000; //!< Sampling frequncy that maximizes the acquisition SNR while using a non-multiple of chip rate // F/NAV message structure diff --git a/src/tests/system-tests/position_test.cc b/src/tests/system-tests/position_test.cc index e5efd2150..a1e550ea5 100644 --- a/src/tests/system-tests/position_test.cc +++ b/src/tests/system-tests/position_test.cc @@ -45,6 +45,7 @@ #include "gnuplot_i.h" #include "test_flags.h" #include "signal_generator_flags.h" +#include "tracking_tests_flags.h" //acquisition resampler #include #include #include @@ -184,6 +185,11 @@ int PositionSystemTest::configure_receiver() const int output_rate_ms = 100; config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(sampling_rate_internal)); + // Enable automatic resampler for the acquisition, if required + if (FLAGS_use_acquisition_resampler == true) + { + config->set_property("GNSS-SDR.use_acquisition_resampler", "true"); + } // Set the assistance system parameters config->set_property("GNSS-SDR.SUPL_read_gps_assistance_xml", "false"); diff --git a/src/tests/unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc b/src/tests/unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc index 4883b3c60..af18d5b28 100644 --- a/src/tests/unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc @@ -30,6 +30,11 @@ * ------------------------------------------------------------------------- */ +#include "GPS_L1_CA.h" +#include "Galileo_E1.h" +#include "GPS_L2C.h" +#include "GPS_L5.h" +#include "Galileo_E5a.h" #include #include #include @@ -38,6 +43,12 @@ #include #include #include +#ifdef GR_GREATER_38 +#include +#else +#include +#endif +#include #include #include #include @@ -45,7 +56,6 @@ #include #include #include -#include "GPS_L1_CA.h" #include "gnss_satellite.h" #include "gnss_block_factory.h" #include "gnss_block_interface.h" @@ -186,6 +196,19 @@ HybridObservablesTest_tlm_msg_rx::~HybridObservablesTest_tlm_msg_rx() class HybridObservablesTest : public ::testing::Test { public: + enum StringValue + { + evGPS_1C, + evGPS_2S, + evGPS_L5, + evSBAS_1C, + evGAL_1B, + evGAL_5X, + evGLO_1G, + evGLO_2G + }; + std::map mapStringValues_; + std::string generator_binary; std::string p1; std::string p2; @@ -247,6 +270,13 @@ public: factory = std::make_shared(); config = std::make_shared(); item_size = sizeof(gr_complex); + mapStringValues_["1C"] = evGPS_1C; + mapStringValues_["2S"] = evGPS_2S; + mapStringValues_["L5"] = evGPS_L5; + mapStringValues_["1B"] = evGAL_1B; + mapStringValues_["5X"] = evGAL_5X; + mapStringValues_["1G"] = evGLO_1G; + mapStringValues_["2G"] = evGLO_2G; } ~HybridObservablesTest() @@ -328,6 +358,11 @@ bool HybridObservablesTest::acquire_signal() tmp_gnss_synchro.Channel_ID = 0; config = std::make_shared(); config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq)); + // Enable automatic resampler for the acquisition, if required + if (FLAGS_use_acquisition_resampler == true) + { + config->set_property("GNSS-SDR.use_acquisition_resampler", "true"); + } config->set_property("Acquisition.blocking_on_standby", "true"); config->set_property("Acquisition.blocking", "true"); config->set_property("Acquisition.dump", "false"); @@ -337,11 +372,12 @@ bool HybridObservablesTest::acquire_signal() std::shared_ptr acquisition; std::string System_and_Signal; + std::string signal; //create the correspondign acquisition block according to the desired tracking signal if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking") == 0) { tmp_gnss_synchro.System = 'G'; - std::string signal = "1C"; + signal = "1C"; const char* str = signal.c_str(); // get a C style null terminated string std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null tmp_gnss_synchro.PRN = SV_ID; @@ -353,7 +389,7 @@ bool HybridObservablesTest::acquire_signal() else if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking") == 0) { tmp_gnss_synchro.System = 'E'; - std::string signal = "1B"; + signal = "1B"; const char* str = signal.c_str(); // get a C style null terminated string std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null tmp_gnss_synchro.PRN = SV_ID; @@ -364,7 +400,7 @@ bool HybridObservablesTest::acquire_signal() else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking") == 0) { tmp_gnss_synchro.System = 'G'; - std::string signal = "2S"; + signal = "2S"; const char* str = signal.c_str(); // get a C style null terminated string std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null tmp_gnss_synchro.PRN = SV_ID; @@ -375,7 +411,7 @@ bool HybridObservablesTest::acquire_signal() else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking_b") == 0) { tmp_gnss_synchro.System = 'E'; - std::string signal = "5X"; + signal = "5X"; const char* str = signal.c_str(); // get a C style null terminated string std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null tmp_gnss_synchro.PRN = SV_ID; @@ -391,7 +427,7 @@ bool HybridObservablesTest::acquire_signal() else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking") == 0) { tmp_gnss_synchro.System = 'E'; - std::string signal = "5X"; + signal = "5X"; const char* str = signal.c_str(); // get a C style null terminated string std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null tmp_gnss_synchro.PRN = SV_ID; @@ -402,7 +438,7 @@ bool HybridObservablesTest::acquire_signal() else if (implementation.compare("GPS_L5_DLL_PLL_Tracking") == 0) { tmp_gnss_synchro.System = 'G'; - std::string signal = "L5"; + signal = "L5"; const char* str = signal.c_str(); // get a C style null terminated string std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null tmp_gnss_synchro.PRN = SV_ID; @@ -433,10 +469,88 @@ bool HybridObservablesTest::acquire_signal() file_source->seek(2 * FLAGS_skip_samples, 0); //skip head. ibyte, two bytes per complex sample gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make(); //gr::blocks::head::sptr head_samples = gr::blocks::head::make(sizeof(gr_complex), baseband_sampling_freq * FLAGS_duration); + //top_block->connect(head_samples, 0, acquisition->get_left_block(), 0); top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0); - top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0); - //top_block->connect(head_samples, 0, acquisition->get_left_block(), 0); + + // Enable automatic resampler for the acquisition, if required + if (FLAGS_use_acquisition_resampler == true) + { + //create acquisition resamplers if required + double resampler_ratio = 1.0; + + double opt_fs = baseband_sampling_freq; + //find the signal associated to this channel + switch (mapStringValues_[signal]) + { + case evGPS_1C: + opt_fs = GPS_L1_CA_OPT_ACQ_FS_HZ; + break; + case evGPS_2S: + opt_fs = GPS_L2C_OPT_ACQ_FS_HZ; + break; + case evGPS_L5: + opt_fs = GPS_L5_OPT_ACQ_FS_HZ; + break; + case evSBAS_1C: + opt_fs = GPS_L1_CA_OPT_ACQ_FS_HZ; + break; + case evGAL_1B: + opt_fs = Galileo_E1_OPT_ACQ_FS_HZ; + break; + case evGAL_5X: + opt_fs = Galileo_E5a_OPT_ACQ_FS_HZ; + break; + case evGLO_1G: + opt_fs = baseband_sampling_freq; + break; + case evGLO_2G: + opt_fs = baseband_sampling_freq; + break; + } + if (opt_fs < baseband_sampling_freq) + { + resampler_ratio = baseband_sampling_freq / opt_fs; + int decimation = floor(resampler_ratio); + while (baseband_sampling_freq % decimation > 0) + { + decimation--; + }; + double acq_fs = baseband_sampling_freq / decimation; + + if (decimation > 1) + { + //create a FIR low pass filter + std::vector taps; + taps = gr::filter::firdes::low_pass(1.0, + baseband_sampling_freq, + acq_fs / 2.1, + acq_fs / 10, + gr::filter::firdes::win_type::WIN_HAMMING); + std::cout << "Enabled decimation low pass filter with " << taps.size() << " taps and decimation factor of " << decimation << std::endl; + acquisition->set_resampler_latency((taps.size() - 1) / 2); + gr::basic_block_sptr fir_filter_ccf_ = gr::filter::fir_filter_ccf::make(decimation, taps); + top_block->connect(gr_interleaved_char_to_complex, 0, fir_filter_ccf_, 0); + top_block->connect(fir_filter_ccf_, 0, acquisition->get_left_block(), 0); + } + else + { + std::cout << "Disabled acquisition resampler because the input sampling frequency is too low\n"; + top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0); + } + } + else + { + std::cout << "Disabled acquisition resampler because the input sampling frequency is too low\n"; + top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0); + } + } + else + { + top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0); + //top_block->connect(head_samples, 0, acquisition->get_left_block(), 0); + } + boost::shared_ptr msg_rx; try diff --git a/src/tests/unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test.cc b/src/tests/unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test.cc index ba63a7f18..99aabdce2 100644 --- a/src/tests/unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test.cc @@ -58,10 +58,8 @@ #include #ifdef GR_GREATER_38 -#include #include #else -#include #include #endif #include @@ -322,7 +320,7 @@ void TrackingPullInTest::configure_receiver( System_and_Signal = "GPS L2CM"; signal.copy(gnss_synchro.Signal, 2, 0); config->set_property("Tracking.early_late_space_chips", "0.5"); - config->set_property("Tracking.track_pilot", "false"); + config->set_property("Tracking.track_pilot", "true"); } else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking") == 0 or implementation.compare("Galileo_E5a_DLL_PLL_Tracking_b") == 0) { @@ -335,7 +333,7 @@ void TrackingPullInTest::configure_receiver( config->supersede_property("Tracking.implementation", std::string("Galileo_E5a_DLL_PLL_Tracking")); } config->set_property("Tracking.early_late_space_chips", "0.5"); - config->set_property("Tracking.track_pilot", "false"); + config->set_property("Tracking.track_pilot", "true"); config->set_property("Tracking.order", "2"); } else if (implementation.compare("GPS_L5_DLL_PLL_Tracking") == 0) @@ -345,7 +343,7 @@ void TrackingPullInTest::configure_receiver( System_and_Signal = "GPS L5I"; signal.copy(gnss_synchro.Signal, 2, 0); config->set_property("Tracking.early_late_space_chips", "0.5"); - config->set_property("Tracking.track_pilot", "false"); + config->set_property("Tracking.track_pilot", "true"); config->set_property("Tracking.order", "2"); } else @@ -497,8 +495,6 @@ bool TrackingPullInTest::acquire_signal(int SV_ID) top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0); // Enable automatic resampler for the acquisition, if required - std::vector taps; - int decimation = 1; if (FLAGS_use_acquisition_resampler == true) { //create acquisition resamplers if required @@ -524,7 +520,7 @@ bool TrackingPullInTest::acquire_signal(int SV_ID) opt_fs = Galileo_E1_OPT_ACQ_FS_HZ; break; case evGAL_5X: - opt_fs = baseband_sampling_freq; + opt_fs = Galileo_E5a_OPT_ACQ_FS_HZ; break; case evGLO_1G: opt_fs = baseband_sampling_freq; @@ -536,30 +532,38 @@ bool TrackingPullInTest::acquire_signal(int SV_ID) if (opt_fs < baseband_sampling_freq) { resampler_ratio = baseband_sampling_freq / opt_fs; - decimation = floor(resampler_ratio); + int decimation = floor(resampler_ratio); while (baseband_sampling_freq % decimation > 0) { decimation--; }; double acq_fs = baseband_sampling_freq / decimation; - //create a FIR low pass filter - taps = gr::filter::firdes::low_pass(1.0, - baseband_sampling_freq, - acq_fs / 2.1, - acq_fs / 20, - gr::filter::firdes::win_type::WIN_HAMMING); - std::cout << "Enabled decimation low pass filter with " << taps.size() << " taps and decimation factor of " << decimation << std::endl; - gr::basic_block_sptr fir_filter_ccf_ = gr::filter::fir_filter_ccf::make(decimation, taps); - - //#ifdef GR_GREATER_38 - // gr::basic_block_sptr resampler = gr::filter::mmse_resampler_cc::make(0.0, resampler_ratio); - //#else - // gr::basic_block_sptr resampler = gr::filter::fractional_resampler_cc::make(0.0, resampler_ratio); - //#endif - top_block->connect(gr_interleaved_char_to_complex, 0, fir_filter_ccf_, 0); - // top_block->connect(fir_filter_ccf_, 0, resampler, 0); - top_block->connect(fir_filter_ccf_, 0, acquisition->get_left_block(), 0); + if (decimation > 1) + { + //create a FIR low pass filter + std::vector taps; + taps = gr::filter::firdes::low_pass(1.0, + baseband_sampling_freq, + acq_fs / 2.1, + acq_fs / 10, + gr::filter::firdes::win_type::WIN_HAMMING); + std::cout << "Enabled decimation low pass filter with " << taps.size() << " taps and decimation factor of " << decimation << std::endl; + acquisition->set_resampler_latency((taps.size() - 1) / 2); + gr::basic_block_sptr fir_filter_ccf_ = gr::filter::fir_filter_ccf::make(decimation, taps); + top_block->connect(gr_interleaved_char_to_complex, 0, fir_filter_ccf_, 0); + top_block->connect(fir_filter_ccf_, 0, acquisition->get_left_block(), 0); + } + else + { + std::cout << "Disabled acquisition resampler because the input sampling frequency is too low\n"; + top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0); + } + } + else + { + std::cout << "Disabled acquisition resampler because the input sampling frequency is too low\n"; + top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0); } } else @@ -567,6 +571,8 @@ bool TrackingPullInTest::acquire_signal(int SV_ID) top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0); //top_block->connect(head_samples, 0, acquisition->get_left_block(), 0); } + + boost::shared_ptr msg_rx; try { @@ -633,17 +639,8 @@ bool TrackingPullInTest::acquire_signal(int SV_ID) { std::cout << " " << PRN << " "; doppler_measurements_map.insert(std::pair(PRN, tmp_gnss_synchro.Acq_doppler_hz)); - - if (FLAGS_use_acquisition_resampler == true) - { - code_delay_measurements_map.insert(std::pair(PRN, tmp_gnss_synchro.Acq_delay_samples - (taps.size()) / 2)); - acq_samplestamp_map.insert(std::pair(PRN, tmp_gnss_synchro.Acq_samplestamp_samples)); - } - else - { - code_delay_measurements_map.insert(std::pair(PRN, tmp_gnss_synchro.Acq_delay_samples)); - acq_samplestamp_map.insert(std::pair(PRN, tmp_gnss_synchro.Acq_samplestamp_samples)); - } + code_delay_measurements_map.insert(std::pair(PRN, tmp_gnss_synchro.Acq_delay_samples)); + acq_samplestamp_map.insert(std::pair(PRN, tmp_gnss_synchro.Acq_samplestamp_samples)); } else {