diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc index 742faff0e..f6262800d 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc @@ -229,7 +229,7 @@ int pcps_acquisition_cc::general_work(int noutput_items, std::stringstream filename; std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write filename.str(""); - filename << "../data/fft_galileo_e1_sat_" << d_gnss_synchro->PRN << "_doppler_"<< doppler << ".dat"; + filename << "../data/test_statistics_"<System<<"_"<Signal<<"_sat_" << d_gnss_synchro->PRN << "_doppler_"<< doppler << ".dat"; //std::cout << filename.str().c_str(); //std::cout << ".\n"; d_dump_file.open(filename.str().c_str(), std::ios::out diff --git a/src/tests/gnss_block/galileo_e1_pcps_ambiguous_acquisition_gsoc_test.cc b/src/tests/gnss_block/galileo_e1_pcps_ambiguous_acquisition_gsoc_test.cc new file mode 100644 index 000000000..d9c10c0b7 --- /dev/null +++ b/src/tests/gnss_block/galileo_e1_pcps_ambiguous_acquisition_gsoc_test.cc @@ -0,0 +1,253 @@ +/*! + * \file galileo_e1_pcps_ambiguous_acquisition_gsoc_test.cc + * \brief This class implements an acquisition test based on GSoC 2012 + * experiments. + * + * This test is a part of an experiment performed by Luis Esteve in the + * framework of the Google Summer of Code (GSoC) 2012, with the collaboration + * of Javier Arribas and Carles Fernández, related to the extension of GNSS-SDR + * to Galileo. The objective is perform a positive acquisition of in-orbit + * Galileo signals in the E1 band. + * + * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gnss_block_factory.h" +#include "gnss_block_interface.h" +#include "in_memory_configuration.h" +#include "gnss_sdr_valve.h" +#include "gnss_signal.h" +#include "gnss_synchro.h" + +#include "galileo_e1_pcps_ambiguous_acquisition.h" + +class GalileoE1PcpsAmbiguousAcquisitionGSoCTest: public ::testing::Test { +protected: + GalileoE1PcpsAmbiguousAcquisitionGSoCTest() { + queue = gr_make_msg_queue(0); + top_block = gr_make_top_block("Acquisition test"); + factory = new GNSSBlockFactory(); + config = new InMemoryConfiguration(); + item_size = sizeof(gr_complex); + stop = false; + message = 0; + } + + ~GalileoE1PcpsAmbiguousAcquisitionGSoCTest() { + delete factory; + delete config; + } + + void init(); + void start_queue(); + void wait_message(); + void stop_queue(); + + gr_msg_queue_sptr queue; + gr_top_block_sptr top_block; + GNSSBlockFactory* factory; + InMemoryConfiguration* config; + Gnss_Synchro gnss_synchro; + size_t item_size; + concurrent_queue channel_internal_queue; + bool stop; + int message; + boost::thread ch_thread; +}; + +void GalileoE1PcpsAmbiguousAcquisitionGSoCTest::init(){ + + gnss_synchro.Channel_ID=0; + gnss_synchro.System = 'E'; + std::string signal = "1C"; + signal.copy(gnss_synchro.Signal,2,0); + gnss_synchro.PRN=11; + + config->set_property("GNSS-SDR.internal_fs_hz", "4000000"); + + config->set_property("Acquisition.item_type", "gr_complex"); + config->set_property("Acquisition.if", "0"); + config->set_property("Acquisition.sampled_ms", "4"); + config->set_property("Acquisition.dump", "false"); + config->set_property("Acquisition.implementation", "Galileo_E1_PCPS_Ambiguous_Acquisition"); + config->set_property("Acquisition.threshold", "50"); + config->set_property("Acquisition.doppler_max", "10000"); + config->set_property("Acquisition.doppler_step", "125"); + config->set_property("Acquisition.repeat_satellite", "false"); + config->set_property("Acquisition1.cboc", "true"); +} + +void GalileoE1PcpsAmbiguousAcquisitionGSoCTest::start_queue() +{ + ch_thread = boost::thread(&GalileoE1PcpsAmbiguousAcquisitionGSoCTest::wait_message, this); +} + + +void GalileoE1PcpsAmbiguousAcquisitionGSoCTest::wait_message() +{ + while (!stop) + { + channel_internal_queue.wait_and_pop(message); + stop_queue(); + } +} + +void GalileoE1PcpsAmbiguousAcquisitionGSoCTest::stop_queue() +{ + stop = true; + } + + + +TEST_F(GalileoE1PcpsAmbiguousAcquisitionGSoCTest, Instantiate) +{ + + init(); + + GalileoE1PcpsAmbiguousAcquisition *acquisition = new GalileoE1PcpsAmbiguousAcquisition(config, "Acquisition", 1, 1, queue); + + delete acquisition; + +} + +TEST_F(GalileoE1PcpsAmbiguousAcquisitionGSoCTest, ConnectAndRun) +{ + int fs_in = 4000000; + int nsamples = 4*fs_in; + struct timeval tv; + long long int begin; + long long int end; + + init(); + GalileoE1PcpsAmbiguousAcquisition *acquisition = new GalileoE1PcpsAmbiguousAcquisition(config, "Acquisition", 1, 1, queue); + + ASSERT_NO_THROW( { + acquisition->connect(top_block); + + gr_sig_source_c_sptr source = gr_make_sig_source_c(fs_in,GR_SIN_WAVE, 1000, 1, gr_complex(0)); + gr_block_sptr valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue); + + top_block->connect(source, 0, valve, 0); + top_block->connect(valve, 0, acquisition->get_left_block(), 0); + }) << "Failure connecting the blocks of acquisition test."<< std::endl; + + EXPECT_NO_THROW( { + gettimeofday(&tv, NULL); + begin = tv.tv_sec *1000000 + tv.tv_usec; + top_block->run(); // Start threads and wait + gettimeofday(&tv, NULL); + end = tv.tv_sec *1000000 + tv.tv_usec; + }) << "Failure running he top_block."<< std::endl; + + delete acquisition; + std::cout << "Processed " << nsamples << " samples in " << (end-begin) << " microseconds" << std::endl; + +} + +TEST_F(GalileoE1PcpsAmbiguousAcquisitionGSoCTest, ValidationOfResults) +{ + struct timeval tv; + long long int begin; + long long int end; + + init(); + GalileoE1PcpsAmbiguousAcquisition *acquisition = new GalileoE1PcpsAmbiguousAcquisition(config, "Acquisition", 1, 1, queue); + + + ASSERT_NO_THROW( { + acquisition->set_channel(gnss_synchro.Channel_ID); + }) << "Failure setting channel."<< std::endl; + + ASSERT_NO_THROW( { + acquisition->set_gnss_synchro(&gnss_synchro); + }) << "Failure setting gnss_synchro."<< std::endl; + + ASSERT_NO_THROW( { + acquisition->set_channel_queue(&channel_internal_queue); + }) << "Failure setting channel_internal_queue."<< std::endl; + + ASSERT_NO_THROW( { + acquisition->set_threshold(config->property("Acquisition.threshold", 0.0)); + }) << "Failure setting threshold."<< std::endl; + + ASSERT_NO_THROW( { + acquisition->set_doppler_max(config->property("Acquisition.doppler_max", + 10000)); + }) << "Failure setting doppler_max."<< std::endl; + + ASSERT_NO_THROW( { + acquisition->set_doppler_step(config->property("Acquisition.doppler_step", + 500)); + }) << "Failure setting doppler_step."<< std::endl; + + ASSERT_NO_THROW( { + acquisition->connect(top_block); + }) << "Failure connecting acquisition to the top_block."<< std::endl; + + ASSERT_NO_THROW( { + std::string file = "../src/tests/signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms.dat"; + const char * file_name = file.c_str(); + gr_file_source_sptr file_source = gr_make_file_source(sizeof(gr_complex),file_name,false); + + top_block->connect(file_source, 0, acquisition->get_left_block(), 0); + }) << "Failure connecting the blocks of acquisition test."<< std::endl; + + start_queue(); + acquisition->init(); + acquisition->reset(); + + EXPECT_NO_THROW( { + gettimeofday(&tv, NULL); + begin = tv.tv_sec *1000000 + tv.tv_usec; + top_block->run(); // Start threads and wait + gettimeofday(&tv, NULL); + end = tv.tv_sec *1000000 + tv.tv_usec; + }) << "Failure running he top_block."<< std::endl; + + ch_thread.join(); + + unsigned long int nsamples = gnss_synchro.Acq_samplestamp_samples; + std::cout << "Acquired " << nsamples << " samples in " << (end-begin) << " microseconds" << std::endl; + + EXPECT_EQ(1, message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS."; + + delete acquisition; + +} diff --git a/src/tests/gnss_block/galileo_e1_pcps_ambiguous_acquisition_test.cc b/src/tests/gnss_block/galileo_e1_pcps_ambiguous_acquisition_test.cc index 4de92e6c3..bdad59f4a 100644 --- a/src/tests/gnss_block/galileo_e1_pcps_ambiguous_acquisition_test.cc +++ b/src/tests/gnss_block/galileo_e1_pcps_ambiguous_acquisition_test.cc @@ -85,12 +85,13 @@ protected: void GalileoE1PcpsAmbiguousAcquisitionTest::init(){ + gnss_synchro.Channel_ID=0; + gnss_synchro.System = 'E'; + std::string signal = "1C"; + signal.copy(gnss_synchro.Signal,2,0); + gnss_synchro.PRN=1; config->set_property("GNSS-SDR.internal_fs_hz", "4000000"); - config->set_property("Channel1.system", "Galileo"); - config->set_property("Channel1.signal", "1B"); - config->set_property("Channel1.satellite", "1"); - config->set_property("Acquisition.item_type", "gr_complex"); config->set_property("Acquisition.if", "0"); config->set_property("Acquisition.sampled_ms", "4"); @@ -180,22 +181,8 @@ TEST_F(GalileoE1PcpsAmbiguousAcquisitionTest, ValidationOfResults) init(); GalileoE1PcpsAmbiguousAcquisition *acquisition = new GalileoE1PcpsAmbiguousAcquisition(config, "Acquisition", 1, 1, queue); - std::string default_system = "Galileo"; - std::string default_signal = "1C"; - - std::string gnss_system = config->property("Channel1.system", default_system); - std::string gnss_signal = config->property("Channel1.signal", default_signal); - unsigned int sat = config->property("Channel1.satellite", 0); - - Gnss_Signal signal_value = Gnss_Signal(Gnss_Satellite(gnss_system, (unsigned int)sat), gnss_signal); - - signal_value.get_signal().copy(gnss_synchro.Signal,2,0); - gnss_synchro.PRN = sat; - gnss_synchro.System = signal_value.get_satellite().get_system_short().c_str()[0]; - gnss_synchro.Channel_ID=1; - ASSERT_NO_THROW( { - acquisition->set_channel(1); + acquisition->set_channel(gnss_synchro.Channel_ID); }) << "Failure setting channel."<< std::endl; ASSERT_NO_THROW( { diff --git a/src/tests/gnss_block/gps_l1_ca_pcps_acquisition_test.cc b/src/tests/gnss_block/gps_l1_ca_pcps_acquisition_test.cc index a299959ad..b23816bbf 100644 --- a/src/tests/gnss_block/gps_l1_ca_pcps_acquisition_test.cc +++ b/src/tests/gnss_block/gps_l1_ca_pcps_acquisition_test.cc @@ -84,7 +84,7 @@ protected: void GpsL1CaPcpsAcquisitionTest::init(){ - gnss_synchro.Channel_ID=1; + gnss_synchro.Channel_ID=0; gnss_synchro.System = 'G'; std::string signal = "1C"; signal.copy(gnss_synchro.Signal,2,0); diff --git a/src/tests/signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms.dat b/src/tests/signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms.dat new file mode 100644 index 000000000..5bc7a6f12 Binary files /dev/null and b/src/tests/signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms.dat differ diff --git a/src/tests/signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms_analysis.txt b/src/tests/signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms_analysis.txt new file mode 100644 index 000000000..680e72aba --- /dev/null +++ b/src/tests/signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms_analysis.txt @@ -0,0 +1,50 @@ +Signal capturing: + +Hardware: USRP1 + DBSRX daughterboard (Rev 4.5) + Antenna Novatel GPS-600. The USRP1 uses its internal 64 MHz onboard reference for deriving the sampling clock. + +Date: July 26th, 2012 +Time: 13:31:49 (UTC) +Location: Roof of the Centre Tecnològic de Telecomunicacions de Catalunya (CTTC), (40.396764 N, 3.713379 E), located at the Parc Mediterrani de la Tecnologia, Av. Carl Friedrich Gauss, 7, 08860 Castelldefels, Barcelona, Spain. + +Signal capture utility: we used the Universal Hardware Driver (UHD). +UHD driver capture to file example located in uhd/host/build/examples/$.rx_samples_to_file + +File sink: +In order to avoid buffer overflows the target destination for the capture file was a 4 GB RAM unit (in a system equipped with 8 GB of RAM). The linux command used to setup the RAM drive was: +$ mkdir /tmp/ram +$ mount -t tmpfs -o size=4G tmpfs /tmp/ram + +The command for capturing data was: + +$ ./rx_samples_to_file --file /tmp/ram/usrpcap1.dat --type short --freq 1575420000 --gain 50 --rate 8000000 --nsamps 800000000 + +This captures samples in interleaved (I&Q) short format (signed 16-bits, or 2 bytes), which is still not implemented in GNSS-SDR. Thus, the file was converted to gr_complex using a simple script in GNU Radio Companion. + +===== MATLAB Results using plot_acq_grid_gsoc.m =========================================================================================== + +Settings: + +sampling_freq_Hz = 4000000 +Doppler_max_Hz = 9875 +Doppler_min_Hz = -10000 +Doppler_step_Hz = 125 + +Results: + +PRN 11 + +POSITIVE ACQUISITION +maximum_correlation_peak = 23.0285 +delay_error_sps = 13873 +Doppler_error_Hz = -9500 +noise_floor = 1.8919 +Gain_dbs = 10.8538 + +PRN 12 + +POSITIVE ACQUISITION +maximum_correlation_peak = 16.5534 +delay_error_sps = 10583 +Doppler_error_Hz = -7250 +noise_floor = 1.9020 +Gain_dbs = 9.3968 diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index ed94a5618..96f61e618 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -63,6 +63,8 @@ #include "gnss_block/fir_filter_test.cc" #include "gnss_block/gps_l1_ca_pcps_acquisition_test.cc" #include "gnss_block/galileo_e1_pcps_ambiguous_acquisition_test.cc" +#include "gnss_block/galileo_e1_pcps_ambiguous_acquisition_gsoc_test.cc" +#include "gnss_block/gps_l1_ca_dll_pll_tracking_test.cc" #include "gnss_block/file_output_filter_test.cc" #include "gnss_block/gnss_block_factory_test.cc" //#include "gnss_block/direct_resampler_conditioner_test.cc" diff --git a/src/utils/matlab/plot_acq_grid_gsoc.m b/src/utils/matlab/plot_acq_grid_gsoc.m new file mode 100644 index 000000000..c38d5ea18 --- /dev/null +++ b/src/utils/matlab/plot_acq_grid_gsoc.m @@ -0,0 +1,96 @@ +% /*! +% * \file plot_acq_grid_gsoc.m +% * \brief Read GNSS-SDR Acquisition dump binary file using the provided +% function and plot acquisition grid of acquisition statistic of PRN sat +% +% This function analyzes a experiment performed by Luis Esteve in the framework +% of the Google Summer of Code (GSoC) 2012, with the collaboration of Javier Arribas +% and Carles Fernández, related to the extension of GNSS-SDR to Galileo. +% +% * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com +% * ------------------------------------------------------------------------- +% * +% * Copyright (C) 2010-2011 (see AUTHORS file for a list of contributors) +% * +% * GNSS-SDR is a software defined Global Navigation +% * Satellite Systems receiver +% * +% * This file is part of GNSS-SDR. +% * +% * GNSS-SDR is free software: you can redistribute it and/or modify +% * it under the terms of the GNU General Public License as published by +% * the Free Software Foundation, either version 3 of the License, or +% * at your option) any later version. +% * +% * GNSS-SDR is distributed in the hope that it will be useful, +% * but WITHOUT ANY WARRANTY; without even the implied warranty of +% * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% * GNU General Public License for more details. +% * +% * You should have received a copy of the GNU General Public License +% * along with GNSS-SDR. If not, see . +% * +% * ------------------------------------------------------------------------- +% */ + +function plot_acq_grid_gsoc(sat) + +file=['test_statistics_E_1C_sat_' num2str(sat) '_doppler_0.dat']; + +sampling_freq_Hz=4E6 +Doppler_max_Hz = 9875 +Doppler_min_Hz = -10000 +Doppler_step_Hz = 125 + + +% read files + +x=read_complex_binary (file); + +l_y=length(x); + +Doppler_axes=Doppler_min_Hz:Doppler_step_Hz:Doppler_max_Hz; + +l_x=length(Doppler_axes); + +acq_grid = zeros(l_x,l_y); + +index=0; + +for k=Doppler_min_Hz:Doppler_step_Hz:Doppler_max_Hz + index=index+1; + filename=['test_statistics_E_1C_sat_' num2str(sat) '_doppler_' num2str(k) '.dat']; + acq_grid(index,:)=abs(read_complex_binary (filename)); + end + +maximum_correlation_peak = max(max(acq_grid)) + +[fila,col]=find(acq_grid==max(max(acq_grid))); + +delay_error_sps = col -1 + +Doppler_error_Hz = Doppler_axes(fila) + +noise_grid=acq_grid; +delay_span=floor(3*sampling_freq_Hz/(1.023e6)); +Doppler_span=floor(500/Doppler_step_Hz); +noise_grid(fila-Doppler_span:fila+Doppler_span,col-delay_span:col+delay_span)=0; + +n=numel(noise_grid)-(2*delay_span+1)*(2*Doppler_span+1); + +noise_floor= sum(sum(noise_grid))/n + +Gain_dbs = 10*log10(maximum_correlation_peak/noise_floor) + + +%% Plot 3D FULL RESOLUTION + + +[X,Y] = meshgrid(Doppler_axes,1:1:l_y); +figure; +surf(X,Y,acq_grid'); + +xlabel('Doppler(Hz)');ylabel('Code Delay(samples)');title(['GLRT statistic of Galileo Parallel Code Phase Search Acquisition. Local replica: E1C cboc PRN ' num2str(sat)]); + + +end \ No newline at end of file