1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-14 20:20:35 +00:00

Add acquisition grid plot

This commit is contained in:
Carles Fernandez 2017-10-28 18:15:59 +02:00
parent 498dc22940
commit 41b5365244
5 changed files with 343 additions and 24 deletions

View File

@ -510,6 +510,10 @@ public:
Gnuplot& plot_xy_err(const X &x, const Y &y, const E &dy,
const std::string &title = "");
template<typename X, typename Y, typename E>
Gnuplot& plot_grid3d(const X &x, const Y &y, const E &mag,
const std::string &title = "");
/// plot x,y,z triples: x y z
/// from file
Gnuplot& plotfile_xyz(const std::string &filename,
@ -804,6 +808,63 @@ Gnuplot& Gnuplot::plot_xy_err(const X &x,
}
//------------------------------------------------------------------------------
//
// Plots a 3d grid
//
template<typename X, typename Y, typename E>
Gnuplot& Gnuplot::plot_grid3d(const X &x,
const Y &y,
const E &mag,
const std::string &title)
{
if (x.size() == 0 || y.size() == 0 )
{
throw GnuplotException("std::vectors too small");
return *this;
}
std::ofstream tmp;
std::string name = create_tmpfile(tmp);
if (name == "")
return *this;
//
// write the data to file
//
for (unsigned int i = 0; i < x.size(); i++)
{
for (unsigned int k = 0; k < y.size(); k++)
{
tmp << static_cast<float>(x.at(i)) << " " << static_cast<float>(y.at(k)) << " " << mag.at(i).at(k) << std::endl;
}
tmp.flush();
}
tmp.close();
std::ostringstream cmdstr;
cmdstr << "set ticslevel 0\n";
cmdstr << "set hidden3d\n";
cmdstr << "unset colorbox\n";
cmdstr << "set border 5\n";
cmdstr << "unset ztics\n";
cmdstr << " splot \"" << name << "\" u 1:2:3";
if (title == "")
cmdstr << " notitle with " << pstyle << " palette";
else
cmdstr << " title \"" << title << "\" with " << pstyle << " palette";
cmdstr << "\n";
//
// Do the actual plot
//
cmd(cmdstr.str());
return *this;
}
//------------------------------------------------------------------------------
//
// Plots a 3d graph from a list of doubles: x y z

View File

@ -34,6 +34,7 @@
#include <chrono>
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/make_shared.hpp>
#include <gnuradio/top_block.h>
#include <gnuradio/blocks/file_source.h>
@ -47,8 +48,14 @@
#include "in_memory_configuration.h"
#include "gnss_sdr_valve.h"
#include "gnss_synchro.h"
#include "gnuplot_i.h"
#include "test_flags.h"
#include "acquisition_dump_reader.h"
#include "gps_l1_ca_pcps_acquisition.h"
DEFINE_bool(plot_acq_grid, false, "Plots results of GpsL1CaPcpsAcquisitionTest with gnuplot");
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
class GpsL1CaPcpsAcquisitionTest_msg_rx;
@ -120,6 +127,7 @@ protected:
{}
void init();
void plot_grid();
gr::top_block_sptr top_block;
std::shared_ptr<GNSSBlockFactory> factory;
@ -136,24 +144,88 @@ void GpsL1CaPcpsAcquisitionTest::init()
std::string signal = "1C";
signal.copy(gnss_synchro.Signal, 2, 0);
gnss_synchro.PRN = 1;
config->set_property("Acquisition_1C.implementation", "GPS_L1_CA_PCPS_Acquisition");
config->set_property("GNSS-SDR.internal_fs_sps", "4000000");
config->set_property("Acquisition.item_type", "gr_complex");
config->set_property("Acquisition.if", "0");
config->set_property("Acquisition.coherent_integration_time_ms", "1");
config->set_property("Acquisition.dump", "false");
config->set_property("Acquisition.implementation", "GPS_L1_CA_PCPS_Acquisition");
config->set_property("Acquisition.threshold", "0.00001");
config->set_property("Acquisition.doppler_max", "5000");
config->set_property("Acquisition.doppler_step", "500");
config->set_property("Acquisition.repeat_satellite", "false");
//config->set_property("Acquisition.pfa", "0.0");
config->set_property("Acquisition_1C.item_type", "gr_complex");
config->set_property("Acquisition_1C.if", "0");
config->set_property("Acquisition_1C.coherent_integration_time_ms", "1");
if(FLAGS_plot_acq_grid == true)
{
config->set_property("Acquisition_1C.dump", "true");
}
else
{
config->set_property("Acquisition_1C.dump", "false");
}
config->set_property("Acquisition_1C.threshold", "0.00001");
config->set_property("Acquisition_1C.doppler_max", "5000");
config->set_property("Acquisition_1C.doppler_step", "500");
config->set_property("Acquisition_1C.repeat_satellite", "false");
//config->set_property("Acquisition_1C.pfa", "0.0");
}
void GpsL1CaPcpsAcquisitionTest::plot_grid()
{
//load the measured values
std::string basename = "./data/acquisition_G_1C";
unsigned int sat = static_cast<unsigned int>(gnss_synchro.PRN);
unsigned int doppler_max = 5000; // !!!
unsigned int doppler_step = 100; // !!
unsigned int samples_per_code = static_cast<unsigned int>(round(4000000 / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS))); // !!
acquisition_dump_reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code);
if(!acq_dump.read_binary_acq()) std::cout << "Error reading files" << std::endl;
std::vector<int> doppler = acq_dump.doppler;
std::vector<unsigned int> samples = acq_dump.samples;
std::vector<std::vector<float> > 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..." << std::endl;
try
{
boost::filesystem::path p(gnuplot_executable);
boost::filesystem::path dir = p.parent_path();
std::string gnuplot_path = dir.native();
Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("lines");
g1.set_title("GPS L1 C/A 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("GPS_L1_acq_grid");
g1.savetopdf("GPS_L1_acq_grid");
g1.showonscreen();
}
catch (const GnuplotException & ge)
{
std::cout << ge.what() << std::endl;
}
}
std::string data_str = "./data";
if (boost::filesystem::exists(data_str))
{
boost::filesystem::remove_all(data_str);
}
}
TEST_F(GpsL1CaPcpsAcquisitionTest, Instantiate)
{
init();
boost::shared_ptr<GpsL1CaPcpsAcquisition> acquisition = boost::make_shared<GpsL1CaPcpsAcquisition>(config.get(), "Acquisition", 1, 1);
boost::shared_ptr<GpsL1CaPcpsAcquisition> acquisition = boost::make_shared<GpsL1CaPcpsAcquisition>(config.get(), "Acquisition_1C", 1, 1);
}
@ -167,7 +239,7 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ConnectAndRun)
top_block = gr::make_top_block("Acquisition test");
init();
boost::shared_ptr<GpsL1CaPcpsAcquisition> acquisition = boost::make_shared<GpsL1CaPcpsAcquisition>(config.get(), "Acquisition", 1, 1);
boost::shared_ptr<GpsL1CaPcpsAcquisition> acquisition = boost::make_shared<GpsL1CaPcpsAcquisition>(config.get(), "Acquisition_1C", 1, 1);
boost::shared_ptr<GpsL1CaPcpsAcquisitionTest_msg_rx> msg_rx = GpsL1CaPcpsAcquisitionTest_msg_rx_make();
ASSERT_NO_THROW( {
@ -178,14 +250,14 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ConnectAndRun)
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." << std::endl;
}) << "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::endl;
}) << "Failure running the top_block.";
std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl;
}
@ -194,7 +266,7 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ConnectAndRun)
TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults)
{
std::chrono::time_point<std::chrono::system_clock> start, end;
std::chrono::duration<double> elapsed_seconds(0);
std::chrono::duration<double> elapsed_seconds(0.0);
top_block = gr::make_top_block("Acquisition test");
double expected_delay_samples = 524;
@ -202,32 +274,42 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults)
init();
std::shared_ptr<GpsL1CaPcpsAcquisition> acquisition = std::make_shared<GpsL1CaPcpsAcquisition>(config.get(), "Acquisition", 1, 1);
if(FLAGS_plot_acq_grid == true)
{
std::string data_str = "./data";
if (boost::filesystem::exists(data_str))
{
boost::filesystem::remove_all(data_str);
}
boost::filesystem::create_directory(data_str);
}
std::shared_ptr<GpsL1CaPcpsAcquisition> acquisition = std::make_shared<GpsL1CaPcpsAcquisition>(config.get(), "Acquisition_1C", 1, 1);
boost::shared_ptr<GpsL1CaPcpsAcquisitionTest_msg_rx> msg_rx = GpsL1CaPcpsAcquisitionTest_msg_rx_make();
ASSERT_NO_THROW( {
acquisition->set_channel(1);
}) << "Failure setting channel." << std::endl;
}) << "Failure setting channel.";
ASSERT_NO_THROW( {
acquisition->set_gnss_synchro(&gnss_synchro);
}) << "Failure setting gnss_synchro." << std::endl;
}) << "Failure setting gnss_synchro.";
ASSERT_NO_THROW( {
acquisition->set_threshold(0.001);
}) << "Failure setting threshold." << std::endl;
}) << "Failure setting threshold.";
ASSERT_NO_THROW( {
acquisition->set_doppler_max(5000);
}) << "Failure setting doppler_max." << std::endl;
}) << "Failure setting doppler_max.";
ASSERT_NO_THROW( {
acquisition->set_doppler_step(100);
}) << "Failure setting doppler_step." << std::endl;
}) << "Failure setting doppler_step.";
ASSERT_NO_THROW( {
acquisition->connect(top_block);
}) << "Failure connecting acquisition to the top_block." << std::endl;
}) << "Failure connecting acquisition to the top_block.";
ASSERT_NO_THROW( {
std::string path = std::string(TEST_PATH);
@ -236,7 +318,7 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults)
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." << std::endl;
}) << "Failure connecting the blocks of acquisition test.";
acquisition->set_local_code();
acquisition->set_state(1); // Ensure that acquisition starts at the first sample
@ -247,7 +329,7 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults)
top_block->run(); // Start threads and wait
end = std::chrono::system_clock::now();
elapsed_seconds = end - start;
}) << "Failure running the top_block." << std::endl;
}) << "Failure running the top_block.";
unsigned long int nsamples = gnss_synchro.Acq_samplestamp_samples;
std::cout << "Acquired " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl;
@ -259,4 +341,9 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults)
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();
}
}

View File

@ -18,6 +18,7 @@
set(SIGNAL_PROCESSING_TESTING_LIB_SOURCES
acquisition_dump_reader.cc
tracking_dump_reader.cc
tlm_dump_reader.cc
observables_dump_reader.cc

View File

@ -0,0 +1,109 @@
/*!
* \file acquisition_dump_reader.cc
* \brief Helper file for unit testing
* \author Javier Arribas, 2017. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (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 <complex>
#include "acquisition_dump_reader.h"
bool acquisition_dump_reader::read_binary_acq()
{
std::complex<float>* aux = new std::complex<float>[1];
for(int i = 0; i < d_num_doppler_bins; i++)
{
try
{
std::ifstream ifs;
ifs.exceptions( std::ifstream::failbit | std::ifstream::badbit );
ifs.open(d_dump_filenames.at(i).c_str(), std::ios::in | std::ios::binary);
d_dump_files.at(i).swap(ifs);
if (d_dump_files.at(i).is_open())
{
for(int k = 0; k < d_samples_per_code; k++)
{
d_dump_files.at(i).read(reinterpret_cast<char *>(&aux[0]), sizeof(std::complex<float>));
mag.at(i).at(k) = std::abs(*aux) / std::pow(d_samples_per_code, 2);
}
}
else
{
std::cout << "File " << d_dump_filenames.at(i).c_str() << " not found." << std::endl;
delete[] aux;
return false;
}
d_dump_files.at(i).close();
}
catch (const std::ifstream::failure &e)
{
std::cout << e.what() << std::endl;
delete[] aux;
return false;
}
}
delete[] aux;
return true;
}
acquisition_dump_reader::acquisition_dump_reader(std::string & basename, unsigned int sat, unsigned int doppler_max, unsigned int doppler_step, unsigned int samples_per_code)
{
d_basename = basename;
d_sat = sat;
d_doppler_max = doppler_max;
d_doppler_step = doppler_step;
d_samples_per_code = samples_per_code;
d_num_doppler_bins = static_cast<unsigned int>(ceil( static_cast<double>(static_cast<int>(d_doppler_max) - static_cast<int>(-d_doppler_max)) / static_cast<double>(d_doppler_step)));
std::vector<std::vector<float> > mag_aux(d_num_doppler_bins, std::vector<float>(d_samples_per_code));
mag = mag_aux;
for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
{
doppler.push_back(-static_cast<int>(d_doppler_max) + d_doppler_step * doppler_index);
d_dump_filenames.push_back(d_basename + "_sat_" + std::to_string(d_sat) + "_doppler_" + std::to_string(doppler.at(doppler_index)) + ".dat");
}
for (unsigned int k = 0; k < d_samples_per_code; k++)
{
samples.push_back(k);
}
for(int i = 0; i < d_num_doppler_bins; i++)
{
std::ifstream is;
d_dump_files.push_back(std::move(is));
}
}
acquisition_dump_reader::~acquisition_dump_reader()
{
for(int i = 0; i < d_num_doppler_bins; i++)
{
if (d_dump_files.at(i).is_open() == true)
{
d_dump_files.at(i).close();
}
}
}

View File

@ -0,0 +1,61 @@
/*!
* \file acquisition_dump_reader.h
* \brief Helper file for unit testing
* \author Javier Arribas, 2017. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (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_ACQUISITION_DUMP_READER_H
#define GNSS_SDR_ACQUISITION_DUMP_READER_H
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
class acquisition_dump_reader
{
public:
acquisition_dump_reader(std::string & basename, unsigned int sat, unsigned int doppler_max, unsigned int doppler_step, unsigned int samples_per_code);
~acquisition_dump_reader();
bool read_binary_acq();
std::vector<int> doppler;
std::vector<unsigned int> samples;
std::vector<std::vector<float> > mag;
private:
std::string d_basename;
unsigned int d_sat;
unsigned int d_doppler_max;
unsigned int d_doppler_step;
unsigned int d_samples_per_code;
unsigned int d_num_doppler_bins;
std::vector<std::string> d_dump_filenames;
std::vector<std::ifstream> d_dump_files;
};
#endif // GNSS_SDR_ACQUISITION_DUMP_READER_H