From e59267228251ee559eec914a9b712af82864d3b9 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Wed, 20 Mar 2013 18:19:26 +0000 Subject: [PATCH] GPS L1 multi-dwell Assisted acquisition algorithm under construction. git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@352 64b25241-fba3-4117-9849-534c7e92360d --- .../acquisition/adapters/CMakeLists.txt | 1 + .../gps_l1_ca_pcps_assisted_acquisition.cc | 185 +++++++++++ .../gps_l1_ca_pcps_assisted_acquisition.h | 154 +++++++++ .../gnuradio_blocks/CMakeLists.txt | 5 +- .../pcps_assisted_acquisition_cc.cc | 311 ++++++++++++++++++ .../pcps_assisted_acquisition_cc.h | 229 +++++++++++++ src/core/libs/gnss_sdr_supl_client.cc | 1 + src/core/receiver/control_thread.cc | 201 ++++++----- src/core/receiver/control_thread.h | 2 + src/core/receiver/gnss_block_factory.cc | 6 + src/main/main.cc | 3 + 11 files changed, 1020 insertions(+), 78 deletions(-) create mode 100644 src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.cc create mode 100644 src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h create mode 100644 src/algorithms/acquisition/gnuradio_blocks/pcps_assisted_acquisition_cc.cc create mode 100644 src/algorithms/acquisition/gnuradio_blocks/pcps_assisted_acquisition_cc.h diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index 10839b0ac..4e9048b4d 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -19,6 +19,7 @@ set(ACQ_ADAPTER_SOURCES galileo_e1_pcps_ambiguous_acquisition.cc gps_l1_ca_pcps_acquisition.cc + gps_l1_ca_pcps_assisted_acquisition.cc ) include_directories( diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.cc new file mode 100644 index 000000000..532001ad2 --- /dev/null +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.cc @@ -0,0 +1,185 @@ +/*! + * \file gps_l1_ca_pcps_acquisition.cc + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * GPS L1 C/A Signals + * \authors + * + * ------------------------------------------------------------------------- + * + * 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 . + * + * ------------------------------------------------------------------------- + */ + +#include "gps_l1_ca_pcps_assisted_acquisition.h" +#include "gps_sdr_signal_processing.h" +#include "GPS_L1_CA.h" +#include "configuration_interface.h" +#include +#include +#include +#include + +using google::LogMessage; + +GpsL1CaPcpsAssistedAcquisition::GpsL1CaPcpsAssistedAcquisition( + 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) +{ + + std::string default_item_type = "gr_complex"; + std::string default_dump_filename = "./data/acquisition.dat"; + + DLOG(INFO) << "role " << role; + + item_type_ = configuration->property(role + ".item_type", + default_item_type); + + fs_in_ = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); + if_ = configuration->property(role + ".ifreq", 0); + dump_ = configuration->property(role + ".dump", false); + shift_resolution_ = configuration->property(role + ".doppler_max", 15); + sampled_ms_ = configuration->property(role + ".sampled_ms", 1); + max_dwells_= configuration->property(role + ".max_dwells", 1); + dump_filename_ = configuration->property(role + ".dump_filename", + default_dump_filename); + + //--- Find number of samples per spreading code ------------------------- + vector_length_ = round(fs_in_ + / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); + + code_= new gr_complex[vector_length_]; + + if (item_type_.compare("gr_complex") == 0) + { + item_size_ = sizeof(gr_complex); + acquisition_cc_ = pcps_make_assisted_acquisition_cc(max_dwells_,sampled_ms_, + shift_resolution_, if_, fs_in_, vector_length_, queue_, + dump_, dump_filename_); + + } + else + { + LOG_AT_LEVEL(WARNING) << item_type_ + << " unknown acquisition item type"; + } +} + + +GpsL1CaPcpsAssistedAcquisition::~GpsL1CaPcpsAssistedAcquisition() +{ + delete[] code_; +} + + +void GpsL1CaPcpsAssistedAcquisition::set_channel(unsigned int channel) +{ + channel_ = channel; + acquisition_cc_->set_channel(channel_); +} + + +void GpsL1CaPcpsAssistedAcquisition::set_threshold(float threshold) +{ + threshold_ = threshold; + acquisition_cc_->set_threshold(threshold_); +} + + +void GpsL1CaPcpsAssistedAcquisition::set_doppler_max(unsigned int doppler_max) +{ + doppler_max_ = doppler_max; + acquisition_cc_->set_doppler_max(doppler_max_); +} + + +void GpsL1CaPcpsAssistedAcquisition::set_doppler_step(unsigned int doppler_step) +{ + doppler_step_ = doppler_step; + acquisition_cc_->set_doppler_step(doppler_step_); +} + + +void GpsL1CaPcpsAssistedAcquisition::set_channel_queue( + concurrent_queue *channel_internal_queue) +{ + channel_internal_queue_ = channel_internal_queue; + acquisition_cc_->set_channel_queue(channel_internal_queue_); +} + + +void GpsL1CaPcpsAssistedAcquisition::set_gnss_synchro(Gnss_Synchro* gnss_synchro) +{ + gnss_synchro_ = gnss_synchro; + acquisition_cc_->set_gnss_synchro(gnss_synchro_); +} + + +signed int GpsL1CaPcpsAssistedAcquisition::mag() +{ + return acquisition_cc_->mag(); +} + + +void GpsL1CaPcpsAssistedAcquisition::init(){ + gps_l1_ca_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_, 0); + acquisition_cc_->set_local_code(code_); + acquisition_cc_->init(); +} + + +void GpsL1CaPcpsAssistedAcquisition::reset() +{ + acquisition_cc_->set_active(true); +} + + +void GpsL1CaPcpsAssistedAcquisition::connect(gr_top_block_sptr top_block) +{ + + //nothing to disconnect, now the tracking uses gr_sync_decimator + +} + + +void GpsL1CaPcpsAssistedAcquisition::disconnect(gr_top_block_sptr top_block) +{ + //nothing to disconnect, now the tracking uses gr_sync_decimator +} + + +gr_basic_block_sptr GpsL1CaPcpsAssistedAcquisition::get_left_block() +{ + return acquisition_cc_; +} + + +gr_basic_block_sptr GpsL1CaPcpsAssistedAcquisition::get_right_block() +{ + return acquisition_cc_; +} + diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h new file mode 100644 index 000000000..6f13dd847 --- /dev/null +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h @@ -0,0 +1,154 @@ +/*! + * \file gps_l1_ca_pcps_assisted_acquisition.h + * \brief Adapts a PCPS Assisted acquisition block to an AcquisitionInterface for + * GPS L1 C/A signals + * \authors
    + *
  • Javier Arribas, 2011. jarribas(at)cttc.es + *
* + * + * ------------------------------------------------------------------------- + * + * 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 . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_GPS_L1_CA_PCPS_ASSISTED_ACQUISITION_H_ +#define GNSS_SDR_GPS_L1_CA_PCPS_ASSISTED_ACQUISITION_H_ + +#include "gnss_synchro.h" +#include "acquisition_interface.h" +#include "pcps_assisted_acquisition_cc.h" +#include +#include + + +class ConfigurationInterface; + +/*! + * \brief This class adapts a PCPS acquisition block to an AcquisitionInterface + * for GPS L1 C/A signals + */ +class GpsL1CaPcpsAssistedAcquisition: public AcquisitionInterface +{ +public: + GpsL1CaPcpsAssistedAcquisition(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, + unsigned int out_streams, gr_msg_queue_sptr queue); + + virtual ~GpsL1CaPcpsAssistedAcquisition(); + + std::string role() + { + return role_; + } + + /*! + * \brief Returns "GPS_L1_CA_PCPS_Assisted_Acquisition" + */ + std::string implementation() + { + return "GPS_L1_CA_PCPS_Assisted_Acquisition"; + } + 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 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 acquisition channel unique ID + */ + void set_channel(unsigned int channel); + + /*! + * \brief Set statistics threshold of PCPS algorithm + */ + void set_threshold(float threshold); + + /*! + * \brief Set maximum Doppler off grid search + */ + void set_doppler_max(unsigned int doppler_max); + + /*! + * \brief Set Doppler steps for the grid search + */ + void set_doppler_step(unsigned int doppler_step); + + /*! + * \brief Set tracking channel internal queue + */ + void set_channel_queue(concurrent_queue *channel_internal_queue); + + /*! + * \brief Initializes acquisition algorithm. + */ + void init(); + + /*! + * \brief Returns the maximum peak of grid search + */ + signed int mag(); + + /*! + * \brief Restart acquisition algorithm + */ + void reset(); + +private: + pcps_assisted_acquisition_cc_sptr acquisition_cc_; + size_t item_size_; + std::string item_type_; + unsigned int vector_length_; + //unsigned int satellite_; + unsigned int channel_; + float threshold_; + unsigned int doppler_max_; + unsigned int doppler_step_; + unsigned int shift_resolution_; + unsigned int sampled_ms_; + int max_dwells_; + long fs_in_; + long if_; + bool dump_; + std::string dump_filename_; + std::complex * code_; + Gnss_Synchro * gnss_synchro_; + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + gr_msg_queue_sptr queue_; + concurrent_queue *channel_internal_queue_; +}; + +#endif /* GNSS_SDR_GPS_L1_CA_PCPS_ASSISTED_ACQUISITION_H_ */ diff --git a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt index ea056b773..e7860052e 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt @@ -16,7 +16,10 @@ # along with GNSS-SDR. If not, see . # -set(ACQ_GR_BLOCKS_SOURCES pcps_acquisition_cc.cc ) +set(ACQ_GR_BLOCKS_SOURCES + pcps_acquisition_cc.cc + pcps_assisted_acquisition_cc.cc +) include_directories( $(CMAKE_CURRENT_SOURCE_DIR) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_assisted_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_assisted_acquisition_cc.cc new file mode 100644 index 000000000..036f3d943 --- /dev/null +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_assisted_acquisition_cc.cc @@ -0,0 +1,311 @@ +/*! + * \file pcps_acquisition_cc.cc + * \brief This class implements a Parallel Code Phase Search Acquisition + * \authors
    + *
  • Javier Arribas, 2011. jarribas(at)cttc.es + *
  • 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 . + * + * ------------------------------------------------------------------------- + */ + +#include "pcps_assisted_acquisition_cc.h" +#include "gnss_signal_processing.h" +#include "control_message_factory.h" +#include +#include +#include +#include +#include + +using google::LogMessage; + +pcps_assisted_acquisition_cc_sptr pcps_make_assisted_acquisition_cc( + int max_dwells, unsigned int sampled_ms, unsigned int doppler_max, long freq, + long fs_in, int samples_per_ms, gr_msg_queue_sptr queue, bool dump, + std::string dump_filename) +{ + + return pcps_assisted_acquisition_cc_sptr( + new pcps_assisted_acquisition_cc(max_dwells, sampled_ms, doppler_max, freq, + fs_in, samples_per_ms, queue, dump, dump_filename)); +} + + + +pcps_assisted_acquisition_cc::pcps_assisted_acquisition_cc( + int max_dwells, unsigned int sampled_ms, unsigned int doppler_max, long freq, + long fs_in, int samples_per_ms, gr_msg_queue_sptr queue, bool dump, + std::string dump_filename) : + gr_block("pcps_assisted_acquisition_cc", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(0, 0, sizeof(gr_complex))) +{ + d_sample_counter = 0; // SAMPLE COUNTER + d_active = false; + d_queue = queue; + d_freq = freq; + d_fs_in = fs_in; + d_samples_per_ms = samples_per_ms; + d_sampled_ms = sampled_ms; + d_doppler_max = doppler_max; + d_fft_size = d_sampled_ms * d_samples_per_ms; + // HS Acquisition + d_max_dwells= max_dwells; + d_gnuradio_forecast_samples=d_fft_size*d_max_dwells; + d_mag = 0; + d_input_power = 0.0; + + //todo: do something if posix_memalign fails + if (posix_memalign((void**)&d_carrier, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_fft_codes, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + + // Direct FFT + d_fft_if = new gr::fft::fft_complex(d_fft_size, true); + + // Inverse FFT + d_ifft = new gr::fft::fft_complex(d_fft_size, false); + + // For dumping samples into a file + d_dump = dump; + d_dump_filename = dump_filename; +} + + + +pcps_assisted_acquisition_cc::~pcps_assisted_acquisition_cc() +{ + free(d_carrier); + free(d_fft_codes); + delete d_ifft; + delete d_fft_if; + if (d_dump) + { + d_dump_file.close(); + } +} + + + +void pcps_assisted_acquisition_cc::set_local_code(std::complex * code) +{ + memcpy(d_fft_if->get_inbuf(),code,sizeof(gr_complex)*d_fft_size); +} + + + +void pcps_assisted_acquisition_cc::init() +{ + d_gnss_synchro->Acq_delay_samples = 0.0; + d_gnss_synchro->Acq_doppler_hz = 0.0; + d_gnss_synchro->Acq_samplestamp_samples = 0; + d_mag = 0.0; + d_input_power = 0.0; + + d_fft_if->execute(); // We need the FFT of local code + + //Conjugate the local code + for (unsigned int i = 0; i < d_fft_size; i++) + { + d_fft_codes[i] = std::complex(conj(d_fft_if->get_outbuf()[i])); + } +} + + +void pcps_assisted_acquisition_cc::forecast (int noutput_items, + gr_vector_int &ninput_items_required) +{ + ninput_items_required[0] = d_gnuradio_forecast_samples ; //set the required available samples in each call +} + + +int pcps_assisted_acquisition_cc::general_work(int noutput_items, + gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + /* + * By J.Arribas and L.Esteve + * Acquisition strategy (Kay Borre book + CFAR threshold): + * 1. Compute the input signal power estimation + * 2. Doppler serial search loop + * 3. Perform the FFT-based circular convolution (parallel time search) + * 4. Record the maximum peak and the associated synchronization parameters + * 5. Compute the test statistics and compare to the threshold + * 6. Declare positive or negative acquisition using a message queue + */ + + /*! + * TODO: High sensitivity acquisition algorithm: + * 0. Define search grid with assistance information. Reset grid matrix + * 1. Perform the FFT acqusition doppler and delay grid + * 2. accumulate the search grid matrix (#doppler_bins x #fft_size) + * 3. compare maximum to threshold and decide positive or negative + * 4. positive: stop. negative: if dwell_count< max_dwells -> dwell_count++ and goto 1, else -> negative acquisition: stop. + */ + if (!d_active) + { + d_sample_counter += d_fft_size * noutput_items; // sample counter + consume_each(noutput_items); + } + else + { + // initialize acquisition algorithm + int doppler; + unsigned int indext = 0; + float magt = 0.0; + float tmp_magt = 0.0; + const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer + bool positive_acquisition = false; + int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL + //aux vars + unsigned int i; + float fft_normalization_factor; + + d_sample_counter += d_fft_size; // sample counter + + //restart acquisition variables + d_gnss_synchro->Acq_delay_samples = 0.0; + d_gnss_synchro->Acq_doppler_hz = 0.0; + d_mag = 0.0; + d_input_power = 0.0; + + DLOG(INFO) << "Channel: " << d_channel + << " , doing acquisition of satellite: " << d_gnss_synchro->System << " "<< d_gnss_synchro->PRN + << " ,sample stamp: " << d_sample_counter << ", threshold: " + << d_threshold << ", doppler_max: " << d_doppler_max + << ", doppler_step: " << d_doppler_step; + + // 1- Compute the input signal power estimation + for (i = 0; i < d_fft_size; i++) + { + d_input_power += std::norm(in[i]); + } + d_input_power = d_input_power / (float)d_fft_size; + + // 2- Doppler frequency search loop + for (doppler = (int)(-d_doppler_max); doppler < (int)d_doppler_max; doppler += d_doppler_step) + { + // doppler search steps + // Perform the carrier wipe-off + complex_exp_gen_conj(d_carrier, d_freq + doppler, d_fs_in, d_fft_size); + + volk_32fc_x2_multiply_32fc_u(d_fft_if->get_inbuf(), in, d_carrier, d_fft_size); + // 3- Perform the FFT-based convolution (parallel time search) + // Compute the FFT of the carrier wiped--off incoming signal + d_fft_if->execute(); + + // Multiply carrier wiped--off, Fourier transformed incoming signal + // with the local FFT'd code reference using SIMD operations with VOLK library + volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); + + // compute the inverse FFT + d_ifft->execute(); + + // Search maximum + indext = 0; + magt = 0; + fft_normalization_factor = (float)d_fft_size * (float)d_fft_size; + for (i = 0; i < d_fft_size; i++) + { + tmp_magt = std::norm(d_ifft->get_outbuf()[i]); + if (tmp_magt > magt) + { + magt = tmp_magt; + indext = i; + } + } + // Normalize the maximum value to correct the scale factor introduced by FFTW + magt = magt / (fft_normalization_factor * fft_normalization_factor); + + // 4- record the maximum peak and the associated synchronization parameters + if (d_mag < magt) + { + d_mag = magt; + d_gnss_synchro->Acq_delay_samples = (double)indext; + d_gnss_synchro->Acq_doppler_hz = (double)doppler; + } + + // Record results to file if required + if (d_dump) + { + std::stringstream filename; + std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write + filename.str(""); + filename << "../data/test_statistics_" << d_gnss_synchro->System + <<"_" << d_gnss_synchro->Signal << "_sat_" + << d_gnss_synchro->PRN << "_doppler_" << doppler << ".dat"; + d_dump_file.open(filename.str().c_str(), std::ios::out + | std::ios::binary); + d_dump_file.write((char*)d_ifft->get_outbuf(), n); //write directly |abs(x)|^2 in this Doppler bin? + d_dump_file.close(); + } + } + + // 5- Compute the test statistics and compare to the threshold + d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; + + // 6- Declare positive or negative acquisition using a message queue + if (d_test_statistics > d_threshold) + { + positive_acquisition = true; + d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; + DLOG(INFO) << "positive acquisition"; + DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; + DLOG(INFO) << "sample_stamp " << d_sample_counter; + DLOG(INFO) << "test statistics value " << d_test_statistics; + DLOG(INFO) << "test statistics threshold " << d_threshold; + DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; + DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; + DLOG(INFO) << "magnitude " << d_mag; + DLOG(INFO) << "input signal power " << d_input_power; + } + else + { + DLOG(INFO) << "negative acquisition"; + DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; + DLOG(INFO) << "sample_stamp " << d_sample_counter; + DLOG(INFO) << "test statistics value " << d_test_statistics; + DLOG(INFO) << "test statistics threshold " << d_threshold; + DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; + DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; + DLOG(INFO) << "magnitude " << d_mag; + DLOG(INFO) << "input signal power " << d_input_power; + } + + d_active = false; + + if (positive_acquisition) + { + acquisition_message = 1; + } + else + { + acquisition_message = 2; + } + d_channel_internal_queue->push(acquisition_message); + consume_each(1); + } + return 0; +} diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_assisted_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_assisted_acquisition_cc.h new file mode 100644 index 000000000..fbf89b570 --- /dev/null +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_assisted_acquisition_cc.h @@ -0,0 +1,229 @@ +/*! + * \file pcps_assisted_acquisition_cc.h + * \brief This class implements a Parallel Code Phase Search Acquisition + * + * Acquisition strategy (Kay Borre book + CFAR threshold). + *
    + *
  1. Compute the input signal power estimation + *
  2. Doppler serial search loop + *
  3. Perform the FFT-based circular convolution (parallel time search) + *
  4. Record the maximum peak and the associated synchronization parameters + *
  5. Compute the test statistics and compare to the threshold + *
  6. Declare positive or negative acquisition using a message queue + *
+ * + * Kay Borre book: 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. pp 81-84 + * + * \authors
    + *
  • Javier Arribas, 2011. jarribas(at)cttc.es + *
  • 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 . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_PCPS_assisted_acquisition_cc_H_ +#define GNSS_SDR_PCPS_assisted_acquisition_cc_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "concurrent_queue.h" +#include "gnss_synchro.h" + +class pcps_assisted_acquisition_cc; +typedef boost::shared_ptr +pcps_assisted_acquisition_cc_sptr; +pcps_assisted_acquisition_cc_sptr +pcps_make_assisted_acquisition_cc(int max_dwells, unsigned int sampled_ms, + unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, + gr_msg_queue_sptr queue, bool dump, std::string dump_filename); + +/*! + * \brief This class implements a Parallel Code Phase Search Acquisition. + * + * Check \ref Navitec2012 "An Open Source Galileo E1 Software Receiver", + * Algorithm 1, for a pseudocode description of this implementation. + */ + +class pcps_assisted_acquisition_cc: public gr_block +{ +private: + friend pcps_assisted_acquisition_cc_sptr + pcps_make_assisted_acquisition_cc(int max_dwells, unsigned int sampled_ms, + unsigned int doppler_max, long freq, long fs_in, + int samples_per_ms, gr_msg_queue_sptr queue, bool dump, + std::string dump_filename); + + pcps_assisted_acquisition_cc(int max_dwells, unsigned int sampled_ms, + unsigned int doppler_max, long freq, long fs_in, + int samples_per_ms, gr_msg_queue_sptr queue, bool dump, + std::string dump_filename); + + void calculate_magnitudes(gr_complex* fft_begin, int doppler_shift, + int doppler_offset); + + long d_fs_in; + long d_freq; + int d_samples_per_ms; + int d_max_dwells; + unsigned int d_doppler_resolution; + int d_gnuradio_forecast_samples; + float d_threshold; + std::string d_satellite_str; + unsigned int d_doppler_max; + unsigned int d_doppler_step; + unsigned int d_sampled_ms; + unsigned int d_fft_size; + unsigned long int d_sample_counter; + gr_complex* d_carrier; + gr_complex* d_fft_codes; + 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_input_power; + float d_test_statistics; + gr_msg_queue_sptr d_queue; + concurrent_queue *d_channel_internal_queue; + std::ofstream d_dump_file; + bool d_active; + bool d_dump; + unsigned int d_channel; + std::string d_dump_filename; + +public: + /*! + * \brief Default destructor. + */ + ~pcps_assisted_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. + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) + { + d_gnss_synchro = p_gnss_synchro; + } + + /*! + * \brief Returns the maximum peak of grid search. + */ + unsigned int mag() + { + return d_mag; + } + + /*! + * \brief Initializes acquisition algorithm. + */ + void init(); + + /*! + * \brief Sets local code for PCPS acquisition algorithm. + * \param code - Pointer to the PRN 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. + */ + void set_active(bool active) + { + d_active = active; + } + + /*! + * \brief Set acquisition channel unique ID + * \param channel - receiver channel. + */ + void set_channel(unsigned int channel) + { + 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). + */ + void set_threshold(float threshold) + { + d_threshold = threshold; + } + + /*! + * \brief Set maximum Doppler grid search + * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz]. + */ + void set_doppler_max(unsigned int doppler_max) + { + d_doppler_max = doppler_max; + } + + /*! + * \brief Set Doppler steps for the grid search + * \param doppler_step - Frequency bin of the search grid [Hz]. + */ + void set_doppler_step(unsigned int doppler_step) + { + d_doppler_step = doppler_step; + } + + + /*! + * \brief Set tracking channel internal queue. + * \param channel_internal_queue - Channel's internal blocks information queue. + */ + void set_channel_queue(concurrent_queue *channel_internal_queue) + { + d_channel_internal_queue = channel_internal_queue; + } + + /*! + * \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); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + +}; + +#endif /* GNSS_SDR_PCPS_assisted_acquisition_cc_H_*/ diff --git a/src/core/libs/gnss_sdr_supl_client.cc b/src/core/libs/gnss_sdr_supl_client.cc index 94316bf9e..31b076ee8 100644 --- a/src/core/libs/gnss_sdr_supl_client.cc +++ b/src/core/libs/gnss_sdr_supl_client.cc @@ -302,6 +302,7 @@ void gnss_sdr_supl_client::read_supl_data() gps_acq_iterator=this->gps_acq_map.find(e->prn); } // fill the acquisition assistance structure + gps_acq_iterator->second.i_satellite_PRN=e->prn; gps_acq_iterator->second.d_TOW=(double)assist.acq_time; gps_acq_iterator->second.d_Doppler0=(double)e->doppler0; gps_acq_iterator->second.d_Doppler1=(double)e->doppler1; diff --git a/src/core/receiver/control_thread.cc b/src/core/receiver/control_thread.cc index da725b464..009d25534 100644 --- a/src/core/receiver/control_thread.cc +++ b/src/core/receiver/control_thread.cc @@ -54,12 +54,14 @@ extern concurrent_map global_gps_ephemeris_map; extern concurrent_map global_gps_iono_map; extern concurrent_map global_gps_utc_model_map; +extern concurrent_map global_gps_almanac_map; +extern concurrent_map global_gps_acq_assist_map; extern concurrent_queue global_gps_ephemeris_queue; extern concurrent_queue global_gps_iono_queue; extern concurrent_queue global_gps_utc_model_queue; extern concurrent_queue global_gps_almanac_queue; - +extern concurrent_queue global_gps_acq_assist_queue; using google::LogMessage; @@ -132,6 +134,7 @@ void ControlThread::run() gps_ephemeris_data_collector_thread_ =boost::thread(&ControlThread::gps_ephemeris_data_collector, this); gps_iono_data_collector_thread_ =boost::thread(&ControlThread::gps_iono_data_collector, this); gps_utc_model_data_collector_thread_ =boost::thread(&ControlThread::gps_utc_model_data_collector, this); + gps_acq_assist_data_collector_thread_=boost::thread(&ControlThread::gps_acq_assist_data_collector,this); // Main loop to read and process the control messages while (flowgraph_->running() && !stop_) @@ -141,11 +144,13 @@ void ControlThread::run() if (control_messages_ != 0) process_control_messages(); } std::cout<<"Stopping GNSS-SDR, please wait!"<stop(); gps_ephemeris_data_collector_thread_.timed_join(boost::posix_time::seconds(1)); gps_iono_data_collector_thread_.timed_join(boost::posix_time::seconds(1)); gps_utc_model_data_collector_thread_.timed_join(boost::posix_time::seconds(1)); + gps_acq_assist_data_collector_thread_.timed_join(boost::posix_time::seconds(1)); keyboard_thread_.timed_join(boost::posix_time::seconds(1)); - flowgraph_->stop(); + LOG_AT_LEVEL(INFO) << "Flowgraph stopped"; } @@ -186,27 +191,27 @@ bool ControlThread::read_assistance_from_XML() } void ControlThread::init() { - // Instantiates a control queue, a GNSS flowgraph, and a control message factory - control_queue_ = gr_make_msg_queue(0); - flowgraph_ = new GNSSFlowgraph(configuration_, control_queue_); - control_message_factory_ = new ControlMessageFactory(); - stop_ = false; - processed_control_messages_ = 0; - applied_actions_ = 0; + // Instantiates a control queue, a GNSS flowgraph, and a control message factory + control_queue_ = gr_make_msg_queue(0); + flowgraph_ = new GNSSFlowgraph(configuration_, control_queue_); + control_message_factory_ = new ControlMessageFactory(); + stop_ = false; + processed_control_messages_ = 0; + applied_actions_ = 0; - // GNSS Assistance configuration - bool enable_gps_supl_assistance=configuration_->property("GNSS-SDR.SUPL_gps_enabled",false); - if (enable_gps_supl_assistance==true) - //SUPL SERVER TEST. Not operational yet! - { - std::cout<< "SUPL RRLP GPS assistance enabled!"<property("GNSS-SDR.SUPL_gps_enabled",false); + if (enable_gps_supl_assistance==true) + //SUPL SERVER TEST. Not operational yet! + { + std::cout<< "SUPL RRLP GPS assistance enabled!"<property("GNSS-SDR.SUPL_gps_ephemeris_server",default_acq_server); supl_client_acquisition_.server_name=configuration_->property("GNSS-SDR.SUPL_gps_acquisition_server",default_eph_server); supl_client_ephemeris_.server_port=configuration_->property("GNSS-SDR.SUPL_gps_ephemeris_port",7275); supl_client_acquisition_.server_port=configuration_->property("GNSS-SDR.SUPL_gps_acquisition_port",7275); - supl_mcc=configuration_->property("GNSS-SDR.SUPL_MCC",244); supl_mns=configuration_->property("GNSS-SDR.SUPL_MNS",5); @@ -218,7 +223,7 @@ void ControlThread::init() supl_lac=0x59e2; } try { - supl_ci = boost::lexical_cast(configuration_->property("GNSS-SDR.SUPL_CI",default_ci)); + supl_ci = boost::lexical_cast(configuration_->property("GNSS-SDR.SUPL_CI",default_ci)); } catch(boost::bad_lexical_cast &) { supl_ci=0x31b0; } @@ -230,76 +235,90 @@ void ControlThread::init() read_assistance_from_XML(); }else{ - // Request ephemeris from SUPL server - int error; - supl_client_ephemeris_.request=1; - std::cout<< "SUPL: Try read GPS ephemeris from SUPL server.."<::iterator gps_eph_iter; - for(gps_eph_iter = supl_client_ephemeris_.gps_ephemeris_map.begin(); - gps_eph_iter != supl_client_ephemeris_.gps_ephemeris_map.end(); - gps_eph_iter++) + // Request ephemeris from SUPL server + int error; + supl_client_ephemeris_.request=1; + std::cout<< "SUPL: Try read GPS ephemeris from SUPL server.."<first<second); + std::map::iterator gps_eph_iter; + for(gps_eph_iter = supl_client_ephemeris_.gps_ephemeris_map.begin(); + gps_eph_iter != supl_client_ephemeris_.gps_ephemeris_map.end(); + gps_eph_iter++) + { + std::cout<<"SUPL: Received Ephemeris for GPS SV "<first<second); + } + //Save ephemeris to XML file + std::string eph_xml_filename="gps_ephemeris.xml"; + if (supl_client_ephemeris_.save_ephemeris_xml(eph_xml_filename)==true) + { + std::cout<<"SUPL: XML Ephemeris file created"<::iterator gps_alm_iter; - for(gps_alm_iter = supl_client_ephemeris_.gps_almanac_map.begin(); - gps_alm_iter != supl_client_ephemeris_.gps_almanac_map.end(); - gps_alm_iter++) + // Request almanac , IONO and UTC Model + supl_client_ephemeris_.request=0; + std::cout<< "SUPL: Try read Almanac, Iono, Utc Model, Ref Time and Ref Location from SUPL server.."<first<second); + std::map::iterator gps_alm_iter; + for(gps_alm_iter = supl_client_ephemeris_.gps_almanac_map.begin(); + gps_alm_iter != supl_client_ephemeris_.gps_almanac_map.end(); + gps_alm_iter++) + { + std::cout<<"SUPL: Received Almanac for GPS SV "<first<second); + } + if (supl_client_ephemeris_.gps_iono.valid==true) + { + std::cout<<"SUPL: Received GPS Iono"<::iterator gps_acq_iter; + for(gps_acq_iter = supl_client_acquisition_.gps_acq_map.begin(); + gps_acq_iter != supl_client_acquisition_.gps_acq_map.end(); + gps_acq_iter++) + { + std::cout<<"SUPL: Received Acquisition assistance for GPS SV "<first<second); + } + }else{ + std::cout<< "ERROR: SUPL client for Acquisition assistance returned "< global_gps_ephemeris_queue; concurrent_queue global_gps_iono_queue; concurrent_queue global_gps_utc_model_queue; concurrent_queue global_gps_almanac_queue; +concurrent_queue global_gps_acq_assist_queue; concurrent_map global_gps_ephemeris_map; concurrent_map global_gps_iono_map; concurrent_map global_gps_utc_model_map; +concurrent_map global_gps_almanac_map; +concurrent_map global_gps_acq_assist_map; int main(int argc, char** argv)