From b9229657468f0f0238f09d84ba7931d1ddd575f9 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 13 Jul 2018 00:16:57 +0200 Subject: [PATCH 1/6] Fix number of read samples --- .../acquisition/acq_performance_test.cc | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc index 312085442..032b575ba 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc @@ -64,9 +64,9 @@ DEFINE_double(acq_test_cn0_init, 33.0, "Initial CN0, in dBHz."); DEFINE_double(acq_test_cn0_final, 45.0, "Final CN0, in dBHz."); DEFINE_double(acq_test_cn0_step, 3.0, "CN0 step, in dB."); -DEFINE_double(acq_test_threshold_init, 11.0, "Initial acquisition threshold"); -DEFINE_double(acq_test_threshold_final, 16.0, "Final acquisition threshold"); -DEFINE_double(acq_test_threshold_step, 1.0, "Acquisition threshold step"); +DEFINE_double(acq_test_threshold_init, 3.0, "Initial acquisition threshold"); +DEFINE_double(acq_test_threshold_final, 4.0, "Final acquisition threshold"); +DEFINE_double(acq_test_threshold_step, 0.5, "Acquisition threshold step"); DEFINE_double(acq_test_pfa_init, 1e-5, "Set initial threshold via probability of false alarm. Disable with -1.0"); @@ -165,17 +165,20 @@ protected: signal_id = "1C"; system_id = 'G'; coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; + min_integration_ms = 1; } else if (implementation.compare("GPS_L1_CA_PCPS_Acquisition_Fine_Doppler") == 0) { signal_id = "1C"; system_id = 'G'; coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; + min_integration_ms = 1; } else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0) { signal_id = "1B"; system_id = 'E'; + min_integration_ms = 4; if (FLAGS_acq_test_coherent_time_ms == 1) { coherent_integration_time_ms = 4; @@ -190,12 +193,14 @@ protected: signal_id = "1G"; system_id = 'R'; coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; + min_integration_ms = 1; } else if (implementation.compare("GLONASS_L2_CA_PCPS_Acquisition") == 0) { signal_id = "2G"; system_id = 'R'; coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; + min_integration_ms = 1; } else if (implementation.compare("GPS_L2_M_PCPS_Acquisition") == 0) { @@ -209,12 +214,14 @@ protected: { coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; } + min_integration_ms = 20; } else if (implementation.compare("Galileo_E5a_Pcps_Acquisition") == 0) { signal_id = "5X"; system_id = 'E'; coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; + min_integration_ms = 1; } else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0) { @@ -227,6 +234,7 @@ protected: signal_id = "1C"; system_id = 'G'; coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; + min_integration_ms = 1; } init(); @@ -327,6 +335,7 @@ protected: std::string path_str = "./acq-perf-test"; int num_thresholds; + unsigned int min_integration_ms; std::vector> Pd; std::vector> Pfa; @@ -804,9 +813,27 @@ TEST_F(AcquisitionPerformanceTest, ROC) double coh_time_ms = config->property("Acquisition.coherent_integration_time_ms", 1); std::cout << "Num executions: " << num_executions << std::endl; + + unsigned int fft_size = 0; + unsigned int d_consumed_samples = coh_time_ms * config->property("GNSS-SDR.internal_fs_sps", 0) * 0.001; // * (config->property("Acquisition.bit_transition_flag", false) ? 2 : 1); + if (coh_time_ms == min_integration_ms) + { + fft_size = d_consumed_samples; + } + else + { + fft_size = d_consumed_samples * 2; + } + for (int execution = 1; execution <= num_executions; execution++) { - acquisition_dump_reader acq_dump(basename, observed_satellite, config->property("Acquisition.doppler_max", 0), config->property("Acquisition.doppler_step", 0), config->property("GNSS-SDR.internal_fs_sps", 0) * GPS_L1_CA_CODE_PERIOD * static_cast(coh_time_ms) * (config->property("Acquisition.bit_transition_flag", false) ? 2 : 1), ch, execution); + acquisition_dump_reader acq_dump(basename, + observed_satellite, + config->property("Acquisition.doppler_max", 0), + config->property("Acquisition.doppler_step", 0), + fft_size, + ch, + execution); acq_dump.read_binary_acq(); if (acq_dump.positive_acq) { From b779f5cb3d50118d4f5ae2b62c7b8b0b12181389 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Fri, 13 Jul 2018 10:32:24 +0200 Subject: [PATCH 2/6] Fix incoherence between the number of samples per code in GPS L2 acquisition --- .../acquisition/adapters/gps_l2_m_pcps_acquisition.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 132c5ff1c..301bc14a5 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc @@ -78,8 +78,11 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); acq_parameters.dump_filename = dump_filename_; //--- Find number of samples per spreading code ------------------------- - code_length_ = std::round(static_cast(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast(GPS_L2_M_CODE_LENGTH_CHIPS))); + //code_length_ = std::round(static_cast(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast(GPS_L2_M_CODE_LENGTH_CHIPS))); + acq_parameters.samples_per_ms = static_cast(std::round(static_cast(fs_in_) * 0.001)); + acq_parameters.sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 20); + code_length_ = acq_parameters.sampled_ms * acq_parameters.samples_per_ms * (acq_parameters.bit_transition_flag ? 2 : 1); vector_length_ = code_length_; if (bit_transition_flag_) @@ -97,10 +100,10 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( { item_size_ = sizeof(gr_complex); } - acq_parameters.samples_per_ms = static_cast(std::round(static_cast(fs_in_) * 0.001)); + acq_parameters.samples_per_code = code_length_; acq_parameters.it_size = item_size_; - acq_parameters.sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 20); + 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); From 92a6676b9e298f3b99e03b416f023b005267acf5 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 13 Jul 2018 11:50:31 +0200 Subject: [PATCH 3/6] Enable second refinement stage in a thinner grid for coherent and/or non-coherent acquisitions --- .../gnuradio_blocks/pcps_acquisition.cc | 93 ++++++++----------- .../gnuradio_blocks/pcps_acquisition.h | 4 +- .../acquisition/acq_performance_test.cc | 23 +++-- 3 files changed, 59 insertions(+), 61 deletions(-) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc index 75b8e58f3..74bd766ab 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc @@ -460,7 +460,7 @@ void pcps_acquisition::dump_results(int effective_fft_size) } -float pcps_acquisition::max_to_input_power_statistic(uint32_t& indext, int& doppler, float input_power) +float pcps_acquisition::max_to_input_power_statistic(uint32_t& indext, int& doppler, float input_power, unsigned int num_doppler_bins, int doppler_max, int doppler_step) { float grid_maximum = 0.0; unsigned int index_doppler = 0; @@ -469,7 +469,7 @@ float pcps_acquisition::max_to_input_power_statistic(uint32_t& indext, int& dopp float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); // Find the correlation peak and the carrier frequency - for (unsigned int i = 0; i < d_num_doppler_bins; i++) + for (unsigned int i = 0; i < num_doppler_bins; i++) { volk_gnsssdr_32f_index_max_32u(&tmp_intex_t, d_magnitude_grid[i], d_fft_size); if (d_magnitude_grid[i][tmp_intex_t] > grid_maximum) @@ -480,14 +480,21 @@ float pcps_acquisition::max_to_input_power_statistic(uint32_t& indext, int& dopp } } indext = index_time; - doppler = -static_cast(acq_parameters.doppler_max) + d_doppler_step * static_cast(index_doppler); + if (!d_step_two) + { + doppler = -static_cast(doppler_max) + doppler_step * static_cast(index_doppler); + } + else + { + doppler = static_cast(d_doppler_center_step_two + (index_doppler - (acq_parameters.num_doppler_bins_step2 / 2.0) * acq_parameters.doppler_step2)); + } float magt = grid_maximum / (fft_normalization_factor * fft_normalization_factor); return magt / input_power; } -float pcps_acquisition::first_vs_second_peak_statistic(uint32_t& indext, int& doppler) +float pcps_acquisition::first_vs_second_peak_statistic(uint32_t& indext, int& doppler, unsigned int num_doppler_bins, int doppler_max, int doppler_step) { // Look for correlation peaks in the results // Find the highest peak and compare it to the second highest peak @@ -499,7 +506,7 @@ float pcps_acquisition::first_vs_second_peak_statistic(uint32_t& indext, int& do uint32_t index_time = 0; // Find the correlation peak and the carrier frequency - for (unsigned int i = 0; i < d_num_doppler_bins; i++) + for (unsigned int i = 0; i < num_doppler_bins; i++) { volk_gnsssdr_32f_index_max_32u(&tmp_intex_t, d_magnitude_grid[i], d_fft_size); if (d_magnitude_grid[i][tmp_intex_t] > firstPeak) @@ -510,7 +517,15 @@ float pcps_acquisition::first_vs_second_peak_statistic(uint32_t& indext, int& do } } indext = index_time; - doppler = -static_cast(acq_parameters.doppler_max) + d_doppler_step * static_cast(index_doppler); + + if (!d_step_two) + { + doppler = -static_cast(doppler_max) + doppler_step * static_cast(index_doppler); + } + else + { + doppler = static_cast(d_doppler_center_step_two + (index_doppler - (acq_parameters.num_doppler_bins_step2 / 2.0) * acq_parameters.doppler_step2)); + } // Find 1 chip wide code phase exclude range around the peak int32_t excludeRangeIndex1 = index_time - d_samplesPerChip; @@ -629,11 +644,11 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) // Compute the test statistic if (d_use_CFAR_algorithm_flag) { - d_test_statistics = max_to_input_power_statistic(indext, doppler, d_input_power); + d_test_statistics = max_to_input_power_statistic(indext, doppler, d_input_power, d_num_doppler_bins, acq_parameters.doppler_max, d_doppler_step); } else { - d_test_statistics = first_vs_second_peak_statistic(indext, doppler); + d_test_statistics = first_vs_second_peak_statistic(indext, doppler, d_num_doppler_bins, acq_parameters.doppler_max, d_doppler_step); } d_gnss_synchro->Acq_delay_samples = static_cast(indext % acq_parameters.samples_per_code); d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); @@ -643,9 +658,6 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) { for (unsigned int doppler_index = 0; doppler_index < acq_parameters.num_doppler_bins_step2; doppler_index++) { - // doppler search steps - float doppler = d_doppler_center_step_two + (static_cast(doppler_index) - static_cast(acq_parameters.num_doppler_bins_step2) / 2.0) * acq_parameters.doppler_step2; - volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, d_grid_doppler_wipeoffs_step_two[doppler_index], d_fft_size); // 3- Perform the FFT-based convolution (parallel time search) @@ -659,54 +671,29 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) // compute the inverse FFT d_ifft->execute(); - // Search maximum size_t offset = (acq_parameters.bit_transition_flag ? effective_fft_size : 0); - volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf() + offset, effective_fft_size); - volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size); - magt = d_magnitude[indext]; - - if (d_use_CFAR_algorithm_flag) + if (d_num_noncoherent_integrations_counter == 1) { - // Normalize the maximum value to correct the scale factor introduced by FFTW - magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); + volk_32fc_magnitude_squared_32f(d_magnitude_grid[doppler_index], d_ifft->get_outbuf() + offset, effective_fft_size); } - // 4- record the maximum peak and the associated synchronization parameters - if (d_mag < magt) + else { - d_mag = magt; - - if (!d_use_CFAR_algorithm_flag) - { - // Search grid noise floor approximation for this doppler line - volk_32f_accumulator_s32f(&d_input_power, d_magnitude, effective_fft_size); - d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1); - } - - // In case that acq_parameters.bit_transition_flag = true, we compare the potentially - // new maximum test statistics (d_mag/d_input_power) with the value in - // d_test_statistics. When the second dwell is being processed, the value - // of d_mag/d_input_power could be lower than d_test_statistics (i.e, - // the maximum test statistics in the previous dwell is greater than - // current d_mag/d_input_power). Note that d_test_statistics is not - // restarted between consecutive dwells in multidwell operation. - - if (d_test_statistics < (d_mag / d_input_power) or !acq_parameters.bit_transition_flag) - { - d_gnss_synchro->Acq_delay_samples = static_cast(indext % acq_parameters.samples_per_code); - d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); - d_gnss_synchro->Acq_samplestamp_samples = samp_count; - - // 5- Compute the test statistics and compare to the threshold - //d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; - d_test_statistics = d_mag / d_input_power; - } - } - // Record results to file if required - if (acq_parameters.dump and d_channel == d_dump_channel) - { - memcpy(grid_.colptr(doppler_index), d_magnitude, sizeof(float) * effective_fft_size); + volk_32fc_magnitude_squared_32f(d_tmp_buffer, d_ifft->get_outbuf() + offset, effective_fft_size); + volk_32f_x2_add_32f(d_magnitude_grid[doppler_index], d_magnitude_grid[doppler_index], d_tmp_buffer, effective_fft_size); } } + // Compute the test statistic + if (d_use_CFAR_algorithm_flag) + { + d_test_statistics = max_to_input_power_statistic(indext, doppler, d_input_power, acq_parameters.num_doppler_bins_step2, static_cast(d_doppler_center_step_two - (static_cast(acq_parameters.num_doppler_bins_step2) / 2.0) * acq_parameters.doppler_step2), acq_parameters.doppler_step2); + } + else + { + d_test_statistics = first_vs_second_peak_statistic(indext, doppler, acq_parameters.num_doppler_bins_step2, static_cast(d_doppler_center_step_two - (static_cast(acq_parameters.num_doppler_bins_step2) / 2.0) * acq_parameters.doppler_step2), acq_parameters.doppler_step2); + } + d_gnss_synchro->Acq_delay_samples = static_cast(indext % acq_parameters.samples_per_code); + d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); + d_gnss_synchro->Acq_samplestamp_samples = samp_count; } lk.lock(); diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h index e39648525..4e71340ba 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h @@ -95,8 +95,8 @@ private: void dump_results(int effective_fft_size); - float first_vs_second_peak_statistic(uint32_t& indext, int& doppler); - float max_to_input_power_statistic(uint32_t& indext, int& doppler, float input_power); + float first_vs_second_peak_statistic(uint32_t& indext, int& doppler, unsigned int num_doppler_bins, int doppler_max, int doppler_step); + float max_to_input_power_statistic(uint32_t& indext, int& doppler, float input_power, unsigned int num_doppler_bins, int doppler_max, int doppler_step); Acq_Conf acq_parameters; bool d_active; diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc index 032b575ba..9e8b86626 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc @@ -54,9 +54,12 @@ DEFINE_string(acq_test_implementation, std::string("GPS_L1_CA_PCPS_Acquisition") DEFINE_int32(acq_test_doppler_max, 5000, "Maximum Doppler, in Hz"); DEFINE_int32(acq_test_doppler_step, 125, "Doppler step, in Hz."); DEFINE_int32(acq_test_coherent_time_ms, 1, "Acquisition coherent time, in ms"); -DEFINE_int32(acq_test_max_dwells, 1, "Number of non-coherent integrations"); -DEFINE_bool(acq_test_use_CFAR_algorithm, true, "Use CFAR algorithm"); -DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag"); +DEFINE_int32(acq_test_max_dwells, 1, "Number of non-coherent integrations."); +DEFINE_bool(acq_test_use_CFAR_algorithm, true, "Use CFAR algorithm."); +DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag."); +DEFINE_bool(acq_test_make_two_steps, false, "Perform second step in a thinner grid."); +DEFINE_int32(acq_test_second_nbins, 4, "If --acq_test_make_two_steps is set to true, this parameter sets the number of bins done in the acquisition refinement stage."); +DEFINE_int32(acq_test_second_doppler_step, 10, "If --acq_test_make_two_steps is set to true, this parameter sets the Doppler step applied in the acquisition refinement stage, in Hz."); DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration, in s"); DEFINE_int32(acq_test_num_meas, 0, "Number of measurements per run. 0 means the complete file."); @@ -501,9 +504,17 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign config->set_property("Acquisition.repeat_satellite", "true"); config->set_property("Acquisition.blocking", "true"); - config->set_property("Acquisition.make_two_steps", "false"); - config->set_property("Acquisition.second_nbins", std::to_string(4)); - config->set_property("Acquisition.second_doppler_step", std::to_string(125)); + if (FLAGS_acq_test_make_two_steps) + { + config->set_property("Acquisition.make_two_steps", "true"); + config->set_property("Acquisition.second_nbins", std::to_string(FLAGS_acq_test_second_nbins)); + config->set_property("Acquisition.second_doppler_step", std::to_string(FLAGS_acq_test_second_doppler_step)); + } + else + { + config->set_property("Acquisition.make_two_steps", "false"); + } + config->set_property("Acquisition.dump", "true"); std::string dump_file = path_str + std::string("/acquisition_") + std::to_string(cn0) + "_" + std::to_string(iter) + "_" + std::to_string(pfa); From 0352108a79c61f8ac62500c4af8c4fb394688bca Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 13 Jul 2018 14:23:14 +0200 Subject: [PATCH 4/6] Accept non-integer number of samples per code period --- .../adapters/galileo_e1_pcps_ambiguous_acquisition.cc | 10 ++++++++-- .../adapters/galileo_e5a_pcps_acquisition.cc | 4 ++-- .../adapters/glonass_l1_ca_pcps_acquisition.cc | 4 ++-- .../adapters/glonass_l2_ca_pcps_acquisition.cc | 4 ++-- .../adapters/gps_l1_ca_pcps_acquisition.cc | 4 ++-- .../acquisition/adapters/gps_l2_m_pcps_acquisition.cc | 11 ++++++++--- .../acquisition/adapters/gps_l5i_pcps_acquisition.cc | 6 +++--- .../acquisition/gnuradio_blocks/pcps_acquisition.cc | 6 ++---- src/algorithms/acquisition/libs/acq_conf.cc | 4 ++-- src/algorithms/acquisition/libs/acq_conf.h | 4 ++-- 10 files changed, 33 insertions(+), 24 deletions(-) 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 7f1df1c2f..52487df49 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc @@ -64,6 +64,11 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( acq_parameters.doppler_max = doppler_max_; sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 4); acq_parameters.sampled_ms = sampled_ms_; + if ((acq_parameters.sampled_ms % 4) != 0) + { + LOG(WARNING) << "Parameter coherent_integration_time_ms should be a multiple of 4. Setting it to 4"; + acq_parameters.sampled_ms = 4; + } bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); 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 @@ -80,9 +85,10 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( acq_parameters.dump_filename = dump_filename_; //--- Find number of samples per spreading code (4 ms) ----------------- code_length_ = static_cast(std::round(static_cast(fs_in_) / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS))); - acq_parameters.samples_per_code = code_length_; - int samples_per_ms = static_cast(std::round(static_cast(fs_in_) * 0.001)); + + 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; if (bit_transition_flag_) diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc index 9ff35a922..f300d6158 100644 --- a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc @@ -101,9 +101,9 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con LOG(WARNING) << item_type_ << " unknown acquisition item type"; } acq_parameters.it_size = item_size_; - acq_parameters.samples_per_code = code_length_; - acq_parameters.samples_per_ms = code_length_; + acq_parameters.samples_per_ms = static_cast(fs_in_) * 0.001; acq_parameters.sampled_ms = sampled_ms_; + 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); diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc index 43354e627..81a4eb200 100644 --- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc @@ -100,8 +100,8 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition( } acq_parameters.it_size = item_size_; acq_parameters.sampled_ms = sampled_ms_; - acq_parameters.samples_per_ms = code_length_; - acq_parameters.samples_per_code = code_length_; + acq_parameters.samples_per_ms = static_cast(fs_in_) * 0.001; + acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast(GLONASS_L1_CA_CODE_PERIOD); 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); diff --git a/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc index 374b69e35..61a61383a 100644 --- a/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc @@ -99,8 +99,8 @@ GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition( } acq_parameters.it_size = item_size_; acq_parameters.sampled_ms = sampled_ms_; - acq_parameters.samples_per_ms = code_length_; - acq_parameters.samples_per_code = code_length_; + acq_parameters.samples_per_ms = static_cast(fs_in_) * 0.001; + acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast(GLONASS_L2_CA_CODE_PERIOD * 1000.0); 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); 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 18c728412..87076a66d 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc @@ -102,8 +102,8 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( { item_size_ = sizeof(gr_complex); } - acq_parameters.samples_per_ms = code_length_; - acq_parameters.samples_per_code = code_length_; + 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); acq_parameters.it_size = item_size_; acq_parameters.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); acquisition_ = pcps_make_acquisition(acq_parameters); 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 301bc14a5..361a0375a 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc @@ -78,11 +78,16 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); acq_parameters.dump_filename = dump_filename_; //--- Find number of samples per spreading code ------------------------- - //code_length_ = std::round(static_cast(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast(GPS_L2_M_CODE_LENGTH_CHIPS))); - acq_parameters.samples_per_ms = static_cast(std::round(static_cast(fs_in_) * 0.001)); + acq_parameters.samples_per_ms = static_cast(fs_in_) * 0.001; acq_parameters.sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 20); + if ((acq_parameters.sampled_ms % 20) != 0) + { + LOG(WARNING) << "Parameter coherent_integration_time_ms should be a multiple of 20. Setting it to 20"; + acq_parameters.sampled_ms = 20; + } code_length_ = acq_parameters.sampled_ms * acq_parameters.samples_per_ms * (acq_parameters.bit_transition_flag ? 2 : 1); + vector_length_ = code_length_; if (bit_transition_flag_) @@ -101,7 +106,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( item_size_ = sizeof(gr_complex); } - acq_parameters.samples_per_code = code_length_; + 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); diff --git a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc index 66537426c..146137ef7 100644 --- a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc @@ -96,10 +96,10 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition( { item_size_ = sizeof(gr_complex); } - acq_parameters.samples_per_code = code_length_; - acq_parameters.samples_per_ms = code_length_; + 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); acq_parameters.it_size = item_size_; - acq_parameters.sampled_ms = 1; + acq_parameters.sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1); 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); diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc index 74bd766ab..798d6c5ae 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc @@ -565,7 +565,6 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) gr::thread::scoped_lock lk(d_setlock); // initialize acquisition algorithm - float magt = 0.0; int doppler = 0; uint32_t indext = 0; int effective_fft_size = (acq_parameters.bit_transition_flag ? d_fft_size / 2 : d_fft_size); @@ -582,7 +581,6 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) } } const gr_complex* in = d_input_signal; // Get the input samples pointer - float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); d_input_power = 0.0; d_mag = 0.0; @@ -650,7 +648,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) { d_test_statistics = first_vs_second_peak_statistic(indext, doppler, d_num_doppler_bins, acq_parameters.doppler_max, d_doppler_step); } - d_gnss_synchro->Acq_delay_samples = static_cast(indext % acq_parameters.samples_per_code); + d_gnss_synchro->Acq_delay_samples = static_cast(std::fmod(static_cast(indext), acq_parameters.samples_per_code)); d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); d_gnss_synchro->Acq_samplestamp_samples = samp_count; } @@ -691,7 +689,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) { d_test_statistics = first_vs_second_peak_statistic(indext, doppler, acq_parameters.num_doppler_bins_step2, static_cast(d_doppler_center_step_two - (static_cast(acq_parameters.num_doppler_bins_step2) / 2.0) * acq_parameters.doppler_step2), acq_parameters.doppler_step2); } - d_gnss_synchro->Acq_delay_samples = static_cast(indext % acq_parameters.samples_per_code); + d_gnss_synchro->Acq_delay_samples = static_cast(std::fmod(static_cast(indext), acq_parameters.samples_per_code)); d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); d_gnss_synchro->Acq_samplestamp_samples = samp_count; } diff --git a/src/algorithms/acquisition/libs/acq_conf.cc b/src/algorithms/acquisition/libs/acq_conf.cc index c3439b9c0..cacf0cec9 100644 --- a/src/algorithms/acquisition/libs/acq_conf.cc +++ b/src/algorithms/acquisition/libs/acq_conf.cc @@ -41,8 +41,8 @@ Acq_Conf::Acq_Conf() num_doppler_bins_step2 = 0; doppler_step2 = 0.0; fs_in = 0; - samples_per_ms = 0; - samples_per_code = 0; + samples_per_ms = 0.0; + samples_per_code = 0.0; bit_transition_flag = false; use_CFAR_algorithm_flag = false; dump = false; diff --git a/src/algorithms/acquisition/libs/acq_conf.h b/src/algorithms/acquisition/libs/acq_conf.h index afd43b1fb..b22b2bceb 100644 --- a/src/algorithms/acquisition/libs/acq_conf.h +++ b/src/algorithms/acquisition/libs/acq_conf.h @@ -46,8 +46,8 @@ public: unsigned int num_doppler_bins_step2; float doppler_step2; long fs_in; - int samples_per_ms; - int samples_per_code; + float samples_per_ms; + float samples_per_code; bool bit_transition_flag; bool use_CFAR_algorithm_flag; bool dump; From 994a4b32d8f2ad6be4ce457049f61295013b94c1 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 13 Jul 2018 15:16:48 +0200 Subject: [PATCH 5/6] Fix Glonass acquisition test --- .../acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc | 2 +- .../glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc index 81a4eb200..dafc2475c 100644 --- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc @@ -101,7 +101,7 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition( acq_parameters.it_size = item_size_; acq_parameters.sampled_ms = sampled_ms_; acq_parameters.samples_per_ms = static_cast(fs_in_) * 0.001; - acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast(GLONASS_L1_CA_CODE_PERIOD); + acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast(GLONASS_L1_CA_CODE_PERIOD * 1000.0); 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); diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc index 2f7c23a2c..e5a588cff 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc @@ -341,7 +341,7 @@ void GlonassL1CaPcpsAcquisitionGSoC2017Test::config_2() std::to_string(integration_time_ms)); config->set_property("Acquisition.max_dwells", "1"); config->set_property("Acquisition.implementation", "GLONASS_L1_CA_PCPS_Acquisition"); - config->set_property("Acquisition.pfa", "0.1"); + //config->set_property("Acquisition.pfa", "0.1"); config->set_property("Acquisition.doppler_max", "10000"); config->set_property("Acquisition.doppler_step", "250"); config->set_property("Acquisition.bit_transition_flag", "false"); @@ -496,7 +496,7 @@ TEST_F(GlonassL1CaPcpsAcquisitionGSoC2017Test, ValidationOfResults) }) << "Failure setting doppler_step."; ASSERT_NO_THROW({ - acquisition->set_threshold(0.5); + acquisition->set_threshold(0.05); }) << "Failure setting threshold."; ASSERT_NO_THROW({ From a392117c0b2f66fe90079888835e30af88a8f417 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Fri, 13 Jul 2018 15:23:20 +0200 Subject: [PATCH 6/6] Improving bit synchronization in GPS L1 CA tracking --- .../gnuradio_blocks/dll_pll_veml_tracking.cc | 111 +++++++++++++++--- .../gnuradio_blocks/dll_pll_veml_tracking.h | 7 +- 2 files changed, 98 insertions(+), 20 deletions(-) diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.cc b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.cc index 70eef4727..3cb599866 100755 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.cc +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.cc @@ -2,6 +2,7 @@ * \file dll_pll_veml_tracking.cc * \brief Implementation of a code DLL + carrier PLL tracking block. * \author Antonio Ramos, 2018 antonio.ramosdet(at)gmail.com + * Javier Arribas, 2018. jarribas(at)cttc.es * * Code DLL + carrier PLL according to the algorithms described in: * [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, @@ -84,10 +85,12 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl this->message_port_register_out(pmt::mp("events")); this->set_relative_rate(1.0 / static_cast(trk_parameters.vector_length)); + // Telemetry bit synchronization message port input (mainly for GPS L1 CA) + this->message_port_register_in(pmt::mp("preamble_samplestamp")); + // initialize internal vars d_veml = false; d_cloop = true; - d_synchonizing = false; d_code_chip_rate = 0.0; d_secondary_code_length = 0; d_secondary_code_string = nullptr; @@ -120,6 +123,30 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl d_secondary = false; trk_parameters.track_pilot = false; interchange_iq = false; + + // set the preamble + unsigned short int preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS] = GPS_PREAMBLE; + + // preamble bits to sampled symbols + d_gps_l1ca_preambles_symbols = static_cast(volk_gnsssdr_malloc(GPS_CA_PREAMBLE_LENGTH_SYMBOLS * sizeof(int), volk_gnsssdr_get_alignment())); + int n = 0; + for (int i = 0; i < GPS_CA_PREAMBLE_LENGTH_BITS; i++) + { + for (unsigned int j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++) + { + if (preambles_bits[i] == 1) + { + d_gps_l1ca_preambles_symbols[n] = 1; + } + else + { + d_gps_l1ca_preambles_symbols[n] = -1; + } + n++; + } + } + d_symbol_history.resize(GPS_CA_PREAMBLE_LENGTH_SYMBOLS); // Change fixed buffer size + d_symbol_history.clear(); // Clear all the elements in the buffer } else if (signal_type.compare("2S") == 0) { @@ -521,7 +548,6 @@ void dll_pll_veml_tracking::start_tracking() // enable tracking pull-in d_state = 1; - d_synchonizing = false; d_cloop = true; d_Prompt_buffer_deque.clear(); d_last_prompt = gr_complex(0.0, 0.0); @@ -533,6 +559,11 @@ void dll_pll_veml_tracking::start_tracking() dll_pll_veml_tracking::~dll_pll_veml_tracking() { + if (signal_type.compare("1C") == 0) + { + volk_gnsssdr_free(d_gps_l1ca_preambles_symbols); + } + if (d_dump_file.is_open()) { try @@ -1281,39 +1312,82 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused) } else if (d_symbols_per_bit > 1) //Signal does not have secondary code. Search a bit transition by sign change { - if (d_synchonizing) + float current_tracking_time_s = static_cast(d_sample_counter - d_acq_sample_stamp) / trk_parameters.fs_in; + if (current_tracking_time_s > 10) { - if (d_Prompt->real() * d_last_prompt.real() > 0.0) + d_symbol_history.push_back(d_Prompt->real()); + //******* preamble correlation ******** + int corr_value = 0; + if ((d_symbol_history.size() == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)) // and (d_make_correlation or !d_flag_frame_sync)) { - d_current_symbol++; + for (unsigned int i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++) + { + if (d_symbol_history.at(i) < 0) // symbols clipping + { + corr_value -= d_gps_l1ca_preambles_symbols[i]; + } + else + { + corr_value += d_gps_l1ca_preambles_symbols[i]; + } + } } - else if (d_current_symbol > d_symbols_per_bit) + if (corr_value == GPS_CA_PREAMBLE_LENGTH_SYMBOLS) { - d_synchonizing = false; - d_current_symbol = 1; + //std::cout << "Preamble detected at tracking!" << std::endl; + next_state = true; } else { - d_current_symbol = 1; - d_last_prompt = *d_Prompt; + next_state = false; } } - else if (d_last_prompt.real() != 0.0) - { - d_current_symbol++; - if (d_current_symbol == d_symbols_per_bit) next_state = true; - } else { - d_last_prompt = *d_Prompt; - d_synchonizing = true; - d_current_symbol = 1; + next_state = false; } } else { next_state = true; } + + // ########### Output the tracking results to Telemetry block ########## + if (interchange_iq) + { + if (trk_parameters.track_pilot) + { + // Note that data and pilot components are in quadrature. I and Q are interchanged + current_synchro_data.Prompt_I = static_cast((*d_Prompt_Data).imag()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt_Data).real()); + } + else + { + current_synchro_data.Prompt_I = static_cast((*d_Prompt).imag()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt).real()); + } + } + else + { + if (trk_parameters.track_pilot) + { + // Note that data and pilot components are in quadrature. I and Q are interchanged + current_synchro_data.Prompt_I = static_cast((*d_Prompt_Data).real()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt_Data).imag()); + } + else + { + current_synchro_data.Prompt_I = static_cast((*d_Prompt).real()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt).imag()); + } + } + current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; + current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; + current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; + current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; + current_synchro_data.Flag_valid_symbol_output = true; + current_synchro_data.correlation_length_ms = d_correlation_length_ms; + if (next_state) { // reset extended correlator d_VE_accu = gr_complex(0.0, 0.0); @@ -1324,7 +1398,6 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused) d_last_prompt = gr_complex(0.0, 0.0); d_Prompt_buffer_deque.clear(); d_current_symbol = 0; - d_synchonizing = false; if (d_enable_extended_integration) { diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.h b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.h index 0437e8a35..b57bc2200 100755 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.h +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.h @@ -41,6 +41,7 @@ #include #include #include +#include class dll_pll_veml_tracking; @@ -69,6 +70,7 @@ private: friend dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(const Dll_Pll_Conf &conf_); dll_pll_veml_tracking(const Dll_Pll_Conf &conf_); + void msg_handler_preamble_index(pmt::pmt_t msg); bool cn0_and_tracking_lock_status(double coh_integration_time_s); bool acquire_secondary(); @@ -102,9 +104,12 @@ private: std::string *d_secondary_code_string; std::string signal_pretty_name; + uint64_t d_preamble_sample_counter; + int *d_gps_l1ca_preambles_symbols; + boost::circular_buffer d_symbol_history; + //tracking state machine int d_state; - bool d_synchonizing; //Integration period in samples int d_correlation_length_ms; int d_n_correlator_taps;