From 67fe04f881c1d423e1d571288041ef68fa0a43a5 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Tue, 19 Jun 2018 09:15:46 +0200 Subject: [PATCH 01/16] Start work on acq performance tests --- .../common-files/signal_generator_flags.h | 2 + src/tests/test_main.cc | 1 + .../gps_l1_acq_performance_test.cc | 537 ++++++++++++++++++ .../gps_l1_ca_dll_pll_tracking_test.cc | 5 +- 4 files changed, 542 insertions(+), 3 deletions(-) create mode 100644 src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc diff --git a/src/tests/common-files/signal_generator_flags.h b/src/tests/common-files/signal_generator_flags.h index cfc93b8d0..e65e98846 100644 --- a/src/tests/common-files/signal_generator_flags.h +++ b/src/tests/common-files/signal_generator_flags.h @@ -32,6 +32,7 @@ #define GNSS_SDR_SIGNAL_GENERATOR_FLAGS_H_ #include +#include DEFINE_bool(disable_generator, false, "Disable the signal generator (a external signal file must be available for the test)"); DEFINE_string(generator_binary, std::string(SW_GENERATOR_BIN), "Path of software-defined signal generator binary"); @@ -44,5 +45,6 @@ DEFINE_string(filename_raw_data, "signal_out.bin", "Filename of output raw data DEFINE_int32(fs_gen_sps, 2600000, "Sampling frequency [sps]"); DEFINE_int32(test_satellite_PRN, 1, "PRN of the satellite under test (must be visible during the observation time)"); DEFINE_int32(test_satellite_PRN2, 2, "PRN of the satellite under test (must be visible during the observation time)"); +DEFINE_double(CN0_dBHz, std::numeric_limits::infinity(), "Enable noise generator and set the CN0 [dB-Hz]"); #endif diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index b139e993e..39fe900b8 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -145,6 +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/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/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc" diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc new file mode 100644 index 000000000..08287722c --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -0,0 +1,537 @@ +/*! + * \file gps_l1_acq_performance_test.cc + * \brief This class implements an acquisition performance test + * \author Carles Fernandez-Prades, 2018. cfernandez(at)cttc.cat + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "test_flags.h" +#include "signal_generator_flags.h" +#include +#include +#include + +DEFINE_string(config_file_ptest, std::string(""), "File containing the configuration parameters for the position test."); + +// ######## GNURADIO BLOCK MESSAGE RECEVER ######### +//class AcqPerfTest_msg_rx; +// +//typedef boost::shared_ptr AcqPerfTest_msg_rx_sptr; +// +//AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); +// +//class AcqPerfTest_msg_rx : public gr::block +//{ +//private: +// friend AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); +// void msg_handler_events(pmt::pmt_t msg); +// AcqPerfTest_msg_rx(); +// +//public: +// int rx_message; +// ~AcqPerfTest_msg_rx(); //!< Default destructor +//}; +// +// +//AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make() +//{ +// return AcqPerfTest_msg_rx_sptr(new AcqPerfTest_msg_rx()); +//} +// +// +//void AcqPerfTest_msg_rx::msg_handler_events(pmt::pmt_t msg) +//{ +// try +// { +// long int message = pmt::to_long(msg); +// rx_message = message; +// } +// catch (boost::bad_any_cast& e) +// { +// LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; +// rx_message = 0; +// } +//} +// +// +//AcqPerfTest_msg_rx::AcqPerfTest_msg_rx() : gr::block("AcqPerfTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) +//{ +// this->message_port_register_in(pmt::mp("events")); +// this->set_msg_handler(pmt::mp("events"), boost::bind(&AcqPerfTest_msg_rx::msg_handler_events, this, _1)); +// rx_message = 0; +//} +// +// +//AcqPerfTest_msg_rx::~AcqPerfTest_msg_rx() +//{ +//} +// +//// ----------------------------------------- + + +class AcquisitionPerformanceTest : public ::testing::Test +{ +protected: + AcquisitionPerformanceTest() + { + config = std::make_shared(); + item_size = sizeof(gr_complex); + gnss_synchro = Gnss_Synchro(); + doppler_max = 5000; + doppler_step = 100; + } + + ~AcquisitionPerformanceTest() + { + } + + std::vector cn0_ = {41.0, 42.0, 43.0}; + int N_iterations = 2; + void init(); + //void plot_grid(); + + int configure_generator(double cn0); + int generate_signal(); + int configure_receiver(double cn0, unsigned int iter); + int run_receiver(); + void check_results(); + gr::top_block_sptr top_block; + Gnss_Synchro gnss_synchro; + size_t item_size; + unsigned int doppler_max; + unsigned int doppler_step; + std::string implementation = "GPS_L1_CA_PCPS_Acquisition"; + std::shared_ptr config; + std::shared_ptr config_f; + +private: + std::string generator_binary; + std::string p1; + std::string p2; + std::string p3; + std::string p4; + std::string p5; + std::string p6; + + const double baseband_sampling_freq = static_cast(FLAGS_fs_gen_sps); + + std::string filename_rinex_obs = FLAGS_filename_rinex_obs; + std::string filename_raw_data = FLAGS_filename_raw_data; + + /*void print_results(const std::vector& east, + const std::vector& north, + const std::vector& up);*/ + + double compute_stdev_precision(const std::vector& vec); + double compute_stdev_accuracy(const std::vector& vec, double ref); + + + //std::string generated_kml_file; +}; + + +void AcquisitionPerformanceTest::init() +{ + gnss_synchro.Channel_ID = 0; + gnss_synchro.System = 'G'; + std::string signal = "1C"; + signal.copy(gnss_synchro.Signal, 2, 0); + gnss_synchro.PRN = 1; +} + + +int AcquisitionPerformanceTest::configure_generator(double cn0) +{ + // Configure signal generator + generator_binary = FLAGS_generator_binary; + int duration_s = 2; + + p1 = std::string("-rinex_nav_file=") + FLAGS_rinex_nav_file; + if (FLAGS_dynamic_position.empty()) + { + p2 = std::string("-static_position=") + FLAGS_static_position + std::string(",") + std::to_string(std::min(duration_s * 10, 3000)); + } + else + { + p2 = std::string("-obs_pos_file=") + std::string(FLAGS_dynamic_position); + } + p3 = std::string("-rinex_obs_file=") + FLAGS_filename_rinex_obs; // RINEX 2.10 observation file output + p4 = std::string("-sig_out_file=") + FLAGS_filename_raw_data; // Baseband signal output file. Will be stored in int8_t IQ multiplexed samples + p5 = std::string("-sampling_freq=") + std::to_string(baseband_sampling_freq); // Baseband sampling frequency [MSps] + p6 = std::string("-CN0_dBHz=") + std::to_string(cn0); + return 0; +} + + +int AcquisitionPerformanceTest::generate_signal() +{ + pid_t wait_result; + int child_status; + std::cout << "Generating signal for " << p6 << "..." << std::endl; + char* const parmList[] = {&generator_binary[0], &generator_binary[0], &p1[0], &p2[0], &p3[0], &p4[0], &p5[0], &p6[0], NULL}; + + int pid; + if ((pid = fork()) == -1) + perror("fork error"); + else if (pid == 0) + { + execv(&generator_binary[0], parmList); + std::cout << "Return not expected. Must be an execv error." << std::endl; + std::terminate(); + } + + wait_result = waitpid(pid, &child_status, 0); + if (wait_result == -1) perror("waitpid error"); + return 0; +} + + +int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter) +{ + if (FLAGS_config_file_ptest.empty()) + { + config = std::make_shared(); + const int sampling_rate_internal = baseband_sampling_freq; + + const int number_of_taps = 11; + const int number_of_bands = 2; + const float band1_begin = 0.0; + const float band1_end = 0.48; + const float band2_begin = 0.52; + const float band2_end = 1.0; + const float ampl1_begin = 1.0; + const float ampl1_end = 1.0; + const float ampl2_begin = 0.0; + const float ampl2_end = 0.0; + const float band1_error = 1.0; + const float band2_error = 1.0; + const int grid_density = 16; + + const float zero = 0.0; + const int number_of_channels = 1; + const int in_acquisition = 1; + + const float threshold = 0.01; + const float doppler_max = 8000.0; + const float doppler_step = 500.0; + const int max_dwells = 1; + const int tong_init_val = 2; + const int tong_max_val = 10; + const int tong_max_dwells = 30; + const int coherent_integration_time_ms = 1; + + const float pll_bw_hz = 30.0; + const float dll_bw_hz = 4.0; + const float early_late_space_chips = 0.5; + const float pll_bw_narrow_hz = 20.0; + const float dll_bw_narrow_hz = 2.0; + const int extend_correlation_ms = 1; + + const int display_rate_ms = 500; + const int output_rate_ms = 100; + + config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(sampling_rate_internal)); + + // Set the assistance system parameters + config->set_property("GNSS-SDR.SUPL_read_gps_assistance_xml", "false"); + config->set_property("GNSS-SDR.SUPL_gps_enabled", "false"); + config->set_property("GNSS-SDR.SUPL_gps_ephemeris_server", "supl.google.com"); + config->set_property("GNSS-SDR.SUPL_gps_ephemeris_port", std::to_string(7275)); + config->set_property("GNSS-SDR.SUPL_gps_acquisition_server", "supl.google.com"); + config->set_property("GNSS-SDR.SUPL_gps_acquisition_port", std::to_string(7275)); + config->set_property("GNSS-SDR.SUPL_MCC", std::to_string(244)); + config->set_property("GNSS-SDR.SUPL_MNS", std::to_string(5)); + config->set_property("GNSS-SDR.SUPL_LAC", "0x59e2"); + config->set_property("GNSS-SDR.SUPL_CI", "0x31b0"); + + // Set the Signal Source + config->set_property("SignalSource.implementation", "File_Signal_Source"); + config->set_property("SignalSource.filename", "./" + filename_raw_data); + config->set_property("SignalSource.sampling_frequency", std::to_string(sampling_rate_internal)); + config->set_property("SignalSource.item_type", "ibyte"); + config->set_property("SignalSource.samples", std::to_string(zero)); + + // Set the Signal Conditioner + config->set_property("SignalConditioner.implementation", "Signal_Conditioner"); + config->set_property("DataTypeAdapter.implementation", "Ibyte_To_Complex"); + config->set_property("InputFilter.implementation", "Fir_Filter"); + config->set_property("InputFilter.dump", "false"); + config->set_property("InputFilter.input_item_type", "gr_complex"); + config->set_property("InputFilter.output_item_type", "gr_complex"); + config->set_property("InputFilter.taps_item_type", "float"); + config->set_property("InputFilter.number_of_taps", std::to_string(number_of_taps)); + config->set_property("InputFilter.number_of_bands", std::to_string(number_of_bands)); + config->set_property("InputFilter.band1_begin", std::to_string(band1_begin)); + config->set_property("InputFilter.band1_end", std::to_string(band1_end)); + config->set_property("InputFilter.band2_begin", std::to_string(band2_begin)); + config->set_property("InputFilter.band2_end", std::to_string(band2_end)); + config->set_property("InputFilter.ampl1_begin", std::to_string(ampl1_begin)); + config->set_property("InputFilter.ampl1_end", std::to_string(ampl1_end)); + config->set_property("InputFilter.ampl2_begin", std::to_string(ampl2_begin)); + config->set_property("InputFilter.ampl2_end", std::to_string(ampl2_end)); + config->set_property("InputFilter.band1_error", std::to_string(band1_error)); + config->set_property("InputFilter.band2_error", std::to_string(band2_error)); + config->set_property("InputFilter.filter_type", "bandpass"); + config->set_property("InputFilter.grid_density", std::to_string(grid_density)); + config->set_property("InputFilter.sampling_frequency", std::to_string(sampling_rate_internal)); + config->set_property("InputFilter.IF", std::to_string(zero)); + config->set_property("Resampler.implementation", "Pass_Through"); + config->set_property("Resampler.dump", "false"); + config->set_property("Resampler.item_type", "gr_complex"); + config->set_property("Resampler.sample_freq_in", std::to_string(sampling_rate_internal)); + config->set_property("Resampler.sample_freq_out", std::to_string(sampling_rate_internal)); + + // Set the number of Channels + config->set_property("Channels_1C.count", std::to_string(number_of_channels)); + config->set_property("Channels.in_acquisition", std::to_string(in_acquisition)); + config->set_property("Channel.signal", "1C"); + + // 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_step", std::to_string(doppler_step)); + + config->set_property("Acquisition_1C.threshold", "0.00001"); + //config->set_property("Acquisition_1C.pfa", "0.0"); + config->set_property("Acquisition_1C.use_CFAR_algorithm", "false"); + + config->set_property("Acquisition_1C.coherent_integration_time_ms", "1"); + config->set_property("Acquisition_1C.use_bit_transition_flag", "false"); + + config->set_property("Acquisition_1C.max_dwells", std::to_string(1)); + + config->set_property("Acquisition_1C.repeat_satellite", "false"); + + 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)); + //if (FLAGS_plot_acq_grid == true) + // { + config->set_property("Acquisition_1C.dump", "true"); + // } + //else + // { + // config->set_property("Acquisition_1C.dump", "false"); + // } + std::string dump_file = std::string("./acquisition_") + std::to_string(cn0) + "_" + std::to_string(iter); + config->set_property("Acquisition_1C.dump_filename", dump_file); + + // Set Tracking + config->set_property("Tracking_1C.implementation", "GPS_L1_CA_DLL_PLL_Tracking"); + //config->set_property("Tracking_1C.implementation", "GPS_L1_CA_DLL_PLL_C_Aid_Tracking"); + config->set_property("Tracking_1C.item_type", "gr_complex"); + config->set_property("Tracking_1C.dump", "false"); + config->set_property("Tracking_1C.dump_filename", "./tracking_ch_"); + config->set_property("Tracking_1C.pll_bw_hz", std::to_string(pll_bw_hz)); + config->set_property("Tracking_1C.dll_bw_hz", std::to_string(dll_bw_hz)); + config->set_property("Tracking_1C.early_late_space_chips", std::to_string(early_late_space_chips)); + + config->set_property("Tracking_1C.pll_bw_narrow_hz", std::to_string(pll_bw_narrow_hz)); + config->set_property("Tracking_1C.dll_bw_narrow_hz", std::to_string(dll_bw_narrow_hz)); + config->set_property("Tracking_1C.extend_correlation_symbols", std::to_string(extend_correlation_ms)); + + // Set Telemetry + config->set_property("TelemetryDecoder_1C.implementation", "GPS_L1_CA_Telemetry_Decoder"); + config->set_property("TelemetryDecoder_1C.dump", "false"); + + // Set Observables + config->set_property("Observables.implementation", "Hybrid_Observables"); + config->set_property("Observables.dump", "false"); + config->set_property("Observables.dump_filename", "./observables.dat"); + + // Set PVT + config->set_property("PVT.implementation", "RTKLIB_PVT"); + config->set_property("PVT.positioning_mode", "PPP_Static"); + config->set_property("PVT.output_rate_ms", std::to_string(output_rate_ms)); + config->set_property("PVT.display_rate_ms", std::to_string(display_rate_ms)); + config->set_property("PVT.dump_filename", "./PVT"); + config->set_property("PVT.nmea_dump_filename", "./gnss_sdr_pvt.nmea"); + config->set_property("PVT.flag_nmea_tty_port", "false"); + config->set_property("PVT.nmea_dump_devname", "/dev/pts/4"); + config->set_property("PVT.flag_rtcm_server", "false"); + config->set_property("PVT.flag_rtcm_tty_port", "false"); + config->set_property("PVT.rtcm_dump_devname", "/dev/pts/1"); + config->set_property("PVT.dump", "false"); + config->set_property("PVT.rinex_version", std::to_string(2)); + config->set_property("PVT.iono_model", "OFF"); + config->set_property("PVT.trop_model", "OFF"); + config->set_property("PVT.AR_GPS", "PPP-AR"); + + config_f = 0; + } + else + { + config_f = std::make_shared(FLAGS_config_file_ptest); + config = 0; + } + return 0; +} + + +int AcquisitionPerformanceTest::run_receiver() +{ + std::shared_ptr control_thread; + if (FLAGS_config_file_ptest.empty()) + { + control_thread = std::make_shared(config); + } + else + { + control_thread = std::make_shared(config_f); + } + + // start receiver + try + { + control_thread->run(); + } + catch (const boost::exception& e) + { + std::cout << "Boost exception: " << boost::diagnostic_information(e); + } + catch (const std::exception& ex) + { + std::cout << "STD exception: " << ex.what(); + } + return 0; +} + + +TEST_F(AcquisitionPerformanceTest, PdvsCn0) +{ + for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) + { + // Set parameter to sweep + + // Do N_iterations of the experiment + for (unsigned iter = 0; iter < N_iterations; iter++) + { + // Configure the signal generator + configure_generator(*it); + + // Generate signal raw signal samples and observations RINEX file + generate_signal(); + + // Configure the receiver + configure_receiver(*it, iter); + + // Run it + run_receiver(); + + // Read and store reference data and results + } + } + + // Compute results +} + +//TEST_F(AcquisitionPerformanceTest, ValidationOfResults) +//{ +// std::chrono::time_point start, end; +// std::chrono::duration elapsed_seconds(0.0); +// top_block = gr::make_top_block("Acquisition test"); +// +// double expected_delay_samples = 524; +// double expected_doppler_hz = 1680; +// +// init(); +// +// if (FLAGS_plot_acq_grid == true) +// { +// std::string data_str = "./tmp-acq-gps1"; +// if (boost::filesystem::exists(data_str)) +// { +// boost::filesystem::remove_all(data_str); +// } +// boost::filesystem::create_directory(data_str); +// } +// +// std::shared_ptr acquisition = std::make_shared(config.get(), "Acquisition_1C", 1, 0); +// boost::shared_ptr msg_rx = AcqPerfTest_msg_rx_make(); +// +// ASSERT_NO_THROW({ +// acquisition->set_channel(1); +// }) << "Failure setting channel."; +// +// ASSERT_NO_THROW({ +// acquisition->set_gnss_synchro(&gnss_synchro); +// }) << "Failure setting gnss_synchro."; +// +// ASSERT_NO_THROW({ +// acquisition->set_threshold(0.001); +// }) << "Failure setting threshold."; +// +// ASSERT_NO_THROW({ +// acquisition->set_doppler_max(doppler_max); +// }) << "Failure setting doppler_max."; +// +// ASSERT_NO_THROW({ +// acquisition->set_doppler_step(doppler_step); +// }) << "Failure setting doppler_step."; +// +// ASSERT_NO_THROW({ +// acquisition->connect(top_block); +// }) << "Failure connecting acquisition to the top_block."; +// +// ASSERT_NO_THROW({ +// std::string path = std::string(TEST_PATH); +// std::string file = path + "signal_samples/GPS_L1_CA_ID_1_Fs_4Msps_2ms.dat"; +// const char* file_name = file.c_str(); +// gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); +// top_block->connect(file_source, 0, acquisition->get_left_block(), 0); +// top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); +// }) << "Failure connecting the blocks of acquisition test."; +// +// acquisition->set_local_code(); +// acquisition->set_state(1); // Ensure that acquisition starts at the first sample +// acquisition->init(); +// +// EXPECT_NO_THROW({ +// start = std::chrono::system_clock::now(); +// top_block->run(); // Start threads and wait +// end = std::chrono::system_clock::now(); +// elapsed_seconds = end - start; +// }) << "Failure running the top_block."; +// +// unsigned long int nsamples = gnss_synchro.Acq_samplestamp_samples; +// std::cout << "Acquired " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; +// ASSERT_EQ(1, msg_rx->rx_message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS."; +// +// double delay_error_samples = std::abs(expected_delay_samples - gnss_synchro.Acq_delay_samples); +// float delay_error_chips = static_cast(delay_error_samples * 1023 / 4000); +// double doppler_error_hz = std::abs(expected_doppler_hz - gnss_synchro.Acq_doppler_hz); +// +// EXPECT_LE(doppler_error_hz, 666) << "Doppler error exceeds the expected value: 666 Hz = 2/(3*integration period)"; +// EXPECT_LT(delay_error_chips, 0.5) << "Delay error exceeds the expected value: 0.5 chips"; +// +// /*if (FLAGS_plot_acq_grid == true) +// { +// plot_grid(); +// }*/ +//} diff --git a/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc b/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc index b8363c383..30a48cb71 100644 --- a/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc @@ -54,7 +54,6 @@ #include "test_flags.h" DEFINE_bool(plot_gps_l1_tracking_test, false, "Plots results of GpsL1CADllPllTrackingTest with gnuplot"); -DEFINE_double(CN0_dBHz, std::numeric_limits::infinity(), "Enable noise generator and set the CN0 [dB-Hz]"); DEFINE_int32(extend_correlation_symbols, 1, "Set the tracking coherent correlation to N symbols (up to 20 for GPS L1 C/A)"); // ######## GNURADIO BLOCK MESSAGE RECEVER ######### @@ -184,7 +183,7 @@ int GpsL1CADllPllTrackingTest::configure_generator() p3 = std::string("-rinex_obs_file=") + FLAGS_filename_rinex_obs; // RINEX 2.10 observation file output p4 = std::string("-sig_out_file=") + FLAGS_filename_raw_data; // Baseband signal output file. Will be stored in int8_t IQ multiplexed samples p5 = std::string("-sampling_freq=") + std::to_string(baseband_sampling_freq); //Baseband sampling frequency [MSps] - p6 = std::string("-CN0_dBHz=") + std::to_string(FLAGS_CN0_dBHz); // Signal generator CN0 + p6 = std::string("-CN0_dBHz=") + std::to_string(FLAGS_CN0_dBHz); // Signal generator CN0 return 0; } @@ -193,7 +192,7 @@ int GpsL1CADllPllTrackingTest::generate_signal() { int child_status; - char* const parmList[] = {&generator_binary[0], &generator_binary[0], &p1[0], &p2[0], &p3[0], &p4[0], &p5[0],&p6[0], NULL}; + char* const parmList[] = {&generator_binary[0], &generator_binary[0], &p1[0], &p2[0], &p3[0], &p4[0], &p5[0], &p6[0], NULL}; int pid; if ((pid = fork()) == -1) From 175f1355d599484435994a1848bd6df6428ae7a0 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Wed, 20 Jun 2018 20:09:58 +0200 Subject: [PATCH 02/16] Add work on acq performance test --- .../gps_l1_acq_performance_test.cc | 166 ++++++++++++------ 1 file changed, 112 insertions(+), 54 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index 08287722c..c0d2e8133 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -38,59 +38,60 @@ DEFINE_string(config_file_ptest, std::string(""), "File containing the configuration parameters for the position test."); // ######## GNURADIO BLOCK MESSAGE RECEVER ######### -//class AcqPerfTest_msg_rx; +class AcqPerfTest_msg_rx; // -//typedef boost::shared_ptr AcqPerfTest_msg_rx_sptr; +typedef boost::shared_ptr AcqPerfTest_msg_rx_sptr; // -//AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); +AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); // -//class AcqPerfTest_msg_rx : public gr::block -//{ -//private: -// friend AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); -// void msg_handler_events(pmt::pmt_t msg); -// AcqPerfTest_msg_rx(); -// -//public: -// int rx_message; -// ~AcqPerfTest_msg_rx(); //!< Default destructor -//}; -// -// -//AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make() -//{ -// return AcqPerfTest_msg_rx_sptr(new AcqPerfTest_msg_rx()); -//} -// -// -//void AcqPerfTest_msg_rx::msg_handler_events(pmt::pmt_t msg) -//{ -// try -// { -// long int message = pmt::to_long(msg); -// rx_message = message; -// } -// catch (boost::bad_any_cast& e) -// { -// LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; -// rx_message = 0; -// } -//} -// -// -//AcqPerfTest_msg_rx::AcqPerfTest_msg_rx() : gr::block("AcqPerfTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) -//{ -// this->message_port_register_in(pmt::mp("events")); -// this->set_msg_handler(pmt::mp("events"), boost::bind(&AcqPerfTest_msg_rx::msg_handler_events, this, _1)); -// rx_message = 0; -//} -// -// -//AcqPerfTest_msg_rx::~AcqPerfTest_msg_rx() -//{ -//} -// -//// ----------------------------------------- +class AcqPerfTest_msg_rx : public gr::block +{ +private: + friend AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); + void msg_handler_events(pmt::pmt_t msg); + AcqPerfTest_msg_rx(); + +public: + int rx_message; + ~AcqPerfTest_msg_rx(); //!< Default destructor +}; + + +AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make() +{ + return AcqPerfTest_msg_rx_sptr(new AcqPerfTest_msg_rx()); +} + + +void AcqPerfTest_msg_rx::msg_handler_events(pmt::pmt_t msg) +{ + try + { + long int message = pmt::to_long(msg); + rx_message = message; + } + catch (boost::bad_any_cast& e) + { + LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; + rx_message = 0; + } + std::cout << "Received message:" << rx_message << std::endl; +} + + +AcqPerfTest_msg_rx::AcqPerfTest_msg_rx() : gr::block("AcqPerfTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) +{ + this->message_port_register_in(pmt::mp("events")); + this->set_msg_handler(pmt::mp("events"), boost::bind(&AcqPerfTest_msg_rx::msg_handler_events, this, _1)); + rx_message = 0; +} + + +AcqPerfTest_msg_rx::~AcqPerfTest_msg_rx() +{ +} + +// ----------------------------------------- class AcquisitionPerformanceTest : public ::testing::Test @@ -109,8 +110,8 @@ protected: { } - std::vector cn0_ = {41.0, 42.0, 43.0}; - int N_iterations = 2; + std::vector cn0_ = {38.0, 40.0, 43.0}; + int N_iterations = 1; void init(); //void plot_grid(); @@ -118,6 +119,7 @@ protected: int generate_signal(); int configure_receiver(double cn0, unsigned int iter); int run_receiver(); + int run_receiver2(); void check_results(); gr::top_block_sptr top_block; Gnss_Synchro gnss_synchro; @@ -125,6 +127,7 @@ protected: unsigned int doppler_max; unsigned int doppler_step; std::string implementation = "GPS_L1_CA_PCPS_Acquisition"; + boost::shared_ptr acquisition; std::shared_ptr config; std::shared_ptr config_f; @@ -325,7 +328,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Acquisition_1C.max_dwells", std::to_string(1)); - config->set_property("Acquisition_1C.repeat_satellite", "false"); + config->set_property("Acquisition_1C.repeat_satellite", "true"); config->set_property("Acquisition_1C.blocking", "true"); config->set_property("Acquisition_1C.make_two_steps", "false"); @@ -355,6 +358,9 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Tracking_1C.pll_bw_narrow_hz", std::to_string(pll_bw_narrow_hz)); config->set_property("Tracking_1C.dll_bw_narrow_hz", std::to_string(dll_bw_narrow_hz)); config->set_property("Tracking_1C.extend_correlation_symbols", std::to_string(extend_correlation_ms)); + config->set_property("Tracking_1C.cn0_min", std::to_string(50)); + config->set_property("Tracking_1C.max_lock_fail", std::to_string(1)); + config->set_property("Tracking_1C.cn0_samples", std::to_string(1)); // Set Telemetry config->set_property("TelemetryDecoder_1C.implementation", "GPS_L1_CA_Telemetry_Decoder"); @@ -395,6 +401,58 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter int AcquisitionPerformanceTest::run_receiver() +{ + std::chrono::time_point start, end; + std::chrono::duration elapsed_seconds(0); + std::string file = "./" + filename_raw_data; //+ std::to_string(current_cn0_idx); + const char* file_name = file.c_str(); + gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false); + + for (unsigned k = 0; k < 2; k++) + { + gr::top_block_sptr top_block_ = gr::make_top_block("Acquisition test"); + boost::shared_ptr msg_rx = AcqPerfTest_msg_rx_make(); + + gnss_synchro = Gnss_Synchro(); + init(); + auto acquisition_ = boost::make_shared(config.get(), "Acquisition_1C", 1, 0); + + //acquisition->connect(top_block); + acquisition_->set_gnss_synchro(&gnss_synchro); + + acquisition_->connect(top_block_); + acquisition_->set_local_code(); + acquisition_->set_state(1); // Ensure that acquisition starts at the first sample + acquisition_->init(); + //file_source->seek(static_cast(100 * k), SEEK_SET); + + if (not file_source->seek(static_cast(100 * k), SEEK_SET)) + { + std::cout << "Error skipping " << k << std::endl; + } + gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make(); + 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_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); + + + start = std::chrono::system_clock::now(); + top_block_->run(); // Start threads and wait + end = std::chrono::system_clock::now(); + //file_source->close(); + elapsed_seconds = end - start; + std::cout << "Acq_delay_samples: " << gnss_synchro.Acq_delay_samples << std::endl; + std::cout << "Acq_doppler_hz: " << gnss_synchro.Acq_doppler_hz << std::endl; + std::cout << "Acq_samplestamp_samples: " << gnss_synchro.Acq_samplestamp_samples << std::endl + << std::endl; + } + + //std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; + + return 0; +} + +int AcquisitionPerformanceTest::run_receiver2() { std::shared_ptr control_thread; if (FLAGS_config_file_ptest.empty()) @@ -442,7 +500,7 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) configure_receiver(*it, iter); // Run it - run_receiver(); + run_receiver2(); // Read and store reference data and results } From 2a9a8f5b29fba1cc986f31cb66afb3995a784e00 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Wed, 20 Jun 2018 20:44:13 +0200 Subject: [PATCH 03/16] Stire results also when using the refinement stage --- .../gnuradio_blocks/pcps_acquisition.cc | 88 +++++++++++-------- .../gnuradio_blocks/pcps_acquisition.h | 2 + 2 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc index 1176105d3..8e93024a8 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc @@ -335,6 +335,50 @@ void pcps_acquisition::send_negative_acquisition() } +void pcps_acquisition::dump_results(unsigned int doppler_index, int effective_fft_size) +{ + memcpy(grid_.colptr(doppler_index), d_magnitude, sizeof(float) * effective_fft_size); + if (doppler_index == (d_num_doppler_bins - 1)) + { + std::string filename = acq_parameters.dump_filename; + filename.append("_"); + filename.append(1, d_gnss_synchro->System); + filename.append("_"); + filename.append(1, d_gnss_synchro->Signal[0]); + filename.append(1, d_gnss_synchro->Signal[1]); + filename.append("_sat_"); + filename.append(std::to_string(d_gnss_synchro->PRN)); + filename.append(".mat"); + + mat_t* matfp = Mat_CreateVer(filename.c_str(), NULL, MAT_FT_MAT73); + if (matfp == NULL) + { + std::cout << "Unable to create or open Acquisition dump file" << std::endl; + acq_parameters.dump = false; + } + else + { + size_t dims[2] = {static_cast(effective_fft_size), static_cast(d_num_doppler_bins)}; + matvar_t* matvar = Mat_VarCreate("grid", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, grid_.memptr(), 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); + + dims[0] = static_cast(1); + dims[1] = static_cast(1); + matvar = Mat_VarCreate("doppler_max", MAT_C_UINT32, MAT_T_UINT32, 1, dims, &acq_parameters.doppler_max, 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); + + matvar = Mat_VarCreate("doppler_step", MAT_C_UINT32, MAT_T_UINT32, 1, dims, &d_doppler_step, 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); + + Mat_Close(matfp); + } + } +} + + void pcps_acquisition::acquisition_core(unsigned long int samp_count) { gr::thread::scoped_lock lk(d_setlock); @@ -435,44 +479,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) // Record results to file if required if (acq_parameters.dump) { - memcpy(grid_.colptr(doppler_index), d_magnitude, sizeof(float) * effective_fft_size); - if (doppler_index == (d_num_doppler_bins - 1)) - { - std::string filename = acq_parameters.dump_filename; - filename.append("_"); - filename.append(1, d_gnss_synchro->System); - filename.append("_"); - filename.append(1, d_gnss_synchro->Signal[0]); - filename.append(1, d_gnss_synchro->Signal[1]); - filename.append("_sat_"); - filename.append(std::to_string(d_gnss_synchro->PRN)); - filename.append(".mat"); - mat_t* matfp = Mat_CreateVer(filename.c_str(), NULL, MAT_FT_MAT73); - if (matfp == NULL) - { - std::cout << "Unable to create or open Acquisition dump file" << std::endl; - acq_parameters.dump = false; - } - else - { - size_t dims[2] = {static_cast(effective_fft_size), static_cast(d_num_doppler_bins)}; - matvar_t* matvar = Mat_VarCreate("grid", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, grid_.memptr(), 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - dims[0] = static_cast(1); - dims[1] = static_cast(1); - matvar = Mat_VarCreate("doppler_max", MAT_C_SINGLE, MAT_T_UINT32, 1, dims, &acq_parameters.doppler_max, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - matvar = Mat_VarCreate("doppler_step", MAT_C_SINGLE, MAT_T_UINT32, 1, dims, &d_doppler_step, 0); - Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE - Mat_VarFree(matvar); - - Mat_Close(matfp); - } - } + pcps_acquisition::dump_results(doppler_index, effective_fft_size); } } } @@ -538,6 +545,11 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) d_test_statistics = d_mag / d_input_power; } } + // Record results to file if required + if (acq_parameters.dump) + { + pcps_acquisition::dump_results(doppler_index, effective_fft_size); + } } } lk.lock(); diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h index 615957921..429353bd9 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h @@ -93,6 +93,8 @@ private: void send_positive_acquisition(); + void dump_results(unsigned int doppler_index, int effective_fft_size); + Acq_Conf acq_parameters; bool d_active; bool d_worker_active; From 68fd25a20f78821a75585342f5b0483353f28f18 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 21 Jun 2018 09:53:47 +0200 Subject: [PATCH 04/16] Merging --- .../gps_l1_acq_performance_test.cc | 166 ++-- .../gps_l1_ca_dll_pll_tracking_test.cc | 838 ++++++++++++------ 2 files changed, 659 insertions(+), 345 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index 08287722c..c0d2e8133 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -38,59 +38,60 @@ DEFINE_string(config_file_ptest, std::string(""), "File containing the configuration parameters for the position test."); // ######## GNURADIO BLOCK MESSAGE RECEVER ######### -//class AcqPerfTest_msg_rx; +class AcqPerfTest_msg_rx; // -//typedef boost::shared_ptr AcqPerfTest_msg_rx_sptr; +typedef boost::shared_ptr AcqPerfTest_msg_rx_sptr; // -//AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); +AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); // -//class AcqPerfTest_msg_rx : public gr::block -//{ -//private: -// friend AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); -// void msg_handler_events(pmt::pmt_t msg); -// AcqPerfTest_msg_rx(); -// -//public: -// int rx_message; -// ~AcqPerfTest_msg_rx(); //!< Default destructor -//}; -// -// -//AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make() -//{ -// return AcqPerfTest_msg_rx_sptr(new AcqPerfTest_msg_rx()); -//} -// -// -//void AcqPerfTest_msg_rx::msg_handler_events(pmt::pmt_t msg) -//{ -// try -// { -// long int message = pmt::to_long(msg); -// rx_message = message; -// } -// catch (boost::bad_any_cast& e) -// { -// LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; -// rx_message = 0; -// } -//} -// -// -//AcqPerfTest_msg_rx::AcqPerfTest_msg_rx() : gr::block("AcqPerfTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) -//{ -// this->message_port_register_in(pmt::mp("events")); -// this->set_msg_handler(pmt::mp("events"), boost::bind(&AcqPerfTest_msg_rx::msg_handler_events, this, _1)); -// rx_message = 0; -//} -// -// -//AcqPerfTest_msg_rx::~AcqPerfTest_msg_rx() -//{ -//} -// -//// ----------------------------------------- +class AcqPerfTest_msg_rx : public gr::block +{ +private: + friend AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); + void msg_handler_events(pmt::pmt_t msg); + AcqPerfTest_msg_rx(); + +public: + int rx_message; + ~AcqPerfTest_msg_rx(); //!< Default destructor +}; + + +AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make() +{ + return AcqPerfTest_msg_rx_sptr(new AcqPerfTest_msg_rx()); +} + + +void AcqPerfTest_msg_rx::msg_handler_events(pmt::pmt_t msg) +{ + try + { + long int message = pmt::to_long(msg); + rx_message = message; + } + catch (boost::bad_any_cast& e) + { + LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; + rx_message = 0; + } + std::cout << "Received message:" << rx_message << std::endl; +} + + +AcqPerfTest_msg_rx::AcqPerfTest_msg_rx() : gr::block("AcqPerfTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) +{ + this->message_port_register_in(pmt::mp("events")); + this->set_msg_handler(pmt::mp("events"), boost::bind(&AcqPerfTest_msg_rx::msg_handler_events, this, _1)); + rx_message = 0; +} + + +AcqPerfTest_msg_rx::~AcqPerfTest_msg_rx() +{ +} + +// ----------------------------------------- class AcquisitionPerformanceTest : public ::testing::Test @@ -109,8 +110,8 @@ protected: { } - std::vector cn0_ = {41.0, 42.0, 43.0}; - int N_iterations = 2; + std::vector cn0_ = {38.0, 40.0, 43.0}; + int N_iterations = 1; void init(); //void plot_grid(); @@ -118,6 +119,7 @@ protected: int generate_signal(); int configure_receiver(double cn0, unsigned int iter); int run_receiver(); + int run_receiver2(); void check_results(); gr::top_block_sptr top_block; Gnss_Synchro gnss_synchro; @@ -125,6 +127,7 @@ protected: unsigned int doppler_max; unsigned int doppler_step; std::string implementation = "GPS_L1_CA_PCPS_Acquisition"; + boost::shared_ptr acquisition; std::shared_ptr config; std::shared_ptr config_f; @@ -325,7 +328,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Acquisition_1C.max_dwells", std::to_string(1)); - config->set_property("Acquisition_1C.repeat_satellite", "false"); + config->set_property("Acquisition_1C.repeat_satellite", "true"); config->set_property("Acquisition_1C.blocking", "true"); config->set_property("Acquisition_1C.make_two_steps", "false"); @@ -355,6 +358,9 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Tracking_1C.pll_bw_narrow_hz", std::to_string(pll_bw_narrow_hz)); config->set_property("Tracking_1C.dll_bw_narrow_hz", std::to_string(dll_bw_narrow_hz)); config->set_property("Tracking_1C.extend_correlation_symbols", std::to_string(extend_correlation_ms)); + config->set_property("Tracking_1C.cn0_min", std::to_string(50)); + config->set_property("Tracking_1C.max_lock_fail", std::to_string(1)); + config->set_property("Tracking_1C.cn0_samples", std::to_string(1)); // Set Telemetry config->set_property("TelemetryDecoder_1C.implementation", "GPS_L1_CA_Telemetry_Decoder"); @@ -395,6 +401,58 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter int AcquisitionPerformanceTest::run_receiver() +{ + std::chrono::time_point start, end; + std::chrono::duration elapsed_seconds(0); + std::string file = "./" + filename_raw_data; //+ std::to_string(current_cn0_idx); + const char* file_name = file.c_str(); + gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false); + + for (unsigned k = 0; k < 2; k++) + { + gr::top_block_sptr top_block_ = gr::make_top_block("Acquisition test"); + boost::shared_ptr msg_rx = AcqPerfTest_msg_rx_make(); + + gnss_synchro = Gnss_Synchro(); + init(); + auto acquisition_ = boost::make_shared(config.get(), "Acquisition_1C", 1, 0); + + //acquisition->connect(top_block); + acquisition_->set_gnss_synchro(&gnss_synchro); + + acquisition_->connect(top_block_); + acquisition_->set_local_code(); + acquisition_->set_state(1); // Ensure that acquisition starts at the first sample + acquisition_->init(); + //file_source->seek(static_cast(100 * k), SEEK_SET); + + if (not file_source->seek(static_cast(100 * k), SEEK_SET)) + { + std::cout << "Error skipping " << k << std::endl; + } + gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make(); + 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_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); + + + start = std::chrono::system_clock::now(); + top_block_->run(); // Start threads and wait + end = std::chrono::system_clock::now(); + //file_source->close(); + elapsed_seconds = end - start; + std::cout << "Acq_delay_samples: " << gnss_synchro.Acq_delay_samples << std::endl; + std::cout << "Acq_doppler_hz: " << gnss_synchro.Acq_doppler_hz << std::endl; + std::cout << "Acq_samplestamp_samples: " << gnss_synchro.Acq_samplestamp_samples << std::endl + << std::endl; + } + + //std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; + + return 0; +} + +int AcquisitionPerformanceTest::run_receiver2() { std::shared_ptr control_thread; if (FLAGS_config_file_ptest.empty()) @@ -442,7 +500,7 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) configure_receiver(*it, iter); // Run it - run_receiver(); + run_receiver2(); // Read and store reference data and results } diff --git a/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc b/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc index d429460b5..1b3598489 100644 --- a/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc @@ -53,7 +53,27 @@ #include "gnuplot_i.h" #include "test_flags.h" -DEFINE_bool(plot_gps_l1_tracking_test, false, "Plots results of GpsL1CADllPllTrackingTest with gnuplot"); + +// Input signal configuration +DEFINE_bool(enable_external_signal_file, false, "Use an external signal file capture instead of the software-defined signal generator"); +DEFINE_string(signal_file, std::string("gps_l1_capture.dat"), "Path of the external signal capture file"); +DEFINE_double(CN0_dBHz_start, std::numeric_limits::infinity(), "Enable noise generator and set the CN0 start sweep value [dB-Hz]"); +DEFINE_double(CN0_dBHz_stop, std::numeric_limits::infinity(), "Enable noise generator and set the CN0 stop sweep value [dB-Hz]"); +DEFINE_double(CN0_dB_step, 3.0, "Noise generator CN0 sweep step value [dB]"); + +DEFINE_double(PLL_bw_hz_start, 40.0, "PLL Wide configuration start sweep value [Hz]"); +DEFINE_double(PLL_bw_hz_stop, 40.0, "PLL Wide configuration stop sweep value [Hz]"); +DEFINE_double(PLL_bw_hz_step, 5.0, "PLL Wide configuration sweep step value [Hz]"); + +DEFINE_double(DLL_bw_hz_start, 1.5, "DLL Wide configuration start sweep value [Hz]"); +DEFINE_double(DLL_bw_hz_stop, 1.5, "DLL Wide configuration stop sweep value [Hz]"); +DEFINE_double(DLL_bw_hz_step, 0.25, "DLL Wide configuration sweep step value [Hz]"); + +DEFINE_bool(plot_extra, false, "Enable or disable plots of the correlators output and constellation diagrams"); + +//Emulated acquisition configuration + +//Tracking configuration DEFINE_int32(extend_correlation_symbols, 1, "Set the tracking coherent correlation to N symbols (up to 20 for GPS L1 C/A)"); //Test output configuration @@ -137,15 +157,21 @@ public: std::vector check_results_doppler(arma::vec& true_time_s, arma::vec& true_value, arma::vec& meas_time_s, - arma::vec& meas_value); + arma::vec& meas_value, + double& mean_error, + double& std_dev_error); std::vector check_results_acc_carrier_phase(arma::vec& true_time_s, arma::vec& true_value, arma::vec& meas_time_s, - arma::vec& meas_value); + arma::vec& meas_value, + double& mean_error, + double& std_dev_error); std::vector check_results_codephase(arma::vec& true_time_s, arma::vec& true_value, arma::vec& meas_time_s, - arma::vec& meas_value); + arma::vec& meas_value, + double& mean_error, + double& std_dev_error); GpsL1CADllPllTrackingTest() { @@ -159,7 +185,11 @@ public: { } - void configure_receiver(); + void configure_receiver(double PLL_wide_bw_hz, + double DLL_wide_bw_hz, + double PLL_narrow_bw_hz, + double DLL_narrow_bw_hz, + int extend_correlation_symbols); gr::top_block_sptr top_block; std::shared_ptr factory; @@ -214,7 +244,12 @@ int GpsL1CADllPllTrackingTest::generate_signal() } -void GpsL1CADllPllTrackingTest::configure_receiver() +void GpsL1CADllPllTrackingTest::configure_receiver( + double PLL_wide_bw_hz, + double DLL_wide_bw_hz, + double PLL_narrow_bw_hz, + double DLL_narrow_bw_hz, + int extend_correlation_symbols) { gnss_synchro.Channel_ID = 0; gnss_synchro.System = 'G'; @@ -222,26 +257,40 @@ void GpsL1CADllPllTrackingTest::configure_receiver() signal.copy(gnss_synchro.Signal, 2, 0); gnss_synchro.PRN = FLAGS_test_satellite_PRN; + config = std::make_shared(); config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq)); // Set Tracking config->set_property("Tracking_1C.implementation", implementation); config->set_property("Tracking_1C.item_type", "gr_complex"); - config->set_property("Tracking_1C.pll_bw_hz", "20.0"); - config->set_property("Tracking_1C.dll_bw_hz", "1.5"); + config->set_property("Tracking_1C.pll_bw_hz", std::to_string(PLL_wide_bw_hz)); + config->set_property("Tracking_1C.dll_bw_hz", std::to_string(DLL_wide_bw_hz)); config->set_property("Tracking_1C.early_late_space_chips", "0.5"); - config->set_property("Tracking_1C.extend_correlation_symbols", std::to_string(FLAGS_extend_correlation_symbols)); - config->set_property("Tracking_1C.pll_bw_narrow_hz", "2.0"); - config->set_property("Tracking_1C.dll_bw_narrow_hz", "1.0"); + config->set_property("Tracking_1C.extend_correlation_symbols", std::to_string(extend_correlation_symbols)); + config->set_property("Tracking_1C.pll_bw_narrow_hz", std::to_string(PLL_narrow_bw_hz)); + config->set_property("Tracking_1C.dll_bw_narrow_hz", std::to_string(DLL_narrow_bw_hz)); config->set_property("Tracking_1C.early_late_space_narrow_chips", "0.5"); config->set_property("Tracking_1C.dump", "true"); config->set_property("Tracking_1C.dump_filename", "./tracking_ch_"); + + std::cout << "*****************************************\n"; + std::cout << "*** Tracking configuration parameters ***\n"; + std::cout << "*****************************************\n"; + std::cout << "pll_bw_hz: " << config->property("Tracking_1C.pll_bw_hz", 0.0) << " Hz\n"; + std::cout << "dll_bw_hz: " << config->property("Tracking_1C.dll_bw_hz", 0.0) << " Hz\n"; + std::cout << "pll_bw_narrow_hz: " << config->property("Tracking_1C.pll_bw_narrow_hz", 0.0) << " Hz\n"; + std::cout << "dll_bw_narrow_hz: " << config->property("Tracking_1C.dll_bw_narrow_hz", 0.0) << " Hz\n"; + std::cout << "extend_correlation_symbols: " << config->property("Tracking_1C.extend_correlation_symbols", 0) << " Symbols\n"; + std::cout << "*****************************************\n"; + std::cout << "*****************************************\n"; } std::vector GpsL1CADllPllTrackingTest::check_results_doppler(arma::vec& true_time_s, arma::vec& true_value, arma::vec& meas_time_s, - arma::vec& meas_value) + arma::vec& meas_value, + double& mean_error, + double& std_dev_error) { // 1. True value interpolation to match the measurement times arma::vec true_value_interp; @@ -269,6 +318,9 @@ std::vector GpsL1CADllPllTrackingTest::check_results_doppler(arma::vec& double error_mean = arma::mean(err); double error_var = arma::var(err); + mean_error = error_mean; + std_dev_error = sqrt(error_var); + // 4. Peaks double max_error = arma::max(err); double min_error = arma::min(err); @@ -286,7 +338,9 @@ std::vector GpsL1CADllPllTrackingTest::check_results_doppler(arma::vec& std::vector GpsL1CADllPllTrackingTest::check_results_acc_carrier_phase(arma::vec& true_time_s, arma::vec& true_value, arma::vec& meas_time_s, - arma::vec& meas_value) + arma::vec& meas_value, + double& mean_error, + double& std_dev_error) { // 1. True value interpolation to match the measurement times arma::vec true_value_interp; @@ -312,6 +366,8 @@ std::vector GpsL1CADllPllTrackingTest::check_results_acc_carrier_phase(a double error_mean = arma::mean(err); double error_var = arma::var(err); + mean_error = error_mean; + std_dev_error = sqrt(error_var); // 4. Peaks double max_error = arma::max(err); double min_error = arma::min(err); @@ -329,7 +385,9 @@ std::vector GpsL1CADllPllTrackingTest::check_results_acc_carrier_phase(a std::vector GpsL1CADllPllTrackingTest::check_results_codephase(arma::vec& true_time_s, arma::vec& true_value, arma::vec& meas_time_s, - arma::vec& meas_value) + arma::vec& meas_value, + double& mean_error, + double& std_dev_error) { // 1. True value interpolation to match the measurement times arma::vec true_value_interp; @@ -356,6 +414,9 @@ std::vector GpsL1CADllPllTrackingTest::check_results_codephase(arma::vec double error_mean = arma::mean(err); double error_var = arma::var(err); + mean_error = error_mean; + std_dev_error = sqrt(error_var); + // 4. Peaks double max_error = arma::max(err); double min_error = arma::min(err); @@ -378,18 +439,18 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults) std::vector generator_CN0_values; - std::vector> prompt_sweep; - std::vector> early_sweep; - std::vector> late_sweep; - std::vector> promptI_sweep; - std::vector> promptQ_sweep; - std::vector> CN0_dBHz_sweep; - //error vectors - std::vector> doppler_error_sweep; - std::vector> code_phase_error_sweep; - std::vector> acc_carrier_phase_error_sweep; - std::vector> trk_timestamp_s_sweep; + //data containers for config param sweep + std::vector> mean_doppler_error_sweep; //swep config param and cn0 sweep + std::vector> std_dev_doppler_error_sweep; //swep config param and cn0 sweep + + std::vector> mean_code_phase_error_sweep; //swep config param and cn0 sweep + std::vector> std_dev_code_phase_error_sweep; //swep config param and cn0 sweep + + std::vector> mean_carrier_phase_error_sweep; //swep config param and cn0 sweep + std::vector> std_dev_carrier_phase_error_sweep; //swep config param and cn0 sweep + + std::vector> trk_valid_timestamp_s_sweep; if (FLAGS_CN0_dBHz_start == FLAGS_CN0_dBHz_stop) { @@ -433,192 +494,430 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults) } - //CN0 LOOP + // CONFIG PARAM SWEEP LOOP + std::vector PLL_wide_bw_values; + std::vector DLL_wide_bw_values; - for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + + if (FLAGS_PLL_bw_hz_start == FLAGS_PLL_bw_hz_stop) { - //****************************************************************************************** - //***** Obtain the initial signal sinchronization parameters (emulating an acquisition) **** - //****************************************************************************************** - if (!FLAGS_enable_external_signal_file) + if (FLAGS_DLL_bw_hz_start == FLAGS_DLL_bw_hz_stop) { - test_satellite_PRN = FLAGS_test_satellite_PRN; - std::string true_obs_file = std::string("./gps_l1_ca_obs_prn"); - true_obs_file.append(std::to_string(test_satellite_PRN)); - true_obs_file.append(".dat"); - true_obs_data.close_obs_file(); - ASSERT_EQ(true_obs_data.open_obs_file(true_obs_file), true) << "Failure opening true observables file"; - // load acquisition data based on the first epoch of the true observations - ASSERT_EQ(true_obs_data.read_binary_obs(), true) - << "Failure reading true tracking dump file." << std::endl - << "Maybe sat PRN #" + std::to_string(FLAGS_test_satellite_PRN) + - " is not available?"; - std::cout << "Testing satellite PRN=" << test_satellite_PRN << std::endl; - std::cout << "Initial Doppler [Hz]=" << true_obs_data.doppler_l1_hz << " Initial code delay [Chips]=" << true_obs_data.prn_delay_chips << std::endl; - acq_doppler_hz = true_obs_data.doppler_l1_hz; - acq_delay_samples = (GPS_L1_CA_CODE_LENGTH_CHIPS - true_obs_data.prn_delay_chips / GPS_L1_CA_CODE_LENGTH_CHIPS) * static_cast(baseband_sampling_freq) * GPS_L1_CA_CODE_PERIOD; - // restart the epoch counter - true_obs_data.restart(); + //NO PLL/DLL BW sweep + PLL_wide_bw_values.push_back(FLAGS_PLL_bw_hz_start); + DLL_wide_bw_values.push_back(FLAGS_DLL_bw_hz_start); } - - - //***** STEP 4: Configure the signal tracking parameters ***** - //************************************************************ - std::chrono::time_point start, end; - configure_receiver(); - - top_block = gr::make_top_block("Tracking test"); - - std::shared_ptr trk_ = factory->GetBlock(config, "Tracking_1C", implementation, 1, 1); - std::shared_ptr tracking = std::dynamic_pointer_cast(trk_); - - boost::shared_ptr msg_rx = GpsL1CADllPllTrackingTest_msg_rx_make(); - - gnss_synchro.Acq_delay_samples = acq_delay_samples; - gnss_synchro.Acq_doppler_hz = acq_doppler_hz; - gnss_synchro.Acq_samplestamp_samples = 0; - - ASSERT_NO_THROW({ - tracking->set_channel(gnss_synchro.Channel_ID); - }) << "Failure setting channel."; - - ASSERT_NO_THROW({ - tracking->set_gnss_synchro(&gnss_synchro); - }) << "Failure setting gnss_synchro."; - - ASSERT_NO_THROW({ - tracking->connect(top_block); - }) << "Failure connecting tracking to the top_block."; - - ASSERT_NO_THROW({ - std::string file = "./" + filename_raw_data + std::to_string(current_cn0_idx); - const char* file_name = file.c_str(); - 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)); - 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(tracking->get_right_block(), 0, sink, 0); - top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); - }) << "Failure connecting the blocks of tracking test."; - - - //******************************************************************** - //***** STEP 5: Perform the signal tracking and read the results ***** - //******************************************************************** - tracking->start_tracking(); - - EXPECT_NO_THROW({ - start = std::chrono::system_clock::now(); - top_block->run(); // Start threads and wait - end = std::chrono::system_clock::now(); - }) << "Failure running the top_block."; - - std::chrono::duration elapsed_seconds = end - start; - std::cout << "Signal tracking completed in " << elapsed_seconds.count() << " seconds" << std::endl; - - //check results - //load the measured values - tracking_dump_reader trk_dump; - ASSERT_EQ(trk_dump.open_obs_file(std::string("./tracking_ch_0.dat")), true) - << "Failure opening tracking dump file"; - - long int n_measured_epochs = trk_dump.num_epochs(); - std::cout << "Measured observation epochs=" << n_measured_epochs << std::endl; - - arma::vec trk_timestamp_s = arma::zeros(n_measured_epochs, 1); - arma::vec trk_acc_carrier_phase_cycles = arma::zeros(n_measured_epochs, 1); - arma::vec trk_Doppler_Hz = arma::zeros(n_measured_epochs, 1); - arma::vec trk_prn_delay_chips = arma::zeros(n_measured_epochs, 1); - - long int epoch_counter = 0; - - std::vector prompt; - std::vector early; - std::vector late; - std::vector promptI; - std::vector promptQ; - std::vector CN0_dBHz; - while (trk_dump.read_binary_obs()) + else { - trk_timestamp_s(epoch_counter) = static_cast(trk_dump.PRN_start_sample_count) / static_cast(baseband_sampling_freq); - trk_acc_carrier_phase_cycles(epoch_counter) = trk_dump.acc_carrier_phase_rad / GPS_TWO_PI; - trk_Doppler_Hz(epoch_counter) = trk_dump.carrier_doppler_hz; - double delay_chips = GPS_L1_CA_CODE_LENGTH_CHIPS - GPS_L1_CA_CODE_LENGTH_CHIPS * (fmod((static_cast(trk_dump.PRN_start_sample_count) + trk_dump.aux1) / static_cast(baseband_sampling_freq), 1.0e-3) / 1.0e-3); - - trk_prn_delay_chips(epoch_counter) = delay_chips; - epoch_counter++; - - - prompt.push_back(trk_dump.abs_P); - early.push_back(trk_dump.abs_E); - late.push_back(trk_dump.abs_L); - promptI.push_back(trk_dump.prompt_I); - promptQ.push_back(trk_dump.prompt_Q); - CN0_dBHz.push_back(trk_dump.CN0_SNV_dB_Hz); + //DLL BW Sweep + for (double dll_bw = FLAGS_DLL_bw_hz_start; dll_bw > FLAGS_DLL_bw_hz_stop; dll_bw = dll_bw - FLAGS_DLL_bw_hz_step) + { + PLL_wide_bw_values.push_back(FLAGS_PLL_bw_hz_start); + DLL_wide_bw_values.push_back(dll_bw); + } } - - prompt_sweep.push_back(prompt); - early_sweep.push_back(early); - late_sweep.push_back(late); - promptI_sweep.push_back(promptI); - promptQ_sweep.push_back(promptQ); - CN0_dBHz_sweep.push_back(CN0_dBHz); - - //*********************************************************** - //***** STEP 6: Compare with true values (if available) ***** - //*********************************************************** - if (!FLAGS_enable_external_signal_file) + } + else + { + //PLL BW Sweep + for (double pll_bw = FLAGS_PLL_bw_hz_start; pll_bw > FLAGS_PLL_bw_hz_stop; pll_bw = pll_bw - FLAGS_PLL_bw_hz_step) { - // load the true values - long int n_true_epochs = true_obs_data.num_epochs(); - std::cout << "True observation epochs=" << n_true_epochs << std::endl; + PLL_wide_bw_values.push_back(pll_bw); + DLL_wide_bw_values.push_back(FLAGS_DLL_bw_hz_start); + } + } - arma::vec true_timestamp_s = arma::zeros(n_true_epochs, 1); - arma::vec true_acc_carrier_phase_cycles = arma::zeros(n_true_epochs, 1); - arma::vec true_Doppler_Hz = arma::zeros(n_true_epochs, 1); - arma::vec true_prn_delay_chips = arma::zeros(n_true_epochs, 1); - arma::vec true_tow_s = arma::zeros(n_true_epochs, 1); + for (int config_idx = 0; config_idx < PLL_wide_bw_values.size(); config_idx++) + { + //CN0 LOOP + // data containers for CN0 sweep + std::vector> prompt_sweep; + std::vector> early_sweep; + std::vector> late_sweep; + std::vector> promptI_sweep; + std::vector> promptQ_sweep; + std::vector> CN0_dBHz_sweep; + std::vector> trk_timestamp_s_sweep; + + std::vector> doppler_error_sweep; + std::vector> code_phase_error_sweep; + std::vector> acc_carrier_phase_error_sweep; + + std::vector mean_doppler_error; + std::vector std_dev_doppler_error; + std::vector mean_code_phase_error; + std::vector std_dev_code_phase_error; + std::vector mean_carrier_phase_error; + std::vector std_dev_carrier_phase_error; + + configure_receiver(PLL_wide_bw_values.at(config_idx), + DLL_wide_bw_values.at(config_idx), + 2.0, + 1.0, + FLAGS_extend_correlation_symbols); + for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + //****************************************************************************************** + //***** Obtain the initial signal sinchronization parameters (emulating an acquisition) **** + //****************************************************************************************** + if (!FLAGS_enable_external_signal_file) + { + test_satellite_PRN = FLAGS_test_satellite_PRN; + std::string true_obs_file = std::string("./gps_l1_ca_obs_prn"); + true_obs_file.append(std::to_string(test_satellite_PRN)); + true_obs_file.append(".dat"); + true_obs_data.close_obs_file(); + ASSERT_EQ(true_obs_data.open_obs_file(true_obs_file), true) << "Failure opening true observables file"; + // load acquisition data based on the first epoch of the true observations + ASSERT_EQ(true_obs_data.read_binary_obs(), true) + << "Failure reading true tracking dump file." << std::endl + << "Maybe sat PRN #" + std::to_string(FLAGS_test_satellite_PRN) + + " is not available?"; + std::cout << "Testing satellite PRN=" << test_satellite_PRN << std::endl; + std::cout << "Initial Doppler [Hz]=" << true_obs_data.doppler_l1_hz << " Initial code delay [Chips]=" << true_obs_data.prn_delay_chips << std::endl; + acq_doppler_hz = true_obs_data.doppler_l1_hz; + acq_delay_samples = (GPS_L1_CA_CODE_LENGTH_CHIPS - true_obs_data.prn_delay_chips / GPS_L1_CA_CODE_LENGTH_CHIPS) * static_cast(baseband_sampling_freq) * GPS_L1_CA_CODE_PERIOD; + // restart the epoch counter + true_obs_data.restart(); + } + + + //***** STEP 4: Configure the signal tracking parameters ***** + //************************************************************ + std::chrono::time_point start, end; + + top_block = gr::make_top_block("Tracking test"); + + std::shared_ptr trk_ = factory->GetBlock(config, "Tracking_1C", implementation, 1, 1); + std::shared_ptr tracking = std::dynamic_pointer_cast(trk_); + + boost::shared_ptr msg_rx = GpsL1CADllPllTrackingTest_msg_rx_make(); + + gnss_synchro.Acq_delay_samples = acq_delay_samples; + gnss_synchro.Acq_doppler_hz = acq_doppler_hz; + gnss_synchro.Acq_samplestamp_samples = 0; + + ASSERT_NO_THROW({ + tracking->set_channel(gnss_synchro.Channel_ID); + }) << "Failure setting channel."; + + ASSERT_NO_THROW({ + tracking->set_gnss_synchro(&gnss_synchro); + }) << "Failure setting gnss_synchro."; + + ASSERT_NO_THROW({ + tracking->connect(top_block); + }) << "Failure connecting tracking to the top_block."; + + ASSERT_NO_THROW({ + std::string file = "./" + filename_raw_data + std::to_string(current_cn0_idx); + const char* file_name = file.c_str(); + 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)); + 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(tracking->get_right_block(), 0, sink, 0); + top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); + }) << "Failure connecting the blocks of tracking test."; + + + //******************************************************************** + //***** STEP 5: Perform the signal tracking and read the results ***** + //******************************************************************** + tracking->start_tracking(); + + EXPECT_NO_THROW({ + start = std::chrono::system_clock::now(); + top_block->run(); // Start threads and wait + end = std::chrono::system_clock::now(); + }) << "Failure running the top_block."; + + std::chrono::duration elapsed_seconds = end - start; + std::cout << "Signal tracking completed in " << elapsed_seconds.count() << " seconds" << std::endl; + + //check results + //load the measured values + tracking_dump_reader trk_dump; + ASSERT_EQ(trk_dump.open_obs_file(std::string("./tracking_ch_0.dat")), true) + << "Failure opening tracking dump file"; + + long int n_measured_epochs = trk_dump.num_epochs(); + std::cout << "Measured observation epochs=" << n_measured_epochs << std::endl; + + arma::vec trk_timestamp_s = arma::zeros(n_measured_epochs, 1); + arma::vec trk_acc_carrier_phase_cycles = arma::zeros(n_measured_epochs, 1); + arma::vec trk_Doppler_Hz = arma::zeros(n_measured_epochs, 1); + arma::vec trk_prn_delay_chips = arma::zeros(n_measured_epochs, 1); long int epoch_counter = 0; - while (true_obs_data.read_binary_obs()) + + std::vector timestamp_s; + std::vector prompt; + std::vector early; + std::vector late; + std::vector promptI; + std::vector promptQ; + std::vector CN0_dBHz; + while (trk_dump.read_binary_obs()) { - true_timestamp_s(epoch_counter) = true_obs_data.signal_timestamp_s; - true_acc_carrier_phase_cycles(epoch_counter) = true_obs_data.acc_carrier_phase_cycles; - true_Doppler_Hz(epoch_counter) = true_obs_data.doppler_l1_hz; - true_prn_delay_chips(epoch_counter) = true_obs_data.prn_delay_chips; - true_tow_s(epoch_counter) = true_obs_data.tow; + trk_timestamp_s(epoch_counter) = static_cast(trk_dump.PRN_start_sample_count) / static_cast(baseband_sampling_freq); + trk_acc_carrier_phase_cycles(epoch_counter) = trk_dump.acc_carrier_phase_rad / GPS_TWO_PI; + trk_Doppler_Hz(epoch_counter) = trk_dump.carrier_doppler_hz; + double delay_chips = GPS_L1_CA_CODE_LENGTH_CHIPS - GPS_L1_CA_CODE_LENGTH_CHIPS * (fmod((static_cast(trk_dump.PRN_start_sample_count) + trk_dump.aux1) / static_cast(baseband_sampling_freq), 1.0e-3) / 1.0e-3); + + trk_prn_delay_chips(epoch_counter) = delay_chips; + + timestamp_s.push_back(trk_timestamp_s(epoch_counter)); + prompt.push_back(trk_dump.abs_P); + early.push_back(trk_dump.abs_E); + late.push_back(trk_dump.abs_L); + promptI.push_back(trk_dump.prompt_I); + promptQ.push_back(trk_dump.prompt_Q); + CN0_dBHz.push_back(trk_dump.CN0_SNV_dB_Hz); + epoch_counter++; } - // Align initial measurements and cut the tracking pull-in transitory - double pull_in_offset_s = 1.0; - arma::uvec initial_meas_point = arma::find(trk_timestamp_s >= (true_timestamp_s(0) + pull_in_offset_s), 1, "first"); + trk_timestamp_s_sweep.push_back(timestamp_s); + prompt_sweep.push_back(prompt); + early_sweep.push_back(early); + late_sweep.push_back(late); + promptI_sweep.push_back(promptI); + promptQ_sweep.push_back(promptQ); + CN0_dBHz_sweep.push_back(CN0_dBHz); - trk_timestamp_s = trk_timestamp_s.subvec(initial_meas_point(0), trk_timestamp_s.size() - 1); - trk_acc_carrier_phase_cycles = trk_acc_carrier_phase_cycles.subvec(initial_meas_point(0), trk_acc_carrier_phase_cycles.size() - 1); - trk_Doppler_Hz = trk_Doppler_Hz.subvec(initial_meas_point(0), trk_Doppler_Hz.size() - 1); - trk_prn_delay_chips = trk_prn_delay_chips.subvec(initial_meas_point(0), trk_prn_delay_chips.size() - 1); + //*********************************************************** + //***** STEP 6: Compare with true values (if available) ***** + //*********************************************************** + if (!FLAGS_enable_external_signal_file) + { + std::vector doppler_error_hz; + std::vector code_phase_error_chips; + std::vector acc_carrier_phase_hz; + try + { + // load the true values + long int n_true_epochs = true_obs_data.num_epochs(); + std::cout << "True observation epochs=" << n_true_epochs << std::endl; - std::vector doppler_error_hz; - std::vector code_phase_error_chips; - std::vector acc_carrier_phase_hz; - doppler_error_hz = check_results_doppler(true_timestamp_s, true_Doppler_Hz, trk_timestamp_s, trk_Doppler_Hz); - code_phase_error_chips = check_results_codephase(true_timestamp_s, true_prn_delay_chips, trk_timestamp_s, trk_prn_delay_chips); - acc_carrier_phase_hz = check_results_acc_carrier_phase(true_timestamp_s, true_acc_carrier_phase_cycles, trk_timestamp_s, trk_acc_carrier_phase_cycles); - //save tracking measurement timestamps to std::vector - std::vector vector_trk_timestamp_s(trk_timestamp_s.colptr(0), trk_timestamp_s.colptr(0) + trk_timestamp_s.n_rows); - trk_timestamp_s_sweep.push_back(vector_trk_timestamp_s); + arma::vec true_timestamp_s = arma::zeros(n_true_epochs, 1); + arma::vec true_acc_carrier_phase_cycles = arma::zeros(n_true_epochs, 1); + arma::vec true_Doppler_Hz = arma::zeros(n_true_epochs, 1); + arma::vec true_prn_delay_chips = arma::zeros(n_true_epochs, 1); + arma::vec true_tow_s = arma::zeros(n_true_epochs, 1); - doppler_error_sweep.push_back(doppler_error_hz); - code_phase_error_sweep.push_back(code_phase_error_chips); - acc_carrier_phase_error_sweep.push_back(acc_carrier_phase_hz); + long int epoch_counter = 0; + while (true_obs_data.read_binary_obs()) + { + true_timestamp_s(epoch_counter) = true_obs_data.signal_timestamp_s; + true_acc_carrier_phase_cycles(epoch_counter) = true_obs_data.acc_carrier_phase_cycles; + true_Doppler_Hz(epoch_counter) = true_obs_data.doppler_l1_hz; + true_prn_delay_chips(epoch_counter) = true_obs_data.prn_delay_chips; + true_tow_s(epoch_counter) = true_obs_data.tow; + epoch_counter++; + } + // Align initial measurements and cut the tracking pull-in transitory + double pull_in_offset_s = 1.0; + + arma::uvec initial_meas_point = arma::find(trk_timestamp_s >= (true_timestamp_s(0) + pull_in_offset_s), 1, "first"); + + trk_timestamp_s = trk_timestamp_s.subvec(initial_meas_point(0), trk_timestamp_s.size() - 1); + trk_acc_carrier_phase_cycles = trk_acc_carrier_phase_cycles.subvec(initial_meas_point(0), trk_acc_carrier_phase_cycles.size() - 1); + trk_Doppler_Hz = trk_Doppler_Hz.subvec(initial_meas_point(0), trk_Doppler_Hz.size() - 1); + trk_prn_delay_chips = trk_prn_delay_chips.subvec(initial_meas_point(0), trk_prn_delay_chips.size() - 1); + + + double mean_error; + double std_dev_error; + + doppler_error_hz = check_results_doppler(true_timestamp_s, true_Doppler_Hz, trk_timestamp_s, trk_Doppler_Hz, mean_error, std_dev_error); + mean_doppler_error.push_back(mean_error); + std_dev_doppler_error.push_back(std_dev_error); + + code_phase_error_chips = check_results_codephase(true_timestamp_s, true_prn_delay_chips, trk_timestamp_s, trk_prn_delay_chips, mean_error, std_dev_error); + mean_code_phase_error.push_back(mean_error); + std_dev_code_phase_error.push_back(std_dev_error); + + acc_carrier_phase_hz = check_results_acc_carrier_phase(true_timestamp_s, true_acc_carrier_phase_cycles, trk_timestamp_s, trk_acc_carrier_phase_cycles, mean_error, std_dev_error); + mean_carrier_phase_error.push_back(mean_error); + std_dev_carrier_phase_error.push_back(std_dev_error); + + //save tracking measurement timestamps to std::vector + std::vector vector_trk_timestamp_s(trk_timestamp_s.colptr(0), trk_timestamp_s.colptr(0) + trk_timestamp_s.n_rows); + trk_valid_timestamp_s_sweep.push_back(vector_trk_timestamp_s); + + doppler_error_sweep.push_back(doppler_error_hz); + code_phase_error_sweep.push_back(code_phase_error_chips); + acc_carrier_phase_error_sweep.push_back(acc_carrier_phase_hz); + } + catch (const std::exception& ex) + { + std::cout << "Tracking output could not be used, possible loss of lock " << ex.what() << std::endl; + + std::vector vector_trk_timestamp_s; + trk_valid_timestamp_s_sweep.push_back(vector_trk_timestamp_s); + doppler_error_sweep.push_back(doppler_error_hz); + code_phase_error_sweep.push_back(code_phase_error_chips); + acc_carrier_phase_error_sweep.push_back(acc_carrier_phase_hz); + } + } + + } //CN0 LOOP + + if (!FLAGS_enable_external_signal_file) + { + mean_doppler_error_sweep.push_back(mean_doppler_error); + std_dev_doppler_error_sweep.push_back(std_dev_doppler_error); + mean_code_phase_error_sweep.push_back(mean_code_phase_error); + std_dev_code_phase_error_sweep.push_back(std_dev_code_phase_error); + mean_carrier_phase_error_sweep.push_back(mean_carrier_phase_error); + std_dev_carrier_phase_error_sweep.push_back(std_dev_carrier_phase_error); } - } //CN0 LOOP + std::cout << "A\n\n\n"; + //******************************** + //***** STEP 7: Plot results ***** + //******************************** + if (FLAGS_plot_gps_l1_tracking_test == true) + { + const std::string gnuplot_executable(FLAGS_gnuplot_executable); + if (gnuplot_executable.empty()) + { + std::cout << "WARNING: Although the flag plot_gps_l1_tracking_test has been set to TRUE," << std::endl; + std::cout << "gnuplot has not been found in your system." << std::endl; + std::cout << "Test results will not be plotted." << std::endl; + } + else + { + try + { + boost::filesystem::path p(gnuplot_executable); + boost::filesystem::path dir = p.parent_path(); + std::string gnuplot_path = dir.native(); + Gnuplot::set_GNUPlotPath(gnuplot_path); + unsigned int decimate = static_cast(FLAGS_plot_decimate); + + if (FLAGS_plot_extra) + { + for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + Gnuplot g1("linespoints"); + g1.showonscreen(); // window output + g1.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz, " + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz" + "GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + g1.set_grid(); + g1.set_xlabel("Time [s]"); + g1.set_ylabel("Correlators' output"); + //g1.cmd("set key box opaque"); + g1.plot_xy(trk_timestamp_s_sweep.at(current_cn0_idx), prompt_sweep.at(current_cn0_idx), "Prompt", decimate); + g1.plot_xy(trk_timestamp_s_sweep.at(current_cn0_idx), early_sweep.at(current_cn0_idx), "Early", decimate); + g1.plot_xy(trk_timestamp_s_sweep.at(current_cn0_idx), late_sweep.at(current_cn0_idx), "Late", decimate); + g1.set_legend(); + g1.savetops("Correlators_outputs" + std::to_string(generator_CN0_values.at(current_cn0_idx))); + g1.savetopdf("Correlators_outputs" + std::to_string(generator_CN0_values.at(current_cn0_idx)), 18); + } + Gnuplot g2("points"); + g2.showonscreen(); // window output + g2.set_multiplot(ceil(static_cast(generator_CN0_values.size()) / 2.0), + ceil(static_cast(generator_CN0_values.size()) / 2)); + for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + g2.reset_plot(); + g2.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz Constellation " + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz" + "GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + g2.set_grid(); + g2.set_xlabel("Inphase"); + g2.set_ylabel("Quadrature"); + //g2.cmd("set size ratio -1"); + g2.plot_xy(promptI_sweep.at(current_cn0_idx), promptQ_sweep.at(current_cn0_idx)); + } + g2.unset_multiplot(); + g2.savetops("Constellation"); + g2.savetopdf("Constellation", 18); + + Gnuplot g3("linespoints"); + g3.set_title("GPS L1 C/A tracking CN0 output (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + g3.set_grid(); + g3.set_xlabel("Time [s]"); + g3.set_ylabel("Reported CN0 [dB-Hz]"); + g3.cmd("set key box opaque"); + for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + g3.plot_xy(trk_timestamp_s_sweep.at(current_cn0_idx), CN0_dBHz_sweep.at(current_cn0_idx), + std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz]", decimate); + } + g3.set_legend(); + g3.savetops("CN0_output"); + g3.savetopdf("CN0_output", 18); + g3.showonscreen(); // window output + } + + std::cout << "B\n\n\n"; + //PLOT ERROR FIGURES (only if it is used the signal generator) + if (!FLAGS_enable_external_signal_file) + { + Gnuplot g4("points"); + g4.showonscreen(); // window output + g4.set_multiplot(ceil(static_cast(generator_CN0_values.size()) / 2.0), + ceil(static_cast(generator_CN0_values.size()) / 2)); + for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + g4.reset_plot(); + g4.set_title(std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz] Doppler error " + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + g4.set_grid(); + //g4.cmd("set key box opaque"); + g4.set_xlabel("Time [s]"); + g4.set_ylabel("Dopper error [Hz]"); + g4.plot_xy(trk_valid_timestamp_s_sweep.at(current_cn0_idx), doppler_error_sweep.at(current_cn0_idx), + std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz]", decimate); + //g4.set_legend(); + } + g4.unset_multiplot(); + g4.savetops("Doppler_error_output"); + g4.savetopdf("Doppler_error_output", 18); + + Gnuplot g5("points"); + g5.set_title("Code delay error, PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + g5.set_grid(); + g5.set_xlabel("Time [s]"); + g5.set_ylabel("Code delay error [Chips]"); + g5.cmd("set key box opaque"); + + for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + g5.plot_xy(trk_valid_timestamp_s_sweep.at(current_cn0_idx), code_phase_error_sweep.at(current_cn0_idx), + std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz]", decimate); + } + g5.set_legend(); + g5.savetops("Code_error_output"); + g5.savetopdf("Code_error_output", 18); + g5.showonscreen(); // window output + + Gnuplot g6("points"); + g6.set_title("Accumulated carrier phase error, PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + g6.set_grid(); + g6.set_xlabel("Time [s]"); + g6.set_ylabel("Accumulated carrier phase error [Cycles]"); + g6.cmd("set key box opaque"); + + for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + g6.plot_xy(trk_valid_timestamp_s_sweep.at(current_cn0_idx), acc_carrier_phase_error_sweep.at(current_cn0_idx), + std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz]", decimate); + } + g6.set_legend(); + g6.savetops("Carrier_phase_error_output"); + g6.savetopdf("Carrier_phase_error_output", 18); + g6.showonscreen(); // window output + } + } + catch (const GnuplotException& ge) + { + std::cout << ge.what() << std::endl; + } + } + } + } + - //******************************** - //***** STEP 7: Plot results ***** - //******************************** if (FLAGS_plot_gps_l1_tracking_test == true) { const std::string gnuplot_executable(FLAGS_gnuplot_executable); @@ -632,110 +931,67 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults) { try { - boost::filesystem::path p(gnuplot_executable); - boost::filesystem::path dir = p.parent_path(); - std::string gnuplot_path = dir.native(); - Gnuplot::set_GNUPlotPath(gnuplot_path); - std::vector timevec; - unsigned int decimate = static_cast(FLAGS_plot_decimate); - for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + if (generator_CN0_values.size() > 1) { - timevec.clear(); - //todo: timevector MUST BE READED from the trk output file - double t = 0.0; - for (auto it = prompt_sweep.at(current_cn0_idx).begin(); it != prompt_sweep.at(current_cn0_idx).end(); it++) + //plot metrics + + Gnuplot g7("linespoints"); + g7.set_title("Doppler error metrics (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + g7.set_grid(); + g7.set_xlabel("CN0 [dB-Hz]"); + g7.set_ylabel("Doppler error [Hz]"); + g7.set_pointsize(2); + g7.cmd("set termoption lw 2"); + g7.cmd("set key box opaque"); + for (int config_sweep_idx = 0; config_sweep_idx < mean_doppler_error_sweep.size(); config_sweep_idx++) { - timevec.push_back(t); - t = t + GPS_L1_CA_CODE_PERIOD; + g7.plot_xy_err(generator_CN0_values, + mean_doppler_error_sweep.at(config_sweep_idx), + std_dev_doppler_error_sweep.at(config_sweep_idx), + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) + + +"," + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)) + " Hz"); } - Gnuplot g1("linespoints"); - g1.set_title("[" + std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz ] GPS L1 C/A signal tracking correlators' output (satellite PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); - g1.set_grid(); - g1.set_xlabel("Time [s]"); - g1.set_ylabel("Correlators' output"); - g1.cmd("set key box opaque"); - g1.plot_xy(timevec, prompt_sweep.at(current_cn0_idx), "Prompt", decimate); - g1.plot_xy(timevec, early_sweep.at(current_cn0_idx), "Early", decimate); - g1.plot_xy(timevec, late_sweep.at(current_cn0_idx), "Late", decimate); - g1.savetops("Correlators_outputs"); - g1.savetopdf("Correlators_outputs", 18); - g1.showonscreen(); // window output - Gnuplot g2("points"); - g2.set_title("[" + std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz ] Constellation diagram (satellite PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); - g2.set_grid(); - g2.set_xlabel("Inphase"); - g2.set_ylabel("Quadrature"); - g2.cmd("set size ratio -1"); - g2.plot_xy(promptI_sweep.at(current_cn0_idx), promptQ_sweep.at(current_cn0_idx)); - g2.savetops("Constellation"); - g2.savetopdf("Constellation", 18); - g2.showonscreen(); // window output - } - Gnuplot g3("linespoints"); - g3.set_title("GPS L1 C/A tracking CN0 output (satellite PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); - g3.set_grid(); - g3.set_xlabel("Time [s]"); - g3.set_ylabel("Reported CN0 [dB-Hz]"); - g3.cmd("set key box opaque"); - for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) - { - g3.plot_xy(timevec, CN0_dBHz_sweep.at(current_cn0_idx), - std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz]", decimate); - } - g3.set_legend(); - g3.savetops("CN0_output"); - g3.savetopdf("CN0_output", 18); - g3.showonscreen(); // window output + g7.savetops("Doppler_error_metrics"); + g7.savetopdf("Doppler_error_metrics", 18); - Gnuplot g4("points"); - g4.set_title("Doppler error (satellite PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); - g4.set_grid(); - g4.set_xlabel("Time [s]"); - g4.set_ylabel("Dopper error [Hz]"); - g4.cmd("set key box opaque"); - for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) - { - g4.plot_xy(trk_timestamp_s_sweep.at(current_cn0_idx), doppler_error_sweep.at(current_cn0_idx), - std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz]", decimate); + Gnuplot g8("linespoints"); + g8.set_title("Accumulated carrier phase error metrics (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + g8.set_grid(); + g8.set_xlabel("CN0 [dB-Hz]"); + g8.set_ylabel("Accumulated Carrier Phase error [Cycles]"); + g8.cmd("set key box opaque"); + g8.cmd("set termoption lw 2"); + g8.set_pointsize(2); + for (int config_sweep_idx = 0; config_sweep_idx < mean_doppler_error_sweep.size(); config_sweep_idx++) + { + g8.plot_xy_err(generator_CN0_values, + mean_carrier_phase_error_sweep.at(config_sweep_idx), + std_dev_carrier_phase_error_sweep.at(config_sweep_idx), + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) + + +"," + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)) + " Hz"); + } + g8.savetops("Carrier_error_metrics"); + g8.savetopdf("Carrier_error_metrics", 18); + + Gnuplot g9("linespoints"); + g9.set_title("Code Phase error metrics (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + g9.set_grid(); + g9.set_xlabel("CN0 [dB-Hz]"); + g9.set_ylabel("Code Phase error [Chips]"); + g9.cmd("set key box opaque"); + g9.cmd("set termoption lw 2"); + g9.set_pointsize(2); + for (int config_sweep_idx = 0; config_sweep_idx < mean_doppler_error_sweep.size(); config_sweep_idx++) + { + g9.plot_xy_err(generator_CN0_values, + mean_code_phase_error_sweep.at(config_sweep_idx), + std_dev_code_phase_error_sweep.at(config_sweep_idx), + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) + + +"," + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)) + " Hz"); + } + g9.savetops("Code_error_metrics"); + g9.savetopdf("Code_error_metrics", 18); } - g4.set_legend(); - g4.savetops("Doppler_error_output"); - g4.savetopdf("Doppler_error_output", 18); - g4.showonscreen(); // window output - - Gnuplot g5("points"); - g5.set_title("Code delay error (satellite PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); - g5.set_grid(); - g5.set_xlabel("Time [s]"); - g5.set_ylabel("Code delay error [Chips]"); - g5.cmd("set key box opaque"); - - for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) - { - g5.plot_xy(trk_timestamp_s_sweep.at(current_cn0_idx), code_phase_error_sweep.at(current_cn0_idx), - std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz]", decimate); - } - g5.set_legend(); - g5.savetops("Code_error_output"); - g5.savetopdf("Code_error_output", 18); - g5.showonscreen(); // window output - - Gnuplot g6("points"); - g6.set_title("Accumulated carrier phase error (satellite PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); - g6.set_grid(); - g6.set_xlabel("Time [s]"); - g6.set_ylabel("Accumulated carrier phase error [Cycles]"); - g6.cmd("set key box opaque"); - - for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) - { - g6.plot_xy(trk_timestamp_s_sweep.at(current_cn0_idx), acc_carrier_phase_error_sweep.at(current_cn0_idx), - std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz]", decimate); - } - g6.set_legend(); - g6.savetops("Carrier_phase_error_output"); - g6.savetopdf("Carrier_phase_error_output", 18); - g6.showonscreen(); // window output } catch (const GnuplotException& ge) { From eadabaf900a006d8d4fd2ce070e9bd768ae1eca6 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 21 Jun 2018 12:21:35 +0200 Subject: [PATCH 05/16] Add more info in acquisition dumps --- .../gnuradio_blocks/pcps_acquisition.cc | 45 ++++++++++++++++--- .../gnuradio_blocks/pcps_acquisition.h | 1 + .../gps_l1_ca_pcps_acquisition_test.cc | 2 +- .../libs/acquisition_dump_reader.cc | 14 +++++- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc index 7f81d68e3..f16855790 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc @@ -60,6 +60,7 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu acq_parameters = conf_; d_sample_counter = 0; // SAMPLE COUNTER d_active = false; + d_positive_acq = 0; d_state = 0; d_old_freq = 0; d_well_count = 0; @@ -376,6 +377,36 @@ void pcps_acquisition::dump_results(int effective_fft_size) Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE Mat_VarFree(matvar); + matvar = Mat_VarCreate("d_positive_acq", MAT_C_INT32, MAT_T_INT32, 1, dims, &d_positive_acq, 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); + + float aux = static_cast(d_gnss_synchro->Acq_doppler_hz); + matvar = Mat_VarCreate("acq_doppler_hz", MAT_C_SINGLE, MAT_T_SINGLE, 1, dims, &aux, 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); + + aux = static_cast(d_gnss_synchro->Acq_delay_samples); + matvar = Mat_VarCreate("acq_delay_samples", MAT_C_SINGLE, MAT_T_SINGLE, 1, dims, &aux, 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); + + matvar = Mat_VarCreate("test_statistic", MAT_C_SINGLE, MAT_T_SINGLE, 1, dims, &d_test_statistics, 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); + + matvar = Mat_VarCreate("threshold", MAT_C_SINGLE, MAT_T_SINGLE, 1, dims, &d_threshold, 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); + + matvar = Mat_VarCreate("input_power", MAT_C_SINGLE, MAT_T_SINGLE, 1, dims, &d_input_power, 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); + + matvar = Mat_VarCreate("sample_counter", MAT_C_UINT64, MAT_T_UINT64, 1, dims, &d_sample_counter, 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); + Mat_Close(matfp); } } @@ -554,11 +585,6 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) } } } - // Record results to file if required - if (acq_parameters.dump) - { - pcps_acquisition::dump_results(effective_fft_size); - } lk.lock(); if (!acq_parameters.bit_transition_flag) { @@ -572,6 +598,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) send_positive_acquisition(); d_step_two = false; d_state = 0; // Positive acquisition + d_positive_acq = 1; } else { @@ -583,6 +610,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) { send_positive_acquisition(); d_state = 0; // Positive acquisition + d_positive_acq = 1; } } else if (d_well_count == acq_parameters.max_dwells) @@ -605,6 +633,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) send_positive_acquisition(); d_step_two = false; d_state = 0; // Positive acquisition + d_positive_acq = 1; } else { @@ -616,6 +645,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) { send_positive_acquisition(); d_state = 0; // Positive acquisition + d_positive_acq = 1; } } else @@ -626,6 +656,11 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) } } d_worker_active = false; + // Record results to file if required + if (acq_parameters.dump) + { + pcps_acquisition::dump_results(effective_fft_size); + } } diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h index f0fd69e7f..d34888fd8 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h @@ -100,6 +100,7 @@ private: bool d_worker_active; bool d_cshort; bool d_step_two; + int d_positive_acq; float d_threshold; float d_mag; float d_input_power; diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc index 05b374e06..d2c5a96c9 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc @@ -175,7 +175,7 @@ void GpsL1CaPcpsAcquisitionTest::plot_grid() unsigned int sat = static_cast(gnss_synchro.PRN); unsigned int samples_per_code = static_cast(round(4000000 / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS))); // !! - acquisition_dump_reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code); + acquisition_dump_reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code, 1); if (!acq_dump.read_binary_acq()) std::cout << "Error reading files" << std::endl; diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.cc b/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.cc index 5fcd1308b..6302f2e63 100644 --- a/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.cc +++ b/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.cc @@ -73,17 +73,27 @@ bool acquisition_dump_reader::read_binary_acq() Mat_Close(matfile); return false; } + matvar_t* var2_ = Mat_VarRead(matfile, "doppler_max"); + d_doppler_max = *static_cast(var2_->data); + Mat_VarFree(var2_); + + var2_ = Mat_VarRead(matfile, "doppler_step"); + d_doppler_step = *static_cast(var2_->data); + Mat_VarFree(var2_); + + var2_ = Mat_VarRead(matfile, "input_power"); + float normalization_factor = *static_cast(var2_->data); + Mat_VarFree(var2_); std::vector >::iterator it1; std::vector::iterator it2; float* aux = static_cast(var_->data); int k = 0; - float normalization_factor = std::pow(d_samples_per_code, 2); for (it1 = mag.begin(); it1 != mag.end(); it1++) { for (it2 = it1->begin(); it2 != it1->end(); it2++) { - *it2 = static_cast(std::sqrt(aux[k])) / normalization_factor; + *it2 = static_cast(aux[k]) / normalization_factor; k++; } } From 73a944aaf4735c0cb7141a66cf038a252fb61f1c Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 21 Jun 2018 19:26:46 +0200 Subject: [PATCH 06/16] Read results --- .../gps_l1_acq_performance_test.cc | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index c0d2e8133..a013f3b73 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -483,6 +483,7 @@ int AcquisitionPerformanceTest::run_receiver2() TEST_F(AcquisitionPerformanceTest, PdvsCn0) { + init(); for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) { // Set parameter to sweep @@ -503,6 +504,37 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) run_receiver2(); // Read and store reference data and results + std::string basename = std::string("./acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + gnss_synchro.System + "_1C"; + std::cout << basename << std::endl; + //count executions + FILE* fp; + std::string argum2 = std::string("/bin/ls ") + basename + "* | wc -l"; + char buffer[1024]; + fp = popen(&argum2[0], "r"); + int num_executions = 1; + if (fp == NULL) + { + std::cout << "Failed to run command: " << argum2 << std::endl; + //return -1; + } + while (fgets(buffer, sizeof(buffer), fp) != NULL) + { + std::string aux = std::string(buffer); + EXPECT_EQ(aux.empty(), false); + num_executions = std::stoi(aux); + } + pclose(fp); + + for (int ch = 0; ch < config->property("Channels_1C.count", 0); ch++) + { + for (int execution = 1; execution <= num_executions; execution++) + { + acquisition_dump_reader acq_dump(basename, 1, config->property("Acquisition_1C.doppler_max", 0), config->property("Acquisition_1C.doppler_step", 0), config->property("GNSS-SDR.internal_fs_sps", 0) * 0.001, ch, execution); + acq_dump.read_binary_acq(); + std::cout << "Doppler: " << acq_dump.acq_doppler_hz << std::endl; + std::cout << "Execution: " << execution << std::endl; + } + } } } From 4e6bd76f279c0260046367bf62f5a4068a7b043b Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 22 Jun 2018 12:24:39 +0200 Subject: [PATCH 07/16] Add work on performance test --- .../gps_l1_acq_performance_test.cc | 128 ++++++++++++++++-- 1 file changed, 114 insertions(+), 14 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index a013f3b73..5beafd726 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -31,6 +31,8 @@ #include "test_flags.h" #include "signal_generator_flags.h" +#include "tracking_true_obs_reader.h" +#include "true_observables_reader.h" #include #include #include @@ -130,6 +132,7 @@ protected: boost::shared_ptr acquisition; std::shared_ptr config; std::shared_ptr config_f; + const double baseband_sampling_freq = static_cast(FLAGS_fs_gen_sps); private: std::string generator_binary; @@ -140,7 +143,6 @@ private: std::string p5; std::string p6; - const double baseband_sampling_freq = static_cast(FLAGS_fs_gen_sps); std::string filename_rinex_obs = FLAGS_filename_rinex_obs; std::string filename_raw_data = FLAGS_filename_raw_data; @@ -281,7 +283,8 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter // Set the Signal Conditioner config->set_property("SignalConditioner.implementation", "Signal_Conditioner"); config->set_property("DataTypeAdapter.implementation", "Ibyte_To_Complex"); - config->set_property("InputFilter.implementation", "Fir_Filter"); + //config->set_property("InputFilter.implementation", "Fir_Filter"); + config->set_property("InputFilter.implementation", "Pass_Through"); config->set_property("InputFilter.dump", "false"); config->set_property("InputFilter.input_item_type", "gr_complex"); config->set_property("InputFilter.output_item_type", "gr_complex"); @@ -312,6 +315,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Channels_1C.count", std::to_string(number_of_channels)); config->set_property("Channels.in_acquisition", std::to_string(in_acquisition)); config->set_property("Channel.signal", "1C"); + config->set_property("Channel0.satellite", "1"); // Set Acquisition config->set_property("Acquisition_1C.implementation", implementation); @@ -319,7 +323,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Acquisition_1C.doppler_max", std::to_string(doppler_max)); config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step)); - config->set_property("Acquisition_1C.threshold", "0.00001"); + config->set_property("Acquisition_1C.threshold", "15.0"); //config->set_property("Acquisition_1C.pfa", "0.0"); config->set_property("Acquisition_1C.use_CFAR_algorithm", "false"); @@ -443,8 +447,7 @@ int AcquisitionPerformanceTest::run_receiver() elapsed_seconds = end - start; std::cout << "Acq_delay_samples: " << gnss_synchro.Acq_delay_samples << std::endl; std::cout << "Acq_doppler_hz: " << gnss_synchro.Acq_doppler_hz << std::endl; - std::cout << "Acq_samplestamp_samples: " << gnss_synchro.Acq_samplestamp_samples << std::endl - << std::endl; + std::cout << "Acq_samplestamp_samples: " << gnss_synchro.Acq_samplestamp_samples << std::endl; } //std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; @@ -484,6 +487,8 @@ int AcquisitionPerformanceTest::run_receiver2() TEST_F(AcquisitionPerformanceTest, PdvsCn0) { init(); + tracking_true_obs_reader true_trk_data; + //true_observables_reader true_obs_data; for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) { // Set parameter to sweep @@ -491,6 +496,8 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) // Do N_iterations of the experiment for (unsigned iter = 0; iter < N_iterations; iter++) { + std::string basename = std::string("./acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + gnss_synchro.System + "_1C"; + // Configure the signal generator configure_generator(*it); @@ -500,18 +507,23 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) // Configure the receiver configure_receiver(*it, iter); + // remove old files + FILE* fp2; + std::string remove_old_files = std::string("/bin/rm ") + basename + "*.mat"; + fp2 = popen(&remove_old_files[0], "r"); + pclose(fp2); + // Run it run_receiver2(); // Read and store reference data and results - std::string basename = std::string("./acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + gnss_synchro.System + "_1C"; std::cout << basename << std::endl; - //count executions + // count executions FILE* fp; std::string argum2 = std::string("/bin/ls ") + basename + "* | wc -l"; char buffer[1024]; fp = popen(&argum2[0], "r"); - int num_executions = 1; + int num_executions = 0; if (fp == NULL) { std::cout << "Failed to run command: " << argum2 << std::endl; @@ -527,20 +539,108 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) for (int ch = 0; ch < config->property("Channels_1C.count", 0); ch++) { + 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); + std::cout << "Num executions: " + << num_executions << std::endl; for (int execution = 1; execution <= num_executions; execution++) { - acquisition_dump_reader acq_dump(basename, 1, config->property("Acquisition_1C.doppler_max", 0), config->property("Acquisition_1C.doppler_step", 0), config->property("GNSS-SDR.internal_fs_sps", 0) * 0.001, ch, execution); + acquisition_dump_reader acq_dump(basename, 1, 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, ch, execution); acq_dump.read_binary_acq(); - std::cout << "Doppler: " << acq_dump.acq_doppler_hz << std::endl; - std::cout << "Execution: " << execution << std::endl; + //std::cout << "Doppler: " << acq_dump.acq_doppler_hz << std::endl; + //std::cout << "Execution: " << execution << std::endl; + //std::cout << "Sample counter [s]: " << acq_dump.sample_counter / baseband_sampling_freq << std::endl; + if (acq_dump.positive_acq) + { + //std::cout << "Meas acq_delay_samples: " << acq_dump.acq_delay_samples << " chips: " << acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS) << std::endl; + meas_timestamp_s(execution - 1) = acq_dump.sample_counter / baseband_sampling_freq; + meas_doppler(execution - 1) = acq_dump.acq_doppler_hz; + meas_acq_delay_chips(execution - 1) = acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS); + positive_acq(execution - 1) = acq_dump.positive_acq; + } + else + { + //std::cout << "Failed acquisition." << std::endl; + meas_timestamp_s(execution - 1) = arma::datum::inf; + meas_doppler(execution - 1) = arma::datum::inf; + meas_acq_delay_chips(execution - 1) = arma::datum::inf; + positive_acq(execution - 1) = acq_dump.positive_acq; + } } + + std::string true_trk_file = std::string("./gps_l1_ca_obs_prn"); + true_trk_file.append(std::to_string(1)); + true_trk_file.append(".dat"); + true_trk_data.close_obs_file(); + true_trk_data.open_obs_file(true_trk_file); + + + // load the true values + long int n_true_epochs = true_trk_data.num_epochs(); + + arma::vec true_timestamp_s = arma::zeros(n_true_epochs, 1); + arma::vec true_acc_carrier_phase_cycles = arma::zeros(n_true_epochs, 1); + arma::vec true_Doppler_Hz = arma::zeros(n_true_epochs, 1); + arma::vec true_prn_delay_chips = arma::zeros(n_true_epochs, 1); + arma::vec true_tow_s = arma::zeros(n_true_epochs, 1); + + long int epoch_counter = 0; + while (true_trk_data.read_binary_obs()) + { + true_timestamp_s(epoch_counter) = true_trk_data.signal_timestamp_s; + true_acc_carrier_phase_cycles(epoch_counter) = true_trk_data.acc_carrier_phase_cycles; + true_Doppler_Hz(epoch_counter) = true_trk_data.doppler_l1_hz; + true_prn_delay_chips(epoch_counter) = GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips; + true_tow_s(epoch_counter) = true_trk_data.tow; + epoch_counter++; + //std::cout << "True PRN_Delay chips = " << GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips << " at " << true_trk_data.signal_timestamp_s << std::endl; + } + + arma::vec true_interpolated_doppler = arma::zeros(num_executions, 1); + arma::vec true_interpolated_prn_delay_chips = arma::zeros(num_executions, 1); + interp1(true_timestamp_s, true_Doppler_Hz, meas_timestamp_s, true_interpolated_doppler); + interp1(true_timestamp_s, true_prn_delay_chips, meas_timestamp_s, true_interpolated_prn_delay_chips); + + arma::vec doppler_estimation_error = true_interpolated_doppler - meas_doppler; + std::cout << "Doppler estimation error [Hz]: "; + for (int i = 0; i < num_executions - 1; i++) + { + std::cout << doppler_estimation_error(i) << " "; + } + std::cout << std::endl; + arma::vec delay_estimation_error = true_interpolated_prn_delay_chips - meas_acq_delay_chips; + std::cout << "Delay estimation error [chips]: "; + for (int i = 0; i < num_executions - 1; i++) + { + std::cout << delay_estimation_error(i) << " "; + } + std::cout << std::endl; + + double detected = arma::accu(positive_acq); + std::cout << "Probability of detection for channel=" << ch << ", CN0=" << *it << " dBHz" + << ": " << (num_executions > 0 ? (detected / num_executions) : 0.0) << std::endl; + + arma::vec correct_acq = arma::zeros(num_executions, 1); + double correctly_detected = 0.0; + for (int i = 0; i < num_executions - 1; i++) + + { + if (abs(delay_estimation_error(i)) < 0.5) + { + correctly_detected = correctly_detected + 1.0; + } + } + std::cout << "Probability of correct detection for channel=" << ch << ", CN0=" << *it << " dBHz" + << ": " << (num_executions > 0 ? (correctly_detected / num_executions) : 0.0) << std::endl; + true_trk_data.restart(); } } + + // Compute results } - - // Compute results } - //TEST_F(AcquisitionPerformanceTest, ValidationOfResults) //{ // std::chrono::time_point start, end; From 54fd4c83f2a5c4045cd2c7bf59ca3a86055aa98a Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sun, 24 Jun 2018 10:53:12 +0200 Subject: [PATCH 08/16] Add work in acquisition performance test --- .../gps_l1_acq_performance_test.cc | 369 ++++++++++++------ 1 file changed, 242 insertions(+), 127 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index 5beafd726..209779d57 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -38,20 +38,24 @@ #include DEFINE_string(config_file_ptest, std::string(""), "File containing the configuration parameters for the position test."); +DEFINE_double(acq_test_threshold, 0.001, "Acquisition threshold"); +DEFINE_int32(acq_test_coherent_time_ms, 10, "Acquisition coherent time, in ms"); +DEFINE_int32(acq_test_PRN, 1, "PRN number"); // ######## GNURADIO BLOCK MESSAGE RECEVER ######### class AcqPerfTest_msg_rx; // typedef boost::shared_ptr AcqPerfTest_msg_rx_sptr; // -AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); +AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(concurrent_queue& queue); // class AcqPerfTest_msg_rx : public gr::block { private: - friend AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(); + friend AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(concurrent_queue& queue); void msg_handler_events(pmt::pmt_t msg); - AcqPerfTest_msg_rx(); + AcqPerfTest_msg_rx(concurrent_queue& queue); + concurrent_queue& channel_internal_queue; public: int rx_message; @@ -59,9 +63,9 @@ public: }; -AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make() +AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(concurrent_queue& queue) { - return AcqPerfTest_msg_rx_sptr(new AcqPerfTest_msg_rx()); + return AcqPerfTest_msg_rx_sptr(new AcqPerfTest_msg_rx(queue)); } @@ -71,17 +75,18 @@ void AcqPerfTest_msg_rx::msg_handler_events(pmt::pmt_t msg) { long int message = pmt::to_long(msg); rx_message = message; + channel_internal_queue.push(rx_message); } catch (boost::bad_any_cast& e) { LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; rx_message = 0; } - std::cout << "Received message:" << rx_message << std::endl; + //std::cout << "Received message:" << rx_message << std::endl; } -AcqPerfTest_msg_rx::AcqPerfTest_msg_rx() : gr::block("AcqPerfTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) +AcqPerfTest_msg_rx::AcqPerfTest_msg_rx(concurrent_queue& queue) : gr::block("AcqPerfTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)), channel_internal_queue(queue) { this->message_port_register_in(pmt::mp("events")); this->set_msg_handler(pmt::mp("events"), boost::bind(&AcqPerfTest_msg_rx::msg_handler_events, this, _1)); @@ -105,7 +110,10 @@ protected: item_size = sizeof(gr_complex); gnss_synchro = Gnss_Synchro(); doppler_max = 5000; - doppler_step = 100; + doppler_step = 125; + stop = false; + acquisition = 0; + init(); } ~AcquisitionPerformanceTest() @@ -120,19 +128,46 @@ protected: int configure_generator(double cn0); int generate_signal(); int configure_receiver(double cn0, unsigned int iter); + void start_queue(); + void wait_message(); + void process_message(); + void stop_queue(); int run_receiver(); int run_receiver2(); void check_results(); + + concurrent_queue channel_internal_queue; + + gr::msg_queue::sptr queue; gr::top_block_sptr top_block; + std::shared_ptr acquisition; + std::shared_ptr config; + std::shared_ptr config_f; Gnss_Synchro gnss_synchro; size_t item_size; unsigned int doppler_max; unsigned int doppler_step; + bool stop; + + int message; + boost::thread ch_thread; + std::string implementation = "GPS_L1_CA_PCPS_Acquisition"; - boost::shared_ptr acquisition; - std::shared_ptr config; - std::shared_ptr config_f; + const double baseband_sampling_freq = static_cast(FLAGS_fs_gen_sps); + const int coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; + const int number_of_channels = 2; + const int in_acquisition = 1; + const float threshold = FLAGS_acq_test_threshold; + const int max_dwells = 1; + const int tong_init_val = 2; + const int tong_max_val = 10; + const int tong_max_dwells = 30; + + int generated_signal_duration_s = 2; + + unsigned int num_of_realizations = (generated_signal_duration_s * 1000) / FLAGS_acq_test_coherent_time_ms; + unsigned int realization_counter; private: std::string generator_binary; @@ -147,10 +182,6 @@ private: std::string filename_rinex_obs = FLAGS_filename_rinex_obs; std::string filename_raw_data = FLAGS_filename_raw_data; - /*void print_results(const std::vector& east, - const std::vector& north, - const std::vector& up);*/ - double compute_stdev_precision(const std::vector& vec); double compute_stdev_accuracy(const std::vector& vec, double ref); @@ -166,6 +197,85 @@ void AcquisitionPerformanceTest::init() std::string signal = "1C"; signal.copy(gnss_synchro.Signal, 2, 0); gnss_synchro.PRN = 1; + message = 0; + realization_counter = 0; +} + + +void AcquisitionPerformanceTest::start_queue() +{ + stop = false; + ch_thread = boost::thread(&AcquisitionPerformanceTest::wait_message, this); +} + + +void AcquisitionPerformanceTest::wait_message() +{ + //std::chrono::time_point start, end; + //std::chrono::duration elapsed_seconds(0); + + while (!stop) + { + acquisition->reset(); + acquisition->set_state(1); + + //start = std::chrono::system_clock::now(); + + channel_internal_queue.wait_and_pop(message); + + //end = std::chrono::system_clock::now(); + //elapsed_seconds = end - start; + + //mean_acq_time_us += elapsed_seconds.count() * 1e6; + + process_message(); + } +} + + +void AcquisitionPerformanceTest::process_message() +{ + if (message == 1) + { + //detection_counter++; + + // The term -5 is here to correct the additional delay introduced by the FIR filter + //double delay_error_chips = std::abs(static_cast(expected_delay_chips) - static_cast(gnss_synchro.Acq_delay_samples - 5) * 1023.0 / (static_cast(fs_in) * 1e-3)); + //double doppler_error_hz = std::abs(expected_doppler_hz - gnss_synchro.Acq_doppler_hz); + + // mse_delay += std::pow(delay_error_chips, 2); + // mse_doppler += std::pow(doppler_error_hz, 2); + + // if ((delay_error_chips < max_delay_error_chips) && (doppler_error_hz < max_doppler_error_hz)) + // { + // correct_estimation_counter++; + // } + } + + realization_counter++; + + std::cout << "Progress: " << round(static_cast(realization_counter) / static_cast(num_of_realizations) * 100.0) << "% \r" << std::flush; + + if (realization_counter == num_of_realizations) + { + // mse_delay /= num_of_realizations; + // mse_doppler /= num_of_realizations; + + //Pd = static_cast(correct_estimation_counter) / static_cast(num_of_realizations); + //Pfa_a = static_cast(detection_counter) / static_cast(num_of_realizations); + //Pfa_p = static_cast(detection_counter - correct_estimation_counter) / static_cast(num_of_realizations); + + // mean_acq_time_us /= num_of_realizations; + + stop_queue(); + top_block->stop(); + } +} + + +void AcquisitionPerformanceTest::stop_queue() +{ + stop = true; } @@ -173,12 +283,11 @@ int AcquisitionPerformanceTest::configure_generator(double cn0) { // Configure signal generator generator_binary = FLAGS_generator_binary; - int duration_s = 2; p1 = std::string("-rinex_nav_file=") + FLAGS_rinex_nav_file; if (FLAGS_dynamic_position.empty()) { - p2 = std::string("-static_position=") + FLAGS_static_position + std::string(",") + std::to_string(std::min(duration_s * 10, 3000)); + p2 = std::string("-static_position=") + FLAGS_static_position + std::string(",") + std::to_string(std::min(generated_signal_duration_s * 10, 3000)); } else { @@ -237,17 +346,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter const int grid_density = 16; const float zero = 0.0; - const int number_of_channels = 1; - const int in_acquisition = 1; - const float threshold = 0.01; - const float doppler_max = 8000.0; - const float doppler_step = 500.0; - const int max_dwells = 1; - const int tong_init_val = 2; - const int tong_max_val = 10; - const int tong_max_dwells = 30; - const int coherent_integration_time_ms = 1; const float pll_bw_hz = 30.0; const float dll_bw_hz = 4.0; @@ -315,7 +414,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Channels_1C.count", std::to_string(number_of_channels)); config->set_property("Channels.in_acquisition", std::to_string(in_acquisition)); config->set_property("Channel.signal", "1C"); - config->set_property("Channel0.satellite", "1"); + //config->set_property("Channel0.satellite", std::to_string(FLAGS_acq_test_PRN)); // Set Acquisition config->set_property("Acquisition_1C.implementation", implementation); @@ -323,11 +422,11 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Acquisition_1C.doppler_max", std::to_string(doppler_max)); config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step)); - config->set_property("Acquisition_1C.threshold", "15.0"); + config->set_property("Acquisition_1C.threshold", std::to_string(threshold)); //config->set_property("Acquisition_1C.pfa", "0.0"); - config->set_property("Acquisition_1C.use_CFAR_algorithm", "false"); + config->set_property("Acquisition_1C.use_CFAR_algorithm", "true"); - config->set_property("Acquisition_1C.coherent_integration_time_ms", "1"); + config->set_property("Acquisition_1C.coherent_integration_time_ms", std::to_string(coherent_integration_time_ms)); config->set_property("Acquisition_1C.use_bit_transition_flag", "false"); config->set_property("Acquisition_1C.max_dwells", std::to_string(1)); @@ -408,47 +507,56 @@ int AcquisitionPerformanceTest::run_receiver() { std::chrono::time_point start, end; std::chrono::duration elapsed_seconds(0); - std::string file = "./" + filename_raw_data; //+ std::to_string(current_cn0_idx); + std::string file = "./" + filename_raw_data; const char* file_name = file.c_str(); gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false); + std::cout << "Source created" << std::endl; - for (unsigned k = 0; k < 2; k++) - { - gr::top_block_sptr top_block_ = gr::make_top_block("Acquisition test"); - boost::shared_ptr msg_rx = AcqPerfTest_msg_rx_make(); + gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make(); + std::cout << "Interleaver created" << std::endl; - gnss_synchro = Gnss_Synchro(); - init(); - auto acquisition_ = boost::make_shared(config.get(), "Acquisition_1C", 1, 0); + top_block = gr::make_top_block("Acquisition test"); + boost::shared_ptr msg_rx = AcqPerfTest_msg_rx_make(channel_internal_queue); - //acquisition->connect(top_block); - acquisition_->set_gnss_synchro(&gnss_synchro); + queue = gr::msg_queue::make(0); + gnss_synchro = Gnss_Synchro(); + init(); + acquisition = std::make_shared(config.get(), "Acquisition_1C", 1, 0); + int nsamples = floor(config->property("GNSS-SDR.internal_fs_sps", 2000000) * generated_signal_duration_s); + boost::shared_ptr valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue); - acquisition_->connect(top_block_); - acquisition_->set_local_code(); - acquisition_->set_state(1); // Ensure that acquisition starts at the first sample - acquisition_->init(); - //file_source->seek(static_cast(100 * k), SEEK_SET); - - if (not file_source->seek(static_cast(100 * k), SEEK_SET)) - { - std::cout << "Error skipping " << k << std::endl; - } - gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make(); - 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_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); + acquisition->set_gnss_synchro(&gnss_synchro); + acquisition->set_channel(0); + acquisition->set_local_code(); + 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_state(1); // Ensure that acquisition starts at the first sample + acquisition->connect(top_block); + top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); - start = std::chrono::system_clock::now(); - top_block_->run(); // Start threads and wait - end = std::chrono::system_clock::now(); - //file_source->close(); - elapsed_seconds = end - start; - std::cout << "Acq_delay_samples: " << gnss_synchro.Acq_delay_samples << std::endl; - std::cout << "Acq_doppler_hz: " << gnss_synchro.Acq_doppler_hz << std::endl; - std::cout << "Acq_samplestamp_samples: " << gnss_synchro.Acq_samplestamp_samples << std::endl; - } + acquisition->init(); + + top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0); + top_block->connect(gr_interleaved_char_to_complex, 0, valve, 0); + top_block->connect(valve, 0, acquisition->get_left_block(), 0); + std::cout << "Num of realizations: " << num_of_realizations << std::endl; + start_queue(); + start = std::chrono::system_clock::now(); + top_block->run(); // Start threads and wait + end = std::chrono::system_clock::now(); + //file_source->close(); + elapsed_seconds = end - start; + std::cout << "Acq_delay_samples: " << gnss_synchro.Acq_delay_samples << std::endl; + std::cout << "Acq_doppler_hz: " << gnss_synchro.Acq_doppler_hz << std::endl; + std::cout << "Acq_samplestamp_samples: " << gnss_synchro.Acq_samplestamp_samples << std::endl; +#ifdef OLD_BOOST + ch_thread.timed_join(boost::posix_time::seconds(1)); +#endif +#ifndef OLD_BOOST + ch_thread.try_join_until(boost::chrono::steady_clock::now() + boost::chrono::milliseconds(50)); +#endif //std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; @@ -488,7 +596,6 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) { init(); tracking_true_obs_reader true_trk_data; - //true_observables_reader true_obs_data; for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) { // Set parameter to sweep @@ -508,13 +615,13 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) configure_receiver(*it, iter); // remove old files - FILE* fp2; - std::string remove_old_files = std::string("/bin/rm ") + basename + "*.mat"; - fp2 = popen(&remove_old_files[0], "r"); - pclose(fp2); + // FILE* fp2; + // std::string remove_old_files = std::string("/bin/rm ") + basename + "*.mat"; + // fp2 = popen(&remove_old_files[0], "r"); + // pclose(fp2); // Run it - run_receiver2(); + run_receiver(); // Read and store reference data and results std::cout << basename << std::endl; @@ -523,7 +630,7 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) std::string argum2 = std::string("/bin/ls ") + basename + "* | wc -l"; char buffer[1024]; fp = popen(&argum2[0], "r"); - int num_executions = 0; + int num_executions = 1; if (fp == NULL) { std::cout << "Failed to run command: " << argum2 << std::endl; @@ -536,68 +643,68 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) num_executions = std::stoi(aux); } pclose(fp); + int ch = 0; - for (int ch = 0; ch < config->property("Channels_1C.count", 0); ch++) + 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); + + std::cout << "Num executions: " << std::endl; + for (int execution = 1; execution <= num_executions; execution++) { - 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); - std::cout << "Num executions: " - << num_executions << std::endl; - for (int execution = 1; execution <= num_executions; execution++) + acquisition_dump_reader acq_dump(basename, FLAGS_acq_test_PRN, 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(coh_time_ms), ch, execution); + if (!acq_dump.read_binary_acq()) + ; + if (acq_dump.positive_acq) { - acquisition_dump_reader acq_dump(basename, 1, 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, ch, execution); - acq_dump.read_binary_acq(); - //std::cout << "Doppler: " << acq_dump.acq_doppler_hz << std::endl; - //std::cout << "Execution: " << execution << std::endl; - //std::cout << "Sample counter [s]: " << acq_dump.sample_counter / baseband_sampling_freq << std::endl; - if (acq_dump.positive_acq) - { - //std::cout << "Meas acq_delay_samples: " << acq_dump.acq_delay_samples << " chips: " << acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS) << std::endl; - meas_timestamp_s(execution - 1) = acq_dump.sample_counter / baseband_sampling_freq; - meas_doppler(execution - 1) = acq_dump.acq_doppler_hz; - meas_acq_delay_chips(execution - 1) = acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS); - positive_acq(execution - 1) = acq_dump.positive_acq; - } - else - { - //std::cout << "Failed acquisition." << std::endl; - meas_timestamp_s(execution - 1) = arma::datum::inf; - meas_doppler(execution - 1) = arma::datum::inf; - meas_acq_delay_chips(execution - 1) = arma::datum::inf; - positive_acq(execution - 1) = acq_dump.positive_acq; - } + //std::cout << "Meas acq_delay_samples: " << acq_dump.acq_delay_samples << " chips: " << acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS) << std::endl; + meas_timestamp_s(execution - 1) = acq_dump.sample_counter / baseband_sampling_freq; + meas_doppler(execution - 1) = acq_dump.acq_doppler_hz; + meas_acq_delay_chips(execution - 1) = acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS); + positive_acq(execution - 1) = acq_dump.positive_acq; } - - std::string true_trk_file = std::string("./gps_l1_ca_obs_prn"); - true_trk_file.append(std::to_string(1)); - true_trk_file.append(".dat"); - true_trk_data.close_obs_file(); - true_trk_data.open_obs_file(true_trk_file); - - - // load the true values - long int n_true_epochs = true_trk_data.num_epochs(); - - arma::vec true_timestamp_s = arma::zeros(n_true_epochs, 1); - arma::vec true_acc_carrier_phase_cycles = arma::zeros(n_true_epochs, 1); - arma::vec true_Doppler_Hz = arma::zeros(n_true_epochs, 1); - arma::vec true_prn_delay_chips = arma::zeros(n_true_epochs, 1); - arma::vec true_tow_s = arma::zeros(n_true_epochs, 1); - - long int epoch_counter = 0; - while (true_trk_data.read_binary_obs()) + else { - true_timestamp_s(epoch_counter) = true_trk_data.signal_timestamp_s; - true_acc_carrier_phase_cycles(epoch_counter) = true_trk_data.acc_carrier_phase_cycles; - true_Doppler_Hz(epoch_counter) = true_trk_data.doppler_l1_hz; - true_prn_delay_chips(epoch_counter) = GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips; - true_tow_s(epoch_counter) = true_trk_data.tow; - epoch_counter++; - //std::cout << "True PRN_Delay chips = " << GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips << " at " << true_trk_data.signal_timestamp_s << std::endl; + //std::cout << "Failed acquisition." << std::endl; + meas_timestamp_s(execution - 1) = arma::datum::inf; + meas_doppler(execution - 1) = arma::datum::inf; + meas_acq_delay_chips(execution - 1) = arma::datum::inf; + positive_acq(execution - 1) = acq_dump.positive_acq; } + } + std::string true_trk_file = std::string("./gps_l1_ca_obs_prn"); + true_trk_file.append(std::to_string(FLAGS_acq_test_PRN)); + true_trk_file.append(".dat"); + true_trk_data.close_obs_file(); + true_trk_data.open_obs_file(true_trk_file); + + + // load the true values + long int n_true_epochs = true_trk_data.num_epochs(); + + arma::vec true_timestamp_s = arma::zeros(n_true_epochs, 1); + arma::vec true_acc_carrier_phase_cycles = arma::zeros(n_true_epochs, 1); + arma::vec true_Doppler_Hz = arma::zeros(n_true_epochs, 1); + arma::vec true_prn_delay_chips = arma::zeros(n_true_epochs, 1); + arma::vec true_tow_s = arma::zeros(n_true_epochs, 1); + + long int epoch_counter = 0; + while (true_trk_data.read_binary_obs()) + { + true_timestamp_s(epoch_counter) = true_trk_data.signal_timestamp_s; + true_acc_carrier_phase_cycles(epoch_counter) = true_trk_data.acc_carrier_phase_cycles; + true_Doppler_Hz(epoch_counter) = true_trk_data.doppler_l1_hz; + true_prn_delay_chips(epoch_counter) = GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips; + true_tow_s(epoch_counter) = true_trk_data.tow; + epoch_counter++; + //std::cout << "True PRN_Delay chips = " << GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips << " at " << true_trk_data.signal_timestamp_s << std::endl; + } + if (epoch_counter > 2) + { arma::vec true_interpolated_doppler = arma::zeros(num_executions, 1); arma::vec true_interpolated_prn_delay_chips = arma::zeros(num_executions, 1); interp1(true_timestamp_s, true_Doppler_Hz, meas_timestamp_s, true_interpolated_doppler); @@ -634,8 +741,16 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) } std::cout << "Probability of correct detection for channel=" << ch << ", CN0=" << *it << " dBHz" << ": " << (num_executions > 0 ? (correctly_detected / num_executions) : 0.0) << std::endl; - true_trk_data.restart(); } + else + { + std::cout << "No reference data has been found. Maybe a non-present satellite?" << std::endl; + + double wrongly_detected = arma::accu(positive_acq); + std::cout << "Probability of false alarm for channel=" << ch << ", CN0=" << *it << " dBHz" + << ": " << (num_executions > 0 ? (wrongly_detected / num_executions) : 0.0) << std::endl; + } + true_trk_data.restart(); } // Compute results From e7bc582e5f39e03f7d59efaf034da10b8f4c1a10 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Mon, 25 Jun 2018 00:56:11 +0200 Subject: [PATCH 09/16] Add work on acqusition performance test --- .../gps_l1_acq_performance_test.cc | 478 ++++++++---------- 1 file changed, 201 insertions(+), 277 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index 209779d57..529514c88 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -33,22 +33,27 @@ #include "signal_generator_flags.h" #include "tracking_true_obs_reader.h" #include "true_observables_reader.h" +#include "display.h" #include #include #include DEFINE_string(config_file_ptest, std::string(""), "File containing the configuration parameters for the position test."); DEFINE_double(acq_test_threshold, 0.001, "Acquisition threshold"); +DEFINE_double(acq_test_pfa, -1.0, "Set threshold via probability of false alarm"); DEFINE_int32(acq_test_coherent_time_ms, 10, "Acquisition coherent time, in ms"); DEFINE_int32(acq_test_PRN, 1, "PRN number"); +DEFINE_int32(acq_test_fake_PRN, 33, "Fake PRN number"); +DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration"); +DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag"); // ######## GNURADIO BLOCK MESSAGE RECEVER ######### class AcqPerfTest_msg_rx; -// + typedef boost::shared_ptr AcqPerfTest_msg_rx_sptr; -// + AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(concurrent_queue& queue); -// + class AcqPerfTest_msg_rx : public gr::block { private: @@ -59,7 +64,7 @@ private: public: int rx_message; - ~AcqPerfTest_msg_rx(); //!< Default destructor + ~AcqPerfTest_msg_rx(); }; @@ -82,7 +87,6 @@ void AcqPerfTest_msg_rx::msg_handler_events(pmt::pmt_t msg) LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; rx_message = 0; } - //std::cout << "Received message:" << rx_message << std::endl; } @@ -134,6 +138,7 @@ protected: void stop_queue(); int run_receiver(); int run_receiver2(); + int count_executions(const std::string& basename, unsigned int sat); void check_results(); concurrent_queue channel_internal_queue; @@ -160,15 +165,15 @@ protected: const int in_acquisition = 1; const float threshold = FLAGS_acq_test_threshold; const int max_dwells = 1; - const int tong_init_val = 2; - const int tong_max_val = 10; - const int tong_max_dwells = 30; + const int dump_channel = 0; - int generated_signal_duration_s = 2; + int generated_signal_duration_s = FLAGS_acq_test_signal_duration_s; unsigned int num_of_realizations = (generated_signal_duration_s * 1000) / FLAGS_acq_test_coherent_time_ms; unsigned int realization_counter; + unsigned int observed_satellite = FLAGS_acq_test_PRN; + private: std::string generator_binary; std::string p1; @@ -196,7 +201,7 @@ void AcquisitionPerformanceTest::init() gnss_synchro.System = 'G'; std::string signal = "1C"; signal.copy(gnss_synchro.Signal, 2, 0); - gnss_synchro.PRN = 1; + gnss_synchro.PRN = observed_satellite; message = 0; realization_counter = 0; } @@ -211,23 +216,13 @@ void AcquisitionPerformanceTest::start_queue() void AcquisitionPerformanceTest::wait_message() { - //std::chrono::time_point start, end; - //std::chrono::duration elapsed_seconds(0); - while (!stop) { acquisition->reset(); acquisition->set_state(1); - //start = std::chrono::system_clock::now(); - channel_internal_queue.wait_and_pop(message); - //end = std::chrono::system_clock::now(); - //elapsed_seconds = end - start; - - //mean_acq_time_us += elapsed_seconds.count() * 1e6; - process_message(); } } @@ -235,38 +230,12 @@ void AcquisitionPerformanceTest::wait_message() void AcquisitionPerformanceTest::process_message() { - if (message == 1) - { - //detection_counter++; - - // The term -5 is here to correct the additional delay introduced by the FIR filter - //double delay_error_chips = std::abs(static_cast(expected_delay_chips) - static_cast(gnss_synchro.Acq_delay_samples - 5) * 1023.0 / (static_cast(fs_in) * 1e-3)); - //double doppler_error_hz = std::abs(expected_doppler_hz - gnss_synchro.Acq_doppler_hz); - - // mse_delay += std::pow(delay_error_chips, 2); - // mse_doppler += std::pow(doppler_error_hz, 2); - - // if ((delay_error_chips < max_delay_error_chips) && (doppler_error_hz < max_doppler_error_hz)) - // { - // correct_estimation_counter++; - // } - } - realization_counter++; - - std::cout << "Progress: " << round(static_cast(realization_counter) / static_cast(num_of_realizations) * 100.0) << "% \r" << std::flush; + acquisition->reset(); + acquisition->set_state(1); if (realization_counter == num_of_realizations) { - // mse_delay /= num_of_realizations; - // mse_doppler /= num_of_realizations; - - //Pd = static_cast(correct_estimation_counter) / static_cast(num_of_realizations); - //Pfa_a = static_cast(detection_counter) / static_cast(num_of_realizations); - //Pfa_p = static_cast(detection_counter - correct_estimation_counter) / static_cast(num_of_realizations); - - // mean_acq_time_us /= num_of_realizations; - stop_queue(); top_block->stop(); } @@ -414,7 +383,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Channels_1C.count", std::to_string(number_of_channels)); config->set_property("Channels.in_acquisition", std::to_string(in_acquisition)); config->set_property("Channel.signal", "1C"); - //config->set_property("Channel0.satellite", std::to_string(FLAGS_acq_test_PRN)); + //config->set_property("Channel1.satellite", std::to_string(FLAGS_acq_test_PRN)); // Set Acquisition config->set_property("Acquisition_1C.implementation", implementation); @@ -423,11 +392,19 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step)); config->set_property("Acquisition_1C.threshold", std::to_string(threshold)); - //config->set_property("Acquisition_1C.pfa", "0.0"); + if (FLAGS_acq_test_pfa > 0.0) config->set_property("Acquisition_1C.pfa", std::to_string(FLAGS_acq_test_pfa)); + config->set_property("Acquisition_1C.use_CFAR_algorithm", "true"); config->set_property("Acquisition_1C.coherent_integration_time_ms", std::to_string(coherent_integration_time_ms)); - config->set_property("Acquisition_1C.use_bit_transition_flag", "false"); + if (FLAGS_acq_test_bit_transition_flag) + { + config->set_property("Acquisition_1C.bit_transition_flag", "true"); + } + else + { + config->set_property("Acquisition_1C.bit_transition_flag", "false"); + } config->set_property("Acquisition_1C.max_dwells", std::to_string(1)); @@ -437,16 +414,11 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter 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)); - //if (FLAGS_plot_acq_grid == true) - // { + config->set_property("Acquisition_1C.dump", "true"); - // } - //else - // { - // config->set_property("Acquisition_1C.dump", "false"); - // } std::string dump_file = std::string("./acquisition_") + std::to_string(cn0) + "_" + std::to_string(iter); config->set_property("Acquisition_1C.dump_filename", dump_file); + config->set_property("Acquisition_1C.dump_channel", std::to_string(dump_channel)); // Set Tracking config->set_property("Tracking_1C.implementation", "GPS_L1_CA_DLL_PLL_Tracking"); @@ -510,10 +482,8 @@ int AcquisitionPerformanceTest::run_receiver() std::string file = "./" + filename_raw_data; const char* file_name = file.c_str(); gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false); - std::cout << "Source created" << std::endl; gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make(); - std::cout << "Interleaver created" << std::endl; top_block = gr::make_top_block("Acquisition test"); boost::shared_ptr msg_rx = AcqPerfTest_msg_rx_make(channel_internal_queue); @@ -521,10 +491,11 @@ int AcquisitionPerformanceTest::run_receiver() queue = gr::msg_queue::make(0); gnss_synchro = Gnss_Synchro(); init(); - acquisition = std::make_shared(config.get(), "Acquisition_1C", 1, 0); + int nsamples = floor(config->property("GNSS-SDR.internal_fs_sps", 2000000) * generated_signal_duration_s); boost::shared_ptr valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue); + acquisition = std::make_shared(config.get(), "Acquisition_1C", 1, 0); acquisition->set_gnss_synchro(&gnss_synchro); acquisition->set_channel(0); acquisition->set_local_code(); @@ -535,22 +506,19 @@ int AcquisitionPerformanceTest::run_receiver() acquisition->connect(top_block); top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); - acquisition->init(); top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0); top_block->connect(gr_interleaved_char_to_complex, 0, valve, 0); top_block->connect(valve, 0, acquisition->get_left_block(), 0); - std::cout << "Num of realizations: " << num_of_realizations << std::endl; + start_queue(); + start = std::chrono::system_clock::now(); top_block->run(); // Start threads and wait end = std::chrono::system_clock::now(); - //file_source->close(); elapsed_seconds = end - start; - std::cout << "Acq_delay_samples: " << gnss_synchro.Acq_delay_samples << std::endl; - std::cout << "Acq_doppler_hz: " << gnss_synchro.Acq_doppler_hz << std::endl; - std::cout << "Acq_samplestamp_samples: " << gnss_synchro.Acq_samplestamp_samples << std::endl; + #ifdef OLD_BOOST ch_thread.timed_join(boost::posix_time::seconds(1)); #endif @@ -563,6 +531,7 @@ int AcquisitionPerformanceTest::run_receiver() return 0; } + int AcquisitionPerformanceTest::run_receiver2() { std::shared_ptr control_thread; @@ -592,14 +561,34 @@ int AcquisitionPerformanceTest::run_receiver2() } +int AcquisitionPerformanceTest::count_executions(const std::string& basename, unsigned int sat) +{ + FILE* fp; + std::string argum2 = std::string("/bin/ls ") + basename + "* | grep sat_" + std::to_string(sat) + " | wc -l"; + char buffer[1024]; + fp = popen(&argum2[0], "r"); + int num_executions = 1; + if (fp == NULL) + { + std::cout << "Failed to run command: " << argum2 << std::endl; + return 0; + } + while (fgets(buffer, sizeof(buffer), fp) != NULL) + { + std::string aux = std::string(buffer); + EXPECT_EQ(aux.empty(), false); + num_executions = std::stoi(aux); + } + pclose(fp); + return num_executions; +} + + TEST_F(AcquisitionPerformanceTest, PdvsCn0) { - init(); tracking_true_obs_reader true_trk_data; for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) { - // Set parameter to sweep - // Do N_iterations of the experiment for (unsigned iter = 0; iter < N_iterations; iter++) { @@ -611,232 +600,167 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) // Generate signal raw signal samples and observations RINEX file generate_signal(); - // Configure the receiver - configure_receiver(*it, iter); - - // remove old files - // FILE* fp2; - // std::string remove_old_files = std::string("/bin/rm ") + basename + "*.mat"; - // fp2 = popen(&remove_old_files[0], "r"); - // pclose(fp2); - - // Run it - run_receiver(); - - // Read and store reference data and results - std::cout << basename << std::endl; - // count executions - FILE* fp; - std::string argum2 = std::string("/bin/ls ") + basename + "* | wc -l"; - char buffer[1024]; - fp = popen(&argum2[0], "r"); - int num_executions = 1; - if (fp == NULL) + std::cout << "Execution for CN0 = " << *it << " dB-Hz" << std::endl; + for (unsigned k = 0; k < 2; k++) { - std::cout << "Failed to run command: " << argum2 << std::endl; - //return -1; - } - while (fgets(buffer, sizeof(buffer), fp) != NULL) - { - std::string aux = std::string(buffer); - EXPECT_EQ(aux.empty(), false); - num_executions = std::stoi(aux); - } - pclose(fp); - int ch = 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); - - std::cout << "Num executions: " << std::endl; - for (int execution = 1; execution <= num_executions; execution++) - { - acquisition_dump_reader acq_dump(basename, FLAGS_acq_test_PRN, 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(coh_time_ms), ch, execution); - if (!acq_dump.read_binary_acq()) - ; - if (acq_dump.positive_acq) + if (k == 0) { - //std::cout << "Meas acq_delay_samples: " << acq_dump.acq_delay_samples << " chips: " << acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS) << std::endl; - meas_timestamp_s(execution - 1) = acq_dump.sample_counter / baseband_sampling_freq; - meas_doppler(execution - 1) = acq_dump.acq_doppler_hz; - meas_acq_delay_chips(execution - 1) = acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS); - positive_acq(execution - 1) = acq_dump.positive_acq; + observed_satellite = FLAGS_acq_test_PRN; } else { - //std::cout << "Failed acquisition." << std::endl; - meas_timestamp_s(execution - 1) = arma::datum::inf; - meas_doppler(execution - 1) = arma::datum::inf; - meas_acq_delay_chips(execution - 1) = arma::datum::inf; - positive_acq(execution - 1) = acq_dump.positive_acq; + observed_satellite = FLAGS_acq_test_fake_PRN; } - } + init(); - std::string true_trk_file = std::string("./gps_l1_ca_obs_prn"); - true_trk_file.append(std::to_string(FLAGS_acq_test_PRN)); - true_trk_file.append(".dat"); - true_trk_data.close_obs_file(); - true_trk_data.open_obs_file(true_trk_file); + // Configure the receiver + configure_receiver(*it, iter); + // Run it + run_receiver(); - // load the true values - long int n_true_epochs = true_trk_data.num_epochs(); + // count executions + int num_executions = count_executions(basename, observed_satellite); - arma::vec true_timestamp_s = arma::zeros(n_true_epochs, 1); - arma::vec true_acc_carrier_phase_cycles = arma::zeros(n_true_epochs, 1); - arma::vec true_Doppler_Hz = arma::zeros(n_true_epochs, 1); - arma::vec true_prn_delay_chips = arma::zeros(n_true_epochs, 1); - arma::vec true_tow_s = arma::zeros(n_true_epochs, 1); + // Read measured data + int ch = config->property("Acquisition_1C.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); - long int epoch_counter = 0; - while (true_trk_data.read_binary_obs()) - { - true_timestamp_s(epoch_counter) = true_trk_data.signal_timestamp_s; - true_acc_carrier_phase_cycles(epoch_counter) = true_trk_data.acc_carrier_phase_cycles; - true_Doppler_Hz(epoch_counter) = true_trk_data.doppler_l1_hz; - true_prn_delay_chips(epoch_counter) = GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips; - true_tow_s(epoch_counter) = true_trk_data.tow; - epoch_counter++; - //std::cout << "True PRN_Delay chips = " << GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips << " at " << true_trk_data.signal_timestamp_s << std::endl; - } - if (epoch_counter > 2) - { - arma::vec true_interpolated_doppler = arma::zeros(num_executions, 1); - arma::vec true_interpolated_prn_delay_chips = arma::zeros(num_executions, 1); - interp1(true_timestamp_s, true_Doppler_Hz, meas_timestamp_s, true_interpolated_doppler); - interp1(true_timestamp_s, true_prn_delay_chips, meas_timestamp_s, true_interpolated_prn_delay_chips); + double coh_time_ms = config->property("Acquisition_1C.coherent_integration_time_ms", 1); - arma::vec doppler_estimation_error = true_interpolated_doppler - meas_doppler; - std::cout << "Doppler estimation error [Hz]: "; - for (int i = 0; i < num_executions - 1; i++) + std::cout << "Num executions: " << num_executions << std::endl; + for (int execution = 1; execution <= num_executions; execution++) { - std::cout << doppler_estimation_error(i) << " "; - } - std::cout << std::endl; - arma::vec delay_estimation_error = true_interpolated_prn_delay_chips - meas_acq_delay_chips; - std::cout << "Delay estimation error [chips]: "; - for (int i = 0; i < num_executions - 1; i++) - { - std::cout << delay_estimation_error(i) << " "; - } - std::cout << std::endl; - - double detected = arma::accu(positive_acq); - std::cout << "Probability of detection for channel=" << ch << ", CN0=" << *it << " dBHz" - << ": " << (num_executions > 0 ? (detected / num_executions) : 0.0) << std::endl; - - arma::vec correct_acq = arma::zeros(num_executions, 1); - double correctly_detected = 0.0; - for (int i = 0; i < num_executions - 1; i++) - - { - if (abs(delay_estimation_error(i)) < 0.5) + 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(coh_time_ms), ch, execution); + acq_dump.read_binary_acq(); + if (acq_dump.positive_acq) { - correctly_detected = correctly_detected + 1.0; + //std::cout << "Meas acq_delay_samples: " << acq_dump.acq_delay_samples << " chips: " << acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS) << std::endl; + meas_timestamp_s(execution - 1) = acq_dump.sample_counter / baseband_sampling_freq; + meas_doppler(execution - 1) = acq_dump.acq_doppler_hz; + meas_acq_delay_chips(execution - 1) = acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS); + positive_acq(execution - 1) = acq_dump.positive_acq; + } + else + { + //std::cout << "Failed acquisition." << std::endl; + meas_timestamp_s(execution - 1) = arma::datum::inf; + meas_doppler(execution - 1) = arma::datum::inf; + meas_acq_delay_chips(execution - 1) = arma::datum::inf; + positive_acq(execution - 1) = acq_dump.positive_acq; } } - std::cout << "Probability of correct detection for channel=" << ch << ", CN0=" << *it << " dBHz" - << ": " << (num_executions > 0 ? (correctly_detected / num_executions) : 0.0) << std::endl; - } - else - { - std::cout << "No reference data has been found. Maybe a non-present satellite?" << std::endl; - double wrongly_detected = arma::accu(positive_acq); - std::cout << "Probability of false alarm for channel=" << ch << ", CN0=" << *it << " dBHz" - << ": " << (num_executions > 0 ? (wrongly_detected / num_executions) : 0.0) << std::endl; + // Read reference data + std::string true_trk_file = std::string("./gps_l1_ca_obs_prn"); + true_trk_file.append(std::to_string(observed_satellite)); + true_trk_file.append(".dat"); + true_trk_data.close_obs_file(); + true_trk_data.open_obs_file(true_trk_file); + + // load the true values + long int n_true_epochs = true_trk_data.num_epochs(); + arma::vec true_timestamp_s = arma::zeros(n_true_epochs, 1); + arma::vec true_acc_carrier_phase_cycles = arma::zeros(n_true_epochs, 1); + arma::vec true_Doppler_Hz = arma::zeros(n_true_epochs, 1); + arma::vec true_prn_delay_chips = arma::zeros(n_true_epochs, 1); + arma::vec true_tow_s = arma::zeros(n_true_epochs, 1); + + long int epoch_counter = 0; + int num_clean_executions = 0; + while (true_trk_data.read_binary_obs()) + { + true_timestamp_s(epoch_counter) = true_trk_data.signal_timestamp_s; + true_acc_carrier_phase_cycles(epoch_counter) = true_trk_data.acc_carrier_phase_cycles; + true_Doppler_Hz(epoch_counter) = true_trk_data.doppler_l1_hz; + true_prn_delay_chips(epoch_counter) = GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips; + true_tow_s(epoch_counter) = true_trk_data.tow; + epoch_counter++; + //std::cout << "True PRN_Delay chips = " << GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips << " at " << true_trk_data.signal_timestamp_s << std::endl; + } + + // Process results + arma::vec clean_doppler_estimation_error; + arma::vec clean_delay_estimation_error; + if (epoch_counter > 2) + { + arma::vec true_interpolated_doppler = arma::zeros(num_executions, 1); + arma::vec true_interpolated_prn_delay_chips = arma::zeros(num_executions, 1); + interp1(true_timestamp_s, true_Doppler_Hz, meas_timestamp_s, true_interpolated_doppler); + interp1(true_timestamp_s, true_prn_delay_chips, meas_timestamp_s, true_interpolated_prn_delay_chips); + + arma::vec doppler_estimation_error = true_interpolated_doppler - meas_doppler; + arma::vec delay_estimation_error = true_interpolated_prn_delay_chips - (meas_acq_delay_chips - ((1.0 / baseband_sampling_freq) / GPS_L1_CA_CHIP_PERIOD)); // compensate 1 sample delay + + // Cut measurements without reference + for (unsigned int i = 0; i < num_executions; i++) + { + if (!std::isnan(doppler_estimation_error(i)) and !std::isnan(delay_estimation_error(i))) + { + num_clean_executions++; + } + } + clean_doppler_estimation_error = arma::zeros(num_clean_executions, 1); + clean_delay_estimation_error = arma::zeros(num_clean_executions, 1); + num_clean_executions = 0; + for (unsigned int i = 0; i < num_executions; i++) + { + if (!std::isnan(doppler_estimation_error(i)) and !std::isnan(delay_estimation_error(i))) + { + clean_doppler_estimation_error(num_clean_executions) = doppler_estimation_error(i); + clean_delay_estimation_error(num_clean_executions) = delay_estimation_error(i); + num_clean_executions++; + } + } + + std::cout << "Doppler estimation error [Hz]: "; + for (int i = 0; i < num_executions - 1; i++) + { + std::cout << doppler_estimation_error(i) << " "; + } + std::cout << std::endl; + + std::cout << "Delay estimation error [chips]: "; + for (int i = 0; i < num_executions - 1; i++) + { + std::cout << delay_estimation_error(i) << " "; + } + std::cout << std::endl; + + double detected = arma::accu(positive_acq); + std::cout << TEXT_BOLD_BLACK << "Probability of detection for channel=" << ch << ", CN0=" << *it << " dBHz" + << ": " << (num_executions > 0 ? (detected / num_executions) : 0.0) << TEXT_RESET << std::endl; + } + if (num_clean_executions > 0) + { + arma::vec correct_acq = arma::zeros(num_executions, 1); + double correctly_detected = 0.0; + 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(config->property("Acquisition_1C.doppler_step", 1)) / 2.0) + { + correctly_detected = correctly_detected + 1.0; + } + } + std::cout << TEXT_BOLD_BLACK << "Probability of correct detection for channel=" << ch << ", CN0=" << *it << " dBHz" + << ": " << (num_clean_executions > 0 ? (correctly_detected / num_clean_executions) : 0.0) << TEXT_RESET << std::endl; + } + else + { + std::cout << "No reference data has been found. Maybe a non-present satellite?" << std::endl; + + double wrongly_detected = arma::accu(positive_acq); + std::cout << TEXT_BOLD_BLACK << "Probability of false alarm for channel=" << ch << ", CN0=" << *it << " dBHz" + << ": " << (num_executions > 0 ? (wrongly_detected / num_executions) : 0.0) << TEXT_RESET << std::endl; + } + true_trk_data.restart(); } - true_trk_data.restart(); } - + true_trk_data.close_obs_file(); // Compute results } } -//TEST_F(AcquisitionPerformanceTest, ValidationOfResults) -//{ -// std::chrono::time_point start, end; -// std::chrono::duration elapsed_seconds(0.0); -// top_block = gr::make_top_block("Acquisition test"); -// -// double expected_delay_samples = 524; -// double expected_doppler_hz = 1680; -// -// init(); -// -// if (FLAGS_plot_acq_grid == true) -// { -// std::string data_str = "./tmp-acq-gps1"; -// if (boost::filesystem::exists(data_str)) -// { -// boost::filesystem::remove_all(data_str); -// } -// boost::filesystem::create_directory(data_str); -// } -// -// std::shared_ptr acquisition = std::make_shared(config.get(), "Acquisition_1C", 1, 0); -// boost::shared_ptr msg_rx = AcqPerfTest_msg_rx_make(); -// -// ASSERT_NO_THROW({ -// acquisition->set_channel(1); -// }) << "Failure setting channel."; -// -// ASSERT_NO_THROW({ -// acquisition->set_gnss_synchro(&gnss_synchro); -// }) << "Failure setting gnss_synchro."; -// -// ASSERT_NO_THROW({ -// acquisition->set_threshold(0.001); -// }) << "Failure setting threshold."; -// -// ASSERT_NO_THROW({ -// acquisition->set_doppler_max(doppler_max); -// }) << "Failure setting doppler_max."; -// -// ASSERT_NO_THROW({ -// acquisition->set_doppler_step(doppler_step); -// }) << "Failure setting doppler_step."; -// -// ASSERT_NO_THROW({ -// acquisition->connect(top_block); -// }) << "Failure connecting acquisition to the top_block."; -// -// ASSERT_NO_THROW({ -// std::string path = std::string(TEST_PATH); -// std::string file = path + "signal_samples/GPS_L1_CA_ID_1_Fs_4Msps_2ms.dat"; -// const char* file_name = file.c_str(); -// gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); -// top_block->connect(file_source, 0, acquisition->get_left_block(), 0); -// top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); -// }) << "Failure connecting the blocks of acquisition test."; -// -// acquisition->set_local_code(); -// acquisition->set_state(1); // Ensure that acquisition starts at the first sample -// acquisition->init(); -// -// EXPECT_NO_THROW({ -// start = std::chrono::system_clock::now(); -// top_block->run(); // Start threads and wait -// end = std::chrono::system_clock::now(); -// elapsed_seconds = end - start; -// }) << "Failure running the top_block."; -// -// unsigned long int nsamples = gnss_synchro.Acq_samplestamp_samples; -// std::cout << "Acquired " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; -// ASSERT_EQ(1, msg_rx->rx_message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS."; -// -// double delay_error_samples = std::abs(expected_delay_samples - gnss_synchro.Acq_delay_samples); -// float delay_error_chips = static_cast(delay_error_samples * 1023 / 4000); -// double doppler_error_hz = std::abs(expected_doppler_hz - gnss_synchro.Acq_doppler_hz); -// -// EXPECT_LE(doppler_error_hz, 666) << "Doppler error exceeds the expected value: 666 Hz = 2/(3*integration period)"; -// EXPECT_LT(delay_error_chips, 0.5) << "Delay error exceeds the expected value: 0.5 chips"; -// -// /*if (FLAGS_plot_acq_grid == true) -// { -// plot_grid(); -// }*/ -//} From bc0b267acc4c14c0bc2c08b5b5f4d75b0df127c4 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Tue, 26 Jun 2018 08:43:22 +0200 Subject: [PATCH 10/16] Add work on acq performance test --- .../gps_l1_acq_performance_test.cc | 349 ++++++++++-------- 1 file changed, 204 insertions(+), 145 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index 529514c88..bfb6c3974 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -34,6 +34,9 @@ #include "tracking_true_obs_reader.h" #include "true_observables_reader.h" #include "display.h" +#include // for create_directories, exists +//#include // for path, operator<< +#include // for filesystem #include #include #include @@ -118,20 +121,24 @@ protected: stop = false; acquisition = 0; init(); + Pd.resize(cn0_.size()); + for (int i = 0; i < cn0_.size(); i++) Pd[i].reserve(num_thresholds); + Pfa.resize(cn0_.size()); + for (int i = 0; i < cn0_.size(); i++) Pfa[i].reserve(num_thresholds); } ~AcquisitionPerformanceTest() { } - std::vector cn0_ = {38.0, 40.0, 43.0}; + std::vector cn0_ = {35.0, 38.0, 43.0}; int N_iterations = 1; void init(); //void plot_grid(); int configure_generator(double cn0); int generate_signal(); - int configure_receiver(double cn0, unsigned int iter); + int configure_receiver(double cn0, float pfa, unsigned int iter); void start_queue(); void wait_message(); void process_message(); @@ -173,6 +180,16 @@ protected: unsigned int realization_counter; unsigned int observed_satellite = FLAGS_acq_test_PRN; + std::string path_str = "./acq-perf-test"; + + //std::vector> meas_Pd; + //std::vector> meas_Pd_correct; + //std::vector> meas_Pfa; + + int num_thresholds = 1; + std::vector> Pd; + std::vector> Pfa; + private: std::string generator_binary; @@ -293,7 +310,7 @@ int AcquisitionPerformanceTest::generate_signal() } -int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter) +int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsigned int iter) { if (FLAGS_config_file_ptest.empty()) { @@ -392,7 +409,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step)); config->set_property("Acquisition_1C.threshold", std::to_string(threshold)); - if (FLAGS_acq_test_pfa > 0.0) config->set_property("Acquisition_1C.pfa", std::to_string(FLAGS_acq_test_pfa)); + if (FLAGS_acq_test_pfa > 0.0) config->force_set_property("Acquisition_1C.pfa", std::to_string(pfa)); config->set_property("Acquisition_1C.use_CFAR_algorithm", "true"); @@ -416,7 +433,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter config->set_property("Acquisition_1C.second_doppler_step", std::to_string(125)); config->set_property("Acquisition_1C.dump", "true"); - std::string dump_file = std::string("./acquisition_") + std::to_string(cn0) + "_" + std::to_string(iter); + 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)); @@ -477,8 +494,6 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, unsigned int iter int AcquisitionPerformanceTest::run_receiver() { - std::chrono::time_point start, end; - std::chrono::duration elapsed_seconds(0); std::string file = "./" + filename_raw_data; const char* file_name = file.c_str(); gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false); @@ -514,10 +529,7 @@ int AcquisitionPerformanceTest::run_receiver() start_queue(); - start = std::chrono::system_clock::now(); top_block->run(); // Start threads and wait - end = std::chrono::system_clock::now(); - elapsed_seconds = end - start; #ifdef OLD_BOOST ch_thread.timed_join(boost::posix_time::seconds(1)); @@ -526,8 +538,6 @@ int AcquisitionPerformanceTest::run_receiver() ch_thread.try_join_until(boost::chrono::steady_clock::now() + boost::chrono::milliseconds(50)); #endif - //std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; - return 0; } @@ -587,180 +597,229 @@ int AcquisitionPerformanceTest::count_executions(const std::string& basename, un TEST_F(AcquisitionPerformanceTest, PdvsCn0) { tracking_true_obs_reader true_trk_data; + + if (boost::filesystem::exists(path_str)) + { + boost::filesystem::remove_all(path_str); + } + boost::system::error_code ec; + if (!boost::filesystem::create_directory(path_str, ec)) + { + std::cout << "Could not create the " << path_str << " folder." << std::endl; + // error + } + unsigned int cn0_index = 0; for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) { // Do N_iterations of the experiment + std::vector pfa_local = {0.01}; //{FLAGS_acq_test_pfa}; //{0.001, 0.01, 0.1, 1}; + std::vector meas_Pd_; + std::vector meas_Pd_correct_; + std::vector meas_Pfa_; for (unsigned iter = 0; iter < N_iterations; iter++) { - std::string basename = std::string("./acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + gnss_synchro.System + "_1C"; + // Set parameter to sweep - // Configure the signal generator - configure_generator(*it); - // Generate signal raw signal samples and observations RINEX file - generate_signal(); - - std::cout << "Execution for CN0 = " << *it << " dB-Hz" << std::endl; - for (unsigned k = 0; k < 2; k++) + for (int pfa_iter = 0; pfa_iter < pfa_local.size(); pfa_iter++) { - if (k == 0) + std::string basename = path_str + std::string("/acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + std::to_string(pfa_local[pfa_iter]) + "_" + gnss_synchro.System + "_1C"; + + // Configure the signal generator + configure_generator(*it); + + // Generate signal raw signal samples and observations RINEX file + generate_signal(); + + std::cout << "Execution for CN0 = " << *it << " dB-Hz" << std::endl; + for (unsigned k = 0; k < 2; k++) { - observed_satellite = FLAGS_acq_test_PRN; - } - else - { - observed_satellite = FLAGS_acq_test_fake_PRN; - } - init(); - - // Configure the receiver - configure_receiver(*it, iter); - - // Run it - run_receiver(); - - // count executions - int num_executions = count_executions(basename, observed_satellite); - - // Read measured data - int ch = config->property("Acquisition_1C.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); - - 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(coh_time_ms), ch, execution); - acq_dump.read_binary_acq(); - if (acq_dump.positive_acq) + if (k == 0) { - //std::cout << "Meas acq_delay_samples: " << acq_dump.acq_delay_samples << " chips: " << acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS) << std::endl; - meas_timestamp_s(execution - 1) = acq_dump.sample_counter / baseband_sampling_freq; - meas_doppler(execution - 1) = acq_dump.acq_doppler_hz; - meas_acq_delay_chips(execution - 1) = acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS); - positive_acq(execution - 1) = acq_dump.positive_acq; + observed_satellite = FLAGS_acq_test_PRN; } else { - //std::cout << "Failed acquisition." << std::endl; - meas_timestamp_s(execution - 1) = arma::datum::inf; - meas_doppler(execution - 1) = arma::datum::inf; - meas_acq_delay_chips(execution - 1) = arma::datum::inf; - positive_acq(execution - 1) = acq_dump.positive_acq; + observed_satellite = FLAGS_acq_test_fake_PRN; } - } + init(); - // Read reference data - std::string true_trk_file = std::string("./gps_l1_ca_obs_prn"); - true_trk_file.append(std::to_string(observed_satellite)); - true_trk_file.append(".dat"); - true_trk_data.close_obs_file(); - true_trk_data.open_obs_file(true_trk_file); + // Configure the receiver + configure_receiver(*it, pfa_local[pfa_iter], iter); - // load the true values - long int n_true_epochs = true_trk_data.num_epochs(); - arma::vec true_timestamp_s = arma::zeros(n_true_epochs, 1); - arma::vec true_acc_carrier_phase_cycles = arma::zeros(n_true_epochs, 1); - arma::vec true_Doppler_Hz = arma::zeros(n_true_epochs, 1); - arma::vec true_prn_delay_chips = arma::zeros(n_true_epochs, 1); - arma::vec true_tow_s = arma::zeros(n_true_epochs, 1); + // Run it + run_receiver(); - long int epoch_counter = 0; - int num_clean_executions = 0; - while (true_trk_data.read_binary_obs()) - { - true_timestamp_s(epoch_counter) = true_trk_data.signal_timestamp_s; - true_acc_carrier_phase_cycles(epoch_counter) = true_trk_data.acc_carrier_phase_cycles; - true_Doppler_Hz(epoch_counter) = true_trk_data.doppler_l1_hz; - true_prn_delay_chips(epoch_counter) = GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips; - true_tow_s(epoch_counter) = true_trk_data.tow; - epoch_counter++; - //std::cout << "True PRN_Delay chips = " << GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips << " at " << true_trk_data.signal_timestamp_s << std::endl; - } + // count executions + int num_executions = count_executions(basename, observed_satellite); - // Process results - arma::vec clean_doppler_estimation_error; - arma::vec clean_delay_estimation_error; - if (epoch_counter > 2) - { - arma::vec true_interpolated_doppler = arma::zeros(num_executions, 1); - arma::vec true_interpolated_prn_delay_chips = arma::zeros(num_executions, 1); - interp1(true_timestamp_s, true_Doppler_Hz, meas_timestamp_s, true_interpolated_doppler); - interp1(true_timestamp_s, true_prn_delay_chips, meas_timestamp_s, true_interpolated_prn_delay_chips); + // Read measured data + int ch = config->property("Acquisition_1C.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); - arma::vec doppler_estimation_error = true_interpolated_doppler - meas_doppler; - arma::vec delay_estimation_error = true_interpolated_prn_delay_chips - (meas_acq_delay_chips - ((1.0 / baseband_sampling_freq) / GPS_L1_CA_CHIP_PERIOD)); // compensate 1 sample delay + double coh_time_ms = config->property("Acquisition_1C.coherent_integration_time_ms", 1); - // Cut measurements without reference - for (unsigned int i = 0; i < num_executions; i++) + std::cout << "Num executions: " << num_executions << std::endl; + for (int execution = 1; execution <= num_executions; execution++) { - if (!std::isnan(doppler_estimation_error(i)) and !std::isnan(delay_estimation_error(i))) + 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(coh_time_ms), ch, execution); + acq_dump.read_binary_acq(); + if (acq_dump.positive_acq) { - num_clean_executions++; + //std::cout << "Meas acq_delay_samples: " << acq_dump.acq_delay_samples << " chips: " << acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS) << std::endl; + meas_timestamp_s(execution - 1) = acq_dump.sample_counter / baseband_sampling_freq; + meas_doppler(execution - 1) = acq_dump.acq_doppler_hz; + meas_acq_delay_chips(execution - 1) = acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS); + positive_acq(execution - 1) = acq_dump.positive_acq; } - } - clean_doppler_estimation_error = arma::zeros(num_clean_executions, 1); - clean_delay_estimation_error = arma::zeros(num_clean_executions, 1); - num_clean_executions = 0; - for (unsigned int i = 0; i < num_executions; i++) - { - if (!std::isnan(doppler_estimation_error(i)) and !std::isnan(delay_estimation_error(i))) + else { - clean_doppler_estimation_error(num_clean_executions) = doppler_estimation_error(i); - clean_delay_estimation_error(num_clean_executions) = delay_estimation_error(i); - num_clean_executions++; + //std::cout << "Failed acquisition." << std::endl; + meas_timestamp_s(execution - 1) = arma::datum::inf; + meas_doppler(execution - 1) = arma::datum::inf; + meas_acq_delay_chips(execution - 1) = arma::datum::inf; + positive_acq(execution - 1) = acq_dump.positive_acq; } } - std::cout << "Doppler estimation error [Hz]: "; - for (int i = 0; i < num_executions - 1; i++) + // Read reference data + std::string true_trk_file = std::string("./gps_l1_ca_obs_prn"); + true_trk_file.append(std::to_string(observed_satellite)); + true_trk_file.append(".dat"); + true_trk_data.close_obs_file(); + true_trk_data.open_obs_file(true_trk_file); + + // load the true values + long int n_true_epochs = true_trk_data.num_epochs(); + arma::vec true_timestamp_s = arma::zeros(n_true_epochs, 1); + arma::vec true_acc_carrier_phase_cycles = arma::zeros(n_true_epochs, 1); + arma::vec true_Doppler_Hz = arma::zeros(n_true_epochs, 1); + arma::vec true_prn_delay_chips = arma::zeros(n_true_epochs, 1); + arma::vec true_tow_s = arma::zeros(n_true_epochs, 1); + + long int epoch_counter = 0; + int num_clean_executions = 0; + while (true_trk_data.read_binary_obs()) { - std::cout << doppler_estimation_error(i) << " "; + true_timestamp_s(epoch_counter) = true_trk_data.signal_timestamp_s; + true_acc_carrier_phase_cycles(epoch_counter) = true_trk_data.acc_carrier_phase_cycles; + true_Doppler_Hz(epoch_counter) = true_trk_data.doppler_l1_hz; + true_prn_delay_chips(epoch_counter) = GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips; + true_tow_s(epoch_counter) = true_trk_data.tow; + epoch_counter++; + //std::cout << "True PRN_Delay chips = " << GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips << " at " << true_trk_data.signal_timestamp_s << std::endl; } - std::cout << std::endl; - std::cout << "Delay estimation error [chips]: "; - for (int i = 0; i < num_executions - 1; i++) + // Process results + arma::vec clean_doppler_estimation_error; + arma::vec clean_delay_estimation_error; + std::vector meas_Pd_; + std::vector meas_Pd_correct_; + if (epoch_counter > 2) { - std::cout << delay_estimation_error(i) << " "; - } - std::cout << std::endl; + arma::vec true_interpolated_doppler = arma::zeros(num_executions, 1); + arma::vec true_interpolated_prn_delay_chips = arma::zeros(num_executions, 1); + interp1(true_timestamp_s, true_Doppler_Hz, meas_timestamp_s, true_interpolated_doppler); + interp1(true_timestamp_s, true_prn_delay_chips, meas_timestamp_s, true_interpolated_prn_delay_chips); - double detected = arma::accu(positive_acq); - std::cout << TEXT_BOLD_BLACK << "Probability of detection for channel=" << ch << ", CN0=" << *it << " dBHz" - << ": " << (num_executions > 0 ? (detected / num_executions) : 0.0) << TEXT_RESET << std::endl; - } - if (num_clean_executions > 0) - { - arma::vec correct_acq = arma::zeros(num_executions, 1); - double correctly_detected = 0.0; - for (int i = 0; i < num_clean_executions - 1; i++) + arma::vec doppler_estimation_error = true_interpolated_doppler - meas_doppler; + arma::vec delay_estimation_error = true_interpolated_prn_delay_chips - (meas_acq_delay_chips - ((1.0 / baseband_sampling_freq) / GPS_L1_CA_CHIP_PERIOD)); // compensate 1 sample delay - { - if (abs(clean_delay_estimation_error(i)) < 0.5 and abs(clean_doppler_estimation_error(i)) < static_cast(config->property("Acquisition_1C.doppler_step", 1)) / 2.0) + // Cut measurements without reference + for (unsigned int i = 0; i < num_executions; i++) { - correctly_detected = correctly_detected + 1.0; + if (!std::isnan(doppler_estimation_error(i)) and !std::isnan(delay_estimation_error(i))) + { + num_clean_executions++; + } + } + clean_doppler_estimation_error = arma::zeros(num_clean_executions, 1); + clean_delay_estimation_error = arma::zeros(num_clean_executions, 1); + num_clean_executions = 0; + for (unsigned int i = 0; i < num_executions; i++) + { + if (!std::isnan(doppler_estimation_error(i)) and !std::isnan(delay_estimation_error(i))) + { + clean_doppler_estimation_error(num_clean_executions) = doppler_estimation_error(i); + clean_delay_estimation_error(num_clean_executions) = delay_estimation_error(i); + num_clean_executions++; + } + } + + std::cout << "Doppler estimation error [Hz]: "; + for (int i = 0; i < num_executions - 1; i++) + { + std::cout << doppler_estimation_error(i) << " "; + } + std::cout << std::endl; + + std::cout << "Delay estimation error [chips]: "; + for (int i = 0; i < num_executions - 1; i++) + { + std::cout << delay_estimation_error(i) << " "; + } + std::cout << std::endl; + } + if (k == 0) + { + double detected = arma::accu(positive_acq); + if (num_executions > 0) meas_Pd_.push_back(static_cast(detected / num_executions)); + std::cout << TEXT_BOLD_BLACK << "Probability of detection for channel=" << ch << ", CN0=" << *it << " dBHz" + << ": " << (num_executions > 0 ? (detected / num_executions) : 0.0) << TEXT_RESET << std::endl; + } + if (num_clean_executions > 0) + { + arma::vec correct_acq = arma::zeros(num_executions, 1); + double correctly_detected = 0.0; + 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(config->property("Acquisition_1C.doppler_step", 1)) / 2.0) + { + correctly_detected = correctly_detected + 1.0; + } + } + std::cout << TEXT_BOLD_BLACK << "Probability of correct detection for channel=" << ch << ", CN0=" << *it << " dBHz" + << ": " << (num_clean_executions > 0 ? (correctly_detected / num_clean_executions) : 0.0) << TEXT_RESET << std::endl; + } + else + { + // std::cout << "No reference data has been found. Maybe a non-present satellite?" << std::endl; + if (k == 1) + { + double wrongly_detected = arma::accu(positive_acq); + if (num_executions > 0) meas_Pfa_.push_back(static_cast(wrongly_detected / num_executions)); + std::cout + << TEXT_BOLD_BLACK << "Probability of false alarm for channel=" << ch << ", CN0=" << *it << " dBHz" + << ": " << (num_executions > 0 ? (wrongly_detected / num_executions) : 0.0) << TEXT_RESET << std::endl; } } - std::cout << TEXT_BOLD_BLACK << "Probability of correct detection for channel=" << ch << ", CN0=" << *it << " dBHz" - << ": " << (num_clean_executions > 0 ? (correctly_detected / num_clean_executions) : 0.0) << TEXT_RESET << std::endl; + true_trk_data.restart(); } - else - { - std::cout << "No reference data has been found. Maybe a non-present satellite?" << std::endl; - double wrongly_detected = arma::accu(positive_acq); - std::cout << TEXT_BOLD_BLACK << "Probability of false alarm for channel=" << ch << ", CN0=" << *it << " dBHz" - << ": " << (num_executions > 0 ? (wrongly_detected / num_executions) : 0.0) << TEXT_RESET << std::endl; - } - true_trk_data.restart(); + float sum_ = static_cast(std::accumulate(meas_Pd_.begin(), meas_Pd_.end(), 0.0)); + Pd[cn0_index][pfa_iter] = sum_ / static_cast(meas_Pd_.size()); + sum_ = static_cast(std::accumulate(meas_Pfa_.begin(), meas_Pfa_.end(), 0.0)); + Pfa[cn0_index][pfa_iter] = sum_ / static_cast(meas_Pfa_.size()); + cn0_index++; } } true_trk_data.close_obs_file(); // Compute results } + unsigned int aux_index = 0; + for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) + { + std::cout << "Results for CN0 = " << *it << " dBHz:" << std::endl; + std::cout << "Pd = "; + for (int pfa_iter = 0; pfa_iter < 1; pfa_iter++) + { + std::cout << Pd[aux_index][pfa_iter] << " "; + } + std::cout << std::endl; + aux_index++; + } } From 09ef8dc1f1ba13d597cad55e8bd2d1ed095c9a42 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Wed, 27 Jun 2018 08:07:42 +0200 Subject: [PATCH 11/16] Add work on acq performance test --- .../gps_l1_acq_performance_test.cc | 300 ++++++------------ 1 file changed, 102 insertions(+), 198 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index bfb6c3974..c9459763d 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -49,6 +49,7 @@ DEFINE_int32(acq_test_PRN, 1, "PRN number"); DEFINE_int32(acq_test_fake_PRN, 33, "Fake PRN number"); DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration"); DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag"); +DEFINE_int32(acq_test_iterations, 1, "Number of iterations"); // ######## GNURADIO BLOCK MESSAGE RECEVER ######### class AcqPerfTest_msg_rx; @@ -122,9 +123,11 @@ protected: acquisition = 0; init(); Pd.resize(cn0_.size()); - for (int i = 0; i < cn0_.size(); i++) Pd[i].reserve(num_thresholds); + for (int i = 0; i < static_cast(cn0_.size()); i++) Pd[i].reserve(num_thresholds); Pfa.resize(cn0_.size()); - for (int i = 0; i < cn0_.size(); i++) Pfa[i].reserve(num_thresholds); + for (int i = 0; i < static_cast(cn0_.size()); i++) Pfa[i].reserve(num_thresholds); + Pd_correct.resize(cn0_.size()); + for (int i = 0; i < static_cast(cn0_.size()); i++) Pd_correct[i].reserve(num_thresholds); } ~AcquisitionPerformanceTest() @@ -132,7 +135,8 @@ protected: } std::vector cn0_ = {35.0, 38.0, 43.0}; - int N_iterations = 1; + std::vector pfa_local = {0.01, 0.1}; //{FLAGS_acq_test_pfa}; //{0.001, 0.01, 0.1, 1}; + int N_iterations = FLAGS_acq_test_iterations; void init(); //void plot_grid(); @@ -144,7 +148,6 @@ protected: void process_message(); void stop_queue(); int run_receiver(); - int run_receiver2(); int count_executions(const std::string& basename, unsigned int sat); void check_results(); @@ -182,13 +185,11 @@ protected: unsigned int observed_satellite = FLAGS_acq_test_PRN; std::string path_str = "./acq-perf-test"; - //std::vector> meas_Pd; - //std::vector> meas_Pd_correct; - //std::vector> meas_Pfa; + int num_thresholds = pfa_local.size(); - int num_thresholds = 1; std::vector> Pd; std::vector> Pfa; + std::vector> Pd_correct; private: @@ -317,91 +318,8 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign config = std::make_shared(); const int sampling_rate_internal = baseband_sampling_freq; - const int number_of_taps = 11; - const int number_of_bands = 2; - const float band1_begin = 0.0; - const float band1_end = 0.48; - const float band2_begin = 0.52; - const float band2_end = 1.0; - const float ampl1_begin = 1.0; - const float ampl1_end = 1.0; - const float ampl2_begin = 0.0; - const float ampl2_end = 0.0; - const float band1_error = 1.0; - const float band2_error = 1.0; - const int grid_density = 16; - - const float zero = 0.0; - - - const float pll_bw_hz = 30.0; - const float dll_bw_hz = 4.0; - const float early_late_space_chips = 0.5; - const float pll_bw_narrow_hz = 20.0; - const float dll_bw_narrow_hz = 2.0; - const int extend_correlation_ms = 1; - - const int display_rate_ms = 500; - const int output_rate_ms = 100; - config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(sampling_rate_internal)); - // Set the assistance system parameters - config->set_property("GNSS-SDR.SUPL_read_gps_assistance_xml", "false"); - config->set_property("GNSS-SDR.SUPL_gps_enabled", "false"); - config->set_property("GNSS-SDR.SUPL_gps_ephemeris_server", "supl.google.com"); - config->set_property("GNSS-SDR.SUPL_gps_ephemeris_port", std::to_string(7275)); - config->set_property("GNSS-SDR.SUPL_gps_acquisition_server", "supl.google.com"); - config->set_property("GNSS-SDR.SUPL_gps_acquisition_port", std::to_string(7275)); - config->set_property("GNSS-SDR.SUPL_MCC", std::to_string(244)); - config->set_property("GNSS-SDR.SUPL_MNS", std::to_string(5)); - config->set_property("GNSS-SDR.SUPL_LAC", "0x59e2"); - config->set_property("GNSS-SDR.SUPL_CI", "0x31b0"); - - // Set the Signal Source - config->set_property("SignalSource.implementation", "File_Signal_Source"); - config->set_property("SignalSource.filename", "./" + filename_raw_data); - config->set_property("SignalSource.sampling_frequency", std::to_string(sampling_rate_internal)); - config->set_property("SignalSource.item_type", "ibyte"); - config->set_property("SignalSource.samples", std::to_string(zero)); - - // Set the Signal Conditioner - config->set_property("SignalConditioner.implementation", "Signal_Conditioner"); - config->set_property("DataTypeAdapter.implementation", "Ibyte_To_Complex"); - //config->set_property("InputFilter.implementation", "Fir_Filter"); - config->set_property("InputFilter.implementation", "Pass_Through"); - config->set_property("InputFilter.dump", "false"); - config->set_property("InputFilter.input_item_type", "gr_complex"); - config->set_property("InputFilter.output_item_type", "gr_complex"); - config->set_property("InputFilter.taps_item_type", "float"); - config->set_property("InputFilter.number_of_taps", std::to_string(number_of_taps)); - config->set_property("InputFilter.number_of_bands", std::to_string(number_of_bands)); - config->set_property("InputFilter.band1_begin", std::to_string(band1_begin)); - config->set_property("InputFilter.band1_end", std::to_string(band1_end)); - config->set_property("InputFilter.band2_begin", std::to_string(band2_begin)); - config->set_property("InputFilter.band2_end", std::to_string(band2_end)); - config->set_property("InputFilter.ampl1_begin", std::to_string(ampl1_begin)); - config->set_property("InputFilter.ampl1_end", std::to_string(ampl1_end)); - config->set_property("InputFilter.ampl2_begin", std::to_string(ampl2_begin)); - config->set_property("InputFilter.ampl2_end", std::to_string(ampl2_end)); - config->set_property("InputFilter.band1_error", std::to_string(band1_error)); - config->set_property("InputFilter.band2_error", std::to_string(band2_error)); - config->set_property("InputFilter.filter_type", "bandpass"); - config->set_property("InputFilter.grid_density", std::to_string(grid_density)); - config->set_property("InputFilter.sampling_frequency", std::to_string(sampling_rate_internal)); - config->set_property("InputFilter.IF", std::to_string(zero)); - config->set_property("Resampler.implementation", "Pass_Through"); - config->set_property("Resampler.dump", "false"); - config->set_property("Resampler.item_type", "gr_complex"); - config->set_property("Resampler.sample_freq_in", std::to_string(sampling_rate_internal)); - config->set_property("Resampler.sample_freq_out", std::to_string(sampling_rate_internal)); - - // Set the number of Channels - config->set_property("Channels_1C.count", std::to_string(number_of_channels)); - config->set_property("Channels.in_acquisition", std::to_string(in_acquisition)); - config->set_property("Channel.signal", "1C"); - //config->set_property("Channel1.satellite", std::to_string(FLAGS_acq_test_PRN)); - // Set Acquisition config->set_property("Acquisition_1C.implementation", implementation); config->set_property("Acquisition_1C.item_type", "gr_complex"); @@ -409,7 +327,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step)); config->set_property("Acquisition_1C.threshold", std::to_string(threshold)); - if (FLAGS_acq_test_pfa > 0.0) config->force_set_property("Acquisition_1C.pfa", std::to_string(pfa)); + if (FLAGS_acq_test_pfa > 0.0) config->supersede_property("Acquisition_1C.pfa", std::to_string(pfa)); config->set_property("Acquisition_1C.use_CFAR_algorithm", "true"); @@ -437,50 +355,6 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign config->set_property("Acquisition_1C.dump_filename", dump_file); config->set_property("Acquisition_1C.dump_channel", std::to_string(dump_channel)); - // Set Tracking - config->set_property("Tracking_1C.implementation", "GPS_L1_CA_DLL_PLL_Tracking"); - //config->set_property("Tracking_1C.implementation", "GPS_L1_CA_DLL_PLL_C_Aid_Tracking"); - config->set_property("Tracking_1C.item_type", "gr_complex"); - config->set_property("Tracking_1C.dump", "false"); - config->set_property("Tracking_1C.dump_filename", "./tracking_ch_"); - config->set_property("Tracking_1C.pll_bw_hz", std::to_string(pll_bw_hz)); - config->set_property("Tracking_1C.dll_bw_hz", std::to_string(dll_bw_hz)); - config->set_property("Tracking_1C.early_late_space_chips", std::to_string(early_late_space_chips)); - - config->set_property("Tracking_1C.pll_bw_narrow_hz", std::to_string(pll_bw_narrow_hz)); - config->set_property("Tracking_1C.dll_bw_narrow_hz", std::to_string(dll_bw_narrow_hz)); - config->set_property("Tracking_1C.extend_correlation_symbols", std::to_string(extend_correlation_ms)); - config->set_property("Tracking_1C.cn0_min", std::to_string(50)); - config->set_property("Tracking_1C.max_lock_fail", std::to_string(1)); - config->set_property("Tracking_1C.cn0_samples", std::to_string(1)); - - // Set Telemetry - config->set_property("TelemetryDecoder_1C.implementation", "GPS_L1_CA_Telemetry_Decoder"); - config->set_property("TelemetryDecoder_1C.dump", "false"); - - // Set Observables - config->set_property("Observables.implementation", "Hybrid_Observables"); - config->set_property("Observables.dump", "false"); - config->set_property("Observables.dump_filename", "./observables.dat"); - - // Set PVT - config->set_property("PVT.implementation", "RTKLIB_PVT"); - config->set_property("PVT.positioning_mode", "PPP_Static"); - config->set_property("PVT.output_rate_ms", std::to_string(output_rate_ms)); - config->set_property("PVT.display_rate_ms", std::to_string(display_rate_ms)); - config->set_property("PVT.dump_filename", "./PVT"); - config->set_property("PVT.nmea_dump_filename", "./gnss_sdr_pvt.nmea"); - config->set_property("PVT.flag_nmea_tty_port", "false"); - config->set_property("PVT.nmea_dump_devname", "/dev/pts/4"); - config->set_property("PVT.flag_rtcm_server", "false"); - config->set_property("PVT.flag_rtcm_tty_port", "false"); - config->set_property("PVT.rtcm_dump_devname", "/dev/pts/1"); - config->set_property("PVT.dump", "false"); - config->set_property("PVT.rinex_version", std::to_string(2)); - config->set_property("PVT.iono_model", "OFF"); - config->set_property("PVT.trop_model", "OFF"); - config->set_property("PVT.AR_GPS", "PPP-AR"); - config_f = 0; } else @@ -542,35 +416,6 @@ int AcquisitionPerformanceTest::run_receiver() } -int AcquisitionPerformanceTest::run_receiver2() -{ - std::shared_ptr control_thread; - if (FLAGS_config_file_ptest.empty()) - { - control_thread = std::make_shared(config); - } - else - { - control_thread = std::make_shared(config_f); - } - - // start receiver - try - { - control_thread->run(); - } - catch (const boost::exception& e) - { - std::cout << "Boost exception: " << boost::diagnostic_information(e); - } - catch (const std::exception& ex) - { - std::cout << "STD exception: " << ex.what(); - } - return 0; -} - - int AcquisitionPerformanceTest::count_executions(const std::string& basename, unsigned int sat) { FILE* fp; @@ -603,35 +448,34 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) boost::filesystem::remove_all(path_str); } boost::system::error_code ec; - if (!boost::filesystem::create_directory(path_str, ec)) - { - std::cout << "Could not create the " << path_str << " folder." << std::endl; - // error - } + ASSERT_TRUE(boost::filesystem::create_directory(path_str, ec)) << "Could not create the " << path_str << " folder."; + unsigned int cn0_index = 0; + //for (unsigned iter = 0; iter < N_iterations; iter++) + //unsigned iter = 0; + //{ for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) { // Do N_iterations of the experiment - std::vector pfa_local = {0.01}; //{FLAGS_acq_test_pfa}; //{0.001, 0.01, 0.1, 1}; + std::vector meas_Pd_; std::vector meas_Pd_correct_; std::vector meas_Pfa_; - for (unsigned iter = 0; iter < N_iterations; iter++) + + // Set parameter to sweep + std::cout << "Execution for CN0 = " << *it << " dB-Hz" << std::endl; + for (int pfa_iter = 0; pfa_iter < static_cast(pfa_local.size()); pfa_iter++) { - // Set parameter to sweep - - - for (int pfa_iter = 0; pfa_iter < pfa_local.size(); pfa_iter++) + for (int iter = 0; iter < N_iterations; iter++) { std::string basename = path_str + std::string("/acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + std::to_string(pfa_local[pfa_iter]) + "_" + gnss_synchro.System + "_1C"; - // Configure the signal generator configure_generator(*it); // Generate signal raw signal samples and observations RINEX file generate_signal(); - std::cout << "Execution for CN0 = " << *it << " dB-Hz" << std::endl; + //std::cout << "Execution for CN0 = " << *it << " dB-Hz" << std::endl; for (unsigned k = 0; k < 2; k++) { if (k == 0) @@ -716,8 +560,7 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) // Process results arma::vec clean_doppler_estimation_error; arma::vec clean_delay_estimation_error; - std::vector meas_Pd_; - std::vector meas_Pd_correct_; + if (epoch_counter > 2) { arma::vec true_interpolated_doppler = arma::zeros(num_executions, 1); @@ -729,7 +572,7 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) arma::vec delay_estimation_error = true_interpolated_prn_delay_chips - (meas_acq_delay_chips - ((1.0 / baseband_sampling_freq) / GPS_L1_CA_CHIP_PERIOD)); // compensate 1 sample delay // Cut measurements without reference - for (unsigned int i = 0; i < num_executions; i++) + for (int i = 0; i < num_executions; i++) { if (!std::isnan(doppler_estimation_error(i)) and !std::isnan(delay_estimation_error(i))) { @@ -739,7 +582,7 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) clean_doppler_estimation_error = arma::zeros(num_clean_executions, 1); clean_delay_estimation_error = arma::zeros(num_clean_executions, 1); num_clean_executions = 0; - for (unsigned int i = 0; i < num_executions; i++) + for (int i = 0; i < num_executions; i++) { if (!std::isnan(doppler_estimation_error(i)) and !std::isnan(delay_estimation_error(i))) { @@ -766,9 +609,17 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) if (k == 0) { double detected = arma::accu(positive_acq); - if (num_executions > 0) meas_Pd_.push_back(static_cast(detected / num_executions)); + double computed_Pd = detected / static_cast(num_executions); + if (num_executions > 0) + { + meas_Pd_.push_back(computed_Pd); + } + else + { + meas_Pd_.push_back(0.0); + } std::cout << TEXT_BOLD_BLACK << "Probability of detection for channel=" << ch << ", CN0=" << *it << " dBHz" - << ": " << (num_executions > 0 ? (detected / num_executions) : 0.0) << TEXT_RESET << std::endl; + << ": " << (num_executions > 0 ? computed_Pd : 0.0) << TEXT_RESET << std::endl; } if (num_clean_executions > 0) { @@ -782,8 +633,10 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) correctly_detected = correctly_detected + 1.0; } } + double computed_Pd_correct = correctly_detected / static_cast(num_clean_executions); + meas_Pd_correct_.push_back(computed_Pd_correct); std::cout << TEXT_BOLD_BLACK << "Probability of correct detection for channel=" << ch << ", CN0=" << *it << " dBHz" - << ": " << (num_clean_executions > 0 ? (correctly_detected / num_clean_executions) : 0.0) << TEXT_RESET << std::endl; + << ": " << computed_Pd_correct << TEXT_RESET << std::endl; } else { @@ -791,35 +644,86 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) if (k == 1) { double wrongly_detected = arma::accu(positive_acq); - if (num_executions > 0) meas_Pfa_.push_back(static_cast(wrongly_detected / num_executions)); - std::cout - << TEXT_BOLD_BLACK << "Probability of false alarm for channel=" << ch << ", CN0=" << *it << " dBHz" - << ": " << (num_executions > 0 ? (wrongly_detected / num_executions) : 0.0) << TEXT_RESET << std::endl; + double computed_Pfa = wrongly_detected / static_cast(num_executions); + if (num_executions > 0) + { + meas_Pfa_.push_back(computed_Pfa); + } + else + { + meas_Pfa_.push_back(0.0); + } + std::cout << TEXT_BOLD_BLACK << "Probability of false alarm for channel=" << ch << ", CN0=" << *it << " dBHz" + << ": " << (num_executions > 0 ? computed_Pfa : 0.0) << TEXT_RESET << std::endl; } } true_trk_data.restart(); } - - float sum_ = static_cast(std::accumulate(meas_Pd_.begin(), meas_Pd_.end(), 0.0)); - Pd[cn0_index][pfa_iter] = sum_ / static_cast(meas_Pd_.size()); - sum_ = static_cast(std::accumulate(meas_Pfa_.begin(), meas_Pfa_.end(), 0.0)); - Pfa[cn0_index][pfa_iter] = sum_ / static_cast(meas_Pfa_.size()); - cn0_index++; + } + true_trk_data.close_obs_file(); + float sum_pd = static_cast(std::accumulate(meas_Pd_.begin(), meas_Pd_.end(), 0.0)); + float sum_pd_correct = static_cast(std::accumulate(meas_Pd_correct_.begin(), meas_Pd_correct_.end(), 0.0)); + float sum_pfa = static_cast(std::accumulate(meas_Pfa_.begin(), meas_Pfa_.end(), 0.0)); + if (meas_Pd_.size() > 0 and meas_Pfa_.size() > 0) + { + Pd[cn0_index][pfa_iter] = sum_pd / static_cast(meas_Pd_.size()); + Pfa[cn0_index][pfa_iter] = sum_pfa / static_cast(meas_Pfa_.size()); + } + else + { + if (meas_Pd_.size() > 0) + { + Pd[cn0_index][pfa_iter] = sum_pd / static_cast(meas_Pd_.size()); + } + else + { + Pd[cn0_index][pfa_iter] = 0.0; + } + if (meas_Pfa_.size() > 0) + { + Pfa[cn0_index][pfa_iter] = sum_pfa / static_cast(meas_Pfa_.size()); + } + else + { + Pfa[cn0_index][pfa_iter] = 0.0; + } + } + if (meas_Pd_correct_.size() > 0) + { + Pd_correct[cn0_index][pfa_iter] = sum_pd_correct / static_cast(meas_Pd_correct_.size()); + } + else + { + Pd_correct[cn0_index][pfa_iter] = 0.0; } } - true_trk_data.close_obs_file(); - // Compute results + cn0_index++; } + + // Compute results unsigned int aux_index = 0; for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) { std::cout << "Results for CN0 = " << *it << " dBHz:" << std::endl; std::cout << "Pd = "; - for (int pfa_iter = 0; pfa_iter < 1; pfa_iter++) + for (int pfa_iter = 0; pfa_iter < num_thresholds; pfa_iter++) { std::cout << Pd[aux_index][pfa_iter] << " "; } std::cout << std::endl; + std::cout << "Pd_correct = "; + for (int pfa_iter = 0; pfa_iter < num_thresholds; pfa_iter++) + { + std::cout << Pd_correct[aux_index][pfa_iter] << " "; + } + std::cout << std::endl; + std::cout << "Pfa = "; + for (int pfa_iter = 0; pfa_iter < num_thresholds; pfa_iter++) + { + std::cout << Pfa[aux_index][pfa_iter] << " "; + } + std::cout << std::endl; + aux_index++; } } From 85810daa74f3d4d46d5a50a0dfc59e3cceb84eda Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 28 Jun 2018 09:18:37 +0200 Subject: [PATCH 12/16] Add work on acq performance test --- .../gps_l1_acq_performance_test.cc | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index c9459763d..572fd5d92 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -34,8 +34,7 @@ #include "tracking_true_obs_reader.h" #include "true_observables_reader.h" #include "display.h" -#include // for create_directories, exists -//#include // for path, operator<< +#include // for create_directories, exists #include // for filesystem #include #include @@ -49,7 +48,7 @@ DEFINE_int32(acq_test_PRN, 1, "PRN number"); DEFINE_int32(acq_test_fake_PRN, 33, "Fake PRN number"); DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration"); DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag"); -DEFINE_int32(acq_test_iterations, 1, "Number of iterations"); +DEFINE_int32(acq_test_iterations, 2, "Number of iterations"); // ######## GNURADIO BLOCK MESSAGE RECEVER ######### class AcqPerfTest_msg_rx; @@ -120,7 +119,7 @@ protected: doppler_max = 5000; doppler_step = 125; stop = false; - acquisition = 0; + //acquisition_ = 0; init(); Pd.resize(cn0_.size()); for (int i = 0; i < static_cast(cn0_.size()); i++) Pd[i].reserve(num_thresholds); @@ -134,8 +133,8 @@ protected: { } - std::vector cn0_ = {35.0, 38.0, 43.0}; - std::vector pfa_local = {0.01, 0.1}; //{FLAGS_acq_test_pfa}; //{0.001, 0.01, 0.1, 1}; + std::vector cn0_ = {35.0}; + std::vector pfa_local = {0.0001, 0.001, 0.01, 0.1, 1}; //{FLAGS_acq_test_pfa}; //{0.001, 0.01, 0.1, 1}; int N_iterations = FLAGS_acq_test_iterations; void init(); //void plot_grid(); @@ -327,8 +326,8 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step)); config->set_property("Acquisition_1C.threshold", std::to_string(threshold)); - if (FLAGS_acq_test_pfa > 0.0) config->supersede_property("Acquisition_1C.pfa", std::to_string(pfa)); - + //if (FLAGS_acq_test_pfa > 0.0) config->supersede_property("Acquisition_1C.pfa", std::to_string(pfa)); + config->supersede_property("Acquisition_1C.pfa", std::to_string(pfa)); config->set_property("Acquisition_1C.use_CFAR_algorithm", "true"); config->set_property("Acquisition_1C.coherent_integration_time_ms", std::to_string(coherent_integration_time_ms)); @@ -451,9 +450,6 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) ASSERT_TRUE(boost::filesystem::create_directory(path_str, ec)) << "Could not create the " << path_str << " folder."; unsigned int cn0_index = 0; - //for (unsigned iter = 0; iter < N_iterations; iter++) - //unsigned iter = 0; - //{ for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) { // Do N_iterations of the experiment @@ -640,11 +636,12 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) } else { - // std::cout << "No reference data has been found. Maybe a non-present satellite?" << std::endl; + //std::cout << "No reference data has been found. Maybe a non-present satellite?" << num_executions << std::endl; if (k == 1) { double wrongly_detected = arma::accu(positive_acq); double computed_Pfa = wrongly_detected / static_cast(num_executions); + std::cout << computed_Pfa << std::endl; if (num_executions > 0) { meas_Pfa_.push_back(computed_Pfa); @@ -696,6 +693,9 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) { Pd_correct[cn0_index][pfa_iter] = 0.0; } + meas_Pd_.clear(); + meas_Pfa_.clear(); + meas_Pd_correct_.clear(); } cn0_index++; } From 566611fd5e5147f54a5c39c2b1afbca27e0dad6e Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 28 Jun 2018 16:30:36 +0200 Subject: [PATCH 13/16] Add work on acq performance --- .../gps_l1_acq_performance_test.cc | 93 ++++++++++++++++++- 1 file changed, 88 insertions(+), 5 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index 572fd5d92..e6d0e0626 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -34,8 +34,8 @@ #include "tracking_true_obs_reader.h" #include "true_observables_reader.h" #include "display.h" -#include // for create_directories, exists -#include // for filesystem +#include "gnuplot_i.h" +#include #include #include #include @@ -49,6 +49,7 @@ DEFINE_int32(acq_test_fake_PRN, 33, "Fake PRN number"); DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration"); DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag"); DEFINE_int32(acq_test_iterations, 2, "Number of iterations"); +DEFINE_bool(plot_acq_test, false, "Plots results of AcquisitionPerformanceTest with gnuplot"); // ######## GNURADIO BLOCK MESSAGE RECEVER ######### class AcqPerfTest_msg_rx; @@ -133,8 +134,8 @@ protected: { } - std::vector cn0_ = {35.0}; - std::vector pfa_local = {0.0001, 0.001, 0.01, 0.1, 1}; //{FLAGS_acq_test_pfa}; //{0.001, 0.01, 0.1, 1}; + std::vector cn0_ = {35.0, 38.0}; + std::vector pfa_local = {0.001, 0.01, 1}; //{0.0001, 0.001, 0.01, 0.1, 1}; //{FLAGS_acq_test_pfa}; //{0.001, 0.01, 0.1, 1}; int N_iterations = FLAGS_acq_test_iterations; void init(); //void plot_grid(); @@ -149,6 +150,7 @@ protected: int run_receiver(); int count_executions(const std::string& basename, unsigned int sat); void check_results(); + void plot_results(); concurrent_queue channel_internal_queue; @@ -438,7 +440,86 @@ int AcquisitionPerformanceTest::count_executions(const std::string& basename, un } -TEST_F(AcquisitionPerformanceTest, PdvsCn0) +void AcquisitionPerformanceTest::plot_results() +{ + if (FLAGS_plot_acq_test == true) + { + const std::string gnuplot_executable(FLAGS_gnuplot_executable); + if (gnuplot_executable.empty()) + { + std::cout << "WARNING: Although the flag plot_gps_l1_tracking_test has been set to TRUE," << std::endl; + std::cout << "gnuplot has not been found in your system." << std::endl; + std::cout << "Test results will not be plotted." << std::endl; + } + else + { + try + { + boost::filesystem::path p(gnuplot_executable); + boost::filesystem::path dir = p.parent_path(); + std::string gnuplot_path = dir.native(); + Gnuplot::set_GNUPlotPath(gnuplot_path); + + Gnuplot g1("linespoints"); + g1.set_title("Receiver Operating Characteristic for GPS L1 C/A acquisition"); + g1.cmd("set logscale x"); + g1.cmd("set yrange [0:1]"); + g1.cmd("set grid xtics 0.001 0.01 0.1 1"); + g1.cmd("set grid ytics"); + g1.set_grid(); + g1.set_xlabel("Pfa"); + g1.set_ylabel("Pd"); + for (int i = 0; i < static_cast(cn0_.size()); i++) + { + std::vector Pd_i; + std::vector Pfa_i; + for (int k = 0; k < num_thresholds; k++) + { + Pd_i.push_back(Pd[i][k]); + Pfa_i.push_back(Pd[i][k]); + } + g1.plot_xy(Pfa_i, Pd_i, "CN0 = " + std::to_string(static_cast(cn0_[i])) + " dBHz"); + } + g1.set_legend(); + g1.savetops("ROC"); + g1.savetopdf("ROC", 18); + g1.showonscreen(); // window output + + if (Pd_correct[0].size() > 0) + { + Gnuplot g2("linespoints"); + g2.set_title("Receiver Operating Characteristic for GPS L1 C/A correct acquisition"); + g2.cmd("set logscale x"); + g2.set_xlabel("Pfa"); + g2.set_xlabel("Pd"); + g2.set_grid(); + for (int i = 0; i < static_cast(cn0_.size()); i++) + { + std::vector Pd_i_correct; + std::vector Pfa_i; + for (int k = 0; k < num_thresholds; k++) + { + Pd_i_correct.push_back(Pd_correct[i][k]); + Pfa_i.push_back(Pd[i][k]); + } + g2.plot_xy(Pfa_i, Pd_i_correct, "CN0 = " + std::to_string(static_cast(cn0_[i])) + " dBHz"); + } + g2.set_legend(); + g2.savetops("ROC-correct"); + g2.savetopdf("ROC-correct", 18); + g2.showonscreen(); // window output + } + } + catch (const GnuplotException& ge) + { + std::cout << ge.what() << std::endl; + } + } + } +} + + +TEST_F(AcquisitionPerformanceTest, ROC) { tracking_true_obs_reader true_trk_data; @@ -726,4 +807,6 @@ TEST_F(AcquisitionPerformanceTest, PdvsCn0) aux_index++; } + + plot_results(); } From c4f3b6ec318988529e992481e3a24b99cb72d26a Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 29 Jun 2018 13:33:53 +0200 Subject: [PATCH 14/16] Add work on Acq perfromance test --- .../gps_l1_acq_performance_test.cc | 162 +++++++++--------- 1 file changed, 85 insertions(+), 77 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index e6d0e0626..87abc2661 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -40,16 +40,17 @@ #include #include -DEFINE_string(config_file_ptest, std::string(""), "File containing the configuration parameters for the position test."); -DEFINE_double(acq_test_threshold, 0.001, "Acquisition threshold"); -DEFINE_double(acq_test_pfa, -1.0, "Set threshold via probability of false alarm"); -DEFINE_int32(acq_test_coherent_time_ms, 10, "Acquisition coherent time, in ms"); -DEFINE_int32(acq_test_PRN, 1, "PRN number"); -DEFINE_int32(acq_test_fake_PRN, 33, "Fake PRN number"); -DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration"); +DEFINE_string(config_file_ptest, std::string(""), "File containing alternative configuration parameters for the position test."); +//DEFINE_double(acq_test_threshold, 0.001, "Acquisition threshold"); +DEFINE_double(acq_test_pfa_init, 1e-5, "Set initial threshold via probability of false alarm"); +DEFINE_int32(acq_test_coherent_time_ms, 1, "Acquisition coherent time, in ms"); +DEFINE_int32(acq_test_PRN, 1, "PRN number of a present satellite"); +DEFINE_int32(acq_test_fake_PRN, 33, "PRN number of a non-present satellite"); +DEFINE_int32(acq_test_signal_duration_s, 1, "Generated signal duration, in s"); DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag"); -DEFINE_int32(acq_test_iterations, 2, "Number of iterations"); -DEFINE_bool(plot_acq_test, false, "Plots results of AcquisitionPerformanceTest with gnuplot"); +DEFINE_int32(acq_test_iterations, 1, "Number of iterations (same signal, diferent noise realization)"); +DEFINE_bool(plot_acq_test, false, "Plots results with gnuplot, if available"); +DEFINE_bool(acq_test_use_CFAR_algorithm, true, "Use CFAR algorithm"); // ######## GNURADIO BLOCK MESSAGE RECEVER ######### class AcqPerfTest_msg_rx; @@ -120,25 +121,33 @@ protected: doppler_max = 5000; doppler_step = 125; stop = false; - //acquisition_ = 0; init(); - Pd.resize(cn0_.size()); - for (int i = 0; i < static_cast(cn0_.size()); i++) Pd[i].reserve(num_thresholds); - Pfa.resize(cn0_.size()); - for (int i = 0; i < static_cast(cn0_.size()); i++) Pfa[i].reserve(num_thresholds); - Pd_correct.resize(cn0_.size()); - for (int i = 0; i < static_cast(cn0_.size()); i++) Pd_correct[i].reserve(num_thresholds); + pfa_vector.push_back(FLAGS_acq_test_pfa_init); + float aux = 1.0; + while ((FLAGS_acq_test_pfa_init * std::pow(10, aux)) < 1) + { + pfa_vector.push_back(FLAGS_acq_test_pfa_init * std::pow(10, aux)); + aux = aux + 1.0; + } + pfa_vector.push_back(1.0); + num_thresholds = pfa_vector.size(); + Pd.resize(cn0_vector.size()); + for (int i = 0; i < static_cast(cn0_vector.size()); i++) Pd[i].reserve(num_thresholds); + Pfa.resize(cn0_vector.size()); + for (int i = 0; i < static_cast(cn0_vector.size()); i++) Pfa[i].reserve(num_thresholds); + Pd_correct.resize(cn0_vector.size()); + for (int i = 0; i < static_cast(cn0_vector.size()); i++) Pd_correct[i].reserve(num_thresholds); } ~AcquisitionPerformanceTest() { } - std::vector cn0_ = {35.0, 38.0}; - std::vector pfa_local = {0.001, 0.01, 1}; //{0.0001, 0.001, 0.01, 0.1, 1}; //{FLAGS_acq_test_pfa}; //{0.001, 0.01, 0.1, 1}; + std::vector cn0_vector = {35.0, 38.0}; + std::vector pfa_vector; + int N_iterations = FLAGS_acq_test_iterations; void init(); - //void plot_grid(); int configure_generator(double cn0); int generate_signal(); @@ -174,25 +183,24 @@ protected: const int coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; const int number_of_channels = 2; const int in_acquisition = 1; - const float threshold = FLAGS_acq_test_threshold; + const float threshold = 0.001; // FLAGS_acq_test_threshold; const int max_dwells = 1; const int dump_channel = 0; int generated_signal_duration_s = FLAGS_acq_test_signal_duration_s; - unsigned int num_of_realizations = (generated_signal_duration_s * 1000) / FLAGS_acq_test_coherent_time_ms; - unsigned int realization_counter; + unsigned int num_of_realizations = ((generated_signal_duration_s * 1000 - FLAGS_acq_test_coherent_time_ms) / FLAGS_acq_test_coherent_time_ms); + unsigned int realization_counter = 0; unsigned int observed_satellite = FLAGS_acq_test_PRN; std::string path_str = "./acq-perf-test"; - int num_thresholds = pfa_local.size(); + int num_thresholds; std::vector> Pd; std::vector> Pfa; std::vector> Pd_correct; - private: std::string generator_binary; std::string p1; @@ -202,15 +210,11 @@ private: std::string p5; std::string p6; - std::string filename_rinex_obs = FLAGS_filename_rinex_obs; std::string filename_raw_data = FLAGS_filename_raw_data; double compute_stdev_precision(const std::vector& vec); double compute_stdev_accuracy(const std::vector& vec, double ref); - - - //std::string generated_kml_file; }; @@ -237,11 +241,7 @@ void AcquisitionPerformanceTest::wait_message() { while (!stop) { - acquisition->reset(); - acquisition->set_state(1); - channel_internal_queue.wait_and_pop(message); - process_message(); } } @@ -252,7 +252,7 @@ void AcquisitionPerformanceTest::process_message() realization_counter++; acquisition->reset(); acquisition->set_state(1); - + std::cout << "Progress: " << round(static_cast(realization_counter) / static_cast(num_of_realizations) * 100.0) << "% \r" << std::flush; if (realization_counter == num_of_realizations) { stop_queue(); @@ -328,9 +328,16 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step)); config->set_property("Acquisition_1C.threshold", std::to_string(threshold)); - //if (FLAGS_acq_test_pfa > 0.0) config->supersede_property("Acquisition_1C.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_1C.pfa", std::to_string(pfa)); - config->set_property("Acquisition_1C.use_CFAR_algorithm", "true"); + if (FLAGS_acq_test_use_CFAR_algorithm) + { + config->set_property("Acquisition_1C.use_CFAR_algorithm", "true"); + } + else + { + config->set_property("Acquisition_1C.use_CFAR_algorithm", "false"); + } config->set_property("Acquisition_1C.coherent_integration_time_ms", std::to_string(coherent_integration_time_ms)); if (FLAGS_acq_test_bit_transition_flag) @@ -355,6 +362,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign 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_f = 0; } @@ -420,7 +428,7 @@ int AcquisitionPerformanceTest::run_receiver() int AcquisitionPerformanceTest::count_executions(const std::string& basename, unsigned int sat) { FILE* fp; - std::string argum2 = std::string("/bin/ls ") + basename + "* | grep sat_" + std::to_string(sat) + " | wc -l"; + std::string argum2 = std::string("/usr/bin/find ") + path_str + std::string(" -maxdepth 1 -name ") + basename.substr(path_str.length() + 1, basename.length() - path_str.length()) + std::string("* | grep sat_") + std::to_string(sat) + std::string(" | wc -l"); char buffer[1024]; fp = popen(&argum2[0], "r"); int num_executions = 1; @@ -461,15 +469,16 @@ void AcquisitionPerformanceTest::plot_results() Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot g1("linespoints"); - g1.set_title("Receiver Operating Characteristic for GPS L1 C/A acquisition"); + g1.set_title("Receiver Operating Characteristic for GPS L1 C/A acquisition, coherent integration time: " + std::to_string(config->property("Acquisition_1C.coherent_integration_time_ms", 1)) + " ms."); g1.cmd("set logscale x"); g1.cmd("set yrange [0:1]"); - g1.cmd("set grid xtics 0.001 0.01 0.1 1"); - g1.cmd("set grid ytics"); - g1.set_grid(); g1.set_xlabel("Pfa"); g1.set_ylabel("Pd"); - for (int i = 0; i < static_cast(cn0_.size()); i++) + g1.cmd("set grid xtics"); + g1.cmd("set grid mytics"); + g1.set_grid(); + g1.cmd("show grid"); + for (int i = 0; i < static_cast(cn0_vector.size()); i++) { std::vector Pd_i; std::vector Pfa_i; @@ -478,37 +487,38 @@ void AcquisitionPerformanceTest::plot_results() Pd_i.push_back(Pd[i][k]); Pfa_i.push_back(Pd[i][k]); } - g1.plot_xy(Pfa_i, Pd_i, "CN0 = " + std::to_string(static_cast(cn0_[i])) + " dBHz"); + g1.plot_xy(Pfa_i, Pd_i, "CN0 = " + std::to_string(static_cast(cn0_vector[i])) + " dBHz"); } g1.set_legend(); g1.savetops("ROC"); g1.savetopdf("ROC", 18); g1.showonscreen(); // window output - if (Pd_correct[0].size() > 0) + Gnuplot g2("linespoints"); + g2.set_title("Receiver Operating Characteristic for GPS L1 C/A valid acquisition, coherent integration time: " + std::to_string(config->property("Acquisition_1C.coherent_integration_time_ms", 1)) + " ms."); + g2.cmd("set logscale x"); + g2.cmd("set yrange [0:1]"); + g1.cmd("set grid xtics"); + g1.cmd("set grid mytics"); + g2.set_xlabel("Pfa"); + g2.set_ylabel("Valid Pd"); + g2.set_grid(); + g2.cmd("show grid"); + for (int i = 0; i < static_cast(cn0_vector.size()); i++) { - Gnuplot g2("linespoints"); - g2.set_title("Receiver Operating Characteristic for GPS L1 C/A correct acquisition"); - g2.cmd("set logscale x"); - g2.set_xlabel("Pfa"); - g2.set_xlabel("Pd"); - g2.set_grid(); - for (int i = 0; i < static_cast(cn0_.size()); i++) + std::vector Pd_i_correct; + std::vector Pfa_i; + for (int k = 0; k < num_thresholds; k++) { - std::vector Pd_i_correct; - std::vector Pfa_i; - for (int k = 0; k < num_thresholds; k++) - { - Pd_i_correct.push_back(Pd_correct[i][k]); - Pfa_i.push_back(Pd[i][k]); - } - g2.plot_xy(Pfa_i, Pd_i_correct, "CN0 = " + std::to_string(static_cast(cn0_[i])) + " dBHz"); + Pd_i_correct.push_back(Pd_correct[i][k]); + Pfa_i.push_back(Pd[i][k]); } - g2.set_legend(); - g2.savetops("ROC-correct"); - g2.savetopdf("ROC-correct", 18); - g2.showonscreen(); // window output + g2.plot_xy(Pfa_i, Pd_i_correct, "CN0 = " + std::to_string(static_cast(cn0_vector[i])) + " dBHz"); } + g2.set_legend(); + g2.savetops("ROC-valid-detection"); + g2.savetopdf("ROC-valid-detection", 18); + g2.showonscreen(); // window output } catch (const GnuplotException& ge) { @@ -531,28 +541,25 @@ TEST_F(AcquisitionPerformanceTest, ROC) ASSERT_TRUE(boost::filesystem::create_directory(path_str, ec)) << "Could not create the " << path_str << " folder."; unsigned int cn0_index = 0; - for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) + for (std::vector::const_iterator it = cn0_vector.cbegin(); it != cn0_vector.cend(); ++it) { - // Do N_iterations of the experiment - std::vector meas_Pd_; std::vector meas_Pd_correct_; std::vector meas_Pfa_; - // Set parameter to sweep std::cout << "Execution for CN0 = " << *it << " dB-Hz" << std::endl; - for (int pfa_iter = 0; pfa_iter < static_cast(pfa_local.size()); pfa_iter++) + + // Do N_iterations of the experiment + for (int pfa_iter = 0; pfa_iter < static_cast(pfa_vector.size()); pfa_iter++) { + std::cout << "Setting threshold for Pfa = " << pfa_vector[pfa_iter] << std::endl; + // Configure the signal generator + configure_generator(*it); for (int iter = 0; iter < N_iterations; iter++) { - std::string basename = path_str + std::string("/acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + std::to_string(pfa_local[pfa_iter]) + "_" + gnss_synchro.System + "_1C"; - // Configure the signal generator - configure_generator(*it); - // Generate signal raw signal samples and observations RINEX file generate_signal(); - //std::cout << "Execution for CN0 = " << *it << " dB-Hz" << std::endl; for (unsigned k = 0; k < 2; k++) { if (k == 0) @@ -566,12 +573,13 @@ TEST_F(AcquisitionPerformanceTest, ROC) init(); // Configure the receiver - configure_receiver(*it, pfa_local[pfa_iter], iter); + configure_receiver(*it, pfa_vector[pfa_iter], iter); // Run it 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"; int num_executions = count_executions(basename, observed_satellite); // Read measured data @@ -669,7 +677,7 @@ TEST_F(AcquisitionPerformanceTest, ROC) } } - std::cout << "Doppler estimation error [Hz]: "; + /* std::cout << "Doppler estimation error [Hz]: "; for (int i = 0; i < num_executions - 1; i++) { std::cout << doppler_estimation_error(i) << " "; @@ -680,8 +688,9 @@ TEST_F(AcquisitionPerformanceTest, ROC) for (int i = 0; i < num_executions - 1; i++) { std::cout << delay_estimation_error(i) << " "; + } - std::cout << std::endl; + std::cout << std::endl; */ } if (k == 0) { @@ -722,7 +731,6 @@ TEST_F(AcquisitionPerformanceTest, ROC) { double wrongly_detected = arma::accu(positive_acq); double computed_Pfa = wrongly_detected / static_cast(num_executions); - std::cout << computed_Pfa << std::endl; if (num_executions > 0) { meas_Pfa_.push_back(computed_Pfa); @@ -783,7 +791,7 @@ TEST_F(AcquisitionPerformanceTest, ROC) // Compute results unsigned int aux_index = 0; - for (std::vector::const_iterator it = cn0_.cbegin(); it != cn0_.cend(); ++it) + for (std::vector::const_iterator it = cn0_vector.cbegin(); it != cn0_vector.cend(); ++it) { std::cout << "Results for CN0 = " << *it << " dBHz:" << std::endl; std::cout << "Pd = "; From 37e1ba8a009bfe042f4f2ac5d77f8eecda05b138 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 29 Jun 2018 20:43:09 +0200 Subject: [PATCH 15/16] Add work on acq performance test --- .../gps_l1_acq_performance_test.cc | 171 +++++++++++++----- 1 file changed, 126 insertions(+), 45 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index 87abc2661..af358b43c 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -40,17 +40,34 @@ #include #include -DEFINE_string(config_file_ptest, std::string(""), "File containing alternative configuration parameters for the position test."); -//DEFINE_double(acq_test_threshold, 0.001, "Acquisition threshold"); -DEFINE_double(acq_test_pfa_init, 1e-5, "Set initial threshold via probability of false alarm"); +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_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_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."); +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, "Initial acquisition threshold"); +DEFINE_double(acq_test_threshold_step, 1.0, "Acquisition threshold step"); + +DEFINE_double(acq_test_pfa_init, 1e-5, "Set initial threshold via probability of false alarm. Disable with -1.0"); + DEFINE_int32(acq_test_PRN, 1, "PRN number of a present satellite"); DEFINE_int32(acq_test_fake_PRN, 33, "PRN number of a non-present satellite"); -DEFINE_int32(acq_test_signal_duration_s, 1, "Generated signal duration, in s"); -DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag"); -DEFINE_int32(acq_test_iterations, 1, "Number of iterations (same signal, diferent noise realization)"); + +DEFINE_int32(acq_test_iterations, 1, "Number of iterations (same signal, different noise realization)"); DEFINE_bool(plot_acq_test, false, "Plots results with gnuplot, if available"); -DEFINE_bool(acq_test_use_CFAR_algorithm, true, "Use CFAR algorithm"); +DEFINE_bool(show_plots, true, "Show plots on screen. Disable for non-interactive testing."); // ######## GNURADIO BLOCK MESSAGE RECEVER ######### class AcqPerfTest_msg_rx; @@ -118,19 +135,60 @@ protected: config = std::make_shared(); item_size = sizeof(gr_complex); gnss_synchro = Gnss_Synchro(); - doppler_max = 5000; - doppler_step = 125; + doppler_max = static_cast(FLAGS_acq_test_doppler_max); + doppler_step = static_cast(FLAGS_acq_test_doppler_step); stop = false; - init(); - pfa_vector.push_back(FLAGS_acq_test_pfa_init); - float aux = 1.0; - while ((FLAGS_acq_test_pfa_init * std::pow(10, aux)) < 1) + if (FLAGS_acq_test_input_file.empty()) { - pfa_vector.push_back(FLAGS_acq_test_pfa_init * std::pow(10, aux)); - aux = aux + 1.0; + cn0_vector.push_back(FLAGS_acq_test_cn0_init); + double aux = FLAGS_acq_test_cn0_init + FLAGS_acq_test_cn0_step; + while (aux <= FLAGS_acq_test_cn0_final) + { + cn0_vector.push_back(aux); + aux = aux + FLAGS_acq_test_cn0_step; + } } - pfa_vector.push_back(1.0); + else + { + cn0_vector = {0.0}; + } + init(); + + if (FLAGS_acq_test_pfa_init > 0.0) + { + pfa_vector.push_back(FLAGS_acq_test_pfa_init); + float aux = 1.0; + while ((FLAGS_acq_test_pfa_init * std::pow(10, aux)) < 1) + { + pfa_vector.push_back(FLAGS_acq_test_pfa_init * std::pow(10, aux)); + aux = aux + 1.0; + } + pfa_vector.push_back(1.0); + } + else + { + float aux = static_cast(FLAGS_acq_test_threshold_init); + pfa_vector.push_back(aux); + aux = aux + static_cast(FLAGS_acq_test_threshold_step); + while (aux <= static_cast(FLAGS_acq_test_threshold_final)) + { + pfa_vector.push_back(aux); + aux = aux + static_cast(FLAGS_acq_test_threshold_step); + } + } + num_thresholds = pfa_vector.size(); + + int aux2 = ((generated_signal_duration_s * 1000 - FLAGS_acq_test_coherent_time_ms) / FLAGS_acq_test_coherent_time_ms); + if ((FLAGS_acq_test_num_meas > 0) and (FLAGS_acq_test_num_meas < aux2)) + { + num_of_measurements = static_cast(FLAGS_acq_test_num_meas); + } + else + { + num_of_measurements = static_cast(aux2); + } + Pd.resize(cn0_vector.size()); for (int i = 0; i < static_cast(cn0_vector.size()); i++) Pd[i].reserve(num_thresholds); Pfa.resize(cn0_vector.size()); @@ -143,7 +201,8 @@ protected: { } - std::vector cn0_vector = {35.0, 38.0}; + + std::vector cn0_vector; std::vector pfa_vector; int N_iterations = FLAGS_acq_test_iterations; @@ -181,16 +240,12 @@ protected: const double baseband_sampling_freq = static_cast(FLAGS_fs_gen_sps); const int coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; - const int number_of_channels = 2; const int in_acquisition = 1; - const float threshold = 0.001; // FLAGS_acq_test_threshold; - const int max_dwells = 1; const int dump_channel = 0; int generated_signal_duration_s = FLAGS_acq_test_signal_duration_s; - - unsigned int num_of_realizations = ((generated_signal_duration_s * 1000 - FLAGS_acq_test_coherent_time_ms) / FLAGS_acq_test_coherent_time_ms); - unsigned int realization_counter = 0; + unsigned int num_of_measurements; + unsigned int measurement_counter = 0; unsigned int observed_satellite = FLAGS_acq_test_PRN; std::string path_str = "./acq-perf-test"; @@ -226,7 +281,7 @@ void AcquisitionPerformanceTest::init() signal.copy(gnss_synchro.Signal, 2, 0); gnss_synchro.PRN = observed_satellite; message = 0; - realization_counter = 0; + measurement_counter = 0; } @@ -249,11 +304,11 @@ void AcquisitionPerformanceTest::wait_message() void AcquisitionPerformanceTest::process_message() { - realization_counter++; + measurement_counter++; acquisition->reset(); acquisition->set_state(1); - std::cout << "Progress: " << round(static_cast(realization_counter) / static_cast(num_of_realizations) * 100.0) << "% \r" << std::flush; - if (realization_counter == num_of_realizations) + std::cout << "Progress: " << round(static_cast(measurement_counter) / static_cast(num_of_measurements) * 100.0) << "% \r" << std::flush; + if (measurement_counter == num_of_measurements) { stop_queue(); top_block->stop(); @@ -327,9 +382,12 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign config->set_property("Acquisition_1C.doppler_max", std::to_string(doppler_max)); config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step)); - config->set_property("Acquisition_1C.threshold", std::to_string(threshold)); + 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->supersede_property("Acquisition_1C.pfa", std::to_string(pfa)); + if (FLAGS_acq_test_pfa_init > 0.0) + { + config->supersede_property("Acquisition_1C.pfa", std::to_string(pfa)); + } if (FLAGS_acq_test_use_CFAR_algorithm) { config->set_property("Acquisition_1C.use_CFAR_algorithm", "true"); @@ -349,7 +407,7 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign config->set_property("Acquisition_1C.bit_transition_flag", "false"); } - config->set_property("Acquisition_1C.max_dwells", std::to_string(1)); + config->set_property("Acquisition_1C.max_dwells", std::to_string(FLAGS_acq_test_max_dwells)); config->set_property("Acquisition_1C.repeat_satellite", "true"); @@ -377,7 +435,15 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign int AcquisitionPerformanceTest::run_receiver() { - std::string file = "./" + filename_raw_data; + std::string file; + if (FLAGS_acq_test_input_file.empty()) + { + file = "./" + filename_raw_data; + } + else + { + file = FLAGS_acq_test_input_file; + } const char* file_name = file.c_str(); gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false); @@ -469,13 +535,16 @@ void AcquisitionPerformanceTest::plot_results() Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot g1("linespoints"); - g1.set_title("Receiver Operating Characteristic for GPS L1 C/A acquisition, coherent integration time: " + std::to_string(config->property("Acquisition_1C.coherent_integration_time_ms", 1)) + " ms."); + 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 logscale x"); g1.cmd("set yrange [0:1]"); + g1.cmd("set xrange[0.0001:1]"); + g1.cmd("set grid mxtics"); + g1.cmd("set grid ytics"); g1.set_xlabel("Pfa"); g1.set_ylabel("Pd"); - g1.cmd("set grid xtics"); - g1.cmd("set grid mytics"); g1.set_grid(); g1.cmd("show grid"); for (int i = 0; i < static_cast(cn0_vector.size()); i++) @@ -485,21 +554,24 @@ void AcquisitionPerformanceTest::plot_results() for (int k = 0; k < num_thresholds; k++) { Pd_i.push_back(Pd[i][k]); - Pfa_i.push_back(Pd[i][k]); + Pfa_i.push_back(Pfa[i][k]); } g1.plot_xy(Pfa_i, Pd_i, "CN0 = " + std::to_string(static_cast(cn0_vector[i])) + " dBHz"); } g1.set_legend(); g1.savetops("ROC"); g1.savetopdf("ROC", 18); - g1.showonscreen(); // window output + if (FLAGS_show_plots) g1.showonscreen(); // window output Gnuplot g2("linespoints"); - g2.set_title("Receiver Operating Characteristic for GPS L1 C/A valid acquisition, coherent integration time: " + std::to_string(config->property("Acquisition_1C.coherent_integration_time_ms", 1)) + " ms."); + 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 logscale x"); g2.cmd("set yrange [0:1]"); - g1.cmd("set grid xtics"); - g1.cmd("set grid mytics"); + g2.cmd("set xrange[0.0001:1]"); + g2.cmd("set grid mxtics"); + g2.cmd("set grid ytics"); g2.set_xlabel("Pfa"); g2.set_ylabel("Valid Pd"); g2.set_grid(); @@ -511,14 +583,14 @@ void AcquisitionPerformanceTest::plot_results() for (int k = 0; k < num_thresholds; k++) { Pd_i_correct.push_back(Pd_correct[i][k]); - Pfa_i.push_back(Pd[i][k]); + Pfa_i.push_back(Pfa[i][k]); } g2.plot_xy(Pfa_i, Pd_i_correct, "CN0 = " + std::to_string(static_cast(cn0_vector[i])) + " dBHz"); } g2.set_legend(); g2.savetops("ROC-valid-detection"); g2.savetopdf("ROC-valid-detection", 18); - g2.showonscreen(); // window output + if (FLAGS_show_plots) g2.showonscreen(); // window output } catch (const GnuplotException& ge) { @@ -547,18 +619,27 @@ TEST_F(AcquisitionPerformanceTest, ROC) std::vector meas_Pd_correct_; std::vector meas_Pfa_; - std::cout << "Execution for CN0 = " << *it << " dB-Hz" << std::endl; + if (FLAGS_acq_test_input_file.empty()) std::cout << "Execution for CN0 = " << *it << " dB-Hz" << std::endl; // Do N_iterations of the experiment for (int pfa_iter = 0; pfa_iter < static_cast(pfa_vector.size()); pfa_iter++) { - std::cout << "Setting threshold for Pfa = " << pfa_vector[pfa_iter] << std::endl; + if (FLAGS_acq_test_pfa_init > 0.0) + { + std::cout << "Setting threshold for Pfa = " << pfa_vector[pfa_iter] << std::endl; + } + else + { + std::cout << "Setting threshold to " << pfa_vector[pfa_iter] << std::endl; + } + // Configure the signal generator - configure_generator(*it); + if (FLAGS_acq_test_input_file.empty()) configure_generator(*it); + for (int iter = 0; iter < N_iterations; iter++) { // Generate signal raw signal samples and observations RINEX file - generate_signal(); + if (FLAGS_acq_test_input_file.empty()) generate_signal(); for (unsigned k = 0; k < 2; k++) { From 4a9cf9db6021345f10d08f166ca0d08d499654c5 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 29 Jun 2018 21:22:20 +0200 Subject: [PATCH 16/16] Fix typo --- .../acquisition/gps_l1_acq_performance_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc index af358b43c..e85263f31 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc @@ -57,7 +57,7 @@ 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, "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_pfa_init, 1e-5, "Set initial threshold via probability of false alarm. Disable with -1.0");