1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-15 04:30:33 +00:00

Extend GPS L1 CA Pull-in test to support external signal file. Add GNUPlot interface function to disable the screen output

This commit is contained in:
Javier Arribas 2018-07-02 17:43:34 +02:00
parent 224e798ba3
commit 12cd65e108
2 changed files with 303 additions and 49 deletions

View File

@ -218,6 +218,7 @@ public:
const std::string &labely = "y",
const std::string &labelz = "z");
/// destructor: needed to delete temporary files
~Gnuplot();
@ -246,6 +247,9 @@ public:
/// sets terminal type to terminal_std
Gnuplot &showonscreen(); // window output is set by default (win/x11/aqua)
/// sets terminal type to unknown (disable the screen output)
Gnuplot &disablescreen();
/// saves a gnuplot session to a postscript file, filename without extension
Gnuplot &savetops(const std::string &filename = "gnuplot_output");
@ -1195,6 +1199,17 @@ Gnuplot &Gnuplot::set_smooth(const std::string &stylestr)
}
//------------------------------------------------------------------------------
//
// Disable screen output
//
Gnuplot &Gnuplot::disablescreen()
{
cmd("set output");
cmd("set terminal unknown");
return *this;
}
//------------------------------------------------------------------------------
//
// sets terminal type to windows / x11
@ -2090,19 +2105,19 @@ std::string Gnuplot::create_tmpfile(std::ofstream &tmp)
throw GnuplotException(except.str());
}
// int mkstemp(char *name);
// shall replace the contents of the string pointed to by "name" by a unique
// filename, and return a file descriptor for the file open for reading and
// writing. Otherwise, -1 shall be returned if no suitable file could be
// created. The string in template should look like a filename with six
// trailing 'X' s; mkstemp() replaces each 'X' with a character from the
// portable filename character set. The characters are chosen such that the
// resulting name does not duplicate the name of an existing file at the
// time of a call to mkstemp()
// int mkstemp(char *name);
// shall replace the contents of the string pointed to by "name" by a unique
// filename, and return a file descriptor for the file open for reading and
// writing. Otherwise, -1 shall be returned if no suitable file could be
// created. The string in template should look like a filename with six
// trailing 'X' s; mkstemp() replaces each 'X' with a character from the
// portable filename character set. The characters are chosen such that the
// resulting name does not duplicate the name of an existing file at the
// time of a call to mkstemp()
//
// open temporary files for output
//
//
// open temporary files for output
//
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
if (_mktemp(name) == NULL)

View File

@ -44,6 +44,7 @@
#include "GPS_L1_CA.h"
#include "gnss_block_factory.h"
#include "tracking_interface.h"
#include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
#include "in_memory_configuration.h"
#include "tracking_true_obs_reader.h"
#include "tracking_dump_reader.h"
@ -52,7 +53,59 @@
#include "test_flags.h"
#include "tracking_tests_flags.h"
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
// ######## GNURADIO ACQUISITION BLOCK MESSAGE RECEVER #########
class Acquisition_msg_rx;
typedef boost::shared_ptr<Acquisition_msg_rx> Acquisition_msg_rx_sptr;
Acquisition_msg_rx_sptr Acquisition_msg_rx_make();
class Acquisition_msg_rx : public gr::block
{
private:
friend Acquisition_msg_rx_sptr Acquisition_msg_rx_make();
void msg_handler_events(pmt::pmt_t msg);
Acquisition_msg_rx();
public:
int rx_message;
~Acquisition_msg_rx(); //!< Default destructor
};
Acquisition_msg_rx_sptr Acquisition_msg_rx_make()
{
return Acquisition_msg_rx_sptr(new Acquisition_msg_rx());
}
void Acquisition_msg_rx::msg_handler_events(pmt::pmt_t msg)
{
try
{
long int message = pmt::to_long(msg);
rx_message = message;
}
catch (boost::bad_any_cast& e)
{
LOG(WARNING) << "msg_handler_acquisition Bad cast!\n";
rx_message = 0;
}
}
Acquisition_msg_rx::Acquisition_msg_rx() : gr::block("Acquisition_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(&Acquisition_msg_rx::msg_handler_events, this, _1));
rx_message = 0;
}
Acquisition_msg_rx::~Acquisition_msg_rx() {}
// ######## GNURADIO TRACKING BLOCK MESSAGE RECEVER #########
class GpsL1CADllPllTrackingPullInTest_msg_rx;
typedef boost::shared_ptr<GpsL1CADllPllTrackingPullInTest_msg_rx> GpsL1CADllPllTrackingPullInTest_msg_rx_sptr;
@ -88,7 +141,7 @@ void GpsL1CADllPllTrackingPullInTest_msg_rx::msg_handler_events(pmt::pmt_t msg)
}
catch (boost::bad_any_cast& e)
{
LOG(WARNING) << "msg_handler_telemetry Bad any cast!";
LOG(WARNING) << "msg_handler_tracking Bad cast!";
rx_message = 0;
}
}
@ -126,6 +179,10 @@ public:
std::string filename_rinex_obs = FLAGS_filename_rinex_obs;
std::string filename_raw_data = FLAGS_filename_raw_data;
std::map<int, double> doppler_measurements_map;
std::map<int, double> code_delay_measurements_map;
std::map<int, unsigned long int> acq_samplestamp_map;
int configure_generator(double CN0_dBHz, int file_idx);
int generate_signal();
std::vector<double> check_results_doppler(arma::vec& true_time_s,
@ -165,6 +222,7 @@ public:
double DLL_narrow_bw_hz,
int extend_correlation_symbols);
bool acquire_GPS_L1CA_signal(int SV_ID);
gr::top_block_sptr top_block;
std::shared_ptr<GNSSBlockFactory> factory;
std::shared_ptr<InMemoryConfiguration> config;
@ -259,12 +317,120 @@ void GpsL1CADllPllTrackingPullInTest::configure_receiver(
}
bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
{
// 1. Setup GNU Radio flowgraph (file_source -> Acquisition_10m)
gr::top_block_sptr top_block;
top_block = gr::make_top_block("Acquisition test");
// Satellite signal definition
Gnss_Synchro tmp_gnss_synchro;
tmp_gnss_synchro.Channel_ID = 0;
tmp_gnss_synchro.System = 'G';
std::string signal = "1C";
signal.copy(tmp_gnss_synchro.Signal, 2, 0);
tmp_gnss_synchro.PRN = SV_ID;
config = std::make_shared<InMemoryConfiguration>();
config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq));
GNSSBlockFactory block_factory;
GpsL1CaPcpsAcquisitionFineDoppler* acquisition;
acquisition = new GpsL1CaPcpsAcquisitionFineDoppler(config.get(), "Acquisition", 1, 1);
acquisition->set_channel(1);
acquisition->set_gnss_synchro(&tmp_gnss_synchro);
acquisition->set_threshold(config->property("Acquisition.threshold", 0.05));
acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 10000));
acquisition->set_doppler_step(config->property("Acquisition.doppler_step", 250));
boost::shared_ptr<Acquisition_msg_rx> msg_rx;
try
{
msg_rx = Acquisition_msg_rx_make();
}
catch (const std::exception& e)
{
std::cout << "Failure connecting the message port system: " << e.what() << std::endl;
exit(0);
}
gr::blocks::file_source::sptr file_source;
std::string file = FLAGS_filename_raw_data;
const char* file_name = file.c_str();
file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false);
gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make();
gr::blocks::null_sink::sptr sink = gr::blocks::null_sink::make(sizeof(Gnss_Synchro));
top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0);
top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0);
top_block->msg_connect(acquisition->get_left_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
// 5. Run the flowgraph
// Get visible GPS satellites (positive acquisitions with Doppler measurements)
// record startup time
std::chrono::time_point<std::chrono::system_clock> start, end;
std::chrono::duration<double> elapsed_seconds;
start = std::chrono::system_clock::now();
bool start_msg = true;
doppler_measurements_map.clear();
code_delay_measurements_map.clear();
acq_samplestamp_map.clear();
for (unsigned int PRN = 1; PRN < 33; PRN++)
{
tmp_gnss_synchro.PRN = PRN;
acquisition->set_gnss_synchro(&tmp_gnss_synchro);
acquisition->init();
acquisition->set_local_code();
acquisition->reset();
msg_rx->rx_message = 0;
top_block->run();
if (start_msg == true)
{
std::cout << "Reading external signal file: " << FLAGS_filename_raw_data << std::endl;
std::cout << "Searching for GPS Satellites in L1 band..." << std::endl;
std::cout << "[";
start_msg = false;
}
while (msg_rx->rx_message == 0)
{
usleep(100000);
}
if (msg_rx->rx_message == 1)
{
std::cout << " " << PRN << " ";
doppler_measurements_map.insert(std::pair<int, double>(PRN, tmp_gnss_synchro.Acq_doppler_hz));
code_delay_measurements_map.insert(std::pair<int, double>(PRN, tmp_gnss_synchro.Acq_delay_samples));
acq_samplestamp_map.insert(std::pair<int, double>(PRN, tmp_gnss_synchro.Acq_samplestamp_samples));
}
else
{
std::cout << " . ";
}
top_block->stop();
file_source->seek(0, 0);
std::cout.flush();
}
std::cout << "]" << std::endl;
// report the elapsed time
end = std::chrono::system_clock::now();
elapsed_seconds = end - start;
std::cout << "Total signal acquisition run time "
<< elapsed_seconds.count()
<< " [seconds]" << std::endl;
return true;
}
TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
{
//*************************************************
//***** STEP 2: Prepare the parameters sweep ******
//***** STEP 1: Prepare the parameters sweep ******
//*************************************************
std::vector<double> acq_doppler_error_hz_values;
std::vector<double>
acq_doppler_error_hz_values;
std::vector<std::vector<double>> acq_delay_error_chips_values; //vector of vector
for (double doppler_hz = FLAGS_Acq_Doppler_error_hz_start; doppler_hz >= FLAGS_Acq_Doppler_error_hz_stop; doppler_hz = doppler_hz + FLAGS_Acq_Doppler_error_hz_step)
@ -280,10 +446,12 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
}
//*********************************************
//***** STEP 3: Generate the input signal *****
//*********************************************
//***********************************************************
//***** STEP 2: Generate the input signal (if required) *****
//***********************************************************
std::vector<double> generator_CN0_values;
if (FLAGS_enable_external_signal_file)
{
if (FLAGS_CN0_dBHz_start == FLAGS_CN0_dBHz_stop)
{
generator_CN0_values.push_back(FLAGS_CN0_dBHz_start);
@ -295,11 +463,19 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
generator_CN0_values.push_back(cn0);
}
}
}
else
{
generator_CN0_values.push_back(999); // an external input signal capture is selected, no CN0 information available
}
// use generator or use an external capture file
if (FLAGS_enable_external_signal_file)
{
//todo: create and configure an acquisition block and perform an acquisition to obtain the synchronization parameters
//create and configure an acquisition block and perform an acquisition to obtain the synchronization parameters
ASSERT_EQ(acquire_GPS_L1CA_signal(FLAGS_test_satellite_PRN), true);
EXPECT_TRUE(doppler_measurements_map.find(FLAGS_test_satellite_PRN) != doppler_measurements_map.end())
<< "Error: satellite SV: " << FLAGS_test_satellite_PRN << " is not acquired";
}
else
{
@ -326,6 +502,10 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
//***** Obtain the initial signal sinchronization parameters (emulating an acquisition) ****
//******************************************************************************************
int test_satellite_PRN = 0;
double true_acq_doppler_hz = 0.0;
double true_acq_delay_samples = 0.0;
unsigned long int acq_samplestamp_samples = 0;
tracking_true_obs_reader true_obs_data;
if (!FLAGS_enable_external_signal_file)
{
@ -341,14 +521,21 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
<< "Maybe sat PRN #" + std::to_string(FLAGS_test_satellite_PRN) +
" is not available?";
std::cout << "Testing satellite PRN=" << test_satellite_PRN << std::endl;
std::cout << "True Initial Doppler [Hz]=" << true_obs_data.doppler_l1_hz << " rue Initial code delay [Chips]=" << true_obs_data.prn_delay_chips << std::endl;
std::cout << "True Initial Doppler " << true_obs_data.doppler_l1_hz << "[Hz], true Initial code delay [Chips]=" << true_obs_data.prn_delay_chips << "[Chips]" << std::endl;
true_acq_doppler_hz = true_obs_data.doppler_l1_hz;
true_acq_delay_samples = (GPS_L1_CA_CODE_LENGTH_CHIPS - true_obs_data.prn_delay_chips / GPS_L1_CA_CODE_LENGTH_CHIPS) * static_cast<double>(baseband_sampling_freq) * GPS_L1_CA_CODE_PERIOD;
acq_samplestamp_samples = 0;
}
else
{
//todo: Simulate a perfect acquisition for the external capture file
true_acq_doppler_hz = doppler_measurements_map.find(FLAGS_test_satellite_PRN)->second;
true_acq_delay_samples = code_delay_measurements_map.find(FLAGS_test_satellite_PRN)->second;
acq_samplestamp_samples = 0; //acq_samplestamp_map.find(FLAGS_test_satellite_PRN)->second;
std::cout << "Estimated Initial Doppler " << true_acq_doppler_hz << "[Hz], estimated Initial code delay " << true_acq_delay_samples << " [Samples]" << std::endl;
}
//CN0 LOOP
std::vector<std::vector<double>> pull_in_results_v_v;
for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++)
{
std::vector<double> pull_in_results_v;
@ -356,23 +543,18 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
{
for (unsigned int current_acq_code_error_idx = 0; current_acq_code_error_idx < acq_delay_error_chips_values.at(current_acq_doppler_error_idx).size(); current_acq_code_error_idx++)
{
gnss_synchro.Acq_samplestamp_samples = acq_samplestamp_samples;
//simulate a Doppler error in acquisition
double acq_doppler_hz = true_obs_data.doppler_l1_hz + acq_doppler_error_hz_values.at(current_acq_doppler_error_idx);
gnss_synchro.Acq_doppler_hz = true_acq_doppler_hz + acq_doppler_error_hz_values.at(current_acq_doppler_error_idx);
//simulate Code Delay error in acquisition
double acq_delay_samples;
acq_delay_samples = (GPS_L1_CA_CODE_LENGTH_CHIPS - true_obs_data.prn_delay_chips / GPS_L1_CA_CODE_LENGTH_CHIPS) * static_cast<double>(baseband_sampling_freq) * GPS_L1_CA_CODE_PERIOD;
acq_delay_samples += (acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx) / GPS_L1_CA_CODE_RATE_HZ) * static_cast<double>(baseband_sampling_freq);
gnss_synchro.Acq_delay_samples = true_acq_delay_samples + (acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx) / GPS_L1_CA_CODE_RATE_HZ) * static_cast<double>(baseband_sampling_freq);
//create flowgraph
top_block = gr::make_top_block("Tracking test");
std::shared_ptr<GNSSBlockInterface> trk_ = factory->GetBlock(config, "Tracking_1C", implementation, 1, 1);
std::shared_ptr<TrackingInterface> tracking = std::dynamic_pointer_cast<TrackingInterface>(trk_);
boost::shared_ptr<GpsL1CADllPllTrackingPullInTest_msg_rx> msg_rx = GpsL1CADllPllTrackingPullInTest_msg_rx_make();
gnss_synchro.Acq_delay_samples = acq_delay_samples;
gnss_synchro.Acq_doppler_hz = acq_doppler_hz;
gnss_synchro.Acq_samplestamp_samples = 0;
ASSERT_NO_THROW({
tracking->set_channel(gnss_synchro.Channel_ID);
@ -386,8 +568,16 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
tracking->connect(top_block);
}) << "Failure connecting tracking to the top_block.";
std::string file;
ASSERT_NO_THROW({
std::string file = "./" + filename_raw_data + std::to_string(current_cn0_idx);
if (!FLAGS_enable_external_signal_file)
{
file = "./" + filename_raw_data + std::to_string(current_cn0_idx);
}
else
{
file = FLAGS_filename_raw_data;
}
const char* file_name = file.c_str();
gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false);
gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make();
@ -396,6 +586,8 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
top_block->connect(gr_interleaved_char_to_complex, 0, tracking->get_left_block(), 0);
top_block->connect(tracking->get_right_block(), 0, sink, 0);
top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
file_source->seek(acq_samplestamp_samples, 0);
}) << "Failure connecting the blocks of tracking test.";
@ -479,11 +671,19 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
Gnuplot::set_GNUPlotPath(gnuplot_path);
unsigned int decimate = static_cast<unsigned int>(FLAGS_plot_decimate);
if (FLAGS_plot_detail_level >= 2)
if (FLAGS_plot_detail_level >= 2 and FLAGS_show_plots)
{
Gnuplot g1("linespoints");
if (FLAGS_show_plots) g1.showonscreen(); // window output
g1.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz, " + "PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " Hz" + "GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
g1.showonscreen(); // window output
if (!FLAGS_enable_external_signal_file)
{
g1.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz, " + "PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
}
else
{
g1.set_title("D_e=" + std::to_string(acq_doppler_error_hz_values.at(current_acq_doppler_error_idx)) + " [Hz] " + "T_e= " + std::to_string(acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx)) + " [Chips], PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
}
g1.set_grid();
g1.set_xlabel("Time [s]");
g1.set_ylabel("Correlators' output");
@ -496,8 +696,16 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
//g1.savetopdf("Correlators_outputs" + std::to_string(generator_CN0_values.at(current_cn0_idx)), 18);
Gnuplot g2("points");
if (FLAGS_show_plots) g2.showonscreen(); // window output
g2.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz Constellation " + "PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " Hz" + "GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
g2.showonscreen(); // window output
if (!FLAGS_enable_external_signal_file)
{
g2.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz Constellation " + "PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
}
else
{
g2.set_title("D_e=" + std::to_string(acq_doppler_error_hz_values.at(current_acq_doppler_error_idx)) + " [Hz] " + "T_e= " + std::to_string(acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx)) + " [Chips], PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
}
g2.set_grid();
g2.set_xlabel("Inphase");
g2.set_ylabel("Quadrature");
@ -507,7 +715,14 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
//g2.savetopdf("Constellation", 18);
Gnuplot g3("linespoints");
if (!FLAGS_enable_external_signal_file)
{
g3.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz, GPS L1 C/A tracking CN0 output (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
}
else
{
g3.set_title("D_e=" + std::to_string(acq_doppler_error_hz_values.at(current_acq_doppler_error_idx)) + " [Hz] " + "T_e= " + std::to_string(acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx)) + " [Chips] PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
}
g3.set_grid();
g3.set_xlabel("Time [s]");
g3.set_ylabel("Reported CN0 [dB-Hz]");
@ -519,7 +734,7 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
g3.set_legend();
//g3.savetops("CN0_output");
//g3.savetopdf("CN0_output", 18);
if (FLAGS_show_plots) g3.showonscreen(); // window output
g3.showonscreen(); // window output
}
}
catch (const GnuplotException& ge)
@ -553,21 +768,45 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
pull_in_result_mesh = pull_in_results_v_v.at(current_cn0_idx);
//plot grid
Gnuplot g4("points palette pointsize 2 pointtype 7");
if (FLAGS_show_plots)
{
g4.showonscreen(); // window output
}
else
{
g4.disablescreen();
}
g4.cmd("set palette defined ( 0 \"black\", 1 \"green\" )");
g4.cmd("set key off");
g4.cmd("set view map");
std::string title("Tracking Pull-in result grid at CN0:" + std::to_string(static_cast<int>(round(generator_CN0_values.at(current_cn0_idx)))) + " dB-Hz, PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " Hz.");
std::string title;
if (!FLAGS_enable_external_signal_file)
{
title = std::string("Tracking Pull-in result grid at CN0:" + std::to_string(static_cast<int>(round(generator_CN0_values.at(current_cn0_idx)))) + " [dB-Hz], PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz].");
}
else
{
title = std::string("Tracking Pull-in result grid, PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
}
g4.set_title(title);
g4.set_grid();
g4.set_xlabel("Acquisition Doppler error [Hz]");
g4.set_ylabel("Acquisition Code Delay error [Chips]");
g4.cmd("set cbrange[0:1]");
g4.plot_xyz(doppler_error_mesh,
code_delay_error_mesh,
pull_in_result_mesh);
g4.set_legend();
if (!FLAGS_enable_external_signal_file)
{
g4.savetops("trk_pull_in_grid_" + std::to_string(static_cast<int>(round(generator_CN0_values.at(current_cn0_idx)))));
g4.savetopdf("trk_pull_in_grid_" + std::to_string(static_cast<int>(round(generator_CN0_values.at(current_cn0_idx)))), 12);
if (FLAGS_show_plots) g4.showonscreen(); // window output
}
else
{
g4.savetops("trk_pull_in_grid_" + FLAGS_filename_raw_data);
g4.savetopdf("trk_pull_in_grid_" + FLAGS_filename_raw_data, 12);
}
}
}