1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-09-12 07:19:50 +00:00

Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into next

This commit is contained in:
Carles Fernandez 2018-07-11 18:21:07 +02:00
commit b21ceb4917
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
22 changed files with 478 additions and 194 deletions

View File

@ -58,24 +58,24 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition(
long 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_;
dump_ = configuration_->property(role + ".dump", false);
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.samples_per_chip = static_cast<unsigned int>(ceil((1.0 / Galileo_E1_CODE_CHIP_RATE_HZ) * static_cast<float>(acq_parameters.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_;
sampled_ms_ = 4;
sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 4);
acq_parameters.sampled_ms = sampled_ms_;
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
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_;
dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
blocking_ = configuration_->property(role + ".blocking", true);
acq_parameters.blocking = blocking_;
dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
acq_parameters.dump_filename = dump_filename_;
//--- Find number of samples per spreading code (4 ms) -----------------

View File

@ -57,6 +57,7 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con
long 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<unsigned int>(ceil((1.0 / Galileo_E5a_CODE_CHIP_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
acq_pilot_ = configuration_->property(role + ".acquire_pilot", false);
acq_iq_ = configuration_->property(role + ".acquire_iq", false);
if (acq_iq_)

View File

@ -59,6 +59,7 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition(
long 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<unsigned int>(ceil(GLONASS_L1_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);

View File

@ -58,6 +58,7 @@ GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition(
long 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<unsigned int>(ceil(GLONASS_L2_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);

View File

@ -60,6 +60,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
long 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<unsigned int>(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);

View File

@ -56,6 +56,7 @@ GpsL1CaPcpsAcquisitionFineDoppler::GpsL1CaPcpsAcquisitionFineDoppler(
long 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<unsigned int>(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration->property(role + ".dump", false);
acq_parameters.dump = dump_;
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);

View File

@ -60,6 +60,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
long 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<unsigned int>(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.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_;

View File

@ -60,6 +60,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
long 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<unsigned int>(ceil((1.0 / GPS_L2_M_CODE_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
@ -99,10 +100,10 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
acq_parameters.samples_per_ms = static_cast<int>(std::round(static_cast<double>(fs_in_) * 0.001));
acq_parameters.samples_per_code = code_length_;
acq_parameters.it_size = item_size_;
acq_parameters.sampled_ms = 20;
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", true);
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() << ")";

View File

@ -1,5 +1,5 @@
/*!
* \file gps_l5i pcps_acquisition.cc
* \file gps_l5i_pcps_acquisition.cc
* \brief Adapts a PCPS acquisition block to an Acquisition Interface for
* GPS L5i signals
* \authors <ul>
@ -59,6 +59,7 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition(
long 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<unsigned int>(ceil((1.0 / GPS_L5i_CODE_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);

View File

@ -1,5 +1,5 @@
/*!
* \file GPS_L5i_PCPS_Acquisition.h
* \file gps_l5i_pcps_acquisition.h
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* GPS L5i signals
* \authors <ul>

View File

@ -63,8 +63,17 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
d_positive_acq = 0;
d_state = 0;
d_old_freq = 0;
d_well_count = 0;
d_fft_size = acq_parameters.sampled_ms * acq_parameters.samples_per_ms;
d_num_noncoherent_integrations_counter = 0;
d_consumed_samples = acq_parameters.sampled_ms * acq_parameters.samples_per_ms * (acq_parameters.bit_transition_flag ? 2 : 1);
if (acq_parameters.sampled_ms == (acq_parameters.samples_per_code / acq_parameters.samples_per_ms)) //
{
d_fft_size = d_consumed_samples;
}
else
{
d_fft_size = d_consumed_samples * 2;
}
//d_fft_size = next power of two? ////
d_mag = 0;
d_input_power = 0.0;
d_num_doppler_bins = 0;
@ -94,12 +103,14 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
// size of the input buffer and padding the code with zeros.
if (acq_parameters.bit_transition_flag)
{
d_fft_size *= 2;
acq_parameters.max_dwells = 1; //Activation of acq_parameters.bit_transition_flag invalidates the value of acq_parameters.max_dwells
d_fft_size = d_consumed_samples * 2;
acq_parameters.max_dwells = 1; // Activation of acq_parameters.bit_transition_flag invalidates the value of acq_parameters.max_dwells
}
d_tmp_buffer = static_cast<float*>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment()));
d_fft_codes = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_magnitude = static_cast<float*>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment()));
d_input_signal = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
// Direct FFT
d_fft_if = new gr::fft::fft_complex(d_fft_size, true);
@ -110,11 +121,12 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
d_gnss_synchro = 0;
d_grid_doppler_wipeoffs = nullptr;
d_grid_doppler_wipeoffs_step_two = nullptr;
d_magnitude_grid = nullptr;
d_worker_active = false;
d_data_buffer = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_data_buffer = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_consumed_samples * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
if (d_cshort)
{
d_data_buffer_sc = static_cast<lv_16sc_t*>(volk_gnsssdr_malloc(d_fft_size * sizeof(lv_16sc_t), volk_gnsssdr_get_alignment()));
d_data_buffer_sc = static_cast<lv_16sc_t*>(volk_gnsssdr_malloc(d_consumed_samples * sizeof(lv_16sc_t), volk_gnsssdr_get_alignment()));
}
else
{
@ -124,6 +136,16 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
d_step_two = false;
d_dump_number = 0;
d_dump_channel = acq_parameters.dump_channel;
d_samplesPerChip = acq_parameters.samples_per_chip;
// todo: CFAR statistic not available for non-coherent integration
if (acq_parameters.max_dwells == 1)
{
d_use_CFAR_algorithm_flag = acq_parameters.use_CFAR_algorithm_flag;
}
else
{
d_use_CFAR_algorithm_flag = false;
}
}
@ -134,8 +156,10 @@ pcps_acquisition::~pcps_acquisition()
for (unsigned int i = 0; i < d_num_doppler_bins; i++)
{
volk_gnsssdr_free(d_grid_doppler_wipeoffs[i]);
volk_gnsssdr_free(d_magnitude_grid[i]);
}
delete[] d_grid_doppler_wipeoffs;
delete[] d_magnitude_grid;
}
if (acq_parameters.make_2_steps)
{
@ -147,6 +171,8 @@ pcps_acquisition::~pcps_acquisition()
}
volk_gnsssdr_free(d_fft_codes);
volk_gnsssdr_free(d_magnitude);
volk_gnsssdr_free(d_tmp_buffer);
volk_gnsssdr_free(d_input_signal);
delete d_ifft;
delete d_fft_if;
volk_gnsssdr_free(d_data_buffer);
@ -179,7 +205,15 @@ void pcps_acquisition::set_local_code(std::complex<float>* code)
}
else
{
memcpy(d_fft_if->get_inbuf(), code, sizeof(gr_complex) * d_fft_size);
if (acq_parameters.sampled_ms == (acq_parameters.samples_per_code / acq_parameters.samples_per_ms))
{
memcpy(d_fft_if->get_inbuf(), code, sizeof(gr_complex) * d_consumed_samples);
}
else
{
std::fill_n(d_fft_if->get_inbuf(), d_fft_size - d_consumed_samples, gr_complex(0.0, 0.0));
memcpy(d_fft_if->get_inbuf() + d_consumed_samples, code, sizeof(gr_complex) * d_consumed_samples);
}
}
d_fft_if->execute(); // We need the FFT of local code
@ -243,9 +277,12 @@ void pcps_acquisition::init()
d_grid_doppler_wipeoffs_step_two[doppler_index] = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
}
}
d_magnitude_grid = new float*[d_num_doppler_bins];
for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
{
d_grid_doppler_wipeoffs[doppler_index] = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_magnitude_grid[doppler_index] = static_cast<float*>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment()));
int doppler = -static_cast<int>(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_old_freq + doppler);
}
@ -268,6 +305,7 @@ void pcps_acquisition::update_grid_doppler_wipeoffs()
}
}
void pcps_acquisition::update_grid_doppler_wipeoffs_step2()
{
for (unsigned int doppler_index = 0; doppler_index < acq_parameters.num_doppler_bins_step2; doppler_index++)
@ -277,6 +315,7 @@ void pcps_acquisition::update_grid_doppler_wipeoffs_step2()
}
}
void pcps_acquisition::set_state(int state)
{
gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
@ -286,7 +325,6 @@ void pcps_acquisition::set_state(int state)
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;
d_gnss_synchro->Acq_samplestamp_samples = 0;
d_well_count = 0;
d_mag = 0.0;
d_input_power = 0.0;
d_test_statistics = 0.0;
@ -417,109 +455,184 @@ 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 grid_maximum = 0.0;
unsigned int index_doppler = 0;
uint32_t tmp_intex_t = 0;
uint32_t index_time = 0;
float fft_normalization_factor = static_cast<float>(d_fft_size) * static_cast<float>(d_fft_size);
// Find the correlation peak and the carrier frequency
for (unsigned int i = 0; i < d_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)
{
grid_maximum = d_magnitude_grid[i][tmp_intex_t];
index_doppler = i;
index_time = tmp_intex_t;
}
}
indext = index_time;
doppler = -static_cast<int>(acq_parameters.doppler_max) + d_doppler_step * static_cast<int>(index_doppler);
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)
{
// Look for correlation peaks in the results
// Find the highest peak and compare it to the second highest peak
// The second peak is chosen not closer than 1 chip to the highest peak
float firstPeak = 0.0;
unsigned int index_doppler = 0;
uint32_t tmp_intex_t = 0;
uint32_t index_time = 0;
// Find the correlation peak and the carrier frequency
for (unsigned int i = 0; i < d_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)
{
firstPeak = d_magnitude_grid[i][tmp_intex_t];
index_doppler = i;
index_time = tmp_intex_t;
}
}
indext = index_time;
doppler = -static_cast<int>(acq_parameters.doppler_max) + d_doppler_step * static_cast<int>(index_doppler);
// Find 1 chip wide code phase exclude range around the peak
int32_t excludeRangeIndex1 = index_time - d_samplesPerChip;
int32_t excludeRangeIndex2 = index_time + d_samplesPerChip;
// Correct code phase exclude range if the range includes array boundaries
if (excludeRangeIndex1 < 0)
{
excludeRangeIndex1 = d_fft_size + excludeRangeIndex1;
}
else if (excludeRangeIndex2 >= static_cast<int>(d_fft_size))
{
excludeRangeIndex2 = excludeRangeIndex2 - d_fft_size;
}
int32_t idx = excludeRangeIndex1;
memcpy(d_tmp_buffer, d_magnitude_grid[index_doppler], d_fft_size);
do
{
d_tmp_buffer[idx] = 0.0;
idx++;
if (idx == static_cast<int>(d_fft_size)) idx = 0;
}
while (idx != excludeRangeIndex2);
// Find the second highest correlation peak in the same freq. bin ---
volk_gnsssdr_32f_index_max_32u(&tmp_intex_t, d_tmp_buffer, d_fft_size);
float secondPeak = d_tmp_buffer[tmp_intex_t];
// Compute the test statistics and compare to the threshold
return firstPeak / secondPeak;
}
void pcps_acquisition::acquisition_core(unsigned long int samp_count)
{
gr::thread::scoped_lock lk(d_setlock);
// initialize acquisition algorithm
uint32_t indext = 0;
float magt = 0.0;
const gr_complex* in = d_data_buffer; // Get the input samples pointer
int doppler = 0;
uint32_t indext = 0;
int effective_fft_size = (acq_parameters.bit_transition_flag ? d_fft_size / 2 : d_fft_size);
if (d_cshort)
{
volk_gnsssdr_16ic_convert_32fc(d_data_buffer, d_data_buffer_sc, d_fft_size);
volk_gnsssdr_16ic_convert_32fc(d_data_buffer, d_data_buffer_sc, d_consumed_samples);
}
memcpy(d_input_signal, d_data_buffer, d_consumed_samples * sizeof(gr_complex));
if (d_fft_size > d_consumed_samples)
{
for (unsigned int i = d_consumed_samples; i < d_fft_size; i++)
{
d_input_signal[i] = gr_complex(0.0, 0.0);
}
}
const gr_complex* in = d_input_signal; // Get the input samples pointer
float fft_normalization_factor = static_cast<float>(d_fft_size) * static_cast<float>(d_fft_size);
d_input_power = 0.0;
d_mag = 0.0;
d_well_count++;
d_num_noncoherent_integrations_counter++;
DLOG(INFO) << "Channel: " << d_channel
<< " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
<< " ,sample stamp: " << samp_count << ", threshold: "
<< d_threshold << ", doppler_max: " << acq_parameters.doppler_max
<< ", doppler_step: " << d_doppler_step
<< ", use_CFAR_algorithm_flag: " << (acq_parameters.use_CFAR_algorithm_flag ? "true" : "false");
<< ", use_CFAR_algorithm_flag: " << (d_use_CFAR_algorithm_flag ? "true" : "false");
lk.unlock();
if (acq_parameters.use_CFAR_algorithm_flag)
if (d_use_CFAR_algorithm_flag or acq_parameters.bit_transition_flag)
{
// 1- (optional) Compute the input signal power estimation
volk_32fc_magnitude_squared_32f(d_magnitude, in, d_fft_size);
volk_32f_accumulator_s32f(&d_input_power, d_magnitude, d_fft_size);
// Compute the input signal power estimation
volk_32fc_magnitude_squared_32f(d_tmp_buffer, in, d_fft_size);
volk_32f_accumulator_s32f(&d_input_power, d_tmp_buffer, d_fft_size);
d_input_power /= static_cast<float>(d_fft_size);
}
// 2- Doppler frequency search loop
// Doppler frequency grid loop
if (!d_step_two)
{
for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
{
// doppler search steps
int doppler = -static_cast<int>(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
// Remove Doppler
volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, d_grid_doppler_wipeoffs[doppler_index], d_fft_size);
// 3- Perform the FFT-based convolution (parallel time search)
// Perform the FFT-based convolution (parallel time search)
// Compute the FFT of the carrier wiped--off incoming signal
d_fft_if->execute();
// Multiply carrier wiped--off, Fourier transformed incoming signal
// with the local FFT'd code reference using SIMD operations with VOLK library
// Multiply carrier wiped--off, Fourier transformed incoming signal with the local FFT'd code reference
volk_32fc_x2_multiply_32fc(d_ifft->get_inbuf(), d_fft_if->get_outbuf(), d_fft_codes, d_fft_size);
// compute the inverse FFT
// Compute the inverse FFT
d_ifft->execute();
// Search maximum
// Compute squared magnitude (and accumulate in case of non-coherent integration)
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 (acq_parameters.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 (!acq_parameters.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<double>(indext % acq_parameters.samples_per_code);
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(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;
}
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);
}
// 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);
memcpy(grid_.colptr(doppler_index), d_magnitude_grid[doppler_index], sizeof(float) * 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);
}
else
{
d_test_statistics = first_vs_second_peak_statistic(indext, doppler);
}
d_gnss_synchro->Acq_delay_samples = static_cast<double>(indext % acq_parameters.samples_per_code);
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(doppler);
d_gnss_synchro->Acq_samplestamp_samples = samp_count;
}
else
{
@ -547,7 +660,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size);
magt = d_magnitude[indext];
if (acq_parameters.use_CFAR_algorithm_flag)
if (d_use_CFAR_algorithm_flag)
{
// Normalize the maximum value to correct the scale factor introduced by FFTW
magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor);
@ -557,7 +670,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
{
d_mag = magt;
if (!acq_parameters.use_CFAR_algorithm_flag)
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);
@ -590,6 +703,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
}
}
}
lk.lock();
if (!acq_parameters.bit_transition_flag)
{
@ -616,12 +730,13 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
d_state = 0; // Positive acquisition
}
}
else if (d_well_count == acq_parameters.max_dwells)
if (d_num_noncoherent_integrations_counter == acq_parameters.max_dwells)
{
if (d_state != 0) send_negative_acquisition();
d_state = 0;
d_active = false;
d_step_two = false;
send_negative_acquisition();
}
}
else
@ -657,10 +772,16 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
}
}
d_worker_active = false;
// Record results to file if required
if (acq_parameters.dump and d_channel == d_dump_channel)
if ((d_num_noncoherent_integrations_counter == acq_parameters.max_dwells) or (d_positive_acq == 1))
{
pcps_acquisition::dump_results(effective_fft_size);
// Record results to file if required
if (acq_parameters.dump and d_channel == d_dump_channel)
{
pcps_acquisition::dump_results(effective_fft_size);
}
d_num_noncoherent_integrations_counter = 0;
d_positive_acq = 0;
}
}
@ -685,7 +806,7 @@ int pcps_acquisition::general_work(int noutput_items __attribute__((unused)),
{
if (!acq_parameters.blocking_on_standby)
{
d_sample_counter += d_fft_size * ninput_items[0];
d_sample_counter += d_consumed_samples * ninput_items[0];
consume_each(ninput_items[0]);
}
if (d_step_two)
@ -706,14 +827,13 @@ int pcps_acquisition::general_work(int noutput_items __attribute__((unused)),
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;
d_gnss_synchro->Acq_samplestamp_samples = 0;
d_well_count = 0;
d_mag = 0.0;
d_input_power = 0.0;
d_test_statistics = 0.0;
d_state = 1;
if (!acq_parameters.blocking_on_standby)
{
d_sample_counter += d_fft_size * ninput_items[0]; // sample counter
d_sample_counter += d_consumed_samples * ninput_items[0]; // sample counter
consume_each(ninput_items[0]);
}
break;
@ -724,11 +844,11 @@ int pcps_acquisition::general_work(int noutput_items __attribute__((unused)),
// Copy the data to the core and let it know that new data is available
if (d_cshort)
{
memcpy(d_data_buffer_sc, input_items[0], d_fft_size * sizeof(lv_16sc_t));
memcpy(d_data_buffer_sc, input_items[0], d_consumed_samples * sizeof(lv_16sc_t));
}
else
{
memcpy(d_data_buffer, input_items[0], d_fft_size * sizeof(gr_complex));
memcpy(d_data_buffer, input_items[0], d_consumed_samples * sizeof(gr_complex));
}
if (acq_parameters.blocking)
{
@ -740,7 +860,7 @@ int pcps_acquisition::general_work(int noutput_items __attribute__((unused)),
gr::thread::thread d_worker(&pcps_acquisition::acquisition_core, this, d_sample_counter);
d_worker_active = true;
}
d_sample_counter += d_fft_size;
d_sample_counter += d_consumed_samples;
consume_each(1);
break;
}

View File

@ -95,24 +95,33 @@ 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);
Acq_Conf acq_parameters;
bool d_active;
bool d_worker_active;
bool d_cshort;
bool d_step_two;
bool d_use_CFAR_algorithm_flag;
int d_positive_acq;
float d_threshold;
float d_mag;
float d_input_power;
float d_test_statistics;
float* d_magnitude;
float** d_magnitude_grid;
float* d_tmp_buffer;
gr_complex* d_input_signal;
uint32_t d_samplesPerChip;
long d_old_freq;
int d_state;
unsigned int d_channel;
unsigned int d_doppler_step;
float d_doppler_center_step_two;
unsigned int d_well_count;
unsigned int d_num_noncoherent_integrations_counter;
unsigned int d_fft_size;
unsigned int d_consumed_samples;
unsigned int d_num_doppler_bins;
unsigned long int d_sample_counter;
gr_complex** d_grid_doppler_wipeoffs;
@ -150,7 +159,7 @@ public:
}
/*!
* \brief Initializes acquisition algorithm.
* \brief Initializes acquisition algorithm and reserves memory.
*/
void init();

View File

@ -63,10 +63,8 @@ pcps_acquisition_fine_doppler_cc::pcps_acquisition_fine_doppler_cc(const Acq_Con
d_active = false;
d_fs_in = conf_.fs_in;
d_samples_per_ms = conf_.samples_per_ms;
d_sampled_ms = conf_.sampled_ms;
d_config_doppler_max = conf_.doppler_max;
d_config_doppler_min = -conf_.doppler_max;
d_fft_size = d_sampled_ms * d_samples_per_ms;
d_fft_size = d_samples_per_ms;
// HS Acquisition
d_max_dwells = conf_.max_dwells;
d_gnuradio_forecast_samples = d_fft_size;
@ -75,7 +73,7 @@ pcps_acquisition_fine_doppler_cc::pcps_acquisition_fine_doppler_cc(const Acq_Con
d_fft_codes = static_cast<gr_complex *>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_magnitude = static_cast<float *>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment()));
d_10_ms_buffer = static_cast<gr_complex *>(volk_gnsssdr_malloc(10 * d_samples_per_ms * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_10_ms_buffer = static_cast<gr_complex *>(volk_gnsssdr_malloc(50 * d_samples_per_ms * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
// Direct FFT
d_fft_if = new gr::fft::fft_complex(d_fft_size, true);
@ -126,7 +124,7 @@ void pcps_acquisition_fine_doppler_cc::set_doppler_step(unsigned int doppler_ste
d_doppler_step = doppler_step;
// Create the search grid array
d_num_doppler_points = floor(std::abs(d_config_doppler_max - d_config_doppler_min) / d_doppler_step);
d_num_doppler_points = floor(std::abs(2 * d_config_doppler_max) / d_doppler_step);
d_grid_data = new float *[d_num_doppler_points];
for (int i = 0; i < d_num_doppler_points; i++)
@ -222,7 +220,7 @@ void pcps_acquisition_fine_doppler_cc::update_carrier_wipeoff()
d_grid_doppler_wipeoffs = new gr_complex *[d_num_doppler_points];
for (int doppler_index = 0; doppler_index < d_num_doppler_points; doppler_index++)
{
doppler_hz = d_config_doppler_min + d_doppler_step * doppler_index;
doppler_hz = d_doppler_step * doppler_index - d_config_doppler_max;
// doppler search steps
// compute the carrier doppler wipe-off signal and store it
phase_step_rad = static_cast<float>(GPS_TWO_PI) * doppler_hz / static_cast<float>(d_fs_in);
@ -295,7 +293,7 @@ double pcps_acquisition_fine_doppler_cc::compute_CAF()
// 4- record the maximum peak and the associated synchronization parameters
d_gnss_synchro->Acq_delay_samples = static_cast<double>(index_time);
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(index_doppler * d_doppler_step + d_config_doppler_min);
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(index_doppler * d_doppler_step - d_config_doppler_max);
d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter;
return d_test_statistics;
@ -333,6 +331,7 @@ int pcps_acquisition_fine_doppler_cc::compute_and_accumulate_grid(gr_vector_cons
// doppler search steps
// Perform the carrier wipe-off
volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, d_grid_doppler_wipeoffs[doppler_index], d_fft_size);
// 3- Perform the FFT-based convolution (parallel time search)
// Compute the FFT of the carrier wiped--off incoming signal
d_fft_if->execute();
@ -352,6 +351,14 @@ int pcps_acquisition_fine_doppler_cc::compute_and_accumulate_grid(gr_vector_cons
volk_gnsssdr_free(p_tmp_vector);
return d_fft_size;
//debug
// std::cout << "iff=[";
// for (int n = 0; n < d_fft_size; n++)
// {
// std::cout << std::real(d_ifft->get_outbuf()[n]) << "+" << std::imag(d_ifft->get_outbuf()[n]) << "i,";
// }
// std::cout << "]\n";
// getchar();
}
@ -495,6 +502,7 @@ int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items,
if (d_active == true)
{
reset_grid();
d_n_samples_in_buffer = 0;
d_state = 1;
}
if (!acq_parameters.blocking_on_standby)
@ -505,6 +513,8 @@ int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items,
break;
case 1: // S1. ComputeGrid
compute_and_accumulate_grid(input_items);
memcpy(&d_10_ms_buffer[d_n_samples_in_buffer], reinterpret_cast<const gr_complex *>(input_items[0]), d_fft_size * sizeof(gr_complex));
d_n_samples_in_buffer += d_fft_size;
d_well_count++;
if (d_well_count >= d_max_dwells)
{
@ -522,10 +532,9 @@ int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items,
else
{
d_state = 5; //negative acquisition
d_n_samples_in_buffer = 0;
}
d_n_samples_in_buffer = 0;
d_sample_counter += d_fft_size; // sample counter
consume_each(d_fft_size);
break;
case 3: // Fine doppler estimation
samples_remaining = 10 * d_samples_per_ms - d_n_samples_in_buffer;
@ -539,10 +548,14 @@ int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items,
}
else
{
memcpy(&d_10_ms_buffer[d_n_samples_in_buffer], reinterpret_cast<const gr_complex *>(input_items[0]), samples_remaining * sizeof(gr_complex));
estimate_Doppler(); //disabled in repo
d_sample_counter += samples_remaining; // sample counter
consume_each(samples_remaining);
if (samples_remaining > 0)
{
memcpy(&d_10_ms_buffer[d_n_samples_in_buffer], reinterpret_cast<const gr_complex *>(input_items[0]), samples_remaining * sizeof(gr_complex));
d_sample_counter += samples_remaining; // sample counter
consume_each(samples_remaining);
}
estimate_Doppler(); //disabled in repo
d_n_samples_in_buffer = 0;
d_state = 4;
}
break;

View File

@ -94,11 +94,9 @@ private:
float d_threshold;
std::string d_satellite_str;
int d_config_doppler_max;
int d_config_doppler_min;
int d_num_doppler_points;
int d_doppler_step;
unsigned int d_sampled_ms;
unsigned int d_fft_size;
unsigned long int d_sample_counter;
gr_complex* d_carrier;

View File

@ -36,6 +36,7 @@ Acq_Conf::Acq_Conf()
/* PCPS acquisition configuration */
sampled_ms = 0;
max_dwells = 0;
samples_per_chip = 0;
doppler_max = 0;
num_doppler_bins_step2 = 0;
doppler_step2 = 0.0;

View File

@ -40,6 +40,7 @@ class Acq_Conf
public:
/* PCPS Acquisition configuration */
unsigned int sampled_ms;
unsigned int samples_per_chip;
unsigned int max_dwells;
unsigned int doppler_max;
unsigned int num_doppler_bins_step2;

View File

@ -418,7 +418,7 @@ void GNSSFlowgraph::connect()
}
if (sat == 0)
{
channels_.at(i)->set_signal(search_next_signal(gnss_signal, true));
channels_.at(i)->set_signal(search_next_signal(gnss_signal, false));
}
else
{
@ -1357,9 +1357,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
{
case evGPS_1C:
result = available_GPS_1C_signals_.front();
if (pop)
available_GPS_1C_signals_.pop_front();
if (!pop)
{
available_GPS_1C_signals_.pop_front();
available_GPS_1C_signals_.push_back(result);
}
if (tracked)
{
@ -1387,9 +1388,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGPS_2S:
result = available_GPS_2S_signals_.front();
if (pop)
available_GPS_2S_signals_.pop_front();
if (!pop)
{
available_GPS_2S_signals_.pop_front();
available_GPS_2S_signals_.push_back(result);
}
if (tracked)
{
@ -1417,9 +1419,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGPS_L5:
result = available_GPS_L5_signals_.front();
if (pop)
available_GPS_L5_signals_.pop_front();
if (!pop)
{
available_GPS_L5_signals_.pop_front();
available_GPS_L5_signals_.push_back(result);
}
if (tracked)
{
@ -1447,9 +1450,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGAL_1B:
result = available_GAL_1B_signals_.front();
if (pop)
available_GAL_1B_signals_.pop_front();
if (!pop)
{
available_GAL_1B_signals_.pop_front();
available_GAL_1B_signals_.push_back(result);
}
if (tracked)
{
@ -1471,9 +1475,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGAL_5X:
result = available_GAL_5X_signals_.front();
if (pop)
available_GAL_5X_signals_.pop_front();
if (!pop)
{
available_GAL_5X_signals_.pop_front();
available_GAL_5X_signals_.push_back(result);
}
if (tracked)
{
@ -1495,9 +1500,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGLO_1G:
result = available_GLO_1G_signals_.front();
if (pop)
available_GLO_1G_signals_.pop_front();
if (!pop)
{
available_GLO_1G_signals_.pop_front();
available_GLO_1G_signals_.push_back(result);
}
if (tracked)
{
@ -1519,9 +1525,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGLO_2G:
result = available_GLO_2G_signals_.front();
if (pop)
available_GLO_2G_signals_.pop_front();
if (!pop)
{
available_GLO_2G_signals_.pop_front();
available_GLO_2G_signals_.push_back(result);
}
if (tracked)
{

View File

@ -61,6 +61,7 @@ DEFINE_double(acq_Delay_error_chips_start, 2.0, "Acquisition Code Delay error st
DEFINE_double(acq_Delay_error_chips_stop, -2.0, "Acquisition Code Delay error stop sweep value [Chips]");
DEFINE_double(acq_Delay_error_chips_step, -0.1, "Acquisition Code Delay error sweep step value [Chips]");
DEFINE_int64(skip_samples, 0, "Skip an initial transitory in the processed signal file capture [samples]");
DEFINE_int32(plot_detail_level, 0, "Specify the desired plot detail (0,1,2): 0 - Minimum plots (default) 2 - Plot all tracking parameters");

View File

@ -145,7 +145,7 @@ DECLARE_string(log_dir);
#if EXTRA_TESTS
#include "unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc"
#include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc"
#include "unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc"
#include "unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/gps_l2_m_dll_pll_tracking_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_pull-in_test.cc"

View File

@ -1,5 +1,5 @@
/*!
* \file gps_l1_acq_performance_test.cc
* \file acq_performance_test.cc
* \brief This class implements an acquisition performance test
* \author Carles Fernandez-Prades, 2018. cfernandez(at)cttc.cat
*
@ -29,22 +29,27 @@
* -------------------------------------------------------------------------
*/
#include "test_flags.h"
#include "signal_generator_flags.h"
#include "tracking_true_obs_reader.h"
#include "true_observables_reader.h"
#include "gps_l1_ca_pcps_acquisition.h"
#include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
#include "galileo_e1_pcps_ambiguous_acquisition.h"
#include "galileo_e5a_pcps_acquisition.h"
#include "glonass_l1_ca_pcps_acquisition.h"
#include "glonass_l2_ca_pcps_acquisition.h"
#include "gps_l2_m_pcps_acquisition.h"
#include "gps_l5i_pcps_acquisition.h"
#include "display.h"
#include "gnuplot_i.h"
#include "signal_generator_flags.h"
#include "test_flags.h"
#include "tracking_true_obs_reader.h"
#include "true_observables_reader.h"
#include <boost/filesystem.hpp>
#include <gnuradio/top_block.h>
#include <glog/logging.h>
#include <gtest/gtest.h>
DEFINE_string(config_file_ptest, std::string(""), "File containing alternative configuration parameters for the acquisition performance test.");
DEFINE_string(acq_test_input_file, std::string(""), "File containing raw signal data, must be in int8_t format. The signal generator will not be used.");
DEFINE_string(acq_test_implementation, std::string("GPS_L1_CA_PCPS_Acquisition"), "Acquisition block implementation under test. Alternative: GPS_L1_CA_PCPS_Acquisition_Fine_Doppler");
DEFINE_string(acq_test_implementation, std::string("GPS_L1_CA_PCPS_Acquisition"), "Acquisition block implementation under test. Alternatives: GPS_L1_CA_PCPS_Acquisition, GPS_L1_CA_PCPS_Acquisition_Fine_Doppler, Galileo_E1_PCPS_Ambiguous_Acquisition, GLONASS_L1_CA_PCPS_Acquisition, GLONASS_L2_CA_PCPS_Acquisition, GPS_L2_M_PCPS_Acquisition, Galileo_E5a_Pcps_Acquisition, GPS_L5i_PCPS_Acquisition");
DEFINE_int32(acq_test_doppler_max, 5000, "Maximum Doppler, in Hz");
DEFINE_int32(acq_test_doppler_step, 125, "Doppler step, in Hz.");
@ -154,6 +159,76 @@ protected:
{
cn0_vector = {0.0};
}
if (implementation.compare("GPS_L1_CA_PCPS_Acquisition") == 0)
{
signal_id = "1C";
system_id = 'G';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
}
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;
}
else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0)
{
signal_id = "1B";
system_id = 'E';
if (FLAGS_acq_test_coherent_time_ms == 1)
{
coherent_integration_time_ms = 4;
}
else
{
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
}
}
else if (implementation.compare("GLONASS_L1_CA_PCPS_Acquisition") == 0)
{
signal_id = "1G";
system_id = 'R';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
}
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;
}
else if (implementation.compare("GPS_L2_M_PCPS_Acquisition") == 0)
{
signal_id = "2S";
system_id = 'G';
if (FLAGS_acq_test_coherent_time_ms == 1)
{
coherent_integration_time_ms = 20;
}
else
{
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
}
}
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;
}
else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0)
{
signal_id = "L5";
system_id = 'G';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
}
else
{
signal_id = "1C";
system_id = 'G';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
}
init();
if (FLAGS_acq_test_pfa_init > 0.0)
@ -181,7 +256,7 @@ protected:
num_thresholds = pfa_vector.size();
int aux2 = ((generated_signal_duration_s * 1000 - FLAGS_acq_test_coherent_time_ms) / FLAGS_acq_test_coherent_time_ms);
int aux2 = ((generated_signal_duration_s * 1000 - (FLAGS_acq_test_coherent_time_ms * FLAGS_acq_test_max_dwells)) / (FLAGS_acq_test_coherent_time_ms * FLAGS_acq_test_max_dwells));
if ((FLAGS_acq_test_num_meas > 0) and (FLAGS_acq_test_num_meas < aux2))
{
num_of_measurements = static_cast<unsigned int>(FLAGS_acq_test_num_meas);
@ -240,7 +315,7 @@ protected:
std::string implementation = FLAGS_acq_test_implementation;
const double baseband_sampling_freq = static_cast<double>(FLAGS_fs_gen_sps);
const int coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
int coherent_integration_time_ms;
const int in_acquisition = 1;
const int dump_channel = 0;
@ -257,6 +332,8 @@ protected:
std::vector<std::vector<float>> Pfa;
std::vector<std::vector<float>> Pd_correct;
std::string signal_id;
private:
std::string generator_binary;
std::string p1;
@ -268,6 +345,7 @@ private:
std::string filename_rinex_obs = FLAGS_filename_rinex_obs;
std::string filename_raw_data = FLAGS_filename_raw_data;
char system_id;
double compute_stdev_precision(const std::vector<double>& vec);
double compute_stdev_accuracy(const std::vector<double>& vec, double ref);
@ -277,8 +355,8 @@ private:
void AcquisitionPerformanceTest::init()
{
gnss_synchro.Channel_ID = 0;
gnss_synchro.System = 'G';
std::string signal = "1C";
gnss_synchro.System = system_id;
std::string signal = signal_id;
signal.copy(gnss_synchro.Signal, 2, 0);
gnss_synchro.PRN = observed_satellite;
message = 0;
@ -378,51 +456,51 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign
config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(sampling_rate_internal));
// Set Acquisition
config->set_property("Acquisition_1C.implementation", implementation);
config->set_property("Acquisition_1C.item_type", "gr_complex");
config->set_property("Acquisition_1C.doppler_max", std::to_string(doppler_max));
config->set_property("Acquisition_1C.doppler_min", std::to_string(-doppler_max));
config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step));
config->set_property("Acquisition.implementation", implementation);
config->set_property("Acquisition.item_type", "gr_complex");
config->set_property("Acquisition.doppler_max", std::to_string(doppler_max));
config->set_property("Acquisition.doppler_min", std::to_string(-doppler_max));
config->set_property("Acquisition.doppler_step", std::to_string(doppler_step));
config->set_property("Acquisition_1C.threshold", std::to_string(pfa));
//if (FLAGS_acq_test_pfa_init > 0.0) config->supersede_property("Acquisition_1C.pfa", std::to_string(pfa));
config->set_property("Acquisition.threshold", std::to_string(pfa));
//if (FLAGS_acq_test_pfa_init > 0.0) config->supersede_property("Acquisition.pfa", std::to_string(pfa));
if (FLAGS_acq_test_pfa_init > 0.0)
{
config->supersede_property("Acquisition_1C.pfa", std::to_string(pfa));
config->supersede_property("Acquisition.pfa", std::to_string(pfa));
}
if (FLAGS_acq_test_use_CFAR_algorithm)
{
config->set_property("Acquisition_1C.use_CFAR_algorithm", "true");
config->set_property("Acquisition.use_CFAR_algorithm", "true");
}
else
{
config->set_property("Acquisition_1C.use_CFAR_algorithm", "false");
config->set_property("Acquisition.use_CFAR_algorithm", "false");
}
config->set_property("Acquisition_1C.coherent_integration_time_ms", std::to_string(coherent_integration_time_ms));
config->set_property("Acquisition.coherent_integration_time_ms", std::to_string(coherent_integration_time_ms));
if (FLAGS_acq_test_bit_transition_flag)
{
config->set_property("Acquisition_1C.bit_transition_flag", "true");
config->set_property("Acquisition.bit_transition_flag", "true");
}
else
{
config->set_property("Acquisition_1C.bit_transition_flag", "false");
config->set_property("Acquisition.bit_transition_flag", "false");
}
config->set_property("Acquisition_1C.max_dwells", std::to_string(FLAGS_acq_test_max_dwells));
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_acq_test_max_dwells));
config->set_property("Acquisition_1C.repeat_satellite", "true");
config->set_property("Acquisition.repeat_satellite", "true");
config->set_property("Acquisition_1C.blocking", "true");
config->set_property("Acquisition_1C.make_two_steps", "false");
config->set_property("Acquisition_1C.second_nbins", std::to_string(4));
config->set_property("Acquisition_1C.second_doppler_step", std::to_string(125));
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));
config->set_property("Acquisition_1C.dump", "true");
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);
config->set_property("Acquisition_1C.dump_filename", dump_file);
config->set_property("Acquisition_1C.dump_channel", std::to_string(dump_channel));
config->set_property("Acquisition_1C.blocking_on_standby", "true");
config->set_property("Acquisition.dump_filename", dump_file);
config->set_property("Acquisition.dump_channel", std::to_string(dump_channel));
config->set_property("Acquisition.blocking_on_standby", "true");
config_f = 0;
}
@ -462,26 +540,47 @@ int AcquisitionPerformanceTest::run_receiver()
boost::shared_ptr<gr::block> valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue);
if (implementation.compare("GPS_L1_CA_PCPS_Acquisition") == 0)
{
acquisition = std::make_shared<GpsL1CaPcpsAcquisition>(config.get(), "Acquisition_1C", 1, 0);
acquisition = std::make_shared<GpsL1CaPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GPS_L1_CA_PCPS_Acquisition_Fine_Doppler") == 0)
{
acquisition = std::make_shared<GpsL1CaPcpsAcquisitionFineDoppler>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0)
{
acquisition = std::make_shared<GalileoE1PcpsAmbiguousAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GLONASS_L1_CA_PCPS_Acquisition") == 0)
{
acquisition = std::make_shared<GlonassL1CaPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GLONASS_L2_CA_PCPS_Acquisition") == 0)
{
acquisition = std::make_shared<GlonassL2CaPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GPS_L2_M_PCPS_Acquisition") == 0)
{
acquisition = std::make_shared<GpsL2MPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("Galileo_E5a_Pcps_Acquisition") == 0)
{
acquisition = std::make_shared<GalileoE5aPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0)
{
acquisition = std::make_shared<GpsL5iPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else
{
if (implementation.compare("GPS_L1_CA_PCPS_Acquisition_Fine_Doppler") == 0)
{
acquisition = std::make_shared<GpsL1CaPcpsAcquisitionFineDoppler>(config.get(), "Acquisition_1C", 1, 0);
}
else
{
bool aux = false;
EXPECT_EQ(true, aux);
}
bool aux = false;
EXPECT_EQ(true, aux);
}
acquisition->set_gnss_synchro(&gnss_synchro);
acquisition->set_channel(0);
acquisition->set_doppler_max(config->property("Acquisition_1C.doppler_max", 10000));
acquisition->set_doppler_step(config->property("Acquisition_1C.doppler_step", 500));
acquisition->set_threshold(config->property("Acquisition_1C.threshold", 0.0));
acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 10000));
acquisition->set_doppler_step(config->property("Acquisition.doppler_step", 500));
acquisition->set_threshold(config->property("Acquisition.threshold", 0.0));
acquisition->init();
acquisition->set_local_code();
@ -563,7 +662,7 @@ void AcquisitionPerformanceTest::plot_results()
}
g1.cmd("set font \"Times,18\"");
g1.set_title("Receiver Operating Characteristic for GPS L1 C/A acquisition");
g1.cmd("set label 1 \"" + std::string("Coherent integration time: ") + std::to_string(config->property("Acquisition_1C.coherent_integration_time_ms", 1)) + " ms, Non-coherent integrations: " + std::to_string(config->property("Acquisition_1C.max_dwells", 1)) + " \" at screen 0.12, 0.83 font \"Times,16\"");
g1.cmd("set label 1 \"" + std::string("Coherent integration time: ") + std::to_string(config->property("Acquisition.coherent_integration_time_ms", 1)) + " ms, Non-coherent integrations: " + std::to_string(config->property("Acquisition.max_dwells", 1)) + " \" at screen 0.12, 0.83 font \"Times,16\"");
g1.cmd("set logscale x");
g1.cmd("set yrange [0:1]");
g1.cmd("set xrange[0.0001:1]");
@ -599,7 +698,7 @@ void AcquisitionPerformanceTest::plot_results()
}
g2.cmd("set font \"Times,18\"");
g2.set_title("Receiver Operating Characteristic for GPS L1 C/A valid acquisition");
g2.cmd("set label 1 \"" + std::string("Coherent integration time: ") + std::to_string(config->property("Acquisition_1C.coherent_integration_time_ms", 1)) + " ms, Non-coherent integrations: " + std::to_string(config->property("Acquisition_1C.max_dwells", 1)) + " \" at screen 0.12, 0.83 font \"Times,16\"");
g2.cmd("set label 1 \"" + std::string("Coherent integration time: ") + std::to_string(config->property("Acquisition.coherent_integration_time_ms", 1)) + " ms, Non-coherent integrations: " + std::to_string(config->property("Acquisition.max_dwells", 1)) + " \" at screen 0.12, 0.83 font \"Times,16\"");
g2.cmd("set logscale x");
g2.cmd("set yrange [0:1]");
g2.cmd("set xrange[0.0001:1]");
@ -692,22 +791,22 @@ TEST_F(AcquisitionPerformanceTest, ROC)
run_receiver();
// count executions
std::string basename = path_str + std::string("/acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + std::to_string(pfa_vector[pfa_iter]) + "_" + gnss_synchro.System + "_1C";
std::string basename = path_str + std::string("/acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + std::to_string(pfa_vector[pfa_iter]) + "_" + gnss_synchro.System + "_" + signal_id;
int num_executions = count_executions(basename, observed_satellite);
// Read measured data
int ch = config->property("Acquisition_1C.dump_channel", 0);
int ch = config->property("Acquisition.dump_channel", 0);
arma::vec meas_timestamp_s = arma::zeros(num_executions, 1);
arma::vec meas_doppler = arma::zeros(num_executions, 1);
arma::vec positive_acq = arma::zeros(num_executions, 1);
arma::vec meas_acq_delay_chips = arma::zeros(num_executions, 1);
double coh_time_ms = config->property("Acquisition_1C.coherent_integration_time_ms", 1);
double coh_time_ms = config->property("Acquisition.coherent_integration_time_ms", 1);
std::cout << "Num executions: " << num_executions << std::endl;
for (int execution = 1; execution <= num_executions; execution++)
{
acquisition_dump_reader acq_dump(basename, observed_satellite, config->property("Acquisition_1C.doppler_max", 0), config->property("Acquisition_1C.doppler_step", 0), config->property("GNSS-SDR.internal_fs_sps", 0) * GPS_L1_CA_CODE_PERIOD * static_cast<double>(coh_time_ms), ch, 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<double>(coh_time_ms) * (config->property("Acquisition.bit_transition_flag", false) ? 2 : 1), ch, execution);
acq_dump.read_binary_acq();
if (acq_dump.positive_acq)
{
@ -827,7 +926,7 @@ TEST_F(AcquisitionPerformanceTest, ROC)
for (int i = 0; i < num_clean_executions - 1; i++)
{
if (abs(clean_delay_estimation_error(i)) < 0.5 and abs(clean_doppler_estimation_error(i)) < static_cast<float>(config->property("Acquisition_1C.doppler_step", 1)) / 2.0)
if (abs(clean_delay_estimation_error(i)) < 0.5 and abs(clean_doppler_estimation_error(i)) < static_cast<float>(config->property("Acquisition.doppler_step", 1)) / 2.0)
{
correctly_detected = correctly_detected + 1.0;
}

View File

@ -40,10 +40,12 @@
#include <gnuradio/blocks/interleaved_char_to_complex.h>
#include <gnuradio/blocks/null_sink.h>
#include <gnuradio/blocks/skiphead.h>
#include <gnuradio/blocks/head.h>
#include <gtest/gtest.h>
#include "GPS_L1_CA.h"
#include "gnss_block_factory.h"
#include "tracking_interface.h"
#include "gps_l1_ca_pcps_acquisition.h"
#include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
#include "in_memory_configuration.h"
#include "tracking_true_obs_reader.h"
@ -71,6 +73,7 @@ private:
public:
int rx_message;
gr::top_block_sptr top_block;
~Acquisition_msg_rx(); //!< Default destructor
};
@ -87,6 +90,7 @@ void Acquisition_msg_rx::msg_handler_events(pmt::pmt_t msg)
{
long int message = pmt::to_long(msg);
rx_message = message;
top_block->stop(); //stop the flowgraph
}
catch (boost::bad_any_cast& e)
{
@ -335,16 +339,36 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq));
config->set_property("Acquisition.max_dwells", "10");
config->set_property("Acquisition.blocking_on_standby", "true");
config->set_property("Acquisition.dump", "true");
GNSSBlockFactory block_factory;
config->set_property("Acquisition.dump_filename", "./data/acquisition.dat");
config->set_property("Acquisition.use_CFAR_algorithm", "false");
GpsL1CaPcpsAcquisitionFineDoppler* acquisition;
acquisition = new GpsL1CaPcpsAcquisitionFineDoppler(config.get(), "Acquisition", 1, 1);
acquisition = new GpsL1CaPcpsAcquisitionFineDoppler(config.get(), "Acquisition", 1, 0);
//GpsL1CaPcpsAcquisition* acquisition;
//acquisition = new GpsL1CaPcpsAcquisition(config.get(), "Acquisition", 1, 0);
acquisition->set_channel(1);
acquisition->set_gnss_synchro(&tmp_gnss_synchro);
acquisition->set_threshold(config->property("Acquisition.threshold", FLAGS_external_signal_acquisition_threshold));
acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 10000));
acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 25000));
acquisition->set_doppler_step(config->property("Acquisition.doppler_step", 500));
acquisition->connect(top_block);
gr::blocks::file_source::sptr file_source;
std::string file = FLAGS_signal_file;
const char* file_name = file.c_str();
file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false);
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(file_source, 0, gr_interleaved_char_to_complex, 0);
top_block->connect(gr_interleaved_char_to_complex, 0, head_samples, 0);
top_block->connect(head_samples, 0, acquisition->get_left_block(), 0);
boost::shared_ptr<Acquisition_msg_rx> msg_rx;
try
@ -357,15 +381,8 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
exit(0);
}
gr::blocks::file_source::sptr file_source;
std::string file = FLAGS_signal_file;
const char* file_name = file.c_str();
file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false);
gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make();
gr::blocks::null_sink::sptr sink = gr::blocks::null_sink::make(sizeof(Gnss_Synchro));
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->msg_connect(acquisition->get_left_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
msg_rx->top_block = top_block;
top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
// 5. Run the flowgraph
// Get visible GPS satellites (positive acquisitions with Doppler measurements)
@ -380,6 +397,7 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
code_delay_measurements_map.clear();
acq_samplestamp_map.clear();
for (unsigned int PRN = 1; PRN < 33; PRN++)
{
tmp_gnss_synchro.PRN = PRN;
@ -387,6 +405,7 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
acquisition->init();
acquisition->set_local_code();
acquisition->reset();
acquisition->set_state(1);
msg_rx->rx_message = 0;
top_block->run();
if (start_msg == true)
@ -412,10 +431,17 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
std::cout << " . ";
}
top_block->stop();
file_source->seek(0, 0);
file_source->seek(2 * FLAGS_skip_samples, 0); //skip head. ibyte, two bytes per complex sample
head_samples.reset();
std::cout.flush();
}
std::cout << "]" << std::endl;
std::cout << "-------------------------------------------\n";
for (auto& x : doppler_measurements_map)
{
std::cout << "DETECTED PRN: " << x.first << " with Doppler: " << x.second << " [Hz], code phase: " << code_delay_measurements_map.at(x.first) << " [samples] at signal SampleStamp " << acq_samplestamp_map.at(x.first) << "\n";
}
// report the elapsed time
end = std::chrono::system_clock::now();
@ -587,19 +613,20 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false);
gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make();
gr::blocks::null_sink::sptr sink = gr::blocks::null_sink::make(sizeof(Gnss_Synchro));
gr::blocks::head::sptr head_samples = gr::blocks::head::make(sizeof(gr_complex), baseband_sampling_freq * FLAGS_duration);
top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0);
top_block->connect(gr_interleaved_char_to_complex, 0, tracking->get_left_block(), 0);
top_block->connect(gr_interleaved_char_to_complex, 0, head_samples, 0);
top_block->connect(head_samples, 0, tracking->get_left_block(), 0);
top_block->connect(tracking->get_right_block(), 0, sink, 0);
top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
file_source->seek(acq_samplestamp_samples, 0);
file_source->seek(2 * FLAGS_skip_samples + acq_samplestamp_samples, 0); //skip head. ibyte, two bytes per complex sample
}) << "Failure connecting the blocks of tracking test.";
//********************************************************************
//***** STEP 5: Perform the signal tracking and read the results *****
//********************************************************************
std::cout << "------------ START TRACKING -------------" << std::endl;
std::cout << "--- START TRACKING WITH PULL-IN ERROR: " << acq_doppler_error_hz_values.at(current_acq_doppler_error_idx) << " [Hz] and " << acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx) << " [Chips] ---" << std::endl;
tracking->start_tracking();
std::chrono::time_point<std::chrono::system_clock> start, end;
EXPECT_NO_THROW({

View File

@ -85,7 +85,7 @@ Acquisition_2S.doppler_step=125
Acquisition_2S.use_CFAR_algorithm=false
Acquisition_2S.threshold=19.5
Acquisition_2S.threshold=10
Acquisition_2S.blocking=true