mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 15:23:04 +00:00 
			
		
		
		
	Towards a front-end frequency and sample rate calibration tool. VERY experimental yet.
Bug fixes in acquisition assistance and in linker include files. git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@371 64b25241-fba3-4117-9849-534c7e92360d
This commit is contained in:
		
							
								
								
									
										193
									
								
								conf/front-end-cal.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								conf/front-end-cal.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||||
|  |  | ||||||
| @@ -20,4 +20,4 @@ add_subdirectory(algorithms) | |||||||
| add_subdirectory(core) | add_subdirectory(core) | ||||||
| add_subdirectory(main) | add_subdirectory(main) | ||||||
| add_subdirectory(tests) | add_subdirectory(tests) | ||||||
| #add_subdirectory(utils) | add_subdirectory(utils) | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ set(ACQ_ADAPTER_SOURCES | |||||||
|      galileo_e1_pcps_ambiguous_acquisition.cc |      galileo_e1_pcps_ambiguous_acquisition.cc | ||||||
|      gps_l1_ca_pcps_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( | include_directories( | ||||||
|   | |||||||
| @@ -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 <ul> | ||||||
|  |  *          <li> Javier Arribas, 2011. jarribas(at)cttc.es | ||||||
|  |  *          <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com | ||||||
|  |  *          </ul> | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  * | ||||||
|  |  * 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 <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #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 <iostream> | ||||||
|  | #include <gnuradio/io_signature.h> | ||||||
|  | #include <glog/log_severity.h> | ||||||
|  | #include <glog/logging.h> | ||||||
|  |  | ||||||
|  | using google::LogMessage; | ||||||
|  |  | ||||||
|  | GpsL1CaPcpsAcquisitionFineDoppler::GpsL1CaPcpsAcquisitionFineDoppler( | ||||||
|  |         ConfigurationInterface* configuration, std::string role, | ||||||
|  |         unsigned int in_streams, unsigned int out_streams, | ||||||
|  |         boost::shared_ptr<gr::msg_queue> 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<int> *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<gr::top_block> top_block) | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     //nothing to disconnect, now the tracking uses gr_sync_decimator | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void GpsL1CaPcpsAcquisitionFineDoppler::disconnect(boost::shared_ptr<gr::top_block> top_block) | ||||||
|  | { | ||||||
|  |     //nothing to disconnect, now the tracking uses gr_sync_decimator | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | boost::shared_ptr<gr::basic_block> GpsL1CaPcpsAcquisitionFineDoppler::get_left_block() | ||||||
|  | { | ||||||
|  |     return acquisition_cc_; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | boost::shared_ptr<gr::basic_block> GpsL1CaPcpsAcquisitionFineDoppler::get_right_block() | ||||||
|  | { | ||||||
|  |     return acquisition_cc_; | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -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 <ul> | ||||||
|  |  *          <li> Javier Arribas, 2013. jarribas(at)cttc.es | ||||||
|  |  *          </ul> * | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  * | ||||||
|  |  * 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 <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #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 <gnuradio/msg_queue.h> | ||||||
|  | #include <gnuradio/blocks/stream_to_vector.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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<gr::msg_queue> 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<gr::top_block> top_block); | ||||||
|  |     void disconnect(boost::shared_ptr<gr::top_block> top_block); | ||||||
|  |     boost::shared_ptr<gr::basic_block> get_left_block(); | ||||||
|  |     boost::shared_ptr<gr::basic_block> 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<int> *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<float> * code_; | ||||||
|  |     Gnss_Synchro * gnss_synchro_; | ||||||
|  |     std::string role_; | ||||||
|  |     unsigned int in_streams_; | ||||||
|  |     unsigned int out_streams_; | ||||||
|  |     boost::shared_ptr<gr::msg_queue> queue_; | ||||||
|  |     concurrent_queue<int> *channel_internal_queue_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif /* GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FINE_DOPPLER_H_ */ | ||||||
| @@ -19,6 +19,7 @@ | |||||||
| set(ACQ_GR_BLOCKS_SOURCES  | set(ACQ_GR_BLOCKS_SOURCES  | ||||||
| 	pcps_acquisition_cc.cc  | 	pcps_acquisition_cc.cc  | ||||||
| 	pcps_assisted_acquisition_cc.cc | 	pcps_assisted_acquisition_cc.cc | ||||||
|  | 	pcps_acquisition_fine_doppler_cc.cc | ||||||
| ) | ) | ||||||
|  |  | ||||||
| include_directories( | include_directories( | ||||||
|   | |||||||
| @@ -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 <ul> | ||||||
|  |  *          <li> Javier Arribas, 2013. jarribas(at)cttc.es | ||||||
|  |  *          </ul> | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  * | ||||||
|  |  * 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 <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #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 <gnuradio/io_signature.h> | ||||||
|  | #include <sstream> | ||||||
|  | #include <glog/log_severity.h> | ||||||
|  | #include <glog/logging.h> | ||||||
|  | #include <volk/volk.h> | ||||||
|  | #include "nco_lib.h" | ||||||
|  | #include "concurrent_map.h" | ||||||
|  | #include <algorithm>    // std::rotate | ||||||
|  |  | ||||||
|  | extern concurrent_map<Gps_Acq_Assist> 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<gr::msg_queue> 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<gr::msg_queue> 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<d_num_doppler_points;i++) | ||||||
|  | 	{ | ||||||
|  | 		delete[] d_grid_data[i]; | ||||||
|  | 		delete[] d_grid_doppler_wipeoffs[i]; | ||||||
|  | 	} | ||||||
|  | 	delete d_grid_data; | ||||||
|  | } | ||||||
|  | pcps_acquisition_fine_doppler_cc::~pcps_acquisition_fine_doppler_cc() | ||||||
|  | { | ||||||
|  | 	free(d_carrier); | ||||||
|  | 	free(d_fft_codes); | ||||||
|  | 	delete d_ifft; | ||||||
|  | 	delete d_fft_if; | ||||||
|  | 	if (d_dump) | ||||||
|  | 	{ | ||||||
|  | 		d_dump_file.close(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void pcps_acquisition_fine_doppler_cc::set_local_code(std::complex<float> * 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 "<<this->d_gnss_synchro->PRN<<" (Doppler max,Doppler min)=(" | ||||||
|  | 				<<d_doppler_max<<","<<d_doppler_min<<")"<<std::endl; | ||||||
|  | 	}else{ | ||||||
|  | 		this->d_disable_assist=true; | ||||||
|  | 		//std::cout<<"Acq assist DISABLED for GPS SV "<<this->d_gnss_synchro->PRN<<std::endl; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | void pcps_acquisition_fine_doppler_cc::reset_grid() | ||||||
|  | { | ||||||
|  | 	d_well_count=0; | ||||||
|  | 	for (int i=0;i<d_num_doppler_points;i++) | ||||||
|  | 	{ | ||||||
|  | 		for (unsigned int j=0;j<d_fft_size;j++) | ||||||
|  | 		{ | ||||||
|  | 			d_grid_data[i][j]=0.0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | void pcps_acquisition_fine_doppler_cc::redefine_grid() | ||||||
|  | { | ||||||
|  | 	if (this->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<d_num_doppler_points;i++) | ||||||
|  | 	{ | ||||||
|  | 		if (posix_memalign((void**)&d_grid_data[i], 16, d_fft_size * sizeof(float)) == 0){}; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// create the carrier Doppler wipeoff signals | ||||||
|  | 	int doppler_hz; | ||||||
|  |     float phase_step_rad; | ||||||
|  |     d_grid_doppler_wipeoffs=new gr_complex*[d_num_doppler_points]; | ||||||
|  | 	for (int doppler_index=0;doppler_index<d_num_doppler_points;doppler_index++) | ||||||
|  | 		{ | ||||||
|  |  | ||||||
|  | 		doppler_hz=d_doppler_min+d_doppler_step*doppler_index; | ||||||
|  | 		// doppler search steps | ||||||
|  | 		// compute the carrier doppler wipe-off signal and store it | ||||||
|  | 	    phase_step_rad = (float)GPS_TWO_PI*doppler_hz / (float)d_fs_in; | ||||||
|  |  | ||||||
|  | 	    d_grid_doppler_wipeoffs[doppler_index]=new gr_complex[d_fft_size]; | ||||||
|  | 	    fxp_nco(d_grid_doppler_wipeoffs[doppler_index], d_fft_size,0, phase_step_rad); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | double pcps_acquisition_fine_doppler_cc::search_maximum() | ||||||
|  | { | ||||||
|  | 	float magt = 0.0; | ||||||
|  | 	float fft_normalization_factor; | ||||||
|  | 	int index_doppler = 0; | ||||||
|  | 	unsigned int tmp_intex_t; | ||||||
|  | 	unsigned int index_time = 0; | ||||||
|  |  | ||||||
|  | 	for (int i=0;i<d_num_doppler_points;i++) | ||||||
|  | 	{ | ||||||
|  | 		volk_32f_index_max_16u_a(&tmp_intex_t,d_grid_data[i],d_fft_size); | ||||||
|  | 		if (d_grid_data[i][tmp_intex_t] > 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_index<d_num_doppler_points;doppler_index++) | ||||||
|  | 		{ | ||||||
|  | 		// doppler search steps | ||||||
|  | 		// Perform the carrier wipe-off | ||||||
|  | 		volk_32fc_x2_multiply_32fc_u(d_fft_if->get_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="<<shift_index<<std::endl; | ||||||
|  | 	//std::rotate(code_replica,code_replica+shift_index,code_replica+available_samples); | ||||||
|  |  | ||||||
|  | 	//2. Perform code wipe-off | ||||||
|  | 	const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer | ||||||
|  |  | ||||||
|  | 	volk_32fc_x2_multiply_32fc_u(d_fft_if->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;i<d_fft_size;i++) | ||||||
|  | 	{ | ||||||
|  | 		fftFreqBins[i]=(d_fs_in/2.0)*curr_normal_freq; | ||||||
|  | 		curr_normal_freq+=2/d_fft_size; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	std::stringstream filename; | ||||||
|  | 	std::streamsize n = sizeof(gr_complex) * (d_fft_size); | ||||||
|  |  | ||||||
|  | 	filename.str(""); | ||||||
|  | 	filename << "../data/code_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*)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 "<<fftFreqBins[tmp_index_freq]<<" [Hz]"<<std::endl; | ||||||
|  |  | ||||||
|  | 	return d_fft_size; | ||||||
|  | } | ||||||
|  | int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items, | ||||||
|  | 		gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, | ||||||
|  | 		gr_vector_void_star &output_items) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | 	/*! | ||||||
|  | 	 * TODO: 	High sensitivity acquisition algorithm: | ||||||
|  | 	 * 			State Mechine: | ||||||
|  | 	 * 			S0. StandBy. If d_active==1 -> 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<max_dwells -> 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 "<<this->d_gnss_synchro->PRN<<std::endl; | ||||||
|  | 				d_state=4; | ||||||
|  | 			}else{ | ||||||
|  | 				d_state=7; //negative acquisition | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		d_sample_counter += ninput_items[0]; // sample counter | ||||||
|  | 		consume_each(ninput_items[0]); | ||||||
|  | 		break; | ||||||
|  | 	case 4: // RedefineGrid | ||||||
|  | 		free_grid_memory(); | ||||||
|  | 		redefine_grid(); | ||||||
|  | 		reset_grid(); | ||||||
|  | 		d_sample_counter += ninput_items[0]; // sample counter | ||||||
|  | 		consume_each(ninput_items[0]); | ||||||
|  | 		d_state=2; | ||||||
|  | 		break; | ||||||
|  | 	case 5: // Fine doppler estimation | ||||||
|  | 		DLOG(INFO) << "Performing fine Doppler estimation"; | ||||||
|  | 		//estimate_Doppler(input_items, ninput_items[0]); //disabled in repo | ||||||
|  | 		d_sample_counter += ninput_items[0]; // sample counter | ||||||
|  | 		consume_each(ninput_items[0]); | ||||||
|  | 		d_state=6; | ||||||
|  | 		break; | ||||||
|  | 	case 6: // Positive_Acq | ||||||
|  | 		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) << "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; | ||||||
|  | } | ||||||
| @@ -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). | ||||||
|  |  *  <ol> | ||||||
|  |  *  <li> Compute the input signal power estimation | ||||||
|  |  *  <li> Doppler serial search loop | ||||||
|  |  *  <li> Perform the FFT-based circular convolution (parallel time search) | ||||||
|  |  *  <li> Record the maximum peak and the associated synchronization parameters | ||||||
|  |  *  <li> Compute the test statistics and compare to the threshold | ||||||
|  |  *  <li> Declare positive or negative acquisition using a message queue | ||||||
|  |  *  </ol> | ||||||
|  |  * | ||||||
|  |  * 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 <ul> | ||||||
|  |  *          <li> Javier Arribas, 2013. jarribas(at)cttc.es | ||||||
|  |  *          </ul> | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  * | ||||||
|  |  * 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 <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef GNSS_SDR_PCPS_acquisition_fine_doppler_cc_H_ | ||||||
|  | #define GNSS_SDR_PCPS_acquisition_fine_doppler_cc_H_ | ||||||
|  |  | ||||||
|  | #include <fstream> | ||||||
|  | #include <gnuradio/block.h> | ||||||
|  | #include <gnuradio/msg_queue.h> | ||||||
|  | #include <gnuradio/gr_complex.h> | ||||||
|  | #include <gnuradio/fft/fft.h> | ||||||
|  | #include <queue> | ||||||
|  | #include <boost/thread/mutex.hpp> | ||||||
|  | #include <boost/thread/thread.hpp> | ||||||
|  | #include "concurrent_queue.h" | ||||||
|  | #include "gnss_synchro.h" | ||||||
|  |  | ||||||
|  | class pcps_acquisition_fine_doppler_cc; | ||||||
|  | typedef boost::shared_ptr<pcps_acquisition_fine_doppler_cc> | ||||||
|  | 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<gr::msg_queue> 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<gr::msg_queue> 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<gr::msg_queue> 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<gr::msg_queue> d_queue; | ||||||
|  | 	concurrent_queue<int> *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<float> * 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<int> *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*/ | ||||||
| @@ -46,4 +46,4 @@ include_directories( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| add_library(gnss_sp_libs ${GNSS_SPLIBS_SOURCES}) | 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) | ||||||
|   | |||||||
| @@ -60,7 +60,9 @@ RtlsdrSignalSource::RtlsdrSignalSource(ConfigurationInterface* configuration, | |||||||
|     // RTLSDR Driver parameters |     // RTLSDR Driver parameters | ||||||
|     AGC_enabled_ = configuration->property(role + ".AGC_enabled",true); |     AGC_enabled_ = configuration->property(role + ".AGC_enabled",true); | ||||||
|     freq_ = configuration->property(role + ".freq", GPS_L1_FREQ_HZ); |     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); |     sample_rate_ = configuration->property(role + ".sampling_frequency", (double)2.0e6); | ||||||
|     item_type_ = configuration->property(role + ".item_type", default_item_type); |     item_type_ = configuration->property(role + ".item_type", default_item_type); | ||||||
|  |  | ||||||
| @@ -98,7 +100,9 @@ RtlsdrSignalSource::RtlsdrSignalSource(ConfigurationInterface* configuration, | |||||||
|             else |             else | ||||||
|                 { |                 { | ||||||
|                     rtlsdr_source_->set_gain_mode(false); |                     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; |                     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(); |                     LOG(INFO) << boost::format("Actual RX Gain: %f dB...") % rtlsdr_source_->get_gain(); | ||||||
|                 } |                 } | ||||||
|   | |||||||
| @@ -87,6 +87,8 @@ private: | |||||||
|  |  | ||||||
|     double freq_; |     double freq_; | ||||||
|     double gain_; |     double gain_; | ||||||
|  |     double if_gain_; | ||||||
|  |     double rf_gain_; | ||||||
|  |  | ||||||
|     std::string item_type_; |     std::string item_type_; | ||||||
|     size_t item_size_; |     size_t item_size_; | ||||||
|   | |||||||
| @@ -484,10 +484,10 @@ void ControlThread::gps_utc_model_data_collector() | |||||||
| 			if (global_gps_utc_model_map.read(0,gps_utc_old)) | 			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 | 				// 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{ | 			}else{ | ||||||
| 				// insert new ephemeris record | 				// insert new ephemeris record | ||||||
| 				global_gps_utc_model_map.write(0,gps_utc_old); | 				global_gps_utc_model_map.write(0,gps_utc); | ||||||
| 			} | 			} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								src/utils/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/utils/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <http://www.gnu.org/licenses/>. | ||||||
|  | # | ||||||
|  |  | ||||||
|  | add_subdirectory(front-end-cal) | ||||||
							
								
								
									
										52
									
								
								src/utils/front-end-cal/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/utils/front-end-cal/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <http://www.gnu.org/licenses/>. | ||||||
|  | # | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  |         ) | ||||||
							
								
								
									
										417
									
								
								src/utils/front-end-cal/front_end_cal.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										417
									
								
								src/utils/front-end-cal/front_end_cal.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,417 @@ | |||||||
|  |  | ||||||
|  | #include <exception> | ||||||
|  | #include <boost/filesystem.hpp> | ||||||
|  | #include <gflags/gflags.h> | ||||||
|  | #include <glog/log_severity.h> | ||||||
|  | #include <glog/logging.h> | ||||||
|  |  | ||||||
|  | #include <boost/thread/mutex.hpp> | ||||||
|  | #include <boost/thread/thread.hpp> | ||||||
|  | #include <boost/lexical_cast.hpp> | ||||||
|  |  | ||||||
|  | #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 <sys/time.h> | ||||||
|  | #include <ctime> | ||||||
|  | #include <memory> | ||||||
|  | #include <math.h> | ||||||
|  |  | ||||||
|  | #include "front_end_cal.h" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | extern	concurrent_map<Gps_Ephemeris> global_gps_ephemeris_map; | ||||||
|  | extern	concurrent_map<Gps_Iono> global_gps_iono_map; | ||||||
|  | extern	concurrent_map<Gps_Utc_Model> global_gps_utc_model_map; | ||||||
|  | extern	concurrent_map<Gps_Almanac> global_gps_almanac_map; | ||||||
|  | extern	concurrent_map<Gps_Acq_Assist> 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 "<<eph_xml_filename<<std::endl; | ||||||
|  | 	if (supl_client_ephemeris_.load_ephemeris_xml(eph_xml_filename)==true) | ||||||
|  | 	{ | ||||||
|  | 		std::map<int,Gps_Ephemeris>::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 "<<gps_eph_iter->first<<std::endl; | ||||||
|  | 			std::cout << "New Ephemeris record inserted with Toe="<<gps_eph_iter->second.d_Toe<<" and GPS Week="<<gps_eph_iter->second.i_GPS_week<<std::endl; | ||||||
|  | 			global_gps_ephemeris_map.write(gps_eph_iter->second.i_satellite_PRN,gps_eph_iter->second); | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	}else{ | ||||||
|  | 		std::cout<< "ERROR: SUPL client error reading XML"<<std::endl; | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int FrontEndCal::Get_SUPL_Assist() | ||||||
|  | { | ||||||
|  | 	//#########GNSS Asistence ################################# | ||||||
|  | 	gnss_sdr_supl_client supl_client_acquisition_; | ||||||
|  | 	gnss_sdr_supl_client supl_client_ephemeris_; | ||||||
|  | 	int supl_mcc; // Current network MCC (Mobile country code), 3 digits. | ||||||
|  | 	int supl_mns; //Current network MNC (Mobile Network code), 2 or 3 digits. | ||||||
|  | 	int supl_lac; // Current network LAC (Location area code),16 bits, 1-65520 are valid values. | ||||||
|  | 	int supl_ci; // Cell Identity (16 bits, 0-65535 are valid values). | ||||||
|  | 	// GNSS Assistance configuration | ||||||
|  | 	int error=0; | ||||||
|  | 	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! | ||||||
|  | 	{ | ||||||
|  | 		DLOG(INFO) << "SUPL RRLP GPS assistance enabled!"<<std::endl; | ||||||
|  | 		std::string default_acq_server="supl.nokia.com"; | ||||||
|  | 		std::string default_eph_server="supl.google.com"; | ||||||
|  | 		supl_client_ephemeris_.server_name=configuration_->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<int>(configuration_->property("GNSS-SDR.SUPL_LAC",default_lac)); | ||||||
|  | 		} catch(boost::bad_lexical_cast &) { | ||||||
|  | 			supl_lac=0x59e2; | ||||||
|  | 		} | ||||||
|  | 		try { | ||||||
|  | 			supl_ci = boost::lexical_cast<int>(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.."<<std::endl; | ||||||
|  | 			error=supl_client_ephemeris_.get_assistance(supl_mcc,supl_mns,supl_lac,supl_ci); | ||||||
|  | 			if (error==0) | ||||||
|  | 			{ | ||||||
|  | 				std::map<int,Gps_Ephemeris>::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 "<<gps_eph_iter->first<<std::endl; | ||||||
|  | 					DLOG(INFO)  << "New Ephemeris record inserted with Toe="<<gps_eph_iter->second.d_Toe<<" and GPS Week="<<gps_eph_iter->second.i_GPS_week<<std::endl; | ||||||
|  | 					global_gps_ephemeris_map.write(gps_eph_iter->second.i_satellite_PRN,gps_eph_iter->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) | ||||||
|  | 				{ | ||||||
|  | 					DLOG(INFO) <<"SUPL: XML Ephemeris file created"<<std::endl; | ||||||
|  | 				} | ||||||
|  | 			}else{ | ||||||
|  | 				DLOG(INFO) << "ERROR: SUPL client for Ephemeris returned "<<error<<std::endl; | ||||||
|  | 				DLOG(INFO) << "Please check internet connection and SUPL server configuration"<<error<<std::endl; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Request almanac , IONO and UTC Model | ||||||
|  | 			supl_client_ephemeris_.request=0; | ||||||
|  | 			DLOG(INFO) << "SUPL: Try read Almanac, Iono, Utc Model, Ref Time and Ref Location from SUPL server.."<<std::endl; | ||||||
|  | 			error=supl_client_ephemeris_.get_assistance(supl_mcc,supl_mns,supl_lac,supl_ci); | ||||||
|  | 			if (error==0) | ||||||
|  | 			{ | ||||||
|  | 				std::map<int,Gps_Almanac>::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 "<<gps_alm_iter->first<<std::endl; | ||||||
|  | 					global_gps_almanac_map.write(gps_alm_iter->first,gps_alm_iter->second); | ||||||
|  | 				} | ||||||
|  | 				if (supl_client_ephemeris_.gps_iono.valid==true) | ||||||
|  | 				{ | ||||||
|  | 					DLOG(INFO) <<"SUPL: Received GPS Iono"<<std::endl; | ||||||
|  | 					global_gps_iono_map.write(0,supl_client_ephemeris_.gps_iono); | ||||||
|  | 				} | ||||||
|  | 				if (supl_client_ephemeris_.gps_utc.valid==true) | ||||||
|  | 				{ | ||||||
|  | 					DLOG(INFO) <<"SUPL: Received GPS UTC Model"<<std::endl; | ||||||
|  | 					global_gps_utc_model_map.write(0,supl_client_ephemeris_.gps_utc); | ||||||
|  | 				} | ||||||
|  | 			}else{ | ||||||
|  | 				DLOG(INFO) << "ERROR: SUPL client for Almanac returned "<<error<<std::endl; | ||||||
|  | 				DLOG(INFO) << "Please check internet connection and SUPL server configuration"<<error<<std::endl; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Request acquisition assistance | ||||||
|  | 			supl_client_acquisition_.request=2; | ||||||
|  | 			DLOG(INFO) << "SUPL: Try read Acquisition assistance from SUPL server.."<<std::endl; | ||||||
|  |  | ||||||
|  | 			error=supl_client_acquisition_.get_assistance(supl_mcc,supl_mns,supl_lac,supl_ci); | ||||||
|  | 			if (error==0) | ||||||
|  | 			{ | ||||||
|  | 				std::map<int,Gps_Acq_Assist>::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 "<<gps_acq_iter->first<<std::endl; | ||||||
|  | 					DLOG(INFO)  << "New acq assist record inserted"<<std::endl; | ||||||
|  | 					global_gps_acq_assist_map.write(gps_acq_iter->second.i_satellite_PRN,gps_acq_iter->second); | ||||||
|  | 				} | ||||||
|  | 			}else{ | ||||||
|  | 				DLOG(INFO) << "ERROR: SUPL client for Acquisition assistance returned "<<error<<std::endl; | ||||||
|  | 				DLOG(INFO) << "Please check internet connection and SUPL server configuration"<<error<<std::endl; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return error; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void FrontEndCal::set_configuration(ConfigurationInterface *configuration) | ||||||
|  | { | ||||||
|  |     configuration_= configuration; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void FrontEndCal::get_ephemeris() | ||||||
|  | { | ||||||
|  | 	bool read_ephemeris_from_xml=configuration_->property("GNSS-SDR.read_eph_from_xml",false); | ||||||
|  |  | ||||||
|  | 	if (read_ephemeris_from_xml==true) | ||||||
|  | 	{ | ||||||
|  | 		std::cout<< "Trying to read ephemeris from XML file"<<std::endl; | ||||||
|  | 		if (read_assistance_from_XML()==false) | ||||||
|  | 		{ | ||||||
|  | 			std::cout<< "ERROR: Could not read Ephemeris file: Trying to get ephemeris from SUPL client.."<<std::endl; | ||||||
|  | 			Get_SUPL_Assist(); | ||||||
|  | 		} | ||||||
|  | 	}else{ | ||||||
|  | 		std::cout<< "Trying to read ephemeris from SUPL server"<<std::endl; | ||||||
|  | 		Get_SUPL_Assist(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | arma::vec FrontEndCal::lla2ecef(arma::vec lla) | ||||||
|  | { | ||||||
|  | //	%  LLA2ECEF Convert geodetic coordinates to Earth-centered Earth-fixed | ||||||
|  | //	%  (ECEF)  coordinates. | ||||||
|  | //	%   P = LLA2ECEF( LLA ) converts an M-by-3 array of geodetic coordinates | ||||||
|  | //	%   (latitude, longitude and altitude), LLA, to an M-by-3 array of ECEF | ||||||
|  | //	%   coordinates, P.  LLA is in [degrees degrees meters].  P is in meters. | ||||||
|  | //	%   The default ellipsoid planet is WGS84. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	// WGS84 flattening | ||||||
|  | 	double f; | ||||||
|  | 	f  = 1/298.257223563; | ||||||
|  |  | ||||||
|  | 	// WGS84 equatorial radius | ||||||
|  | 	double R; | ||||||
|  | 	R =  6378137; | ||||||
|  |  | ||||||
|  | 	double phi,lambda; | ||||||
|  | 	arma::vec ellipsoid="0.0 0.0"; | ||||||
|  | 	phi=(lla(0)/360.0)*GPS_TWO_PI; | ||||||
|  | 	lambda=(lla(1)/360.0)*GPS_TWO_PI; | ||||||
|  |  | ||||||
|  | 	ellipsoid(0)=R; | ||||||
|  | 	ellipsoid(1)=sqrt(1-(1-f)*(1-f)); | ||||||
|  |  | ||||||
|  | 	arma::vec ecef="0.0 0.0 0.0 0.0"; | ||||||
|  | 	ecef = geodetic2ecef(phi, lambda,lla(3),ellipsoid); | ||||||
|  |  | ||||||
|  | 	return ecef; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | arma::vec FrontEndCal::geodetic2ecef(double phi, double lambda, double h, arma::vec ellipsoid) | ||||||
|  | { | ||||||
|  | //%GEODETIC2ECEF Convert geodetic to geocentric (ECEF) coordinates | ||||||
|  | //% | ||||||
|  | //%   [X, Y, Z] = GEODETIC2ECEF(PHI, LAMBDA, H, ELLIPSOID) converts geodetic | ||||||
|  | //%   point locations specified by the coordinate arrays PHI (geodetic | ||||||
|  | //%   latitude in radians), LAMBDA (longitude in radians), and H (ellipsoidal | ||||||
|  | //%   height) to geocentric Cartesian coordinates X, Y, and Z.  The geodetic | ||||||
|  | //%   coordinates refer to the reference ellipsoid specified by ELLIPSOID (a | ||||||
|  | //%   row vector with the form [semimajor axis, eccentricity]).  H must use | ||||||
|  | //%   the same units as the semimajor axis;  X, Y, and Z will be expressed in | ||||||
|  | //%   these units also. | ||||||
|  | //% | ||||||
|  | //%   The geocentric Cartesian coordinate system is fixed with respect to the | ||||||
|  | //%   Earth, with its origin at the center of the ellipsoid and its X-, Y-, | ||||||
|  | //%   and Z-axes intersecting the surface at the following points: | ||||||
|  | //% | ||||||
|  | //%                PHI  LAMBDA | ||||||
|  | //%      X-axis:    0     0      (Equator at the Prime Meridian) | ||||||
|  | //%      Y-axis:    0   pi/2     (Equator at 90-degrees East) | ||||||
|  | //%      Z-axis:  pi/2    0      (North Pole) | ||||||
|  | //% | ||||||
|  | //%   A common synonym is Earth-Centered, Earth-Fixed coordinates, or ECEF. | ||||||
|  | //% | ||||||
|  | //%   See also ECEF2GEODETIC, ECEF2LV, GEODETIC2GEOCENTRICLAT, LV2ECEF. | ||||||
|  | //% Copyright 2004-2009 The MathWorks, Inc. | ||||||
|  | //% $Revision: 1.1.6.4 $  $Date: 2009/04/15 23:34:46 $ | ||||||
|  |  | ||||||
|  | //% Reference | ||||||
|  | //% --------- | ||||||
|  | //% Paul R. Wolf and Bon A. Dewitt, "Elements of Photogrammetry with | ||||||
|  | //% Applications in GIS," 3rd Ed., McGraw-Hill, 2000 (Appendix F-3). | ||||||
|  |  | ||||||
|  | 	double a; | ||||||
|  | 	a  = ellipsoid(0); | ||||||
|  | 	double e2; | ||||||
|  | 	e2 = ellipsoid(1)*ellipsoid(1); | ||||||
|  |  | ||||||
|  | 	double sinphi,cosphi; | ||||||
|  |  | ||||||
|  | 	sinphi = sin(phi); | ||||||
|  | 	cosphi = cos(phi); | ||||||
|  | 	double N; | ||||||
|  | 	N  = a / sqrt(1 - e2 * sinphi*sinphi); | ||||||
|  |  | ||||||
|  | 	arma::vec ecef="0.0 0.0 0.0 0.0"; | ||||||
|  |  | ||||||
|  | 	ecef(0) = (N + h) * cosphi * cos(lambda); | ||||||
|  | 	ecef(1) = (N + h) * cosphi * sin(lambda); | ||||||
|  | 	ecef(2)= (N*(1 - e2) + h) * sinphi; | ||||||
|  |  | ||||||
|  | 	return ecef; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | double FrontEndCal::estimate_doppler_from_eph(unsigned int PRN, double TOW, double lat, double lon, double height) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | 	int num_secs=10; | ||||||
|  | 	double step_secs=0.5; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	//Observer position ECEF | ||||||
|  | 	arma::vec obs_ecef= "0.0 0.0 0.0 0.0"; | ||||||
|  | 	arma::vec lla = "0.0 0.0 0.0 0.0"; | ||||||
|  | 	lla(0)=lat; | ||||||
|  | 	lla(1)=lon; | ||||||
|  | 	lla(2)=height; | ||||||
|  | 	obs_ecef=lla2ecef(lla); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	//Satellite positions ECEF | ||||||
|  | 	std::map<int,Gps_Ephemeris> eph_map; | ||||||
|  | 	eph_map=global_gps_ephemeris_map.get_map_copy(); | ||||||
|  |  | ||||||
|  | 	std::map<int,Gps_Ephemeris>::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;i<n_points;i++) | ||||||
|  | 		{ | ||||||
|  | 			eph_it->second.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; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										20
									
								
								src/utils/front-end-cal/front_end_cal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/utils/front-end-cal/front_end_cal.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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(); | ||||||
|  | }; | ||||||
							
								
								
									
										435
									
								
								src/utils/front-end-cal/main.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										435
									
								
								src/utils/front-end-cal/main.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  */ | ||||||
|  | #ifndef FRONT_END_CAL_VERSION | ||||||
|  | #define FRONT_END_CAL_VERSION "0.0.1" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include <exception> | ||||||
|  | #include <boost/filesystem.hpp> | ||||||
|  | #include <gflags/gflags.h> | ||||||
|  | #include <glog/log_severity.h> | ||||||
|  | #include <glog/logging.h> | ||||||
|  | #include <gnuradio/msg_queue.h> | ||||||
|  | #include <gnuradio/top_block.h> | ||||||
|  | #include <gnuradio/blocks/null_sink.h> | ||||||
|  | #include <gnuradio/blocks/skiphead.h> | ||||||
|  | #include <gnuradio/blocks/head.h> | ||||||
|  | #include <gnuradio/blocks/file_source.h> | ||||||
|  | #include <gnuradio/blocks/file_sink.h> | ||||||
|  |  | ||||||
|  | #include <queue> | ||||||
|  | #include <boost/thread/mutex.hpp> | ||||||
|  | #include <boost/thread/thread.hpp> | ||||||
|  | #include <boost/lexical_cast.hpp> | ||||||
|  | #include <vector> | ||||||
|  | #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 <sys/time.h> | ||||||
|  | #include <ctime> | ||||||
|  | #include <memory> | ||||||
|  |  | ||||||
|  | #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<Gps_Ephemeris> global_gps_ephemeris_queue; | ||||||
|  | concurrent_queue<Gps_Iono> global_gps_iono_queue; | ||||||
|  | concurrent_queue<Gps_Utc_Model> global_gps_utc_model_queue; | ||||||
|  | concurrent_queue<Gps_Almanac> global_gps_almanac_queue; | ||||||
|  | concurrent_queue<Gps_Acq_Assist> global_gps_acq_assist_queue; | ||||||
|  |  | ||||||
|  | concurrent_map<Gps_Ephemeris> global_gps_ephemeris_map; | ||||||
|  | concurrent_map<Gps_Iono> global_gps_iono_map; | ||||||
|  | concurrent_map<Gps_Utc_Model> global_gps_utc_model_map; | ||||||
|  | concurrent_map<Gps_Almanac> global_gps_almanac_map; | ||||||
|  | concurrent_map<Gps_Acq_Assist> global_gps_acq_assist_map; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | bool stop; | ||||||
|  | concurrent_queue<int> channel_internal_queue; | ||||||
|  | GpsL1CaPcpsAcquisitionFineDoppler *acquisition; | ||||||
|  | Gnss_Synchro *gnss_synchro; | ||||||
|  | std::vector<Gnss_Synchro> gnss_sync_vector; | ||||||
|  |  | ||||||
|  | void wait_message() | ||||||
|  | { | ||||||
|  |     while (!stop) | ||||||
|  |         { | ||||||
|  |     		int message; | ||||||
|  |     		channel_internal_queue.wait_and_pop(message); | ||||||
|  |     		//std::cout<<"Acq mesage rx="<<message<<std::endl; | ||||||
|  |     		switch (message) | ||||||
|  |     		{ | ||||||
|  |     		case 1: // Positive acq | ||||||
|  |     		    gnss_sync_vector.push_back(*gnss_synchro); | ||||||
|  |     			acquisition->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<gr::msg_queue> 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 "<<e.what()<<std::endl; | ||||||
|  |     	return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     delete conditioner; | ||||||
|  |     delete source; | ||||||
|  |  | ||||||
|  |     return true; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(int argc, char** argv) | ||||||
|  | { | ||||||
|  |     const std::string intro_help( | ||||||
|  |             std::string("\n RTL-SDR E4000 RF fornt-end center frequency and sampling rate calibration tool that uses GPS signals\n") | ||||||
|  |     + | ||||||
|  |     "Copyright (C) 2010-2013 (see AUTHORS file for a list of contributors)\n" | ||||||
|  |     + | ||||||
|  |     "This program comes with ABSOLUTELY NO WARRANTY;\n" | ||||||
|  |     + | ||||||
|  |     "See COPYING file to see a copy of the General Public License\n \n"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     google::SetUsageMessage(intro_help); | ||||||
|  |     google::SetVersionString(FRONT_END_CAL_VERSION); | ||||||
|  |     google::ParseCommandLineFlags(&argc, &argv, true); | ||||||
|  |  | ||||||
|  |     std::cout << "Initializing... Please wait." << std::endl; | ||||||
|  |  | ||||||
|  |     google::InitGoogleLogging(argv[0]); | ||||||
|  |     if (FLAGS_log_dir.empty()) | ||||||
|  |         { | ||||||
|  |              std::cout << "Logging will be done at " | ||||||
|  |  | ||||||
|  |                  << "/tmp" | ||||||
|  |                  << std::endl | ||||||
|  |                  << "Use gnss-sdr --log_dir=/path/to/log to change that." | ||||||
|  |                  << std::endl; | ||||||
|  |         } | ||||||
|  |     else | ||||||
|  |         { | ||||||
|  |             const boost::filesystem::path p (FLAGS_log_dir); | ||||||
|  |             if (!boost::filesystem::exists(p)) | ||||||
|  |                 { | ||||||
|  |                     std::cout << "The path " | ||||||
|  |                         << FLAGS_log_dir | ||||||
|  |                         << " does not exist, attempting to create it" | ||||||
|  |                         << std::endl; | ||||||
|  |                     boost::filesystem::create_directory(p); | ||||||
|  |                 } | ||||||
|  |             std::cout << "Logging with be done at " | ||||||
|  |                 << FLAGS_log_dir << std::endl; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     // 0. Instantiate the FrontEnd Calibration class | ||||||
|  |     FrontEndCal front_end_cal; | ||||||
|  |  | ||||||
|  |     // 1. Load configuration parameters from config file | ||||||
|  |  | ||||||
|  |     ConfigurationInterface *configuration; | ||||||
|  |     configuration= new FileConfiguration(FLAGS_config_file); | ||||||
|  |     front_end_cal.set_configuration(configuration); | ||||||
|  |  | ||||||
|  |     // Capture file | ||||||
|  |  | ||||||
|  |     if (front_end_capture(configuration)) | ||||||
|  |     { | ||||||
|  |     	std::cout<<"Front-end RAW samples captured"<<std::endl; | ||||||
|  |     }else{ | ||||||
|  |     	std::cout<<"Failure capturing front-end samples"<<std::endl; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 3. Setup GNU Radio flowgraph (RTL-SDR -> Acquisition_10m) | ||||||
|  |  | ||||||
|  |     gr::top_block_sptr top_block; | ||||||
|  |     boost::shared_ptr<gr::msg_queue> 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<gr_head>(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 "<<std::endl; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 4. Run the flowgraph | ||||||
|  |  | ||||||
|  |     std::map<int,double> doppler_measurements_map; | ||||||
|  |     std::map<int,double> 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..."<<std::endl; | ||||||
|  |         	std::cout<<"["; | ||||||
|  |         	start_msg=false; | ||||||
|  |         } | ||||||
|  |         if (gnss_sync_vector.size()>0) | ||||||
|  |         { | ||||||
|  |         	std::cout<<" "<<PRN<<" "; | ||||||
|  |         	double doppler_measurement_hz=0; | ||||||
|  |             for (std::vector<Gnss_Synchro>::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]"<<std::endl; | ||||||
|  |               } | ||||||
|  |             doppler_measurement_hz=doppler_measurement_hz/gnss_sync_vector.size(); | ||||||
|  |             doppler_measurements_map.insert(std::pair<int,double>(PRN,doppler_measurement_hz)); | ||||||
|  |         }else{ | ||||||
|  |         	std::cout<<" . "; | ||||||
|  |         } | ||||||
|  |         channel_internal_queue.push(3); | ||||||
|  |         ch_thread.join(); | ||||||
|  |         gnss_sync_vector.clear(); | ||||||
|  |         boost::dynamic_pointer_cast<gr::blocks::file_source>(source)->seek(0,0); | ||||||
|  |         std::cout.flush(); | ||||||
|  |     } | ||||||
|  |     std::cout<<"]"<<std::endl; | ||||||
|  |  | ||||||
|  |     // report the elapsed time | ||||||
|  |     gettimeofday(&tv, NULL); | ||||||
|  |     long long int end = tv.tv_sec * 1000000 + tv.tv_usec; | ||||||
|  |     std::cout << "Total signal acquisition run time " | ||||||
|  |         << ((double)(end - begin))/1000000.0 | ||||||
|  |         << " [seconds]" << std::endl; | ||||||
|  |  | ||||||
|  |     // 5. Get visible GPS satellites (positive acquisitions with Doppler measurements) | ||||||
|  |  | ||||||
|  |     // 2. Get SUPL information from server: Ephemeris record, assistance info and TOW | ||||||
|  |     front_end_cal.get_ephemeris(); | ||||||
|  |  | ||||||
|  |     // 6. Compute Doppler estimations | ||||||
|  |  | ||||||
|  |     //find TOW from SUPL assistance | ||||||
|  |  | ||||||
|  |     double current_TOW=0; | ||||||
|  |         if (global_gps_ephemeris_map.size()>0) | ||||||
|  |         { | ||||||
|  |         	std::map<int,Gps_Ephemeris> 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 = "<<current_TOW<<std::endl; | ||||||
|  |         }else{ | ||||||
|  |         	std::cout<<"Unable to get Ephemeris SUPL assistance. TOW is unknown!"<<std::endl; | ||||||
|  |         } | ||||||
|  |     //Get user position from config file (or from SUPL using GSM Cell ID) | ||||||
|  |     double lat_deg = configuration->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<int,double> f_if_estimation_Hz_map; | ||||||
|  |     std::map<int,double> f_fs_estimation_Hz_map; | ||||||
|  |     std::map<int,double> f_ppm_estimation_Hz_map; | ||||||
|  |  | ||||||
|  |     for (std::map<int,double>::iterator it = doppler_measurements_map.begin() ; it != doppler_measurements_map.end(); ++it) | ||||||
|  |       { | ||||||
|  |     	std::cout << "Doppler measured for (SV=" << it->first<<")="<<it->second<<" [Hz]"<<std::endl; | ||||||
|  |     	try{ | ||||||
|  |     		double doppler_estimated_hz; | ||||||
|  |     		doppler_estimated_hz=front_end_cal.estimate_doppler_from_eph(it->first,current_TOW,lat_deg,lon_deg,altitude_m); | ||||||
|  |     		std::cout << "Doppler estimated for (SV=" << it->first<<")="<<doppler_estimated_hz<<" [Hz]"<<std::endl; | ||||||
|  |     		// 7. Compute front-end IF and sampling frequency estimation | ||||||
|  |     		// Compare with the measurements and compute clock drift using FE model | ||||||
|  |     		double estimated_fs_Hz, estimated_f_if_Hz,f_osc_err_ppm; | ||||||
|  |     		front_end_cal.GPS_L1_front_end_model_E4000(doppler_estimated_hz,it->second,fs_in_, &estimated_fs_Hz, &estimated_f_if_Hz, &f_osc_err_ppm ); | ||||||
|  |  | ||||||
|  |     		f_if_estimation_Hz_map.insert(std::pair<int,double>(it->first,estimated_f_if_Hz)); | ||||||
|  |     		f_fs_estimation_Hz_map.insert(std::pair<int,double>(it->first,estimated_fs_Hz)); | ||||||
|  |     		f_ppm_estimation_Hz_map.insert(std::pair<int,double>(it->first,f_osc_err_ppm)); | ||||||
|  |  | ||||||
|  |     	}catch(int ex) | ||||||
|  |     	{ | ||||||
|  |     		std::cout<<"Eph not found for SV "<<it->first<<std::endl; | ||||||
|  |     	} | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     // FINAL FE estimations | ||||||
|  |     double mean_f_if_Hz=0; | ||||||
|  |     double mean_fs_Hz=0; | ||||||
|  |     double mean_osc_err_ppm=0; | ||||||
|  |     int n_elements=f_if_estimation_Hz_map.size(); | ||||||
|  |  | ||||||
|  |     for (std::map<int,double>::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 <<std::setiosflags(std::ios::fixed)<<std::setprecision(2)<<"FE parameters estimation for Elonics E4000 Front-End:"<<std::endl; | ||||||
|  |  | ||||||
|  | 	std::cout<<"Sampling frequency ="<<mean_fs_Hz<<" [Hz]"<<std::endl; | ||||||
|  | 	std::cout<<"IF bias present in baseband="<<mean_f_if_Hz<<" [Hz]"<<std::endl; | ||||||
|  | 	std::cout<<"Reference oscillator error ="<<mean_osc_err_ppm<<" [ppm]"<<std::endl; | ||||||
|  |  | ||||||
|  |     // 8. Generate GNSS-SDR config file. | ||||||
|  |  | ||||||
|  |     delete configuration; | ||||||
|  |     delete acquisition; | ||||||
|  |     delete gnss_synchro; | ||||||
|  |  | ||||||
|  |     google::ShutDownCommandLineFlags(); | ||||||
|  |     std::cout << "GNSS-SDR program ended." << std::endl; | ||||||
|  |  | ||||||
|  | //    if (global_gps_acq_assist_map.size()>0) | ||||||
|  | //    { | ||||||
|  | //    	std::map<int,Gps_Acq_Assist> 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 = "<<current_TOW<<std::endl; | ||||||
|  | //    }else{ | ||||||
|  | //    	std::cout<<"Unable to get acquisition assistance information. TOW is unknown!"<<std::endl; | ||||||
|  | //    } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Javier Arribas
					Javier Arribas