From 77851e55891cb65eebb1283dfe79d7cfbd6033fd Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Tue, 26 Mar 2019 22:34:08 +0100 Subject: [PATCH] BeiDou B3I bug fixes (credits to dmiralles2019) --- conf/gnss-sdr_BDS_B1I_byte.conf | 6 +- src/algorithms/PVT/libs/rtklib_solver.cc | 12 +- .../adapters/beidou_b1i_pcps_acquisition.cc | 3 +- .../libs/rtklib/rtklib_conversions.cc | 18 +- .../adapters/beidou_b3i_telemetry_decoder.h | 8 +- .../beidou_b3i_telemetry_decoder_gs.cc | 5 + .../beidou_b3i_telemetry_decoder_gs.h | 5 +- .../beidou_b1i_pcps_acquisition_test.cc | 76 ++-- .../beidou_b3i_pcps_acquisition_test.cc | 361 ++++++++++++++++++ src/utils/matlab/dll_pll_veml_plot_sample.m | 2 +- src/utils/matlab/plot_acq_grid.m | 65 ++-- 11 files changed, 482 insertions(+), 79 deletions(-) create mode 100644 src/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b3i_pcps_acquisition_test.cc diff --git a/conf/gnss-sdr_BDS_B1I_byte.conf b/conf/gnss-sdr_BDS_B1I_byte.conf index ce522bca0..15e86537d 100644 --- a/conf/gnss-sdr_BDS_B1I_byte.conf +++ b/conf/gnss-sdr_BDS_B1I_byte.conf @@ -47,6 +47,8 @@ InputFilter.filter_type=bandpass InputFilter.grid_density=16 InputFilter.sampling_frequency=25000000 InputFilter.IF=6250000 +InputFilter.dump = false +InputFilter.dump_filename=/home/dmiralles/Documents/gnss-sdr/src/tests/signal_samples/BdsB1IStr01_fs25e6_if0_4ms.dat Resampler.implementation=Pass_Through Resampler.sample_freq_in=25000000 Resampler.sample_freq_out=25000000 @@ -77,7 +79,7 @@ Acquisition_B1.threshold=0.0038 ;Acquisition_B1.pfa=0.0000001; Acquisition_B1.doppler_max=10000 Acquisition_B1.doppler_step=100 -Acquisition_B1.dump=false +Acquisition_B1.dump=true Acquisition_B1.dump_filename=./bds_acq Acquisition_B1.blocking=false; Acquisition_B1.use_CFAR_algorithm=true; @@ -89,7 +91,7 @@ Tracking_B1.implementation=BEIDOU_B1I_DLL_PLL_Tracking Tracking_B1.item_type=gr_complex Tracking_B1.pll_bw_hz=25.0; Tracking_B1.dll_bw_hz=2.50; -Tracking_B1.dump=false; +Tracking_B1.dump=true; Tracking_B1.dump_filename=./epl_tracking_ch_ diff --git a/src/algorithms/PVT/libs/rtklib_solver.cc b/src/algorithms/PVT/libs/rtklib_solver.cc index 8e916cb5c..eb7c9c6bd 100644 --- a/src/algorithms/PVT/libs/rtklib_solver.cc +++ b/src/algorithms/PVT/libs/rtklib_solver.cc @@ -66,7 +66,6 @@ #include - Rtklib_Solver::Rtklib_Solver(int nchannels, std::string dump_filename, bool flag_dump_to_file, bool flag_dump_to_mat, const rtk_t &rtk) { // init empty ephemeris for all the available GNSS channels @@ -908,11 +907,12 @@ bool Rtklib_Solver::get_PVT(const std::map &gnss_observables_ // Keep update on sat number sat++; - if(sat > NSYSGPS + NSYSGLO + NSYSGAL + NSYSQZS and sat < NSYSGPS + NSYSGLO + NSYSGAL + NSYSQZS + NSYSBDS) { - i[0] = SPEED_OF_LIGHT / FREQ1_BDS; // B1I - i[1] = SPEED_OF_LIGHT / FREQ3_BDS; // B3I - i[2] = SPEED_OF_LIGHT / FREQ5; // L5/E5 - } + if (sat > NSYSGPS + NSYSGLO + NSYSGAL + NSYSQZS and sat < NSYSGPS + NSYSGLO + NSYSGAL + NSYSQZS + NSYSBDS) + { + i[0] = SPEED_OF_LIGHT / FREQ1_BDS; // B1I + i[1] = SPEED_OF_LIGHT / FREQ3_BDS; // B3I + i[2] = SPEED_OF_LIGHT / FREQ5; // L5/E5 + } } result = rtkpos(&rtk_, obs_data, valid_obs + glo_valid_obs, &nav_data); diff --git a/src/algorithms/acquisition/adapters/beidou_b1i_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/beidou_b1i_pcps_acquisition.cc index 168209193..b5423c471 100644 --- a/src/algorithms/acquisition/adapters/beidou_b1i_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/beidou_b1i_pcps_acquisition.cc @@ -26,7 +26,7 @@ * 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 . + * along with GNSS-SDR. If not, see . * * ------------------------------------------------------------------------- */ @@ -57,7 +57,6 @@ BeidouB1iPcpsAcquisition::BeidouB1iPcpsAcquisition( DLOG(INFO) << "role " << role; item_type_ = configuration_->property(role + ".item_type", default_item_type); - int64_t fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); acq_parameters.fs_in = fs_in_; diff --git a/src/algorithms/libs/rtklib/rtklib_conversions.cc b/src/algorithms/libs/rtklib/rtklib_conversions.cc index 43b770b5b..463a63598 100644 --- a/src/algorithms/libs/rtklib/rtklib_conversions.cc +++ b/src/algorithms/libs/rtklib/rtklib_conversions.cc @@ -47,8 +47,8 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro, int week, int band) { - // Get signal type info to adjust code type based on constellation - std::string sig_= gnss_synchro.Signal; + // Get signal type info to adjust code type based on constellation + std::string sig_ = gnss_synchro.Signal; rtklib_obs.D[band] = gnss_synchro.Carrier_Doppler_hz; rtklib_obs.P[band] = gnss_synchro.Pseudorange_m; @@ -92,12 +92,14 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro case 'C': rtklib_obs.sat = gnss_synchro.PRN + NSATGPS + NSATGLO + NSATGAL + NSATQZS; // Update signal code - if (sig_ == "B1"){ - rtklib_obs.code[band] = static_cast(CODE_L2I); - } - else if (sig_ == "B3"){ - rtklib_obs.code[band] = static_cast(CODE_L6I); - } + if (sig_ == "B1") + { + rtklib_obs.code[band] = static_cast(CODE_L2I); + } + else if (sig_ == "B3") + { + rtklib_obs.code[band] = static_cast(CODE_L6I); + } break; diff --git a/src/algorithms/telemetry_decoder/adapters/beidou_b3i_telemetry_decoder.h b/src/algorithms/telemetry_decoder/adapters/beidou_b3i_telemetry_decoder.h index 6df5a9994..f38f6c3b4 100644 --- a/src/algorithms/telemetry_decoder/adapters/beidou_b3i_telemetry_decoder.h +++ b/src/algorithms/telemetry_decoder/adapters/beidou_b3i_telemetry_decoder.h @@ -48,7 +48,7 @@ class BeidouB3iTelemetryDecoder : public TelemetryDecoderInterface { public: BeidouB3iTelemetryDecoder(ConfigurationInterface *configuration, - const std::string& role, unsigned int in_streams, + const std::string &role, unsigned int in_streams, unsigned int out_streams); virtual ~BeidouB3iTelemetryDecoder(); @@ -72,7 +72,11 @@ public: telemetry_decoder_->set_channel(channel); } - inline void reset() override { return; } + inline void reset() override + { + telemetry_decoder_->reset(); + return; + } inline size_t item_size() override { return 0; } diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b3i_telemetry_decoder_gs.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b3i_telemetry_decoder_gs.cc index 6e65de72a..9f1396b8b 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b3i_telemetry_decoder_gs.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b3i_telemetry_decoder_gs.cc @@ -56,6 +56,7 @@ beidou_b3i_make_telemetry_decoder_gs(const Gnss_Satellite &satellite, new beidou_b3i_telemetry_decoder_gs(satellite, dump)); } + beidou_b3i_telemetry_decoder_gs::beidou_b3i_telemetry_decoder_gs( const Gnss_Satellite &satellite, bool dump) : gr::block("beidou_b3i_telemetry_decoder_gs", @@ -64,6 +65,9 @@ beidou_b3i_telemetry_decoder_gs::beidou_b3i_telemetry_decoder_gs( { // Ephemeris data port out this->message_port_register_out(pmt::mp("telemetry")); + // Control messages to tracking block + this->message_port_register_out(pmt::mp("telemetry_to_trk")); + // initialize internal vars d_dump = dump; d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); @@ -396,6 +400,7 @@ void beidou_b3i_telemetry_decoder_gs::set_satellite( } } + void beidou_b3i_telemetry_decoder_gs::set_channel(int32_t channel) { d_channel = channel; diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b3i_telemetry_decoder_gs.h b/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b3i_telemetry_decoder_gs.h index 746e68895..54bac3adb 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b3i_telemetry_decoder_gs.h +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/beidou_b3i_telemetry_decoder_gs.h @@ -60,7 +60,10 @@ public: ~beidou_b3i_telemetry_decoder_gs(); //!< Class destructor void set_satellite(const Gnss_Satellite &satellite); //!< Set satellite PRN void set_channel(int channel); //!< Set receiver's channel - + inline void reset() + { + return; + } /*! * \brief This is where all signal processing takes place */ diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b1i_pcps_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b1i_pcps_acquisition_test.cc index 959d73fed..be0214766 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b1i_pcps_acquisition_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b1i_pcps_acquisition_test.cc @@ -3,7 +3,7 @@ * \brief This class implements an acquisition test for * BeidouB1iPcpsAcquisition class based on some input parameters. * \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com - * + * \author Damian Miralles, 2019. dmiralles2009(at)gmail.com * * ------------------------------------------------------------------------- * @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -52,12 +51,18 @@ #include #include #include +#include +#ifdef GR_GREATER_38 +#include +#else +#include +#endif // ######## GNURADIO BLOCK MESSAGE RECEVER ######### class BeidouB1iPcpsAcquisitionTest_msg_rx; -typedef boost::shared_ptr BeidouB1iPcpsAcquisitionTest_msg_rx_sptr; +using BeidouB1iPcpsAcquisitionTest_msg_rx_sptr = boost::shared_ptr; BeidouB1iPcpsAcquisitionTest_msg_rx_sptr BeidouB1iPcpsAcquisitionTest_msg_rx_make(); @@ -84,7 +89,7 @@ void BeidouB1iPcpsAcquisitionTest_msg_rx::msg_handler_events(pmt::pmt_t msg) { try { - long int message = pmt::to_long(msg); + int64_t message = pmt::to_long(std::move(msg)); rx_message = message; } catch (boost::bad_any_cast &e) @@ -103,9 +108,7 @@ BeidouB1iPcpsAcquisitionTest_msg_rx::BeidouB1iPcpsAcquisitionTest_msg_rx() : gr: } -BeidouB1iPcpsAcquisitionTest_msg_rx::~BeidouB1iPcpsAcquisitionTest_msg_rx() -{ -} +BeidouB1iPcpsAcquisitionTest_msg_rx::~BeidouB1iPcpsAcquisitionTest_msg_rx() = default; // ########################################################### @@ -123,9 +126,7 @@ protected: doppler_step = 100; } - ~BeidouB1iPcpsAcquisitionTest() - { - } + ~BeidouB1iPcpsAcquisitionTest() = default; void init(); void plot_grid(); @@ -133,7 +134,7 @@ protected: gr::top_block_sptr top_block; std::shared_ptr factory; std::shared_ptr config; - Gnss_Synchro gnss_synchro; + Gnss_Synchro gnss_synchro{}; size_t item_size; unsigned int doppler_max; unsigned int doppler_step; @@ -159,8 +160,9 @@ void BeidouB1iPcpsAcquisitionTest::init() { config->set_property("Acquisition_B1.dump", "false"); } - config->set_property("Acquisition_B1.dump_filename", "./tmp-acq-beidou1/acquisition"); - config->set_property("Acquisition_B1.threshold", "0.00001"); + config->set_property("Acquisition_B1.dump_filename", "./tmp-acq-bds-b1i/acquisition"); + config->set_property("Acquisition_B1.dump_channel", "1"); + config->set_property("Acquisition_B1.threshold", "0.0038"); config->set_property("Acquisition_B1.doppler_max", std::to_string(doppler_max)); config->set_property("Acquisition_B1.doppler_step", std::to_string(doppler_step)); config->set_property("Acquisition_B1.repeat_satellite", "false"); @@ -171,13 +173,16 @@ void BeidouB1iPcpsAcquisitionTest::init() void BeidouB1iPcpsAcquisitionTest::plot_grid() { //load the measured values - std::string basename = "./tmp-acq-beidou1/acquisition_C_B1"; - unsigned int sat = static_cast(gnss_synchro.PRN); + std::string basename = "./tmp-acq-bds-b1i/acquisition_C_B1"; + auto sat = static_cast(gnss_synchro.PRN); - unsigned int samples_per_code = static_cast(round(4000000 / (BEIDOU_B1I_CODE_RATE_HZ / BEIDOU_B1I_CODE_LENGTH_CHIPS))); // !! - acquisition_dump_reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code); + auto samples_per_code = static_cast(round(25000000 / (BEIDOU_B1I_CODE_RATE_HZ / BEIDOU_B1I_CODE_LENGTH_CHIPS))); // !! + Acquisition_Dump_Reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code, 1); - if (!acq_dump.read_binary_acq()) std::cout << "Error reading files" << std::endl; + if (!acq_dump.read_binary_acq()) + { + std::cout << "Error reading files" << std::endl; + } std::vector *doppler = &acq_dump.doppler; std::vector *samples = &acq_dump.samples; @@ -197,26 +202,33 @@ void BeidouB1iPcpsAcquisitionTest::plot_grid() { boost::filesystem::path p(gnuplot_executable); boost::filesystem::path dir = p.parent_path(); - std::string gnuplot_path = dir.native(); + const std::string &gnuplot_path = dir.native(); Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot g1("lines"); - g1.set_title("BeiDou signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN)); + if (FLAGS_show_plots) + { + g1.showonscreen(); // window output + } + else + { + g1.disablescreen(); + } + g1.set_title("BeiDou B1I signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN)); g1.set_xlabel("Doppler [Hz]"); g1.set_ylabel("Sample"); //g1.cmd("set view 60, 105, 1, 1"); g1.plot_grid3d(*doppler, *samples, *mag); - g1.savetops("BEIDOU_B1I_acq_grid"); - g1.savetopdf("BEIDOU_BI1_acq_grid"); - g1.showonscreen(); + g1.savetops("BeiDou_B1I_acq_grid"); + g1.savetopdf("BeiDou_B1I_acq_grid"); } catch (const GnuplotException &ge) { std::cout << ge.what() << std::endl; } } - std::string data_str = "./tmp-acq-beidou1"; + std::string data_str = "./tmp-acq-bds-b1i"; if (boost::filesystem::exists(data_str)) { boost::filesystem::remove_all(data_str); @@ -234,7 +246,7 @@ TEST_F(BeidouB1iPcpsAcquisitionTest, Instantiate) TEST_F(BeidouB1iPcpsAcquisitionTest, ConnectAndRun) { int fs_in = 25000000; - int nsamples = 4000; + int nsamples = 25000; std::chrono::time_point start, end; std::chrono::duration elapsed_seconds(0); gr::msg_queue::sptr queue = gr::msg_queue::make(0); @@ -270,14 +282,14 @@ TEST_F(BeidouB1iPcpsAcquisitionTest, ValidationOfResults) std::chrono::duration elapsed_seconds(0.0); top_block = gr::make_top_block("Acquisition test"); - double expected_delay_samples = 524; - double expected_doppler_hz = 1680; + double expected_delay_samples = 22216; + double expected_doppler_hz = 125; init(); if (FLAGS_plot_acq_grid == true) { - std::string data_str = "./tmp-acq-beidou1"; + std::string data_str = "./tmp-acq-bds-b1i"; if (boost::filesystem::exists(data_str)) { boost::filesystem::remove_all(data_str); @@ -297,7 +309,7 @@ TEST_F(BeidouB1iPcpsAcquisitionTest, ValidationOfResults) }) << "Failure setting gnss_synchro."; ASSERT_NO_THROW({ - acquisition->set_threshold(0.001); + acquisition->set_threshold(0.0038); }) << "Failure setting threshold."; ASSERT_NO_THROW({ @@ -314,7 +326,7 @@ TEST_F(BeidouB1iPcpsAcquisitionTest, ValidationOfResults) ASSERT_NO_THROW({ std::string path = std::string(TEST_PATH); - std::string file = path + "signal_samples/BEIDOU_B1I_ID_1_Fs_4Msps_2ms.dat"; + std::string file = path + "signal_samples/BdsB1IStr01_fs25e6_if0_4ms.dat"; const char *file_name = file.c_str(); gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); top_block->connect(file_source, 0, acquisition->get_left_block(), 0); @@ -332,12 +344,12 @@ TEST_F(BeidouB1iPcpsAcquisitionTest, ValidationOfResults) elapsed_seconds = end - start; }) << "Failure running the top_block."; - unsigned long int nsamples = gnss_synchro.Acq_samplestamp_samples; + uint64_t nsamples = gnss_synchro.Acq_samplestamp_samples; std::cout << "Acquired " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; ASSERT_EQ(1, msg_rx->rx_message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS."; double delay_error_samples = std::abs(expected_delay_samples - gnss_synchro.Acq_delay_samples); - float delay_error_chips = static_cast(delay_error_samples * 1023 / 4000); + auto delay_error_chips = static_cast(delay_error_samples * BEIDOU_B1I_CODE_LENGTH_CHIPS / 25000); double doppler_error_hz = std::abs(expected_doppler_hz - gnss_synchro.Acq_doppler_hz); EXPECT_LE(doppler_error_hz, 666) << "Doppler error exceeds the expected value: 666 Hz = 2/(3*integration period)"; diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b3i_pcps_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b3i_pcps_acquisition_test.cc new file mode 100644 index 000000000..d80ca6e66 --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/beidou_b3i_pcps_acquisition_test.cc @@ -0,0 +1,361 @@ +/*! + * \file beidou_b3i_pcps_acquisition_test.cc + * \brief This class implements an acquisition test for + * BeidouB3iPcpsAcquisition class based on some input parameters. + * \author Damian Miralles, 2019. dmiralles2009(at)gmail.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (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 "Beidou_B3I.h" +#include "acquisition_dump_reader.h" +#include "gnss_block_factory.h" +#include "gnss_block_interface.h" +#include "gnss_sdr_valve.h" +#include "gnss_synchro.h" +#include "gnuplot_i.h" +#include "beidou_b3i_pcps_acquisition.h" +#include "in_memory_configuration.h" +#include "test_flags.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef GR_GREATER_38 +#include +#else +#include +#endif + + +// ######## GNURADIO BLOCK MESSAGE RECEVER ######### +class BeidouB3iPcpsAcquisitionTest_msg_rx; + +using BeidouB3iPcpsAcquisitionTest_msg_rx_sptr = boost::shared_ptr; + +BeidouB3iPcpsAcquisitionTest_msg_rx_sptr BeidouB3iPcpsAcquisitionTest_msg_rx_make(); + +class BeidouB3iPcpsAcquisitionTest_msg_rx : public gr::block +{ +private: + friend BeidouB3iPcpsAcquisitionTest_msg_rx_sptr BeidouB3iPcpsAcquisitionTest_msg_rx_make(); + void msg_handler_events(pmt::pmt_t msg); + BeidouB3iPcpsAcquisitionTest_msg_rx(); + +public: + int rx_message; + ~BeidouB3iPcpsAcquisitionTest_msg_rx(); //!< Default destructor +}; + + +BeidouB3iPcpsAcquisitionTest_msg_rx_sptr BeidouB3iPcpsAcquisitionTest_msg_rx_make() +{ + return BeidouB3iPcpsAcquisitionTest_msg_rx_sptr(new BeidouB3iPcpsAcquisitionTest_msg_rx()); +} + + +void BeidouB3iPcpsAcquisitionTest_msg_rx::msg_handler_events(pmt::pmt_t msg) +{ + try + { + int64_t message = pmt::to_long(std::move(msg)); + rx_message = message; + } + catch (boost::bad_any_cast &e) + { + LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; + rx_message = 0; + } +} + + +BeidouB3iPcpsAcquisitionTest_msg_rx::BeidouB3iPcpsAcquisitionTest_msg_rx() : gr::block("BeidouB3iPcpsAcquisitionTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) +{ + this->message_port_register_in(pmt::mp("events")); + this->set_msg_handler(pmt::mp("events"), boost::bind(&BeidouB3iPcpsAcquisitionTest_msg_rx::msg_handler_events, this, _1)); + rx_message = 0; +} + + +BeidouB3iPcpsAcquisitionTest_msg_rx::~BeidouB3iPcpsAcquisitionTest_msg_rx() = default; + + +// ########################################################### + +class BeidouB3iPcpsAcquisitionTest : public ::testing::Test +{ +protected: + BeidouB3iPcpsAcquisitionTest() + { + factory = std::make_shared(); + config = std::make_shared(); + item_size = sizeof(gr_complex); + gnss_synchro = Gnss_Synchro(); + doppler_max = 5000; + doppler_step = 100; + } + + ~BeidouB3iPcpsAcquisitionTest() = default; + + void init(); + void plot_grid(); + + gr::top_block_sptr top_block; + std::shared_ptr factory; + std::shared_ptr config; + Gnss_Synchro gnss_synchro{}; + size_t item_size; + unsigned int doppler_max; + unsigned int doppler_step; +}; + + +void BeidouB3iPcpsAcquisitionTest::init() +{ + gnss_synchro.Channel_ID = 0; + gnss_synchro.System = 'C'; + std::string signal = "B3"; + signal.copy(gnss_synchro.Signal, 2, 0); + gnss_synchro.PRN = 1; + config->set_property("GNSS-SDR.internal_fs_sps", "50000000"); + config->set_property("Acquisition_B3.implementation", "BEIDOU_B3I_PCPS_Acquisition"); + config->set_property("Acquisition_B3.item_type", "gr_complex"); + config->set_property("Acquisition_B3.coherent_integration_time_ms", "1"); + if (FLAGS_plot_acq_grid == true) + { + config->set_property("Acquisition_B3.dump", "true"); + } + else + { + config->set_property("Acquisition_B3.dump", "false"); + } + config->set_property("Acquisition_B3.dump_filename", "./tmp-acq-bds-b3i/acquisition"); + config->set_property("Acquisition_B3.dump_channel", "1"); + config->set_property("Acquisition_B3.threshold", "0.00001"); + config->set_property("Acquisition_B3.doppler_max", std::to_string(doppler_max)); + config->set_property("Acquisition_B3.doppler_step", std::to_string(doppler_step)); + config->set_property("Acquisition_B3.repeat_satellite", "false"); +} + + +void BeidouB3iPcpsAcquisitionTest::plot_grid() +{ + //load the measured values + std::string basename = "./tmp-acq-bds-b3i/acquisition_C_B3"; + auto sat = static_cast(gnss_synchro.PRN); + + auto samples_per_code = static_cast(round(50000000 / (BEIDOU_B3I_CODE_RATE_HZ / BEIDOU_B3I_CODE_LENGTH_CHIPS))); // !! + Acquisition_Dump_Reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code, 1); + + if (!acq_dump.read_binary_acq()) + { + std::cout << "Error reading files" << std::endl; + } + + std::vector *doppler = &acq_dump.doppler; + std::vector *samples = &acq_dump.samples; + std::vector > *mag = &acq_dump.mag; + + const std::string gnuplot_executable(FLAGS_gnuplot_executable); + if (gnuplot_executable.empty()) + { + std::cout << "WARNING: Although the flag plot_acq_grid has been set to TRUE," << std::endl; + std::cout << "gnuplot has not been found in your system." << std::endl; + std::cout << "Test results will not be plotted." << std::endl; + } + else + { + std::cout << "Plotting the acquisition grid. This can take a while..." << std::endl; + try + { + boost::filesystem::path p(gnuplot_executable); + boost::filesystem::path dir = p.parent_path(); + const std::string &gnuplot_path = dir.native(); + Gnuplot::set_GNUPlotPath(gnuplot_path); + + Gnuplot g1("lines"); + if (FLAGS_show_plots) + { + g1.showonscreen(); // window output + } + else + { + g1.disablescreen(); + } + g1.set_title("BeiDou B3I signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN)); + g1.set_xlabel("Doppler [Hz]"); + g1.set_ylabel("Sample"); + //g1.cmd("set view 60, 105, 1, 1"); + g1.plot_grid3d(*doppler, *samples, *mag); + + g1.savetops("BDS_B3I_acq_grid"); + g1.savetopdf("BDS_B3I_acq_grid"); + } + catch (const GnuplotException &ge) + { + std::cout << ge.what() << std::endl; + } + } + std::string data_str = "./tmp-acq-bds-b3i"; + if (boost::filesystem::exists(data_str)) + { + boost::filesystem::remove_all(data_str); + } +} + + +TEST_F(BeidouB3iPcpsAcquisitionTest, Instantiate) +{ + init(); + boost::shared_ptr acquisition = boost::make_shared(config.get(), "Acquisition_B3", 1, 0); +} + + +TEST_F(BeidouB3iPcpsAcquisitionTest, ConnectAndRun) +{ + int fs_in = 50000000; + int nsamples = 50000; + std::chrono::time_point start, end; + std::chrono::duration elapsed_seconds(0); + gr::msg_queue::sptr queue = gr::msg_queue::make(0); + + top_block = gr::make_top_block("Acquisition test"); + init(); + boost::shared_ptr acquisition = boost::make_shared(config.get(), "Acquisition_B3", 1, 0); + boost::shared_ptr msg_rx = BeidouB3iPcpsAcquisitionTest_msg_rx_make(); + + ASSERT_NO_THROW({ + acquisition->connect(top_block); + boost::shared_ptr source = gr::analog::sig_source_c::make(fs_in, gr::analog::GR_SIN_WAVE, 1000, 1, gr_complex(0)); + boost::shared_ptr 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); + top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); + }) << "Failure connecting the blocks of acquisition test."; + + EXPECT_NO_THROW({ + start = std::chrono::system_clock::now(); + top_block->run(); // Start threads and wait + end = std::chrono::system_clock::now(); + elapsed_seconds = end - start; + }) << "Failure running the top_block."; + + std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; +} + + +TEST_F(BeidouB3iPcpsAcquisitionTest, ValidationOfResults) +{ + std::chrono::time_point start, end; + std::chrono::duration elapsed_seconds(0.0); + top_block = gr::make_top_block("Acquisition test"); + + double expected_delay_samples = 3380; + double expected_doppler_hz = 700; + + init(); + + if (FLAGS_plot_acq_grid == true) + { + std::string data_str = "./tmp-acq-bds-b3i"; + if (boost::filesystem::exists(data_str)) + { + boost::filesystem::remove_all(data_str); + } + boost::filesystem::create_directory(data_str); + } + + std::shared_ptr acquisition = std::make_shared(config.get(), "Acquisition_B3", 1, 0); + boost::shared_ptr msg_rx = BeidouB3iPcpsAcquisitionTest_msg_rx_make(); + + ASSERT_NO_THROW({ + acquisition->set_channel(1); + }) << "Failure setting channel."; + + ASSERT_NO_THROW({ + acquisition->set_gnss_synchro(&gnss_synchro); + }) << "Failure setting gnss_synchro."; + + ASSERT_NO_THROW({ + acquisition->set_threshold(0.0002); + }) << "Failure setting threshold."; + + ASSERT_NO_THROW({ + acquisition->set_doppler_max(doppler_max); + }) << "Failure setting doppler_max."; + + ASSERT_NO_THROW({ + acquisition->set_doppler_step(doppler_step); + }) << "Failure setting doppler_step."; + + ASSERT_NO_THROW({ + acquisition->connect(top_block); + }) << "Failure connecting acquisition to the top_block."; + + ASSERT_NO_THROW({ + std::string path = std::string(TEST_PATH); + std::string file = path + "signal_samples/BdsB3IStr01_fs50e6_if0_4ms.dat"; + const char *file_name = file.c_str(); + gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); + top_block->connect(file_source, 0, acquisition->get_left_block(), 0); + top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); + }) << "Failure connecting the blocks of acquisition test."; + + acquisition->set_local_code(); + acquisition->set_state(1); // Ensure that acquisition starts at the first sample + acquisition->init(); + + EXPECT_NO_THROW({ + start = std::chrono::system_clock::now(); + top_block->run(); // Start threads and wait + end = std::chrono::system_clock::now(); + elapsed_seconds = end - start; + }) << "Failure running the top_block."; + + uint64_t nsamples = gnss_synchro.Acq_samplestamp_samples; + std::cout << "Acquired " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; + ASSERT_EQ(1, msg_rx->rx_message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS."; + + double delay_error_samples = std::abs(expected_delay_samples - gnss_synchro.Acq_delay_samples); + auto delay_error_chips = static_cast(delay_error_samples * BEIDOU_B3I_CODE_LENGTH_CHIPS / 50000); + double doppler_error_hz = std::abs(expected_doppler_hz - gnss_synchro.Acq_doppler_hz); + + EXPECT_LE(doppler_error_hz, 666) << "Doppler error exceeds the expected value: 666 Hz = 2/(3*integration period)"; + EXPECT_LT(delay_error_chips, 0.5) << "Delay error exceeds the expected value: 0.5 chips"; + + if (FLAGS_plot_acq_grid == true) + { + plot_grid(); + } +} diff --git a/src/utils/matlab/dll_pll_veml_plot_sample.m b/src/utils/matlab/dll_pll_veml_plot_sample.m index ce4c3d087..2cd61d101 100644 --- a/src/utils/matlab/dll_pll_veml_plot_sample.m +++ b/src/utils/matlab/dll_pll_veml_plot_sample.m @@ -36,7 +36,7 @@ end samplingFreq = 25000000; %[Hz] coherent_integration_time_ms = 1; %[ms] -channels = 10; % Number of channels +channels = 1; % Number of channels first_channel = 0; % Number of the first channel path = '/home/dmiralles/Documents/gnss-sdr/'; %% CHANGE THIS PATH diff --git a/src/utils/matlab/plot_acq_grid.m b/src/utils/matlab/plot_acq_grid.m index 53412376c..e903b0245 100644 --- a/src/utils/matlab/plot_acq_grid.m +++ b/src/utils/matlab/plot_acq_grid.m @@ -26,15 +26,12 @@ % ------------------------------------------------------------------------- % -%%%%%%%%% ?????? CONFIGURE !!! %%%%%%%%%%%%% - -path = '/home/dmiralles/Documents/Research/Publications/INSIDE_GNSS/bds_leg_pvt/Data/'; %% CHANGE THIS PATH -file = 'bds_b3i_acq'; - -sat = 27; - +%% Configuration +path = '/home/dmiralles/Documents/gnss-sdr/'; +file = 'bds_acq'; +sat = 6; channel = 0; -execution = 6; +execution = 4; % Signal: % 1 GPS L1 % 2 GPS L2M @@ -42,17 +39,21 @@ execution = 6; % 4 Gal. E1B % 5 Gal. E5 % 6 Glo. 1G -% 7 BDS B1 +% 7 Glo. 2G +% 8 BDS. B1 +% 9 BDS. B3 +% 10 BDS. B2a signal_type = 8; -%%% True for light acq_grid representation +%%% True for light grid representation lite_view = true; %%% If lite_view, it sets the number of samples per chip in the graphical representation n_samples_per_chip = 3; +d_samples_per_code = 25000; -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Load data switch(signal_type) case 1 @@ -80,45 +81,59 @@ switch(signal_type) system = 'R'; signal = '1G'; case 7 - n_chips = 2046; + n_chips = 511; + system = 'R'; + signal = '2G'; + case 8 + n_chips = 2048; system = 'C'; signal = 'B1'; - case 8 + case 9 n_chips = 10230; system = 'C'; - signal = 'B3'; + signal = 'B3'; + case 10 + n_chips = 10230; + system = 'C'; + signal = '5C'; end filename = [path file '_' system '_' signal '_ch_' num2str(channel) '_' num2str(execution) '_sat_' num2str(sat) '.mat']; load(filename); -[n_fft n_dop_bins] = size(acq_grid); -[d_max f_max] = find(acq_grid == max(max(acq_grid))); -freq = (0 : n_dop_bins - 1) * doppler_step - doppler_max; +[n_fft, n_dop_bins] = size(acq_grid); +[d_max, f_max] = find(acq_grid == max(max(acq_grid))); +freq = (0 : n_dop_bins - 1) * double(doppler_step) - double(doppler_max); delay = (0 : n_fft - 1) / n_fft * n_chips; + + +%% Plot data +%--- Acquisition grid (3D) figure(1) if(lite_view == false) surf(freq, delay, acq_grid, 'FaceColor', 'interp', 'LineStyle', 'none') ylim([min(delay) max(delay)]) else delay_interp = (0 : n_samples_per_chip * n_chips - 1) / n_samples_per_chip; - acq_grid_interp = spline(delay, acq_grid', delay_interp)'; - surf(freq, delay_interp, acq_grid_interp, 'FaceColor', 'interp', 'LineStyle', 'none') + grid_interp = spline(delay, acq_grid', delay_interp)'; + surf(freq, delay_interp, grid_interp, 'FaceColor', 'interp', 'LineStyle', 'none') ylim([min(delay_interp) max(delay_interp)]) end -xlabel('Doppler shift / Hz') +xlabel('Doppler shift (Hz)') xlim([min(freq) max(freq)]) -ylabel('Code delay / chips') -zlabel('Test statistics') +ylabel('Code delay (chips)') +zlabel('Test Statistics') + +%--- Acquisition grid (2D) figure(2) subplot(2,1,1) plot(freq, acq_grid(d_max, :)) xlim([min(freq) max(freq)]) -xlabel('Doppler shift / Hz') +xlabel('Doppler shift (Hz)') ylabel('Test statistics') title(['Fixed code delay to ' num2str((d_max - 1) / n_fft * n_chips) ' chips']) subplot(2,1,2) normalization = (d_samples_per_code^4) * input_power; -plot(delay, acq_acq_grid(:, f_max)./normalization) +plot(delay, acq_grid(:, f_max)./normalization) xlim([min(delay) max(delay)]) -xlabel('Code delay / chips') +xlabel('Code delay (chips)') ylabel('Test statistics') title(['Doppler wipe-off = ' num2str((f_max - 1) * doppler_step - doppler_max) ' Hz'])