2017-01-25 10:58:05 +00:00
/*!
* \ file gps_l1_ca_dll_pll_tracking_test . cc
2018-06-24 20:31:44 +00:00
* \ brief This class implements a tracking test for GPS_L1_CA_DLL_PLL_Tracking
2017-01-25 10:58:05 +00:00
* implementation based on some input parameters .
2017-02-05 19:07:34 +00:00
* \ author Javier Arribas , 2017. jarribas ( at ) cttc . es
2017-01-25 10:58:05 +00:00
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
2019-07-26 10:38:20 +00:00
* Copyright ( C ) 2012 - 2019 ( see AUTHORS file for a list of contributors )
2017-01-25 10:58:05 +00:00
*
* GNSS - SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS - SDR .
*
2020-02-08 00:20:02 +00:00
* SPDX - License - Identifier : GPL - 3.0 - or - later
2017-01-25 10:58:05 +00:00
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2018-12-09 21:00:09 +00:00
# include "GPS_L1_CA.h"
# include "gnss_block_factory.h"
# include "gnuplot_i.h"
# include "in_memory_configuration.h"
# include "signal_generator_flags.h"
# include "test_flags.h"
# include "tracking_dump_reader.h"
# include "tracking_interface.h"
# include "tracking_tests_flags.h"
# include "tracking_true_obs_reader.h"
2017-02-02 17:10:24 +00:00
# include <armadillo>
2017-01-25 10:58:05 +00:00
# include <gnuradio/analog/sig_source_waveform.h>
2018-12-09 21:00:09 +00:00
# include <gnuradio/blocks/file_source.h>
# include <gnuradio/blocks/interleaved_char_to_complex.h>
# include <gnuradio/blocks/null_sink.h>
# include <gnuradio/blocks/skiphead.h>
# include <gnuradio/top_block.h>
# include <gtest/gtest.h>
# include <matio.h>
# include <chrono>
# include <unistd.h>
2019-02-11 17:38:42 +00:00
# include <utility>
2018-12-09 21:00:09 +00:00
# include <vector>
2019-06-10 19:41:13 +00:00
2020-04-26 06:41:49 +00:00
# if HAS_GENERIC_LAMBDA
# else
2020-06-06 21:41:38 +00:00
# include <boost/bind/bind.hpp>
2020-04-26 06:41:49 +00:00
# endif
2018-08-31 11:52:35 +00:00
# ifdef GR_GREATER_38
# include <gnuradio/analog/sig_source.h>
# else
2017-01-25 10:58:05 +00:00
# include <gnuradio/analog/sig_source_c.h>
2018-08-31 11:52:35 +00:00
# endif
2018-06-19 15:51:22 +00:00
2019-06-10 19:41:13 +00:00
# if HAS_STD_FILESYSTEM
2019-06-12 18:39:29 +00:00
# if HAS_STD_FILESYSTEM_EXPERIMENTAL
# include <experimental/filesystem>
namespace fs = std : : experimental : : filesystem ;
# else
2019-06-10 19:41:13 +00:00
# include <filesystem>
namespace fs = std : : filesystem ;
2019-06-12 18:39:29 +00:00
# endif
2019-06-10 19:41:13 +00:00
# else
# include <boost/filesystem.hpp>
namespace fs = boost : : filesystem ;
# endif
2020-04-02 21:59:35 +00:00
# if GNURADIO_USES_STD_POINTERS
# include <memory>
# else
# include <boost/shared_ptr.hpp>
# endif
2017-01-25 10:58:05 +00:00
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
class GpsL1CADllPllTrackingTest_msg_rx ;
2020-04-02 21:59:35 +00:00
# if GNURADIO_USES_STD_POINTERS
2020-04-02 11:23:20 +00:00
using GpsL1CADllPllTrackingTest_msg_rx_sptr = std : : shared_ptr < GpsL1CADllPllTrackingTest_msg_rx > ;
2020-04-02 21:59:35 +00:00
# else
using GpsL1CADllPllTrackingTest_msg_rx_sptr = boost : : shared_ptr < GpsL1CADllPllTrackingTest_msg_rx > ;
# endif
2017-01-25 10:58:05 +00:00
GpsL1CADllPllTrackingTest_msg_rx_sptr GpsL1CADllPllTrackingTest_msg_rx_make ( ) ;
class GpsL1CADllPllTrackingTest_msg_rx : public gr : : block
{
private :
friend GpsL1CADllPllTrackingTest_msg_rx_sptr GpsL1CADllPllTrackingTest_msg_rx_make ( ) ;
void msg_handler_events ( pmt : : pmt_t msg ) ;
GpsL1CADllPllTrackingTest_msg_rx ( ) ;
public :
int rx_message ;
2018-03-03 01:03:39 +00:00
~ GpsL1CADllPllTrackingTest_msg_rx ( ) ; //!< Default destructor
2017-01-25 10:58:05 +00:00
} ;
2017-08-11 11:11:38 +00:00
2017-01-25 10:58:05 +00:00
GpsL1CADllPllTrackingTest_msg_rx_sptr GpsL1CADllPllTrackingTest_msg_rx_make ( )
{
return GpsL1CADllPllTrackingTest_msg_rx_sptr ( new GpsL1CADllPllTrackingTest_msg_rx ( ) ) ;
}
2017-08-11 11:11:38 +00:00
2017-01-25 10:58:05 +00:00
void GpsL1CADllPllTrackingTest_msg_rx : : msg_handler_events ( pmt : : pmt_t msg )
{
try
2018-03-03 01:03:39 +00:00
{
2019-02-11 17:38:42 +00:00
int64_t message = pmt : : to_long ( std : : move ( msg ) ) ;
2019-08-18 23:29:04 +00:00
rx_message = message ; // 3 -> loss of lock
// std::cout << "Received trk message: " << rx_message << std::endl;
2018-03-03 01:03:39 +00:00
}
catch ( boost : : bad_any_cast & e )
{
2017-01-25 10:58:05 +00:00
LOG ( WARNING ) < < " msg_handler_telemetry Bad any cast! " ;
rx_message = 0 ;
2018-03-03 01:03:39 +00:00
}
2017-01-25 10:58:05 +00:00
}
2017-08-11 11:11:38 +00:00
2018-03-03 01:03:39 +00:00
GpsL1CADllPllTrackingTest_msg_rx : : GpsL1CADllPllTrackingTest_msg_rx ( ) : gr : : block ( " GpsL1CADllPllTrackingTest_msg_rx " , gr : : io_signature : : make ( 0 , 0 , 0 ) , gr : : io_signature : : make ( 0 , 0 , 0 ) )
2017-01-25 10:58:05 +00:00
{
this - > message_port_register_in ( pmt : : mp ( " events " ) ) ;
2020-04-26 06:41:49 +00:00
this - > set_msg_handler ( pmt : : mp ( " events " ) ,
# if HAS_GENERIC_LAMBDA
2020-06-08 18:04:01 +00:00
[ this ] ( auto & & PH1 ) { msg_handler_events ( PH1 ) ; } ) ;
2020-04-26 06:41:49 +00:00
# else
2020-06-12 22:32:40 +00:00
# if USE_BOOST_BIND_PLACEHOLDERS
2020-05-18 16:58:39 +00:00
boost : : bind ( & GpsL1CADllPllTrackingTest_msg_rx : : msg_handler_events , this , boost : : placeholders : : _1 ) ) ;
2020-05-18 20:50:34 +00:00
# else
boost : : bind ( & GpsL1CADllPllTrackingTest_msg_rx : : msg_handler_events , this , _1 ) ) ;
# endif
2020-04-26 06:41:49 +00:00
# endif
2017-01-25 10:58:05 +00:00
rx_message = 0 ;
}
2017-08-11 11:11:38 +00:00
2019-02-11 20:13:02 +00:00
GpsL1CADllPllTrackingTest_msg_rx : : ~ GpsL1CADllPllTrackingTest_msg_rx ( ) = default ;
2017-01-25 10:58:05 +00:00
// ###########################################################
2018-03-03 01:03:39 +00:00
class GpsL1CADllPllTrackingTest : public : : testing : : Test
2017-01-25 10:58:05 +00:00
{
2017-02-02 17:10:24 +00:00
public :
std : : string generator_binary ;
std : : string p1 ;
std : : string p2 ;
std : : string p3 ;
std : : string p4 ;
std : : string p5 ;
2018-04-23 10:37:43 +00:00
std : : string p6 ;
2019-06-11 08:11:20 +00:00
std : : string implementation = " GPS_L1_CA_DLL_PLL_Tracking " ;
2017-10-24 12:23:59 +00:00
2017-09-02 09:24:44 +00:00
const int baseband_sampling_freq = FLAGS_fs_gen_sps ;
2017-02-02 17:10:24 +00:00
std : : string filename_rinex_obs = FLAGS_filename_rinex_obs ;
std : : string filename_raw_data = FLAGS_filename_raw_data ;
2018-06-19 15:51:22 +00:00
int configure_generator ( double CN0_dBHz , int file_idx ) ;
2017-02-02 17:10:24 +00:00
int generate_signal ( ) ;
2018-06-19 15:51:22 +00:00
std : : vector < double > check_results_doppler ( arma : : vec & true_time_s ,
2018-03-03 01:03:39 +00:00
arma : : vec & true_value ,
arma : : vec & meas_time_s ,
2018-06-20 10:04:03 +00:00
arma : : vec & meas_value ,
double & mean_error ,
2018-07-12 16:52:38 +00:00
double & std_dev_error ,
double & rmse ) ;
2018-06-19 15:51:22 +00:00
std : : vector < double > check_results_acc_carrier_phase ( arma : : vec & true_time_s ,
2018-03-03 01:03:39 +00:00
arma : : vec & true_value ,
arma : : vec & meas_time_s ,
2018-06-20 10:04:03 +00:00
arma : : vec & meas_value ,
double & mean_error ,
2018-07-12 16:52:38 +00:00
double & std_dev_error ,
double & rmse ) ;
2018-06-19 15:51:22 +00:00
std : : vector < double > check_results_codephase ( arma : : vec & true_time_s ,
2018-03-03 01:03:39 +00:00
arma : : vec & true_value ,
arma : : vec & meas_time_s ,
2018-06-20 10:04:03 +00:00
arma : : vec & meas_value ,
double & mean_error ,
2018-07-12 16:52:38 +00:00
double & std_dev_error ,
double & rmse ) ;
2017-02-02 17:10:24 +00:00
2018-07-12 16:52:38 +00:00
bool save_mat_xy ( std : : vector < double > & x , std : : vector < double > & y , std : : string filename ) ;
2017-01-25 10:58:05 +00:00
GpsL1CADllPllTrackingTest ( )
{
factory = std : : make_shared < GNSSBlockFactory > ( ) ;
config = std : : make_shared < InMemoryConfiguration > ( ) ;
item_size = sizeof ( gr_complex ) ;
gnss_synchro = Gnss_Synchro ( ) ;
}
2019-02-11 20:13:02 +00:00
~ GpsL1CADllPllTrackingTest ( ) = default ;
2017-01-25 10:58:05 +00:00
2018-06-20 16:42:06 +00:00
void configure_receiver ( double PLL_wide_bw_hz ,
double DLL_wide_bw_hz ,
double PLL_narrow_bw_hz ,
double DLL_narrow_bw_hz ,
int extend_correlation_symbols ) ;
2017-01-25 10:58:05 +00:00
gr : : top_block_sptr top_block ;
std : : shared_ptr < GNSSBlockFactory > factory ;
std : : shared_ptr < InMemoryConfiguration > config ;
Gnss_Synchro gnss_synchro ;
size_t item_size ;
} ;
2018-06-19 15:51:22 +00:00
int GpsL1CADllPllTrackingTest : : configure_generator ( double CN0_dBHz , int file_idx )
2017-02-02 17:10:24 +00:00
{
// Configure signal generator
generator_binary = FLAGS_generator_binary ;
p1 = std : : string ( " -rinex_nav_file= " ) + FLAGS_rinex_nav_file ;
2018-03-03 01:03:39 +00:00
if ( FLAGS_dynamic_position . empty ( ) )
2017-02-02 17:10:24 +00:00
{
p2 = std : : string ( " -static_position= " ) + FLAGS_static_position + std : : string ( " , " ) + std : : to_string ( FLAGS_duration * 10 ) ;
}
else
{
p2 = std : : string ( " -obs_pos_file= " ) + std : : string ( FLAGS_dynamic_position ) ;
}
2018-06-19 15:51:22 +00:00
p3 = std : : string ( " -rinex_obs_file= " ) + FLAGS_filename_rinex_obs ; // RINEX 2.10 observation file output
p4 = std : : string ( " -sig_out_file= " ) + FLAGS_filename_raw_data + std : : to_string ( file_idx ) ; // Baseband signal output file. Will be stored in int8_t IQ multiplexed samples
2019-08-18 23:29:04 +00:00
p5 = std : : string ( " -sampling_freq= " ) + std : : to_string ( baseband_sampling_freq ) ; // Baseband sampling frequency [MSps]
2018-06-19 15:51:22 +00:00
p6 = std : : string ( " -CN0_dBHz= " ) + std : : to_string ( CN0_dBHz ) ; // Signal generator CN0
2017-02-02 17:10:24 +00:00
return 0 ;
}
int GpsL1CADllPllTrackingTest : : generate_signal ( )
{
int child_status ;
2019-02-11 17:38:42 +00:00
char * const parmList [ ] = { & generator_binary [ 0 ] , & generator_binary [ 0 ] , & p1 [ 0 ] , & p2 [ 0 ] , & p3 [ 0 ] , & p4 [ 0 ] , & p5 [ 0 ] , & p6 [ 0 ] , nullptr } ;
2017-02-02 17:10:24 +00:00
int pid ;
if ( ( pid = fork ( ) ) = = - 1 )
2019-02-11 20:13:02 +00:00
{
perror ( " fork err " ) ;
}
2017-02-02 17:10:24 +00:00
else if ( pid = = 0 )
{
execv ( & generator_binary [ 0 ] , parmList ) ;
std : : cout < < " Return not expected. Must be an execv err. " < < std : : endl ;
std : : terminate ( ) ;
}
waitpid ( pid , & child_status , 0 ) ;
2018-03-03 01:03:39 +00:00
std : : cout < < " Signal and Observables RINEX and RAW files created. " < < std : : endl ;
2017-02-02 17:10:24 +00:00
return 0 ;
}
2018-06-20 16:42:06 +00:00
void GpsL1CADllPllTrackingTest : : configure_receiver (
double PLL_wide_bw_hz ,
double DLL_wide_bw_hz ,
double PLL_narrow_bw_hz ,
double DLL_narrow_bw_hz ,
int extend_correlation_symbols )
2017-01-25 10:58:05 +00:00
{
gnss_synchro . Channel_ID = 0 ;
gnss_synchro . System = ' G ' ;
std : : string signal = " 1C " ;
signal . copy ( gnss_synchro . Signal , 2 , 0 ) ;
2017-02-02 17:10:24 +00:00
gnss_synchro . PRN = FLAGS_test_satellite_PRN ;
2017-01-25 10:58:05 +00:00
2018-06-20 16:42:06 +00:00
config = std : : make_shared < InMemoryConfiguration > ( ) ;
2017-09-02 09:24:44 +00:00
config - > set_property ( " GNSS-SDR.internal_fs_sps " , std : : to_string ( baseband_sampling_freq ) ) ;
2017-01-25 10:58:05 +00:00
// Set Tracking
2017-10-24 12:23:59 +00:00
config - > set_property ( " Tracking_1C.implementation " , implementation ) ;
2017-01-25 10:58:05 +00:00
config - > set_property ( " Tracking_1C.item_type " , " gr_complex " ) ;
2018-06-20 16:42:06 +00:00
config - > set_property ( " Tracking_1C.pll_bw_hz " , std : : to_string ( PLL_wide_bw_hz ) ) ;
config - > set_property ( " Tracking_1C.dll_bw_hz " , std : : to_string ( DLL_wide_bw_hz ) ) ;
2017-01-25 10:58:05 +00:00
config - > set_property ( " Tracking_1C.early_late_space_chips " , " 0.5 " ) ;
2018-06-20 16:42:06 +00:00
config - > set_property ( " Tracking_1C.extend_correlation_symbols " , std : : to_string ( extend_correlation_symbols ) ) ;
config - > set_property ( " Tracking_1C.pll_bw_narrow_hz " , std : : to_string ( PLL_narrow_bw_hz ) ) ;
config - > set_property ( " Tracking_1C.dll_bw_narrow_hz " , std : : to_string ( DLL_narrow_bw_hz ) ) ;
2018-03-20 13:44:34 +00:00
config - > set_property ( " Tracking_1C.early_late_space_narrow_chips " , " 0.5 " ) ;
2017-10-24 12:23:59 +00:00
config - > set_property ( " Tracking_1C.dump " , " true " ) ;
config - > set_property ( " Tracking_1C.dump_filename " , " ./tracking_ch_ " ) ;
2018-06-20 16:42:06 +00:00
std : : cout < < " ***************************************** \n " ;
std : : cout < < " *** Tracking configuration parameters *** \n " ;
std : : cout < < " ***************************************** \n " ;
std : : cout < < " pll_bw_hz: " < < config - > property ( " Tracking_1C.pll_bw_hz " , 0.0 ) < < " Hz \n " ;
std : : cout < < " dll_bw_hz: " < < config - > property ( " Tracking_1C.dll_bw_hz " , 0.0 ) < < " Hz \n " ;
std : : cout < < " pll_bw_narrow_hz: " < < config - > property ( " Tracking_1C.pll_bw_narrow_hz " , 0.0 ) < < " Hz \n " ;
std : : cout < < " dll_bw_narrow_hz: " < < config - > property ( " Tracking_1C.dll_bw_narrow_hz " , 0.0 ) < < " Hz \n " ;
std : : cout < < " extend_correlation_symbols: " < < config - > property ( " Tracking_1C.extend_correlation_symbols " , 0 ) < < " Symbols \n " ;
std : : cout < < " ***************************************** \n " ;
std : : cout < < " ***************************************** \n " ;
2017-01-25 10:58:05 +00:00
}
2017-07-12 18:02:34 +00:00
2018-06-19 15:51:22 +00:00
std : : vector < double > GpsL1CADllPllTrackingTest : : check_results_doppler ( arma : : vec & true_time_s ,
2018-03-03 01:03:39 +00:00
arma : : vec & true_value ,
arma : : vec & meas_time_s ,
2018-06-20 10:04:03 +00:00
arma : : vec & meas_value ,
double & mean_error ,
2018-07-12 16:52:38 +00:00
double & std_dev_error ,
double & rmse )
2017-02-02 17:10:24 +00:00
{
2017-10-24 12:47:05 +00:00
// 1. True value interpolation to match the measurement times
2017-02-02 17:10:24 +00:00
arma : : vec true_value_interp ;
2017-07-12 18:02:34 +00:00
arma : : uvec true_time_s_valid = find ( true_time_s > 0 ) ;
true_time_s = true_time_s ( true_time_s_valid ) ;
true_value = true_value ( true_time_s_valid ) ;
arma : : uvec meas_time_s_valid = find ( meas_time_s > 0 ) ;
meas_time_s = meas_time_s ( meas_time_s_valid ) ;
meas_value = meas_value ( meas_time_s_valid ) ;
2017-02-05 19:07:34 +00:00
arma : : interp1 ( true_time_s , true_value , meas_time_s , true_value_interp ) ;
2017-02-02 17:10:24 +00:00
2017-10-24 12:47:05 +00:00
// 2. RMSE
2017-02-02 17:10:24 +00:00
arma : : vec err ;
2017-02-05 19:07:34 +00:00
err = meas_value - true_value_interp ;
2018-06-19 15:51:22 +00:00
2019-03-02 10:44:45 +00:00
// conversion between arma::vec and std:vector
2018-06-19 15:51:22 +00:00
std : : vector < double > err_std_vector ( err . colptr ( 0 ) , err . colptr ( 0 ) + err . n_rows ) ;
2017-02-05 19:07:34 +00:00
arma : : vec err2 = arma : : square ( err ) ;
2018-07-12 16:52:38 +00:00
rmse = sqrt ( arma : : mean ( err2 ) ) ;
2017-02-02 17:10:24 +00:00
2017-10-24 12:47:05 +00:00
// 3. Mean err and variance
2017-02-05 19:07:34 +00:00
double error_mean = arma : : mean ( err ) ;
double error_var = arma : : var ( err ) ;
2017-02-02 17:10:24 +00:00
2018-06-20 10:04:03 +00:00
mean_error = error_mean ;
std_dev_error = sqrt ( error_var ) ;
2017-10-24 12:47:05 +00:00
// 4. Peaks
2017-02-05 19:07:34 +00:00
double max_error = arma : : max ( err ) ;
double min_error = arma : : min ( err ) ;
2017-02-02 17:10:24 +00:00
2017-10-24 12:47:05 +00:00
// 5. report
2017-07-12 18:02:34 +00:00
std : : streamsize ss = std : : cout . precision ( ) ;
2017-02-05 19:07:34 +00:00
std : : cout < < std : : setprecision ( 10 ) < < " TRK Doppler RMSE= " < < rmse
2017-10-24 12:47:05 +00:00
< < " , mean= " < < error_mean
< < " , stdev= " < < sqrt ( error_var ) < < " (max,min)= " < < max_error < < " , " < < min_error < < " [Hz] " < < std : : endl ;
2018-03-03 01:03:39 +00:00
std : : cout . precision ( ss ) ;
2018-06-19 15:51:22 +00:00
return err_std_vector ;
2017-02-02 17:10:24 +00:00
}
2017-07-12 18:02:34 +00:00
2018-06-19 15:51:22 +00:00
std : : vector < double > GpsL1CADllPllTrackingTest : : check_results_acc_carrier_phase ( arma : : vec & true_time_s ,
2018-03-03 01:03:39 +00:00
arma : : vec & true_value ,
arma : : vec & meas_time_s ,
2018-06-20 10:04:03 +00:00
arma : : vec & meas_value ,
double & mean_error ,
2018-07-12 16:52:38 +00:00
double & std_dev_error ,
double & rmse )
2017-02-02 17:10:24 +00:00
{
2017-10-24 12:47:05 +00:00
// 1. True value interpolation to match the measurement times
2017-02-02 17:10:24 +00:00
arma : : vec true_value_interp ;
2017-07-12 18:02:34 +00:00
arma : : uvec true_time_s_valid = find ( true_time_s > 0 ) ;
true_time_s = true_time_s ( true_time_s_valid ) ;
true_value = true_value ( true_time_s_valid ) ;
arma : : uvec meas_time_s_valid = find ( meas_time_s > 0 ) ;
meas_time_s = meas_time_s ( meas_time_s_valid ) ;
meas_value = meas_value ( meas_time_s_valid ) ;
2017-02-05 19:07:34 +00:00
arma : : interp1 ( true_time_s , true_value , meas_time_s , true_value_interp ) ;
2017-02-02 17:10:24 +00:00
2017-10-24 12:47:05 +00:00
// 2. RMSE
2017-02-02 17:10:24 +00:00
arma : : vec err ;
2019-08-18 23:29:04 +00:00
// it is required to remove the initial offset in the accumulated carrier phase error
2018-07-16 13:09:35 +00:00
err = ( meas_value - meas_value ( 0 ) ) - ( true_value_interp - true_value_interp ( 0 ) ) ;
2017-02-05 19:07:34 +00:00
arma : : vec err2 = arma : : square ( err ) ;
2019-03-02 10:44:45 +00:00
// conversion between arma::vec and std:vector
2018-06-19 15:51:22 +00:00
std : : vector < double > err_std_vector ( err . colptr ( 0 ) , err . colptr ( 0 ) + err . n_rows ) ;
2018-07-12 16:52:38 +00:00
rmse = sqrt ( arma : : mean ( err2 ) ) ;
2017-02-02 17:10:24 +00:00
2017-10-24 12:47:05 +00:00
// 3. Mean err and variance
2017-02-05 19:07:34 +00:00
double error_mean = arma : : mean ( err ) ;
double error_var = arma : : var ( err ) ;
2017-02-02 17:10:24 +00:00
2018-06-20 10:04:03 +00:00
mean_error = error_mean ;
std_dev_error = sqrt ( error_var ) ;
2017-02-02 17:10:24 +00:00
// 4. Peaks
2017-02-05 19:07:34 +00:00
double max_error = arma : : max ( err ) ;
double min_error = arma : : min ( err ) ;
2017-02-02 17:10:24 +00:00
2017-10-24 12:47:05 +00:00
// 5. report
2017-07-12 18:02:34 +00:00
std : : streamsize ss = std : : cout . precision ( ) ;
2017-02-05 19:07:34 +00:00
std : : cout < < std : : setprecision ( 10 ) < < " TRK acc carrier phase RMSE= " < < rmse
< < " , mean= " < < error_mean
< < " , stdev= " < < sqrt ( error_var ) < < " (max,min)= " < < max_error < < " , " < < min_error < < " [Hz] " < < std : : endl ;
2018-03-03 01:03:39 +00:00
std : : cout . precision ( ss ) ;
2018-06-19 15:51:22 +00:00
return err_std_vector ;
2017-02-02 17:10:24 +00:00
}
2017-07-12 18:02:34 +00:00
2018-06-19 15:51:22 +00:00
std : : vector < double > GpsL1CADllPllTrackingTest : : check_results_codephase ( arma : : vec & true_time_s ,
2018-03-03 01:03:39 +00:00
arma : : vec & true_value ,
arma : : vec & meas_time_s ,
2018-06-20 10:04:03 +00:00
arma : : vec & meas_value ,
double & mean_error ,
2018-07-12 16:52:38 +00:00
double & std_dev_error ,
double & rmse )
2017-02-02 17:10:24 +00:00
{
2017-10-24 12:47:05 +00:00
// 1. True value interpolation to match the measurement times
2017-02-02 17:10:24 +00:00
arma : : vec true_value_interp ;
2017-07-12 18:02:34 +00:00
arma : : uvec true_time_s_valid = find ( true_time_s > 0 ) ;
true_time_s = true_time_s ( true_time_s_valid ) ;
true_value = true_value ( true_time_s_valid ) ;
arma : : uvec meas_time_s_valid = find ( meas_time_s > 0 ) ;
meas_time_s = meas_time_s ( meas_time_s_valid ) ;
meas_value = meas_value ( meas_time_s_valid ) ;
2017-02-05 19:07:34 +00:00
arma : : interp1 ( true_time_s , true_value , meas_time_s , true_value_interp ) ;
2017-02-02 17:10:24 +00:00
2017-10-24 12:47:05 +00:00
// 2. RMSE
2017-02-02 17:10:24 +00:00
arma : : vec err ;
2017-02-05 19:07:34 +00:00
err = meas_value - true_value_interp ;
2019-03-02 10:44:45 +00:00
// conversion between arma::vec and std:vector
2018-06-19 15:51:22 +00:00
std : : vector < double > err_std_vector ( err . colptr ( 0 ) , err . colptr ( 0 ) + err . n_rows ) ;
2017-02-05 19:07:34 +00:00
arma : : vec err2 = arma : : square ( err ) ;
2018-07-12 16:52:38 +00:00
rmse = sqrt ( arma : : mean ( err2 ) ) ;
2017-02-02 17:10:24 +00:00
2017-10-24 12:47:05 +00:00
// 3. Mean err and variance
2017-02-05 19:07:34 +00:00
double error_mean = arma : : mean ( err ) ;
double error_var = arma : : var ( err ) ;
2017-02-02 17:10:24 +00:00
2018-06-20 10:04:03 +00:00
mean_error = error_mean ;
std_dev_error = sqrt ( error_var ) ;
2017-02-02 17:10:24 +00:00
// 4. Peaks
2017-02-05 19:07:34 +00:00
double max_error = arma : : max ( err ) ;
double min_error = arma : : min ( err ) ;
2017-02-02 17:10:24 +00:00
2017-10-24 12:47:05 +00:00
// 5. report
2017-07-12 18:02:34 +00:00
std : : streamsize ss = std : : cout . precision ( ) ;
2017-02-05 19:07:34 +00:00
std : : cout < < std : : setprecision ( 10 ) < < " TRK code phase RMSE= " < < rmse
< < " , mean= " < < error_mean
< < " , stdev= " < < sqrt ( error_var ) < < " (max,min)= " < < max_error < < " , " < < min_error < < " [Chips] " < < std : : endl ;
2018-03-03 01:03:39 +00:00
std : : cout . precision ( ss ) ;
2018-06-19 15:51:22 +00:00
return err_std_vector ;
2017-02-02 17:10:24 +00:00
}
2017-02-05 19:07:34 +00:00
2017-07-12 18:02:34 +00:00
2017-01-25 10:58:05 +00:00
TEST_F ( GpsL1CADllPllTrackingTest , ValidationOfResults )
{
2019-08-18 23:29:04 +00:00
// *************************************************
// ***** STEP 2: Prepare the parameters sweep ******
// *************************************************
2018-06-19 15:51:22 +00:00
std : : vector < double > generator_CN0_values ;
2019-08-18 23:29:04 +00:00
// data containers for config param sweep
std : : vector < std : : vector < double > > mean_doppler_error_sweep ; // swep config param and cn0 sweep
std : : vector < std : : vector < double > > std_dev_doppler_error_sweep ; // swep config param and cn0 sweep
std : : vector < std : : vector < double > > rmse_doppler_sweep ; // swep config param and cn0 sweep
2018-06-20 10:04:03 +00:00
2019-08-18 23:29:04 +00:00
std : : vector < std : : vector < double > > mean_code_phase_error_sweep ; // swep config param and cn0 sweep
std : : vector < std : : vector < double > > std_dev_code_phase_error_sweep ; // swep config param and cn0 sweep
std : : vector < std : : vector < double > > rmse_code_phase_sweep ; // swep config param and cn0 sweep
2018-06-20 10:04:03 +00:00
2019-08-18 23:29:04 +00:00
std : : vector < std : : vector < double > > mean_carrier_phase_error_sweep ; // swep config param and cn0 sweep
std : : vector < std : : vector < double > > std_dev_carrier_phase_error_sweep ; // swep config param and cn0 sweep
std : : vector < std : : vector < double > > rmse_carrier_phase_sweep ; // swep config param and cn0 sweep
2018-06-20 10:04:03 +00:00
std : : vector < std : : vector < double > > trk_valid_timestamp_s_sweep ;
2018-06-22 14:10:22 +00:00
std : : vector < std : : vector < double > > generator_CN0_values_sweep_copy ;
2017-02-02 17:10:24 +00:00
2018-06-19 15:51:22 +00:00
int test_satellite_PRN = 0 ;
double acq_delay_samples = 0.0 ;
double acq_doppler_hz = 0.0 ;
2019-02-22 14:57:15 +00:00
Tracking_True_Obs_Reader true_obs_data ;
2017-01-25 10:58:05 +00:00
2018-06-20 16:42:06 +00:00
// CONFIG PARAM SWEEP LOOP
std : : vector < double > PLL_wide_bw_values ;
std : : vector < double > DLL_wide_bw_values ;
2017-02-05 19:07:34 +00:00
2019-08-18 23:29:04 +00:00
// ***********************************************************
// ***** STEP 2: Tracking configuration parameters sweep *****
// ***********************************************************
2018-06-20 16:42:06 +00:00
if ( FLAGS_PLL_bw_hz_start = = FLAGS_PLL_bw_hz_stop )
2018-06-19 15:51:22 +00:00
{
2018-06-20 16:42:06 +00:00
if ( FLAGS_DLL_bw_hz_start = = FLAGS_DLL_bw_hz_stop )
2018-06-19 15:51:22 +00:00
{
2019-08-18 23:29:04 +00:00
// NO PLL/DLL BW sweep
2018-06-20 16:42:06 +00:00
PLL_wide_bw_values . push_back ( FLAGS_PLL_bw_hz_start ) ;
DLL_wide_bw_values . push_back ( FLAGS_DLL_bw_hz_start ) ;
2018-06-19 15:51:22 +00:00
}
2018-06-20 16:42:06 +00:00
else
2018-06-19 15:51:22 +00:00
{
2019-08-18 23:29:04 +00:00
// DLL BW Sweep
2018-06-22 14:10:22 +00:00
for ( double dll_bw = FLAGS_DLL_bw_hz_start ; dll_bw > = FLAGS_DLL_bw_hz_stop ; dll_bw = dll_bw - FLAGS_DLL_bw_hz_step )
2018-06-20 16:42:06 +00:00
{
PLL_wide_bw_values . push_back ( FLAGS_PLL_bw_hz_start ) ;
DLL_wide_bw_values . push_back ( dll_bw ) ;
}
2018-06-20 10:04:03 +00:00
}
2018-06-20 16:42:06 +00:00
}
else
{
2019-08-18 23:29:04 +00:00
// PLL BW Sweep
2018-06-22 14:10:22 +00:00
for ( double pll_bw = FLAGS_PLL_bw_hz_start ; pll_bw > = FLAGS_PLL_bw_hz_stop ; pll_bw = pll_bw - FLAGS_PLL_bw_hz_step )
2018-06-19 15:51:22 +00:00
{
2018-06-20 16:42:06 +00:00
PLL_wide_bw_values . push_back ( pll_bw ) ;
DLL_wide_bw_values . push_back ( FLAGS_DLL_bw_hz_start ) ;
}
}
2019-08-18 23:29:04 +00:00
// *********************************************
// ***** STEP 3: Generate the input signal *****
// *********************************************
2018-06-22 14:10:22 +00:00
std : : vector < double > cno_vector ;
if ( FLAGS_CN0_dBHz_start = = FLAGS_CN0_dBHz_stop )
{
generator_CN0_values . push_back ( FLAGS_CN0_dBHz_start ) ;
}
else
{
for ( double cn0 = FLAGS_CN0_dBHz_start ; cn0 > FLAGS_CN0_dBHz_stop ; cn0 = cn0 - FLAGS_CN0_dB_step )
{
generator_CN0_values . push_back ( cn0 ) ;
}
}
// use generator or use an external capture file
if ( FLAGS_enable_external_signal_file )
{
2019-08-18 23:29:04 +00:00
// todo: create and configure an acquisition block and perform an acquisition to obtain the synchronization parameters
2018-06-22 14:10:22 +00:00
}
else
{
for ( unsigned int current_cn0_idx = 0 ; current_cn0_idx < generator_CN0_values . size ( ) ; current_cn0_idx + + )
{
// Configure the signal generator
configure_generator ( generator_CN0_values . at ( current_cn0_idx ) , current_cn0_idx ) ;
// Generate signal raw signal samples and observations RINEX file
if ( FLAGS_disable_generator = = false )
{
generate_signal ( ) ;
}
// open true observables log file written by the simulator
}
}
2019-08-18 23:29:04 +00:00
// ************************************************************
// ***** STEP 4: Configure the signal tracking parameters *****
// ************************************************************
2018-06-22 14:10:22 +00:00
for ( unsigned int config_idx = 0 ; config_idx < PLL_wide_bw_values . size ( ) ; config_idx + + )
2018-06-20 16:42:06 +00:00
{
2019-08-18 23:29:04 +00:00
// CN0 LOOP
2018-06-20 16:42:06 +00:00
// data containers for CN0 sweep
std : : vector < std : : vector < double > > prompt_sweep ;
std : : vector < std : : vector < double > > early_sweep ;
std : : vector < std : : vector < double > > late_sweep ;
std : : vector < std : : vector < double > > promptI_sweep ;
std : : vector < std : : vector < double > > promptQ_sweep ;
std : : vector < std : : vector < double > > CN0_dBHz_sweep ;
std : : vector < std : : vector < double > > trk_timestamp_s_sweep ;
std : : vector < std : : vector < double > > doppler_error_sweep ;
std : : vector < std : : vector < double > > code_phase_error_sweep ;
2018-07-17 16:31:55 +00:00
std : : vector < std : : vector < double > > code_phase_error_meters_sweep ;
2018-06-20 16:42:06 +00:00
std : : vector < std : : vector < double > > acc_carrier_phase_error_sweep ;
std : : vector < double > mean_doppler_error ;
std : : vector < double > std_dev_doppler_error ;
2018-07-12 16:52:38 +00:00
std : : vector < double > rmse_doppler ;
2018-06-20 16:42:06 +00:00
std : : vector < double > mean_code_phase_error ;
std : : vector < double > std_dev_code_phase_error ;
2018-07-12 16:52:38 +00:00
std : : vector < double > rmse_code_phase ;
2018-06-20 16:42:06 +00:00
std : : vector < double > mean_carrier_phase_error ;
std : : vector < double > std_dev_carrier_phase_error ;
2018-07-12 16:52:38 +00:00
std : : vector < double > rmse_carrier_phase ;
2018-06-22 14:10:22 +00:00
std : : vector < double > valid_CN0_values ;
2018-06-20 16:42:06 +00:00
configure_receiver ( PLL_wide_bw_values . at ( config_idx ) ,
DLL_wide_bw_values . at ( config_idx ) ,
2018-06-22 14:10:22 +00:00
FLAGS_PLL_narrow_bw_hz ,
FLAGS_DLL_narrow_bw_hz ,
2018-06-20 16:42:06 +00:00
FLAGS_extend_correlation_symbols ) ;
2018-06-22 14:10:22 +00:00
for ( unsigned int current_cn0_idx = 0 ; current_cn0_idx < generator_CN0_values . size ( ) ; current_cn0_idx + + )
2018-06-20 16:42:06 +00:00
{
2019-08-18 23:29:04 +00:00
// ******************************************************************************************
// ***** Obtain the initial signal sinchronization parameters (emulating an acquisition) ****
// ******************************************************************************************
2018-06-20 16:42:06 +00:00
if ( ! FLAGS_enable_external_signal_file )
{
test_satellite_PRN = FLAGS_test_satellite_PRN ;
std : : string true_obs_file = std : : string ( " ./gps_l1_ca_obs_prn " ) ;
true_obs_file . append ( std : : to_string ( test_satellite_PRN ) ) ;
true_obs_file . append ( " .dat " ) ;
true_obs_data . close_obs_file ( ) ;
ASSERT_EQ ( true_obs_data . open_obs_file ( true_obs_file ) , true ) < < " Failure opening true observables file " ;
// load acquisition data based on the first epoch of the true observations
ASSERT_EQ ( true_obs_data . read_binary_obs ( ) , true )
< < " Failure reading true tracking dump file. " < < std : : endl
< < " 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 < < " Initial Doppler [Hz]= " < < true_obs_data . doppler_l1_hz < < " Initial code delay [Chips]= " < < true_obs_data . prn_delay_chips < < std : : endl ;
acq_doppler_hz = true_obs_data . doppler_l1_hz ;
2019-08-31 09:37:29 +00:00
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_S ;
2018-06-20 16:42:06 +00:00
// restart the epoch counter
true_obs_data . restart ( ) ;
}
2018-06-19 15:51:22 +00:00
2018-06-20 16:42:06 +00:00
std : : chrono : : time_point < std : : chrono : : system_clock > start , end ;
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_ ) ;
2020-04-02 21:59:35 +00:00
auto msg_rx = GpsL1CADllPllTrackingTest_msg_rx_make ( ) ;
2018-06-20 16:42:06 +00:00
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 ) ;
} ) < < " Failure setting channel. " ;
ASSERT_NO_THROW ( {
tracking - > set_gnss_synchro ( & gnss_synchro ) ;
} ) < < " Failure setting gnss_synchro. " ;
ASSERT_NO_THROW ( {
tracking - > connect ( top_block ) ;
} ) < < " Failure connecting tracking to the top_block. " ;
ASSERT_NO_THROW ( {
std : : string file = " ./ " + filename_raw_data + std : : to_string ( current_cn0_idx ) ;
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 ( ) ;
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 , 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 " ) ) ;
} ) < < " Failure connecting the blocks of tracking test. " ;
2019-08-18 23:29:04 +00:00
// ********************************************************************
// ***** STEP 5: Perform the signal tracking and read the results *****
// ********************************************************************
2018-06-22 14:10:22 +00:00
std : : cout < < " ------------ START TRACKING ------------- " < < std : : endl ;
2018-06-20 16:42:06 +00:00
tracking - > start_tracking ( ) ;
EXPECT_NO_THROW ( {
start = std : : chrono : : system_clock : : now ( ) ;
top_block - > run ( ) ; // Start threads and wait
end = std : : chrono : : system_clock : : now ( ) ;
} ) < < " Failure running the top_block. " ;
std : : chrono : : duration < double > elapsed_seconds = end - start ;
std : : cout < < " Signal tracking completed in " < < elapsed_seconds . count ( ) < < " seconds " < < std : : endl ;
2019-08-18 23:29:04 +00:00
int tracking_last_msg = msg_rx - > rx_message ; // save last aasynchronous tracking message in order to detect a loss of lock
2018-06-22 14:10:22 +00:00
2019-03-02 10:44:45 +00:00
// check results
// load the measured values
2019-02-22 14:57:15 +00:00
Tracking_Dump_Reader trk_dump ;
2018-06-20 16:42:06 +00:00
ASSERT_EQ ( trk_dump . open_obs_file ( std : : string ( " ./tracking_ch_0.dat " ) ) , true )
< < " Failure opening tracking dump file " ;
2018-08-10 19:16:10 +00:00
int64_t n_measured_epochs = trk_dump . num_epochs ( ) ;
2019-08-18 23:29:04 +00:00
// std::cout << "Measured observation epochs=" << n_measured_epochs << std::endl;
2018-06-20 16:42:06 +00:00
arma : : vec trk_timestamp_s = arma : : zeros ( n_measured_epochs , 1 ) ;
arma : : vec trk_acc_carrier_phase_cycles = arma : : zeros ( n_measured_epochs , 1 ) ;
arma : : vec trk_Doppler_Hz = arma : : zeros ( n_measured_epochs , 1 ) ;
arma : : vec trk_prn_delay_chips = arma : : zeros ( n_measured_epochs , 1 ) ;
2018-06-19 15:51:22 +00:00
2018-08-10 19:16:10 +00:00
int64_t epoch_counter = 0 ;
2018-06-20 16:42:06 +00:00
std : : vector < double > timestamp_s ;
std : : vector < double > prompt ;
std : : vector < double > early ;
std : : vector < double > late ;
std : : vector < double > promptI ;
std : : vector < double > promptQ ;
std : : vector < double > CN0_dBHz ;
while ( trk_dump . read_binary_obs ( ) )
2018-06-19 15:51:22 +00:00
{
2018-06-20 16:42:06 +00:00
trk_timestamp_s ( epoch_counter ) = static_cast < double > ( trk_dump . PRN_start_sample_count ) / static_cast < double > ( baseband_sampling_freq ) ;
trk_acc_carrier_phase_cycles ( epoch_counter ) = trk_dump . acc_carrier_phase_rad / GPS_TWO_PI ;
trk_Doppler_Hz ( epoch_counter ) = trk_dump . carrier_doppler_hz ;
double delay_chips = GPS_L1_CA_CODE_LENGTH_CHIPS - GPS_L1_CA_CODE_LENGTH_CHIPS * ( fmod ( ( static_cast < double > ( trk_dump . PRN_start_sample_count ) + trk_dump . aux1 ) / static_cast < double > ( baseband_sampling_freq ) , 1.0e-3 ) / 1.0e-3 ) ;
trk_prn_delay_chips ( epoch_counter ) = delay_chips ;
timestamp_s . push_back ( trk_timestamp_s ( epoch_counter ) ) ;
prompt . push_back ( trk_dump . abs_P ) ;
early . push_back ( trk_dump . abs_E ) ;
late . push_back ( trk_dump . abs_L ) ;
promptI . push_back ( trk_dump . prompt_I ) ;
promptQ . push_back ( trk_dump . prompt_Q ) ;
CN0_dBHz . push_back ( trk_dump . CN0_SNV_dB_Hz ) ;
2018-06-19 15:51:22 +00:00
epoch_counter + + ;
}
2018-06-20 16:42:06 +00:00
trk_timestamp_s_sweep . push_back ( timestamp_s ) ;
prompt_sweep . push_back ( prompt ) ;
early_sweep . push_back ( early ) ;
late_sweep . push_back ( late ) ;
promptI_sweep . push_back ( promptI ) ;
promptQ_sweep . push_back ( promptQ ) ;
CN0_dBHz_sweep . push_back ( CN0_dBHz ) ;
2019-08-18 23:29:04 +00:00
// ***********************************************************
// ***** STEP 6: Compare with true values (if available) *****
// ***********************************************************
2018-06-20 16:42:06 +00:00
if ( ! FLAGS_enable_external_signal_file )
{
std : : vector < double > doppler_error_hz ;
std : : vector < double > code_phase_error_chips ;
2018-07-17 16:31:55 +00:00
std : : vector < double > code_phase_error_meters ;
2018-06-20 16:42:06 +00:00
std : : vector < double > acc_carrier_phase_hz ;
2018-06-22 14:10:22 +00:00
2018-06-20 16:42:06 +00:00
try
{
// load the true values
2018-08-10 19:16:10 +00:00
int64_t n_true_epochs = true_obs_data . num_epochs ( ) ;
2019-08-18 23:29:04 +00:00
// std::cout << "True observation epochs=" << n_true_epochs << std::endl;
2018-06-20 16:42:06 +00:00
arma : : vec true_timestamp_s = arma : : zeros ( n_true_epochs , 1 ) ;
arma : : vec true_acc_carrier_phase_cycles = arma : : zeros ( n_true_epochs , 1 ) ;
arma : : vec true_Doppler_Hz = arma : : zeros ( n_true_epochs , 1 ) ;
arma : : vec true_prn_delay_chips = arma : : zeros ( n_true_epochs , 1 ) ;
arma : : vec true_tow_s = arma : : zeros ( n_true_epochs , 1 ) ;
2020-02-26 21:40:00 +00:00
epoch_counter = 0 ;
2018-06-20 16:42:06 +00:00
while ( true_obs_data . read_binary_obs ( ) )
{
true_timestamp_s ( epoch_counter ) = true_obs_data . signal_timestamp_s ;
true_acc_carrier_phase_cycles ( epoch_counter ) = true_obs_data . acc_carrier_phase_cycles ;
true_Doppler_Hz ( epoch_counter ) = true_obs_data . doppler_l1_hz ;
true_prn_delay_chips ( epoch_counter ) = true_obs_data . prn_delay_chips ;
true_tow_s ( epoch_counter ) = true_obs_data . tow ;
epoch_counter + + ;
}
// Align initial measurements and cut the tracking pull-in transitory
2018-07-12 16:52:38 +00:00
double pull_in_offset_s = FLAGS_skip_trk_transitory_s ;
2018-06-20 16:42:06 +00:00
arma : : uvec initial_meas_point = arma : : find ( trk_timestamp_s > = ( true_timestamp_s ( 0 ) + pull_in_offset_s ) , 1 , " first " ) ;
2019-02-11 17:38:42 +00:00
if ( ! initial_meas_point . empty ( ) and tracking_last_msg ! = 3 )
2018-06-22 14:10:22 +00:00
{
trk_timestamp_s = trk_timestamp_s . subvec ( initial_meas_point ( 0 ) , trk_timestamp_s . size ( ) - 1 ) ;
trk_acc_carrier_phase_cycles = trk_acc_carrier_phase_cycles . subvec ( initial_meas_point ( 0 ) , trk_acc_carrier_phase_cycles . size ( ) - 1 ) ;
trk_Doppler_Hz = trk_Doppler_Hz . subvec ( initial_meas_point ( 0 ) , trk_Doppler_Hz . size ( ) - 1 ) ;
trk_prn_delay_chips = trk_prn_delay_chips . subvec ( initial_meas_point ( 0 ) , trk_prn_delay_chips . size ( ) - 1 ) ;
2018-06-19 15:51:22 +00:00
2018-06-22 14:10:22 +00:00
double mean_error ;
double std_dev_error ;
2018-07-12 16:52:38 +00:00
double rmse ;
2018-06-20 10:04:03 +00:00
2019-08-18 23:29:04 +00:00
valid_CN0_values . push_back ( generator_CN0_values . at ( current_cn0_idx ) ) ; // save the current cn0 value (valid tracking)
2018-06-20 10:04:03 +00:00
2018-07-12 16:52:38 +00:00
doppler_error_hz = check_results_doppler ( true_timestamp_s , true_Doppler_Hz , trk_timestamp_s , trk_Doppler_Hz , mean_error , std_dev_error , rmse ) ;
2018-06-22 14:10:22 +00:00
mean_doppler_error . push_back ( mean_error ) ;
std_dev_doppler_error . push_back ( std_dev_error ) ;
2018-07-12 16:52:38 +00:00
rmse_doppler . push_back ( rmse ) ;
2018-06-20 10:04:03 +00:00
2018-07-12 16:52:38 +00:00
code_phase_error_chips = check_results_codephase ( true_timestamp_s , true_prn_delay_chips , trk_timestamp_s , trk_prn_delay_chips , mean_error , std_dev_error , rmse ) ;
2019-02-11 17:38:42 +00:00
for ( double code_phase_error_chip : code_phase_error_chips )
2018-07-17 16:31:55 +00:00
{
2019-08-31 09:37:29 +00:00
code_phase_error_meters . push_back ( GPS_L1_CA_CHIP_PERIOD_S * code_phase_error_chip * GPS_C_M_S ) ;
2018-07-17 16:31:55 +00:00
}
2018-06-22 14:10:22 +00:00
mean_code_phase_error . push_back ( mean_error ) ;
std_dev_code_phase_error . push_back ( std_dev_error ) ;
2018-07-12 16:52:38 +00:00
rmse_code_phase . push_back ( rmse ) ;
2018-06-20 10:04:03 +00:00
2018-07-12 16:52:38 +00:00
acc_carrier_phase_hz = check_results_acc_carrier_phase ( true_timestamp_s , true_acc_carrier_phase_cycles , trk_timestamp_s , trk_acc_carrier_phase_cycles , mean_error , std_dev_error , rmse ) ;
2018-06-22 14:10:22 +00:00
mean_carrier_phase_error . push_back ( mean_error ) ;
std_dev_carrier_phase_error . push_back ( std_dev_error ) ;
2018-07-12 16:52:38 +00:00
rmse_carrier_phase . push_back ( rmse ) ;
2018-06-20 10:04:03 +00:00
2019-08-18 23:29:04 +00:00
// save tracking measurement timestamps to std::vector
2018-06-22 14:10:22 +00:00
std : : vector < double > vector_trk_timestamp_s ( trk_timestamp_s . colptr ( 0 ) , trk_timestamp_s . colptr ( 0 ) + trk_timestamp_s . n_rows ) ;
trk_valid_timestamp_s_sweep . push_back ( vector_trk_timestamp_s ) ;
2018-06-20 16:42:06 +00:00
2018-06-22 14:10:22 +00:00
doppler_error_sweep . push_back ( doppler_error_hz ) ;
code_phase_error_sweep . push_back ( code_phase_error_chips ) ;
2018-07-17 16:31:55 +00:00
code_phase_error_meters_sweep . push_back ( code_phase_error_meters ) ;
2018-06-22 14:10:22 +00:00
acc_carrier_phase_error_sweep . push_back ( acc_carrier_phase_hz ) ;
}
else
{
std : : cout < < " Tracking output could not be used, possible loss of lock " < < std : : endl ;
}
2018-06-20 16:42:06 +00:00
}
catch ( const std : : exception & ex )
{
std : : cout < < " Tracking output could not be used, possible loss of lock " < < ex . what ( ) < < std : : endl ;
}
}
2019-08-18 23:29:04 +00:00
} // CN0 LOOP
2018-06-20 16:42:06 +00:00
if ( ! FLAGS_enable_external_signal_file )
{
mean_doppler_error_sweep . push_back ( mean_doppler_error ) ;
std_dev_doppler_error_sweep . push_back ( std_dev_doppler_error ) ;
2018-07-12 16:52:38 +00:00
rmse_doppler_sweep . push_back ( rmse_doppler ) ;
2018-06-20 16:42:06 +00:00
mean_code_phase_error_sweep . push_back ( mean_code_phase_error ) ;
std_dev_code_phase_error_sweep . push_back ( std_dev_code_phase_error ) ;
2018-07-12 16:52:38 +00:00
rmse_code_phase_sweep . push_back ( rmse_code_phase ) ;
2018-06-20 16:42:06 +00:00
mean_carrier_phase_error_sweep . push_back ( mean_carrier_phase_error ) ;
std_dev_carrier_phase_error_sweep . push_back ( std_dev_carrier_phase_error ) ;
2018-07-12 16:52:38 +00:00
rmse_carrier_phase_sweep . push_back ( rmse_carrier_phase ) ;
2019-08-18 23:29:04 +00:00
// make a copy of the CN0 vector for each configuration parameter in order to filter the loss of lock events
2018-06-22 14:10:22 +00:00
generator_CN0_values_sweep_copy . push_back ( valid_CN0_values ) ;
2018-06-19 15:51:22 +00:00
}
2017-02-02 17:10:24 +00:00
2019-08-18 23:29:04 +00:00
// ********************************
// ***** STEP 7: Plot results *****
// ********************************
2018-06-20 16:42:06 +00:00
if ( FLAGS_plot_gps_l1_tracking_test = = true )
{
const std : : string gnuplot_executable ( FLAGS_gnuplot_executable ) ;
if ( gnuplot_executable . empty ( ) )
{
std : : cout < < " WARNING: Although the flag plot_gps_l1_tracking_test 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
{
try
{
2019-06-10 19:41:13 +00:00
fs : : path p ( gnuplot_executable ) ;
fs : : path dir = p . parent_path ( ) ;
2019-02-11 17:38:42 +00:00
const std : : string & gnuplot_path = dir . native ( ) ;
2018-06-20 16:42:06 +00:00
Gnuplot : : set_GNUPlotPath ( gnuplot_path ) ;
2019-02-11 17:38:42 +00:00
auto decimate = static_cast < unsigned int > ( FLAGS_plot_decimate ) ;
2018-06-20 16:42:06 +00:00
2018-06-22 14:10:22 +00:00
if ( FLAGS_plot_detail_level > = 2 )
2018-06-20 16:42:06 +00:00
{
2018-06-22 14:10:22 +00:00
for ( unsigned int current_cn0_idx = 0 ; current_cn0_idx < generator_CN0_values . size ( ) ; current_cn0_idx + + )
2018-06-20 16:42:06 +00:00
{
Gnuplot g1 ( " linespoints " ) ;
2018-07-06 09:14:38 +00:00
if ( FLAGS_show_plots )
{
g1 . showonscreen ( ) ; // window output
}
else
{
g1 . disablescreen ( ) ;
}
2018-06-20 16:42:06 +00:00
g1 . set_title ( std : : to_string ( generator_CN0_values . at ( current_cn0_idx ) ) + " dB-Hz, " + " PLL/DLL BW: " + std : : to_string ( PLL_wide_bw_values . at ( config_idx ) ) + " , " + std : : to_string ( DLL_wide_bw_values . at ( config_idx ) ) + " 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 " ) ;
2019-08-18 23:29:04 +00:00
// g1.cmd("set key box opaque");
2018-06-20 16:42:06 +00:00
g1 . plot_xy ( trk_timestamp_s_sweep . at ( current_cn0_idx ) , prompt_sweep . at ( current_cn0_idx ) , " Prompt " , decimate ) ;
g1 . plot_xy ( trk_timestamp_s_sweep . at ( current_cn0_idx ) , early_sweep . at ( current_cn0_idx ) , " Early " , decimate ) ;
g1 . plot_xy ( trk_timestamp_s_sweep . at ( current_cn0_idx ) , late_sweep . at ( current_cn0_idx ) , " Late " , decimate ) ;
g1 . set_legend ( ) ;
g1 . savetops ( " Correlators_outputs " + std : : to_string ( generator_CN0_values . at ( current_cn0_idx ) ) ) ;
g1 . savetopdf ( " Correlators_outputs " + std : : to_string ( generator_CN0_values . at ( current_cn0_idx ) ) , 18 ) ;
}
Gnuplot g2 ( " points " ) ;
2018-07-06 09:14:38 +00:00
if ( FLAGS_show_plots )
{
g2 . showonscreen ( ) ; // window output
}
else
{
g2 . disablescreen ( ) ;
}
2018-06-20 16:42:06 +00:00
g2 . set_multiplot ( ceil ( static_cast < float > ( generator_CN0_values . size ( ) ) / 2.0 ) ,
ceil ( static_cast < float > ( generator_CN0_values . size ( ) ) / 2 ) ) ;
2018-06-22 14:10:22 +00:00
for ( unsigned int current_cn0_idx = 0 ; current_cn0_idx < generator_CN0_values . size ( ) ; current_cn0_idx + + )
2018-06-20 16:42:06 +00:00
{
g2 . reset_plot ( ) ;
g2 . set_title ( std : : to_string ( generator_CN0_values . at ( current_cn0_idx ) ) + " dB-Hz Constellation " + " PLL/DLL BW: " + std : : to_string ( PLL_wide_bw_values . at ( config_idx ) ) + " , " + std : : to_string ( DLL_wide_bw_values . at ( config_idx ) ) + " Hz " + " GPS L1 C/A (PRN # " + std : : to_string ( FLAGS_test_satellite_PRN ) + " ) " ) ;
g2 . set_grid ( ) ;
g2 . set_xlabel ( " Inphase " ) ;
g2 . set_ylabel ( " Quadrature " ) ;
2019-08-18 23:29:04 +00:00
// g2.cmd("set size ratio -1");
2018-06-20 16:42:06 +00:00
g2 . plot_xy ( promptI_sweep . at ( current_cn0_idx ) , promptQ_sweep . at ( current_cn0_idx ) ) ;
}
g2 . unset_multiplot ( ) ;
g2 . savetops ( " Constellation " ) ;
g2 . savetopdf ( " Constellation " , 18 ) ;
Gnuplot g3 ( " linespoints " ) ;
g3 . set_title ( " GPS L1 C/A tracking CN0 output (PRN # " + std : : to_string ( FLAGS_test_satellite_PRN ) + " ) " ) ;
g3 . set_grid ( ) ;
g3 . set_xlabel ( " Time [s] " ) ;
g3 . set_ylabel ( " Reported CN0 [dB-Hz] " ) ;
g3 . cmd ( " set key box opaque " ) ;
2018-06-22 14:10:22 +00:00
for ( unsigned int current_cn0_idx = 0 ; current_cn0_idx < generator_CN0_values . size ( ) ; current_cn0_idx + + )
2018-06-20 16:42:06 +00:00
{
g3 . plot_xy ( trk_timestamp_s_sweep . at ( current_cn0_idx ) , CN0_dBHz_sweep . at ( current_cn0_idx ) ,
std : : to_string ( static_cast < int > ( round ( generator_CN0_values . at ( current_cn0_idx ) ) ) ) + " [dB-Hz] " , decimate ) ;
}
g3 . set_legend ( ) ;
g3 . savetops ( " CN0_output " ) ;
g3 . savetopdf ( " CN0_output " , 18 ) ;
2018-07-06 09:14:38 +00:00
if ( FLAGS_show_plots )
{
g3 . showonscreen ( ) ; // window output
}
else
{
g3 . disablescreen ( ) ;
}
2018-06-20 16:42:06 +00:00
}
2019-03-02 10:44:45 +00:00
// PLOT ERROR FIGURES (only if it is used the signal generator)
2018-06-20 16:42:06 +00:00
if ( ! FLAGS_enable_external_signal_file )
{
2018-06-22 14:10:22 +00:00
if ( FLAGS_plot_detail_level > = 1 )
2018-06-20 16:42:06 +00:00
{
2018-06-22 14:10:22 +00:00
Gnuplot g5 ( " points " ) ;
2018-07-06 09:14:38 +00:00
if ( FLAGS_show_plots )
{
g5 . showonscreen ( ) ; // window output
}
else
{
g5 . disablescreen ( ) ;
}
2018-06-22 14:10:22 +00:00
g5 . set_title ( " Code delay error, PLL/DLL BW: " + std : : to_string ( PLL_wide_bw_values . at ( config_idx ) ) + " , " + std : : to_string ( DLL_wide_bw_values . at ( config_idx ) ) + " Hz (PRN # " + std : : to_string ( FLAGS_test_satellite_PRN ) + " ) " ) ;
g5 . set_grid ( ) ;
g5 . set_xlabel ( " Time [s] " ) ;
g5 . set_ylabel ( " Code delay error [Chips] " ) ;
for ( unsigned int current_cn0_idx = 0 ; current_cn0_idx < generator_CN0_values_sweep_copy . at ( config_idx ) . size ( ) ; current_cn0_idx + + )
{
try
{
g5 . plot_xy ( trk_valid_timestamp_s_sweep . at ( current_cn0_idx ) , code_phase_error_sweep . at ( current_cn0_idx ) ,
std : : to_string ( static_cast < int > ( round ( generator_CN0_values_sweep_copy . at ( config_idx ) . at ( current_cn0_idx ) ) ) ) + " [dB-Hz] " , decimate ) ;
}
catch ( const GnuplotException & ge )
{
}
2018-07-12 16:52:38 +00:00
save_mat_xy ( trk_valid_timestamp_s_sweep . at ( current_cn0_idx ) ,
code_phase_error_sweep . at ( current_cn0_idx ) ,
2018-07-17 16:31:55 +00:00
" Code_error_chips " + std : : to_string ( generator_CN0_values_sweep_copy . at ( config_idx ) . at ( current_cn0_idx ) ) +
2018-07-12 16:52:38 +00:00
std : : to_string ( PLL_wide_bw_values . at ( config_idx ) ) + " _ " + std : : to_string ( DLL_wide_bw_values . at ( config_idx ) ) ) ;
2018-06-22 14:10:22 +00:00
}
g5 . set_legend ( ) ;
g5 . set_legend ( ) ;
2018-07-17 16:31:55 +00:00
g5 . savetops ( " Code_error_chips " ) ;
g5 . savetopdf ( " Code_error_chips " , 18 ) ;
Gnuplot g5b ( " points " ) ;
if ( FLAGS_show_plots )
{
g5b . showonscreen ( ) ; // window output
}
else
{
g5b . disablescreen ( ) ;
}
g5b . set_title ( " Code delay error, PLL/DLL BW: " + std : : to_string ( PLL_wide_bw_values . at ( config_idx ) ) + " , " + std : : to_string ( DLL_wide_bw_values . at ( config_idx ) ) + " Hz (PRN # " + std : : to_string ( FLAGS_test_satellite_PRN ) + " ) " ) ;
g5b . set_grid ( ) ;
g5b . set_xlabel ( " Time [s] " ) ;
g5b . set_ylabel ( " Code delay error [meters] " ) ;
for ( unsigned int current_cn0_idx = 0 ; current_cn0_idx < generator_CN0_values_sweep_copy . at ( config_idx ) . size ( ) ; current_cn0_idx + + )
{
try
{
g5b . plot_xy ( trk_valid_timestamp_s_sweep . at ( current_cn0_idx ) , code_phase_error_meters_sweep . at ( current_cn0_idx ) ,
std : : to_string ( static_cast < int > ( round ( generator_CN0_values_sweep_copy . at ( config_idx ) . at ( current_cn0_idx ) ) ) ) + " [dB-Hz] " , decimate ) ;
}
catch ( const GnuplotException & ge )
{
}
save_mat_xy ( trk_valid_timestamp_s_sweep . at ( current_cn0_idx ) ,
code_phase_error_sweep . at ( current_cn0_idx ) ,
" Code_error_meters " + std : : to_string ( generator_CN0_values_sweep_copy . at ( config_idx ) . at ( current_cn0_idx ) ) +
std : : to_string ( PLL_wide_bw_values . at ( config_idx ) ) + " _ " + std : : to_string ( DLL_wide_bw_values . at ( config_idx ) ) ) ;
}
g5b . set_legend ( ) ;
g5b . set_legend ( ) ;
g5b . savetops ( " Code_error_meters " ) ;
g5b . savetopdf ( " Code_error_meters " , 18 ) ;
2018-06-22 14:10:22 +00:00
Gnuplot g6 ( " points " ) ;
2018-07-06 09:14:38 +00:00
if ( FLAGS_show_plots )
{
g6 . showonscreen ( ) ; // window output
}
else
{
g6 . disablescreen ( ) ;
}
2018-06-22 14:10:22 +00:00
g6 . set_title ( " Accumulated carrier phase error, PLL/DLL BW: " + std : : to_string ( PLL_wide_bw_values . at ( config_idx ) ) + " , " + std : : to_string ( DLL_wide_bw_values . at ( config_idx ) ) + " Hz (PRN # " + std : : to_string ( FLAGS_test_satellite_PRN ) + " ) " ) ;
g6 . set_grid ( ) ;
g6 . set_xlabel ( " Time [s] " ) ;
g6 . set_ylabel ( " Accumulated carrier phase error [Cycles] " ) ;
for ( unsigned int current_cn0_idx = 0 ; current_cn0_idx < generator_CN0_values_sweep_copy . at ( config_idx ) . size ( ) ; current_cn0_idx + + )
{
try
{
g6 . plot_xy ( trk_valid_timestamp_s_sweep . at ( current_cn0_idx ) , acc_carrier_phase_error_sweep . at ( current_cn0_idx ) ,
std : : to_string ( static_cast < int > ( round ( generator_CN0_values_sweep_copy . at ( config_idx ) . at ( current_cn0_idx ) ) ) ) + " [dB-Hz] " , decimate ) ;
}
catch ( const GnuplotException & ge )
{
}
2018-07-12 16:52:38 +00:00
save_mat_xy ( trk_valid_timestamp_s_sweep . at ( current_cn0_idx ) ,
acc_carrier_phase_error_sweep . at ( current_cn0_idx ) ,
2018-07-17 16:31:55 +00:00
" Carrier_phase_error " + std : : to_string ( generator_CN0_values_sweep_copy . at ( config_idx ) . at ( current_cn0_idx ) ) +
2018-07-12 16:52:38 +00:00
std : : to_string ( PLL_wide_bw_values . at ( config_idx ) ) + " _ " + std : : to_string ( DLL_wide_bw_values . at ( config_idx ) ) ) ;
2018-06-22 14:10:22 +00:00
}
g6 . set_legend ( ) ;
g6 . set_legend ( ) ;
2018-07-17 16:31:55 +00:00
g6 . savetops ( " Acc_carrier_phase_error_cycles " ) ;
g6 . savetopdf ( " Acc_carrier_phase_error_cycles " , 18 ) ;
2018-06-22 14:10:22 +00:00
Gnuplot g4 ( " points " ) ;
2018-07-06 09:14:38 +00:00
if ( FLAGS_show_plots )
{
g4 . showonscreen ( ) ; // window output
}
else
{
g4 . disablescreen ( ) ;
}
2018-06-22 14:10:22 +00:00
g4 . set_multiplot ( ceil ( static_cast < float > ( generator_CN0_values . size ( ) ) / 2.0 ) ,
ceil ( static_cast < float > ( generator_CN0_values . size ( ) ) / 2 ) ) ;
for ( unsigned int current_cn0_idx = 0 ; current_cn0_idx < generator_CN0_values_sweep_copy . at ( config_idx ) . size ( ) ; current_cn0_idx + + )
{
g4 . reset_plot ( ) ;
2018-07-12 16:52:38 +00:00
g4 . set_title ( " Dopper error " + std : : to_string ( static_cast < int > ( round ( generator_CN0_values_sweep_copy . at ( config_idx ) . at ( current_cn0_idx ) ) ) ) + " [dB-Hz], PLL/DLL BW: " + std : : to_string ( PLL_wide_bw_values . at ( config_idx ) ) + " , " + std : : to_string ( DLL_wide_bw_values . at ( config_idx ) ) + " Hz (PRN # " + std : : to_string ( FLAGS_test_satellite_PRN ) + " ) " ) ;
2018-06-22 14:10:22 +00:00
g4 . set_grid ( ) ;
2019-08-18 23:29:04 +00:00
// g4.cmd("set key box opaque");
2018-06-22 14:10:22 +00:00
g4 . set_xlabel ( " Time [s] " ) ;
g4 . set_ylabel ( " Dopper error [Hz] " ) ;
try
{
g4 . plot_xy ( trk_valid_timestamp_s_sweep . at ( current_cn0_idx ) , doppler_error_sweep . at ( current_cn0_idx ) ,
std : : to_string ( static_cast < int > ( round ( generator_CN0_values_sweep_copy . at ( config_idx ) . at ( current_cn0_idx ) ) ) ) + " [dB-Hz] " , decimate ) ;
}
catch ( const GnuplotException & ge )
{
}
2018-07-12 16:52:38 +00:00
save_mat_xy ( trk_valid_timestamp_s_sweep . at ( current_cn0_idx ) ,
doppler_error_sweep . at ( current_cn0_idx ) ,
2018-07-17 16:31:55 +00:00
" Doppler_error " + std : : to_string ( generator_CN0_values_sweep_copy . at ( config_idx ) . at ( current_cn0_idx ) ) +
2018-07-12 16:52:38 +00:00
std : : to_string ( PLL_wide_bw_values . at ( config_idx ) ) + " _ " + std : : to_string ( DLL_wide_bw_values . at ( config_idx ) ) ) ;
2018-06-22 14:10:22 +00:00
}
g4 . unset_multiplot ( ) ;
2018-07-17 16:31:55 +00:00
g4 . savetops ( " Doppler_error_hz " ) ;
g4 . savetopdf ( " Doppler_error_hz " , 18 ) ;
2018-06-20 16:42:06 +00:00
}
}
}
catch ( const GnuplotException & ge )
{
std : : cout < < ge . what ( ) < < std : : endl ;
}
}
}
}
2018-03-03 01:03:39 +00:00
if ( FLAGS_plot_gps_l1_tracking_test = = true )
2017-10-23 17:25:41 +00:00
{
2019-07-20 10:55:46 +00:00
std : : cout < < " Plotting performance metrics... " < < std : : endl ;
2018-06-22 14:10:22 +00:00
try
2017-10-23 17:25:41 +00:00
{
2018-06-22 14:10:22 +00:00
if ( generator_CN0_values . size ( ) > 1 )
2018-03-03 01:03:39 +00:00
{
2019-08-18 23:29:04 +00:00
// plot metrics
2018-06-22 14:10:22 +00:00
Gnuplot g7 ( " linespoints " ) ;
2018-07-06 09:14:38 +00:00
if ( FLAGS_show_plots )
{
g7 . showonscreen ( ) ; // window output
}
else
{
g7 . disablescreen ( ) ;
}
2018-06-22 14:10:22 +00:00
g7 . set_title ( " Doppler error metrics (PRN # " + std : : to_string ( FLAGS_test_satellite_PRN ) + " ) " ) ;
g7 . set_grid ( ) ;
g7 . set_xlabel ( " CN0 [dB-Hz] " ) ;
g7 . set_ylabel ( " Doppler error [Hz] " ) ;
g7 . set_pointsize ( 2 ) ;
g7 . cmd ( " set termoption lw 2 " ) ;
g7 . cmd ( " set key box opaque " ) ;
for ( unsigned int config_sweep_idx = 0 ; config_sweep_idx < mean_doppler_error_sweep . size ( ) ; config_sweep_idx + + )
2017-10-24 06:45:13 +00:00
{
2018-06-22 14:10:22 +00:00
g7 . plot_xy_err ( generator_CN0_values_sweep_copy . at ( config_sweep_idx ) ,
2018-07-16 14:23:41 +00:00
mean_doppler_error_sweep . at ( config_sweep_idx ) ,
2018-06-22 14:10:22 +00:00
std_dev_doppler_error_sweep . at ( config_sweep_idx ) ,
" PLL/DLL BW: " + std : : to_string ( PLL_wide_bw_values . at ( config_sweep_idx ) ) +
+ " , " + std : : to_string ( DLL_wide_bw_values . at ( config_sweep_idx ) ) + " Hz " ) ;
2018-07-12 16:52:38 +00:00
2019-08-18 23:29:04 +00:00
// matlab save
2018-07-12 16:52:38 +00:00
save_mat_xy ( generator_CN0_values_sweep_copy . at ( config_sweep_idx ) ,
rmse_doppler_sweep . at ( config_sweep_idx ) ,
" RMSE_Doppler_CN0_Sweep_PLL_DLL " + std : : to_string ( PLL_wide_bw_values . at ( config_sweep_idx ) ) +
+ " _ " + std : : to_string ( DLL_wide_bw_values . at ( config_sweep_idx ) ) ) ;
2018-06-19 15:51:22 +00:00
}
2018-06-22 14:10:22 +00:00
g7 . savetops ( " Doppler_error_metrics " ) ;
g7 . savetopdf ( " Doppler_error_metrics " , 18 ) ;
Gnuplot g8 ( " linespoints " ) ;
g8 . set_title ( " Accumulated carrier phase error metrics (PRN # " + std : : to_string ( FLAGS_test_satellite_PRN ) + " ) " ) ;
g8 . set_grid ( ) ;
g8 . set_xlabel ( " CN0 [dB-Hz] " ) ;
g8 . set_ylabel ( " Accumulated Carrier Phase error [Cycles] " ) ;
g8 . cmd ( " set key box opaque " ) ;
g8 . cmd ( " set termoption lw 2 " ) ;
g8 . set_pointsize ( 2 ) ;
for ( unsigned int config_sweep_idx = 0 ; config_sweep_idx < mean_doppler_error_sweep . size ( ) ; config_sweep_idx + + )
{
g8 . plot_xy_err ( generator_CN0_values_sweep_copy . at ( config_sweep_idx ) ,
mean_carrier_phase_error_sweep . at ( config_sweep_idx ) ,
std_dev_carrier_phase_error_sweep . at ( config_sweep_idx ) ,
" PLL/DLL BW: " + std : : to_string ( PLL_wide_bw_values . at ( config_sweep_idx ) ) +
+ " , " + std : : to_string ( DLL_wide_bw_values . at ( config_sweep_idx ) ) + " Hz " ) ;
2019-08-18 23:29:04 +00:00
// matlab save
2018-07-12 16:52:38 +00:00
save_mat_xy ( generator_CN0_values_sweep_copy . at ( config_sweep_idx ) ,
rmse_carrier_phase_sweep . at ( config_sweep_idx ) ,
" RMSE_Carrier_Phase_CN0_Sweep_PLL_DLL " + std : : to_string ( PLL_wide_bw_values . at ( config_sweep_idx ) ) +
+ " _ " + std : : to_string ( DLL_wide_bw_values . at ( config_sweep_idx ) ) ) ;
2018-06-22 14:10:22 +00:00
}
g8 . savetops ( " Carrier_error_metrics " ) ;
g8 . savetopdf ( " Carrier_error_metrics " , 18 ) ;
Gnuplot g9 ( " linespoints " ) ;
g9 . set_title ( " Code Phase error metrics (PRN # " + std : : to_string ( FLAGS_test_satellite_PRN ) + " ) " ) ;
g9 . set_grid ( ) ;
g9 . set_xlabel ( " CN0 [dB-Hz] " ) ;
g9 . set_ylabel ( " Code Phase error [Chips] " ) ;
g9 . cmd ( " set key box opaque " ) ;
g9 . cmd ( " set termoption lw 2 " ) ;
g9 . set_pointsize ( 2 ) ;
for ( unsigned int config_sweep_idx = 0 ; config_sweep_idx < mean_doppler_error_sweep . size ( ) ; config_sweep_idx + + )
{
g9 . plot_xy_err ( generator_CN0_values_sweep_copy . at ( config_sweep_idx ) ,
mean_code_phase_error_sweep . at ( config_sweep_idx ) ,
std_dev_code_phase_error_sweep . at ( config_sweep_idx ) ,
" PLL/DLL BW: " + std : : to_string ( PLL_wide_bw_values . at ( config_sweep_idx ) ) +
+ " , " + std : : to_string ( DLL_wide_bw_values . at ( config_sweep_idx ) ) + " Hz " ) ;
2019-08-18 23:29:04 +00:00
// matlab save
2018-07-12 16:52:38 +00:00
save_mat_xy ( generator_CN0_values_sweep_copy . at ( config_sweep_idx ) ,
rmse_code_phase_sweep . at ( config_sweep_idx ) ,
" RMSE_Code_Phase_CN0_Sweep_PLL_DLL " + std : : to_string ( PLL_wide_bw_values . at ( config_sweep_idx ) ) +
+ " _ " + std : : to_string ( DLL_wide_bw_values . at ( config_sweep_idx ) ) ) ;
2018-06-22 14:10:22 +00:00
}
g9 . savetops ( " Code_error_metrics " ) ;
g9 . savetopdf ( " Code_error_metrics " , 18 ) ;
2018-03-03 01:03:39 +00:00
}
2018-06-22 14:10:22 +00:00
}
catch ( const GnuplotException & ge )
{
std : : cout < < ge . what ( ) < < std : : endl ;
2017-10-23 17:25:41 +00:00
}
}
}
2018-07-12 16:52:38 +00:00
2019-03-02 10:44:45 +00:00
2018-07-12 16:52:38 +00:00
bool GpsL1CADllPllTrackingTest : : save_mat_xy ( std : : vector < double > & x , std : : vector < double > & y , std : : string filename )
{
try
{
// WRITE MAT FILE
mat_t * matfp ;
matvar_t * matvar ;
filename . erase ( filename . length ( ) - 4 , 4 ) ;
filename . append ( " .mat " ) ;
2019-02-11 17:38:42 +00:00
matfp = Mat_CreateVer ( filename . c_str ( ) , nullptr , MAT_FT_MAT73 ) ;
if ( reinterpret_cast < int64_t * > ( matfp ) ! = nullptr )
2018-07-12 16:52:38 +00:00
{
size_t dims [ 2 ] = { 1 , x . size ( ) } ;
matvar = Mat_VarCreate ( " x " , MAT_C_DOUBLE , MAT_T_DOUBLE , 2 , dims , & x [ 0 ] , 0 ) ;
Mat_VarWrite ( matfp , matvar , MAT_COMPRESSION_ZLIB ) ; // or MAT_COMPRESSION_NONE
Mat_VarFree ( matvar ) ;
matvar = Mat_VarCreate ( " y " , MAT_C_DOUBLE , MAT_T_DOUBLE , 2 , dims , & y [ 0 ] , 0 ) ;
Mat_VarWrite ( matfp , matvar , MAT_COMPRESSION_ZLIB ) ; // or MAT_COMPRESSION_NONE
Mat_VarFree ( matvar ) ;
}
Mat_Close ( matfp ) ;
return true ;
}
catch ( const std : : exception & ex )
{
return false ;
}
}