From 45d7220daea248ab9e38463bbf3c4b4a68446701 Mon Sep 17 00:00:00 2001 From: Luis Esteve Date: Tue, 28 Aug 2012 13:38:33 +0000 Subject: [PATCH] First version of Galileo E1 DLL PLL Very Early Minus Late Tracking. Added some functions in Matlab to analyze the results. git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@234 64b25241-fba3-4117-9849-534c7e92360d --- .../libs/galileo_e1_signal_processing.cc | 52 +- .../galileo_e1_dll_pll_veml_tracking.cc | 170 +++++ .../galileo_e1_dll_pll_veml_tracking.h | 113 +++ src/algorithms/tracking/adapters/jamfile.jam | 3 +- .../galileo_e1_dll_pll_veml_tracking_cc.cc | 681 ++++++++++++++++++ .../galileo_e1_dll_pll_veml_tracking_cc.h | 206 ++++++ .../tracking/gnuradio_blocks/jamfile.jam | 3 +- src/algorithms/tracking/libs/CN_estimators.cc | 42 ++ src/algorithms/tracking/libs/CN_estimators.h | 1 + src/algorithms/tracking/libs/correlator.cc | 33 + src/algorithms/tracking/libs/correlator.h | 1 + .../tracking/libs/tracking_2nd_DLL_filter.cc | 7 +- .../tracking/libs/tracking_2nd_DLL_filter.h | 1 + .../tracking/libs/tracking_2nd_PLL_filter.cc | 6 + .../tracking/libs/tracking_2nd_PLL_filter.h | 1 + .../tracking/libs/tracking_discriminators.cc | 23 +- .../tracking/libs/tracking_discriminators.h | 15 +- .../galileo_e1_dll_pll_veml_tracking_test.cc | 241 +++++++ src/tests/jamfile.jam | 2 + src/tests/test_main.cc | 3 +- ...lileo_e1_dll_pll_veml_plot_sample_64bits.m | 93 +++ ...lileo_e1_dll_pll_veml_read_tracking_dump.m | 192 +++++ src/utils/matlab/libs/plotVEMLTracking.m | 159 ++++ 23 files changed, 2021 insertions(+), 27 deletions(-) create mode 100644 src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.cc create mode 100644 src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.h create mode 100644 src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc create mode 100644 src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.h create mode 100644 src/tests/gnss_block/galileo_e1_dll_pll_veml_tracking_test.cc create mode 100644 src/utils/matlab/galileo_e1_dll_pll_veml_plot_sample_64bits.m create mode 100644 src/utils/matlab/libs/galileo_e1_dll_pll_veml_read_tracking_dump.m create mode 100644 src/utils/matlab/libs/plotVEMLTracking.m diff --git a/src/algorithms/libs/galileo_e1_signal_processing.cc b/src/algorithms/libs/galileo_e1_signal_processing.cc index aae1970e9..1bcff7cdb 100644 --- a/src/algorithms/libs/galileo_e1_signal_processing.cc +++ b/src/algorithms/libs/galileo_e1_signal_processing.cc @@ -32,7 +32,8 @@ #include "galileo_e1_signal_processing.h" -void galileo_e1_code_gen_int(int* _dest, char _Signal[3], signed int _prn, +void +galileo_e1_code_gen_int(int* _dest, char _Signal[3], signed int _prn, unsigned int _chip_shift) { std::string _galileo_signal = _Signal; @@ -71,7 +72,8 @@ void galileo_e1_code_gen_int(int* _dest, char _Signal[3], signed int _prn, } -void galileo_e1_sinboc_11_gen(std::complex* _dest, int* _prn, +void +galileo_e1_sinboc_11_gen(std::complex* _dest, int* _prn, unsigned int _length_out) { const unsigned int _length_in = Galileo_E1_B_CODE_LENGTH_CHIPS; @@ -91,7 +93,8 @@ void galileo_e1_sinboc_11_gen(std::complex* _dest, int* _prn, } -void galileo_e1_sinboc_61_gen(std::complex* _dest, int* _prn, +void +galileo_e1_sinboc_61_gen(std::complex* _dest, int* _prn, unsigned int _length_out) { const unsigned int _length_in = Galileo_E1_B_CODE_LENGTH_CHIPS; @@ -110,7 +113,8 @@ void galileo_e1_sinboc_61_gen(std::complex* _dest, int* _prn, } } -void galileo_e1_gen(std::complex* _dest, int* _prn, char _Signal[3]) +void +galileo_e1_gen(std::complex* _dest, int* _prn, char _Signal[3]) { std::string _galileo_signal = _Signal; const unsigned int _codeLength = 12 * Galileo_E1_B_CODE_LENGTH_CHIPS; @@ -142,9 +146,9 @@ void galileo_e1_gen(std::complex* _dest, int* _prn, char _Signal[3]) return; } -void galileo_e1_code_gen_complex_sampled(std::complex* _dest, - char _Signal[3], bool _cboc, unsigned int _prn, signed int _fs, - unsigned int _chip_shift) +void +galileo_e1_code_gen_complex_sampled(std::complex* _dest, char _Signal[3], + bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift) { // This function is based on the GNU software GPS for MATLAB in the Kay Borre book @@ -162,12 +166,19 @@ void galileo_e1_code_gen_complex_sampled(std::complex* _dest, _codeLength = 12 * Galileo_E1_B_CODE_LENGTH_CHIPS; - std::complex _signal_E1[_codeLength]; + if (_fs != 12 * _codeFreqBasis) + { + std::complex _signal_E1[_codeLength]; - galileo_e1_gen(_signal_E1, primary_code_E1_chips, _Signal); //generate cboc 12 samples per chip + galileo_e1_gen(_signal_E1, primary_code_E1_chips, _Signal); //generate cboc 12 samples per chip - resampler(_signal_E1, _dest, 12 * _codeFreqBasis, _fs, _codeLength, - _samplesPerCode); //resamples code to fs + resampler(_signal_E1, _dest, 12 * _codeFreqBasis, _fs, + _codeLength, _samplesPerCode); //resamples code to fs + } + else + { + galileo_e1_gen(_dest, primary_code_E1_chips, _Signal); //generate cboc 12 samples per chip + } } else @@ -177,13 +188,20 @@ void galileo_e1_code_gen_complex_sampled(std::complex* _dest, _codeLength = 2 * Galileo_E1_B_CODE_LENGTH_CHIPS; - std::complex _signal_E1[_codeLength]; + if (_fs != 2 * _codeFreqBasis) + { + std::complex _signal_E1[_codeLength]; - galileo_e1_sinboc_11_gen(_signal_E1, primary_code_E1_chips, - _codeLength); //generate sinboc(1,1) 2 samples per chip - - resampler(_signal_E1, _dest, 2 * _codeFreqBasis, _fs, _codeLength, - _samplesPerCode); //resamples code to fs + galileo_e1_sinboc_11_gen(_signal_E1, primary_code_E1_chips, + _codeLength); //generate sinboc(1,1) 2 samples per chip + resampler(_signal_E1, _dest, 2 * _codeFreqBasis, _fs, + _codeLength, _samplesPerCode); //resamples code to fs + } + else + { + galileo_e1_sinboc_11_gen(_dest, primary_code_E1_chips, + _codeLength); //generate sinboc(1,1) 2 samples per chip } + } } } 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 new file mode 100644 index 000000000..40ba48bfa --- /dev/null +++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.cc @@ -0,0 +1,170 @@ +/*! + * \file galileo_e1_dll_pll_veml_tracking.cc + * \brief Interface of an adapter of a DLL+PLL VEML (Very Early Minus Late) + * tracking loop block for Galileo E1 to a TrackingInterface + * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com + * + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkhauser, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2012 (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 "galileo_e1_dll_pll_veml_tracking.h" +#include "GPS_L1_CA.h" +#include "Galileo_E1.h" +#include "configuration_interface.h" +#ifdef GNSS_SDR_USE_BOOST_ROUND + #include +#endif +#include +#include +#include + +using google::LogMessage; + +GalileoE1DllPllVemlTracking::GalileoE1DllPllVemlTracking( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams, + gr_msg_queue_sptr queue) : + role_(role), in_streams_(in_streams), out_streams_(out_streams), + queue_(queue) +{ + + DLOG(INFO) << "role " << role; + //DLOG(INFO) << "vector length " << vector_length; + + //################# CONFIGURATION PARAMETERS ######################## + + int fs_in; + int vector_length; + int f_if; + bool dump; + std::string dump_filename; + std::string item_type; + std::string default_item_type = "gr_complex"; + float pll_bw_hz; + float dll_bw_hz; + float early_late_space_chips; + float very_early_late_space_chips; + + item_type = configuration->property(role + ".item_type",default_item_type); + fs_in = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); + f_if = configuration->property(role + ".if", 0); + dump = configuration->property(role + ".dump", false); + pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0); + dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0); + early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.15); + very_early_late_space_chips = configuration->property(role + ".very_early_late_space_chips", 0.6); + + std::string default_dump_filename = "./track_ch"; + dump_filename = configuration->property(role + ".dump_filename", + default_dump_filename); //unused! +#ifdef GNSS_SDR_USE_BOOST_ROUND + vector_length = round(fs_in / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS)); +#else + vector_length = std::round(fs_in / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS)); +#endif + //################# MAKE TRACKING GNURadio object ################### + if (item_type.compare("gr_complex") == 0) + { + item_size_ = sizeof(gr_complex); + tracking_ = galileo_e1_dll_pll_veml_make_tracking_cc( + f_if, + fs_in, + vector_length, + queue_, + dump, + dump_filename, + pll_bw_hz, + dll_bw_hz, + early_late_space_chips, + very_early_late_space_chips); + } + else + { + LOG_AT_LEVEL(WARNING) << item_type << " unknown tracking item type."; + } + + DLOG(INFO) << "tracking(" << tracking_->unique_id() << ")"; +} + +GalileoE1DllPllVemlTracking::~GalileoE1DllPllVemlTracking() +{ +} + +void GalileoE1DllPllVemlTracking::start_tracking() +{ + tracking_->start_tracking(); +} + +/* + * Set tracking channel unique ID + */ +void GalileoE1DllPllVemlTracking::set_channel(unsigned int channel) +{ + channel_ = channel; + tracking_->set_channel(channel); +} + +/* + * Set tracking channel internal queue + */ +void GalileoE1DllPllVemlTracking::set_channel_queue( + concurrent_queue *channel_internal_queue) +{ + channel_internal_queue_ = channel_internal_queue; + + tracking_->set_channel_queue(channel_internal_queue_); + +} + +void GalileoE1DllPllVemlTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) +{ + tracking_->set_gnss_synchro(p_gnss_synchro); +} + +void GalileoE1DllPllVemlTracking::connect(gr_top_block_sptr top_block) +{ + //nothing to connect, now the tracking uses gr_sync_decimator +} + +void GalileoE1DllPllVemlTracking::disconnect(gr_top_block_sptr top_block) +{ + //nothing to disconnect, now the tracking uses gr_sync_decimator +} + +gr_basic_block_sptr GalileoE1DllPllVemlTracking::get_left_block() +{ + return tracking_; +} + +gr_basic_block_sptr GalileoE1DllPllVemlTracking::get_right_block() +{ + return tracking_; +} + diff --git a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.h b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.h new file mode 100644 index 000000000..04c8b64bf --- /dev/null +++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.h @@ -0,0 +1,113 @@ +/*! + * \file galileo_e1_dll_pll_veml_tracking.h + * \brief Interface of an adapter of a DLL+PLL VEML (Very Early Minus Late) + * tracking loop block for Galileo E1 to a TrackingInterface + * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com + * + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkha user, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2012 (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_GALILEO_E1_DLL_PLL_VEML_TRACKING_H_ +#define GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_H_ + +#include "tracking_interface.h" +#include "galileo_e1_dll_pll_veml_tracking_cc.h" +#include + +class ConfigurationInterface; + +/*! + * \brief This class implements a code DLL + carrier PLL tracking loop + */ +class GalileoE1DllPllVemlTracking : public TrackingInterface +{ + +public: + + GalileoE1DllPllVemlTracking(ConfigurationInterface* configuration, + std::string role, + unsigned int in_streams, + unsigned int out_streams, + gr_msg_queue_sptr queue); + + virtual ~GalileoE1DllPllVemlTracking(); + + std::string role() + { + return role_; + } + std::string implementation() + { + return "Galileo_E1_DLL_PLL_VEML_Tracking"; + } + size_t item_size() + { + return item_size_; + } + + void connect(gr_top_block_sptr top_block); + void disconnect(gr_top_block_sptr top_block); + gr_basic_block_sptr get_left_block(); + gr_basic_block_sptr get_right_block(); + + + /*! + * \brief Set tracking channel unique ID + */ + void set_channel(unsigned int channel); + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); + + /*! + * \brief Set tracking channel internal queue + */ + void set_channel_queue(concurrent_queue *channel_internal_queue); + + void start_tracking(); + +private: + + galileo_e1_dll_pll_veml_tracking_cc_sptr tracking_; + size_t item_size_; + + unsigned int channel_; + + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + gr_msg_queue_sptr queue_; + concurrent_queue *channel_internal_queue_; +}; + +#endif // GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_H_ diff --git a/src/algorithms/tracking/adapters/jamfile.jam b/src/algorithms/tracking/adapters/jamfile.jam index 65eb52271..a81b55b40 100644 --- a/src/algorithms/tracking/adapters/jamfile.jam +++ b/src/algorithms/tracking/adapters/jamfile.jam @@ -2,4 +2,5 @@ project : build-dir ../../../../build ; obj gps_l1_ca_dll_pll_tracking : gps_l1_ca_dll_pll_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; obj gps_l1_ca_dll_fll_pll_tracking : gps_l1_ca_dll_fll_pll_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; -obj gps_l1_ca_tcp_connector_tracking : gps_l1_ca_tcp_connector_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; \ No newline at end of file +obj gps_l1_ca_tcp_connector_tracking : gps_l1_ca_tcp_connector_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; +obj galileo_e1_dll_pll_veml_tracking : galileo_e1_dll_pll_veml_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; \ No newline at end of file diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc new file mode 100644 index 000000000..92b8196c7 --- /dev/null +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc @@ -0,0 +1,681 @@ +/*! + * \file galileo_e1_dll_pll_veml_tracking_cc.cc + * \brief Implementation of a code DLL + carrier PLL bump-jump tracking + * block + * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com + * + * Code DLL + carrier PLL according to the algorithms described in: + * [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkha user, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2011 (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 "gnss_synchro.h" +#include "galileo_e1_dll_pll_veml_tracking_cc.h" +#include "galileo_e1_signal_processing.h" +#include "tracking_discriminators.h" +#include "CN_estimators.h" +#include "GPS_L1_CA.h" +#include "Galileo_E1.h" +#include "control_message_factory.h" +#include +#include +#include +#include +#include "math.h" +#include +#include +#include + +/*! + * \todo Include in definition header file + */ +#define CN0_ESTIMATION_SAMPLES 10 +#define MINIMUM_VALID_CN0 25 +#define MAXIMUM_LOCK_FAIL_COUNTER 200 + + +using google::LogMessage; + +galileo_e1_dll_pll_veml_tracking_cc_sptr +galileo_e1_dll_pll_veml_make_tracking_cc( + long if_freq, + long fs_in, + unsigned int vector_length, + gr_msg_queue_sptr queue, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips, + float very_early_late_space_chips) +{ + return galileo_e1_dll_pll_veml_tracking_cc_sptr(new galileo_e1_dll_pll_veml_tracking_cc(if_freq, + fs_in, vector_length, queue, dump, dump_filename, pll_bw_hz, dll_bw_hz, early_late_space_chips, very_early_late_space_chips)); +} + + + +void galileo_e1_dll_pll_veml_tracking_cc::forecast (int noutput_items, + gr_vector_int &ninput_items_required) +{ + ninput_items_required[0] = (int)d_vector_length*2; //set the required available samples in each call +} + + + +galileo_e1_dll_pll_veml_tracking_cc::galileo_e1_dll_pll_veml_tracking_cc( + long if_freq, + long fs_in, + unsigned int vector_length, + gr_msg_queue_sptr queue, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips, + float very_early_late_space_chips): + gr_block ("galileo_e1_dll_pll_veml_tracking_cc", gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(Gnss_Synchro))) +{ + d_debug_counter = 0; + this->set_relative_rate(1.0/vector_length); + // initialize internal vars + d_queue = queue; + d_dump = dump; + d_if_freq = if_freq; + d_fs_in = fs_in; + d_vector_length = vector_length; + d_dump_filename = dump_filename; + d_code_loop_filter=Tracking_2nd_DLL_filter(0.004); + d_carrier_loop_filter=Tracking_2nd_PLL_filter(0.004); + + // Initialize tracking ========================================== + + d_code_loop_filter.set_DLL_BW(dll_bw_hz); + d_carrier_loop_filter.set_PLL_BW(pll_bw_hz); + + //--- DLL variables -------------------------------------------------------- + d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips) + d_very_early_late_spc_chips = very_early_late_space_chips; // Define very-early-late offset (in chips) + + // Initialization of local code replica + // Get space for a vector with the sinboc(1,1) replica sampled 2x/chip +// int d_ca_code_size = (int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS + 4); + d_ca_code = new gr_complex[(int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS + 4)]; + +// std::cout << "d_ca_code_size = " << d_ca_code_size << std::endl; + + /* If an array is partitioned for more than one thread to operate on, + * having the sub-array boundaries unaligned to cache lines could lead + * to performance degradation. Here we allocate memory + * (gr_comlex array of size 2*d_vector_length) aligned to cache of 16 bytes + */ + // todo: do something if posix_memalign fails + // Get space for the resampled early / prompt / late local replicas + if (posix_memalign((void**)&d_very_early_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + if (posix_memalign((void**)&d_early_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + if (posix_memalign((void**)&d_prompt_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + if (posix_memalign((void**)&d_late_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + if (posix_memalign((void**)&d_very_late_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + // space for carrier wipeoff and signal baseband vectors + if (posix_memalign((void**)&d_carr_sign, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + // correlator outputs (scalar) + if (posix_memalign((void**)&d_Very_Early, 16, sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_Early, 16, sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_Prompt, 16, sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_Late, 16, sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_Very_Late, 16, sizeof(gr_complex)) == 0){}; + + + //--- Perform initializations ------------------------------ + // define initial code frequency basis of NCO + d_code_freq_hz = Galileo_E1_CODE_CHIP_RATE_HZ; + // define residual code phase (in chips) + d_rem_code_phase_samples = 0.0; + // define residual carrier phase + d_rem_carr_phase_rad = 0.0; + // define phase step + d_code_phase_step_chips = d_code_freq_hz / (float)d_fs_in; //[chips] + + // sample synchronization + d_sample_counter = 0; + //d_sample_counter_seconds = 0; + d_acq_sample_stamp = 0; + + d_enable_tracking = false; + d_pull_in = false; + d_last_seg = 0; + + d_current_prn_length_samples = (int)d_vector_length; + + // CN0 estimation and lock detector buffers + d_cn0_estimation_counter = 0; + d_Prompt_buffer = new gr_complex[CN0_ESTIMATION_SAMPLES]; + d_carrier_lock_test = 1; + d_CN0_SNV_dB_Hz = 0; + d_carrier_lock_fail_counter = 0; + d_carrier_lock_threshold = 20; + + systemName["G"] = std::string("GPS"); + systemName["R"] = std::string("GLONASS"); + systemName["S"] = std::string("SBAS"); + systemName["E"] = std::string("Galileo"); + systemName["C"] = std::string("Compass"); +} + +void galileo_e1_dll_pll_veml_tracking_cc::start_tracking() +{ + + d_acq_code_phase_samples = d_acquisition_gnss_synchro->Acq_delay_samples; + d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz; + d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples; + +// std::cout << "d_acq_code_phase_samples = " << d_acq_code_phase_samples << std::endl; +// std::cout << "d_acq_carrier_doppler_hz = " << d_acq_carrier_doppler_hz << std::endl; +// std::cout << "d_acq_sample_stamp = " << d_acq_sample_stamp << std::endl; + + // DLL/PLL filter initialization + d_carrier_loop_filter.initialize(d_acq_carrier_doppler_hz); //initialize the carrier filter + d_code_loop_filter.initialize(d_acq_code_phase_samples); //initialize the code filter + + + // generate local reference ALWAYS starting at chip 2 (2 samples per chip) + +// std::cout << "PRN = " << d_acquisition_gnss_synchro->PRN << std::endl; +// std::cout << "Signal = " << d_acquisition_gnss_synchro->Signal << std::endl; +// std::cout << "fs_gen = " << 2*Galileo_E1_CODE_CHIP_RATE_HZ << std::endl; + galileo_e1_code_gen_complex_sampled(&d_ca_code[2],d_acquisition_gnss_synchro->Signal, false, d_acquisition_gnss_synchro->PRN, 2*Galileo_E1_CODE_CHIP_RATE_HZ, 0); + +// std::cout << "Local code generated." << std::endl; +// for(int i=0;i<25; i++) std::cout << d_ca_code[i]; +// std::cout << std::endl; +// for(int i=(int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS-6);i<(int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS+4); i++) std::cout << d_ca_code[i]; +// std::cout << std::endl; +// +// int index = (int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS); + d_ca_code[0] = d_ca_code[(int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS)]; +// std::cout << "d_ca_code[0] = d_ca_code[" << index <<"]" << std::endl; +// index = (int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS+1); + d_ca_code[1] = d_ca_code[(int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS+1)]; +// std::cout << "d_ca_code[1] = d_ca_code[" << index <<"]" << std::endl; +// index = (int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS+2); + d_ca_code[(int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS+2)] = d_ca_code[2]; +// std::cout << "d_ca_code[" << index <<"] = d_ca_code[2]" << std::endl; +// index = (int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS+3); + d_ca_code[(int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS+3)] = d_ca_code[3]; +// std::cout << "d_ca_code[" << index <<"] = d_ca_code[3]" << std::endl; +// for(int i=0;i<25; i++) std::cout << d_ca_code[i]; +// std::cout << std::endl; + d_carrier_lock_fail_counter = 0; + d_rem_code_phase_samples = 0.0; + d_rem_carr_phase_rad = 0; + d_next_rem_code_phase_samples = 0; + d_acc_carrier_phase_rad = 0; + + d_code_phase_samples = d_acq_code_phase_samples; + d_carrier_doppler_hz = d_acq_carrier_doppler_hz; + + d_next_prn_length_samples = d_vector_length; + + std::string sys_ = &d_acquisition_gnss_synchro->System; + sys = sys_.substr(0,1); + + // DEBUG OUTPUT + std::cout << "Tracking start on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl; + DLOG(INFO) << "Start tracking for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << " received" << std::endl; + + // enable tracking + d_pull_in = true; + d_enable_tracking = true; + + std::cout << "PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz + << " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples << std::endl; +} + + + + + +void galileo_e1_dll_pll_veml_tracking_cc::update_local_code() +{ + + double tcode_half_chips; + float rem_code_phase_half_chips; + int associated_chip_index; + int code_length_half_chips = (int)(2*Galileo_E1_B_CODE_LENGTH_CHIPS); + double code_phase_step_chips; + double code_phase_step_half_chips; + int early_late_spc_samples; + int very_early_late_spc_samples; + int epl_loop_length_samples; + + // unified loop for E, P, L code vectors + code_phase_step_chips = ((double)d_code_freq_hz) / ((double)d_fs_in); + code_phase_step_half_chips = (2.0*(double)d_code_freq_hz) / ((double)d_fs_in); + + rem_code_phase_half_chips = d_rem_code_phase_samples * (2*d_code_freq_hz / d_fs_in); + tcode_half_chips = -(double)rem_code_phase_half_chips; + + early_late_spc_samples=round(d_early_late_spc_chips/code_phase_step_chips); + very_early_late_spc_samples=round(d_very_early_late_spc_chips/code_phase_step_chips); + + epl_loop_length_samples=d_current_prn_length_samples+very_early_late_spc_samples*2; + +// if(d_debug_counter<10){ +// std::cout << std::endl; +// std::cout << "======= DEBUG " << d_debug_counter << " ========" << std::endl << std::endl; +// std::cout << "rem_code_phase_half_chips = " << rem_code_phase_half_chips << std::endl; +// std::cout << "code_phase_step_chips = " << code_phase_step_chips << std::endl; +// std::cout << "code_phase_step_half_chips = " << code_phase_step_half_chips << std::endl; +// std::cout << "early_late_spc_samples = " << early_late_spc_samples << std::endl; +// std::cout << "very_early_late_spc_samples = " << very_early_late_spc_samples << std::endl; +// std::cout << "d_current_prn_length_samples = " << d_current_prn_length_samples << std::endl; +// std::cout << "epl_loop_length_samples = " << epl_loop_length_samples << std::endl << std::endl; +// } + + for (int i=0; ipush(tracking_message); + ControlMessageFactory* cmf = new ControlMessageFactory(); + if (d_queue != gr_msg_queue_sptr()) { + d_queue->handle(cmf->GetQueueMessage(d_channel, 2)); + } + delete cmf; + d_carrier_lock_fail_counter = 0; + d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine + + } + //std::cout<<"d_carrier_lock_fail_counter"<PRN) + << ", CN0 = " << d_CN0_SNV_dB_Hz << " [dB-Hz]" << std::endl; + //std::cout<<"TRK CH "<PRN) + << ", CN0 = " << d_CN0_SNV_dB_Hz << " [dB-Hz]" << std::endl; + } + } + } + else + { + *d_Early = gr_complex(0,0); + *d_Prompt = gr_complex(0,0); + *d_Late = gr_complex(0,0); + Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; //block output streams pointer + //std::cout<telemetry_decoder + Gnss_Synchro current_synchro_data; + *out[0] = current_synchro_data; + } + + if(d_dump) + { + // MULTIPLEXED FILE RECORDING - Record results to file + float prompt_I; + float prompt_Q; + float tmp_VE, tmp_E, tmp_P, tmp_L, tmp_VL; + float tmp_float; + double tmp_double; + prompt_I = (*d_Prompt).imag(); + prompt_Q = (*d_Prompt).real(); + tmp_VE = std::abs(*d_Very_Early); + tmp_E = std::abs(*d_Early); + tmp_P = std::abs(*d_Prompt); + tmp_L = std::abs(*d_Late); + tmp_VL = std::abs(*d_Very_Late); + + try + { + // EPR + d_dump_file.write((char*)&tmp_VE, sizeof(float)); + d_dump_file.write((char*)&tmp_E, sizeof(float)); + d_dump_file.write((char*)&tmp_P, sizeof(float)); + d_dump_file.write((char*)&tmp_L, sizeof(float)); + d_dump_file.write((char*)&tmp_VL, sizeof(float)); + // PROMPT I and Q (to analyze navigation symbols) + d_dump_file.write((char*)&prompt_I, sizeof(float)); + d_dump_file.write((char*)&prompt_Q, sizeof(float)); + // PRN start sample stamp + d_dump_file.write((char*)&d_sample_counter, sizeof(unsigned long int)); + // accumulated carrier phase + d_dump_file.write((char*)&d_acc_carrier_phase_rad, sizeof(float)); + + // carrier and code frequency + d_dump_file.write((char*)&d_carrier_doppler_hz, sizeof(float)); + d_dump_file.write((char*)&d_code_freq_hz, sizeof(float)); + + //PLL commands + d_dump_file.write((char*)&carr_error, sizeof(float)); + d_dump_file.write((char*)&carr_nco, sizeof(float)); + + //DLL commands + d_dump_file.write((char*)&code_error, sizeof(float)); + d_dump_file.write((char*)&code_nco, sizeof(float)); + + // CN0 and carrier lock test + d_dump_file.write((char*)&d_CN0_SNV_dB_Hz, sizeof(float)); + d_dump_file.write((char*)&d_carrier_lock_test, sizeof(float)); + + // AUX vars (for debug purposes) + tmp_float = d_rem_code_phase_samples; + d_dump_file.write((char*)&tmp_float, sizeof(float)); + tmp_double=(double)(d_sample_counter+d_current_prn_length_samples); + d_dump_file.write((char*)&tmp_double, sizeof(double)); +// if(d_debug_counter < 10){ +// std::cout << std::endl; +// std::cout << "d_debug_counter = " << d_debug_counter << std::endl; +// std::cout << "VE = " << tmp_VE << ", E = " << tmp_E << ", P = "<< tmp_P << ", L = " << tmp_L << ", VL = " << tmp_VL << std::endl << std::endl; +// } + } + catch (std::ifstream::failure e) + { + std::cout << "Exception writing trk dump file " << e.what() << std::endl; + } + } +// if(d_current_prn_length_samples!=d_vector_length) +// std::cout << "d_current_prn_length_samples = " << d_current_prn_length_samples << std::endl; + consume_each(d_current_prn_length_samples); // this is necesary in gr_block derivates + d_sample_counter += d_current_prn_length_samples; //count for the processed samples + d_debug_counter++; + return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false +} + + + +void galileo_e1_dll_pll_veml_tracking_cc::set_channel(unsigned int channel) +{ + d_channel = channel; + LOG_AT_LEVEL(INFO) << "Tracking Channel set to " << d_channel; + // ############# ENABLE DATA FILE LOG ################# + if (d_dump==true) + { + if (d_dump_file.is_open() == false) + { + try + { + d_dump_filename.append(boost::lexical_cast(d_channel)); + d_dump_filename.append(".dat"); + d_dump_file.exceptions (std::ifstream::failbit | std::ifstream::badbit); + d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary); + std::cout << "Tracking dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str() << std::endl; + } + catch (std::ifstream::failure e) + { + std::cout << "channel " << d_channel << " Exception opening trk dump file " << e.what() << std::endl; + } + } + } +} + + + +void galileo_e1_dll_pll_veml_tracking_cc::set_channel_queue(concurrent_queue *channel_internal_queue) +{ + d_channel_internal_queue = channel_internal_queue; +} + +void galileo_e1_dll_pll_veml_tracking_cc::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) +{ + d_acquisition_gnss_synchro = p_gnss_synchro; + + // Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); + //DLOG(INFO) << "Tracking code phase set to " << d_acq_code_phase_samples; + //DLOG(INFO) << "Tracking carrier doppler set to " << d_acq_carrier_doppler_hz; + //DLOG(INFO) << "Tracking Satellite set to " << d_satellite; + +} diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.h b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.h new file mode 100644 index 000000000..eb8602f26 --- /dev/null +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.h @@ -0,0 +1,206 @@ +/*! + * \file galileo_e1_dll_pll_veml_trakcing_cc.h + * \brief Implementation of a code DLL + carrier PLL bump-jump tracking + * block + * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com + * + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency Approach, + * Birkhauser, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2012 (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_GALILEO_E1_DLL_PLL_VEML_TRACKING_CC_H +#define GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_CC_H + +#include +#include +#include +#include +#include +#include + +#include "concurrent_queue.h" +#include "gnss_synchro.h" +#include "tracking_2nd_DLL_filter.h" +#include "tracking_2nd_PLL_filter.h" +#include "correlator.h" + + + +class galileo_e1_dll_pll_veml_tracking_cc; +typedef boost::shared_ptr +galileo_e1_dll_pll_veml_tracking_cc_sptr; + +galileo_e1_dll_pll_veml_tracking_cc_sptr +galileo_e1_dll_pll_veml_make_tracking_cc(long if_freq, + long fs_in, unsigned + int vector_length, + gr_msg_queue_sptr queue, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips, + float very_early_late_space_chips); + +/*! + * \brief This class implements a DLL + PLL bump-jump tracking loop block + */ +class galileo_e1_dll_pll_veml_tracking_cc: public gr_block +{ +public: + + ~galileo_e1_dll_pll_veml_tracking_cc(); + + void set_channel(unsigned int channel); + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); + void start_tracking(); + void set_channel_queue(concurrent_queue *channel_internal_queue); + + + int general_work (int noutput_items, gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + +private: + + friend galileo_e1_dll_pll_veml_tracking_cc_sptr + galileo_e1_dll_pll_veml_make_tracking_cc(long if_freq, + long fs_in, unsigned + int vector_length, + gr_msg_queue_sptr queue, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips, + float very_early_late_space_chips); + + galileo_e1_dll_pll_veml_tracking_cc(long if_freq, + long fs_in, unsigned + int vector_length, + gr_msg_queue_sptr queue, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips, + float very_early_late_space_chips); + + void update_local_code(); + + void update_local_carrier(); + + // tracking configuration vars + gr_msg_queue_sptr d_queue; + concurrent_queue *d_channel_internal_queue; + unsigned int d_vector_length; + bool d_dump; + + Gnss_Synchro* d_acquisition_gnss_synchro; + unsigned int d_channel; + int d_last_seg; + long d_if_freq; + long d_fs_in; + + float d_early_late_spc_chips; + float d_very_early_late_spc_chips; + + float d_code_phase_step_chips; + + gr_complex* d_ca_code; + + gr_complex* d_very_early_code; + gr_complex* d_early_code; + gr_complex* d_prompt_code; + gr_complex* d_late_code; + gr_complex* d_very_late_code; + gr_complex* d_carr_sign; + + gr_complex *d_Very_Early; + gr_complex *d_Early; + gr_complex *d_Prompt; + gr_complex *d_Late; + gr_complex *d_Very_Late; + + // remaining code phase and carrier phase between tracking loops + float d_rem_code_phase_samples; + float d_next_rem_code_phase_samples; + float d_rem_carr_phase_rad; + + // PLL and DLL filter library + Tracking_2nd_DLL_filter d_code_loop_filter; + Tracking_2nd_PLL_filter d_carrier_loop_filter; + + // acquisition + float d_acq_code_phase_samples; + float d_acq_carrier_doppler_hz; + + // correlator + Correlator d_correlator; + + // tracking vars + float d_code_freq_hz; + float d_carrier_doppler_hz; + float d_acc_carrier_phase_rad; + float d_code_phase_samples; + + //PRN period in samples + int d_current_prn_length_samples; + int d_next_prn_length_samples; + //double d_sample_counter_seconds; + + //processing samples counters + unsigned long int d_sample_counter; + unsigned long int d_acq_sample_stamp; + + // CN0 estimation and lock detector + int d_cn0_estimation_counter; + gr_complex* d_Prompt_buffer; + float d_carrier_lock_test; + float d_CN0_SNV_dB_Hz; + float d_carrier_lock_threshold; + int d_carrier_lock_fail_counter; + + // control vars + bool d_enable_tracking; + bool d_pull_in; + + // file dump + std::string d_dump_filename; + std::ofstream d_dump_file; + + std::map systemName; + std::string sys; + + //debug + int d_debug_counter; +}; + +#endif //GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_CC_H diff --git a/src/algorithms/tracking/gnuradio_blocks/jamfile.jam b/src/algorithms/tracking/gnuradio_blocks/jamfile.jam index a9f9b1ea0..7be2fd5d6 100644 --- a/src/algorithms/tracking/gnuradio_blocks/jamfile.jam +++ b/src/algorithms/tracking/gnuradio_blocks/jamfile.jam @@ -2,4 +2,5 @@ project : build-dir ../../../../build ; obj gps_l1_ca_dll_pll_tracking_cc : gps_l1_ca_dll_pll_tracking_cc.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; obj gps_l1_ca_dll_fll_pll_tracking_cc : gps_l1_ca_dll_fll_pll_tracking_cc.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; -obj gps_l1_ca_tcp_connector_tracking_cc : gps_l1_ca_tcp_connector_tracking_cc.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; \ No newline at end of file +obj gps_l1_ca_tcp_connector_tracking_cc : gps_l1_ca_tcp_connector_tracking_cc.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; +obj galileo_e1_dll_pll_veml_tracking_cc : galileo_e1_dll_pll_veml_tracking_cc.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; diff --git a/src/algorithms/tracking/libs/CN_estimators.cc b/src/algorithms/tracking/libs/CN_estimators.cc index 20ce4d933..d9c885ea5 100644 --- a/src/algorithms/tracking/libs/CN_estimators.cc +++ b/src/algorithms/tracking/libs/CN_estimators.cc @@ -42,6 +42,7 @@ */ #include "CN_estimators.h" #include "GPS_L1_CA.h" +#include "Galileo_E1.h" #include #include @@ -87,6 +88,47 @@ float gps_l1_ca_CN0_SNV(gr_complex* Prompt_buffer, int length, long fs_in) return SNR_dB_Hz; } +/* + * Signal-to-Noise (SNR) (\f$\rho\f$) estimator using the Signal-to-Noise Variance (SNV) estimator: + * \f{equation} + * \hat{\rho}=\frac{\hat{P}_s}{\hat{P}_n}=\frac{\hat{P}_s}{\hat{P}_{tot}-\hat{P}_s}, + * \f} + * where \f$\hat{P}_s=\left(\frac{1}{N}\sum^{N-1}_{i=0}|Re(Pc(i))|\right)^2\f$ is the estimation of the signal power, + * \f$\hat{P}_{tot}=\frac{1}{N}\sum^{N-1}_{i=0}|Pc(i)|^2\f$ is the estimator of the total power, \f$|\cdot|\f$ is the absolute value, + * \f$Re(\cdot)\f$ stands for the real part of the value, and \f$Pc(i)\f$ is the prompt correlator output for the sample index i. + * + * The SNR value is converted to CN0 [dB-Hz], taking to account the receiver bandwidth and the PRN code gain, using the following formula: + * \f{equation} + * CN0_{dB}=10*log(\hat{\rho})+10*log(\frac{f_s}{2})-10*log(L_{PRN}), + * \f} + * where \f$f_s\f$ is the sampling frequency and \f$L_{PRN}\f$ is the PRN sequence length. + * + */ +float galileo_e1_CN0_SNV(gr_complex* Prompt_buffer, int length, long fs_in) +{ + // estimate CN0 using buffered values + // MATLAB CODE + // Psig=((1/N)*sum(abs(imag(x((n-N+1):n)))))^2; + // Ptot=(1/N)*sum(abs(x((n-N+1):n)).^2); + // SNR_SNV(count)=Psig/(Ptot-Psig); + // CN0_SNV_dB=10*log10(SNR_SNV)+10*log10(BW)-10*log10(PRN_length); + float SNR, SNR_dB_Hz; + float tmp_abs_imag; + float Psig, Ptot; + Psig = 0; + Ptot = 0; + for (int i=0; i. + * + * ------------------------------------------------------------------------- + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gnss_block_factory.h" +#include "gnss_block_interface.h" +#include "in_memory_configuration.h" +#include "gnss_sdr_valve.h" +#include "gnss_synchro.h" + +#include "galileo_e1_dll_pll_veml_tracking.h" + +class GalileoE1DllPllVemlTrackingInternalTest: public ::testing::Test { +protected: + GalileoE1DllPllVemlTrackingInternalTest() { + queue = gr_make_msg_queue(0); + top_block = gr_make_top_block("Tracking test"); + factory = new GNSSBlockFactory(); + config = new InMemoryConfiguration(); + item_size = sizeof(gr_complex); + stop = false; + message = 0; + } + + ~GalileoE1DllPllVemlTrackingInternalTest() { + delete factory; + delete config; + } + + void init(); + void start_queue(); + void wait_message(); + void stop_queue(); + + gr_msg_queue_sptr queue; + gr_top_block_sptr top_block; + GNSSBlockFactory* factory; + InMemoryConfiguration* config; + Gnss_Synchro gnss_synchro; + size_t item_size; + concurrent_queue channel_internal_queue; + bool stop; + int message; + boost::thread ch_thread; +}; + +void GalileoE1DllPllVemlTrackingInternalTest::init(){ + + gnss_synchro.Channel_ID=0; + gnss_synchro.System = 'E'; + std::string signal = "1B"; + signal.copy(gnss_synchro.Signal,2,0); + gnss_synchro.PRN=11; + + config->set_property("GNSS-SDR.internal_fs_hz", "8000000"); + config->set_property("Tracking.item_type", "gr_complex"); + config->set_property("Tracking.dump", "true"); + config->set_property("Tracking.dump_filename", "../data/veml_tracking_ch_"); + config->set_property("Tracking.implementation", "Galileo_E1_DLL_PLL_Tracking"); + config->set_property("Tracking.early_late_space_chips", "0.15"); + config->set_property("Tracking.very_early_late_space_chips", "0.6"); + config->set_property("Tracking.pll_bw_hz", "30.0"); + config->set_property("Tracking.dll_bw_hz", "2.0"); +} + +void GalileoE1DllPllVemlTrackingInternalTest::start_queue() +{ + ch_thread = boost::thread(&GalileoE1DllPllVemlTrackingInternalTest::wait_message, this); +} + + +void GalileoE1DllPllVemlTrackingInternalTest::wait_message() +{ + while (!stop) + { + channel_internal_queue.wait_and_pop(message); + stop_queue(); + } +} + +void GalileoE1DllPllVemlTrackingInternalTest::stop_queue() +{ + stop = true; + } + + + +TEST_F(GalileoE1DllPllVemlTrackingInternalTest, Instantiate) +{ + + init(); + + GalileoE1DllPllVemlTracking *tracking = new GalileoE1DllPllVemlTracking(config, "Tracking", 1, 1, queue); + EXPECT_STREQ("Galileo_E1_DLL_PLL_VEML_Tracking", tracking->implementation().c_str()); + + delete tracking; + +} + +//TEST_F(GalileoE1DllPllVemlTrackingInternalTest, ConnectAndRun) +//{ +// int fs_in = 8000000; +// int nsamples = 80000000; +// struct timeval tv; +// long long int begin; +// long long int end; +// +// init(); +// GalileoE1DllPllVemlTracking *tracking = new GalileoE1DllPllVemlTracking(config, "Tracking", 1, 1, queue); +// +// ASSERT_NO_THROW( { +// tracking->connect(top_block); +// +// gr_sig_source_c_sptr source = gr_make_sig_source_c(fs_in,GR_SIN_WAVE, 1000, 1, gr_complex(0)); +// gr_block_sptr valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue); +// gr_null_sink_sptr sink = gr_make_null_sink(sizeof(Gnss_Synchro)); +// top_block->connect(source, 0, valve, 0); +// top_block->connect(valve, 0, tracking->get_left_block(), 0); +// top_block->connect(tracking->get_right_block(), 0, sink, 0); +// +// }) << "Failure connecting the blocks of tracking test."<< std::endl; +// +// EXPECT_NO_THROW( { +// gettimeofday(&tv, NULL); +// begin = tv.tv_sec *1000000 + tv.tv_usec; +// top_block->run(); // Start threads and wait +// gettimeofday(&tv, NULL); +// end = tv.tv_sec *1000000 + tv.tv_usec; +// }) << "Failure running he top_block."<< std::endl; +// +// delete tracking; +// std::cout << "Processed " << nsamples << " samples in " << (end-begin) << " microseconds" << std::endl; +// +//} + +TEST_F(GalileoE1DllPllVemlTrackingInternalTest, ValidationOfResults) +{ + struct timeval tv; + long long int begin; + long long int end; +// int num_samples = 40000000; // 4 Msps +// unsigned int skiphead_sps = 24000000; // 4 Msps + int num_samples = 80000000; // 8 Msps + unsigned int skiphead_sps = 8000000; // 8 Msps + init(); + GalileoE1DllPllVemlTracking *tracking = new GalileoE1DllPllVemlTracking(config, "Tracking", 1, 1, queue); + +// gnss_synchro.Acq_delay_samples=1753; // 4 Msps +// gnss_synchro.Acq_doppler_hz=-9500; // 4 Msps + gnss_synchro.Acq_delay_samples=17256; // 8 Msps + gnss_synchro.Acq_doppler_hz=-8750; // 8 Msps + gnss_synchro.Acq_samplestamp_samples=0; + + ASSERT_NO_THROW( { + tracking->set_channel(gnss_synchro.Channel_ID); + }) << "Failure setting channel."<< std::endl; + + ASSERT_NO_THROW( { + tracking->set_gnss_synchro(&gnss_synchro); + }) << "Failure setting gnss_synchro."<< std::endl; + + ASSERT_NO_THROW( { + tracking->set_channel_queue(&channel_internal_queue); + }) << "Failure setting channel_internal_queue."<< std::endl; + + + ASSERT_NO_THROW( { + tracking->connect(top_block); + }) << "Failure connecting tracking to the top_block."<< std::endl; + + ASSERT_NO_THROW( { + std::string file = "/media/DATA/Proyectos/Signals/cttc_2012_07_26/cp_cttc_2012_07_26_n6_8Msps.dat"; +// std::string file = "/media/DATA/Proyectos/Signals/cttc_2012_07_26/cp_cttc_2012_07_26_n4_4Msps.dat"; +// std::string file = "/media/DATA/Proyectos/Signals/prueba.dat"; +// std::string file = "../data/resampler.dat"; + const char * file_name = file.c_str(); + gr_file_source_sptr file_source = gr_make_file_source(sizeof(gr_complex),file_name,false); + gr_skiphead_sptr skip_head = gr_make_skiphead(sizeof(gr_complex), skiphead_sps); + gr_block_sptr valve = gnss_sdr_make_valve(sizeof(gr_complex), num_samples, queue); + gr_null_sink_sptr sink = gr_make_null_sink(sizeof(Gnss_Synchro)); + top_block->connect(file_source, 0, skip_head, 0); + top_block->connect(skip_head, 0, valve, 0); + top_block->connect(valve, 0, tracking->get_left_block(), 0); + top_block->connect(tracking->get_right_block(), 0, sink, 0); + }) << "Failure connecting the blocks of tracking test."<< std::endl; + + + tracking->start_tracking(); + + EXPECT_NO_THROW( { + gettimeofday(&tv, NULL); + begin = tv.tv_sec *1000000 + tv.tv_usec; + top_block->run(); // Start threads and wait + gettimeofday(&tv, NULL); + end = tv.tv_sec *1000000 + tv.tv_usec; + }) << "Failure running he top_block."<< std::endl; + + std::cout << "Tracked " << num_samples << " samples in " << (end-begin) << " microseconds" << std::endl; + + delete tracking; + +} diff --git a/src/tests/jamfile.jam b/src/tests/jamfile.jam index 27c76e74b..6ccac679a 100644 --- a/src/tests/jamfile.jam +++ b/src/tests/jamfile.jam @@ -49,9 +49,11 @@ exe run_tests : test_main.cc ../algorithms/tracking/adapters//gps_l1_ca_dll_pll_tracking ../algorithms/tracking/adapters//gps_l1_ca_dll_fll_pll_tracking ../algorithms/tracking/adapters//gps_l1_ca_tcp_connector_tracking +../algorithms/tracking/adapters//galileo_e1_dll_pll_veml_tracking ../algorithms/tracking/gnuradio_blocks//gps_l1_ca_dll_pll_tracking_cc ../algorithms/tracking/gnuradio_blocks//gps_l1_ca_dll_fll_pll_tracking_cc ../algorithms/tracking/gnuradio_blocks//gps_l1_ca_tcp_connector_tracking_cc +../algorithms/tracking/gnuradio_blocks//galileo_e1_dll_pll_veml_tracking_cc ../algorithms/tracking/libs//tracking_discriminators ../algorithms/tracking/libs//CN_estimators ../algorithms/tracking/libs//tracking_FLL_PLL_filter diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index 148c92cd7..7a00dae06 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -64,10 +64,9 @@ #include "gnss_block/gps_l1_ca_pcps_acquisition_test.cc" #include "gnss_block/galileo_e1_pcps_ambiguous_acquisition_test.cc" #include "gnss_block/galileo_e1_pcps_ambiguous_acquisition_gsoc_test.cc" -//#include "gnss_block/gps_l1_ca_dll_pll_tracking_test.cc" +//#include "gnss_block/galileo_e1_dll_pll_veml_tracking_test.cc" #include "gnss_block/file_output_filter_test.cc" #include "gnss_block/gnss_block_factory_test.cc" -//#include "gnss_block/direct_resampler_conditioner_test.cc" concurrent_queue global_gps_nav_msg_queue; diff --git a/src/utils/matlab/galileo_e1_dll_pll_veml_plot_sample_64bits.m b/src/utils/matlab/galileo_e1_dll_pll_veml_plot_sample_64bits.m new file mode 100644 index 000000000..798b5f30b --- /dev/null +++ b/src/utils/matlab/galileo_e1_dll_pll_veml_plot_sample_64bits.m @@ -0,0 +1,93 @@ +% /*! +% * \file galileo_l1_ca_dll_pll_vml_plot_sample_64bits.m +% * \brief Read GNSS-SDR Tracking dump binary file using the provided +% function and plot some internal variables +% * \author Javier Arribas, 2011. jarribas(at)cttc.es +% * ------------------------------------------------------------------------- +% * +% * Copyright (C) 2010-2011 (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 . +% * +% * ------------------------------------------------------------------------- +% */ +close all; +clear all; +samplingFreq = 64e6/8; %[Hz] +channels=1; +%path='/home/javier/workspace/gnss-sdr/trunk/install/'; +path='/home/luis/dev/gnss-sdr/trunk/data/'; +clear PRN_absolute_sample_start; +for N=1:1:channels + tracking_log_path=[path 'veml_tracking_ch_' num2str(N-1) '.dat']; + GNSS_tracking(N)= galileo_e1_dll_pll_veml_read_tracking_dump(tracking_log_path); +end + +% GNSS-SDR format conversion to MATLAB GPS receiver + +for N=1:1:channels + trackResults(N).status='T'; %fake track + trackResults(N).codeFreq=GNSS_tracking(N).code_freq_hz.'; + trackResults(N).carrFreq=GNSS_tracking(N).carrier_doppler_hz.'; + trackResults(N).dllDiscr = GNSS_tracking(N).code_error.'; + trackResults(N).dllDiscrFilt = GNSS_tracking(N).code_nco.'; + trackResults(N).pllDiscr = GNSS_tracking(N).carr_error.'; + trackResults(N).pllDiscrFilt = GNSS_tracking(N).carr_nco.'; + + trackResults(N).I_P=GNSS_tracking(N).prompt_I.'; + trackResults(N).Q_P=GNSS_tracking(N).prompt_Q.'; + + trackResults(N).I_VE= GNSS_tracking(N).VE.'; + trackResults(N).I_E= GNSS_tracking(N).E.'; + trackResults(N).I_L = GNSS_tracking(N).L.'; + trackResults(N).I_VL = GNSS_tracking(N).VL.'; + trackResults(N).Q_VE = zeros(1,length(GNSS_tracking(N).VE)); + trackResults(N).Q_E = zeros(1,length(GNSS_tracking(N).E)); + trackResults(N).Q_L =zeros(1,length(GNSS_tracking(N).L)); + trackResults(N).Q_VL =zeros(1,length(GNSS_tracking(N).VL)); + trackResults(N).PRN=N; %fake PRN + + % Use original MATLAB tracking plot function + settings.numberOfChannels=channels; + settings.msToProcess=length(GNSS_tracking(N).E)*4; + plotVEMLTracking(N,trackResults,settings) +end + +% for N=1:1:channels +% % figure; +% % plot([GNSS_tracking(N).E,GNSS_tracking(N).P,GNSS_tracking(N).L],'-*'); +% % title(['Early, Prompt, and Late correlator absolute value output for channel ' num2str(N)']); +% % figure; +% % plot(GNSS_tracking(N).prompt_I,GNSS_tracking(N).prompt_Q,'+'); +% % title(['Navigation constellation plot for channel ' num2str(N)]); +% % figure; +% % +% % plot(GNSS_tracking(N).prompt_Q,'r'); +% % hold on; +% % plot(GNSS_tracking(N).prompt_I); +% % title(['Navigation symbols I(red) Q(blue) for channel ' num2str(N)]); +% % +% figure; +% t=0:4:length(GNSS_tracking(N).carrier_doppler_hz)*4-1; +% t=t/1000; +% plot(t,GNSS_tracking(N).carrier_doppler_hz/1000); +% xlabel('Time(s)');ylabel('Doppler(KHz)');title(['Doppler frequency channel ' num2str(N)]); +% end + + diff --git a/src/utils/matlab/libs/galileo_e1_dll_pll_veml_read_tracking_dump.m b/src/utils/matlab/libs/galileo_e1_dll_pll_veml_read_tracking_dump.m new file mode 100644 index 000000000..4be05dd3a --- /dev/null +++ b/src/utils/matlab/libs/galileo_e1_dll_pll_veml_read_tracking_dump.m @@ -0,0 +1,192 @@ +% /*! +% * \file galileo_e1_dll_pll_veml_read_tracking_dump.m +% * \brief Read GNSS-SDR Tracking dump binary file into MATLAB. +% * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com +% * ------------------------------------------------------------------------- +% * +% * Copyright (C) 2010-2012 (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 . +% * +% * ------------------------------------------------------------------------- +% */ +function [GNSS_tracking] = galileo_e1_dll_pll_veml_read_tracking_dump (filename, count) + + %% usage: galileo_e1_dll_pll_veml_read_tracking_dump (filename, [count]) + %% + %% open GNSS-SDR tracking binary log file .dat and return the contents + %% + + m = nargchk (1,2,nargin); + num_float_vars=17; + num_unsigned_long_int_vars=1; + num_double_vars=1; + double_size_bytes=8; + unsigned_long_int_size_bytes=8; + float_size_bytes=4; + skip_bytes_each_read=float_size_bytes*num_float_vars+unsigned_long_int_size_bytes*num_unsigned_long_int_vars+double_size_bytes*num_double_vars; + bytes_shift=0; + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + %loops_counter = fread (f, count, 'uint32',4*12); + f = fopen (filename, 'rb'); + if (f < 0) + else + v1 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v2 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v3 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v4 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v5 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v6 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v7 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v8 = fread (f, count, 'uint64',skip_bytes_each_read-unsigned_long_int_size_bytes); + bytes_shift=bytes_shift+unsigned_long_int_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v9 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v10 = fread (f, count, '*float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v11 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v12 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v13 = fread (f, count, '*float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v14 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v15 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v16 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v17 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v18 = fread (f, count, 'float',skip_bytes_each_read-float_size_bytes); + bytes_shift=bytes_shift+float_size_bytes; + fseek(f,bytes_shift,'bof'); % move to next interleaved float + v19 = fread (f, count, 'float64',skip_bytes_each_read-double_size_bytes); + fclose (f); + + %%%%%%%% output vars %%%%%%%% + +% // EPR +% d_dump_file.write((char*)&tmp_VE, sizeof(float)); +% d_dump_file.write((char*)&tmp_E, sizeof(float)); +% d_dump_file.write((char*)&tmp_P, sizeof(float)); +% d_dump_file.write((char*)&tmp_L, sizeof(float)); +% d_dump_file.write((char*)&tmp_VL, sizeof(float)); +% // PROMPT I and Q (to analyze navigation symbols) +% d_dump_file.write((char*)&prompt_I, sizeof(float)); +% d_dump_file.write((char*)&prompt_Q, sizeof(float)); +% // PRN start sample stamp +% //tmp_float=(float)d_sample_counter; +% d_dump_file.write((char*)&d_sample_counter, sizeof(unsigned long int)); +% // accumulated carrier phase +% d_dump_file.write((char*)&d_acc_carrier_phase_rad, sizeof(float)); +% +% // carrier and code frequency +% d_dump_file.write((char*)&d_carrier_doppler_hz, sizeof(float)); +% d_dump_file.write((char*)&d_code_freq_hz, sizeof(float)); +% +% //PLL commands +% d_dump_file.write((char*)&carr_error, sizeof(float)); +% d_dump_file.write((char*)&carr_nco, sizeof(float)); +% +% //DLL commands +% d_dump_file.write((char*)&code_error, sizeof(float)); +% d_dump_file.write((char*)&code_nco, sizeof(float)); +% +% // CN0 and carrier lock test +% d_dump_file.write((char*)&d_CN0_SNV_dB_Hz, sizeof(float)); +% d_dump_file.write((char*)&d_carrier_lock_test, sizeof(float)); +% +% // AUX vars (for debug purposes) +% tmp_float = d_rem_code_phase_samples; +% d_dump_file.write((char*)&tmp_float, sizeof(float)); +% tmp_double=(double)(d_sample_counter+d_current_prn_length_samples); +% d_dump_file.write((char*)&tmp_double, sizeof(double)); + + VE=v1; + E=v2; + P=v3; + L=v4; + VL=v5; + prompt_I=v6; + prompt_Q=v7; + PRN_start_sample=v8; + acc_carrier_phase_rad=v9; + carrier_doppler_hz=v10; + code_freq_hz=v11; + carr_error=v12; + carr_nco=v13; + code_error=v14; + code_nco=v15; + CN0_SNV_dB_Hz=v16; + carrier_lock_test=v17; + var1=v18; + var2=v19; + + GNSS_tracking.VE=VE; + GNSS_tracking.E=E; + GNSS_tracking.P=P; + GNSS_tracking.L=L; + GNSS_tracking.VL=VL; + GNSS_tracking.prompt_I=prompt_I; + GNSS_tracking.prompt_Q=prompt_Q; + GNSS_tracking.PRN_start_sample=PRN_start_sample; + GNSS_tracking.acc_carrier_phase_rad=acc_carrier_phase_rad; + GNSS_tracking.carrier_doppler_hz=carrier_doppler_hz; + GNSS_tracking.code_freq_hz=code_freq_hz; + GNSS_tracking.carr_error=carr_error; + GNSS_tracking.carr_nco=carr_nco; + GNSS_tracking.code_error=code_error; + GNSS_tracking.code_nco=code_nco; + GNSS_tracking.CN0_SNV_dB_Hz=CN0_SNV_dB_Hz; + GNSS_tracking.carrier_lock_test=carrier_lock_test; + GNSS_tracking.var1=var1; + GNSS_tracking.var2=var2; + end + diff --git a/src/utils/matlab/libs/plotVEMLTracking.m b/src/utils/matlab/libs/plotVEMLTracking.m new file mode 100644 index 000000000..da219e102 --- /dev/null +++ b/src/utils/matlab/libs/plotVEMLTracking.m @@ -0,0 +1,159 @@ +function plotVEMLTracking(channelList, trackResults, settings) +%This function plots the tracking results for the given channel list. +% +%plotTracking(channelList, trackResults, settings) +% +% Inputs: +% channelList - list of channels to be plotted. +% trackResults - tracking results from the tracking function. +% settings - receiver settings. + +%-------------------------------------------------------------------------- +% SoftGNSS v3.0 +% +% Copyright (C) Darius Plausinaitis +% Written by Darius Plausinaitis +%-------------------------------------------------------------------------- +%This program 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 2 +%of the License, or (at your option) any later version. +% +%This program 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 this program; if not, write to the Free Software +%Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +%USA. +%-------------------------------------------------------------------------- + +%CVS record: +%$Id: plotTracking.m,v 1.5.2.23 2006/08/14 14:45:14 dpl Exp $ + +% Protection - if the list contains incorrect channel numbers +channelList = intersect(channelList, 1:settings.numberOfChannels); + +%=== For all listed channels ============================================== +for channelNr = channelList + +%% Select (or create) and clear the figure ================================ + % The number 200 is added just for more convenient handling of the open + % figure windows, when many figures are closed and reopened. + % Figures drawn or opened by the user, will not be "overwritten" by + % this function. + + figure(channelNr +200); + clf(channelNr +200); + set(channelNr +200, 'Name', ['Channel ', num2str(channelNr), ... + ' (PRN ', ... + num2str(trackResults(channelNr).PRN), ... + ') results']); + +%% Draw axes ============================================================== + % Row 1 + handles(1, 1) = subplot(3, 3, 1); + handles(1, 2) = subplot(3, 3, [2 3]); + % Row 2 + handles(2, 1) = subplot(3, 3, 4); + handles(2, 2) = subplot(3, 3, [5 6]); + % Row 3 + handles(3, 1) = subplot(3, 3, 7); + handles(3, 2) = subplot(3, 3, 8); + handles(3, 3) = subplot(3, 3, 9); + +%% Plot all figures ======================================================= + + timeAxisInSeconds = (1:4:settings.msToProcess)/1000; + + %----- Discrete-Time Scatter Plot --------------------------------- + plot(handles(1, 1), trackResults(channelNr).I_P,... + trackResults(channelNr).Q_P, ... + '.'); + + grid (handles(1, 1)); + axis (handles(1, 1), 'equal'); + title (handles(1, 1), 'Discrete-Time Scatter Plot'); + xlabel(handles(1, 1), 'I prompt'); + ylabel(handles(1, 1), 'Q prompt'); + + %----- Nav bits --------------------------------------------------- + plot (handles(1, 2), timeAxisInSeconds, ... + trackResults(channelNr).I_P); + + grid (handles(1, 2)); + title (handles(1, 2), 'Bits of the navigation message'); + xlabel(handles(1, 2), 'Time (s)'); + axis (handles(1, 2), 'tight'); + + %----- PLL discriminator unfiltered-------------------------------- + plot (handles(2, 1), timeAxisInSeconds, ... + trackResults(channelNr).pllDiscr, 'r'); + + grid (handles(2, 1)); + axis (handles(2, 1), 'tight'); + xlabel(handles(2, 1), 'Time (s)'); + ylabel(handles(2, 1), 'Amplitude'); + title (handles(2, 1), 'Raw PLL discriminator'); + + %----- Correlation ------------------------------------------------ + plot(handles(2, 2), timeAxisInSeconds, ... + [sqrt(trackResults(channelNr).I_VE.^2 + ... + trackResults(channelNr).Q_VE.^2)', ... + sqrt(trackResults(channelNr).I_E.^2 + ... + trackResults(channelNr).Q_E.^2)', ... + sqrt(trackResults(channelNr).I_P.^2 + ... + trackResults(channelNr).Q_P.^2)', ... + sqrt(trackResults(channelNr).I_L.^2 + ... + trackResults(channelNr).Q_L.^2)', ... + sqrt(trackResults(channelNr).I_VL.^2 + ... + trackResults(channelNr).Q_VL.^2)'], ... + '-*'); + + grid (handles(2, 2)); + title (handles(2, 2), 'Correlation results'); + xlabel(handles(2, 2), 'Time (s)'); + axis (handles(2, 2), 'tight'); + + hLegend = legend(handles(2, 2), '$\sqrt{I_{VE}^2 + Q_{VE}^2}$', ... + '$\sqrt{I_{E}^2 + Q_{E}^2}$', ... + '$\sqrt{I_{P}^2 + Q_{P}^2}$', ... + '$\sqrt{I_{L}^2 + Q_{L}^2}$', ... + '$\sqrt{I_{VL}^2 + Q_{VL}^2}$'); + + %set interpreter from tex to latex. This will draw \sqrt correctly + set(hLegend, 'Interpreter', 'Latex'); + + %----- PLL discriminator filtered---------------------------------- + plot (handles(3, 1), timeAxisInSeconds, ... + trackResults(channelNr).pllDiscrFilt, 'b'); + + grid (handles(3, 1)); + axis (handles(3, 1), 'tight'); + xlabel(handles(3, 1), 'Time (s)'); + ylabel(handles(3, 1), 'Amplitude'); + title (handles(3, 1), 'Filtered PLL discriminator'); + + %----- DLL discriminator unfiltered-------------------------------- + plot (handles(3, 2), timeAxisInSeconds, ... + trackResults(channelNr).dllDiscr, 'r'); + + grid (handles(3, 2)); + axis (handles(3, 2), 'tight'); + xlabel(handles(3, 2), 'Time (s)'); + ylabel(handles(3, 2), 'Amplitude'); + title (handles(3, 2), 'Raw DLL discriminator'); + + %----- DLL discriminator filtered---------------------------------- + plot (handles(3, 3), timeAxisInSeconds, ... + trackResults(channelNr).dllDiscrFilt, 'b'); + + grid (handles(3, 3)); + axis (handles(3, 3), 'tight'); + xlabel(handles(3, 3), 'Time (s)'); + ylabel(handles(3, 3), 'Amplitude'); + title (handles(3, 3), 'Filtered DLL discriminator'); + +end % for channelNr = channelList