diff --git a/README.md b/README.md index fcb3fdd6e..9fe634565 100644 --- a/README.md +++ b/README.md @@ -6,20 +6,20 @@ This program is a software-defined receiver which is able to process (that is, to perform detection, synchronization, demodulation and decoding of the navigation message, computation of observables and, finally, computation of position fixes) the following Global Navigation Satellite System's signals: -In the L1 band (centered at 1575.42 MHz): - - 🛰 GPS L1 C/A :white_check_mark: - - 🛰 Galileo E1b/c :white_check_mark: - - 🛰 GLONASS L1 C/A :white_check_mark: +In the L1 band: + - 🛰 GPS L1 C/A (centered at 1575.42 MHz) :white_check_mark: + - 🛰 Galileo E1b/c (centered at 1575.42 MHz) :white_check_mark: + - 🛰 GLONASS L1 C/A (centered at 1601.72 MHz) :white_check_mark: -In the L2 band (centered at 1227.60 MHz): - - 🛰 GPS L2C :white_check_mark: - - 🛰 GLONASS L2 C/A :white_check_mark: +In the L2 band: + - 🛰 GPS L2C (centered at 1227.60 MHz) :white_check_mark: + - 🛰 GLONASS L2 C/A (centered at 1246 MHz) :white_check_mark: -In the L5 band (centered at 1176.45 MHz): - - 🛰 GPS L5 :white_check_mark: - - 🛰 Galileo E5a :white_check_mark: +In the L5 band: + - 🛰 GPS L5 (centered at 1176.45 MHz) :white_check_mark: + - 🛰 Galileo E5a (centered at 1176.45 MHz) :white_check_mark: -GNSS-SDR provides interfaces for a wide range of radio frequency front-ends, generates processing outputs in standard formats, allows for the full inspection of the whole signal processing chain, and offers a framework for the development of new features. Please visit [https://gnss-sdr.org](https://gnss-sdr.org "GNSS-SDR website") for more information about this open source software-defined GNSS receiver. +GNSS-SDR provides interfaces for a wide range of radio frequency front-ends and raw sample file formats, generates processing outputs in standard formats, allows for the full inspection of the whole signal processing chain, and offers a framework for the development of new features. Please visit [https://gnss-sdr.org](https://gnss-sdr.org "GNSS-SDR website") for more information about this open source software-defined GNSS receiver. diff --git a/src/algorithms/acquisition/CMakeLists.txt b/src/algorithms/acquisition/CMakeLists.txt index 0dc31ec9b..96259341c 100644 --- a/src/algorithms/acquisition/CMakeLists.txt +++ b/src/algorithms/acquisition/CMakeLists.txt @@ -18,7 +18,4 @@ add_subdirectory(adapters) add_subdirectory(gnuradio_blocks) -if(ENABLE_FPGA) - add_subdirectory(libs) -endif(ENABLE_FPGA) - +add_subdirectory(libs) diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index 831601796..82b4b33c1 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -65,4 +65,4 @@ file(GLOB ACQ_ADAPTER_HEADERS "*.h") list(SORT ACQ_ADAPTER_HEADERS) add_library(acq_adapters ${ACQ_ADAPTER_SOURCES} ${ACQ_ADAPTER_HEADERS}) source_group(Headers FILES ${ACQ_ADAPTER_HEADERS}) -target_link_libraries(acq_adapters gnss_sp_libs gnss_sdr_flags acq_gr_blocks ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES}) +target_link_libraries(acq_adapters acquisition_lib gnss_sp_libs gnss_sdr_flags acq_gr_blocks ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES}) diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc index 755d8e48e..a9f96da43 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc @@ -34,6 +34,7 @@ #include "galileo_e1_signal_processing.h" #include "Galileo_E1.h" #include "gnss_sdr_flags.h" +#include "acq_conf.h" #include #include #include @@ -45,7 +46,7 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - pcpsconf_t acq_parameters; + Acq_Conf acq_parameters; configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./data/acquisition.dat"; diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc index 82bbb896e..16142eab9 100644 --- a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc @@ -33,6 +33,7 @@ #include "galileo_e5_signal_processing.h" #include "Galileo_E5a.h" #include "gnss_sdr_flags.h" +#include "acq_conf.h" #include #include #include @@ -44,7 +45,7 @@ using google::LogMessage; GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - pcpsconf_t acq_parameters; + Acq_Conf acq_parameters = Acq_Conf(); configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "../data/acquisition.dat"; diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc index 90370eef4..c49f1f0c4 100644 --- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc @@ -35,6 +35,7 @@ #include "configuration_interface.h" #include "glonass_l1_signal_processing.h" #include "gnss_sdr_flags.h" +#include "acq_conf.h" #include "GLONASS_L1_L2_CA.h" #include #include @@ -46,7 +47,7 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - pcpsconf_t acq_parameters; + Acq_Conf acq_parameters = Acq_Conf(); configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./data/acquisition.dat"; diff --git a/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc index de9a28bb5..ec17ad911 100644 --- a/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc @@ -35,6 +35,7 @@ #include "glonass_l2_signal_processing.h" #include "GLONASS_L1_L2_CA.h" #include "gnss_sdr_flags.h" +#include "acq_conf.h" #include #include @@ -45,7 +46,7 @@ GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - pcpsconf_t acq_parameters; + Acq_Conf acq_parameters = Acq_Conf(); configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./data/acquisition.dat"; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc index d319cc46f..45a8d743c 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc @@ -38,6 +38,7 @@ #include "gps_sdr_signal_processing.h" #include "GPS_L1_CA.h" #include "gnss_sdr_flags.h" +#include "acq_conf.h" #include #include @@ -48,7 +49,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - pcpsconf_t acq_parameters; + Acq_Conf acq_parameters = Acq_Conf(); configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./data/acquisition.dat"; diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc index a1c97a9a2..bb185c92c 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc @@ -36,6 +36,7 @@ #include "gps_l2c_signal.h" #include "GPS_L2C.h" #include "gnss_sdr_flags.h" +#include "acq_conf.h" #include #include @@ -46,7 +47,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - pcpsconf_t acq_parameters; + Acq_Conf acq_parameters = Acq_Conf(); configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./data/acquisition.dat"; diff --git a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc index d41824d94..4595bd2e2 100644 --- a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc @@ -36,6 +36,7 @@ #include "gps_l5_signal.h" #include "GPS_L5.h" #include "gnss_sdr_flags.h" +#include "acq_conf.h" #include #include @@ -46,7 +47,7 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - pcpsconf_t acq_parameters; + Acq_Conf acq_parameters = Acq_Conf(); configuration_ = configuration; std::string default_item_type = "gr_complex"; std::string default_dump_filename = "./data/acquisition.dat"; diff --git a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt index fbc33410e..50fc61ae9 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt @@ -26,12 +26,12 @@ set(ACQ_GR_BLOCKS_SOURCES pcps_quicksync_acquisition_cc.cc galileo_pcps_8ms_acquisition_cc.cc galileo_e5a_noncoherent_iq_acquisition_caf_cc.cc -) +) if(ENABLE_FPGA) set(ACQ_GR_BLOCKS_SOURCES ${ACQ_GR_BLOCKS_SOURCES} pcps_acquisition_fpga.cc) endif(ENABLE_FPGA) - + if(OPENCL_FOUND) set(ACQ_GR_BLOCKS_SOURCES ${ACQ_GR_BLOCKS_SOURCES} pcps_opencl_acquisition_cc.cc) endif(OPENCL_FOUND) @@ -64,7 +64,7 @@ endif(OPENCL_FOUND) file(GLOB ACQ_GR_BLOCKS_HEADERS "*.h") list(SORT ACQ_GR_BLOCKS_HEADERS) add_library(acq_gr_blocks ${ACQ_GR_BLOCKS_SOURCES} ${ACQ_GR_BLOCKS_HEADERS}) -source_group(Headers FILES ${ACQ_GR_BLOCKS_HEADERS}) +source_group(Headers FILES ${ACQ_GR_BLOCKS_HEADERS}) if(ENABLE_FPGA) target_link_libraries(acq_gr_blocks acquisition_lib gnss_sp_libs gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${OPT_LIBRARIES} ${OPT_ACQUISITION_LIBRARIES}) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc index 4ac53ab41..f16855790 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc @@ -45,21 +45,22 @@ using google::LogMessage; -pcps_acquisition_sptr pcps_make_acquisition(pcpsconf_t conf_) +pcps_acquisition_sptr pcps_make_acquisition(const Acq_Conf& conf_) { return pcps_acquisition_sptr(new pcps_acquisition(conf_)); } -pcps_acquisition::pcps_acquisition(pcpsconf_t conf_) : gr::block("pcps_acquisition", - gr::io_signature::make(1, 1, conf_.it_size * conf_.sampled_ms * conf_.samples_per_ms * (conf_.bit_transition_flag ? 2 : 1)), - gr::io_signature::make(0, 0, conf_.it_size * conf_.sampled_ms * conf_.samples_per_ms * (conf_.bit_transition_flag ? 2 : 1))) +pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acquisition", + gr::io_signature::make(1, 1, conf_.it_size * conf_.sampled_ms * conf_.samples_per_ms * (conf_.bit_transition_flag ? 2 : 1)), + gr::io_signature::make(0, 0, conf_.it_size * conf_.sampled_ms * conf_.samples_per_ms * (conf_.bit_transition_flag ? 2 : 1))) { this->message_port_register_out(pmt::mp("events")); 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; @@ -121,6 +122,7 @@ pcps_acquisition::pcps_acquisition(pcpsconf_t conf_) : gr::block("pcps_acquisiti } grid_ = arma::fmat(); d_step_two = false; + d_dump_number = 0; } @@ -335,6 +337,81 @@ void pcps_acquisition::send_negative_acquisition() } +void pcps_acquisition::dump_results(int effective_fft_size) +{ + d_dump_number++; + 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("_ch_"); + filename.append(std::to_string(d_channel)); + filename.append("_"); + filename.append(std::to_string(d_dump_number)); + 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); + + 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); + } +} + + void pcps_acquisition::acquisition_core(unsigned long int samp_count) { gr::thread::scoped_lock lk(d_setlock); @@ -342,7 +419,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) // initialize acquisition algorithm uint32_t indext = 0; float magt = 0.0; - const gr_complex* in = d_data_buffer; //Get the input samples pointer + const gr_complex* in = d_data_buffer; // Get the input samples pointer int effective_fft_size = (acq_parameters.bit_transition_flag ? d_fft_size / 2 : d_fft_size); if (d_cshort) { @@ -436,43 +513,6 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count) 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); - } - } } } } @@ -538,6 +578,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) + { + memcpy(grid_.colptr(doppler_index), d_magnitude, sizeof(float) * effective_fft_size); + } } } lk.lock(); @@ -553,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 { @@ -564,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) @@ -586,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 { @@ -597,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 @@ -607,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 4c4dab929..d34888fd8 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h @@ -53,38 +53,20 @@ #define GNSS_SDR_PCPS_ACQUISITION_H_ #include "gnss_synchro.h" +#include "acq_conf.h" #include #include #include #include #include -typedef struct -{ - /* pcps acquisition configuration */ - unsigned int sampled_ms; - unsigned int max_dwells; - unsigned int doppler_max; - unsigned int num_doppler_bins_step2; - float doppler_step2; - long fs_in; - int samples_per_ms; - int samples_per_code; - bool bit_transition_flag; - bool use_CFAR_algorithm_flag; - bool dump; - bool blocking; - bool make_2_steps; - std::string dump_filename; - size_t it_size; -} pcpsconf_t; class pcps_acquisition; typedef boost::shared_ptr pcps_acquisition_sptr; pcps_acquisition_sptr -pcps_make_acquisition(pcpsconf_t conf_); +pcps_make_acquisition(const Acq_Conf& conf_); /*! * \brief This class implements a Parallel Code Phase Search Acquisition. @@ -96,9 +78,9 @@ class pcps_acquisition : public gr::block { private: friend pcps_acquisition_sptr - pcps_make_acquisition(pcpsconf_t conf_); + pcps_make_acquisition(const Acq_Conf& conf_); - pcps_acquisition(pcpsconf_t conf_); + pcps_acquisition(const Acq_Conf& conf_); void update_local_carrier(gr_complex* carrier_vector, int correlator_length_samples, float freq); void update_grid_doppler_wipeoffs(); @@ -111,11 +93,14 @@ private: void send_positive_acquisition(); - pcpsconf_t acq_parameters; + void dump_results(int effective_fft_size); + + Acq_Conf acq_parameters; bool d_active; 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; @@ -139,6 +124,7 @@ private: gr::fft::fft_complex* d_ifft; Gnss_Synchro* d_gnss_synchro; arma::fmat grid_; + long int d_dump_number; public: ~pcps_acquisition(); diff --git a/src/algorithms/acquisition/libs/CMakeLists.txt b/src/algorithms/acquisition/libs/CMakeLists.txt index 332d83723..05a116e0f 100644 --- a/src/algorithms/acquisition/libs/CMakeLists.txt +++ b/src/algorithms/acquisition/libs/CMakeLists.txt @@ -16,12 +16,9 @@ # along with GNSS-SDR. If not, see . # - -set(ACQUISITION_LIB_SOURCES - fpga_acquisition.cc -) - -include_directories( +if(ENABLE_FPGA) + set(ACQUISITION_LIB_SOURCES fpga_acquisition.cc ) + include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src/core/system_parameters ${CMAKE_SOURCE_DIR}/src/core/interfaces @@ -31,10 +28,16 @@ include_directories( ${GLOG_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS} ${VOLK_GNSSSDR_INCLUDE_DIRS} -) + ) -file(GLOB ACQUISITION_LIB_HEADERS "*.h") + file(GLOB ACQUISITION_LIB_HEADERS "*.h") +endif(ENABLE_FPGA) + +set(ACQUISITION_LIB_HEADERS ${ACQUISITION_LIB_HEADERS} acq_conf.h) list(SORT ACQUISITION_LIB_HEADERS) + +set(ACQUISITION_LIB_SOURCES ${ACQUISITION_LIB_SOURCES} acq_conf.cc) + add_library(acquisition_lib ${ACQUISITION_LIB_SOURCES} ${ACQUISITION_LIB_HEADERS}) source_group(Headers FILES ${ACQUISITION_LIB_HEADERS}) target_link_libraries(acquisition_lib ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES}) @@ -43,4 +46,3 @@ if(VOLK_GNSSSDR_FOUND) else(VOLK_GNSSSDR_FOUND) add_dependencies(acquisition_lib glog-${glog_RELEASE} volk_gnsssdr_module) endif() - diff --git a/src/algorithms/acquisition/libs/acq_conf.cc b/src/algorithms/acquisition/libs/acq_conf.cc new file mode 100644 index 000000000..f403992e4 --- /dev/null +++ b/src/algorithms/acquisition/libs/acq_conf.cc @@ -0,0 +1,52 @@ +/*! + * \file acq_conf.cc + * \brief Class that contains all the configuration parameters for generic + * acquisition block based on the PCPS algoritm. + * \author Carles Fernandez, 2018. cfernandez(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * 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 "acq_conf.h" + +Acq_Conf::Acq_Conf() +{ + /* PCPS acquisition configuration */ + sampled_ms = 0; + max_dwells = 0; + doppler_max = 0; + num_doppler_bins_step2 = 0; + doppler_step2 = 0.0; + fs_in = 0; + samples_per_ms = 0; + samples_per_code = 0; + bit_transition_flag = false; + use_CFAR_algorithm_flag = false; + dump = false; + blocking = false; + make_2_steps = false; + dump_filename = ""; + it_size = sizeof(char); +} diff --git a/src/algorithms/acquisition/libs/acq_conf.h b/src/algorithms/acquisition/libs/acq_conf.h new file mode 100644 index 000000000..422e889bc --- /dev/null +++ b/src/algorithms/acquisition/libs/acq_conf.h @@ -0,0 +1,61 @@ +/*! + * \file acq_conf.cc + * \brief Class that contains all the configuration parameters for generic + * acquisition block based on the PCPS algoritm. + * \author Carles Fernandez, 2018. cfernandez(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * 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 . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_ACQ_CONF_H_ +#define GNSS_SDR_ACQ_CONF_H_ + +#include +#include + +class Acq_Conf +{ +public: + /* PCPS Acquisition configuration */ + unsigned int sampled_ms; + unsigned int max_dwells; + unsigned int doppler_max; + unsigned int num_doppler_bins_step2; + float doppler_step2; + long fs_in; + int samples_per_ms; + int samples_per_code; + bool bit_transition_flag; + bool use_CFAR_algorithm_flag; + bool dump; + bool blocking; + bool make_2_steps; + std::string dump_filename; + size_t it_size; + + Acq_Conf(); +}; + +#endif diff --git a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.cc b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.cc index 61eddf20a..48e821674 100644 --- a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.cc +++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.cc @@ -34,6 +34,7 @@ * ------------------------------------------------------------------------- */ +#include "dll_pll_conf.h" #include "galileo_e1_dll_pll_veml_tracking.h" #include "configuration_interface.h" #include "Galileo_E1.h" @@ -48,7 +49,7 @@ GalileoE1DllPllVemlTracking::GalileoE1DllPllVemlTracking( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - dllpllconf_t trk_param; + Dll_Pll_Conf trk_param = Dll_Pll_Conf(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## std::string default_item_type = "gr_complex"; diff --git a/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking.cc b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking.cc index 8fd0cd955..fe6f4a7d6 100644 --- a/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking.cc +++ b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking.cc @@ -35,7 +35,7 @@ * * ------------------------------------------------------------------------- */ - +#include "dll_pll_conf.h" #include "galileo_e5a_dll_pll_tracking.h" #include "configuration_interface.h" #include "Galileo_E5a.h" @@ -49,7 +49,7 @@ GalileoE5aDllPllTracking::GalileoE5aDllPllTracking( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - dllpllconf_t trk_param; + Dll_Pll_Conf trk_param = Dll_Pll_Conf(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## std::string default_item_type = "gr_complex"; diff --git a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking.cc b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking.cc index 6d6ded849..ffa6e1000 100644 --- a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking.cc +++ b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking.cc @@ -35,7 +35,7 @@ * ------------------------------------------------------------------------- */ - +#include "dll_pll_conf.h" #include "gps_l1_ca_dll_pll_tracking.h" #include "configuration_interface.h" #include "GPS_L1_CA.h" @@ -49,7 +49,7 @@ GpsL1CaDllPllTracking::GpsL1CaDllPllTracking( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - dllpllconf_t trk_param; + Dll_Pll_Conf trk_param = Dll_Pll_Conf(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## std::string default_item_type = "gr_complex"; @@ -108,13 +108,13 @@ GpsL1CaDllPllTracking::GpsL1CaDllPllTracking( int cn0_samples = configuration->property(role + ".cn0_samples", 20); if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples; trk_param.cn0_samples = cn0_samples; - int cn0_min = configuration->property(role + ".cn0_min", 25); + int cn0_min = configuration->property(role + ".cn0_min", 30); if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min; trk_param.cn0_min = cn0_min; int max_lock_fail = configuration->property(role + ".max_lock_fail", 50); if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail; trk_param.max_lock_fail = max_lock_fail; - double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85); + double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.80); if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th; trk_param.carrier_lock_th = carrier_lock_th; diff --git a/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking.cc b/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking.cc index 13374590c..499427dfa 100644 --- a/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking.cc +++ b/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking.cc @@ -34,7 +34,7 @@ * ------------------------------------------------------------------------- */ - +#include "dll_pll_conf.h" #include "gps_l2_m_dll_pll_tracking.h" #include "configuration_interface.h" #include "GPS_L2C.h" @@ -49,7 +49,7 @@ GpsL2MDllPllTracking::GpsL2MDllPllTracking( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - dllpllconf_t trk_param; + Dll_Pll_Conf trk_param = Dll_Pll_Conf(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## std::string default_item_type = "gr_complex"; diff --git a/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking.cc b/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking.cc index 554b1ca41..8fbd56531 100644 --- a/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking.cc +++ b/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking.cc @@ -34,7 +34,7 @@ * ------------------------------------------------------------------------- */ - +#include "dll_pll_conf.h" #include "gps_l5_dll_pll_tracking.h" #include "configuration_interface.h" #include "GPS_L5.h" @@ -49,7 +49,7 @@ GpsL5DllPllTracking::GpsL5DllPllTracking( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - dllpllconf_t trk_param; + Dll_Pll_Conf trk_param = Dll_Pll_Conf(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## std::string default_item_type = "gr_complex"; diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.cc b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.cc index 738e3dd90..bd822c74c 100755 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.cc +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.cc @@ -60,7 +60,7 @@ using google::LogMessage; -dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(dllpllconf_t conf_) +dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(const Dll_Pll_Conf &conf_) { return dll_pll_veml_tracking_sptr(new dll_pll_veml_tracking(conf_)); } @@ -76,8 +76,8 @@ void dll_pll_veml_tracking::forecast(int noutput_items, } -dll_pll_veml_tracking::dll_pll_veml_tracking(dllpllconf_t conf_) : gr::block("dll_pll_veml_tracking", gr::io_signature::make(1, 1, sizeof(gr_complex)), - gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) +dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::block("dll_pll_veml_tracking", gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) { trk_parameters = conf_; // Telemetry bit synchronization message port input diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.h b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.h index 9444c6ccb..0437e8a35 100755 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.h +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking.h @@ -31,6 +31,7 @@ #ifndef GNSS_SDR_DLL_PLL_VEML_TRACKING_H #define GNSS_SDR_DLL_PLL_VEML_TRACKING_H +#include "dll_pll_conf.h" #include "gnss_synchro.h" #include "tracking_2nd_DLL_filter.h" #include "tracking_2nd_PLL_filter.h" @@ -39,37 +40,13 @@ #include #include #include - -typedef struct -{ - /* DLL/PLL tracking configuration */ - double fs_in; - unsigned int vector_length; - bool dump; - std::string dump_filename; - float pll_bw_hz; - float dll_bw_hz; - float pll_bw_narrow_hz; - float dll_bw_narrow_hz; - float early_late_space_chips; - float very_early_late_space_chips; - float early_late_space_narrow_chips; - float very_early_late_space_narrow_chips; - int extend_correlation_symbols; - int cn0_samples; - int cn0_min; - int max_lock_fail; - double carrier_lock_th; - bool track_pilot; - char system; - char signal[3]; -} dllpllconf_t; +#include class dll_pll_veml_tracking; typedef boost::shared_ptr dll_pll_veml_tracking_sptr; -dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(dllpllconf_t conf_); +dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(const Dll_Pll_Conf &conf_); /*! * \brief This class implements a code DLL + carrier PLL tracking block. @@ -89,9 +66,9 @@ public: void forecast(int noutput_items, gr_vector_int &ninput_items_required); private: - friend dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(dllpllconf_t conf_); + friend dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(const Dll_Pll_Conf &conf_); - dll_pll_veml_tracking(dllpllconf_t conf_); + dll_pll_veml_tracking(const Dll_Pll_Conf &conf_); bool cn0_and_tracking_lock_status(double coh_integration_time_s); bool acquire_secondary(); @@ -104,7 +81,7 @@ private: int save_matfile(); // tracking configuration vars - dllpllconf_t trk_parameters; + Dll_Pll_Conf trk_parameters; bool d_veml; bool d_cloop; unsigned int d_channel; @@ -201,6 +178,7 @@ private: // CN0 estimation and lock detector int d_cn0_estimation_counter; int d_carrier_lock_fail_counter; + std::deque d_carrier_lock_detector_queue; double d_carrier_lock_test; double d_CN0_SNV_dB_Hz; double d_carrier_lock_threshold; diff --git a/src/algorithms/tracking/libs/CMakeLists.txt b/src/algorithms/tracking/libs/CMakeLists.txt index 9c5051ea2..fdb35a4e9 100644 --- a/src/algorithms/tracking/libs/CMakeLists.txt +++ b/src/algorithms/tracking/libs/CMakeLists.txt @@ -43,6 +43,7 @@ set(TRACKING_LIB_SOURCES tracking_discriminators.cc tracking_FLL_PLL_filter.cc tracking_loop_filter.cc + dll_pll_conf.cc ) if(ENABLE_FPGA) diff --git a/src/algorithms/tracking/libs/dll_pll_conf.cc b/src/algorithms/tracking/libs/dll_pll_conf.cc new file mode 100644 index 000000000..89c6a1256 --- /dev/null +++ b/src/algorithms/tracking/libs/dll_pll_conf.cc @@ -0,0 +1,61 @@ +/*! + * \file dll_pll_conf.cc + * \brief Class that contains all the configuration parameters for generic + * tracking block based on a DLL and a PLL. + * \author Javier Arribas, 2018. jarribas(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * 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 "dll_pll_conf.h" +#include + +Dll_Pll_Conf::Dll_Pll_Conf() +{ + /* DLL/PLL tracking configuration */ + fs_in = 0.0; + vector_length = 0; + dump = false; + dump_filename = "./dll_pll_dump.dat"; + pll_bw_hz = 40.0; + dll_bw_hz = 2.0; + pll_bw_narrow_hz = 5.0; + dll_bw_narrow_hz = 0.75; + early_late_space_chips = 0.5; + very_early_late_space_chips = 0.5; + early_late_space_narrow_chips = 0.1; + very_early_late_space_narrow_chips = 0.1; + extend_correlation_symbols = 5; + cn0_samples = 20; + carrier_lock_det_mav_samples = 20; + cn0_min = 25; + max_lock_fail = 50; + carrier_lock_th = 0.85; + track_pilot = false; + system = 'G'; + char sig_[3] = "1C"; + std::memcpy(signal, sig_, 3); +} diff --git a/src/algorithms/tracking/libs/dll_pll_conf.h b/src/algorithms/tracking/libs/dll_pll_conf.h new file mode 100644 index 000000000..2cee8c405 --- /dev/null +++ b/src/algorithms/tracking/libs/dll_pll_conf.h @@ -0,0 +1,68 @@ +/*! + * \file dll_pll_conf.h + * \brief Class that contains all the configuration parameters for generic tracking block based on a DLL and a PLL. + * \author Javier Arribas, 2018. jarribas(at)cttc.es + * + * Class that contains all the configuration parameters for generic tracking block based on a DLL and a PLL. + * + * ------------------------------------------------------------------------- + * + * 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 . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_DLL_PLL_CONF_H_ +#define GNSS_SDR_DLL_PLL_CONF_H_ + +#include + +class Dll_Pll_Conf +{ +private: +public: + /* DLL/PLL tracking configuration */ + double fs_in; + unsigned int vector_length; + bool dump; + std::string dump_filename; + float pll_bw_hz; + float dll_bw_hz; + float pll_bw_narrow_hz; + float dll_bw_narrow_hz; + float early_late_space_chips; + float very_early_late_space_chips; + float early_late_space_narrow_chips; + float very_early_late_space_narrow_chips; + int extend_correlation_symbols; + int cn0_samples; + int carrier_lock_det_mav_samples; + int cn0_min; + int max_lock_fail; + double carrier_lock_th; + bool track_pilot; + char system; + char signal[3]; + + Dll_Pll_Conf(); +}; + +#endif diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index 8733ee9ed..ab9589658 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -1304,6 +1304,7 @@ void GNSSFlowgraph::set_channels_state() } DLOG(INFO) << "Channel " << i << " in state " << channels_state_[i]; } + std::lock_guard lock(signal_list_mutex); acq_channels_count_ = max_acq_channels_; DLOG(INFO) << acq_channels_count_ << " channels in acquisition state"; } diff --git a/src/core/receiver/gnss_flowgraph.h b/src/core/receiver/gnss_flowgraph.h index 638b81305..5da90cd1f 100644 --- a/src/core/receiver/gnss_flowgraph.h +++ b/src/core/receiver/gnss_flowgraph.h @@ -107,17 +107,17 @@ public: void set_configuration(std::shared_ptr configuration); - unsigned int applied_actions() + unsigned int applied_actions() const { return applied_actions_; } - bool connected() + bool connected() const { return connected_; } - bool running() + bool running() const { return running_; } diff --git a/src/tests/common-files/gnuplot_i.h b/src/tests/common-files/gnuplot_i.h index 2df3a9c92..67e6fb1f8 100644 --- a/src/tests/common-files/gnuplot_i.h +++ b/src/tests/common-files/gnuplot_i.h @@ -69,7 +69,7 @@ #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) //all UNIX-like OSs (Linux, *BSD, MacOSX, Solaris, ...) #include // for access(), mkstemp() -#define GP_MAX_TMP_FILES 64 +#define GP_MAX_TMP_FILES 1024 #else #error unsupported or unknown operating system #endif @@ -302,9 +302,9 @@ public: /// /// \return <-- reference to the gnuplot object // ----------------------------------------------- - inline Gnuplot &set_multiplot() + inline Gnuplot &set_multiplot(int rows, int cols) { - cmd("set multiplot"); + cmd("set multiplot layout " + std::to_string(rows) + "," + std::to_string(cols)); //+ " rowfirst"); return *this; }; @@ -1906,11 +1906,11 @@ void Gnuplot::init() std::string tmp = Gnuplot::m_sGNUPlotPath + "/" + Gnuplot::m_sGNUPlotFileName; - // FILE *popen(const char *command, const char *mode); - // The popen() function shall execute the command specified by the string - // command, create a pipe between the calling program and the executed - // command, and return a pointer to a stream that can be used to either read - // from or write to the pipe. +// FILE *popen(const char *command, const char *mode); +// The popen() function shall execute the command specified by the string +// command, create a pipe between the calling program and the executed +// command, and return a pointer to a stream that can be used to either read +// from or write to the pipe. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) gnucmd = _popen(tmp.c_str(), "w"); #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) @@ -1974,7 +1974,7 @@ bool Gnuplot::get_program_path() std::list ls; - //split path (one long string) into list ls of strings +//split path (one long string) into list ls of strings #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) stringtok(ls, path_str, ";"); #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) @@ -2018,16 +2018,16 @@ bool Gnuplot::file_exists(const std::string &filename, int mode) return false; } - // int _access(const char *path, int mode); - // returns 0 if the file has the given mode, - // it returns -1 if the named file does not exist or is not accessible in - // the given mode - // mode = 0 (F_OK) (default): checks file for existence only - // mode = 1 (X_OK): execution permission - // mode = 2 (W_OK): write permission - // mode = 4 (R_OK): read permission - // mode = 6 : read and write permission - // mode = 7 : read, write and execution permission +// int _access(const char *path, int mode); +// returns 0 if the file has the given mode, +// it returns -1 if the named file does not exist or is not accessible in +// the given mode +// mode = 0 (F_OK) (default): checks file for existence only +// mode = 1 (X_OK): execution permission +// mode = 2 (W_OK): write permission +// mode = 4 (R_OK): read permission +// mode = 6 : read and write permission +// mode = 7 : read, write and execution permission #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) if (_access(filename.c_str(), mode) == 0) #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) @@ -2089,19 +2089,19 @@ std::string Gnuplot::create_tmpfile(std::ofstream &tmp) throw GnuplotException(except.str()); } - // int mkstemp(char *name); - // shall replace the contents of the string pointed to by "name" by a unique - // filename, and return a file descriptor for the file open for reading and - // writing. Otherwise, -1 shall be returned if no suitable file could be - // created. The string in template should look like a filename with six - // trailing 'X' s; mkstemp() replaces each 'X' with a character from the - // portable filename character set. The characters are chosen such that the - // resulting name does not duplicate the name of an existing file at the - // time of a call to mkstemp() +// int mkstemp(char *name); +// shall replace the contents of the string pointed to by "name" by a unique +// filename, and return a file descriptor for the file open for reading and +// writing. Otherwise, -1 shall be returned if no suitable file could be +// created. The string in template should look like a filename with six +// trailing 'X' s; mkstemp() replaces each 'X' with a character from the +// portable filename character set. The characters are chosen such that the +// resulting name does not duplicate the name of an existing file at the +// time of a call to mkstemp() - // - // open temporary files for output - // +// +// open temporary files for output +// #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) if (_mktemp(name) == NULL) 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 32b6de6e2..063d02837 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,16 +73,51 @@ 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"); + input_power = *static_cast(var2_->data); + Mat_VarFree(var2_); + + var2_ = Mat_VarRead(matfile, "acq_doppler_hz"); + acq_doppler_hz = *static_cast(var2_->data); + Mat_VarFree(var2_); + + var2_ = Mat_VarRead(matfile, "acq_delay_samples"); + acq_delay_samples = *static_cast(var2_->data); + Mat_VarFree(var2_); + + var2_ = Mat_VarRead(matfile, "test_statistic"); + test_statistic = *static_cast(var2_->data); + Mat_VarFree(var2_); + + var2_ = Mat_VarRead(matfile, "threshold"); + threshold = *static_cast(var2_->data); + Mat_VarFree(var2_); + + var2_ = Mat_VarRead(matfile, "sample_counter"); + sample_counter = *static_cast(var2_->data); + Mat_VarFree(var2_); + + var2_ = Mat_VarRead(matfile, "d_positive_acq"); + positive_acq = *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]) / input_power; k++; } } @@ -93,17 +128,30 @@ bool acquisition_dump_reader::read_binary_acq() } -acquisition_dump_reader::acquisition_dump_reader(const std::string& basename, unsigned int sat, unsigned int doppler_max, unsigned int doppler_step, unsigned int samples_per_code) +acquisition_dump_reader::acquisition_dump_reader(const std::string& basename, + unsigned int sat, + unsigned int doppler_max, + unsigned int doppler_step, + unsigned int samples_per_code, + int channel, + int execution) { d_basename = basename; d_sat = sat; d_doppler_max = doppler_max; d_doppler_step = doppler_step; d_samples_per_code = samples_per_code; + acq_doppler_hz = 0.0; + acq_delay_samples = 0.0; + test_statistic = 0.0; + input_power = 0.0; + threshold = 0.0; + positive_acq = 0; + sample_counter = 0; d_num_doppler_bins = static_cast(ceil(static_cast(static_cast(d_doppler_max) - static_cast(-d_doppler_max)) / static_cast(d_doppler_step))); std::vector > mag_aux(d_num_doppler_bins, std::vector(d_samples_per_code)); mag = mag_aux; - d_dump_filename = d_basename + "_sat_" + std::to_string(d_sat) + ".mat"; + d_dump_filename = d_basename + "_ch_" + std::to_string(channel) + "_" + std::to_string(execution) + "_sat_" + std::to_string(d_sat) + ".mat"; for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) { doppler.push_back(-static_cast(d_doppler_max) + d_doppler_step * doppler_index); diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.h b/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.h index 7dd8ee44b..3f6b40365 100644 --- a/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.h +++ b/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.h @@ -38,13 +38,26 @@ class acquisition_dump_reader { public: - acquisition_dump_reader(const std::string& basename, unsigned int sat, unsigned int doppler_max, unsigned int doppler_step, unsigned int samples_per_code); + acquisition_dump_reader(const std::string& basename, + unsigned int sat, + unsigned int doppler_max, + unsigned int doppler_step, + unsigned int samples_per_code, + int channel = 0, + int execution = 1); ~acquisition_dump_reader(); bool read_binary_acq(); std::vector doppler; std::vector samples; std::vector > mag; + float acq_doppler_hz; + float acq_delay_samples; + float test_statistic; + float input_power; + float threshold; + int positive_acq; + long unsigned int sample_counter; private: std::string d_basename; diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/observables_dump_reader.cc b/src/tests/unit-tests/signal-processing-blocks/libs/observables_dump_reader.cc index 72a40389d..a913eeee0 100644 --- a/src/tests/unit-tests/signal-processing-blocks/libs/observables_dump_reader.cc +++ b/src/tests/unit-tests/signal-processing-blocks/libs/observables_dump_reader.cc @@ -112,6 +112,13 @@ bool observables_dump_reader::open_obs_file(std::string out_file) } } +void observables_dump_reader::close_obs_file() +{ + if (d_dump_file.is_open() == false) + { + d_dump_file.close(); + } +} observables_dump_reader::observables_dump_reader(int n_channels_) { diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/observables_dump_reader.h b/src/tests/unit-tests/signal-processing-blocks/libs/observables_dump_reader.h index 41c7a60f2..c87062eaf 100644 --- a/src/tests/unit-tests/signal-processing-blocks/libs/observables_dump_reader.h +++ b/src/tests/unit-tests/signal-processing-blocks/libs/observables_dump_reader.h @@ -44,6 +44,7 @@ public: bool restart(); long int num_epochs(); bool open_obs_file(std::string out_file); + void close_obs_file(); //dump variables diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.cc b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.cc index 8b1f91c65..b27c44688 100644 --- a/src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.cc +++ b/src/tests/unit-tests/signal-processing-blocks/libs/tracking_true_obs_reader.cc @@ -89,15 +89,16 @@ bool tracking_true_obs_reader::open_obs_file(std::string out_file) { try { + d_dump_file.clear(); 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 << "Observables dump enabled, Log file: " << d_dump_filename.c_str() << std::endl; + std::cout << "Tracking Log file: " << d_dump_filename.c_str() << " open ok " << std::endl; return true; } catch (const std::ifstream::failure &e) { - std::cout << "Problem opening Observables dump Log file: " << d_dump_filename.c_str() << std::endl; + std::cout << "Problem opening Tracking dump Log file: " << d_dump_filename.c_str() << " Error: " << e.what() << std::endl; return false; } } @@ -107,6 +108,13 @@ bool tracking_true_obs_reader::open_obs_file(std::string out_file) } } +void tracking_true_obs_reader::close_obs_file() +{ + if (d_dump_file.is_open() == true) + { + d_dump_file.close(); + } +} tracking_true_obs_reader::~tracking_true_obs_reader() { 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 index 9c4a5db7c..84bd2d7b0 100644 --- 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 @@ -43,6 +43,7 @@ public: bool restart(); long int num_epochs(); bool open_obs_file(std::string out_file); + void close_obs_file(); bool d_dump; double signal_timestamp_s; 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..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,10 +53,32 @@ #include "gnuplot_i.h" #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]"); + +// 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 +DEFINE_bool(plot_gps_l1_tracking_test, false, "Plots results of GpsL1CADllPllTrackingTest with gnuplot"); + // ######## GNURADIO BLOCK MESSAGE RECEVER ######### class GpsL1CADllPllTrackingTest_msg_rx; @@ -130,20 +152,26 @@ public: std::string filename_rinex_obs = FLAGS_filename_rinex_obs; std::string filename_raw_data = FLAGS_filename_raw_data; - int configure_generator(); + int configure_generator(double CN0_dBHz, int file_idx); int generate_signal(); - void check_results_doppler(arma::vec& true_time_s, + std::vector 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& 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); - void check_results_codephase(arma::vec& true_time_s, + 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() { @@ -157,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; @@ -167,7 +199,7 @@ public: }; -int GpsL1CADllPllTrackingTest::configure_generator() +int GpsL1CADllPllTrackingTest::configure_generator(double CN0_dBHz, int file_idx) { // Configure signal generator generator_binary = FLAGS_generator_binary; @@ -181,10 +213,10 @@ int GpsL1CADllPllTrackingTest::configure_generator() { 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(FLAGS_CN0_dBHz); // Signal generator CN0 + 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 + std::to_string(file_idx); // 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_dBHz); // Signal generator CN0 return 0; } @@ -193,7 +225,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) @@ -212,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'; @@ -220,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"; } -void GpsL1CADllPllTrackingTest::check_results_doppler(arma::vec& true_time_s, +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; @@ -256,6 +307,10 @@ void GpsL1CADllPllTrackingTest::check_results_doppler(arma::vec& true_time_s, arma::vec err; err = meas_value - true_value_interp; + + //conversion between arma::vec and std:vector + std::vector err_std_vector(err.colptr(0), err.colptr(0) + err.n_rows); + arma::vec err2 = arma::square(err); double rmse = sqrt(arma::mean(err2)); @@ -263,6 +318,9 @@ void GpsL1CADllPllTrackingTest::check_results_doppler(arma::vec& true_time_s, 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); @@ -273,13 +331,16 @@ void GpsL1CADllPllTrackingTest::check_results_doppler(arma::vec& true_time_s, << ", mean=" << error_mean << ", stdev=" << sqrt(error_var) << " (max,min)=" << max_error << "," << min_error << " [Hz]" << std::endl; std::cout.precision(ss); + return err_std_vector; } -void GpsL1CADllPllTrackingTest::check_results_acc_carrier_phase(arma::vec& true_time_s, +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; @@ -296,12 +357,17 @@ void GpsL1CADllPllTrackingTest::check_results_acc_carrier_phase(arma::vec& true_ arma::vec err; err = meas_value - true_value_interp; arma::vec err2 = arma::square(err); + //conversion between arma::vec and std:vector + std::vector err_std_vector(err.colptr(0), err.colptr(0) + err.n_rows); + double rmse = sqrt(arma::mean(err2)); // 3. Mean err and variance 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); @@ -312,13 +378,16 @@ void GpsL1CADllPllTrackingTest::check_results_acc_carrier_phase(arma::vec& true_ << ", mean=" << error_mean << ", stdev=" << sqrt(error_var) << " (max,min)=" << max_error << "," << min_error << " [Hz]" << std::endl; std::cout.precision(ss); + return err_std_vector; } -void GpsL1CADllPllTrackingTest::check_results_codephase(arma::vec& true_time_s, +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; @@ -335,6 +404,9 @@ void GpsL1CADllPllTrackingTest::check_results_codephase(arma::vec& true_time_s, arma::vec err; err = meas_value - true_value_interp; + //conversion between arma::vec and std:vector + std::vector err_std_vector(err.colptr(0), err.colptr(0) + err.n_rows); + arma::vec err2 = arma::square(err); double rmse = sqrt(arma::mean(err2)); @@ -342,6 +414,9 @@ void GpsL1CADllPllTrackingTest::check_results_codephase(arma::vec& true_time_s, 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); @@ -352,163 +427,496 @@ void GpsL1CADllPllTrackingTest::check_results_codephase(arma::vec& true_time_s, << ", mean=" << error_mean << ", stdev=" << sqrt(error_var) << " (max,min)=" << max_error << "," << min_error << " [Chips]" << std::endl; std::cout.precision(ss); + return err_std_vector; } TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults) { - // Configure the signal generator - configure_generator(); + //************************************************* + //***** STEP 2: Prepare the parameters sweep ****** + //************************************************* - // Generate signal raw signal samples and observations RINEX file - if (FLAGS_disable_generator == false) + std::vector generator_CN0_values; + + + //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) { - generate_signal(); + generator_CN0_values.push_back(FLAGS_CN0_dBHz_start); + } + else + { + for (double cn0 = FLAGS_CN0_dBHz_start; cn0 > FLAGS_CN0_dBHz_stop; cn0 = cn0 - FLAGS_CN0_dB_step) + { + generator_CN0_values.push_back(cn0); + } } - std::chrono::time_point start, end; - - configure_receiver(); - - // open true observables log file written by the simulator + int test_satellite_PRN = 0; + double acq_delay_samples = 0.0; + double acq_doppler_hz = 0.0; tracking_true_obs_reader true_obs_data; - int test_satellite_PRN = FLAGS_test_satellite_PRN; - std::cout << "Testing satellite PRN=" << test_satellite_PRN << std::endl; - 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"); - ASSERT_EQ(true_obs_data.open_obs_file(true_obs_file), true) << "Failure opening true observables file"; - 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_); //std::make_shared(config.get(), "Tracking_1C", 1, 1); - - boost::shared_ptr msg_rx = GpsL1CADllPllTrackingTest_msg_rx_make(); - - // 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?"; - - // restart the epoch counter - true_obs_data.restart(); - - std::cout << "Initial Doppler [Hz]=" << true_obs_data.doppler_l1_hz << " Initial code delay [Chips]=" << true_obs_data.prn_delay_chips << std::endl; - gnss_synchro.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; - gnss_synchro.Acq_doppler_hz = true_obs_data.doppler_l1_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; - 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."; - - 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."; - - // check results - // load the true values - long int nepoch = true_obs_data.num_epochs(); - std::cout << "True observation epochs=" << nepoch << std::endl; - - arma::vec true_timestamp_s = arma::zeros(nepoch, 1); - arma::vec true_acc_carrier_phase_cycles = arma::zeros(nepoch, 1); - arma::vec true_Doppler_Hz = arma::zeros(nepoch, 1); - arma::vec true_prn_delay_chips = arma::zeros(nepoch, 1); - arma::vec true_tow_s = arma::zeros(nepoch, 1); - - long int epoch_counter = 0; - while (true_obs_data.read_binary_obs()) + //********************************************* + //***** STEP 3: Generate the input signal ***** + //********************************************* + // use generator or use an external capture file + if (FLAGS_enable_external_signal_file) { - 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++; + //todo: create and configure an acquisition block and perform an acquisition to obtain the synchronization parameters + } + else + { + for (int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + // Configure the signal generator + configure_generator(generator_CN0_values.at(current_cn0_idx), current_cn0_idx); + // Generate signal raw signal samples and observations RINEX file + if (FLAGS_disable_generator == false) + { + generate_signal(); + } + // open true observables log file written by the simulator + } } - //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"; + // CONFIG PARAM SWEEP LOOP + std::vector PLL_wide_bw_values; + std::vector DLL_wide_bw_values; - nepoch = trk_dump.num_epochs(); - std::cout << "Measured observation epochs=" << nepoch << std::endl; - arma::vec trk_timestamp_s = arma::zeros(nepoch, 1); - arma::vec trk_acc_carrier_phase_cycles = arma::zeros(nepoch, 1); - arma::vec trk_Doppler_Hz = arma::zeros(nepoch, 1); - arma::vec trk_prn_delay_chips = arma::zeros(nepoch, 1); - - std::vector prompt; - std::vector early; - std::vector late; - std::vector promptI; - std::vector promptQ; - std::vector CN0_dBHz; - - epoch_counter = 0; - while (trk_dump.read_binary_obs()) + if (FLAGS_PLL_bw_hz_start == FLAGS_PLL_bw_hz_stop) { - 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); + if (FLAGS_DLL_bw_hz_start == FLAGS_DLL_bw_hz_stop) + { + //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); + } + else + { + //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); + } + } + } + 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) + { + PLL_wide_bw_values.push_back(pll_bw); + DLL_wide_bw_values.push_back(FLAGS_DLL_bw_hz_start); + } } - // 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"); + 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; - 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); + std::vector> doppler_error_sweep; + std::vector> code_phase_error_sweep; + std::vector> acc_carrier_phase_error_sweep; - check_results_doppler(true_timestamp_s, true_Doppler_Hz, trk_timestamp_s, trk_Doppler_Hz); - check_results_codephase(true_timestamp_s, true_prn_delay_chips, trk_timestamp_s, trk_prn_delay_chips); - check_results_acc_carrier_phase(true_timestamp_s, true_acc_carrier_phase_cycles, trk_timestamp_s, trk_acc_carrier_phase_cycles); + 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; + + 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()) + { + 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++; + } + 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); + + //*********************************************************** + //***** 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; + + 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_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); + } + + 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; + } + } + } + } - std::chrono::duration elapsed_seconds = end - start; - std::cout << "Signal tracking completed in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; if (FLAGS_plot_gps_l1_tracking_test == true) { @@ -523,53 +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; - double t = 0.0; - for (auto it = prompt.begin(); it != prompt.end(); it++) + if (generator_CN0_values.size() > 1) { - timevec.push_back(t); - t = t + GPS_L1_CA_CODE_PERIOD; + //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++) + { + 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"); + } + g7.savetops("Doppler_error_metrics"); + g7.savetopdf("Doppler_error_metrics", 18); + + 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); } - Gnuplot g1("linespoints"); - g1.set_title("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"); - unsigned int decimate = static_cast(FLAGS_plot_decimate); - g1.plot_xy(timevec, prompt, "Prompt", decimate); - g1.plot_xy(timevec, early, "Early", decimate); - g1.plot_xy(timevec, late, "Late", decimate); - g1.savetops("Correlators_outputs"); - g1.savetopdf("Correlators_outputs", 18); - g1.showonscreen(); // window output - - Gnuplot g2("points"); - g2.set_title("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, promptQ); - 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"); - g3.plot_xy(timevec, CN0_dBHz, "Prompt", decimate); - g3.savetops("CN0_output"); - g3.savetopdf("CN0_output", 18); - g3.showonscreen(); // window output } catch (const GnuplotException& ge) { diff --git a/src/utils/matlab/plot_acq_grid.m b/src/utils/matlab/plot_acq_grid.m index c18e44556..182c09b02 100644 --- a/src/utils/matlab/plot_acq_grid.m +++ b/src/utils/matlab/plot_acq_grid.m @@ -33,6 +33,8 @@ file = 'acq'; sat = 7; +channel = 0; +execution = 1; % Signal: % 1 GPS L1 % 2 GPS L2M @@ -77,7 +79,7 @@ switch(signal_type) system = 'R'; signal = '1G'; end -filename = [path file '_' system '_' signal '_sat_' num2str(sat) '.mat']; +filename = [path file '_' system '_' signal '_ch_' num2str(channel) '_' num2str(execution) '_sat_' num2str(sat) '.mat']; load(filename); [n_fft n_dop_bins] = size(grid); [d_max f_max] = find(grid == max(max(grid))); diff --git a/src/utils/matlab/plot_tracking_quality_indicators.m b/src/utils/matlab/plot_tracking_quality_indicators.m new file mode 100644 index 000000000..a1c263aa3 --- /dev/null +++ b/src/utils/matlab/plot_tracking_quality_indicators.m @@ -0,0 +1,18 @@ +%plot tracking quality indicators +figure; +hold on; +title('Carrier lock test output for all the channels'); +for n=1:1:length(GNSS_tracking) + plot(GNSS_tracking(n).carrier_lock_test) + plotnames{n}=['SV ' num2str(round(mean(GNSS_tracking(n).PRN)))]; +end +legend(plotnames); + +figure; +hold on; +title('Carrier CN0 output for all the channels'); +for n=1:1:length(GNSS_tracking) + plot(GNSS_tracking(n).CN0_SNV_dB_Hz) + plotnames{n}=['SV ' num2str(round(mean(GNSS_tracking(n).PRN)))]; +end +legend(plotnames); \ No newline at end of file