From dc910bca4e74678e8dece8d8934763c4ec4e65d4 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Thu, 2 Feb 2017 16:41:58 +0100 Subject: [PATCH 1/2] GNSS simulator-in-the-loop completed for tracking and telemetry unit tests --- .../gps_l1_ca_dll_pll_tracking_cc.cc | 2 +- .../libs/CMakeLists.txt | 6 +- .../libs/tlm_dump_reader.cc | 73 ++++++ .../libs/tlm_dump_reader.h | 34 +++ .../libs/tracking_dump_reader.cc | 93 +++++++ .../libs/tracking_dump_reader.h | 63 +++++ .../libs/tracking_obs_reader.h | 33 --- ..._reader.cc => tracking_true_obs_reader.cc} | 42 +++- .../libs/tracking_true_obs_reader.h | 36 +++ .../gps_l1_ca_telemetry_decoder_test.cc | 232 ++++++++++++++++-- 10 files changed, 545 insertions(+), 69 deletions(-) create mode 100644 src/tests/unit-tests/signal-processing-blocks/libs/tlm_dump_reader.cc create mode 100644 src/tests/unit-tests/signal-processing-blocks/libs/tlm_dump_reader.h create mode 100644 src/tests/unit-tests/signal-processing-blocks/libs/tracking_dump_reader.cc create mode 100644 src/tests/unit-tests/signal-processing-blocks/libs/tracking_dump_reader.h delete mode 100644 src/tests/unit-tests/signal-processing-blocks/libs/tracking_obs_reader.h rename src/tests/unit-tests/signal-processing-blocks/libs/{tracking_obs_reader.cc => tracking_true_obs_reader.cc} (57%) create mode 100644 src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.h diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_cc.cc index fb50e9563..deda7039e 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_cc.cc @@ -465,7 +465,7 @@ int Gps_L1_Ca_Dll_Pll_Tracking_cc::general_work (int noutput_items __attribute__ // PLL commands d_dump_file.write(reinterpret_cast(&carr_error_hz), sizeof(double)); - d_dump_file.write(reinterpret_cast(&d_carrier_doppler_hz), sizeof(double)); + d_dump_file.write(reinterpret_cast(&carr_error_filt_hz), sizeof(double)); // DLL commands d_dump_file.write(reinterpret_cast(&code_error_chips), sizeof(double)); diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/CMakeLists.txt b/src/tests/unit-tests/signal-processing-blocks/libs/CMakeLists.txt index 35efafc99..82d4d76e3 100644 --- a/src/tests/unit-tests/signal-processing-blocks/libs/CMakeLists.txt +++ b/src/tests/unit-tests/signal-processing-blocks/libs/CMakeLists.txt @@ -17,8 +17,10 @@ # -set(SIGNAL_PROCESSING_TESTING_LIB_SOURCES - tracking_obs_reader.cc +set(SIGNAL_PROCESSING_TESTING_LIB_SOURCES + tracking_dump_reader.cc + tlm_dump_reader.cc + tracking_true_obs_reader.cc ) include_directories( diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/tlm_dump_reader.cc b/src/tests/unit-tests/signal-processing-blocks/libs/tlm_dump_reader.cc new file mode 100644 index 000000000..9cfb645a9 --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/libs/tlm_dump_reader.cc @@ -0,0 +1,73 @@ +// +// Created by javier on 1/2/2017. +// + +#include "tlm_dump_reader.h" + +bool tlm_dump_reader::read_binary_obs() + { + try { + d_dump_file.read((char *) &TOW_at_current_symbol, sizeof(double)); + d_dump_file.read((char *) &Prn_timestamp_ms, sizeof(double)); + d_dump_file.read((char *) &d_TOW_at_Preamble, sizeof(double)); + } + catch (const std::ifstream::failure &e) { + return false; + } + return true; + } + +bool tlm_dump_reader::restart() { + if (d_dump_file.is_open()) + { + d_dump_file.clear(); + d_dump_file.seekg(0, std::ios::beg); + return true; + }else{ + return false; + } +} + +long int tlm_dump_reader::num_epochs() +{ + std::ifstream::pos_type size; + int number_of_vars_in_epoch=3; + int epoch_size_bytes=sizeof(double)*number_of_vars_in_epoch; + std::ifstream tmpfile( d_dump_filename.c_str(), std::ios::binary | std::ios::ate); + if (tmpfile.is_open()) + { + size = tmpfile.tellg(); + long int nepoch=size / epoch_size_bytes; + return nepoch; + }else{ + return 0; + } +} + +bool tlm_dump_reader::open_obs_file(std::string out_file) { + if (d_dump_file.is_open() == false) + { + try + { + d_dump_filename=out_file; + d_dump_file.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); + d_dump_file.open(d_dump_filename.c_str(), std::ios::in | std::ios::binary); + std::cout << "TLM dump enabled, Log file: " << d_dump_filename.c_str()<< std::endl; + return true; + } + catch (const std::ifstream::failure & e) + { + std::cout << "Problem opening TLM dump Log file: " << d_dump_filename.c_str()<< std::endl; + return false; + } + }else{ + return false; + } +} + +tlm_dump_reader::~tlm_dump_reader() { + if (d_dump_file.is_open() == true) + { + d_dump_file.close(); + } +} diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/tlm_dump_reader.h b/src/tests/unit-tests/signal-processing-blocks/libs/tlm_dump_reader.h new file mode 100644 index 000000000..0b64d19bf --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/libs/tlm_dump_reader.h @@ -0,0 +1,34 @@ +// +// Created by javier on 23/1/2017. +// + +#ifndef GNSS_SIM_tlm_dump_reader_H +#define GNSS_SIM_tlm_dump_reader_H + +#include +#include +#include +#include + +class tlm_dump_reader { + +public: + ~tlm_dump_reader(); + bool read_binary_obs(); + bool restart(); + long int num_epochs(); + bool open_obs_file(std::string out_file); + + //telemetry decoder dump variables + double TOW_at_current_symbol; + double Prn_timestamp_ms; + double d_TOW_at_Preamble; + +private: + + std::string d_dump_filename; + std::ifstream d_dump_file; + +}; + +#endif //GNSS_SIM_tlm_dump_reader_H diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/tracking_dump_reader.cc b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_dump_reader.cc new file mode 100644 index 000000000..90b46b048 --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_dump_reader.cc @@ -0,0 +1,93 @@ +// +// Created by javier on 1/2/2017. +// + +#include "tracking_dump_reader.h" + +bool tracking_dump_reader::read_binary_obs() + { + try { + d_dump_file.read((char *) &abs_E, sizeof(float)); + d_dump_file.read((char *) &abs_P, sizeof(float)); + d_dump_file.read((char *) &abs_L, sizeof(float)); + d_dump_file.read((char *) &prompt_I, sizeof(float)); + d_dump_file.read((char *) &prompt_Q, sizeof(float)); + + d_dump_file.read((char *) &PRN_start_sample_count, sizeof(unsigned long int)); + + d_dump_file.read((char *) &acc_carrier_phase_rad, sizeof(double)); + d_dump_file.read((char *) &carrier_doppler_hz, sizeof(double)); + d_dump_file.read((char *) &code_freq_chips, sizeof(double)); + d_dump_file.read((char *) &carr_error_hz, sizeof(double)); + d_dump_file.read((char *) &carr_error_filt_hz, sizeof(double)); + d_dump_file.read((char *) &code_error_chips, sizeof(double)); + d_dump_file.read((char *) &code_error_filt_chips, sizeof(double)); + d_dump_file.read((char *) &CN0_SNV_dB_Hz, sizeof(double)); + d_dump_file.read((char *) &carrier_lock_test, sizeof(double)); + d_dump_file.read((char *) &aux1, sizeof(double)); + d_dump_file.read((char *) &aux2, sizeof(double)); + + } + catch (const std::ifstream::failure &e) { + return false; + } + return true; + } + +bool tracking_dump_reader::restart() { + if (d_dump_file.is_open()) + { + d_dump_file.clear(); + d_dump_file.seekg(0, std::ios::beg); + return true; + }else{ + return false; + } +} + +long int tracking_dump_reader::num_epochs() +{ + std::ifstream::pos_type size; + int number_of_double_vars=11; + int number_of_float_vars=5; + int epoch_size_bytes=sizeof(unsigned long int)+ + sizeof(double)*number_of_double_vars+ + sizeof(float)*number_of_float_vars; + std::ifstream tmpfile( d_dump_filename.c_str(), std::ios::binary | std::ios::ate); + if (tmpfile.is_open()) + { + size = tmpfile.tellg(); + long int nepoch=size / epoch_size_bytes; + return nepoch; + }else{ + return 0; + } +} + +bool tracking_dump_reader::open_obs_file(std::string out_file) { + if (d_dump_file.is_open() == false) + { + try + { + d_dump_filename=out_file; + d_dump_file.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); + d_dump_file.open(d_dump_filename.c_str(), std::ios::in | std::ios::binary); + std::cout << "Tracking dump enabled, Log file: " << d_dump_filename.c_str()<< std::endl; + return true; + } + catch (const std::ifstream::failure & e) + { + std::cout << "Problem opening Tracking dump Log file: " << d_dump_filename.c_str()<< std::endl; + return false; + } + }else{ + return false; + } +} + +tracking_dump_reader::~tracking_dump_reader() { + if (d_dump_file.is_open() == true) + { + d_dump_file.close(); + } +} diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/tracking_dump_reader.h b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_dump_reader.h new file mode 100644 index 000000000..a72315ce9 --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_dump_reader.h @@ -0,0 +1,63 @@ +// +// Created by javier on 23/1/2017. +// + +#ifndef GNSS_SIM_tracking_dump_reader_H +#define GNSS_SIM_tracking_dump_reader_H + +#include +#include +#include +#include + +class tracking_dump_reader { + +public: + ~tracking_dump_reader(); + bool read_binary_obs(); + bool restart(); + long int num_epochs(); + bool open_obs_file(std::string out_file); + + //tracking dump variables + // EPR + float abs_E; + float abs_P; + float abs_L; + // PROMPT I and Q (to analyze navigation symbols) + float prompt_I; + float prompt_Q; + // PRN start sample stamp + unsigned long int PRN_start_sample_count; + + // accumulated carrier phase + double acc_carrier_phase_rad; + + // carrier and code frequency + double carrier_doppler_hz; + double code_freq_chips; + + // PLL commands + double carr_error_hz; + double carr_error_filt_hz; + + // DLL commands + double code_error_chips; + double code_error_filt_chips; + + // CN0 and carrier lock test + double CN0_SNV_dB_Hz; + double carrier_lock_test; + + // AUX vars (for debug purposes) + double aux1; + double aux2; + +private: + + std::string d_dump_filename; + std::ifstream d_dump_file; + +}; + +#endif //GNSS_SIM_tracking_dump_reader_H diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/tracking_obs_reader.h b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_obs_reader.h deleted file mode 100644 index c07f539ad..000000000 --- a/src/tests/unit-tests/signal-processing-blocks/libs/tracking_obs_reader.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by javier on 23/1/2017. -// - -#ifndef GNSS_SIM_tracking_obs_reader_H -#define GNSS_SIM_tracking_obs_reader_H - -#include -#include -#include -#include - -class tracking_obs_reader { - -public: - ~tracking_obs_reader(); - bool read_binary_obs(double &signal_timestamp_s, - double &acc_carrier_phase_cycles, - double &doppler_l1_hz, - double &prn_delay_chips, - double &tow); - bool restart(); - bool open_obs_file(std::string out_file); - bool d_dump; - -private: - - std::string d_dump_filename; - std::ifstream d_dump_file; - -}; - -#endif //GNSS_SIM_tracking_obs_reader_H diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/tracking_obs_reader.cc b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.cc similarity index 57% rename from src/tests/unit-tests/signal-processing-blocks/libs/tracking_obs_reader.cc rename to src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.cc index 648c0fd81..cc843e70b 100644 --- a/src/tests/unit-tests/signal-processing-blocks/libs/tracking_obs_reader.cc +++ b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.cc @@ -2,13 +2,9 @@ // Created by javier on 1/2/2017. // -#include "tracking_obs_reader.h" +#include "tracking_true_obs_reader.h" -bool tracking_obs_reader::read_binary_obs(double &signal_timestamp_s, - double &acc_carrier_phase_cycles, - double &doppler_l1_hz, - double &prn_delay_chips, - double &tow) +bool tracking_true_obs_reader::read_binary_obs() { try { d_dump_file.read((char *) &signal_timestamp_s, sizeof(double)); @@ -18,17 +14,39 @@ bool tracking_obs_reader::read_binary_obs(double &signal_timestamp_s, d_dump_file.read((char *) &tow, sizeof(double)); } catch (const std::ifstream::failure &e) { - std::cout << "Exception writing tracking obs dump file " << e.what() << std::endl; + return false; } return true; } -bool tracking_obs_reader::restart() { - d_dump_file.clear(); - d_dump_file.seekg(0, std::ios::beg); +bool tracking_true_obs_reader::restart() { + if (d_dump_file.is_open()) + { + d_dump_file.clear(); + d_dump_file.seekg(0, std::ios::beg); + return true; + }else{ + return false; + } } -bool tracking_obs_reader::open_obs_file(std::string out_file) { +long int tracking_true_obs_reader::num_epochs() +{ + std::ifstream::pos_type size; + int number_of_vars_in_epoch=5; + int epoch_size_bytes=sizeof(double)*number_of_vars_in_epoch; + std::ifstream tmpfile( d_dump_filename.c_str(), std::ios::binary | std::ios::ate); + if (tmpfile.is_open()) + { + size = tmpfile.tellg(); + long int nepoch=size / epoch_size_bytes; + return nepoch; + }else{ + return 0; + } +} + +bool tracking_true_obs_reader::open_obs_file(std::string out_file) { if (d_dump_file.is_open() == false) { try @@ -49,7 +67,7 @@ bool tracking_obs_reader::open_obs_file(std::string out_file) { } } -tracking_obs_reader::~tracking_obs_reader() { +tracking_true_obs_reader::~tracking_true_obs_reader() { if (d_dump_file.is_open() == true) { d_dump_file.close(); diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.h b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.h new file mode 100644 index 000000000..de4664896 --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.h @@ -0,0 +1,36 @@ +// +// Created by javier on 23/1/2017. +// + +#ifndef GNSS_SIM_tracking_true_obs_reader_H +#define GNSS_SIM_tracking_true_obs_reader_H + +#include +#include +#include +#include + +class tracking_true_obs_reader { + +public: + ~tracking_true_obs_reader(); + bool read_binary_obs(); + bool restart(); + long int num_epochs(); + bool open_obs_file(std::string out_file); + bool d_dump; + + double signal_timestamp_s; + double acc_carrier_phase_cycles; + double doppler_l1_hz; + double prn_delay_chips; + double tow; + +private: + + std::string d_dump_filename; + std::ifstream d_dump_file; + +}; + +#endif //GNSS_SIM_tracking_true_obs_reader_H diff --git a/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc b/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc index 58cddb901..ab1d8f68f 100644 --- a/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc @@ -31,8 +31,16 @@ */ +#include +#include #include #include +#include +#include +#include +#include +#include +#include #include #include #include @@ -42,6 +50,8 @@ #include #include #include + +#include "GPS_L1_CA.h" #include "gnss_block_factory.h" #include "gnss_block_interface.h" #include "tracking_interface.h" @@ -50,9 +60,24 @@ #include "gnss_sdr_valve.h" #include "gnss_synchro.h" #include "gps_l1_ca_telemetry_decoder.h" + +#include "../libs/tracking_true_obs_reader.h" +#include "../libs/tracking_dump_reader.h" +#include "../libs/tlm_dump_reader.h" + #include "gps_l1_ca_dll_pll_tracking.h" #include "gps_l1_ca_dll_pll_c_aid_tracking.h" -#include "tracking_obs_reader.h" + +DEFINE_string(generator_binary, std::string(SW_GENERATOR_BIN), "Path of software-defined signal generator binary"); +DEFINE_string(rinex_nav_file, std::string(DEFAULT_RINEX_NAV), "Input RINEX navigation file"); +DEFINE_int32(duration, 20, "Duration of the experiment [in seconds]"); +DEFINE_int32(fs_gen_hz, 2600000, "Samppling frequency [Hz]"); +DEFINE_string(static_position, "30.286502,120.032669,100", "Static receiver position [log,lat,height]"); +DEFINE_string(dynamic_position, "", "Observer positions file, in .csv or .nmea format"); +DEFINE_string(filename_rinex_obs, "sim.16o", "Filename of output RINEX navigation file"); +DEFINE_string(filename_raw_data, "signal_out.bin", "Filename of output raw data file"); +DEFINE_int32(test_satellite_PRN,1, "PRN of the satellite under test (must be visible during the observation time)"); + // ######## GNURADIO BLOCK MESSAGE RECEVER FOR TRACKING MESSAGES ######### class GpsL1CADllPllTelemetryDecoderTest_msg_rx; @@ -164,7 +189,28 @@ GpsL1CADllPllTelemetryDecoderTest_tlm_msg_rx::~GpsL1CADllPllTelemetryDecoderTest class GpsL1CATelemetryDecoderTest: public ::testing::Test { -protected: + +public: + std::string generator_binary; + std::string p1; + std::string p2; + std::string p3; + std::string p4; + std::string p5; + + const int baseband_sampling_freq = FLAGS_fs_gen_hz; + + std::string filename_rinex_obs = FLAGS_filename_rinex_obs; + std::string filename_raw_data = FLAGS_filename_raw_data; + std::string generated_rinex_obs; + + int configure_generator(); + int generate_signal(); + void check_results(arma::vec true_time_s, + arma::vec true_value, + arma::vec meas_time_s, + arma::vec meas_value); + GpsL1CATelemetryDecoderTest() { factory = std::make_shared(); @@ -176,7 +222,7 @@ protected: ~GpsL1CATelemetryDecoderTest() {} - void init(); + void configure_receiver(); gr::msg_queue::sptr queue; gr::top_block_sptr top_block; @@ -186,16 +232,59 @@ protected: size_t item_size; }; +int GpsL1CATelemetryDecoderTest::configure_generator() +{ + // Configure signal generator + generator_binary = FLAGS_generator_binary; -void GpsL1CATelemetryDecoderTest::init() + 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(FLAGS_duration * 10); + } + 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] + return 0; +} + + +int GpsL1CATelemetryDecoderTest::generate_signal() +{ + int child_status; + + char *const parmList[] = { &generator_binary[0], &generator_binary[0], &p1[0], &p2[0], &p3[0], &p4[0], &p5[0], NULL }; + + int pid; + if ((pid = fork()) == -1) + perror("fork err"); + else if (pid == 0) + { + execv(&generator_binary[0], parmList); + std::cout << "Return not expected. Must be an execv err." << std::endl; + std::terminate(); + } + + waitpid(pid, &child_status, 0); + + std::cout << "Signal and Observables RINEX and RAW files created." << std::endl; + return 0; +} + + +void GpsL1CATelemetryDecoderTest::configure_receiver() { gnss_synchro.Channel_ID = 0; gnss_synchro.System = 'G'; std::string signal = "1C"; signal.copy(gnss_synchro.Signal, 2, 0); - gnss_synchro.PRN = 1; + gnss_synchro.PRN = FLAGS_test_satellite_PRN; - config->set_property("GNSS-SDR.internal_fs_hz", "2600000"); + config->set_property("GNSS-SDR.internal_fs_hz", std::to_string(baseband_sampling_freq)); // Set Tracking config->set_property("Tracking_1C.item_type", "gr_complex"); @@ -211,21 +300,57 @@ void GpsL1CATelemetryDecoderTest::init() } +void GpsL1CATelemetryDecoderTest::check_results(arma::vec true_time_s, + arma::vec true_value, + arma::vec meas_time_s, + arma::vec meas_value) +{ + //1. True value interpolation to match the measurement times + + arma::vec true_value_interp; + arma::interp1(true_time_s,true_value,meas_time_s,true_value_interp); + + //2. RMSE + arma::vec err; + + err=meas_value-true_value_interp; + arma::vec err2=arma::square(err); + double rmse=sqrt(arma::mean(err2)); + + //3. Mean err and variance + double error_mean=arma::mean(err); + double error_var=arma::var(err); + + //4. report + + std::cout<< std::setprecision(10)<<"Telemetry reported TOW RMSE="< msg_rx = GpsL1CADllPllTelemetryDecoderTest_msg_rx_make(); - gnss_synchro.Acq_delay_samples = (1023-994.622/1023)*fs_in*1e-3; - gnss_synchro.Acq_doppler_hz = -2583.86; + // load acquisition data based on the first epoch of the true observations + ASSERT_NO_THROW({ + if (true_obs_data.read_binary_obs()==false) + { + throw std::exception(); + }; + })<< "Failure reading true observables file" << std::endl; + + //restart the epoch counter + true_obs_data.restart(); + + std::cout<<"Initial Doppler [Hz]="< valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue); 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, valve, 0); top_block->connect(gr_interleaved_char_to_complex, 0, tracking->get_left_block(), 0); top_block->connect(tracking->get_right_block(), 0, tlm->get_left_block(), 0); top_block->connect(tlm->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." << std::endl; + }) << "Failure connecting the blocks." << std::endl; tracking->start_tracking(); @@ -286,7 +420,63 @@ TEST_F(GpsL1CATelemetryDecoderTest, ValidationOfResults) end = tv.tv_sec *1000000 + tv.tv_usec; }) << "Failure running the top_block." << std::endl; - // TODO: Verify tracking results - std::cout << "Signal tracking completed in " << (end - begin) << " microseconds" << std::endl; + //check results + //load the true values + long int nepoch =true_obs_data.num_epochs(); + std::cout<<"True observation epochs="< Date: Thu, 2 Feb 2017 18:10:24 +0100 Subject: [PATCH 2/2] Completing tracking unit test with simulator-in-the-loop --- .../gps_l1_ca_telemetry_decoder_test.cc | 13 +- .../gps_l1_ca_dll_pll_tracking_test.cc | 322 +++++++++++++++++- 2 files changed, 313 insertions(+), 22 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc b/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc index ab1d8f68f..4798b861e 100644 --- a/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -57,7 +56,6 @@ #include "tracking_interface.h" #include "telemetry_decoder_interface.h" #include "in_memory_configuration.h" -#include "gnss_sdr_valve.h" #include "gnss_synchro.h" #include "gps_l1_ca_telemetry_decoder.h" @@ -202,7 +200,6 @@ public: std::string filename_rinex_obs = FLAGS_filename_rinex_obs; std::string filename_raw_data = FLAGS_filename_raw_data; - std::string generated_rinex_obs; int configure_generator(); int generate_signal(); @@ -321,9 +318,15 @@ void GpsL1CATelemetryDecoderTest::check_results(arma::vec true_time_s, double error_mean=arma::mean(err); double error_var=arma::var(err); - //4. report + // 4. Peaks + double max_error=arma::max(err); + double min_error=arma::min(err); - std::cout<< std::setprecision(10)<<"Telemetry reported TOW RMSE="< #include +#include +#include #include #include #include @@ -42,14 +44,28 @@ #include #include #include +#include "GPS_L1_CA.h" #include "gnss_block_factory.h" #include "gnss_block_interface.h" #include "tracking_interface.h" #include "in_memory_configuration.h" -#include "gnss_sdr_valve.h" #include "gnss_synchro.h" #include "gps_l1_ca_dll_pll_tracking.h" + +#include "../libs/tracking_true_obs_reader.h" +#include "../libs/tracking_dump_reader.h" + +DECLARE_string(generator_binary); +DECLARE_string(rinex_nav_file); +DECLARE_int32(duration); +DECLARE_int32(fs_gen_hz); +DECLARE_string(static_position); +DECLARE_string(dynamic_position); +DECLARE_string(filename_rinex_obs); +DECLARE_string(filename_raw_data); +DECLARE_int32(test_satellite_PRN); + // ######## GNURADIO BLOCK MESSAGE RECEVER ######### class GpsL1CADllPllTrackingTest_msg_rx; @@ -106,7 +122,35 @@ GpsL1CADllPllTrackingTest_msg_rx::~GpsL1CADllPllTrackingTest_msg_rx() class GpsL1CADllPllTrackingTest: public ::testing::Test { -protected: + +public: + std::string generator_binary; + std::string p1; + std::string p2; + std::string p3; + std::string p4; + std::string p5; + + const int baseband_sampling_freq = FLAGS_fs_gen_hz; + + std::string filename_rinex_obs = FLAGS_filename_rinex_obs; + std::string filename_raw_data = FLAGS_filename_raw_data; + + int configure_generator(); + int generate_signal(); + void check_results_doppler(arma::vec true_time_s, + arma::vec true_value, + arma::vec meas_time_s, + arma::vec meas_value); + void check_results_acc_carrier_phase(arma::vec true_time_s, + arma::vec true_value, + arma::vec meas_time_s, + arma::vec meas_value); + void check_results_codephase(arma::vec true_time_s, + arma::vec true_value, + arma::vec meas_time_s, + arma::vec meas_value); + GpsL1CADllPllTrackingTest() { factory = std::make_shared(); @@ -118,7 +162,7 @@ protected: ~GpsL1CADllPllTrackingTest() {} - void init(); + void configure_receiver(); gr::msg_queue::sptr queue; gr::top_block_sptr top_block; @@ -129,15 +173,59 @@ protected: }; -void GpsL1CADllPllTrackingTest::init() +int GpsL1CADllPllTrackingTest::configure_generator() +{ + // Configure signal generator + generator_binary = FLAGS_generator_binary; + + 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(FLAGS_duration * 10); + } + 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] + return 0; +} + + +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], NULL }; + + int pid; + if ((pid = fork()) == -1) + perror("fork err"); + else if (pid == 0) + { + execv(&generator_binary[0], parmList); + std::cout << "Return not expected. Must be an execv err." << std::endl; + std::terminate(); + } + + waitpid(pid, &child_status, 0); + + std::cout << "Signal and Observables RINEX and RAW files created." << std::endl; + return 0; +} + + +void GpsL1CADllPllTrackingTest::configure_receiver() { gnss_synchro.Channel_ID = 0; gnss_synchro.System = 'G'; std::string signal = "1C"; signal.copy(gnss_synchro.Signal, 2, 0); - gnss_synchro.PRN = 1; + gnss_synchro.PRN = FLAGS_test_satellite_PRN; - config->set_property("GNSS-SDR.internal_fs_hz", "2600000"); + config->set_property("GNSS-SDR.internal_fs_hz", std::to_string(baseband_sampling_freq)); // Set Tracking config->set_property("Tracking_1C.implementation", "GPS_L1_CA_DLL_PLL_Tracking"); config->set_property("Tracking_1C.item_type", "gr_complex"); @@ -145,26 +233,158 @@ void GpsL1CADllPllTrackingTest::init() config->set_property("Tracking_1C.dump", "true"); config->set_property("Tracking_1C.dump_filename", "./tracking_ch_"); config->set_property("Tracking_1C.pll_bw_hz", "30.0"); - config->set_property("Tracking_1C.dll_bw_hz", "4.0"); + config->set_property("Tracking_1C.dll_bw_hz", "2.0"); config->set_property("Tracking_1C.early_late_space_chips", "0.5"); } +void GpsL1CADllPllTrackingTest::check_results_doppler(arma::vec true_time_s, + arma::vec true_value, + arma::vec meas_time_s, + arma::vec meas_value) +{ + //1. True value interpolation to match the measurement times + + arma::vec true_value_interp; + arma::interp1(true_time_s,true_value,meas_time_s,true_value_interp); + + //2. RMSE + arma::vec err; + + err=meas_value-true_value_interp; + arma::vec err2=arma::square(err); + double rmse=sqrt(arma::mean(err2)); + + //3. Mean err and variance + double error_mean=arma::mean(err); + double error_var=arma::var(err); + + // 5. Peaks + double max_error=arma::max(err); + double min_error=arma::min(err); + + //5. report + + std::cout<< std::setprecision(10)<<"TRK Doppler RMSE="< tracking = std::make_shared(config.get(), "Tracking_1C", 1, 1); + //std::shared_ptr tracking = std::make_shared(config.get(), "Tracking_1C", 1, 1); + boost::shared_ptr msg_rx = GpsL1CADllPllTrackingTest_msg_rx_make(); - gnss_synchro.Acq_delay_samples = (1023-994.622/1023)*fs_in*1e-3; - gnss_synchro.Acq_doppler_hz = -2583.86; + // load acquisition data based on the first epoch of the true observations + ASSERT_NO_THROW({ + if (true_obs_data.read_binary_obs()==false) + { + throw std::exception(); + }; + })<< "Failure reading true observables file" << std::endl; + + //restart the epoch counter + true_obs_data.restart(); + + std::cout<<"Initial Doppler [Hz]="< valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue); 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, valve, 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")); @@ -204,7 +421,78 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults) end = tv.tv_sec *1000000 + tv.tv_usec; }) << "Failure running the top_block." << std::endl; - // TODO: Verify tracking results + //check results + //load the true values + long int nepoch =true_obs_data.num_epochs(); + std::cout<<"True observation epochs="<