diff --git a/conf/front-end-cal.conf b/conf/front-end-cal.conf new file mode 100644 index 000000000..c699e7434 --- /dev/null +++ b/conf/front-end-cal.conf @@ -0,0 +1,193 @@ +; Default configuration file +; You can define your own receiver and invoke it by doing +; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf +; + +[GNSS-SDR] + +;######### INITIAL RECEIVER POSITIION ###### +;GNSS-SDR.init_latitude_deg=40.74846557442795 +;GNSS-SDR.init_longitude_deg=-73.98593961814200 +;GNSS-SDR.init_altitude_m=329.11968943169342 + +GNSS-SDR.init_latitude_deg=41.27481478485936 +GNSS-SDR.init_longitude_deg=1.98753271588628 +GNSS-SDR.init_altitude_m=25 + +;######### GLOBAL OPTIONS ################## +;internal_fs_hz: Internal signal sampling frequency after the signal conditioning stage [Hz]. +GNSS-SDR.internal_fs_hz=2000000 + +;######### CONTROL_THREAD CONFIG ############ +ControlThread.wait_for_flowgraph=false + +;######### SUPL RRLP GPS assistance configuration ##### +GNSS-SDR.SUPL_gps_enabled=true +GNSS-SDR.SUPL_read_gps_assistance_xml=false +GNSS-SDR.SUPL_gps_ephemeris_server=supl.nokia.com +GNSS-SDR.SUPL_gps_ephemeris_port=7275 +GNSS-SDR.SUPL_gps_acquisition_server=supl.google.com +GNSS-SDR.SUPL_gps_acquisition_port=7275 +GNSS-SDR.SUPL_MCC=217 +GNSS-SDR.SUPL_MNS=7 +GNSS-SDR.SUPL_LAC=861 +GNSS-SDR.SUPL_CI=40184 + +;######### SIGNAL_SOURCE CONFIG ############ +;#implementation: Use [File_Signal_Source] or [UHD_Signal_Source] or [GN3S_Signal_Source] or [Rtlsdr_Signal_Source] +SignalSource.implementation=File_Signal_Source + +SignalSource.AGC_enabled=false + +;#filename: path to file with the captured GNSS signal samples to be processed +SignalSource.filename=/media/DATALOGGER_/signals/Agilent GPS Generator/New York/2msps.dat + +;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. +SignalSource.item_type=gr_complex + +;#sampling_frequency: Original Signal sampling frequency in [Hz] +SignalSource.sampling_frequency=2000000 + +;#freq: RF front-end center frequency in [Hz] +SignalSource.freq=1575420000 + +;#gain: Front-end Gain in [dB] +SignalSource.gain=40 +SignalSource.rf_gain=40 +SignalSource.if_gain=5 + +;#subdevice: UHD subdevice specification (for USRP1 use A:0 or B:0) +SignalSource.subdevice=B:0 + +;#samples: Number of samples to be processed. Notice that 0 indicates the entire file. +SignalSource.samples=0 + +;#repeat: Repeat the processing file. Disable this option in this version +SignalSource.repeat=false + +;#dump: Dump the Signal source data to a file. Disable this option in this version +SignalSource.dump=false + +SignalSource.dump_filename=../data/signal_source.dat + +;######### SIGNAL_CONDITIONER CONFIG ############ +;## It holds blocks to change data type, filter and resample input data. + +;#implementation: Use [Pass_Through] or [Signal_Conditioner] +;#[Pass_Through] disables this block and the [DataTypeAdapter], [InputFilter] and [Resampler] blocks +;#[Signal_Conditioner] enables this block. Then you have to configure [DataTypeAdapter], [InputFilter] and [Resampler] blocks +SignalConditioner.implementation=Signal_Conditioner + +;######### DATA_TYPE_ADAPTER CONFIG ############ +;## Changes the type of input data. Please disable it in this version. +;#implementation: Use [Ishort_To_Complex] or [Pass_Through] +DataTypeAdapter.implementation=Pass_Through +;#dump: Dump the filtered data to a file. +DataTypeAdapter.dump=false +;#dump_filename: Log path and filename. +DataTypeAdapter.dump_filename=../data/data_type_adapter.dat + +;######### INPUT_FILTER CONFIG ############ +;## Filter the input data. Can be combined with frequency translation for IF signals + +;#implementation: Use [Pass_Through] or [Fir_Filter] or [Freq_Xlating_Fir_Filter] +;#[Pass_Through] disables this block +;#[Fir_Filter] enables a FIR Filter +;#[Freq_Xlating_Fir_Filter] enables FIR filter and a composite frequency translation that shifts IF down to zero Hz. + +InputFilter.implementation=Freq_Xlating_Fir_Filter + +;#dump: Dump the filtered data to a file. +InputFilter.dump=false + +;#dump_filename: Log path and filename. +InputFilter.dump_filename=../data/input_filter.dat + +;#The following options are used in the filter design of Fir_Filter and Freq_Xlating_Fir_Filter implementation. +;#These options are based on parameters of gnuradio's function: gr_remez. +;#These function calculates the optimal (in the Chebyshev/minimax sense) FIR filter inpulse reponse given a set of band edges, the desired reponse on those bands, and the weight given to the error in those bands. + +;#input_item_type: Type and resolution for input signal samples. Use only gr_complex in this version. +InputFilter.input_item_type=gr_complex + +;#outut_item_type: Type and resolution for output filtered signal samples. Use only gr_complex in this version. +InputFilter.output_item_type=gr_complex + +;#taps_item_type: Type and resolution for the taps of the filter. Use only float in this version. +InputFilter.taps_item_type=float + +;#number_of_taps: Number of taps in the filter. Increasing this parameter increases the processing time +InputFilter.number_of_taps=5 + +;#number_of _bands: Number of frequency bands in the filter. +InputFilter.number_of_bands=2 + +;#bands: frequency at the band edges [ b1 e1 b2 e2 b3 e3 ...]. +;#Frequency is in the range [0, 1], with 1 being the Nyquist frequency (Fs/2) +;#The number of band_begin and band_end elements must match the number of bands + +InputFilter.band1_begin=0.0 +;InputFilter.band1_end=0.8 +InputFilter.band1_end=0.85 +InputFilter.band2_begin=0.90 +InputFilter.band2_end=1.0 + +;#ampl: desired amplitude at the band edges [ a(b1) a(e1) a(b2) a(e2) ...]. +;#The number of ampl_begin and ampl_end elements must match the number of bands + +InputFilter.ampl1_begin=1.0 +InputFilter.ampl1_end=1.0 +InputFilter.ampl2_begin=0.0 +InputFilter.ampl2_end=0.0 + +;#band_error: weighting applied to each band (usually 1). +;#The number of band_error elements must match the number of bands +InputFilter.band1_error=1.0 +InputFilter.band2_error=1.0 + +;#filter_type: one of "bandpass", "hilbert" or "differentiator" +InputFilter.filter_type=bandpass + +;#grid_density: determines how accurately the filter will be constructed. +;The minimum value is 16; higher values are slower to compute the filter. +InputFilter.grid_density=16 + +;#The following options are used only in Freq_Xlating_Fir_Filter implementation. +;#InputFilter.IF is the intermediate frequency (in Hz) shifted down to zero Hz + +InputFilter.sampling_frequency=2000000 +InputFilter.IF=0 + +InputFilter.decimation_factor=1 + +;######### RESAMPLER CONFIG ############ +;## Resamples the input data. +;#implementation: Use [Pass_Through] or [Direct_Resampler] +;#[Pass_Through] disables this block +Resampler.implementation=Pass_Through + +;######### ACQUISITION GLOBAL CONFIG ############ + +;#dump: Enable or disable the acquisition internal data file logging [true] or [false] +Acquisition.dump=false +;#filename: Log path and filename +Acquisition.dump_filename=./acq_dump.dat +;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. +Acquisition.item_type=gr_complex +;#if: Signal intermediate frequency in [Hz] +Acquisition.if=0 +;#sampled_ms: Signal block duration for the acquisition signal detection [ms] +Acquisition.sampled_ms=1 +;#implementation: Acquisition algorithm selection for this channel: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] +Acquisition.implementation=GPS_L1_CA_PCPS_Acquisition +;#threshold: Acquisition threshold +Acquisition.threshold=40 +;#doppler_max: Maximum expected Doppler shift [Hz] +Acquisition.doppler_max=10000 +;#doppler_max: Maximum expected Doppler shift [Hz] +Acquisition.doppler_min=-10000 +;#doppler_step Doppler step in the grid search [Hz] +Acquisition.doppler_step=250 +;#maximum dwells +Acquisition.max_dwells=2 + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cb55b915d..97ec99153 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,4 +20,4 @@ add_subdirectory(algorithms) add_subdirectory(core) add_subdirectory(main) add_subdirectory(tests) -#add_subdirectory(utils) +add_subdirectory(utils) diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index c9ce71aae..57ce9e1d3 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -19,7 +19,8 @@ set(ACQ_ADAPTER_SOURCES galileo_e1_pcps_ambiguous_acquisition.cc gps_l1_ca_pcps_acquisition.cc - gps_l1_ca_pcps_assisted_acquisition.cc + gps_l1_ca_pcps_assisted_acquisition.cc + gps_l1_ca_pcps_acquisition_fine_doppler.cc ) include_directories( diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.cc new file mode 100644 index 000000000..0c0e5885e --- /dev/null +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.cc @@ -0,0 +1,186 @@ +/*! + * \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_acquisition_fine_doppler.h" +#include "gps_sdr_signal_processing.h" +#include "GPS_L1_CA.h" +#include "configuration_interface.h" +#include +#include +#include +#include + +using google::LogMessage; + +GpsL1CaPcpsAcquisitionFineDoppler::GpsL1CaPcpsAcquisitionFineDoppler( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams, + boost::shared_ptr 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); + doppler_max_ = configuration->property(role + ".doppler_max", 5000); + doppler_min_ = configuration->property(role + ".doppler_min", -5000); + 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_acquisition_fine_doppler_cc(max_dwells_,sampled_ms_, + doppler_max_, doppler_min_, if_, fs_in_, vector_length_, queue_, + dump_, dump_filename_); + + } + else + { + LOG_AT_LEVEL(WARNING) << item_type_ + << " unknown acquisition item type"; + } +} + + +GpsL1CaPcpsAcquisitionFineDoppler::~GpsL1CaPcpsAcquisitionFineDoppler() +{ + delete[] code_; +} + + +void GpsL1CaPcpsAcquisitionFineDoppler::set_channel(unsigned int channel) +{ + channel_ = channel; + acquisition_cc_->set_channel(channel_); +} + + +void GpsL1CaPcpsAcquisitionFineDoppler::set_threshold(float threshold) +{ + threshold_ = threshold; + acquisition_cc_->set_threshold(threshold_); +} + + +void GpsL1CaPcpsAcquisitionFineDoppler::set_doppler_max(unsigned int doppler_max) +{ + doppler_max_ = doppler_max; + acquisition_cc_->set_doppler_max(doppler_max_); +} + + +void GpsL1CaPcpsAcquisitionFineDoppler::set_doppler_step(unsigned int doppler_step) +{ + doppler_step_ = doppler_step; + acquisition_cc_->set_doppler_step(doppler_step_); +} + + +void GpsL1CaPcpsAcquisitionFineDoppler::set_channel_queue( + concurrent_queue *channel_internal_queue) +{ + channel_internal_queue_ = channel_internal_queue; + acquisition_cc_->set_channel_queue(channel_internal_queue_); +} + + +void GpsL1CaPcpsAcquisitionFineDoppler::set_gnss_synchro(Gnss_Synchro* gnss_synchro) +{ + gnss_synchro_ = gnss_synchro; + acquisition_cc_->set_gnss_synchro(gnss_synchro_); +} + + +signed int GpsL1CaPcpsAcquisitionFineDoppler::mag() +{ + return acquisition_cc_->mag(); +} + + +void GpsL1CaPcpsAcquisitionFineDoppler::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 GpsL1CaPcpsAcquisitionFineDoppler::reset() +{ + acquisition_cc_->set_active(true); +} + + +void GpsL1CaPcpsAcquisitionFineDoppler::connect(boost::shared_ptr top_block) +{ + + //nothing to disconnect, now the tracking uses gr_sync_decimator + +} + + +void GpsL1CaPcpsAcquisitionFineDoppler::disconnect(boost::shared_ptr top_block) +{ + //nothing to disconnect, now the tracking uses gr_sync_decimator +} + + +boost::shared_ptr GpsL1CaPcpsAcquisitionFineDoppler::get_left_block() +{ + return acquisition_cc_; +} + + +boost::shared_ptr GpsL1CaPcpsAcquisitionFineDoppler::get_right_block() +{ + return acquisition_cc_; +} + diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h new file mode 100644 index 000000000..cf85f41da --- /dev/null +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h @@ -0,0 +1,154 @@ +/*! + * \file gps_l1_ca_pcps_acquisition_fine_doppler.h + * \brief Adapts a PCPS acquisition block with fine Doppler estimation to an AcquisitionInterface for + * GPS L1 C/A signals + * \authors
    + *
  • Javier Arribas, 2013. 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_ACQUISITION_FINE_DOPPLER_H_ +#define GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FINE_DOPPLER_H_ + +#include "gnss_synchro.h" +#include "acquisition_interface.h" +#include "pcps_acquisition_fine_doppler_cc.h" +#include +#include + + +class ConfigurationInterface; + +/*! + * \brief This class Adapts a PCPS acquisition block with fine Doppler estimation to an AcquisitionInterface for + * GPS L1 C/A signals + */ +class GpsL1CaPcpsAcquisitionFineDoppler: public AcquisitionInterface +{ +public: + GpsL1CaPcpsAcquisitionFineDoppler(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, + unsigned int out_streams, boost::shared_ptr queue); + + virtual ~GpsL1CaPcpsAcquisitionFineDoppler(); + + std::string role() + { + return role_; + } + + /*! + * \brief Returns "GPS_L1_CA_PCPS_Assisted_Acquisition" + */ + std::string implementation() + { + return "GPS_L1_CA_PCPS_Acquisition_Fine_Doppler"; + } + size_t item_size() + { + return item_size_; + } + + void connect(boost::shared_ptr top_block); + void disconnect(boost::shared_ptr top_block); + boost::shared_ptr get_left_block(); + boost::shared_ptr 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_acquisition_fine_doppler_cc_sptr acquisition_cc_; + size_t item_size_; + std::string item_type_; + unsigned int vector_length_; + //unsigned int satellite_; + unsigned int channel_; + float threshold_; + int doppler_max_; + unsigned int doppler_step_; + int doppler_min_; + 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_; + boost::shared_ptr queue_; + concurrent_queue *channel_internal_queue_; +}; + +#endif /* GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FINE_DOPPLER_H_ */ diff --git a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt index adabeda2d..7149f6327 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt @@ -19,6 +19,7 @@ set(ACQ_GR_BLOCKS_SOURCES pcps_acquisition_cc.cc pcps_assisted_acquisition_cc.cc + pcps_acquisition_fine_doppler_cc.cc ) include_directories( diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fine_doppler_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fine_doppler_cc.cc new file mode 100644 index 000000000..440233401 --- /dev/null +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fine_doppler_cc.cc @@ -0,0 +1,526 @@ +/*! + * \file pcps_assisted_acquisition_cc.cc + * \brief This class implements a Parallel Code Phase Search Acquisition with multi-dwells and fine Doppler estimation + * \authors
    + *
  • Javier Arribas, 2013. 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 . + * + * ------------------------------------------------------------------------- + */ + +#include "pcps_acquisition_fine_doppler_cc.h" +#include "gnss_signal_processing.h" +#include "gps_sdr_signal_processing.h" +#include "control_message_factory.h" +#include "gps_acq_assist.h" +#include +#include +#include +#include +#include +#include "nco_lib.h" +#include "concurrent_map.h" +#include // std::rotate + +extern concurrent_map global_gps_acq_assist_map; + +using google::LogMessage; + +pcps_acquisition_fine_doppler_cc_sptr pcps_make_acquisition_fine_doppler_cc( + int max_dwells, unsigned int sampled_ms, int doppler_max, int doppler_min, long freq, + long fs_in, int samples_per_ms, boost::shared_ptr queue, bool dump, + std::string dump_filename) +{ + + return pcps_acquisition_fine_doppler_cc_sptr( + new pcps_acquisition_fine_doppler_cc(max_dwells, sampled_ms, doppler_max, doppler_min, freq, + fs_in, samples_per_ms, queue, dump, dump_filename)); +} + + + +pcps_acquisition_fine_doppler_cc::pcps_acquisition_fine_doppler_cc( + int max_dwells, unsigned int sampled_ms, int doppler_max, int doppler_min, long freq, + long fs_in, int samples_per_ms, boost::shared_ptr queue, bool dump, + std::string dump_filename) : + gr::block("pcps_acquisition_fine_doppler_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(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_config_doppler_max = doppler_max; + d_config_doppler_min=doppler_min; + 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_input_power = 0.0; + d_state=0; + d_disable_assist=false; + //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; +} + +void pcps_acquisition_fine_doppler_cc::set_doppler_step(unsigned int doppler_step) +{ + d_doppler_step = doppler_step; +} + +void pcps_acquisition_fine_doppler_cc::free_grid_memory() +{ + for (int i=0;i * code) +{ + memcpy(d_fft_if->get_inbuf(),code,sizeof(gr_complex)*d_fft_size); +} + + + +void pcps_acquisition_fine_doppler_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_input_power = 0.0; + + d_state=0; + + d_fft_if->execute(); // We need the FFT of local code + + //Conjugate the local code + volk_32fc_conjugate_32fc_a(d_fft_codes,d_fft_if->get_outbuf(),d_fft_size); + +} + + +void pcps_acquisition_fine_doppler_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 +} + + +void pcps_acquisition_fine_doppler_cc::get_assistance() +{ + Gps_Acq_Assist gps_acq_assisistance; + if (global_gps_acq_assist_map.read(this->d_gnss_synchro->PRN,gps_acq_assisistance)==true) + { + //TODO: use the LO tolerance here + if (gps_acq_assisistance.dopplerUncertainty>=1000) + { + d_doppler_max=gps_acq_assisistance.d_Doppler0+gps_acq_assisistance.dopplerUncertainty*2; + d_doppler_min=gps_acq_assisistance.d_Doppler0-gps_acq_assisistance.dopplerUncertainty*2; + }else{ + d_doppler_max=gps_acq_assisistance.d_Doppler0+1000; + d_doppler_min=gps_acq_assisistance.d_Doppler0-1000; + } + this->d_disable_assist=false; + std::cout<<"Acq assist ENABLED for GPS SV "<d_gnss_synchro->PRN<<" (Doppler max,Doppler min)=(" + <d_disable_assist=true; + //std::cout<<"Acq assist DISABLED for GPS SV "<d_gnss_synchro->PRN<d_disable_assist==true) + { + d_doppler_max=d_config_doppler_max; + d_doppler_min=d_config_doppler_min; + } + // Create the search grid array + d_num_doppler_points=floor(std::abs(d_doppler_max-d_doppler_min)/d_doppler_step); + + d_grid_data=new float*[d_num_doppler_points]; + for (int i=0;i magt) + { + magt = d_grid_data[i][index_time]; + index_doppler = i; + index_time = tmp_intex_t; + } + } + + // Normalize the maximum value to correct the scale factor introduced by FFTW + fft_normalization_factor = (float)d_fft_size * (float)d_fft_size; + magt = magt / (fft_normalization_factor * fft_normalization_factor); + + // 5- Compute the test statistics and compare to the threshold + d_test_statistics = 2 * d_fft_size * magt /(d_input_power*d_well_count); + + // 4- record the maximum peak and the associated synchronization parameters + d_gnss_synchro->Acq_delay_samples = (double)index_time; + d_gnss_synchro->Acq_doppler_hz = (double)(index_doppler*d_doppler_step+d_doppler_min); + d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; + + // 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_" << d_gnss_synchro->Acq_doppler_hz << ".dat"; + d_dump_file.open(filename.str().c_str(), std::ios::out + | std::ios::binary); + d_dump_file.write((char*)d_grid_data[index_doppler], n); //write directly |abs(x)|^2 in this Doppler bin? + d_dump_file.close(); + } + + return d_test_statistics; +} + +float pcps_acquisition_fine_doppler_cc::estimate_input_power(gr_vector_const_void_star &input_items) +{ + const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer + // 1- Compute the input signal power estimation + float* p_tmp_vector; + if (posix_memalign((void**)&p_tmp_vector, 16, d_fft_size * sizeof(float)) == 0){}; + volk_32fc_magnitude_squared_32f_u(p_tmp_vector, in, d_fft_size); + + const float* p_const_tmp_vector=p_tmp_vector; + float power; + volk_32f_accumulator_s32f_a(&power, p_const_tmp_vector, d_fft_size); + free(p_tmp_vector); + return ( power / (float)d_fft_size); +} + +int pcps_acquisition_fine_doppler_cc::compute_and_accumulate_grid(gr_vector_const_void_star &input_items) +{ + // initialize acquisition algorithm + const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer + + 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; + + // 2- Doppler frequency search loop + float* p_tmp_vector; + if (posix_memalign((void**)&p_tmp_vector, 16, d_fft_size * sizeof(float)) == 0){}; + + for (int doppler_index=0;doppler_indexget_inbuf(), in, d_grid_doppler_wipeoffs[doppler_index], 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(); + + // save the grid matrix delay file + volk_32fc_magnitude_squared_32f_a(p_tmp_vector, d_ifft->get_outbuf(), d_fft_size); + const float* old_vector=d_grid_data[doppler_index]; + volk_32f_x2_add_32f_u(d_grid_data[doppler_index],old_vector,p_tmp_vector,d_fft_size); + + } + free(p_tmp_vector); + return d_fft_size; +} + +int pcps_acquisition_fine_doppler_cc::estimate_Doppler(gr_vector_const_void_star &input_items, int available_samples) +{ + + //1. generate local code aligned with the acquisition code phase estimation + gr_complex *code_replica; + if (posix_memalign((void**)&code_replica, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + gps_l1_ca_code_gen_complex_sampled(code_replica, d_gnss_synchro->PRN, d_fs_in, 0); + + int shift_index=(int)d_gnss_synchro->Acq_delay_samples; + std::cout<<"shift_index="<get_inbuf(), in, code_replica, d_fft_size); + + // 3. Perform the FFT + d_fft_if->execute(); + + // 4. Compute the magnitude and find the maximum + float* p_tmp_vector; + if (posix_memalign((void**)&p_tmp_vector, 16, d_fft_size * sizeof(float)) == 0){}; + volk_32fc_magnitude_squared_32f_a(p_tmp_vector, d_fft_if->get_outbuf(), d_fft_size); + + unsigned int tmp_index_freq; + volk_32f_index_max_16u_a(&tmp_index_freq,p_tmp_vector,d_fft_size); + + float fftFreqBins[d_fft_size]; + float curr_normal_freq=-1.0; + for (unsigned int i=0;iPRN << ".dat"; + d_dump_file.open(filename.str().c_str(), std::ios::out + | std::ios::binary); + d_dump_file.write((char*)code_replica, n); //write directly |abs(x)|^2 in this Doppler bin? + d_dump_file.close(); + + filename.str(""); + filename << "../data/signal_prn_" << d_gnss_synchro->PRN << ".dat"; + d_dump_file.open(filename.str().c_str(), std::ios::out + | std::ios::binary); + d_dump_file.write((char*)in, n); //write directly |abs(x)|^2 in this Doppler bin? + d_dump_file.close(); + + + n = sizeof(float) * (d_fft_size); + filename.str(""); + filename << "../data/fft_prn_" << d_gnss_synchro->PRN << ".dat"; + d_dump_file.open(filename.str().c_str(), std::ios::out + | std::ios::binary); + d_dump_file.write((char*)p_tmp_vector, n); //write directly |abs(x)|^2 in this Doppler bin? + d_dump_file.close(); + + std::cout<<"FFT maximum present at "< S1 + * S1. GetAssist. Define search grid with assistance information. Reset grid matrix -> S2 + * S2. ComputeGrid. Perform the FFT acqusition doppler and delay grid. + * Accumulate the search grid matrix (#doppler_bins x #fft_size) + * Compare maximum to threshold and decide positive or negative + * If T>=gamma -> S4 else + * If d_well_count S2 + * else if !disable_assist -> S3 + * else -> S5. + * S3. RedefineGrid. Open the grid search to unasisted acquisition. Reset counters and grid. -> S2 + * S4. Positive_Acq: Send message and stop acq -> S0 + * S5. Negative_Acq: Send message and stop acq -> S0 + */ + + switch (d_state) + { + case 0: // S0. StandBy + if (d_active==true) d_state=1; + d_sample_counter += ninput_items[0]; // sample counter + consume_each(ninput_items[0]); + break; + case 1: // S1. GetAssist + get_assistance(); + redefine_grid(); + reset_grid(); + d_sample_counter += ninput_items[0]; // sample counter + consume_each(ninput_items[0]); + d_state=2; + break; + case 2: // S2. ComputeGrid + int consumed_samples; + consumed_samples=compute_and_accumulate_grid(input_items); + d_well_count++; + if (d_well_count>=d_max_dwells) + { + d_state=3; + } + d_sample_counter+=consumed_samples; + consume_each(consumed_samples); + break; + case 3: // Compute test statistics and decide + d_input_power=estimate_input_power(input_items); + d_test_statistics=search_maximum(); + if (d_test_statistics > d_threshold) + { + d_state=5; //perform fine doppler estimation + }else{ + if (d_disable_assist==false) + { + d_disable_assist=true; + //std::cout<<"Acq assist DISABLED for GPS SV "<d_gnss_synchro->PRN<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) << "input signal power " << d_input_power; + + d_active = false; + // Send message to channel queue //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL + d_channel_internal_queue->push(1); // 1-> positive acquisition + free_grid_memory(); + // consume samples to not block the GNU Radio flowgraph + d_sample_counter += ninput_items[0]; // sample counter + consume_each(ninput_items[0]); + d_state=0; + break; + case 7: // Negative_Acq + 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) << "input signal power " << d_input_power; + + d_active = false; + // Send message to channel queue //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL + d_channel_internal_queue->push(2); // 2-> negative acquisition + free_grid_memory(); + // consume samples to not block the GNU Radio flowgraph + d_sample_counter += ninput_items[0]; // sample counter + consume_each(ninput_items[0]); + d_state=0; + break; + default: + d_state=0; + break; + } + return 0; +} diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fine_doppler_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fine_doppler_cc.h new file mode 100644 index 000000000..0b989eee3 --- /dev/null +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fine_doppler_cc.h @@ -0,0 +1,246 @@ +/*! + * \file pcps_assisted_acquisition_cc.h + * \brief This class implements a Parallel Code Phase Search Acquisition with multi-dwells and fine Doppler estimation + * + * 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, 2013. 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_PCPS_acquisition_fine_doppler_cc_H_ +#define GNSS_SDR_PCPS_acquisition_fine_doppler_cc_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "concurrent_queue.h" +#include "gnss_synchro.h" + +class pcps_acquisition_fine_doppler_cc; +typedef boost::shared_ptr +pcps_acquisition_fine_doppler_cc_sptr; +pcps_acquisition_fine_doppler_cc_sptr +pcps_make_acquisition_fine_doppler_cc(int max_dwells, unsigned int sampled_ms, + int doppler_max, int doppler_min, long freq, long fs_in, int samples_per_ms, + boost::shared_ptr 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_acquisition_fine_doppler_cc: public gr::block +{ +private: + friend pcps_acquisition_fine_doppler_cc_sptr + pcps_make_acquisition_fine_doppler_cc(int max_dwells, unsigned int sampled_ms, + int doppler_max, int doppler_min, long freq, long fs_in, + int samples_per_ms, boost::shared_ptr queue, bool dump, + std::string dump_filename); + + pcps_acquisition_fine_doppler_cc(int max_dwells, unsigned int sampled_ms, + int doppler_max, int doppler_min, long freq, long fs_in, + int samples_per_ms, boost::shared_ptr queue, bool dump, + std::string dump_filename); + + void calculate_magnitudes(gr_complex* fft_begin, int doppler_shift, + int doppler_offset); + + int compute_and_accumulate_grid(gr_vector_const_void_star &input_items); + int estimate_Doppler(gr_vector_const_void_star &input_items, int available_samples); + float estimate_input_power(gr_vector_const_void_star &input_items); + double search_maximum(); + void get_assistance(); + void reset_grid(); + void redefine_grid(); + void free_grid_memory(); + + 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; + int d_doppler_max; + int d_doppler_min; + int d_config_doppler_max; + int d_config_doppler_min; + + int d_num_doppler_points; + 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; + + float** d_grid_data; + gr_complex** d_grid_doppler_wipeoffs; + + 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_input_power; + float d_test_statistics; + boost::shared_ptr d_queue; + concurrent_queue *d_channel_internal_queue; + std::ofstream d_dump_file; + int d_state; + bool d_active; + bool d_disable_assist; + int d_well_count; + bool d_dump; + unsigned int d_channel; + + std::string d_dump_filename; + +public: + /*! + * \brief Default destructor. + */ + ~pcps_acquisition_fine_doppler_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_test_statistics; + } + + /*! + * \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); + + + /*! + * \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 /* pcps_acquisition_fine_doppler_cc*/ diff --git a/src/algorithms/libs/CMakeLists.txt b/src/algorithms/libs/CMakeLists.txt index 729398b21..58617d726 100644 --- a/src/algorithms/libs/CMakeLists.txt +++ b/src/algorithms/libs/CMakeLists.txt @@ -46,4 +46,4 @@ include_directories( ) add_library(gnss_sp_libs ${GNSS_SPLIBS_SOURCES}) -target_link_libraries(gnss_sp_libs ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES}) +target_link_libraries(gnss_sp_libs ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES} gnss_rx) diff --git a/src/algorithms/signal_source/adapters/rtlsdr_signal_source.cc b/src/algorithms/signal_source/adapters/rtlsdr_signal_source.cc index 67d8b9daf..f8f3cc271 100644 --- a/src/algorithms/signal_source/adapters/rtlsdr_signal_source.cc +++ b/src/algorithms/signal_source/adapters/rtlsdr_signal_source.cc @@ -60,7 +60,9 @@ RtlsdrSignalSource::RtlsdrSignalSource(ConfigurationInterface* configuration, // RTLSDR Driver parameters AGC_enabled_ = configuration->property(role + ".AGC_enabled",true); freq_ = configuration->property(role + ".freq", GPS_L1_FREQ_HZ); - gain_ = configuration->property(role + ".gain", (double)50.0); + gain_ = configuration->property(role + ".gain", (double)40.0); + rf_gain_ = configuration->property(role + ".rf_gain", (double)40.0); + if_gain_ = configuration->property(role + ".if_gain", (double)40.0); sample_rate_ = configuration->property(role + ".sampling_frequency", (double)2.0e6); item_type_ = configuration->property(role + ".item_type", default_item_type); @@ -98,7 +100,9 @@ RtlsdrSignalSource::RtlsdrSignalSource(ConfigurationInterface* configuration, else { rtlsdr_source_->set_gain_mode(false); - rtlsdr_source_->set_gain(gain_); + rtlsdr_source_->set_gain(gain_,0); + rtlsdr_source_->set_if_gain(rf_gain_,0); + rtlsdr_source_->set_bb_gain(if_gain_,0); std::cout << boost::format("Actual RX Gain: %f dB...") % rtlsdr_source_->get_gain() << std::endl; LOG(INFO) << boost::format("Actual RX Gain: %f dB...") % rtlsdr_source_->get_gain(); } diff --git a/src/algorithms/signal_source/adapters/rtlsdr_signal_source.h b/src/algorithms/signal_source/adapters/rtlsdr_signal_source.h index 81c74022c..12b5d0d85 100644 --- a/src/algorithms/signal_source/adapters/rtlsdr_signal_source.h +++ b/src/algorithms/signal_source/adapters/rtlsdr_signal_source.h @@ -87,6 +87,8 @@ private: double freq_; double gain_; + double if_gain_; + double rf_gain_; std::string item_type_; size_t item_size_; diff --git a/src/core/receiver/control_thread.cc b/src/core/receiver/control_thread.cc index 22b56241d..9b2e48287 100644 --- a/src/core/receiver/control_thread.cc +++ b/src/core/receiver/control_thread.cc @@ -484,10 +484,10 @@ void ControlThread::gps_utc_model_data_collector() if (global_gps_utc_model_map.read(0,gps_utc_old)) { // TODO: Check the UTC MODEL timestamp. If it is newer, then update the UTC MODEL - global_gps_utc_model_map.write(0,gps_utc_old); + global_gps_utc_model_map.write(0,gps_utc); }else{ // insert new ephemeris record - global_gps_utc_model_map.write(0,gps_utc_old); + global_gps_utc_model_map.write(0,gps_utc); } } } diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt new file mode 100644 index 000000000..58570aee9 --- /dev/null +++ b/src/utils/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2010-2013 (see AUTHORS file for a list of contributors) +# +# 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 . +# + +add_subdirectory(front-end-cal) diff --git a/src/utils/front-end-cal/CMakeLists.txt b/src/utils/front-end-cal/CMakeLists.txt new file mode 100644 index 000000000..25029814e --- /dev/null +++ b/src/utils/front-end-cal/CMakeLists.txt @@ -0,0 +1,52 @@ +# Copyright (C) 2012-2013 (see AUTHORS file for a list of contributors) +# +# 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 . +# + +set(FRONT_END_CAL_SOURCES + front_end_cal.cc +) + +include_directories( + ${CMAKE_SOURCE_DIR}/src/core/system_parameters + ${CMAKE_SOURCE_DIR}/src/core/interfaces + ${CMAKE_SOURCE_DIR}/src/core/receiver + ${CMAKE_SOURCE_DIR}/src/core/libs + ${CMAKE_SOURCE_DIR}/src/core/libs/supl + ${CMAKE_SOURCE_DIR}/src/core/libs/supl/asn-rrlp + ${CMAKE_SOURCE_DIR}/src/core/libs/supl/asn-supl + ${CMAKE_SOURCE_DIR}/src/algorithms/libs + ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/adapters + ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/gnuradio_blocks + ${GLOG_INCLUDE_DIRS} + ${GFlags_INCLUDE_DIRS} + ${GNURADIO_CORE_INCLUDE_DIRS} + ${GNURADIO_GRUEL_INCLUDE_DIRS} + ${ARMADILLO_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} +) + +add_library(front_end_cal_lib ${FRONT_END_CAL_SOURCES}) +target_link_libraries(front_end_cal_lib ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES} ${GFlags_LIBS} ${GLOG_LIBRARIES} ${ARMADILLO_LIBRARIES} gnss_rx gnss_sp_libs) + +add_definitions( -DGNSS_SDR_VERSION="${VERSION}" ) + +add_executable(front-end-cal ${CMAKE_CURRENT_SOURCE_DIR}/main.cc) +target_link_libraries(front-end-cal ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES} ${GFlags_LIBS} ${GLOG_LIBRARIES} ${ARMADILLO_LIBRARIES} gnss_rx gnss_sp_libs front_end_cal_lib) + +install(TARGETS front-end-cal + DESTINATION ${CMAKE_SOURCE_DIR}/install + ) diff --git a/src/utils/front-end-cal/front_end_cal.cc b/src/utils/front-end-cal/front_end_cal.cc new file mode 100644 index 000000000..6a77d0586 --- /dev/null +++ b/src/utils/front-end-cal/front_end_cal.cc @@ -0,0 +1,417 @@ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "file_configuration.h" + +#include "gps_navigation_message.h" +#include "gps_ephemeris.h" +#include "gps_almanac.h" +#include "gps_iono.h" +#include "gps_utc_model.h" +#include "gnss_sdr_supl_client.h" +#include +#include +#include +#include + +#include "front_end_cal.h" + + +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; + +FrontEndCal::FrontEndCal() +{ + +} +FrontEndCal::~FrontEndCal() +{ + +} + +bool FrontEndCal::read_assistance_from_XML() +{ + gnss_sdr_supl_client supl_client_ephemeris_; + std::string eph_xml_filename="gps_ephemeris.xml"; + std::cout<< "SUPL: Try read GPS ephemeris from XML file "<::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: Read XML Ephemeris for GPS SV "<first<property("GNSS-SDR.SUPL_gps_enabled",false); + if (enable_gps_supl_assistance==true) + //SUPL SERVER TEST. Not operational yet! + { + DLOG(INFO) << "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); + + std::string default_lac="0x59e2"; + std::string default_ci="0x31b0"; + try { + supl_lac = boost::lexical_cast(configuration_->property("GNSS-SDR.SUPL_LAC",default_lac)); + } catch(boost::bad_lexical_cast &) { + supl_lac=0x59e2; + } + try { + supl_ci = boost::lexical_cast(configuration_->property("GNSS-SDR.SUPL_CI",default_ci)); + } catch(boost::bad_lexical_cast &) { + supl_ci=0x31b0; + } + + bool SUPL_read_gps_assistance_xml=configuration_->property("GNSS-SDR.SUPL_read_gps_assistance_xml",false); + if (SUPL_read_gps_assistance_xml==true) + { + // read assistance from file + read_assistance_from_XML(); + }else{ + + // Request ephemeris from SUPL server + supl_client_ephemeris_.request=1; + DLOG(INFO) << "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++) + { + DLOG(INFO) <<"SUPL: Received Ephemeris for GPS SV "<first<::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++) + { + DLOG(INFO) <<"SUPL: Received Almanac for GPS SV "<first<first,gps_alm_iter->second); + } + if (supl_client_ephemeris_.gps_iono.valid==true) + { + DLOG(INFO) <<"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++) + { + DLOG(INFO) <<"SUPL: Received Acquisition assistance for GPS SV "<first<second.i_satellite_PRN,gps_acq_iter->second); + } + }else{ + DLOG(INFO) << "ERROR: SUPL client for Acquisition assistance returned "<property("GNSS-SDR.read_eph_from_xml",false); + + if (read_ephemeris_from_xml==true) + { + std::cout<< "Trying to read ephemeris from XML file"< eph_map; + eph_map=global_gps_ephemeris_map.get_map_copy(); + + std::map::iterator eph_it; + eph_it=eph_map.find(PRN); + + if (eph_it!=eph_map.end()) + { + + arma::vec SV_pos_ecef = "0.0 0.0 0.0 0.0"; + double obs_time_start,obs_time_stop; + obs_time_start=TOW-num_secs/2; + obs_time_stop=TOW+num_secs/2; + int n_points=round((obs_time_stop-obs_time_start)/step_secs); + arma::vec ranges=arma::zeros(n_points,1); + double obs_time=obs_time_start; + for (int i=0;isecond.satellitePosition(obs_time); + SV_pos_ecef(0)=eph_it->second.d_satpos_X; + SV_pos_ecef(1)=eph_it->second.d_satpos_Y; + SV_pos_ecef(2)=eph_it->second.d_satpos_Z; + // SV distances to observer (true range) + ranges(i)=arma::norm(SV_pos_ecef-obs_ecef,2); + + obs_time+=step_secs; + } + //Observer to satellite radial velocity + //Numeric derivative: Positive slope means that the distance from obs to + //satellite is increasing + arma::vec obs_to_sat_velocity; + obs_to_sat_velocity=(ranges.subvec(1,(n_points-1))-ranges.subvec(0,(n_points-2)))/step_secs; + //Doppler equations are formulated accounting for positive velocities if the + //tx and rx are aproaching to each other. So, the satellite velocity must + //be redefined as: + + obs_to_sat_velocity=-obs_to_sat_velocity; + + //Doppler estimation + arma::vec Doppler_Hz; + Doppler_Hz=(obs_to_sat_velocity/GPS_C_m_s)*GPS_L1_FREQ_HZ; + double mean_Doppler_Hz; + mean_Doppler_Hz=arma::mean(Doppler_Hz); + return mean_Doppler_Hz; + return 0; + }else{ + throw(1); + } + +} + +void FrontEndCal::GPS_L1_front_end_model_E4000(double f_bb_true_Hz,double f_bb_meas_Hz,double fs_nominal_hz, double *estimated_fs_Hz, double *estimated_f_if_Hz, double *f_osc_err_ppm ) +{ +// % Inputs: +// % f_bb_true_Hz - Ideal output frequency in baseband [Hz] +// % f_in_bb_meas_Hz - measured output frequency in baseband [Hz] +// % +// % Outputs: +// % estimated_fs_Hz - Sampling frequency estimation based on the +// % measurements and the front-end model +// % estimated_f_if_bb_Hz - Equivalent bb if frequency estimation based on the +// % measurements and the front-end model + + // Front-end TUNNER Elonics E4000 + RTL2832 sampler + //For GPS L1 1575.42 MHz + + double f_osc_n=28.8e6; + //PLL registers settings (according to E4000 datasheet) + + double N=109; + double Y=65536; + double X=26487; + double R=2; + // Obtained RF center frequency + double f_rf_pll; + f_rf_pll=(f_osc_n*(N+X/Y))/R; + // RF frequency error caused by fractional PLL roundings + double f_bb_err_pll; + f_bb_err_pll=GPS_L1_FREQ_HZ-f_rf_pll; + + // Measured F_rf error + double f_rf_err; + f_rf_err=(f_bb_meas_Hz-f_bb_true_Hz)-f_bb_err_pll; + + double f_osc_err_hz; + f_osc_err_hz=(f_rf_err*R)/(N+X/Y); + + // OJO,segun los datos gnss, la IF positiva hace disminuir la fs!! + f_osc_err_hz=-f_osc_err_hz; + + *f_osc_err_ppm=f_osc_err_hz/(f_osc_n/1e6); + double frac; + frac=fs_nominal_hz/f_osc_n; + + *estimated_fs_Hz=frac*(f_osc_n+f_osc_err_hz); + *estimated_f_if_Hz=f_rf_err; + +} + + diff --git a/src/utils/front-end-cal/front_end_cal.h b/src/utils/front-end-cal/front_end_cal.h new file mode 100644 index 000000000..d5ca55cd3 --- /dev/null +++ b/src/utils/front-end-cal/front_end_cal.h @@ -0,0 +1,20 @@ +#include "concurrent_map.h" +#include "armadillo" + +class FrontEndCal +{ +private: + ConfigurationInterface *configuration_; + arma::vec lla2ecef(arma::vec lla); + arma::vec geodetic2ecef(double phi, double lambda, double h, arma::vec ellipsoid); +public: + + bool read_assistance_from_XML(); + int Get_SUPL_Assist(); + void set_configuration(ConfigurationInterface *configuration); + void get_ephemeris(); + double estimate_doppler_from_eph(unsigned int PRN, double TOW, double lat, double lon, double height); + void GPS_L1_front_end_model_E4000(double f_bb_true_Hz,double f_bb_meas_Hz,double fs_nominal_hz, double *estimated_fs_Hz, double *estimated_f_if_Hz, double *f_osc_err_ppm ); + FrontEndCal(); + ~FrontEndCal(); +}; diff --git a/src/utils/front-end-cal/main.cc b/src/utils/front-end-cal/main.cc new file mode 100644 index 000000000..57042df42 --- /dev/null +++ b/src/utils/front-end-cal/main.cc @@ -0,0 +1,435 @@ +/*! + * \file main.cc + * \brief Main file of the Front-end calibration program. + * \author Javier Arribas, 2013. jarribas(at)cttc.es + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2013 (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 FRONT_END_CAL_VERSION +#define FRONT_END_CAL_VERSION "0.0.1" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "concurrent_map.h" +#include "file_configuration.h" +#include "gps_l1_ca_pcps_acquisition_fine_doppler.h" + +#include "gnss_signal.h" +#include "gnss_synchro.h" +#include "gnss_block_factory.h" + +#include "gps_navigation_message.h" +#include "gps_ephemeris.h" +#include "gps_almanac.h" +#include "gps_iono.h" +#include "gps_utc_model.h" +#include "gnss_sdr_supl_client.h" +#include +#include +#include + +#include "front_end_cal.h" + +using google::LogMessage; + +DECLARE_string(log_dir); + +DEFINE_string(config_file, "../conf/gnss-sdr.conf", + "Path to the file containing the configuration parameters"); + +concurrent_queue 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; + + +bool stop; +concurrent_queue channel_internal_queue; +GpsL1CaPcpsAcquisitionFineDoppler *acquisition; +Gnss_Synchro *gnss_synchro; +std::vector gnss_sync_vector; + +void wait_message() +{ + while (!stop) + { + int message; + channel_internal_queue.wait_and_pop(message); + //std::cout<<"Acq mesage rx="<reset(); + break; + case 2: // negative acq + acquisition->reset(); + break; + case 3: + stop=true; + break; + default: + break; + } + } +} + +bool front_end_capture(ConfigurationInterface *configuration) +{ + gr::top_block_sptr top_block; + GNSSBlockFactory block_factory; + boost::shared_ptr queue; + + queue = gr::msg_queue::make(0); + top_block = gr::make_top_block("Acquisition test"); + + + GNSSBlockInterface *source; + source=block_factory.GetSignalSource(configuration, queue); + + GNSSBlockInterface *conditioner; + conditioner=block_factory.GetSignalConditioner(configuration,queue); + + gr::block_sptr sink; + sink = gr::blocks::file_sink::make(sizeof(gr_complex), "tmp_capture.dat"); + + //--- Find number of samples per spreading code --- + long fs_in_ = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); + int samples_per_code = round(fs_in_ + / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); + int nsamples=samples_per_code*50; + + int skip_samples=fs_in_; // skip 5 seconds + + gr::block_sptr head = gr::blocks::head::make(sizeof(gr_complex), nsamples); + + gr::block_sptr skiphead = gr::blocks::skiphead::make(sizeof(gr_complex), skip_samples); + + try{ + + source->connect(top_block); + conditioner->connect(top_block); + top_block->connect(source->get_right_block(), 0, conditioner->get_left_block(), 0); + top_block->connect(conditioner->get_right_block(), 0, skiphead, 0); + top_block->connect(skiphead, 0,head, 0); + top_block->connect(head, 0, sink, 0); + top_block->run(); + }catch(std::exception& e) + { + std::cout<<"Failure connecting the GNU Radio blocks "< Acquisition_10m) + + gr::top_block_sptr top_block; + boost::shared_ptr queue; + queue = gr::msg_queue::make(0); + top_block = gr::make_top_block("Acquisition test"); + + // Satellite signal definition + gnss_synchro=new Gnss_Synchro(); + gnss_synchro->Channel_ID=0; + gnss_synchro->System = 'G'; + std::string signal = "1C"; + signal.copy(gnss_synchro->Signal,2,0); + gnss_synchro->PRN=1; + + long fs_in_ = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); + + GNSSBlockFactory block_factory; + acquisition = new GpsL1CaPcpsAcquisitionFineDoppler(configuration, "Acquisition", 1, 1, queue); + + acquisition->set_channel(1); + acquisition->set_gnss_synchro(gnss_synchro); + acquisition->set_channel_queue(&channel_internal_queue); + acquisition->set_threshold(configuration->property("Acquisition.threshold", 0.0)); + acquisition->set_doppler_max(configuration->property("Acquisition.doppler_max", 10000)); + acquisition->set_doppler_step(configuration->property("Acquisition.doppler_step", 250)); + + + gr::block_sptr source; + source = gr::blocks::file_source::make(sizeof(gr_complex), "tmp_capture.dat"); + + //gr_basic_block_sptr head = gr_make_head(sizeof(gr_complex), nsamples); + //gr_head_sptr head_sptr = boost::dynamic_pointer_cast(head); + //head_sptr->set_length(nsamples); + //head_sptr->reset(); + + try{ + + acquisition->connect(top_block); + top_block->connect(source, 0, acquisition->get_left_block(), 0); + }catch(std::exception& e) + { + std::cout<<"Failure connecting the GNU Radio blocks "< doppler_measurements_map; + std::map cn0_measurements_map; + + boost::thread ch_thread; + // record startup time + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + bool start_msg=true; + + for (unsigned int PRN=1;PRN<33;PRN++) + { + gnss_synchro->PRN=PRN; + acquisition->set_gnss_synchro(gnss_synchro); + acquisition->init(); + acquisition->reset(); + stop=false; + ch_thread = boost::thread(wait_message); + top_block->run(); + if (start_msg==true) + { + std::cout<<"Searchig for GPS Satellites..."<0) + { + std::cout<<" "<::iterator it = gnss_sync_vector.begin() ; it != gnss_sync_vector.end(); ++it) + { + doppler_measurement_hz+=(*it).Acq_doppler_hz; + //std::cout << "Doppler (SV=" << (*it).PRN<<")="<<(*it).Acq_doppler_hz<<"[Hz]"<(PRN,doppler_measurement_hz)); + }else{ + std::cout<<" . "; + } + channel_internal_queue.push(3); + ch_thread.join(); + gnss_sync_vector.clear(); + boost::dynamic_pointer_cast(source)->seek(0,0); + std::cout.flush(); + } + std::cout<<"]"<0) + { + std::map Eph_map; + Eph_map=global_gps_ephemeris_map.get_map_copy(); + current_TOW=Eph_map.begin()->second.d_TOW; + std::cout<<"Current TOW obtained from SUPL assistance = "<property("GNSS-SDR.init_latitude_deg", 41.0); + double lon_deg = configuration->property("GNSS-SDR.init_longitude_deg", 2.0); + double altitude_m = configuration->property("GNSS-SDR.init_altitude_m", 100); + + std::map f_if_estimation_Hz_map; + std::map f_fs_estimation_Hz_map; + std::map f_ppm_estimation_Hz_map; + + for (std::map::iterator it = doppler_measurements_map.begin() ; it != doppler_measurements_map.end(); ++it) + { + std::cout << "Doppler measured for (SV=" << it->first<<")="<second<<" [Hz]"<first,current_TOW,lat_deg,lon_deg,altitude_m); + std::cout << "Doppler estimated for (SV=" << it->first<<")="<second,fs_in_, &estimated_fs_Hz, &estimated_f_if_Hz, &f_osc_err_ppm ); + + f_if_estimation_Hz_map.insert(std::pair(it->first,estimated_f_if_Hz)); + f_fs_estimation_Hz_map.insert(std::pair(it->first,estimated_fs_Hz)); + f_ppm_estimation_Hz_map.insert(std::pair(it->first,f_osc_err_ppm)); + + }catch(int ex) + { + std::cout<<"Eph not found for SV "<first<::iterator it = f_if_estimation_Hz_map.begin() ; it != f_if_estimation_Hz_map.end(); ++it) + { + mean_f_if_Hz+=(*it).second; + mean_fs_Hz+=f_fs_estimation_Hz_map.find((*it).first)->second; + mean_osc_err_ppm+=f_ppm_estimation_Hz_map.find((*it).first)->second; + } + + mean_f_if_Hz/=n_elements; + mean_fs_Hz/=n_elements; + mean_osc_err_ppm/=n_elements; + + + + + std::cout <0) +// { +// std::map Acq_Assist_map; +// Acq_Assist_map=global_gps_acq_assist_map.get_map_copy(); +// current_TOW=Acq_Assist_map.begin()->second.d_TOW; +// std::cout<<"Current TOW obtained from acquisition assistance = "<