diff --git a/CMakeLists.txt b/CMakeLists.txt index d313aea1e..2faec56d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1112,7 +1112,7 @@ if(NOT MATIO_FOUND) if(CMAKE_VERSION VERSION_LESS 3.2) ExternalProject_Add( matio-${GNSSSDR_MATIO_LOCAL_VERSION} - PREFIX ${CMAKE_CURRENT_BINARY_DIR}/mati + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/matio GIT_REPOSITORY https://github.com/tbeu/matio GIT_TAG v${GNSSSDR_MATIO_LOCAL_VERSION} SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/matio/matio-${GNSSSDR_MATIO_LOCAL_VERSION} diff --git a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt index 8a22651c4..3a7494721 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt @@ -48,6 +48,7 @@ include_directories( ${GFlags_INCLUDE_DIRS} ${GNURADIO_RUNTIME_INCLUDE_DIRS} ${VOLK_GNSSSDR_INCLUDE_DIRS} + ${MATIO_INCLUDE_DIRS} ) @@ -69,7 +70,7 @@ 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}) else(ENABLE_FPGA) - target_link_libraries(acq_gr_blocks gnss_sp_libs gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${OPT_LIBRARIES} ${OPT_ACQUISITION_LIBRARIES}) + target_link_libraries(acq_gr_blocks gnss_sp_libs gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${OPT_LIBRARIES} ${OPT_ACQUISITION_LIBRARIES} ${MATIO_LIBRARIES}) endif(ENABLE_FPGA) if(NOT VOLK_GNSSSDR_FOUND) add_dependencies(acq_gr_blocks volk_gnsssdr_module) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc index 726fd0d48..0c7382945 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc @@ -44,6 +44,7 @@ #include "control_message_factory.h" #include "GPS_L1_CA.h" //GPS_TWO_PI #include "GLONASS_L1_CA.h" //GLONASS_TWO_PI +#include using google::LogMessage; @@ -98,9 +99,6 @@ pcps_acquisition_cc::pcps_acquisition_cc( d_code_phase = 0; d_test_statistics = 0.0; d_channel = 0; - d_doppler_freq = 0.0; - - //set_relative_rate( 1.0/d_fft_size ); // COD: // Experimenting with the overlap/save technique for handling bit trannsitions @@ -113,10 +111,10 @@ pcps_acquisition_cc::pcps_acquisition_cc( // We can avoid this by doing linear correlation, effectively doubling the // size of the input buffer and padding the code with zeros. if( d_bit_transition_flag ) - { - d_fft_size *= 2; - d_max_dwells = 1; //Activation of d_bit_transition_flag invalidates the value of d_max_dwells - } + { + d_fft_size *= 2; + d_max_dwells = 1; //Activation of d_bit_transition_flag invalidates the value of d_max_dwells + } d_fft_codes = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_magnitude = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment())); @@ -135,6 +133,7 @@ pcps_acquisition_cc::pcps_acquisition_cc( d_blocking = blocking; d_worker_active = false; d_data_buffer = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + grid_ = arma::fmat(); } @@ -148,18 +147,11 @@ pcps_acquisition_cc::~pcps_acquisition_cc() } delete[] d_grid_doppler_wipeoffs; } - volk_gnsssdr_free(d_fft_codes); volk_gnsssdr_free(d_magnitude); - delete d_ifft; delete d_fft_if; - - if (d_dump) - { - d_dump_file.close(); - } - volk_gnsssdr_free( d_data_buffer ); + volk_gnsssdr_free(d_data_buffer); } @@ -243,6 +235,12 @@ void pcps_acquisition_cc::init() update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_freq + doppler); } d_worker_active = false; + + if(d_dump) + { + unsigned int effective_fft_size = (d_bit_transition_flag ? (d_fft_size / 2) : d_fft_size); + grid_ = arma::fmat(effective_fft_size, d_num_doppler_bins, arma::fill::zeros); + } } @@ -480,26 +478,46 @@ void pcps_acquisition_cc::acquisition_core( unsigned long int samp_count ) } // Record results to file if required if (d_dump) + { + memcpy(grid_.colptr(doppler_index), d_magnitude, sizeof(float) * effective_fft_size); + if(doppler_index == (d_num_doppler_bins - 1)) { - std::stringstream filename; - std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write - filename.str(""); - boost::filesystem::path p = d_dump_filename; - filename << p.parent_path().string() - << boost::filesystem::path::preferred_separator - << p.stem().string() - << "_" << d_gnss_synchro->System - <<"_" << d_gnss_synchro->Signal << "_sat_" - << d_gnss_synchro->PRN << "_doppler_" - << doppler - << p.extension().string(); + std::string filename = d_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; + d_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); - DLOG(INFO) << "Writing ACQ out to " << filename.str(); + dims[0] = static_cast(1); + dims[1] = static_cast(1); + matvar = Mat_VarCreate("doppler_max", MAT_C_SINGLE, MAT_T_UINT32, 1, dims, &d_doppler_max, 0); + Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE + Mat_VarFree(matvar); - d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); - d_dump_file.write(reinterpret_cast(d_ifft->get_outbuf()), n); //write directly |abs(x)|^2 in this Doppler bin? - d_dump_file.close(); + 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); + } } + } } lk.lock(); if (!d_bit_transition_flag) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h index 5a88aa6f1..44e80f260 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h @@ -58,6 +58,8 @@ #include #include #include "gnss_synchro.h" +#include +#include class pcps_acquisition_cc; @@ -80,6 +82,7 @@ pcps_make_acquisition_cc(unsigned int sampled_ms, unsigned int max_dwells, class pcps_acquisition_cc: public gr::block { private: + friend pcps_acquisition_cc_sptr pcps_make_acquisition_cc(unsigned int sampled_ms, unsigned int max_dwells, unsigned int doppler_max, long freq, long fs_in, @@ -102,146 +105,144 @@ private: void acquisition_core( unsigned long int samp_count ); void send_negative_acquisition(); + void send_positive_acquisition(); + + bool d_bit_transition_flag; + bool d_use_CFAR_algorithm_flag; + bool d_active; + bool d_dump; + bool d_worker_active; + bool d_blocking; + float d_threshold; + float d_mag; + float d_input_power; + float d_test_statistics; + float* d_magnitude; long d_fs_in; long d_freq; long d_old_freq; int d_samples_per_ms; int d_samples_per_code; - //unsigned int d_doppler_resolution; - float d_threshold; + int d_state; + unsigned int d_channel; unsigned int d_doppler_max; unsigned int d_doppler_step; unsigned int d_sampled_ms; unsigned int d_max_dwells; unsigned int d_well_count; unsigned int d_fft_size; + unsigned int d_num_doppler_bins; + unsigned int d_code_phase; unsigned long int d_sample_counter; gr_complex** d_grid_doppler_wipeoffs; - unsigned int d_num_doppler_bins; gr_complex* d_fft_codes; + gr_complex* d_data_buffer; gr::fft::fft_complex* d_fft_if; gr::fft::fft_complex* d_ifft; - Gnss_Synchro *d_gnss_synchro; - unsigned int d_code_phase; - float d_doppler_freq; - float d_mag; - float* d_magnitude; - float d_input_power; - float d_test_statistics; - bool d_bit_transition_flag; - bool d_use_CFAR_algorithm_flag; - std::ofstream d_dump_file; - bool d_active; - int d_state; - bool d_dump; - unsigned int d_channel; + Gnss_Synchro* d_gnss_synchro; std::string d_dump_filename; - bool d_worker_active; - bool d_blocking; - gr_complex *d_data_buffer; + arma::fmat grid_; public: - /*! - * \brief Default destructor. - */ - ~pcps_acquisition_cc(); + + ~pcps_acquisition_cc(); /*! * \brief Set acquisition/tracking common Gnss_Synchro object pointer * to exchange synchronization data between acquisition and tracking blocks. * \param p_gnss_synchro Satellite information shared by the processing blocks. */ - inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) - { - gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler - d_gnss_synchro = p_gnss_synchro; - } + inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) + { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler + d_gnss_synchro = p_gnss_synchro; + } - /*! - * \brief Returns the maximum peak of grid search. - */ - inline unsigned int mag() const - { - return d_mag; - } + /*! + * \brief Returns the maximum peak of grid search. + */ + inline unsigned int mag() const + { + return d_mag; + } /*! * \brief Initializes acquisition algorithm. */ - void init(); + void init(); /*! * \brief Sets local code for PCPS acquisition algorithm. * \param code - Pointer to the PRN code. */ - void set_local_code(std::complex * code); + void set_local_code(std::complex * code); /*! * \brief Starts acquisition algorithm, turning from standby mode to * active mode * \param active - bool that activates/deactivates the block. */ - inline void set_active(bool active) - { - gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler - d_active = active; - } + inline void set_active(bool active) + { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler + d_active = active; + } /*! * \brief If set to 1, ensures that acquisition starts at the * first available sample. * \param state - int=1 forces start of acquisition */ - void set_state(int state); + void set_state(int state); /*! * \brief Set acquisition channel unique ID * \param channel - receiver channel. */ - inline void set_channel(unsigned int channel) - { - gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler - d_channel = channel; - } + inline void set_channel(unsigned int channel) + { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler + d_channel = channel; + } /*! * \brief Set statistics threshold of PCPS algorithm. * \param threshold - Threshold for signal detection (check \ref Navitec2012, * Algorithm 1, for a definition of this threshold). */ - inline void set_threshold(float threshold) - { - gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler - d_threshold = threshold; - } + inline void set_threshold(float threshold) + { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler + d_threshold = threshold; + } /*! * \brief Set maximum Doppler grid search * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz]. */ - inline void set_doppler_max(unsigned int doppler_max) - { - gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler - d_doppler_max = doppler_max; - } + inline void set_doppler_max(unsigned int doppler_max) + { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler + d_doppler_max = doppler_max; + } /*! * \brief Set Doppler steps for the grid search * \param doppler_step - Frequency bin of the search grid [Hz]. */ - inline void set_doppler_step(unsigned int doppler_step) - { - gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler - d_doppler_step = doppler_step; - } + inline void set_doppler_step(unsigned int doppler_step) + { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler + d_doppler_step = doppler_step; + } /*! * \brief Parallel Code Phase Search Acquisition signal processing. */ - int general_work(int noutput_items, gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + int general_work(int noutput_items, gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_ambiguous_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_ambiguous_acquisition_test.cc index 0f8c36cdf..e0b146fd6 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_ambiguous_acquisition_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_ambiguous_acquisition_test.cc @@ -158,7 +158,7 @@ void GalileoE1PcpsAmbiguousAcquisitionTest::init() { config->set_property("Acquisition_1B.dump", "false"); } - config->set_property("Acquisition_1B.dump_filename", "./tmp-acq-gal1/acquisition.dat"); + config->set_property("Acquisition_1B.dump_filename", "./tmp-acq-gal1/acquisition"); config->set_property("Acquisition_1B.threshold", "0.0001"); config->set_property("Acquisition_1B.doppler_max", std::to_string(doppler_max)); config->set_property("Acquisition_1B.doppler_step", std::to_string(doppler_step)); diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc index 7cee76a52..95b73e6e3 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc @@ -141,7 +141,7 @@ void GlonassL1CaPcpsAcquisitionTest::init() config->set_property("Acquisition_1G.if", "9540000"); config->set_property("Acquisition_1G.coherent_integration_time_ms", "1"); config->set_property("Acquisition_1G.dump", "true"); - config->set_property("Acquisition_1G.dump_filename", "./acquisition.dat"); + config->set_property("Acquisition_1G.dump_filename", "./acquisition"); config->set_property("Acquisition_1G.implementation", "Glonass_L1_CA_PCPS_Acquisition"); config->set_property("Acquisition_1G.threshold", "0.001"); config->set_property("Acquisition_1G.doppler_max", "5000"); 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 41a6dad97..a432cec1a 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 @@ -157,7 +157,7 @@ void GpsL1CaPcpsAcquisitionTest::init() { config->set_property("Acquisition_1C.dump", "false"); } - config->set_property("Acquisition_1C.dump_filename", "./tmp-acq-gps1/acquisition.dat"); + config->set_property("Acquisition_1C.dump_filename", "./tmp-acq-gps1/acquisition"); config->set_property("Acquisition_1C.threshold", "0.00001"); config->set_property("Acquisition_1C.doppler_max", std::to_string(doppler_max)); config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step)); diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc index 04480d7c8..be5a6cc69 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc @@ -164,7 +164,7 @@ void GpsL2MPcpsAcquisitionTest::init() { config->set_property("Acquisition_2S.dump", "false"); } - config->set_property("Acquisition_2S.dump_filename", "./tmp-acq-gps2/acquisition.dat"); + config->set_property("Acquisition_2S.dump_filename", "./tmp-acq-gps2/acquisition"); config->set_property("Acquisition_2S.threshold", "0.001"); config->set_property("Acquisition_2S.doppler_max", std::to_string(doppler_max)); config->set_property("Acquisition_2S.doppler_step", std::to_string(doppler_step)); @@ -178,9 +178,8 @@ void GpsL2MPcpsAcquisitionTest::plot_grid() std::string basename = "./tmp-acq-gps2/acquisition_G_2S"; unsigned int sat = static_cast(gnss_synchro.PRN); - unsigned int samples_per_code = static_cast(floor(sampling_frequency_hz / (GPS_L2_M_CODE_RATE_HZ / GPS_L2_M_CODE_LENGTH_CHIPS)) - 1000); // !! + unsigned int samples_per_code = static_cast(floor(static_cast(sampling_frequency_hz) / (GPS_L2_M_CODE_RATE_HZ / static_cast(GPS_L2_M_CODE_LENGTH_CHIPS)))); acquisition_dump_reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code); - if(!acq_dump.read_binary_acq()) std::cout << "Error reading files" << std::endl; std::vector *doppler = &acq_dump.doppler; @@ -204,7 +203,7 @@ void GpsL2MPcpsAcquisitionTest::plot_grid() std::string gnuplot_path = dir.native(); Gnuplot::set_GNUPlotPath(gnuplot_path); - Gnuplot g1("lines"); + Gnuplot g1("impulses"); g1.set_title("GPS L2CM signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN)); g1.set_xlabel("Doppler [Hz]"); g1.set_ylabel("Sample"); diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/CMakeLists.txt b/src/tests/unit-tests/signal-processing-blocks/libs/CMakeLists.txt index 14c2f5bd2..ee71cc113 100644 --- a/src/tests/unit-tests/signal-processing-blocks/libs/CMakeLists.txt +++ b/src/tests/unit-tests/signal-processing-blocks/libs/CMakeLists.txt @@ -30,6 +30,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${GLOG_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS} + ${MATIO_INCLUDE_DIRS} ) 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 8e16812df..6e9d3e493 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 @@ -1,11 +1,13 @@ /*! * \file acquisition_dump_reader.cc * \brief Helper file for unit testing - * \author Carles Fernandez-Prades, 2017. cfernandez(at)cttc.es + * \authors Carles Fernandez-Prades, 2017. cfernandez(at)cttc.es + * Antonio Ramos, 2018. antonio.ramos(at)cttc.es + * * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -28,44 +30,65 @@ * ------------------------------------------------------------------------- */ -#include +#include +#include +#include #include "acquisition_dump_reader.h" bool acquisition_dump_reader::read_binary_acq() { - std::complex* aux = new std::complex[1]; - for(unsigned int i = 0; i < d_num_doppler_bins; i++) + mat_t* matfile = Mat_Open(d_dump_filename.c_str(), MAT_ACC_RDONLY); + if( matfile == NULL) + { + std::cout << "¡¡¡Unreachable Acquisition dump file!!!" << std::endl; + return false; + } + matvar_t* var_= Mat_VarRead(matfile, "grid"); + if( var_ == NULL) + { + std::cout << "¡¡¡Unreachable grid variable into Acquisition dump file!!!" << std::endl; + Mat_Close(matfile); + return false; + } + if(var_->rank != 2) + { + std::cout << "Invalid Acquisition dump file: rank error" << std::endl; + Mat_VarFree(var_); + Mat_Close(matfile); + return false; + } + if((var_->dims[0] != d_samples_per_code) or (var_->dims[1] != d_num_doppler_bins)) + { + std::cout << "Invalid Acquisition dump file: dimension matrix error" << std::endl; + if(var_->dims[0] != d_samples_per_code) std::cout << "Expected " << d_samples_per_code << " samples per code. Obtained " << var_->dims[0] << std::endl; + if(var_->dims[1] != d_num_doppler_bins) std::cout << "Expected " << d_num_doppler_bins << " Doppler bins. Obtained " << var_->dims[1] << std::endl; + Mat_VarFree(var_); + Mat_Close(matfile); + return false; + } + if(var_->data_type != MAT_T_SINGLE) + { + std::cout << "Invalid Acquisition dump file: data type error" << std::endl; + Mat_VarFree(var_); + Mat_Close(matfile); + return false; + } + 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++) { - try - { - std::ifstream ifs; - ifs.exceptions( std::ifstream::failbit | std::ifstream::badbit ); - ifs.open(d_dump_filenames.at(i).c_str(), std::ios::in | std::ios::binary); - d_dump_files.at(i).swap(ifs); - if (d_dump_files.at(i).is_open()) - { - for(unsigned int k = 0; k < d_samples_per_code; k++) - { - d_dump_files.at(i).read(reinterpret_cast(&aux[0]), sizeof(std::complex)); - mag.at(i).at(k) = std::abs(*aux) / std::pow(d_samples_per_code, 2); - } - } - else - { - std::cout << "File " << d_dump_filenames.at(i).c_str() << " not found." << std::endl; - delete[] aux; - return false; - } - d_dump_files.at(i).close(); - } - catch (const std::ifstream::failure &e) - { - std::cout << e.what() << std::endl; - delete[] aux; - return false; - } + *it2 = static_cast(std::sqrt(aux[k])) / normalization_factor; + k++; } - delete[] aux; + } + Mat_VarFree(var_); + Mat_Close(matfile); + return true; } @@ -80,12 +103,10 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string & basename, u 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"; 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); - d_dump_filenames.push_back(d_basename + "_sat_" + std::to_string(d_sat) + "_doppler_" + std::to_string(doppler.at(doppler_index)) + ".dat"); - std::ifstream ifs; - d_dump_files.push_back(std::move(ifs)); } for (unsigned int k = 0; k < d_samples_per_code; k++) { @@ -95,12 +116,4 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string & basename, u acquisition_dump_reader::~acquisition_dump_reader() -{ - for(unsigned int i = 0; i < d_num_doppler_bins; i++) - { - if (d_dump_files.at(i).is_open() == true) - { - d_dump_files.at(i).close(); - } - } -} +{} 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 02c75ea66..ba973dbe4 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 @@ -1,11 +1,12 @@ /*! * \file acquisition_dump_reader.h * \brief Helper file for unit testing - * \author Carles Fernandez-Prades, 2017. cfernandez(at)cttc.es + * \authors Carles Fernandez-Prades, 2017. cfernandez(at)cttc.es + * Antonio Ramos, 2018. antonio.ramos(at)cttc.es * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -31,8 +32,6 @@ #ifndef GNSS_SDR_ACQUISITION_DUMP_READER_H #define GNSS_SDR_ACQUISITION_DUMP_READER_H -#include -#include #include #include @@ -54,8 +53,7 @@ private: unsigned int d_doppler_step; unsigned int d_samples_per_code; unsigned int d_num_doppler_bins; - std::vector d_dump_filenames; - std::vector d_dump_files; + std::string d_dump_filename; }; #endif // GNSS_SDR_ACQUISITION_DUMP_READER_H diff --git a/src/utils/matlab/plot_acq_grid.m b/src/utils/matlab/plot_acq_grid.m new file mode 100644 index 000000000..523f3d03a --- /dev/null +++ b/src/utils/matlab/plot_acq_grid.m @@ -0,0 +1,116 @@ +% /*! +% * \file plot_acq_grid.m +% * \brief Read GNSS-SDR Acquisition dump .mat file using the provided +% function and plot acquisition grid of acquisition statistic of PRN sat +% +% +% * \author Antonio Ramos, 2017. antonio.ramos(at)cttc.es +% * ------------------------------------------------------------------------- +% * +% * Copyright (C) 2010-2017 (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 . +% * +% * ------------------------------------------------------------------------- +% */ + +%%%%%%%%% ¡¡¡ CONFIGURE !!! %%%%%%%%%%%%% + +path = '/archive/'; +file = 'acq'; + +sat = 7; + +% Signal: +% 1 GPS L1 +% 2 GPS L2M +% 3 GPS L5 +% 4 Gal. E1B +% 5 Gal. E5 +% 6 Glo. 1G + +signal_type = 1; + +%%% True for light grid representation +lite_view = true; + +%%% If lite_view, it sets the number of samples per chip in the graphical representation +n_samples_per_chip = 3; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +switch(signal_type) + case 1 + n_chips = 1023; + system = 'G'; + signal = '1C'; + case 2 + n_chips = 10230; + system = 'G'; + signal = '2S'; + case 3 + n_chips = 10230; + system = 'G'; + signal = 'L5'; + case 4 + n_chips = 4092; + system = 'E'; + signal = '1B'; + case 5 + n_chips = 10230; + system = 'E'; + signal = '5X'; + case 6 + n_chips = 511; + system = 'R'; + signal = '1G'; +end +filename = [path file '_' system '_' signal '_sat_' num2str(sat) '.mat']; +load(filename); +[n_fft n_dop_bins] = size(grid); +[d_max f_max] = find(grid == max(max(grid))); +freq = (0 : n_dop_bins - 1) * doppler_step - doppler_max; +delay = (0 : n_fft - 1) / n_fft * n_chips; +figure(1) +if(lite_view == false) + surf(freq, delay, grid, 'FaceColor', 'interp', 'LineStyle', 'none') + ylim([min(delay) max(delay)]) +else + delay_interp = (0 : n_samples_per_chip * n_chips - 1) / n_samples_per_chip; + grid_interp = spline(delay, grid', delay_interp)'; + surf(freq, delay_interp, grid_interp, 'FaceColor', 'interp', 'LineStyle', 'none') + ylim([min(delay_interp) max(delay_interp)]) +end +xlabel('Doppler shift / Hz') +xlim([min(freq) max(freq)]) +ylabel('Code delay / chips') +zlabel('Test statistics') +figure(2) +subplot(2,1,1) +plot(freq, grid(d_max, :)) +xlim([min(freq) max(freq)]) +xlabel('Doppler shift / Hz') +ylabel('Test statistics') +title(['Fixed code delay to ' num2str((d_max - 1) / n_fft * n_chips) ' chips']) +subplot(2,1,2) +plot(delay, grid(:, f_max)) +xlim([min(delay) max(delay)]) +xlabel('Code delay / chips') +ylabel('Test statistics') +title(['Doppler wipe-off = ' num2str((f_max - 1) * doppler_step - doppler_max) ' Hz'])