2017-04-12 15:04:51 +00:00
/*!
* \ file hybrid_observables_test . cc
* \ brief This class implements a tracking test for Galileo_E5a_DLL_PLL_Tracking
* implementation based on some input parameters .
* \ author Javier Arribas , 2015. jarribas ( at ) cttc . es
*
*
2020-07-28 14:57:15 +00:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2017-04-12 15:04:51 +00:00
*
2020-12-30 12:35:06 +00:00
* GNSS - SDR is a Global Navigation Satellite System software - defined receiver .
2017-04-12 15:04:51 +00:00
* This file is part of GNSS - SDR .
*
2020-12-30 12:35:06 +00:00
* Copyright ( C ) 2012 - 2020 ( see AUTHORS file for a list of contributors )
2020-02-08 00:20:02 +00:00
* SPDX - License - Identifier : GPL - 3.0 - or - later
2017-04-12 15:04:51 +00:00
*
2020-07-28 14:57:15 +00:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2017-04-12 15:04:51 +00:00
*/
2018-12-05 15:50:32 +00:00
# include "GPS_L1_CA.h"
# include "GPS_L2C.h"
# include "GPS_L5.h"
2018-12-10 13:24:42 +00:00
# include "Galileo_E1.h"
2018-12-05 15:50:32 +00:00
# include "Galileo_E5a.h"
2018-09-07 12:36:11 +00:00
# include "acquisition_msg_rx.h"
# include "galileo_e1_pcps_ambiguous_acquisition.h"
# include "galileo_e5a_noncoherent_iq_acquisition_caf.h"
2018-12-09 21:00:09 +00:00
# include "galileo_e5a_pcps_acquisition.h"
2018-09-07 12:36:11 +00:00
# include "glonass_l1_ca_pcps_acquisition.h"
# include "glonass_l2_ca_pcps_acquisition.h"
2018-12-09 21:00:09 +00:00
# include "gnss_block_factory.h"
# include "gnss_block_interface.h"
# include "gnss_satellite.h"
# include "gnss_sdr_sample_counter.h"
# include "gnss_synchro.h"
# include "gnuplot_i.h"
# include "gps_l1_ca_dll_pll_tracking.h"
# include "gps_l1_ca_pcps_acquisition.h"
2018-09-07 12:36:11 +00:00
# include "gps_l2_m_pcps_acquisition.h"
# include "gps_l5i_pcps_acquisition.h"
2019-07-20 10:55:46 +00:00
# include "hybrid_observables.h"
2017-04-12 15:04:51 +00:00
# include "in_memory_configuration.h"
2018-12-09 21:00:09 +00:00
# include "observable_tests_flags.h"
2017-04-12 15:04:51 +00:00
# include "observables_dump_reader.h"
# include "signal_generator_flags.h"
2018-12-09 21:00:09 +00:00
# include "telemetry_decoder_interface.h"
2018-07-17 16:31:55 +00:00
# include "test_flags.h"
2018-12-09 21:00:09 +00:00
# include "tlm_dump_reader.h"
# include "tracking_dump_reader.h"
# include "tracking_interface.h"
2018-08-07 18:16:43 +00:00
# include "tracking_tests_flags.h"
2018-12-09 21:00:09 +00:00
# include "tracking_true_obs_reader.h"
# include "true_observables_reader.h"
# include <armadillo>
2019-08-31 09:37:29 +00:00
# include <boost/lexical_cast.hpp>
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>
2018-12-10 13:24:42 +00:00
# include <gnuradio/filter/firdes.h>
2018-12-09 21:00:09 +00:00
# include <gnuradio/top_block.h>
2018-12-10 21:59:10 +00:00
# include <gtest/gtest.h>
# include <matio.h>
2021-10-30 03:43:22 +00:00
# include <pmt/pmt.h>
2018-12-10 21:59:10 +00:00
# include <chrono>
2019-11-12 16:49:18 +00:00
# include <cmath>
2018-12-10 21:59:10 +00:00
# include <exception>
2022-08-26 07:14:58 +00:00
# include <iomanip>
2018-12-09 21:00:09 +00:00
# include <unistd.h>
2019-02-11 17:38:42 +00:00
# include <utility>
2022-07-05 11:46:58 +00:00
# if GNSSTK_USES_GPSTK_NAMESPACE
2022-07-10 17:19:37 +00:00
# include <gpstk/GPSWeekSecond.hpp>
2022-07-05 11:46:58 +00:00
# include <gpstk/Rinex3ObsBase.hpp>
# include <gpstk/Rinex3ObsData.hpp>
# include <gpstk/Rinex3ObsHeader.hpp>
# include <gpstk/Rinex3ObsStream.hpp>
# include <gpstk/RinexUtilities.hpp>
namespace gnsstk = gpstk ;
# else
2022-07-10 17:19:37 +00:00
# include <gnsstk/GPSWeekSecond.hpp>
2022-07-05 11:46:58 +00:00
# include <gnsstk/Rinex3ObsBase.hpp>
# include <gnsstk/Rinex3ObsData.hpp>
# include <gnsstk/Rinex3ObsHeader.hpp>
# include <gnsstk/Rinex3ObsStream.hpp>
# include <gnsstk/RinexUtilities.hpp>
# endif
2021-10-30 03:43:22 +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
2021-10-30 03:43:22 +00:00
2018-12-10 13:24:42 +00:00
# ifdef GR_GREATER_38
# include <gnuradio/filter/fir_filter_blk.h>
# else
# include <gnuradio/filter/fir_filter_ccf.h>
# endif
2017-04-12 15:04:51 +00:00
2021-10-30 03:43:22 +00:00
# if PMT_USES_BOOST_ANY
namespace wht = boost ;
# else
namespace wht = std ;
# endif
2017-04-12 15:04:51 +00:00
// ######## GNURADIO BLOCK MESSAGE RECEVER FOR TRACKING MESSAGES #########
class HybridObservablesTest_msg_rx ;
2020-11-03 19:51:57 +00:00
using HybridObservablesTest_msg_rx_sptr = gnss_shared_ptr < HybridObservablesTest_msg_rx > ;
2020-05-18 20:50:34 +00:00
2017-04-12 15:04:51 +00:00
HybridObservablesTest_msg_rx_sptr HybridObservablesTest_msg_rx_make ( ) ;
2020-05-18 20:50:34 +00:00
2017-04-12 15:04:51 +00:00
class HybridObservablesTest_msg_rx : public gr : : block
{
private :
friend HybridObservablesTest_msg_rx_sptr HybridObservablesTest_msg_rx_make ( ) ;
2020-08-03 06:13:21 +00:00
void msg_handler_channel_events ( const pmt : : pmt_t msg ) ;
2017-04-12 15:04:51 +00:00
HybridObservablesTest_msg_rx ( ) ;
public :
int rx_message ;
2018-03-03 01:03:39 +00:00
~ HybridObservablesTest_msg_rx ( ) ; //!< Default destructor
2017-04-12 15:04:51 +00:00
} ;
2020-05-18 20:50:34 +00:00
2017-04-12 15:04:51 +00:00
HybridObservablesTest_msg_rx_sptr HybridObservablesTest_msg_rx_make ( )
{
return HybridObservablesTest_msg_rx_sptr ( new HybridObservablesTest_msg_rx ( ) ) ;
}
2020-05-18 20:50:34 +00:00
2020-08-03 06:13:21 +00:00
void HybridObservablesTest_msg_rx : : msg_handler_channel_events ( const pmt : : pmt_t msg )
2017-04-12 15:04:51 +00:00
{
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 ) ) ;
2017-04-12 15:04:51 +00:00
rx_message = message ;
2018-03-03 01:03:39 +00:00
}
2021-10-30 03:43:22 +00:00
catch ( const wht : : bad_any_cast & e )
2018-03-03 01:03:39 +00:00
{
2020-08-03 06:13:21 +00:00
LOG ( WARNING ) < < " msg_handler_channel_events Bad any_cast: " < < e . what ( ) ;
2017-04-12 15:04:51 +00:00
rx_message = 0 ;
2018-03-03 01:03:39 +00:00
}
2017-04-12 15:04:51 +00:00
}
2020-05-18 20:50:34 +00:00
2018-03-03 01:03:39 +00:00
HybridObservablesTest_msg_rx : : HybridObservablesTest_msg_rx ( ) : gr : : block ( " HybridObservablesTest_msg_rx " , gr : : io_signature : : make ( 0 , 0 , 0 ) , gr : : io_signature : : make ( 0 , 0 , 0 ) )
2017-04-12 15:04:51 +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-08-03 06:13:21 +00:00
[ this ] ( auto & & PH1 ) { msg_handler_channel_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-08-03 06:13:21 +00:00
boost : : bind ( & HybridObservablesTest_msg_rx : : msg_handler_channel_events , this , boost : : placeholders : : _1 ) ) ;
2020-05-18 20:50:34 +00:00
# else
2020-08-03 06:13:21 +00:00
boost : : bind ( & HybridObservablesTest_msg_rx : : msg_handler_channel_events , this , _1 ) ) ;
2020-05-18 20:50:34 +00:00
# endif
2020-04-26 06:41:49 +00:00
# endif
2017-04-12 15:04:51 +00:00
rx_message = 0 ;
}
2020-05-18 20:50:34 +00:00
2019-02-11 20:13:02 +00:00
HybridObservablesTest_msg_rx : : ~ HybridObservablesTest_msg_rx ( ) = default ;
2017-04-12 15:04:51 +00:00
// ###########################################################
// ######## GNURADIO BLOCK MESSAGE RECEVER FOR TLM MESSAGES #########
class HybridObservablesTest_tlm_msg_rx ;
2020-05-18 20:50:34 +00:00
2020-04-02 11:23:20 +00:00
using HybridObservablesTest_tlm_msg_rx_sptr = std : : shared_ptr < HybridObservablesTest_tlm_msg_rx > ;
2017-04-12 15:04:51 +00:00
2020-05-18 20:50:34 +00:00
2017-04-12 15:04:51 +00:00
HybridObservablesTest_tlm_msg_rx_sptr HybridObservablesTest_tlm_msg_rx_make ( ) ;
2020-05-18 20:50:34 +00:00
2017-04-12 15:04:51 +00:00
class HybridObservablesTest_tlm_msg_rx : public gr : : block
{
private :
friend HybridObservablesTest_tlm_msg_rx_sptr HybridObservablesTest_tlm_msg_rx_make ( ) ;
2020-08-03 06:13:21 +00:00
void msg_handler_channel_events ( const pmt : : pmt_t msg ) ;
2017-04-12 15:04:51 +00:00
HybridObservablesTest_tlm_msg_rx ( ) ;
public :
int rx_message ;
2018-03-03 01:03:39 +00:00
~ HybridObservablesTest_tlm_msg_rx ( ) ; //!< Default destructor
2017-04-12 15:04:51 +00:00
} ;
2020-02-11 20:47:13 +00:00
2017-04-12 15:04:51 +00:00
HybridObservablesTest_tlm_msg_rx_sptr HybridObservablesTest_tlm_msg_rx_make ( )
{
return HybridObservablesTest_tlm_msg_rx_sptr ( new HybridObservablesTest_tlm_msg_rx ( ) ) ;
}
2020-02-11 20:47:13 +00:00
2020-08-03 06:13:21 +00:00
void HybridObservablesTest_tlm_msg_rx : : msg_handler_channel_events ( const pmt : : pmt_t msg )
2017-04-12 15:04:51 +00:00
{
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 ) ) ;
2017-04-12 15:04:51 +00:00
rx_message = message ;
2018-03-03 01:03:39 +00:00
}
2021-10-30 03:43:22 +00:00
catch ( const wht : : bad_any_cast & e )
2018-03-03 01:03:39 +00:00
{
2020-08-03 06:13:21 +00:00
LOG ( WARNING ) < < " msg_handler_channel_events Bad any_cast: " < < e . what ( ) ;
2017-04-12 15:04:51 +00:00
rx_message = 0 ;
2018-03-03 01:03:39 +00:00
}
2017-04-12 15:04:51 +00:00
}
2020-02-11 20:47:13 +00:00
2018-03-03 01:03:39 +00:00
HybridObservablesTest_tlm_msg_rx : : HybridObservablesTest_tlm_msg_rx ( ) : gr : : block ( " HybridObservablesTest_tlm_msg_rx " , gr : : io_signature : : make ( 0 , 0 , 0 ) , gr : : io_signature : : make ( 0 , 0 , 0 ) )
2017-04-12 15:04:51 +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-08-03 06:13:21 +00:00
[ this ] ( auto & & PH1 ) { msg_handler_channel_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-08-03 06:13:21 +00:00
boost : : bind ( & HybridObservablesTest_tlm_msg_rx : : msg_handler_channel_events , this , boost : : placeholders : : _1 ) ) ;
2020-05-18 20:50:34 +00:00
# else
2020-08-03 06:13:21 +00:00
boost : : bind ( & HybridObservablesTest_tlm_msg_rx : : msg_handler_channel_events , this , _1 ) ) ;
2020-05-18 20:50:34 +00:00
# endif
2020-04-26 06:41:49 +00:00
# endif
2017-04-12 15:04:51 +00:00
rx_message = 0 ;
}
2020-02-11 20:47:13 +00:00
2019-02-11 20:13:02 +00:00
HybridObservablesTest_tlm_msg_rx : : ~ HybridObservablesTest_tlm_msg_rx ( ) = default ;
2017-04-12 15:04:51 +00:00
// ###########################################################
2018-03-03 01:03:39 +00:00
class HybridObservablesTest : public : : testing : : Test
2017-04-12 15:04:51 +00:00
{
public :
2018-12-05 15:50:32 +00:00
enum StringValue
{
evGPS_1C ,
evGPS_2S ,
evGPS_L5 ,
evSBAS_1C ,
evGAL_1B ,
evGAL_5X ,
evGLO_1G ,
evGLO_2G
} ;
std : : map < std : : string , StringValue > mapStringValues_ ;
2017-04-12 15:04:51 +00:00
std : : string generator_binary ;
std : : string p1 ;
std : : string p2 ;
std : : string p3 ;
std : : string p4 ;
std : : string p5 ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
std : : string implementation = FLAGS_trk_test_implementation ;
2017-09-02 09:24:44 +00:00
const int baseband_sampling_freq = FLAGS_fs_gen_sps ;
2017-04-12 15:04:51 +00:00
std : : string filename_rinex_obs = FLAGS_filename_rinex_obs ;
std : : string filename_raw_data = FLAGS_filename_raw_data ;
2024-04-29 06:27:33 +00:00
# else
std : : string implementation = absl : : GetFlag ( FLAGS_trk_test_implementation ) ;
const int baseband_sampling_freq = absl : : GetFlag ( FLAGS_fs_gen_sps ) ;
std : : string filename_rinex_obs = absl : : GetFlag ( FLAGS_filename_rinex_obs ) ;
std : : string filename_raw_data = absl : : GetFlag ( FLAGS_filename_raw_data ) ;
# endif
2017-04-12 15:04:51 +00:00
int configure_generator ( ) ;
int generate_signal ( ) ;
2018-07-17 16:31:55 +00:00
bool save_mat_xy ( std : : vector < double > & x , std : : vector < double > & y , std : : string filename ) ;
2017-08-03 15:58:11 +00:00
void check_results_carrier_phase (
2018-03-20 16:24:16 +00:00
arma : : mat & true_ch0 ,
arma : : vec & true_tow_s ,
arma : : mat & measured_ch0 ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title ) ;
2018-08-07 18:16:43 +00:00
void check_results_carrier_phase_double_diff (
2018-07-26 17:25:10 +00:00
arma : : mat & true_ch0 ,
2018-08-07 18:16:43 +00:00
arma : : mat & true_ch1 ,
arma : : vec & true_tow_ch0_s ,
arma : : vec & true_tow_ch1_s ,
arma : : mat & measured_ch0 ,
arma : : mat & measured_ch1 ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title ) ;
2018-08-07 18:16:43 +00:00
void check_results_carrier_doppler ( arma : : mat & true_ch0 ,
2018-07-26 17:25:10 +00:00
arma : : vec & true_tow_s ,
arma : : mat & measured_ch0 ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title ) ;
2018-08-07 18:16:43 +00:00
void check_results_carrier_doppler_double_diff (
arma : : mat & true_ch0 ,
arma : : mat & true_ch1 ,
arma : : vec & true_tow_ch0_s ,
arma : : vec & true_tow_ch1_s ,
arma : : mat & measured_ch0 ,
arma : : mat & measured_ch1 ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title ) ;
2018-07-26 17:25:10 +00:00
void check_results_code_pseudorange (
2018-03-20 16:24:16 +00:00
arma : : mat & true_ch0 ,
arma : : mat & true_ch1 ,
2018-08-07 18:16:43 +00:00
arma : : vec & true_tow_ch0_s ,
arma : : vec & true_tow_ch1_s ,
2018-03-20 16:24:16 +00:00
arma : : mat & measured_ch0 ,
2018-07-26 17:25:10 +00:00
arma : : mat & measured_ch1 ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title ) ;
2017-04-12 15:04:51 +00:00
2018-10-06 17:36:25 +00:00
void check_results_duplicated_satellite (
arma : : mat & measured_sat1 ,
arma : : mat & measured_sat2 ,
2018-10-15 15:02:43 +00:00
int ch_id ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title ) ;
2018-10-06 17:36:25 +00:00
2017-04-12 15:04:51 +00:00
HybridObservablesTest ( )
{
factory = std : : make_shared < GNSSBlockFactory > ( ) ;
config = std : : make_shared < InMemoryConfiguration > ( ) ;
item_size = sizeof ( gr_complex ) ;
2018-12-05 15:50:32 +00:00
mapStringValues_ [ " 1C " ] = evGPS_1C ;
mapStringValues_ [ " 2S " ] = evGPS_2S ;
mapStringValues_ [ " L5 " ] = evGPS_L5 ;
mapStringValues_ [ " 1B " ] = evGAL_1B ;
mapStringValues_ [ " 5X " ] = evGAL_5X ;
mapStringValues_ [ " 1G " ] = evGLO_1G ;
mapStringValues_ [ " 2G " ] = evGLO_2G ;
2017-04-12 15:04:51 +00:00
}
2019-02-11 20:13:02 +00:00
~ HybridObservablesTest ( ) = default ;
2017-04-12 15:04:51 +00:00
2018-08-07 18:16:43 +00:00
bool ReadRinexObs ( std : : vector < arma : : mat > * obs_vec , Gnss_Synchro gnss ) ;
bool acquire_signal ( ) ;
void configure_receiver (
double PLL_wide_bw_hz ,
double DLL_wide_bw_hz ,
double PLL_narrow_bw_hz ,
double DLL_narrow_bw_hz ,
2018-09-18 15:14:33 +00:00
int extend_correlation_symbols ,
uint32_t smoother_length ,
bool high_dyn ) ;
2017-04-12 15:04:51 +00:00
std : : shared_ptr < GNSSBlockFactory > factory ;
std : : shared_ptr < InMemoryConfiguration > config ;
2018-08-07 18:16:43 +00:00
Gnss_Synchro gnss_synchro_master ;
2018-07-26 17:25:10 +00:00
std : : vector < Gnss_Synchro > gnss_synchro_vec ;
2017-04-12 15:04:51 +00:00
size_t item_size ;
} ;
2020-02-11 20:47:13 +00:00
2017-04-12 15:04:51 +00:00
int HybridObservablesTest : : configure_generator ( )
{
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2017-04-12 15:04:51 +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-04-12 15:04:51 +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-03-03 01:03:39 +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 ; // 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]
2024-04-29 06:27:33 +00:00
# else
// Configure signal generator
generator_binary = absl : : GetFlag ( FLAGS_generator_binary ) ;
p1 = std : : string ( " -rinex_nav_file= " ) + absl : : GetFlag ( FLAGS_rinex_nav_file ) ;
if ( absl : : GetFlag ( FLAGS_dynamic_position ) . empty ( ) )
{
p2 = std : : string ( " -static_position= " ) + absl : : GetFlag ( FLAGS_static_position ) + std : : string ( " , " ) + std : : to_string ( absl : : GetFlag ( FLAGS_duration ) * 10 ) ;
}
else
{
p2 = std : : string ( " -obs_pos_file= " ) + std : : string ( absl : : GetFlag ( FLAGS_dynamic_position ) ) ;
}
p3 = std : : string ( " -rinex_obs_file= " ) + absl : : GetFlag ( FLAGS_filename_rinex_obs ) ; // RINEX 2.10 observation file output
p4 = std : : string ( " -sig_out_file= " ) + absl : : GetFlag ( FLAGS_filename_raw_data ) ; // Baseband signal output file. Will be stored in int8_t IQ multiplexed samples
p5 = std : : string ( " -sampling_freq= " ) + std : : to_string ( baseband_sampling_freq ) ; // Baseband sampling frequency [MSps]
# endif
2017-04-12 15:04:51 +00:00
return 0 ;
}
int HybridObservablesTest : : 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 ] , nullptr } ;
2017-04-12 15:04:51 +00:00
int pid ;
if ( ( pid = fork ( ) ) = = - 1 )
2019-02-11 20:13:02 +00:00
{
perror ( " fork err " ) ;
}
2017-04-12 15:04:51 +00:00
else if ( pid = = 0 )
{
execv ( & generator_binary [ 0 ] , parmList ) ;
2020-07-07 16:53:50 +00:00
std : : cout < < " Return not expected. Must be an execv err. \n " ;
2017-04-12 15:04:51 +00:00
std : : terminate ( ) ;
}
waitpid ( pid , & child_status , 0 ) ;
2020-07-07 16:53:50 +00:00
std : : cout < < " Signal and Observables RINEX and RAW files created. \n " ;
2017-04-12 15:04:51 +00:00
return 0 ;
}
2018-08-07 18:16:43 +00:00
bool HybridObservablesTest : : acquire_signal ( )
2017-04-12 15:04:51 +00:00
{
2018-08-07 18:16:43 +00:00
// 1. Setup GNU Radio flowgraph (file_source -> Acquisition_10m)
2020-02-26 21:40:00 +00:00
gr : : top_block_sptr top_block_acq ;
top_block_acq = gr : : make_top_block ( " Acquisition test " ) ;
2019-08-18 23:29:04 +00:00
int SV_ID = 1 ; // initial sv id
2018-08-07 18:16:43 +00:00
// Satellite signal definition
Gnss_Synchro tmp_gnss_synchro ;
tmp_gnss_synchro . Channel_ID = 0 ;
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 ) ) ;
2024-04-29 06:27:33 +00:00
// Enable automatic resampler for the acquisition, if required
# if USE_GLOG_AND_GFLAGS
2018-12-05 15:50:32 +00:00
if ( FLAGS_use_acquisition_resampler = = true )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_use_acquisition_resampler ) = = true )
# endif
2018-12-05 15:50:32 +00:00
{
config - > set_property ( " GNSS-SDR.use_acquisition_resampler " , " true " ) ;
}
2018-08-07 18:16:43 +00:00
config - > set_property ( " Acquisition.blocking_on_standby " , " true " ) ;
config - > set_property ( " Acquisition.blocking " , " true " ) ;
config - > set_property ( " Acquisition.dump " , " false " ) ;
config - > set_property ( " Acquisition.dump_filename " , " ./data/acquisition.dat " ) ;
std : : shared_ptr < AcquisitionInterface > acquisition ;
2017-04-12 15:04:51 +00:00
2018-08-07 18:16:43 +00:00
std : : string System_and_Signal ;
2018-12-05 15:50:32 +00:00
std : : string signal ;
2019-08-18 23:29:04 +00:00
// create the correspondign acquisition block according to the desired tracking signal
2019-02-11 17:38:42 +00:00
if ( implementation = = " GPS_L1_CA_DLL_PLL_Tracking " )
2018-08-07 18:16:43 +00:00
{
tmp_gnss_synchro . System = ' G ' ;
2018-12-05 15:50:32 +00:00
signal = " 1C " ;
2018-08-27 16:08:31 +00:00
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( tmp_gnss_synchro . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
2018-08-07 18:16:43 +00:00
tmp_gnss_synchro . PRN = SV_ID ;
System_and_Signal = " GPS L1 CA " ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( FLAGS_external_signal_acquisition_dwells ) ) ;
2024-04-29 06:27:33 +00:00
# else
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( absl : : GetFlag ( FLAGS_external_signal_acquisition_dwells ) ) ) ;
# endif
2018-08-07 18:16:43 +00:00
acquisition = std : : make_shared < GpsL1CaPcpsAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " Galileo_E1_DLL_PLL_VEML_Tracking " )
2018-08-07 18:16:43 +00:00
{
tmp_gnss_synchro . System = ' E ' ;
2018-12-05 15:50:32 +00:00
signal = " 1B " ;
2018-08-27 16:08:31 +00:00
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( tmp_gnss_synchro . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
2018-08-07 18:16:43 +00:00
tmp_gnss_synchro . PRN = SV_ID ;
System_and_Signal = " Galileo E1B " ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( FLAGS_external_signal_acquisition_dwells ) ) ;
2024-04-29 06:27:33 +00:00
# else
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( absl : : GetFlag ( FLAGS_external_signal_acquisition_dwells ) ) ) ;
# endif
2018-08-07 18:16:43 +00:00
acquisition = std : : make_shared < GalileoE1PcpsAmbiguousAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GPS_L2_M_DLL_PLL_Tracking " )
2018-08-07 18:16:43 +00:00
{
tmp_gnss_synchro . System = ' G ' ;
2018-12-05 15:50:32 +00:00
signal = " 2S " ;
2018-08-27 16:08:31 +00:00
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( tmp_gnss_synchro . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
2018-08-07 18:16:43 +00:00
tmp_gnss_synchro . PRN = SV_ID ;
System_and_Signal = " GPS L2CM " ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( FLAGS_external_signal_acquisition_dwells ) ) ;
2024-04-29 06:27:33 +00:00
# else
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( absl : : GetFlag ( FLAGS_external_signal_acquisition_dwells ) ) ) ;
# endif
2018-08-07 18:16:43 +00:00
acquisition = std : : make_shared < GpsL2MPcpsAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " Galileo_E5a_DLL_PLL_Tracking_b " )
2018-08-07 18:16:43 +00:00
{
tmp_gnss_synchro . System = ' E ' ;
2018-12-05 15:50:32 +00:00
signal = " 5X " ;
2018-08-27 16:08:31 +00:00
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( tmp_gnss_synchro . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
2018-08-07 18:16:43 +00:00
tmp_gnss_synchro . PRN = SV_ID ;
System_and_Signal = " Galileo E5a " ;
config - > set_property ( " Acquisition_5X.coherent_integration_time_ms " , " 1 " ) ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( FLAGS_external_signal_acquisition_dwells ) ) ;
2024-04-29 06:27:33 +00:00
# else
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( absl : : GetFlag ( FLAGS_external_signal_acquisition_dwells ) ) ) ;
# endif
2019-08-18 23:29:04 +00:00
config - > set_property ( " Acquisition.CAF_window_hz " , " 0 " ) ; // **Only for E5a** Resolves doppler ambiguity averaging the specified BW in the winner code delay. If set to 0 CAF filter is deactivated. Recommended value 3000 Hz
config - > set_property ( " Acquisition.Zero_padding " , " 0 " ) ; // **Only for E5a** Avoids power loss and doppler ambiguity in bit transitions by correlating one code with twice the input data length, ensuring that at least one full code is present without transitions. If set to 1 it is ON, if set to 0 it is OFF.
2018-08-07 18:16:43 +00:00
config - > set_property ( " Acquisition.bit_transition_flag " , " false " ) ;
acquisition = std : : make_shared < GalileoE5aNoncoherentIQAcquisitionCaf > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " Galileo_E5a_DLL_PLL_Tracking " )
2018-08-07 18:16:43 +00:00
{
tmp_gnss_synchro . System = ' E ' ;
2018-12-05 15:50:32 +00:00
signal = " 5X " ;
2018-08-27 16:08:31 +00:00
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( tmp_gnss_synchro . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
2018-08-07 18:16:43 +00:00
tmp_gnss_synchro . PRN = SV_ID ;
System_and_Signal = " Galileo E5a " ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( FLAGS_external_signal_acquisition_dwells ) ) ;
2024-04-29 06:27:33 +00:00
# else
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( absl : : GetFlag ( FLAGS_external_signal_acquisition_dwells ) ) ) ;
# endif
2018-08-07 18:16:43 +00:00
acquisition = std : : make_shared < GalileoE5aPcpsAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GPS_L5_DLL_PLL_Tracking " )
2018-08-07 18:16:43 +00:00
{
tmp_gnss_synchro . System = ' G ' ;
2018-12-05 15:50:32 +00:00
signal = " L5 " ;
2018-08-27 16:08:31 +00:00
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( tmp_gnss_synchro . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
2018-08-07 18:16:43 +00:00
tmp_gnss_synchro . PRN = SV_ID ;
System_and_Signal = " GPS L5I " ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( FLAGS_external_signal_acquisition_dwells ) ) ;
2024-04-29 06:27:33 +00:00
# else
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( absl : : GetFlag ( FLAGS_external_signal_acquisition_dwells ) ) ) ;
# endif
2018-08-07 18:16:43 +00:00
acquisition = std : : make_shared < GpsL5iPcpsAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
else
{
std : : cout < < " The test can not run with the selected tracking implementation \n " ;
throw ( std : : exception ( ) ) ;
}
acquisition - > set_gnss_synchro ( & tmp_gnss_synchro ) ;
acquisition - > set_channel ( 0 ) ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
acquisition - > set_doppler_max ( config - > property ( " Acquisition.doppler_max " , FLAGS_external_signal_acquisition_doppler_max_hz ) ) ;
acquisition - > set_doppler_step ( config - > property ( " Acquisition.doppler_step " , FLAGS_external_signal_acquisition_doppler_step_hz ) ) ;
acquisition - > set_threshold ( config - > property ( " Acquisition.threshold " , FLAGS_external_signal_acquisition_threshold ) ) ;
2024-04-29 06:27:33 +00:00
# else
acquisition - > set_doppler_max ( config - > property ( " Acquisition.doppler_max " , absl : : GetFlag ( FLAGS_external_signal_acquisition_doppler_max_hz ) ) ) ;
acquisition - > set_doppler_step ( config - > property ( " Acquisition.doppler_step " , absl : : GetFlag ( FLAGS_external_signal_acquisition_doppler_step_hz ) ) ) ;
acquisition - > set_threshold ( config - > property ( " Acquisition.threshold " , absl : : GetFlag ( FLAGS_external_signal_acquisition_threshold ) ) ) ;
# endif
2018-08-07 18:16:43 +00:00
acquisition - > init ( ) ;
acquisition - > set_local_code ( ) ;
acquisition - > set_state ( 1 ) ; // Ensure that acquisition starts at the first sample
2020-02-26 21:40:00 +00:00
acquisition - > connect ( top_block_acq ) ;
2018-08-07 18:16:43 +00:00
gr : : blocks : : file_source : : sptr file_source ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
std : : string file = FLAGS_signal_file ;
2024-04-29 06:27:33 +00:00
# else
std : : string file = absl : : GetFlag ( FLAGS_signal_file ) ;
# endif
2018-08-07 18:16:43 +00:00
const char * file_name = file . c_str ( ) ;
file_source = gr : : blocks : : file_source : : make ( sizeof ( int8_t ) , file_name , false ) ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2019-08-18 23:29:04 +00:00
file_source - > seek ( 2 * FLAGS_skip_samples , 0 ) ; // skip head. ibyte, two bytes per complex sample
2024-04-29 06:27:33 +00:00
# else
file_source - > seek ( 2 * absl : : GetFlag ( FLAGS_skip_samples ) , 0 ) ; // skip head. ibyte, two bytes per complex sample
# endif
2018-08-07 18:16:43 +00:00
gr : : blocks : : interleaved_char_to_complex : : sptr gr_interleaved_char_to_complex = gr : : blocks : : interleaved_char_to_complex : : make ( ) ;
2020-02-26 21:40:00 +00:00
top_block_acq - > connect ( file_source , 0 , gr_interleaved_char_to_complex , 0 ) ;
2018-12-05 15:50:32 +00:00
// Enable automatic resampler for the acquisition, if required
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-12-05 15:50:32 +00:00
if ( FLAGS_use_acquisition_resampler = = true )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_use_acquisition_resampler ) = = true )
# endif
2018-12-05 15:50:32 +00:00
{
2019-08-18 23:29:04 +00:00
// create acquisition resamplers if required
2018-12-05 15:50:32 +00:00
double resampler_ratio = 1.0 ;
double opt_fs = baseband_sampling_freq ;
2019-08-18 23:29:04 +00:00
// find the signal associated to this channel
2018-12-05 15:50:32 +00:00
switch ( mapStringValues_ [ signal ] )
{
case evGPS_1C :
2019-08-31 09:37:29 +00:00
opt_fs = GPS_L1_CA_OPT_ACQ_FS_SPS ;
2018-12-05 15:50:32 +00:00
break ;
case evGPS_2S :
2019-08-31 09:37:29 +00:00
opt_fs = GPS_L2C_OPT_ACQ_FS_SPS ;
2018-12-05 15:50:32 +00:00
break ;
case evGPS_L5 :
2019-08-31 09:37:29 +00:00
opt_fs = GPS_L5_OPT_ACQ_FS_SPS ;
2018-12-05 15:50:32 +00:00
break ;
case evSBAS_1C :
2019-08-31 09:37:29 +00:00
opt_fs = GPS_L1_CA_OPT_ACQ_FS_SPS ;
2018-12-05 15:50:32 +00:00
break ;
case evGAL_1B :
2019-08-31 09:37:29 +00:00
opt_fs = GALILEO_E1_OPT_ACQ_FS_SPS ;
2018-12-05 15:50:32 +00:00
break ;
case evGAL_5X :
2019-08-31 09:37:29 +00:00
opt_fs = GALILEO_E5A_OPT_ACQ_FS_SPS ;
2018-12-05 15:50:32 +00:00
break ;
case evGLO_1G :
opt_fs = baseband_sampling_freq ;
break ;
case evGLO_2G :
opt_fs = baseband_sampling_freq ;
break ;
}
if ( opt_fs < baseband_sampling_freq )
{
resampler_ratio = baseband_sampling_freq / opt_fs ;
int decimation = floor ( resampler_ratio ) ;
while ( baseband_sampling_freq % decimation > 0 )
{
decimation - - ;
} ;
double acq_fs = baseband_sampling_freq / decimation ;
if ( decimation > 1 )
{
2019-08-18 23:29:04 +00:00
// create a FIR low pass filter
2018-12-05 15:50:32 +00:00
std : : vector < float > taps ;
taps = gr : : filter : : firdes : : low_pass ( 1.0 ,
baseband_sampling_freq ,
acq_fs / 2.1 ,
2020-12-19 11:40:57 +00:00
acq_fs / 10 ) ;
2020-07-07 16:53:50 +00:00
std : : cout < < " Enabled decimation low pass filter with " < < taps . size ( ) < < " taps and decimation factor of " < < decimation < < ' \n ' ;
2018-12-05 15:50:32 +00:00
acquisition - > set_resampler_latency ( ( taps . size ( ) - 1 ) / 2 ) ;
gr : : basic_block_sptr fir_filter_ccf_ = gr : : filter : : fir_filter_ccf : : make ( decimation , taps ) ;
2020-02-26 21:40:00 +00:00
top_block_acq - > connect ( gr_interleaved_char_to_complex , 0 , fir_filter_ccf_ , 0 ) ;
top_block_acq - > connect ( fir_filter_ccf_ , 0 , acquisition - > get_left_block ( ) , 0 ) ;
2018-12-05 15:50:32 +00:00
}
else
{
std : : cout < < " Disabled acquisition resampler because the input sampling frequency is too low \n " ;
2020-02-26 21:40:00 +00:00
top_block_acq - > connect ( gr_interleaved_char_to_complex , 0 , acquisition - > get_left_block ( ) , 0 ) ;
2018-12-05 15:50:32 +00:00
}
}
else
{
std : : cout < < " Disabled acquisition resampler because the input sampling frequency is too low \n " ;
2020-02-26 21:40:00 +00:00
top_block_acq - > connect ( gr_interleaved_char_to_complex , 0 , acquisition - > get_left_block ( ) , 0 ) ;
2018-12-05 15:50:32 +00:00
}
}
else
{
2020-02-26 21:40:00 +00:00
top_block_acq - > connect ( gr_interleaved_char_to_complex , 0 , acquisition - > get_left_block ( ) , 0 ) ;
// top_block_acq->connect(head_samples, 0, acquisition->get_left_block(), 0);
2018-12-05 15:50:32 +00:00
}
2020-11-03 19:51:57 +00:00
gnss_shared_ptr < Acquisition_msg_rx > msg_rx ;
2018-08-07 18:16:43 +00:00
try
{
msg_rx = Acquisition_msg_rx_make ( ) ;
}
catch ( const std : : exception & e )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Failure connecting the message port system: " < < e . what ( ) < < ' \n ' ;
2018-08-07 18:16:43 +00:00
exit ( 0 ) ;
}
2020-02-26 21:40:00 +00:00
msg_rx - > top_block = top_block_acq ;
top_block_acq - > msg_connect ( acquisition - > get_right_block ( ) , pmt : : mp ( " events " ) , msg_rx , pmt : : mp ( " events " ) ) ;
2018-08-07 18:16:43 +00:00
// 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 ;
unsigned int MAX_PRN_IDX = 0 ;
switch ( tmp_gnss_synchro . System )
{
case ' G ' :
MAX_PRN_IDX = 33 ;
break ;
case ' E ' :
MAX_PRN_IDX = 37 ;
break ;
default :
MAX_PRN_IDX = 33 ;
}
for ( unsigned int PRN = 1 ; PRN < MAX_PRN_IDX ; PRN + + )
{
tmp_gnss_synchro . PRN = PRN ;
acquisition - > set_gnss_synchro ( & tmp_gnss_synchro ) ;
acquisition - > init ( ) ;
acquisition - > set_local_code ( ) ;
acquisition - > reset ( ) ;
acquisition - > set_state ( 1 ) ;
msg_rx - > rx_message = 0 ;
2020-02-26 21:40:00 +00:00
top_block_acq - > run ( ) ;
2018-08-07 18:16:43 +00:00
if ( start_msg = = true )
{
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2020-07-07 16:53:50 +00:00
std : : cout < < " Reading external signal file: " < < FLAGS_signal_file < < ' \n ' ;
2024-04-29 06:27:33 +00:00
# else
std : : cout < < " Reading external signal file: " < < absl : : GetFlag ( FLAGS_signal_file ) < < ' \n ' ;
# endif
2020-07-07 16:53:50 +00:00
std : : cout < < " Searching for " < < System_and_Signal < < " Satellites... \n " ;
2018-08-07 18:16:43 +00:00
std : : cout < < " [ " ;
start_msg = false ;
}
while ( msg_rx - > rx_message = = 0 )
{
usleep ( 100000 ) ;
}
if ( msg_rx - > rx_message = = 1 )
{
std : : cout < < " " < < PRN < < " " ;
gnss_synchro_vec . push_back ( tmp_gnss_synchro ) ;
}
else
{
std : : cout < < " . " ;
}
2020-02-26 21:40:00 +00:00
top_block_acq - > stop ( ) ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2019-08-18 23:29:04 +00:00
file_source - > seek ( 2 * FLAGS_skip_samples , 0 ) ; // skip head. ibyte, two bytes per complex sample
2024-04-29 06:27:33 +00:00
# else
file_source - > seek ( 2 * absl : : GetFlag ( FLAGS_skip_samples ) , 0 ) ; // skip head. ibyte, two bytes per complex sample
# endif
2018-08-07 18:16:43 +00:00
std : : cout . flush ( ) ;
}
2020-07-07 16:53:50 +00:00
std : : cout < < " ] \n " ;
2018-08-07 18:16:43 +00:00
std : : cout < < " ------------------------------------------- \n " ;
for ( auto & x : gnss_synchro_vec )
{
std : : cout < < " DETECTED SATELLITE " < < System_and_Signal
< < " PRN: " < < x . PRN
< < " with Doppler: " < < x . Acq_doppler_hz
< < " [Hz], code phase: " < < x . Acq_delay_samples
< < " [samples] at signal SampleStamp " < < x . Acq_samplestamp_samples < < " \n " ;
}
// report the elapsed time
end = std : : chrono : : system_clock : : now ( ) ;
elapsed_seconds = end - start ;
std : : cout < < " Total signal acquisition run time "
< < elapsed_seconds . count ( )
2020-07-07 16:53:50 +00:00
< < " [seconds] \n " ;
2019-02-11 17:38:42 +00:00
if ( ! gnss_synchro_vec . empty ( ) )
2018-08-07 18:16:43 +00:00
{
return true ;
}
else
{
return false ;
}
}
void HybridObservablesTest : : configure_receiver (
double PLL_wide_bw_hz ,
double DLL_wide_bw_hz ,
double PLL_narrow_bw_hz ,
double DLL_narrow_bw_hz ,
2018-09-18 15:14:33 +00:00
int extend_correlation_symbols ,
uint32_t smoother_length ,
bool high_dyn )
2018-08-07 18:16:43 +00:00
{
config = std : : make_shared < InMemoryConfiguration > ( ) ;
2018-09-18 15:14:33 +00:00
if ( high_dyn )
2019-02-11 20:13:02 +00:00
{
config - > set_property ( " Tracking.high_dyn " , " true " ) ;
}
2018-09-18 15:14:33 +00:00
else
2019-02-11 20:13:02 +00:00
{
config - > set_property ( " Tracking.high_dyn " , " false " ) ;
}
2018-08-07 18:16:43 +00:00
config - > set_property ( " Tracking.implementation " , implementation ) ;
config - > set_property ( " Tracking.item_type " , " gr_complex " ) ;
config - > set_property ( " Tracking.pll_bw_hz " , std : : to_string ( PLL_wide_bw_hz ) ) ;
config - > set_property ( " Tracking.dll_bw_hz " , std : : to_string ( DLL_wide_bw_hz ) ) ;
config - > set_property ( " Tracking.extend_correlation_symbols " , std : : to_string ( extend_correlation_symbols ) ) ;
config - > set_property ( " Tracking.pll_bw_narrow_hz " , std : : to_string ( PLL_narrow_bw_hz ) ) ;
config - > set_property ( " Tracking.dll_bw_narrow_hz " , std : : to_string ( DLL_narrow_bw_hz ) ) ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2019-11-14 11:15:41 +00:00
config - > set_property ( " Tracking.fll_bw_hz " , std : : to_string ( FLAGS_fll_bw_hz ) ) ;
config - > set_property ( " Tracking.enable_fll_pull_in " , FLAGS_enable_fll_pull_in ? " true " : " false " ) ;
config - > set_property ( " Tracking.enable_fll_steady_state " , FLAGS_enable_fll_steady_state ? " true " : " false " ) ;
2024-04-29 06:27:33 +00:00
# else
config - > set_property ( " Tracking.fll_bw_hz " , std : : to_string ( absl : : GetFlag ( FLAGS_fll_bw_hz ) ) ) ;
config - > set_property ( " Tracking.enable_fll_pull_in " , absl : : GetFlag ( FLAGS_enable_fll_pull_in ) ? " true " : " false " ) ;
config - > set_property ( " Tracking.enable_fll_steady_state " , absl : : GetFlag ( FLAGS_enable_fll_steady_state ) ? " true " : " false " ) ;
# endif
2019-11-14 11:15:41 +00:00
config - > set_property ( " Tracking.smoother_length " , std : : to_string ( smoother_length ) ) ;
config - > set_property ( " Tracking.dump " , " true " ) ;
config - > set_property ( " Tracking.dump_filename " , " ./tracking_ch_ " ) ;
2018-08-07 18:16:43 +00:00
config - > set_property ( " Observables.implementation " , " Hybrid_Observables " ) ;
2018-03-03 01:03:39 +00:00
config - > set_property ( " Observables.dump " , " true " ) ;
2018-08-07 18:16:43 +00:00
config - > set_property ( " TelemetryDecoder.dump " , " true " ) ;
gnss_synchro_master . Channel_ID = 0 ;
config - > set_property ( " GNSS-SDR.internal_fs_sps " , std : : to_string ( baseband_sampling_freq ) ) ;
std : : string System_and_Signal ;
2019-02-11 17:38:42 +00:00
if ( implementation = = " GPS_L1_CA_DLL_PLL_Tracking " )
2018-08-07 18:16:43 +00:00
{
gnss_synchro_master . System = ' G ' ;
std : : string signal = " 1C " ;
System_and_Signal = " GPS L1 CA " ;
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( gnss_synchro_master . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
config - > set_property ( " Tracking.early_late_space_chips " , " 0.5 " ) ;
2019-11-14 11:15:41 +00:00
config - > set_property ( " Tracking.early_late_space_narrow_chips " , " 0.1 " ) ;
2018-08-07 18:16:43 +00:00
config - > set_property ( " TelemetryDecoder.implementation " , " GPS_L1_CA_Telemetry_Decoder " ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " Galileo_E1_DLL_PLL_VEML_Tracking " )
2018-08-07 18:16:43 +00:00
{
gnss_synchro_master . System = ' E ' ;
std : : string signal = " 1B " ;
System_and_Signal = " Galileo E1B " ;
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( gnss_synchro_master . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
config - > set_property ( " Tracking.early_late_space_chips " , " 0.15 " ) ;
2019-07-16 15:41:12 +00:00
config - > set_property ( " Tracking.very_early_late_space_chips " , " 0.5 " ) ;
2018-08-07 18:16:43 +00:00
config - > set_property ( " Tracking.early_late_space_narrow_chips " , " 0.15 " ) ;
2019-07-16 15:41:12 +00:00
config - > set_property ( " Tracking.very_early_late_space_narrow_chips " , " 0.5 " ) ;
2018-08-07 18:16:43 +00:00
config - > set_property ( " Tracking.track_pilot " , " true " ) ;
config - > set_property ( " TelemetryDecoder.implementation " , " Galileo_E1B_Telemetry_Decoder " ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GPS_L2_M_DLL_PLL_Tracking " )
2018-08-07 18:16:43 +00:00
{
gnss_synchro_master . System = ' G ' ;
std : : string signal = " 2S " ;
System_and_Signal = " GPS L2CM " ;
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( gnss_synchro_master . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
config - > set_property ( " Tracking.early_late_space_chips " , " 0.5 " ) ;
2018-08-27 16:08:31 +00:00
config - > set_property ( " Tracking.track_pilot " , " true " ) ;
2018-08-07 18:16:43 +00:00
config - > set_property ( " TelemetryDecoder.implementation " , " GPS_L2C_Telemetry_Decoder " ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " Galileo_E5a_DLL_PLL_Tracking " or implementation = = " Galileo_E5a_DLL_PLL_Tracking_b " )
2018-08-07 18:16:43 +00:00
{
gnss_synchro_master . System = ' E ' ;
std : : string signal = " 5X " ;
System_and_Signal = " Galileo E5a " ;
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( gnss_synchro_master . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
2019-02-11 17:38:42 +00:00
if ( implementation = = " Galileo_E5a_DLL_PLL_Tracking_b " )
2018-08-07 18:16:43 +00:00
{
config - > supersede_property ( " Tracking.implementation " , std : : string ( " Galileo_E5a_DLL_PLL_Tracking " ) ) ;
}
config - > set_property ( " Tracking.early_late_space_chips " , " 0.5 " ) ;
2018-08-27 16:08:31 +00:00
config - > set_property ( " Tracking.track_pilot " , " true " ) ;
2020-02-11 20:47:13 +00:00
// config->set_property("Tracking.pll_filter_order", "2");
// config->set_property("Tracking.dll_filter_order", "2");
2018-08-07 18:16:43 +00:00
config - > set_property ( " TelemetryDecoder.implementation " , " Galileo_E5a_Telemetry_Decoder " ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GPS_L5_DLL_PLL_Tracking " )
2018-08-07 18:16:43 +00:00
{
gnss_synchro_master . System = ' G ' ;
std : : string signal = " L5 " ;
System_and_Signal = " GPS L5I " ;
const char * str = signal . c_str ( ) ; // get a C style null terminated string
std : : memcpy ( static_cast < void * > ( gnss_synchro_master . Signal ) , str , 3 ) ; // copy string into synchro char array: 2 char + null
config - > set_property ( " Tracking.early_late_space_chips " , " 0.5 " ) ;
2018-08-27 16:08:31 +00:00
config - > set_property ( " Tracking.track_pilot " , " true " ) ;
2020-02-11 20:47:13 +00:00
// config->set_property("Tracking.pll_filter_order", "2");
// config->set_property("Tracking.dll_filter_order", "2");
2018-08-07 18:16:43 +00:00
config - > set_property ( " TelemetryDecoder.implementation " , " GPS_L5_Telemetry_Decoder " ) ;
}
else
{
std : : cout < < " The test can not run with the selected tracking implementation \n " ;
throw ( std : : exception ( ) ) ;
}
std : : cout < < " ***************************************** \n " ;
std : : cout < < " *** Tracking configuration parameters *** \n " ;
std : : cout < < " ***************************************** \n " ;
std : : cout < < " Signal: " < < System_and_Signal < < " \n " ;
std : : cout < < " implementation: " < < config - > property ( " Tracking.implementation " , std : : string ( " undefined " ) ) < < " \n " ;
std : : cout < < " pll_bw_hz: " < < config - > property ( " Tracking.pll_bw_hz " , 0.0 ) < < " Hz \n " ;
std : : cout < < " dll_bw_hz: " < < config - > property ( " Tracking.dll_bw_hz " , 0.0 ) < < " Hz \n " ;
2019-11-14 11:15:41 +00:00
std : : cout < < " fll_bw_hz: " < < config - > property ( " Tracking.fll_bw_hz " , 0.0 ) < < " Hz \n " ;
std : : cout < < " enable_fll_pull_in: " < < config - > property ( " Tracking.enable_fll_pull_in " , false ) < < " \n " ;
std : : cout < < " enable_fll_steady_state: " < < config - > property ( " Tracking.enable_fll_steady_state " , false ) < < " \n " ;
2018-08-07 18:16:43 +00:00
std : : cout < < " pll_bw_narrow_hz: " < < config - > property ( " Tracking.pll_bw_narrow_hz " , 0.0 ) < < " Hz \n " ;
std : : cout < < " dll_bw_narrow_hz: " < < config - > property ( " Tracking.dll_bw_narrow_hz " , 0.0 ) < < " Hz \n " ;
std : : cout < < " extend_correlation_symbols: " < < config - > property ( " Tracking.extend_correlation_symbols " , 0 ) < < " Symbols \n " ;
2018-09-18 22:59:13 +00:00
std : : cout < < " high_dyn: " < < config - > property ( " Tracking.high_dyn " , false ) < < " \n " ;
std : : cout < < " smoother_length: " < < config - > property ( " Tracking.smoother_length " , 0 ) < < " \n " ;
2018-08-07 18:16:43 +00:00
std : : cout < < " ***************************************** \n " ;
std : : cout < < " ***************************************** \n " ;
2017-04-12 15:04:51 +00:00
}
2019-11-14 11:15:41 +00:00
2017-08-03 15:58:11 +00:00
void HybridObservablesTest : : check_results_carrier_phase (
2018-03-20 16:24:16 +00:00
arma : : mat & true_ch0 ,
arma : : vec & true_tow_s ,
arma : : mat & measured_ch0 ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title )
2017-08-03 15:58:11 +00:00
{
2019-08-18 23:29:04 +00:00
// 1. True value interpolation to match the measurement times
2018-07-26 17:25:10 +00:00
double t0 = measured_ch0 ( 0 , 0 ) ;
2018-02-26 11:33:40 +00:00
int size1 = measured_ch0 . col ( 0 ) . n_rows ;
2018-07-26 17:25:10 +00:00
double t1 = measured_ch0 ( size1 - 1 , 0 ) ;
2018-02-26 11:33:40 +00:00
arma : : vec t = arma : : linspace < arma : : vec > ( t0 , t1 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2018-07-26 17:25:10 +00:00
arma : : vec t_from_start = arma : : linspace < arma : : vec > ( 0 , t1 - t0 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
std : : vector < double > time_vector ( t_from_start . colptr ( 0 ) , t_from_start . colptr ( 0 ) + t_from_start . n_rows ) ;
2018-02-26 11:33:40 +00:00
2017-08-03 15:58:11 +00:00
arma : : vec true_ch0_phase_interp ;
2018-02-26 11:33:40 +00:00
arma : : interp1 ( true_tow_s , true_ch0 . col ( 3 ) , t , true_ch0_phase_interp ) ;
arma : : vec meas_ch0_phase_interp ;
arma : : interp1 ( measured_ch0 . col ( 0 ) , measured_ch0 . col ( 3 ) , t , meas_ch0_phase_interp ) ;
2017-08-03 15:58:11 +00:00
2019-08-18 23:29:04 +00:00
// 2. RMSE
2017-08-03 15:58:11 +00:00
arma : : vec err_ch0_cycles ;
2019-08-18 23:29:04 +00:00
// compute error without the accumulated carrier phase offsets (which depends on the receiver starting time)
2018-02-26 11:33:40 +00:00
err_ch0_cycles = meas_ch0_phase_interp - true_ch0_phase_interp - meas_ch0_phase_interp ( 0 ) + true_ch0_phase_interp ( 0 ) ;
2017-08-03 15:58:11 +00:00
arma : : vec err2_ch0 = arma : : square ( err_ch0_cycles ) ;
double rmse_ch0 = sqrt ( arma : : mean ( err2_ch0 ) ) ;
2019-08-18 23:29:04 +00:00
// 3. Mean err and variance
2017-08-03 15:58:11 +00:00
double error_mean_ch0 = arma : : mean ( err_ch0_cycles ) ;
double error_var_ch0 = arma : : var ( err_ch0_cycles ) ;
// 4. Peaks
double max_error_ch0 = arma : : max ( err_ch0_cycles ) ;
double min_error_ch0 = arma : : min ( err_ch0_cycles ) ;
2019-08-18 23:29:04 +00:00
// 5. report
2017-08-03 15:58:11 +00:00
std : : streamsize ss = std : : cout . precision ( ) ;
2018-07-26 17:25:10 +00:00
std : : cout < < std : : setprecision ( 10 ) < < data_title < < " Accumulated Carrier phase RMSE = "
2018-02-26 11:33:40 +00:00
< < rmse_ch0 < < " , mean = " < < error_mean_ch0
< < " , stdev = " < < sqrt ( error_var_ch0 )
< < " (max,min) = " < < max_error_ch0
2017-08-03 15:58:11 +00:00
< < " , " < < min_error_ch0
2020-07-07 16:53:50 +00:00
< < " [cycles] \n " ;
2018-03-03 01:03:39 +00:00
std : : cout . precision ( ss ) ;
2017-08-03 15:58:11 +00:00
2019-08-18 23:29:04 +00:00
// plots
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-07-26 17:25:10 +00:00
if ( FLAGS_show_plots )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_show_plots ) )
# endif
2018-07-26 17:25:10 +00:00
{
2018-08-07 18:16:43 +00:00
Gnuplot g3 ( " linespoints " ) ;
g3 . set_title ( data_title + " Accumulated Carrier phase error [cycles] " ) ;
g3 . set_grid ( ) ;
g3 . set_xlabel ( " Time [s] " ) ;
g3 . set_ylabel ( " Carrier Phase error [cycles] " ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2018-08-07 18:16:43 +00:00
std : : vector < double > error_vec ( err_ch0_cycles . colptr ( 0 ) , err_ch0_cycles . colptr ( 0 ) + err_ch0_cycles . n_rows ) ;
g3 . cmd ( " set key box opaque " ) ;
g3 . plot_xy ( time_vector , error_vec ,
" Carrier Phase error " ) ;
g3 . set_legend ( ) ;
g3 . savetops ( data_title + " Carrier_phase_error " ) ;
2018-07-26 17:25:10 +00:00
g3 . showonscreen ( ) ; // window output
}
2018-08-07 18:16:43 +00:00
2019-08-18 23:29:04 +00:00
// check results against the test tolerance
2018-08-07 18:16:43 +00:00
ASSERT_LT ( rmse_ch0 , 0.25 ) ;
ASSERT_LT ( error_mean_ch0 , 0.2 ) ;
ASSERT_GT ( error_mean_ch0 , - 0.2 ) ;
ASSERT_LT ( error_var_ch0 , 0.5 ) ;
ASSERT_LT ( max_error_ch0 , 0.5 ) ;
ASSERT_GT ( min_error_ch0 , - 0.5 ) ;
}
void HybridObservablesTest : : check_results_carrier_phase_double_diff (
arma : : mat & true_ch0 ,
arma : : mat & true_ch1 ,
arma : : vec & true_tow_ch0_s ,
arma : : vec & true_tow_ch1_s ,
arma : : mat & measured_ch0 ,
arma : : mat & measured_ch1 ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title )
2018-08-07 18:16:43 +00:00
{
2019-08-18 23:29:04 +00:00
// 1. True value interpolation to match the measurement times
2018-08-07 18:16:43 +00:00
double t0 = std : : max ( measured_ch0 ( 0 , 0 ) , measured_ch1 ( 0 , 0 ) ) ;
int size1 = measured_ch0 . col ( 0 ) . n_rows ;
int size2 = measured_ch1 . col ( 0 ) . n_rows ;
double t1 = std : : min ( measured_ch0 ( size1 - 1 , 0 ) , measured_ch1 ( size2 - 1 , 0 ) ) ;
2019-07-16 15:41:12 +00:00
if ( ( t1 - t0 ) > 0 )
2018-07-26 17:25:10 +00:00
{
2019-07-16 15:41:12 +00:00
arma : : vec t = arma : : linspace < arma : : vec > ( t0 , t1 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
arma : : vec t_from_start = arma : : linspace < arma : : vec > ( 0 , t1 - t0 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
std : : vector < double > time_vector ( t_from_start . colptr ( 0 ) , t_from_start . colptr ( 0 ) + t_from_start . n_rows ) ;
arma : : vec true_ch0_carrier_phase_interp ;
arma : : vec true_ch1_carrier_phase_interp ;
arma : : interp1 ( true_tow_ch0_s , true_ch0 . col ( 3 ) , t , true_ch0_carrier_phase_interp ) ;
arma : : interp1 ( true_tow_ch1_s , true_ch1 . col ( 3 ) , t , true_ch1_carrier_phase_interp ) ;
arma : : vec meas_ch0_carrier_phase_interp ;
arma : : vec meas_ch1_carrier_phase_interp ;
arma : : interp1 ( measured_ch0 . col ( 0 ) , measured_ch0 . col ( 3 ) , t , meas_ch0_carrier_phase_interp ) ;
arma : : interp1 ( measured_ch1 . col ( 0 ) , measured_ch1 . col ( 3 ) , t , meas_ch1_carrier_phase_interp ) ;
// generate double difference accumulated carrier phases
2019-08-18 23:29:04 +00:00
// compute error without the accumulated carrier phase offsets (which depends on the receiver starting time)
2019-07-16 15:41:12 +00:00
arma : : vec delta_true_carrier_phase_cycles = ( true_ch0_carrier_phase_interp - true_ch0_carrier_phase_interp ( 0 ) ) - ( true_ch1_carrier_phase_interp - true_ch1_carrier_phase_interp ( 0 ) ) ;
arma : : vec delta_measured_carrier_phase_cycles = ( meas_ch0_carrier_phase_interp - meas_ch0_carrier_phase_interp ( 0 ) ) - ( meas_ch1_carrier_phase_interp - meas_ch1_carrier_phase_interp ( 0 ) ) ;
2019-08-18 23:29:04 +00:00
// 2. RMSE
2019-07-16 15:41:12 +00:00
arma : : vec err ;
err = delta_measured_carrier_phase_cycles - delta_true_carrier_phase_cycles ;
arma : : vec err2 = arma : : square ( err ) ;
double rmse = sqrt ( arma : : mean ( err2 ) ) ;
2019-08-18 23:29:04 +00:00
// 3. Mean err and variance
2019-07-16 15:41:12 +00:00
double error_mean = arma : : mean ( err ) ;
double error_var = arma : : var ( err ) ;
// 4. Peaks
double max_error = arma : : max ( err ) ;
double min_error = arma : : min ( err ) ;
2019-08-18 23:29:04 +00:00
// 5. report
2019-07-16 15:41:12 +00:00
std : : streamsize ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 10 ) < < data_title < < " Double diff Carrier Phase RMSE = "
< < rmse < < " , mean = " < < error_mean
< < " , stdev = " < < sqrt ( error_var )
< < " (max,min) = " < < max_error
< < " , " < < min_error
2020-07-07 16:53:50 +00:00
< < " [Cycles] \n " ;
2019-07-16 15:41:12 +00:00
std : : cout . precision ( ss ) ;
2019-08-18 23:29:04 +00:00
// plots
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2019-07-16 15:41:12 +00:00
if ( FLAGS_show_plots )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_show_plots ) )
# endif
2019-07-16 15:41:12 +00:00
{
Gnuplot g3 ( " linespoints " ) ;
g3 . set_title ( data_title + " Double diff Carrier Phase error [Cycles] " ) ;
g3 . set_grid ( ) ;
g3 . set_xlabel ( " Time [s] " ) ;
g3 . set_ylabel ( " Double diff Carrier Phase error [Cycles] " ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
std : : vector < double > range_error_m ( err . colptr ( 0 ) , err . colptr ( 0 ) + err . n_rows ) ;
g3 . cmd ( " set key box opaque " ) ;
g3 . plot_xy ( time_vector , range_error_m ,
" Double diff Carrier Phase error " ) ;
g3 . set_legend ( ) ;
g3 . savetops ( data_title + " double_diff_carrier_phase_error " ) ;
g3 . showonscreen ( ) ; // window output
}
2018-08-07 18:16:43 +00:00
2019-08-18 23:29:04 +00:00
// check results against the test tolerance
2019-11-12 16:49:18 +00:00
if ( ! std : : isnan ( rmse ) )
{
ASSERT_LT ( rmse , 3.0 ) ;
ASSERT_LT ( error_mean , 3.0 ) ;
ASSERT_GT ( error_mean , - 3.0 ) ;
ASSERT_LT ( error_var , 3.0 ) ;
ASSERT_LT ( max_error , 5.0 ) ;
ASSERT_GT ( min_error , - 5.0 ) ;
}
2018-07-26 17:25:10 +00:00
}
2018-08-07 18:16:43 +00:00
}
void HybridObservablesTest : : check_results_carrier_doppler_double_diff (
arma : : mat & true_ch0 ,
arma : : mat & true_ch1 ,
arma : : vec & true_tow_ch0_s ,
arma : : vec & true_tow_ch1_s ,
arma : : mat & measured_ch0 ,
arma : : mat & measured_ch1 ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title )
2018-08-07 18:16:43 +00:00
{
2019-08-18 23:29:04 +00:00
// 1. True value interpolation to match the measurement times
2018-08-07 18:16:43 +00:00
double t0 = std : : max ( measured_ch0 ( 0 , 0 ) , measured_ch1 ( 0 , 0 ) ) ;
int size1 = measured_ch0 . col ( 0 ) . n_rows ;
int size2 = measured_ch1 . col ( 0 ) . n_rows ;
double t1 = std : : min ( measured_ch0 ( size1 - 1 , 0 ) , measured_ch1 ( size2 - 1 , 0 ) ) ;
2019-07-16 15:41:12 +00:00
if ( ( t1 - t0 ) > 0 )
2018-08-07 18:16:43 +00:00
{
2019-07-16 15:41:12 +00:00
arma : : vec t = arma : : linspace < arma : : vec > ( t0 , t1 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
arma : : vec t_from_start = arma : : linspace < arma : : vec > ( 0 , t1 - t0 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
std : : vector < double > time_vector ( t_from_start . colptr ( 0 ) , t_from_start . colptr ( 0 ) + t_from_start . n_rows ) ;
arma : : vec true_ch0_carrier_doppler_interp ;
arma : : vec true_ch1_carrier_doppler_interp ;
arma : : interp1 ( true_tow_ch0_s , true_ch0 . col ( 2 ) , t , true_ch0_carrier_doppler_interp ) ;
arma : : interp1 ( true_tow_ch1_s , true_ch1 . col ( 2 ) , t , true_ch1_carrier_doppler_interp ) ;
arma : : vec meas_ch0_carrier_doppler_interp ;
arma : : vec meas_ch1_carrier_doppler_interp ;
arma : : interp1 ( measured_ch0 . col ( 0 ) , measured_ch0 . col ( 2 ) , t , meas_ch0_carrier_doppler_interp ) ;
arma : : interp1 ( measured_ch1 . col ( 0 ) , measured_ch1 . col ( 2 ) , t , meas_ch1_carrier_doppler_interp ) ;
// generate double difference carrier Doppler
arma : : vec delta_true_carrier_doppler_cycles = true_ch0_carrier_doppler_interp - true_ch1_carrier_doppler_interp ;
arma : : vec delta_measured_carrier_doppler_cycles = meas_ch0_carrier_doppler_interp - meas_ch1_carrier_doppler_interp ;
2019-08-18 23:29:04 +00:00
// 2. RMSE
2019-07-16 15:41:12 +00:00
arma : : vec err ;
err = delta_measured_carrier_doppler_cycles - delta_true_carrier_doppler_cycles ;
arma : : vec err2 = arma : : square ( err ) ;
double rmse = sqrt ( arma : : mean ( err2 ) ) ;
2019-08-18 23:29:04 +00:00
// 3. Mean err and variance
2019-07-16 15:41:12 +00:00
double error_mean = arma : : mean ( err ) ;
double error_var = arma : : var ( err ) ;
// 4. Peaks
double max_error = arma : : max ( err ) ;
double min_error = arma : : min ( err ) ;
2019-08-18 23:29:04 +00:00
// 5. report
2019-07-16 15:41:12 +00:00
std : : streamsize ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 10 ) < < data_title < < " Double diff Carrier Doppler RMSE = "
< < rmse < < " , mean = " < < error_mean
< < " , stdev = " < < sqrt ( error_var )
< < " (max,min) = " < < max_error
< < " , " < < min_error
2020-07-07 16:53:50 +00:00
< < " [Hz] \n " ;
2019-07-16 15:41:12 +00:00
std : : cout . precision ( ss ) ;
2024-04-29 06:27:33 +00:00
// plots
# if USE_GLOG_AND_GFLAGS
2019-07-16 15:41:12 +00:00
if ( FLAGS_show_plots )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_show_plots ) )
# endif
2019-07-16 15:41:12 +00:00
{
Gnuplot g3 ( " linespoints " ) ;
g3 . set_title ( data_title + " Double diff Carrier Doppler error [Hz] " ) ;
g3 . set_grid ( ) ;
g3 . set_xlabel ( " Time [s] " ) ;
g3 . set_ylabel ( " Double diff Carrier Doppler error [Hz] " ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
std : : vector < double > range_error_m ( err . colptr ( 0 ) , err . colptr ( 0 ) + err . n_rows ) ;
g3 . cmd ( " set key box opaque " ) ;
g3 . plot_xy ( time_vector , range_error_m ,
" Double diff Carrier Doppler error " ) ;
g3 . set_legend ( ) ;
g3 . savetops ( data_title + " double_diff_carrier_doppler_error " ) ;
g3 . showonscreen ( ) ; // window output
}
2018-08-07 18:16:43 +00:00
2019-08-18 23:29:04 +00:00
// check results against the test tolerance
2019-11-12 16:49:18 +00:00
if ( ! std : : isnan ( error_mean ) )
{
ASSERT_LT ( error_mean , 5 ) ;
ASSERT_GT ( error_mean , - 5 ) ;
// assuming PLL BW=35
ASSERT_LT ( error_var , 250 ) ;
ASSERT_LT ( max_error , 100 ) ;
ASSERT_GT ( min_error , - 100 ) ;
ASSERT_LT ( rmse , 30 ) ;
}
2018-08-07 18:16:43 +00:00
}
2018-07-26 17:25:10 +00:00
}
2018-08-07 18:16:43 +00:00
2018-07-26 17:25:10 +00:00
void HybridObservablesTest : : check_results_carrier_doppler (
arma : : mat & true_ch0 ,
arma : : vec & true_tow_s ,
arma : : mat & measured_ch0 ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title )
2018-07-26 17:25:10 +00:00
{
2019-08-18 23:29:04 +00:00
// 1. True value interpolation to match the measurement times
2018-07-26 17:25:10 +00:00
double t0 = measured_ch0 ( 0 , 0 ) ;
int size1 = measured_ch0 . col ( 0 ) . n_rows ;
double t1 = measured_ch0 ( size1 - 1 , 0 ) ;
2019-07-16 15:41:12 +00:00
if ( ( t1 - t0 ) > 0 )
{
arma : : vec t = arma : : linspace < arma : : vec > ( t0 , t1 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
arma : : vec t_from_start = arma : : linspace < arma : : vec > ( 0 , t1 - t0 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
std : : vector < double > time_vector ( t_from_start . colptr ( 0 ) , t_from_start . colptr ( 0 ) + t_from_start . n_rows ) ;
2018-07-26 17:25:10 +00:00
2019-07-16 15:41:12 +00:00
arma : : vec true_ch0_doppler_interp ;
arma : : interp1 ( true_tow_s , true_ch0 . col ( 2 ) , t , true_ch0_doppler_interp ) ;
2018-07-26 17:25:10 +00:00
2019-07-16 15:41:12 +00:00
arma : : vec meas_ch0_doppler_interp ;
arma : : interp1 ( measured_ch0 . col ( 0 ) , measured_ch0 . col ( 2 ) , t , meas_ch0_doppler_interp ) ;
2018-07-26 17:25:10 +00:00
2019-08-18 23:29:04 +00:00
// 2. RMSE
2019-07-16 15:41:12 +00:00
arma : : vec err_ch0_hz ;
2018-07-26 17:25:10 +00:00
2019-08-18 23:29:04 +00:00
// compute error
2019-07-16 15:41:12 +00:00
err_ch0_hz = meas_ch0_doppler_interp - true_ch0_doppler_interp ;
2018-07-26 17:25:10 +00:00
2019-07-16 15:41:12 +00:00
arma : : vec err2_ch0 = arma : : square ( err_ch0_hz ) ;
double rmse_ch0 = sqrt ( arma : : mean ( err2_ch0 ) ) ;
2018-07-26 17:25:10 +00:00
2019-08-18 23:29:04 +00:00
// 3. Mean err and variance
2019-07-16 15:41:12 +00:00
double error_mean_ch0 = arma : : mean ( err_ch0_hz ) ;
double error_var_ch0 = arma : : var ( err_ch0_hz ) ;
2017-08-03 15:58:11 +00:00
2019-07-16 15:41:12 +00:00
// 4. Peaks
double max_error_ch0 = arma : : max ( err_ch0_hz ) ;
double min_error_ch0 = arma : : min ( err_ch0_hz ) ;
2017-08-03 15:58:11 +00:00
2019-08-18 23:29:04 +00:00
// 5. report
2019-07-16 15:41:12 +00:00
std : : streamsize ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 10 ) < < data_title < < " Carrier Doppler RMSE = "
< < rmse_ch0 < < " , mean = " < < error_mean_ch0
< < " , stdev = " < < sqrt ( error_var_ch0 )
< < " (max,min) = " < < max_error_ch0
< < " , " < < min_error_ch0
2020-07-07 16:53:50 +00:00
< < " [Hz] \n " ;
2019-07-16 15:41:12 +00:00
std : : cout . precision ( ss ) ;
2018-08-07 18:16:43 +00:00
2019-08-18 23:29:04 +00:00
// plots
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2019-07-16 15:41:12 +00:00
if ( FLAGS_show_plots )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_show_plots ) )
# endif
2019-07-16 15:41:12 +00:00
{
Gnuplot g3 ( " linespoints " ) ;
g3 . set_title ( data_title + " Carrier Doppler error [Hz] " ) ;
g3 . set_grid ( ) ;
g3 . set_xlabel ( " Time [s] " ) ;
g3 . set_ylabel ( " Carrier Doppler error [Hz] " ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
std : : vector < double > error_vec ( err_ch0_hz . colptr ( 0 ) , err_ch0_hz . colptr ( 0 ) + err_ch0_hz . n_rows ) ;
g3 . cmd ( " set key box opaque " ) ;
g3 . plot_xy ( time_vector , error_vec ,
" Carrier Doppler error " ) ;
g3 . set_legend ( ) ;
g3 . savetops ( data_title + " Carrier_doppler_error " ) ;
g3 . showonscreen ( ) ; // window output
}
2017-08-03 15:58:11 +00:00
2019-08-18 23:29:04 +00:00
// check results against the test tolerance
2019-07-16 15:41:12 +00:00
ASSERT_LT ( error_mean_ch0 , 5 ) ;
ASSERT_GT ( error_mean_ch0 , - 5 ) ;
2019-08-18 23:29:04 +00:00
// assuming PLL BW=35
2019-07-16 15:41:12 +00:00
ASSERT_LT ( error_var_ch0 , 250 ) ;
ASSERT_LT ( max_error_ch0 , 100 ) ;
ASSERT_GT ( min_error_ch0 , - 100 ) ;
ASSERT_LT ( rmse_ch0 , 30 ) ;
}
2018-07-26 17:25:10 +00:00
}
2017-10-29 11:26:06 +00:00
2019-11-14 11:15:41 +00:00
2018-10-06 17:36:25 +00:00
void HybridObservablesTest : : check_results_duplicated_satellite (
arma : : mat & measured_sat1 ,
arma : : mat & measured_sat2 ,
2018-10-15 15:02:43 +00:00
int ch_id ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title )
2018-10-06 17:36:25 +00:00
{
2019-08-18 23:29:04 +00:00
// 1. True value interpolation to match the measurement times
2018-10-06 17:36:25 +00:00
2019-08-18 23:29:04 +00:00
// define the common measured time interval
2018-10-15 15:02:43 +00:00
double t0_sat1 = measured_sat1 ( 0 , 0 ) ;
2018-10-06 17:36:25 +00:00
int size1 = measured_sat1 . col ( 0 ) . n_rows ;
2018-10-15 15:02:43 +00:00
double t1_sat1 = measured_sat1 ( size1 - 1 , 0 ) ;
double t0_sat2 = measured_sat2 ( 0 , 0 ) ;
int size2 = measured_sat2 . col ( 0 ) . n_rows ;
double t1_sat2 = measured_sat2 ( size2 - 1 , 0 ) ;
double t0 ;
double t1 ;
if ( t0_sat1 > t0_sat2 )
{
t0 = t0_sat1 ;
}
else
{
t0 = t0_sat2 ;
}
if ( t1_sat1 > t1_sat2 )
{
t1 = t1_sat2 ;
}
else
{
t1 = t1_sat1 ;
}
2019-07-16 15:41:12 +00:00
if ( ( t1 - t0 ) > 0 )
2018-10-06 17:36:25 +00:00
{
2019-07-16 15:41:12 +00:00
arma : : vec t = arma : : linspace < arma : : vec > ( t0 , t1 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
arma : : vec t_from_start = arma : : linspace < arma : : vec > ( 0 , t1 - t0 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
std : : vector < double > time_vector ( t_from_start . colptr ( 0 ) , t_from_start . colptr ( 0 ) + t_from_start . n_rows ) ;
2019-08-18 23:29:04 +00:00
// Doppler
2019-07-16 15:41:12 +00:00
arma : : vec meas_sat1_doppler_interp ;
arma : : interp1 ( measured_sat1 . col ( 0 ) , measured_sat1 . col ( 2 ) , t , meas_sat1_doppler_interp ) ;
arma : : vec meas_sat2_doppler_interp ;
arma : : interp1 ( measured_sat2 . col ( 0 ) , measured_sat2 . col ( 2 ) , t , meas_sat2_doppler_interp ) ;
2019-08-18 23:29:04 +00:00
// Carrier Phase
2019-07-16 15:41:12 +00:00
arma : : vec meas_sat1_carrier_phase_interp ;
arma : : vec meas_sat2_carrier_phase_interp ;
arma : : interp1 ( measured_sat1 . col ( 0 ) , measured_sat1 . col ( 3 ) , t , meas_sat1_carrier_phase_interp ) ;
arma : : interp1 ( measured_sat2 . col ( 0 ) , measured_sat2 . col ( 3 ) , t , meas_sat2_carrier_phase_interp ) ;
// generate double difference accumulated carrier phases
2019-08-18 23:29:04 +00:00
// compute error without the accumulated carrier phase offsets (which depends on the receiver starting time)
2019-07-16 15:41:12 +00:00
arma : : vec delta_measured_carrier_phase_cycles = ( meas_sat1_carrier_phase_interp - meas_sat1_carrier_phase_interp ( 0 ) ) - ( meas_sat2_carrier_phase_interp - meas_sat2_carrier_phase_interp ( 0 ) ) ;
2019-08-18 23:29:04 +00:00
// Pseudoranges
2019-07-16 15:41:12 +00:00
arma : : vec meas_sat1_dist_interp ;
arma : : vec meas_sat2_dist_interp ;
arma : : interp1 ( measured_sat1 . col ( 0 ) , measured_sat1 . col ( 4 ) , t , meas_sat1_dist_interp ) ;
arma : : interp1 ( measured_sat2 . col ( 0 ) , measured_sat2 . col ( 4 ) , t , meas_sat2_dist_interp ) ;
// generate delta pseudoranges
arma : : vec delta_measured_dist_m = meas_sat1_dist_interp - meas_sat2_dist_interp ;
2019-08-18 23:29:04 +00:00
// Carrier Doppler error
// 2. RMSE
2019-07-16 15:41:12 +00:00
arma : : vec err_ch0_hz ;
2019-08-18 23:29:04 +00:00
// compute error
2019-07-16 15:41:12 +00:00
err_ch0_hz = meas_sat1_doppler_interp - meas_sat2_doppler_interp ;
2019-08-18 23:29:04 +00:00
// save matlab file for further analysis
2019-07-16 15:41:12 +00:00
std : : vector < double > tmp_vector_common_time_s ( t . colptr ( 0 ) ,
t . colptr ( 0 ) + t . n_rows ) ;
std : : vector < double > tmp_vector_err_ch0_hz ( err_ch0_hz . colptr ( 0 ) ,
err_ch0_hz . colptr ( 0 ) + err_ch0_hz . n_rows ) ;
save_mat_xy ( tmp_vector_common_time_s , tmp_vector_err_ch0_hz , std : : string ( " measured_doppler_error_ch_ " + std : : to_string ( ch_id ) ) ) ;
2019-08-18 23:29:04 +00:00
// compute statistics
2019-07-16 15:41:12 +00:00
arma : : vec err2_ch0 = arma : : square ( err_ch0_hz ) ;
double rmse_ch0 = sqrt ( arma : : mean ( err2_ch0 ) ) ;
2019-08-18 23:29:04 +00:00
// 3. Mean err and variance
2019-07-16 15:41:12 +00:00
double error_mean_ch0 = arma : : mean ( err_ch0_hz ) ;
double error_var_ch0 = arma : : var ( err_ch0_hz ) ;
// 4. Peaks
double max_error_ch0 = arma : : max ( err_ch0_hz ) ;
double min_error_ch0 = arma : : min ( err_ch0_hz ) ;
2019-08-18 23:29:04 +00:00
// 5. report
2019-07-16 15:41:12 +00:00
std : : streamsize ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 10 ) < < data_title < < " Carrier Doppler RMSE = "
< < rmse_ch0 < < " , mean = " < < error_mean_ch0
< < " , stdev = " < < sqrt ( error_var_ch0 )
< < " (max,min) = " < < max_error_ch0
< < " , " < < min_error_ch0
2020-07-07 16:53:50 +00:00
< < " [Hz] \n " ;
2019-07-16 15:41:12 +00:00
std : : cout . precision ( ss ) ;
2019-08-18 23:29:04 +00:00
// plots
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2019-07-16 15:41:12 +00:00
if ( FLAGS_show_plots )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_show_plots ) )
# endif
2019-07-16 15:41:12 +00:00
{
Gnuplot g3 ( " linespoints " ) ;
g3 . set_title ( data_title + " Carrier Doppler error [Hz] " ) ;
g3 . set_grid ( ) ;
g3 . set_xlabel ( " Time [s] " ) ;
g3 . set_ylabel ( " Carrier Doppler error [Hz] " ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
std : : vector < double > error_vec ( err_ch0_hz . colptr ( 0 ) , err_ch0_hz . colptr ( 0 ) + err_ch0_hz . n_rows ) ;
g3 . cmd ( " set key box opaque " ) ;
g3 . plot_xy ( time_vector , error_vec ,
" Carrier Doppler error " ) ;
g3 . set_legend ( ) ;
g3 . savetops ( data_title + " Carrier_doppler_error " ) ;
g3 . showonscreen ( ) ; // window output
}
2018-10-06 17:36:25 +00:00
2019-08-18 23:29:04 +00:00
// check results against the test tolerance
2019-07-16 15:41:12 +00:00
EXPECT_LT ( error_mean_ch0 , 5 ) ;
EXPECT_GT ( error_mean_ch0 , - 5 ) ;
2019-08-18 23:29:04 +00:00
// assuming PLL BW=35
2019-07-16 15:41:12 +00:00
EXPECT_LT ( error_var_ch0 , 250 ) ;
EXPECT_LT ( max_error_ch0 , 100 ) ;
EXPECT_GT ( min_error_ch0 , - 100 ) ;
EXPECT_LT ( rmse_ch0 , 30 ) ;
2019-08-18 23:29:04 +00:00
// Carrier Phase error
// 2. RMSE
2019-07-16 15:41:12 +00:00
arma : : vec err_carrier_phase ;
err_carrier_phase = delta_measured_carrier_phase_cycles ;
2019-08-18 23:29:04 +00:00
// save matlab file for further analysis
2019-07-16 15:41:12 +00:00
std : : vector < double > tmp_vector_err_carrier_phase ( err_carrier_phase . colptr ( 0 ) ,
err_carrier_phase . colptr ( 0 ) + err_carrier_phase . n_rows ) ;
save_mat_xy ( tmp_vector_common_time_s , tmp_vector_err_carrier_phase , std : : string ( " measured_carrier_phase_error_ch_ " + std : : to_string ( ch_id ) ) ) ;
arma : : vec err2_carrier_phase = arma : : square ( err_carrier_phase ) ;
double rmse_carrier_phase = sqrt ( arma : : mean ( err2_carrier_phase ) ) ;
2019-08-18 23:29:04 +00:00
// 3. Mean err and variance
2019-07-16 15:41:12 +00:00
double error_mean_carrier_phase = arma : : mean ( err_carrier_phase ) ;
double error_var_carrier_phase = arma : : var ( err_carrier_phase ) ;
// 4. Peaks
double max_error_carrier_phase = arma : : max ( err_carrier_phase ) ;
double min_error_carrier_phase = arma : : min ( err_carrier_phase ) ;
2019-08-18 23:29:04 +00:00
// 5. report
2019-07-16 15:41:12 +00:00
ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 10 ) < < data_title < < " Carrier Phase RMSE = "
< < rmse_carrier_phase < < " , mean = " < < error_mean_carrier_phase
< < " , stdev = " < < sqrt ( error_var_carrier_phase )
< < " (max,min) = " < < max_error_carrier_phase
< < " , " < < min_error_carrier_phase
2020-07-07 16:53:50 +00:00
< < " [Cycles] \n " ;
2019-07-16 15:41:12 +00:00
std : : cout . precision ( ss ) ;
2024-04-29 06:27:33 +00:00
// plots
# if USE_GLOG_AND_GFLAGS
2019-07-16 15:41:12 +00:00
if ( FLAGS_show_plots )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_show_plots ) )
# endif
2019-07-16 15:41:12 +00:00
{
Gnuplot g3 ( " linespoints " ) ;
g3 . set_title ( data_title + " Carrier Phase error [Cycles] " ) ;
g3 . set_grid ( ) ;
g3 . set_xlabel ( " Time [s] " ) ;
g3 . set_ylabel ( " Carrier Phase error [Cycles] " ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
std : : vector < double > range_error_m ( err_carrier_phase . colptr ( 0 ) , err_carrier_phase . colptr ( 0 ) + err_carrier_phase . n_rows ) ;
g3 . cmd ( " set key box opaque " ) ;
g3 . plot_xy ( time_vector , range_error_m ,
" Carrier Phase error " ) ;
g3 . set_legend ( ) ;
g3 . savetops ( data_title + " duplicated_satellite_carrier_phase_error " ) ;
g3 . showonscreen ( ) ; // window output
}
2018-10-06 17:36:25 +00:00
2019-08-18 23:29:04 +00:00
// check results against the test tolerance
2019-07-16 15:41:12 +00:00
EXPECT_LT ( rmse_carrier_phase , 0.25 ) ;
EXPECT_LT ( error_mean_carrier_phase , 0.2 ) ;
EXPECT_GT ( error_mean_carrier_phase , - 0.2 ) ;
EXPECT_LT ( error_var_carrier_phase , 0.5 ) ;
EXPECT_LT ( max_error_carrier_phase , 0.5 ) ;
EXPECT_GT ( min_error_carrier_phase , - 0.5 ) ;
2019-08-18 23:29:04 +00:00
// Pseudorange error
// 2. RMSE
2019-07-16 15:41:12 +00:00
arma : : vec err_pseudorange ;
err_pseudorange = delta_measured_dist_m ;
2019-08-18 23:29:04 +00:00
// save matlab file for further analysis
2019-07-16 15:41:12 +00:00
std : : vector < double > tmp_vector_err_pseudorange ( err_pseudorange . colptr ( 0 ) ,
err_pseudorange . colptr ( 0 ) + err_pseudorange . n_rows ) ;
save_mat_xy ( tmp_vector_common_time_s , tmp_vector_err_pseudorange , std : : string ( " measured_pr_error_ch_ " + std : : to_string ( ch_id ) ) ) ;
arma : : vec err2_pseudorange = arma : : square ( err_pseudorange ) ;
double rmse_pseudorange = sqrt ( arma : : mean ( err2_pseudorange ) ) ;
2019-08-18 23:29:04 +00:00
// 3. Mean err and variance
2019-07-16 15:41:12 +00:00
double error_mean_pseudorange = arma : : mean ( err_pseudorange ) ;
double error_var_pseudorange = arma : : var ( err_pseudorange ) ;
// 4. Peaks
double max_error_pseudorange = arma : : max ( err_pseudorange ) ;
double min_error_pseudorange = arma : : min ( err_pseudorange ) ;
2019-08-18 23:29:04 +00:00
// 5. report
2019-07-16 15:41:12 +00:00
ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 10 ) < < data_title < < " Pseudorange RMSE = "
< < rmse_pseudorange < < " , mean = " < < error_mean_pseudorange
< < " , stdev = " < < sqrt ( error_var_pseudorange )
< < " (max,min) = " < < max_error_pseudorange
< < " , " < < min_error_pseudorange
2020-07-07 16:53:50 +00:00
< < " [meters] \n " ;
2019-07-16 15:41:12 +00:00
std : : cout . precision ( ss ) ;
2019-08-18 23:29:04 +00:00
// plots
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2019-07-16 15:41:12 +00:00
if ( FLAGS_show_plots )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_show_plots ) )
# endif
2019-07-16 15:41:12 +00:00
{
Gnuplot g3 ( " linespoints " ) ;
g3 . set_title ( data_title + " Pseudorange error [m] " ) ;
g3 . set_grid ( ) ;
g3 . set_xlabel ( " Time [s] " ) ;
g3 . set_ylabel ( " Pseudorange error [m] " ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
std : : vector < double > range_error_m ( err_pseudorange . colptr ( 0 ) , err_pseudorange . colptr ( 0 ) + err_pseudorange . n_rows ) ;
g3 . cmd ( " set key box opaque " ) ;
g3 . plot_xy ( time_vector , range_error_m ,
" Pseudorrange error " ) ;
g3 . set_legend ( ) ;
g3 . savetops ( data_title + " duplicated_satellite_pseudorrange_error " ) ;
g3 . showonscreen ( ) ; // window output
}
2018-10-06 17:36:25 +00:00
2019-08-18 23:29:04 +00:00
// check results against the test tolerance
2019-07-16 15:41:12 +00:00
EXPECT_LT ( rmse_pseudorange , 3.0 ) ;
EXPECT_LT ( error_mean_pseudorange , 1.0 ) ;
EXPECT_GT ( error_mean_pseudorange , - 1.0 ) ;
EXPECT_LT ( error_var_pseudorange , 10.0 ) ;
2019-11-12 16:49:18 +00:00
EXPECT_LT ( max_error_pseudorange , 15.0 ) ;
EXPECT_GT ( min_error_pseudorange , - 15.0 ) ;
2018-10-06 17:36:25 +00:00
}
}
2019-11-14 11:15:41 +00:00
2018-07-17 16:31:55 +00:00
bool HybridObservablesTest : : 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 . append ( " .mat " ) ;
2020-07-07 16:53:50 +00:00
std : : cout < < " save_mat_xy write " < < filename < < ' \n ' ;
2019-02-11 17:38:42 +00:00
matfp = Mat_CreateVer ( filename . c_str ( ) , nullptr , MAT_FT_MAT5 ) ;
if ( reinterpret_cast < int64_t * > ( matfp ) ! = nullptr )
2018-07-17 16:31:55 +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 ) ;
}
else
{
2020-07-07 16:53:50 +00:00
std : : cout < < " save_mat_xy: error creating file \n " ;
2018-07-17 16:31:55 +00:00
}
Mat_Close ( matfp ) ;
return true ;
}
catch ( const std : : exception & ex )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " save_mat_xy: " < < ex . what ( ) < < ' \n ' ;
2018-07-17 16:31:55 +00:00
return false ;
}
}
2019-08-18 23:29:04 +00:00
2018-07-26 17:25:10 +00:00
void HybridObservablesTest : : check_results_code_pseudorange (
2018-03-20 16:24:16 +00:00
arma : : mat & true_ch0 ,
arma : : mat & true_ch1 ,
2018-08-07 18:16:43 +00:00
arma : : vec & true_tow_ch0_s ,
arma : : vec & true_tow_ch1_s ,
2018-03-20 16:24:16 +00:00
arma : : mat & measured_ch0 ,
2018-07-26 17:25:10 +00:00
arma : : mat & measured_ch1 ,
2019-02-11 17:38:42 +00:00
const std : : string & data_title )
2017-04-12 15:04:51 +00:00
{
2019-08-18 23:29:04 +00:00
// 1. True value interpolation to match the measurement times
2018-02-26 11:33:40 +00:00
double t0 = std : : max ( measured_ch0 ( 0 , 0 ) , measured_ch1 ( 0 , 0 ) ) ;
int size1 = measured_ch0 . col ( 0 ) . n_rows ;
int size2 = measured_ch1 . col ( 0 ) . n_rows ;
double t1 = std : : min ( measured_ch0 ( size1 - 1 , 0 ) , measured_ch1 ( size2 - 1 , 0 ) ) ;
2018-07-17 16:31:55 +00:00
2019-07-16 15:41:12 +00:00
if ( ( t1 - t0 ) > 0 )
2018-07-17 16:31:55 +00:00
{
2019-07-16 15:41:12 +00:00
arma : : vec t = arma : : linspace < arma : : vec > ( t0 , t1 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
arma : : vec t_from_start = arma : : linspace < arma : : vec > ( 0 , t1 - t0 , floor ( ( t1 - t0 ) * 1e3 ) ) ;
std : : vector < double > time_vector ( t_from_start . colptr ( 0 ) , t_from_start . colptr ( 0 ) + t_from_start . n_rows ) ;
arma : : vec true_ch0_dist_interp ;
arma : : vec true_ch1_dist_interp ;
arma : : interp1 ( true_tow_ch0_s , true_ch0 . col ( 1 ) , t , true_ch0_dist_interp ) ;
arma : : interp1 ( true_tow_ch1_s , true_ch1 . col ( 1 ) , t , true_ch1_dist_interp ) ;
arma : : vec meas_ch0_dist_interp ;
arma : : vec meas_ch1_dist_interp ;
arma : : interp1 ( measured_ch0 . col ( 0 ) , measured_ch0 . col ( 4 ) , t , meas_ch0_dist_interp ) ;
arma : : interp1 ( measured_ch1 . col ( 0 ) , measured_ch1 . col ( 4 ) , t , meas_ch1_dist_interp ) ;
// generate delta pseudoranges
arma : : vec delta_true_dist_m = true_ch0_dist_interp - true_ch1_dist_interp ;
arma : : vec delta_measured_dist_m = meas_ch0_dist_interp - meas_ch1_dist_interp ;
2019-08-18 23:29:04 +00:00
// 2. RMSE
2019-07-16 15:41:12 +00:00
arma : : vec err ;
err = delta_measured_dist_m - delta_true_dist_m ;
arma : : vec err2 = arma : : square ( err ) ;
double rmse = sqrt ( arma : : mean ( err2 ) ) ;
2019-08-18 23:29:04 +00:00
// 3. Mean err and variance
2019-07-16 15:41:12 +00:00
double error_mean = arma : : mean ( err ) ;
double error_var = arma : : var ( err ) ;
// 4. Peaks
double max_error = arma : : max ( err ) ;
double min_error = arma : : min ( err ) ;
2019-08-18 23:29:04 +00:00
// 5. report
2019-07-16 15:41:12 +00:00
std : : streamsize ss = std : : cout . precision ( ) ;
std : : cout < < std : : setprecision ( 10 ) < < data_title < < " Double diff Pseudorange RMSE = "
< < rmse < < " , mean = " < < error_mean
< < " , stdev = " < < sqrt ( error_var )
< < " (max,min) = " < < max_error
< < " , " < < min_error
2020-07-07 16:53:50 +00:00
< < " [meters] \n " ;
2019-07-16 15:41:12 +00:00
std : : cout . precision ( ss ) ;
2024-04-29 06:27:33 +00:00
// plots
# if USE_GLOG_AND_GFLAGS
2019-07-16 15:41:12 +00:00
if ( FLAGS_show_plots )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_show_plots ) )
# endif
2019-07-16 15:41:12 +00:00
{
Gnuplot g3 ( " linespoints " ) ;
g3 . set_title ( data_title + " Double diff Pseudorange error [m] " ) ;
g3 . set_grid ( ) ;
g3 . set_xlabel ( " Time [s] " ) ;
g3 . set_ylabel ( " Double diff Pseudorange error [m] " ) ;
2019-08-18 23:29:04 +00:00
// conversion between arma::vec and std:vector
2019-07-16 15:41:12 +00:00
std : : vector < double > range_error_m ( err . colptr ( 0 ) , err . colptr ( 0 ) + err . n_rows ) ;
g3 . cmd ( " set key box opaque " ) ;
g3 . plot_xy ( time_vector , range_error_m ,
" Double diff Pseudorrange error " ) ;
g3 . set_legend ( ) ;
g3 . savetops ( data_title + " double_diff_pseudorrange_error " ) ;
g3 . showonscreen ( ) ; // window output
}
2018-08-07 18:16:43 +00:00
2019-08-18 23:29:04 +00:00
// check results against the test tolerance
2019-11-12 17:35:55 +00:00
if ( ! std : : isnan ( rmse ) )
2019-11-12 16:49:18 +00:00
{
ASSERT_LT ( rmse , 3.0 ) ;
ASSERT_LT ( error_mean , 1.0 ) ;
ASSERT_GT ( error_mean , - 1.0 ) ;
ASSERT_LT ( error_var , 10.0 ) ;
2019-11-12 22:18:41 +00:00
ASSERT_LT ( max_error , 15.0 ) ;
ASSERT_GT ( min_error , - 15.0 ) ;
2019-11-12 16:49:18 +00:00
}
2019-07-16 15:41:12 +00:00
}
else
{
2020-07-07 16:53:50 +00:00
std : : cout < < " Problem with observables in " < < data_title < < ' \n ' ;
2018-07-17 16:31:55 +00:00
}
2017-04-12 15:04:51 +00:00
}
2019-11-14 11:15:41 +00:00
2018-08-07 18:16:43 +00:00
bool HybridObservablesTest : : ReadRinexObs ( std : : vector < arma : : mat > * obs_vec , Gnss_Synchro gnss )
{
// Open and read reference RINEX observables file
try
{
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2022-07-05 11:46:58 +00:00
gnsstk : : Rinex3ObsStream r_ref ( FLAGS_filename_rinex_obs ) ;
2024-04-29 06:27:33 +00:00
# else
gnsstk : : Rinex3ObsStream r_ref ( absl : : GetFlag ( FLAGS_filename_rinex_obs ) ) ;
# endif
2018-08-07 18:16:43 +00:00
r_ref . exceptions ( std : : ios : : failbit ) ;
2022-07-05 11:46:58 +00:00
gnsstk : : Rinex3ObsData r_ref_data ;
gnsstk : : Rinex3ObsHeader r_ref_header ;
2018-08-07 18:16:43 +00:00
2022-07-05 11:46:58 +00:00
gnsstk : : RinexDatum dataobj ;
2018-08-07 18:16:43 +00:00
r_ref > > r_ref_header ;
2017-08-11 03:18:38 +00:00
2018-08-07 18:16:43 +00:00
std : : vector < bool > first_row ;
2022-07-05 11:46:58 +00:00
gnsstk : : SatID prn ;
2018-08-07 18:16:43 +00:00
for ( unsigned int n = 0 ; n < gnss_synchro_vec . size ( ) ; n + + )
{
first_row . push_back ( true ) ;
obs_vec - > push_back ( arma : : zeros < arma : : mat > ( 1 , 4 ) ) ;
}
while ( r_ref > > r_ref_data )
{
for ( unsigned int n = 0 ; n < gnss_synchro_vec . size ( ) ; n + + )
{
int myprn = gnss_synchro_vec . at ( n ) . PRN ;
switch ( gnss . System )
{
case ' G ' :
2020-12-02 13:27:59 +00:00
# if OLD_GPSTK
2022-07-05 11:46:58 +00:00
prn = gnsstk : : SatID ( myprn , gnsstk : : SatID : : systemGPS ) ;
2020-12-02 13:27:59 +00:00
# else
2022-07-05 11:46:58 +00:00
prn = gnsstk : : SatID ( myprn , gnsstk : : SatelliteSystem : : GPS ) ;
2020-12-02 13:27:59 +00:00
# endif
2018-08-07 18:16:43 +00:00
break ;
case ' E ' :
2020-12-02 13:27:59 +00:00
# if OLD_GPSTK
2022-07-05 11:46:58 +00:00
prn = gnsstk : : SatID ( myprn , gnsstk : : SatID : : systemGalileo ) ;
2020-12-02 13:27:59 +00:00
# else
2022-07-05 11:46:58 +00:00
prn = gnsstk : : SatID ( myprn , gnsstk : : SatelliteSystem : : Galileo ) ;
2020-12-02 13:27:59 +00:00
# endif
2018-08-07 18:16:43 +00:00
break ;
default :
2020-12-02 13:27:59 +00:00
# if OLD_GPSTK
2022-07-05 11:46:58 +00:00
prn = gnsstk : : SatID ( myprn , gnsstk : : SatID : : systemGPS ) ;
2020-12-02 13:27:59 +00:00
# else
2022-07-05 11:46:58 +00:00
prn = gnsstk : : SatID ( myprn , gnsstk : : SatelliteSystem : : GPS ) ;
2020-12-02 13:27:59 +00:00
# endif
2018-08-07 18:16:43 +00:00
}
2022-07-05 11:46:58 +00:00
gnsstk : : CommonTime time = r_ref_data . time ;
2022-07-10 17:19:37 +00:00
# if GNSSTK_OLDER_THAN_9
2022-07-05 11:46:58 +00:00
double sow ( static_cast < gnsstk : : GPSWeekSecond > ( time ) . sow ) ;
2022-07-10 17:19:37 +00:00
# else
gnsstk : : GPSWeekSecond gws ( time ) ;
double sow ( gws . getSOW ( ) ) ;
# endif
2019-02-11 17:38:42 +00:00
auto pointer = r_ref_data . obs . find ( prn ) ;
2018-08-07 18:16:43 +00:00
if ( pointer = = r_ref_data . obs . end ( ) )
{
// PRN not present; do nothing
}
else
{
if ( first_row . at ( n ) = = false )
{
2019-08-18 23:29:04 +00:00
// insert next column
2018-08-07 18:16:43 +00:00
obs_vec - > at ( n ) . insert_rows ( obs_vec - > at ( n ) . n_rows , 1 ) ;
}
else
{
first_row . at ( n ) = false ;
}
if ( strcmp ( " 1C \0 " , gnss . Signal ) = = 0 )
{
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 0 ) = sow ;
dataobj = r_ref_data . getObs ( prn , " C1C " , r_ref_header ) ;
2019-08-18 23:29:04 +00:00
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 1 ) = dataobj . data ; // C1C P1 (psudorange L1)
2018-08-07 18:16:43 +00:00
dataobj = r_ref_data . getObs ( prn , " D1C " , r_ref_header ) ;
2019-08-18 23:29:04 +00:00
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 2 ) = dataobj . data ; // D1C Carrier Doppler
2018-08-07 18:16:43 +00:00
dataobj = r_ref_data . getObs ( prn , " L1C " , r_ref_header ) ;
2019-08-18 23:29:04 +00:00
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 3 ) = dataobj . data ; // L1C Carrier Phase
2018-08-07 18:16:43 +00:00
}
else if ( strcmp ( " 1B \0 " , gnss . Signal ) = = 0 )
{
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 0 ) = sow ;
dataobj = r_ref_data . getObs ( prn , " C1B " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 1 ) = dataobj . data ;
dataobj = r_ref_data . getObs ( prn , " D1B " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 2 ) = dataobj . data ;
dataobj = r_ref_data . getObs ( prn , " L1B " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 3 ) = dataobj . data ;
}
2019-08-18 23:29:04 +00:00
else if ( strcmp ( " 2S \0 " , gnss . Signal ) = = 0 ) // L2M
2018-08-07 18:16:43 +00:00
{
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 0 ) = sow ;
dataobj = r_ref_data . getObs ( prn , " C2S " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 1 ) = dataobj . data ;
dataobj = r_ref_data . getObs ( prn , " D2S " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 2 ) = dataobj . data ;
dataobj = r_ref_data . getObs ( prn , " L2S " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 3 ) = dataobj . data ;
}
else if ( strcmp ( " L5 \0 " , gnss . Signal ) = = 0 )
{
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 0 ) = sow ;
dataobj = r_ref_data . getObs ( prn , " C5I " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 1 ) = dataobj . data ;
dataobj = r_ref_data . getObs ( prn , " D5I " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 2 ) = dataobj . data ;
dataobj = r_ref_data . getObs ( prn , " L5I " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 3 ) = dataobj . data ;
}
2019-08-18 23:29:04 +00:00
else if ( strcmp ( " 5X \0 " , gnss . Signal ) = = 0 ) // Simulator gives RINEX with E5a+E5b. Doppler and accumulated Carrier phase WILL differ
2018-08-07 18:16:43 +00:00
{
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 0 ) = sow ;
dataobj = r_ref_data . getObs ( prn , " C8I " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 1 ) = dataobj . data ;
dataobj = r_ref_data . getObs ( prn , " D8I " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 2 ) = dataobj . data ;
dataobj = r_ref_data . getObs ( prn , " L8I " , r_ref_header ) ;
obs_vec - > at ( n ) ( obs_vec - > at ( n ) . n_rows - 1 , 3 ) = dataobj . data ;
}
else
{
2020-07-07 16:53:50 +00:00
std : : cout < < " ReadRinexObs unknown signal requested: " < < gnss . Signal < < ' \n ' ;
2018-08-07 18:16:43 +00:00
return false ;
}
}
}
} // end while
} // End of 'try' block
2022-07-05 11:46:58 +00:00
catch ( const gnsstk : : FFStreamError & e )
2018-08-07 18:16:43 +00:00
{
std : : cout < < e ;
return false ;
}
2022-07-05 11:46:58 +00:00
catch ( const gnsstk : : Exception & e )
2018-08-07 18:16:43 +00:00
{
std : : cout < < e ;
return false ;
}
catch ( const std : : exception & e )
{
std : : cout < < " Exception: " < < e . what ( ) ;
2020-07-07 16:53:50 +00:00
std : : cout < < " unknown error. I don't feel so well... \n " ;
2018-08-07 18:16:43 +00:00
return false ;
}
2020-07-07 16:53:50 +00:00
std : : cout < < " ReadRinexObs info: \n " ;
2018-08-07 18:16:43 +00:00
for ( unsigned int n = 0 ; n < gnss_synchro_vec . size ( ) ; n + + )
{
2020-07-07 16:53:50 +00:00
std : : cout < < " SAT PRN " < < gnss_synchro_vec . at ( n ) . PRN < < " RINEX epoch read: " < < obs_vec - > at ( n ) . n_rows < < ' \n ' ;
2018-08-07 18:16:43 +00:00
}
return true ;
}
2019-11-14 11:15:41 +00:00
2017-04-12 15:04:51 +00:00
TEST_F ( HybridObservablesTest , ValidationOfResults )
{
// Configure the signal generator
configure_generator ( ) ;
// Generate signal raw signal samples and observations RINEX file
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-02-26 11:33:40 +00:00
if ( FLAGS_disable_generator = = false )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_disable_generator ) = = false )
# endif
2017-08-11 03:18:38 +00:00
{
generate_signal ( ) ;
}
2017-04-12 15:04:51 +00:00
2017-08-11 03:18:38 +00:00
std : : chrono : : time_point < std : : chrono : : system_clock > start , end ;
2017-08-11 11:11:38 +00:00
std : : chrono : : duration < double > elapsed_seconds ( 0 ) ;
2017-04-12 15:04:51 +00:00
2018-08-07 18:16:43 +00:00
// use generator or use an external capture file
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
if ( FLAGS_enable_external_signal_file )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_enable_external_signal_file ) )
# endif
2018-08-07 18:16:43 +00:00
{
2019-08-18 23:29:04 +00:00
// create and configure an acquisition block and perform an acquisition to obtain the synchronization parameters
2018-08-07 18:16:43 +00:00
ASSERT_EQ ( acquire_signal ( ) , true ) ;
}
else
{
Gnss_Synchro tmp_gnss_synchro ;
tmp_gnss_synchro . System = ' G ' ;
std : : string signal = " 1C " ;
signal . copy ( tmp_gnss_synchro . Signal , 2 , 0 ) ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
std : : istringstream ss ( FLAGS_test_satellite_PRN_list ) ;
2024-04-29 06:27:33 +00:00
# else
std : : istringstream ss ( absl : : GetFlag ( FLAGS_test_satellite_PRN_list ) ) ;
# endif
2018-08-07 18:16:43 +00:00
std : : string token ;
2017-04-12 15:04:51 +00:00
2018-08-07 18:16:43 +00:00
while ( std : : getline ( ss , token , ' , ' ) )
{
tmp_gnss_synchro . PRN = boost : : lexical_cast < int > ( token ) ;
gnss_synchro_vec . push_back ( tmp_gnss_synchro ) ;
}
2018-07-26 17:25:10 +00:00
}
2017-04-12 15:04:51 +00:00
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
configure_receiver ( FLAGS_PLL_bw_hz_start ,
FLAGS_DLL_bw_hz_start ,
FLAGS_PLL_narrow_bw_hz ,
FLAGS_DLL_narrow_bw_hz ,
2018-09-18 15:14:33 +00:00
FLAGS_extend_correlation_symbols ,
FLAGS_smoother_length ,
FLAGS_high_dyn ) ;
2024-04-29 06:27:33 +00:00
# else
configure_receiver ( absl : : GetFlag ( FLAGS_PLL_bw_hz_start ) ,
absl : : GetFlag ( FLAGS_DLL_bw_hz_start ) ,
absl : : GetFlag ( FLAGS_PLL_narrow_bw_hz ) ,
absl : : GetFlag ( FLAGS_DLL_narrow_bw_hz ) ,
absl : : GetFlag ( FLAGS_extend_correlation_symbols ) ,
absl : : GetFlag ( FLAGS_smoother_length ) ,
absl : : GetFlag ( FLAGS_high_dyn ) ) ;
# endif
2018-08-07 18:16:43 +00:00
2019-02-11 20:13:02 +00:00
for ( auto & n : gnss_synchro_vec )
2018-08-07 18:16:43 +00:00
{
2019-08-18 23:29:04 +00:00
// setup the signal synchronization, simulating an acquisition
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
if ( ! FLAGS_enable_external_signal_file )
2024-04-29 06:27:33 +00:00
# else
if ( ! absl : : GetFlag ( FLAGS_enable_external_signal_file ) )
# endif
2018-08-07 18:16:43 +00:00
{
2019-08-18 23:29:04 +00:00
// based on true observables metadata (for custom sdr generator)
// open true observables log file written by the simulator or based on provided RINEX obs
2020-12-02 13:27:59 +00:00
std : : vector < std : : shared_ptr < Tracking_True_Obs_Reader > > true_reader_vec ;
2019-08-18 23:29:04 +00:00
// read true data from the generator logs
2019-02-22 14:57:15 +00:00
true_reader_vec . push_back ( std : : make_shared < Tracking_True_Obs_Reader > ( ) ) ;
2020-07-07 16:53:50 +00:00
std : : cout < < " Loading true observable data for PRN " < < n . PRN < < ' \n ' ;
2018-08-07 18:16:43 +00:00
std : : string true_obs_file = std : : string ( " ./gps_l1_ca_obs_prn " ) ;
2019-02-11 17:38:42 +00:00
true_obs_file . append ( std : : to_string ( n . PRN ) ) ;
2018-08-07 18:16:43 +00:00
true_obs_file . append ( " .dat " ) ;
ASSERT_NO_THROW ( {
if ( true_reader_vec . back ( ) - > open_obs_file ( true_obs_file ) = = false )
{
throw std : : exception ( ) ;
} ;
} ) < < " Failure opening true observables file " ;
// load acquisition data based on the first epoch of the true observations
ASSERT_NO_THROW ( {
if ( true_reader_vec . back ( ) - > read_binary_obs ( ) = = false )
{
throw std : : exception ( ) ;
} ;
} ) < < " Failure reading true observables file " ;
2019-08-18 23:29:04 +00:00
// restart the epoch counter
2018-08-07 18:16:43 +00:00
true_reader_vec . back ( ) - > restart ( ) ;
std : : cout < < " Initial Doppler [Hz]= " < < true_reader_vec . back ( ) - > doppler_l1_hz < < " Initial code delay [Chips]= "
2020-07-07 16:53:50 +00:00
< < true_reader_vec . back ( ) - > prn_delay_chips < < ' \n ' ;
2019-08-31 09:37:29 +00:00
n . Acq_delay_samples = ( GPS_L1_CA_CODE_LENGTH_CHIPS - true_reader_vec . back ( ) - > prn_delay_chips / GPS_L1_CA_CODE_LENGTH_CHIPS ) * baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD_S ;
2019-02-11 17:38:42 +00:00
n . Acq_doppler_hz = true_reader_vec . back ( ) - > doppler_l1_hz ;
n . Acq_samplestamp_samples = 0 ;
2018-08-07 18:16:43 +00:00
}
else
{
2019-08-18 23:29:04 +00:00
// based on the signal acquisition process
2019-02-11 17:38:42 +00:00
std : : cout < < " Estimated Initial Doppler " < < n . Acq_doppler_hz
< < " [Hz], estimated Initial code delay " < < n . Acq_delay_samples < < " [Samples] "
2020-07-07 16:53:50 +00:00
< < " Acquisition SampleStamp is " < < n . Acq_samplestamp_samples < < ' \n ' ;
2019-02-11 17:38:42 +00:00
n . Acq_samplestamp_samples = 0 ;
2018-08-07 18:16:43 +00:00
}
}
2020-12-02 13:27:59 +00:00
std : : vector < std : : shared_ptr < TrackingInterface > > tracking_ch_vec ;
std : : vector < std : : shared_ptr < TelemetryDecoderInterface > > tlm_ch_vec ;
2017-04-12 15:04:51 +00:00
2018-07-26 17:25:10 +00:00
std : : vector < gr : : blocks : : null_sink : : sptr > null_sink_vec ;
for ( unsigned int n = 0 ; n < gnss_synchro_vec . size ( ) ; n + + )
{
2019-08-18 23:29:04 +00:00
// set channels ids
2018-07-26 17:25:10 +00:00
gnss_synchro_vec . at ( n ) . Channel_ID = n ;
2017-04-12 15:04:51 +00:00
2019-08-18 23:29:04 +00:00
// create the tracking channels and create the telemetry decoders
2017-04-12 15:04:51 +00:00
2020-07-13 13:17:15 +00:00
std : : shared_ptr < GNSSBlockInterface > trk_ = factory - > GetBlock ( config . get ( ) , " Tracking " , 1 , 1 ) ;
2018-08-07 18:16:43 +00:00
tracking_ch_vec . push_back ( std : : dynamic_pointer_cast < TrackingInterface > ( trk_ ) ) ;
2020-07-13 13:17:15 +00:00
std : : shared_ptr < GNSSBlockInterface > tlm_ = factory - > GetBlock ( config . get ( ) , " TelemetryDecoder " , 1 , 1 ) ;
2018-08-07 18:16:43 +00:00
tlm_ch_vec . push_back ( std : : dynamic_pointer_cast < TelemetryDecoderInterface > ( tlm_ ) ) ;
2017-04-12 15:04:51 +00:00
2019-08-18 23:29:04 +00:00
// create null sinks for observables output
2018-07-26 17:25:10 +00:00
null_sink_vec . push_back ( gr : : blocks : : null_sink : : make ( sizeof ( Gnss_Synchro ) ) ) ;
2017-04-12 15:04:51 +00:00
2018-07-26 17:25:10 +00:00
ASSERT_NO_THROW ( {
tlm_ch_vec . back ( ) - > set_channel ( gnss_synchro_vec . at ( n ) . Channel_ID ) ;
2018-08-07 18:16:43 +00:00
switch ( gnss_synchro_master . System )
{
case ' G ' :
tlm_ch_vec . back ( ) - > set_satellite ( Gnss_Satellite ( std : : string ( " GPS " ) , gnss_synchro_vec . at ( n ) . PRN ) ) ;
break ;
case ' E ' :
tlm_ch_vec . back ( ) - > set_satellite ( Gnss_Satellite ( std : : string ( " Galileo " ) , gnss_synchro_vec . at ( n ) . PRN ) ) ;
break ;
default :
tlm_ch_vec . back ( ) - > set_satellite ( Gnss_Satellite ( std : : string ( " GPS " ) , gnss_synchro_vec . at ( n ) . PRN ) ) ;
}
2018-07-26 17:25:10 +00:00
} ) < < " Failure setting gnss_synchro. " ;
2017-04-12 15:04:51 +00:00
2018-07-26 17:25:10 +00:00
ASSERT_NO_THROW ( {
tracking_ch_vec . back ( ) - > set_channel ( gnss_synchro_vec . at ( n ) . Channel_ID ) ;
} ) < < " Failure setting channel. " ;
2017-04-12 15:04:51 +00:00
2018-07-26 17:25:10 +00:00
ASSERT_NO_THROW ( {
tracking_ch_vec . back ( ) - > set_gnss_synchro ( & gnss_synchro_vec . at ( n ) ) ;
} ) < < " Failure setting gnss_synchro. " ;
}
2017-04-12 15:04:51 +00:00
2020-02-26 21:40:00 +00:00
auto top_block_tlm = gr : : make_top_block ( " Telemetry_Decoder test " ) ;
2020-04-02 21:59:35 +00:00
auto dummy_msg_rx_trk = HybridObservablesTest_msg_rx_make ( ) ;
auto dummy_tlm_msg_rx = HybridObservablesTest_tlm_msg_rx_make ( ) ;
2019-08-18 23:29:04 +00:00
// Observables
2020-06-18 09:49:28 +00:00
std : : shared_ptr < ObservablesInterface > observables = std : : make_shared < HybridObservables > ( config . get ( ) , " Observables " , tracking_ch_vec . size ( ) + 1 , tracking_ch_vec . size ( ) ) ;
2017-04-12 15:04:51 +00:00
2019-02-11 20:13:02 +00:00
for ( auto & n : tracking_ch_vec )
2018-07-26 17:25:10 +00:00
{
ASSERT_NO_THROW ( {
2020-02-26 21:40:00 +00:00
n - > connect ( top_block_tlm ) ;
2018-07-26 17:25:10 +00:00
} ) < < " Failure connecting tracking to the top_block. " ;
}
2017-04-12 15:04:51 +00:00
2018-03-03 01:03:39 +00:00
ASSERT_NO_THROW ( {
2018-08-07 18:16:43 +00:00
std : : string file ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
if ( ! FLAGS_enable_external_signal_file )
{
file = " ./ " + filename_raw_data ;
}
else
{
file = FLAGS_signal_file ;
}
2024-04-29 06:27:33 +00:00
# else
if ( ! absl : : GetFlag ( FLAGS_enable_external_signal_file ) )
{
file = " ./ " + filename_raw_data ;
}
else
{
file = absl : : GetFlag ( FLAGS_signal_file ) ;
}
# endif
2018-03-03 01:03:39 +00:00
const char * file_name = file . c_str ( ) ;
2017-04-12 15:04:51 +00:00
gr : : blocks : : file_source : : sptr file_source = gr : : blocks : : file_source : : make ( sizeof ( int8_t ) , file_name , false ) ;
2018-03-03 01:03:39 +00:00
gr : : blocks : : interleaved_char_to_complex : : sptr gr_interleaved_char_to_complex = gr : : blocks : : interleaved_char_to_complex : : make ( ) ;
2018-08-07 18:16:43 +00:00
int observable_interval_ms = 20 ;
gnss_sdr_sample_counter_sptr samp_counter = gnss_sdr_make_sample_counter ( static_cast < double > ( baseband_sampling_freq ) , observable_interval_ms , sizeof ( gr_complex ) ) ;
2020-02-26 21:40:00 +00:00
top_block_tlm - > connect ( file_source , 0 , gr_interleaved_char_to_complex , 0 ) ;
top_block_tlm - > connect ( gr_interleaved_char_to_complex , 0 , samp_counter , 0 ) ;
2018-02-26 11:33:40 +00:00
2018-07-26 17:25:10 +00:00
for ( unsigned int n = 0 ; n < tracking_ch_vec . size ( ) ; n + + )
{
2020-02-26 21:40:00 +00:00
top_block_tlm - > connect ( gr_interleaved_char_to_complex , 0 , tracking_ch_vec . at ( n ) - > get_left_block ( ) , 0 ) ;
top_block_tlm - > connect ( tracking_ch_vec . at ( n ) - > get_right_block ( ) , 0 , tlm_ch_vec . at ( n ) - > get_left_block ( ) , 0 ) ;
top_block_tlm - > connect ( tlm_ch_vec . at ( n ) - > get_right_block ( ) , 0 , observables - > get_left_block ( ) , n ) ;
top_block_tlm - > msg_connect ( tracking_ch_vec . at ( n ) - > get_right_block ( ) , pmt : : mp ( " events " ) , dummy_msg_rx_trk , pmt : : mp ( " events " ) ) ;
top_block_tlm - > connect ( observables - > get_right_block ( ) , n , null_sink_vec . at ( n ) , 0 ) ;
2018-07-26 17:25:10 +00:00
}
2019-08-18 23:29:04 +00:00
// connect sample counter and timmer to the last channel in observables block (extra channel)
2020-02-26 21:40:00 +00:00
top_block_tlm - > connect ( samp_counter , 0 , observables - > get_left_block ( ) , tracking_ch_vec . size ( ) ) ;
2017-04-12 15:04:51 +00:00
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2019-08-18 23:29:04 +00:00
file_source - > seek ( 2 * FLAGS_skip_samples , 0 ) ; // skip head. ibyte, two bytes per complex sample
2024-04-29 06:27:33 +00:00
# else
file_source - > seek ( 2 * absl : : GetFlag ( FLAGS_skip_samples ) , 0 ) ; // skip head. ibyte, two bytes per complex sample
# endif
2017-10-29 11:26:06 +00:00
} ) < < " Failure connecting the blocks. " ;
2017-04-12 15:04:51 +00:00
2019-02-11 20:13:02 +00:00
for ( auto & n : tracking_ch_vec )
2018-07-26 17:25:10 +00:00
{
2019-02-11 17:38:42 +00:00
n - > start_tracking ( ) ;
2018-07-26 17:25:10 +00:00
}
2017-04-12 15:04:51 +00:00
2018-03-03 01:03:39 +00:00
EXPECT_NO_THROW ( {
2017-08-11 03:18:38 +00:00
start = std : : chrono : : system_clock : : now ( ) ;
2020-02-26 21:40:00 +00:00
top_block_tlm - > run ( ) ; // Start threads and wait
2017-08-11 03:18:38 +00:00
end = std : : chrono : : system_clock : : now ( ) ;
elapsed_seconds = end - start ;
2017-10-29 11:26:06 +00:00
} ) < < " Failure running the top_block. " ;
2017-04-12 15:04:51 +00:00
2019-08-18 23:29:04 +00:00
// check results
2018-08-07 18:16:43 +00:00
// Matrices for storing columnwise true GPS time, Range, Doppler and Carrier phase
std : : vector < arma : : mat > true_obs_vec ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-08-07 18:16:43 +00:00
if ( ! FLAGS_enable_external_signal_file )
2024-04-29 06:27:33 +00:00
# else
if ( ! absl : : GetFlag ( FLAGS_enable_external_signal_file ) )
# endif
2018-08-07 18:16:43 +00:00
{
2019-08-18 23:29:04 +00:00
// load the true values
2019-02-22 14:57:15 +00:00
True_Observables_Reader true_observables ;
2018-08-07 18:16:43 +00:00
ASSERT_NO_THROW ( {
if ( true_observables . open_obs_file ( std : : string ( " ./obs_out.bin " ) ) = = false )
{
throw std : : exception ( ) ;
}
} ) < < " Failure opening true observables file " ;
2017-04-12 15:04:51 +00:00
2019-02-11 17:38:42 +00:00
auto nepoch = static_cast < unsigned int > ( true_observables . num_epochs ( ) ) ;
2017-04-12 15:04:51 +00:00
2020-07-07 16:53:50 +00:00
std : : cout < < " True observation epochs = " < < nepoch < < ' \n ' ;
2017-04-12 15:04:51 +00:00
2018-08-07 18:16:43 +00:00
true_observables . restart ( ) ;
2018-08-10 19:16:10 +00:00
int64_t epoch_counter = 0 ;
2018-08-07 18:16:43 +00:00
for ( unsigned int n = 0 ; n < tracking_ch_vec . size ( ) ; n + + )
{
true_obs_vec . push_back ( arma : : zeros < arma : : mat > ( nepoch , 4 ) ) ;
}
2018-07-26 17:25:10 +00:00
2018-08-07 18:16:43 +00:00
ASSERT_NO_THROW ( {
while ( true_observables . read_binary_obs ( ) )
2018-03-20 16:24:16 +00:00
{
2018-08-07 18:16:43 +00:00
for ( unsigned int n = 0 ; n < true_obs_vec . size ( ) ; n + + )
2018-07-26 17:25:10 +00:00
{
2018-08-07 18:16:43 +00:00
if ( round ( true_observables . prn [ n ] ) ! = gnss_synchro_vec . at ( n ) . PRN )
{
std : : cout < < " True observables SV PRN does not match measured ones: "
2020-07-07 16:53:50 +00:00
< < round ( true_observables . prn [ n ] ) < < " vs. " < < gnss_synchro_vec . at ( n ) . PRN < < ' \n ' ;
2018-08-07 18:16:43 +00:00
throw std : : exception ( ) ;
}
true_obs_vec . at ( n ) ( epoch_counter , 0 ) = true_observables . gps_time_sec [ n ] ;
true_obs_vec . at ( n ) ( epoch_counter , 1 ) = true_observables . dist_m [ n ] ;
true_obs_vec . at ( n ) ( epoch_counter , 2 ) = true_observables . doppler_l1_hz [ n ] ;
true_obs_vec . at ( n ) ( epoch_counter , 3 ) = true_observables . acc_carrier_phase_l1_cycles [ n ] ;
2018-07-26 17:25:10 +00:00
}
2018-08-07 18:16:43 +00:00
epoch_counter + + ;
2018-03-20 16:24:16 +00:00
}
2018-08-07 18:16:43 +00:00
} ) ;
}
else
{
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-11-29 20:29:21 +00:00
if ( ! FLAGS_duplicated_satellites_test )
2024-04-29 06:27:33 +00:00
# else
if ( ! absl : : GetFlag ( FLAGS_duplicated_satellites_test ) )
# endif
2018-11-29 20:29:21 +00:00
{
ASSERT_EQ ( ReadRinexObs ( & true_obs_vec , gnss_synchro_master ) , true )
< < " Failure reading RINEX file " ;
}
2018-08-07 18:16:43 +00:00
}
2019-08-18 23:29:04 +00:00
// read measured values
2019-02-22 14:57:15 +00:00
Observables_Dump_Reader estimated_observables ( tracking_ch_vec . size ( ) ) ;
2017-04-12 15:04:51 +00:00
ASSERT_NO_THROW ( {
2018-03-20 16:24:16 +00:00
if ( estimated_observables . open_obs_file ( std : : string ( " ./observables.dat " ) ) = = false )
{
throw std : : exception ( ) ;
}
2017-10-29 11:26:06 +00:00
} ) < < " Failure opening dump observables file " ;
2017-04-12 15:04:51 +00:00
2019-02-11 17:38:42 +00:00
auto nepoch = static_cast < unsigned int > ( estimated_observables . num_epochs ( ) ) ;
2020-07-07 16:53:50 +00:00
std : : cout < < " Measured observations epochs = " < < nepoch < < ' \n ' ;
2017-04-12 15:04:51 +00:00
2018-02-26 11:33:40 +00:00
// Matrices for storing columnwise measured RX_time, TOW, Doppler, Carrier phase and Pseudorange
2018-07-26 17:25:10 +00:00
std : : vector < arma : : mat > measured_obs_vec ;
2018-08-10 19:16:10 +00:00
std : : vector < int64_t > epoch_counters_vec ;
2018-07-26 17:25:10 +00:00
for ( unsigned int n = 0 ; n < tracking_ch_vec . size ( ) ; n + + )
{
measured_obs_vec . push_back ( arma : : zeros < arma : : mat > ( nepoch , 5 ) ) ;
epoch_counters_vec . push_back ( 0 ) ;
}
2017-04-12 15:04:51 +00:00
estimated_observables . restart ( ) ;
2018-03-20 16:24:16 +00:00
while ( estimated_observables . read_binary_obs ( ) )
2018-02-26 11:33:40 +00:00
{
2018-07-26 17:25:10 +00:00
for ( unsigned int n = 0 ; n < measured_obs_vec . size ( ) ; n + + )
2018-03-20 16:24:16 +00:00
{
2018-07-26 17:25:10 +00:00
if ( static_cast < bool > ( estimated_observables . valid [ n ] ) )
{
measured_obs_vec . at ( n ) ( epoch_counters_vec . at ( n ) , 0 ) = estimated_observables . RX_time [ n ] ;
measured_obs_vec . at ( n ) ( epoch_counters_vec . at ( n ) , 1 ) = estimated_observables . TOW_at_current_symbol_s [ n ] ;
measured_obs_vec . at ( n ) ( epoch_counters_vec . at ( n ) , 2 ) = estimated_observables . Carrier_Doppler_hz [ n ] ;
measured_obs_vec . at ( n ) ( epoch_counters_vec . at ( n ) , 3 ) = estimated_observables . Acc_carrier_phase_hz [ n ] ;
measured_obs_vec . at ( n ) ( epoch_counters_vec . at ( n ) , 4 ) = estimated_observables . Pseudorange_m [ n ] ;
epoch_counters_vec . at ( n ) + + ;
}
2018-03-20 16:24:16 +00:00
}
2018-02-26 11:33:40 +00:00
}
2017-04-12 15:04:51 +00:00
2019-08-18 23:29:04 +00:00
// Cut measurement tail zeros
2018-07-26 17:25:10 +00:00
arma : : uvec index ;
2019-02-11 20:13:02 +00:00
for ( auto & n : measured_obs_vec )
2018-03-20 16:24:16 +00:00
{
2019-02-11 17:38:42 +00:00
index = arma : : find ( n . col ( 0 ) > 0.0 , 1 , " last " ) ;
if ( ( ! index . empty ( ) ) and index ( 0 ) < ( nepoch - 1 ) )
2018-07-26 17:25:10 +00:00
{
2019-02-11 17:38:42 +00:00
n . shed_rows ( index ( 0 ) + 1 , nepoch - 1 ) ;
2018-07-26 17:25:10 +00:00
}
2018-03-20 16:24:16 +00:00
}
2017-04-12 15:04:51 +00:00
2024-04-29 06:27:33 +00:00
// Cut measurement initial transitory of the measurements
# if USE_GLOG_AND_GFLAGS
2018-07-26 17:25:10 +00:00
double initial_transitory_s = FLAGS_skip_obs_transitory_s ;
2024-04-29 06:27:33 +00:00
# else
double initial_transitory_s = absl : : GetFlag ( FLAGS_skip_obs_transitory_s ) ;
# endif
2018-07-26 17:25:10 +00:00
for ( unsigned int n = 0 ; n < measured_obs_vec . size ( ) ; n + + )
2018-07-17 16:31:55 +00:00
{
2018-07-26 17:25:10 +00:00
index = arma : : find ( measured_obs_vec . at ( n ) . col ( 0 ) > = ( measured_obs_vec . at ( n ) ( 0 , 0 ) + initial_transitory_s ) , 1 , " first " ) ;
2019-02-11 17:38:42 +00:00
if ( ( ! index . empty ( ) ) and ( index ( 0 ) > 0 ) )
2018-07-26 17:25:10 +00:00
{
measured_obs_vec . at ( n ) . shed_rows ( 0 , index ( 0 ) ) ;
}
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-11-29 20:29:21 +00:00
if ( ! FLAGS_duplicated_satellites_test )
2024-04-29 06:27:33 +00:00
# else
if ( ! absl : : GetFlag ( FLAGS_duplicated_satellites_test ) )
# endif
2018-07-26 17:25:10 +00:00
{
2018-11-29 20:29:21 +00:00
index = arma : : find ( measured_obs_vec . at ( n ) . col ( 0 ) > = true_obs_vec . at ( n ) ( 0 , 0 ) , 1 , " first " ) ;
2019-02-11 17:38:42 +00:00
if ( ( ! index . empty ( ) ) and ( index ( 0 ) > 0 ) )
2018-11-29 20:29:21 +00:00
{
measured_obs_vec . at ( n ) . shed_rows ( 0 , index ( 0 ) ) ;
}
2018-07-26 17:25:10 +00:00
}
2018-03-20 16:24:16 +00:00
}
2018-02-26 11:33:40 +00:00
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-10-06 17:36:25 +00:00
if ( FLAGS_duplicated_satellites_test )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_duplicated_satellites_test ) )
# endif
2018-03-20 16:24:16 +00:00
{
2019-08-18 23:29:04 +00:00
// special test mode for duplicated satellites
2018-10-31 10:06:48 +00:00
std : : vector < unsigned int > prn_pairs ;
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-10-06 17:36:25 +00:00
std : : stringstream ss ( FLAGS_duplicated_satellites_prns ) ;
2024-04-29 06:27:33 +00:00
# else
std : : stringstream ss ( absl : : GetFlag ( FLAGS_duplicated_satellites_prns ) ) ;
# endif
2018-10-31 10:06:48 +00:00
unsigned int i ;
2018-10-06 17:36:25 +00:00
while ( ss > > i )
2018-07-26 17:25:10 +00:00
{
2018-10-06 17:36:25 +00:00
prn_pairs . push_back ( i ) ;
if ( ss . peek ( ) = = ' , ' )
2019-02-11 20:13:02 +00:00
{
ss . ignore ( ) ;
}
2018-10-06 17:36:25 +00:00
}
if ( prn_pairs . size ( ) % 2 ! = 0 )
{
std : : cout < < " Test settings error: duplicated_satellites_prns are even \n " ;
2018-08-07 18:16:43 +00:00
}
else
{
2018-10-06 17:36:25 +00:00
for ( unsigned int n = 0 ; n < prn_pairs . size ( ) ; n = n + 2 )
{
int sat1_ch_id = - 1 ;
int sat2_ch_id = - 1 ;
for ( unsigned int ch = 0 ; ch < measured_obs_vec . size ( ) ; ch + + )
{
2019-08-18 23:29:04 +00:00
if ( epoch_counters_vec . at ( ch ) > 100 ) // discard non-valid channels
2018-10-06 17:36:25 +00:00
{
if ( gnss_synchro_vec . at ( ch ) . PRN = = prn_pairs . at ( n ) )
{
sat1_ch_id = ch ;
}
if ( gnss_synchro_vec . at ( ch ) . PRN = = prn_pairs . at ( n + 1 ) )
{
sat2_ch_id = ch ;
}
}
}
if ( sat1_ch_id ! = - 1 and sat2_ch_id ! = - 1 )
{
2019-08-18 23:29:04 +00:00
// compute single differences for the duplicated satellite
2018-10-06 17:36:25 +00:00
check_results_duplicated_satellite (
measured_obs_vec . at ( sat1_ch_id ) ,
measured_obs_vec . at ( sat2_ch_id ) ,
2018-10-15 15:02:43 +00:00
sat1_ch_id ,
2018-10-06 17:36:25 +00:00
" Duplicated sat [CH " + std : : to_string ( sat1_ch_id ) + " , " + std : : to_string ( sat2_ch_id ) + " ] PRNs " + std : : to_string ( gnss_synchro_vec . at ( sat1_ch_id ) . PRN ) + " , " + std : : to_string ( gnss_synchro_vec . at ( sat2_ch_id ) . PRN ) + " " ) ;
}
else
{
std : : cout < < " Satellites PRNs " < < prn_pairs . at ( n ) < < " and " < < prn_pairs . at ( n ) < < " not found \n " ;
}
}
2018-07-26 17:25:10 +00:00
}
2018-03-20 16:24:16 +00:00
}
2018-10-06 17:36:25 +00:00
else
{
2019-08-18 23:29:04 +00:00
// normal mode
2017-04-12 15:04:51 +00:00
2019-08-18 23:29:04 +00:00
// Correct the clock error using true values (it is not possible for a receiver to correct
// the receiver clock offset error at the observables level because it is required the
// decoding of the ephemeris data and solve the PVT equations)
2017-08-03 15:58:11 +00:00
2019-08-18 23:29:04 +00:00
// Find the reference satellite (the nearest) and compute the receiver time offset at observable level
2018-10-06 17:36:25 +00:00
double min_pr = std : : numeric_limits < double > : : max ( ) ;
unsigned int min_pr_ch_id = 0 ;
for ( unsigned int n = 0 ; n < measured_obs_vec . size ( ) ; n + + )
{
2019-08-18 23:29:04 +00:00
if ( epoch_counters_vec . at ( n ) > 100 ) // discard non-valid channels
2018-10-06 17:36:25 +00:00
{
{
if ( measured_obs_vec . at ( n ) ( 0 , 4 ) < min_pr )
{
min_pr = measured_obs_vec . at ( n ) ( 0 , 4 ) ;
min_pr_ch_id = n ;
}
}
}
else
{
std : : cout < < " PRN " < < gnss_synchro_vec . at ( n ) . PRN < < " has NO observations! \n " ;
}
}
arma : : vec receiver_time_offset_ref_channel_s ;
2019-07-16 15:41:12 +00:00
arma : : uvec index2 ;
index2 = arma : : find ( true_obs_vec . at ( min_pr_ch_id ) . col ( 0 ) > = measured_obs_vec . at ( min_pr_ch_id ) . col ( 0 ) ( 0 ) , 1 , " first " ) ;
if ( ( ! index2 . empty ( ) ) and ( index2 ( 0 ) > 0 ) )
{
2020-07-05 18:20:02 +00:00
receiver_time_offset_ref_channel_s = ( true_obs_vec . at ( min_pr_ch_id ) . col ( 1 ) ( index2 ( 0 ) ) - measured_obs_vec . at ( min_pr_ch_id ) . col ( 4 ) ( 0 ) ) / SPEED_OF_LIGHT_M_S ;
2020-07-07 16:53:50 +00:00
std : : cout < < " Ref. channel initial Receiver time offset " < < receiver_time_offset_ref_channel_s ( 0 ) * 1e3 < < " [ms] \n " ;
2019-07-16 15:41:12 +00:00
}
else
{
ASSERT_NO_THROW (
throw std : : exception ( ) ; )
< < " Error finding observation time epoch in the reference data " ;
}
2018-10-06 17:36:25 +00:00
for ( unsigned int n = 0 ; n < measured_obs_vec . size ( ) ; n + + )
2018-07-26 17:25:10 +00:00
{
2019-08-18 23:29:04 +00:00
// debug save to .mat
2018-10-06 17:36:25 +00:00
std : : vector < double > tmp_vector_x ( true_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) ,
true_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) + true_obs_vec . at ( n ) . col ( 0 ) . n_rows ) ;
std : : vector < double > tmp_vector_y ( true_obs_vec . at ( n ) . col ( 1 ) . colptr ( 0 ) ,
true_obs_vec . at ( n ) . col ( 1 ) . colptr ( 0 ) + true_obs_vec . at ( n ) . col ( 1 ) . n_rows ) ;
save_mat_xy ( tmp_vector_x , tmp_vector_y , std : : string ( " true_pr_ch_ " + std : : to_string ( n ) ) ) ;
std : : vector < double > tmp_vector_x2 ( measured_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) ,
measured_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) + measured_obs_vec . at ( n ) . col ( 0 ) . n_rows ) ;
std : : vector < double > tmp_vector_y2 ( measured_obs_vec . at ( n ) . col ( 4 ) . colptr ( 0 ) ,
measured_obs_vec . at ( n ) . col ( 4 ) . colptr ( 0 ) + measured_obs_vec . at ( n ) . col ( 4 ) . n_rows ) ;
save_mat_xy ( tmp_vector_x2 , tmp_vector_y2 , std : : string ( " measured_pr_ch_ " + std : : to_string ( n ) ) ) ;
std : : vector < double > tmp_vector_x3 ( true_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) ,
true_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) + true_obs_vec . at ( n ) . col ( 0 ) . n_rows ) ;
std : : vector < double > tmp_vector_y3 ( true_obs_vec . at ( n ) . col ( 2 ) . colptr ( 0 ) ,
true_obs_vec . at ( n ) . col ( 2 ) . colptr ( 0 ) + true_obs_vec . at ( n ) . col ( 2 ) . n_rows ) ;
save_mat_xy ( tmp_vector_x3 , tmp_vector_y3 , std : : string ( " true_doppler_ch_ " + std : : to_string ( n ) ) ) ;
std : : vector < double > tmp_vector_x4 ( measured_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) ,
measured_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) + measured_obs_vec . at ( n ) . col ( 0 ) . n_rows ) ;
std : : vector < double > tmp_vector_y4 ( measured_obs_vec . at ( n ) . col ( 2 ) . colptr ( 0 ) ,
measured_obs_vec . at ( n ) . col ( 2 ) . colptr ( 0 ) + measured_obs_vec . at ( n ) . col ( 2 ) . n_rows ) ;
save_mat_xy ( tmp_vector_x4 , tmp_vector_y4 , std : : string ( " measured_doppler_ch_ " + std : : to_string ( n ) ) ) ;
2018-10-10 17:34:51 +00:00
std : : vector < double > tmp_vector_x5 ( true_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) ,
true_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) + true_obs_vec . at ( n ) . col ( 0 ) . n_rows ) ;
std : : vector < double > tmp_vector_y5 ( true_obs_vec . at ( n ) . col ( 3 ) . colptr ( 0 ) ,
true_obs_vec . at ( n ) . col ( 3 ) . colptr ( 0 ) + true_obs_vec . at ( n ) . col ( 3 ) . n_rows ) ;
save_mat_xy ( tmp_vector_x5 , tmp_vector_y5 , std : : string ( " true_cp_ch_ " + std : : to_string ( n ) ) ) ;
std : : vector < double > tmp_vector_x6 ( measured_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) ,
measured_obs_vec . at ( n ) . col ( 0 ) . colptr ( 0 ) + measured_obs_vec . at ( n ) . col ( 0 ) . n_rows ) ;
std : : vector < double > tmp_vector_y6 ( measured_obs_vec . at ( n ) . col ( 3 ) . colptr ( 0 ) ,
measured_obs_vec . at ( n ) . col ( 3 ) . colptr ( 0 ) + measured_obs_vec . at ( n ) . col ( 3 ) . n_rows ) ;
save_mat_xy ( tmp_vector_x6 , tmp_vector_y6 , std : : string ( " measured_cp_ch_ " + std : : to_string ( n ) ) ) ;
2019-08-18 23:29:04 +00:00
if ( epoch_counters_vec . at ( n ) > 100 ) // discard non-valid channels
2018-08-07 18:16:43 +00:00
{
2018-10-06 17:36:25 +00:00
arma : : vec true_TOW_ref_ch_s = true_obs_vec . at ( min_pr_ch_id ) . col ( 0 ) - receiver_time_offset_ref_channel_s ( 0 ) ;
arma : : vec true_TOW_ch_s = true_obs_vec . at ( n ) . col ( 0 ) - receiver_time_offset_ref_channel_s ( 0 ) ;
2019-08-18 23:29:04 +00:00
// Compare measured observables
2018-10-06 17:36:25 +00:00
if ( min_pr_ch_id ! = n )
2018-08-27 16:08:31 +00:00
{
2018-10-06 17:36:25 +00:00
check_results_code_pseudorange ( true_obs_vec . at ( n ) ,
2018-08-27 16:08:31 +00:00
true_obs_vec . at ( min_pr_ch_id ) ,
true_TOW_ch_s ,
true_TOW_ref_ch_s ,
measured_obs_vec . at ( n ) ,
measured_obs_vec . at ( min_pr_ch_id ) ,
" [CH " + std : : to_string ( n ) + " ] PRN " + std : : to_string ( gnss_synchro_vec . at ( n ) . PRN ) + " " ) ;
2024-04-29 06:27:33 +00:00
// Do not compare E5a with E5 RINEX due to the Doppler frequency discrepancy caused by the different center frequencies
// E5a_fc=1176.45e6, E5b_fc=1207.14e6, E5_fc=1191.795e6;
# if USE_GLOG_AND_GFLAGS
2018-10-06 17:36:25 +00:00
if ( strcmp ( " 5X \0 " , gnss_synchro_vec . at ( n ) . Signal ) ! = 0 or FLAGS_compare_with_5X )
2024-04-29 06:27:33 +00:00
# else
if ( strcmp ( " 5X \0 " , gnss_synchro_vec . at ( n ) . Signal ) ! = 0 or absl : : GetFlag ( FLAGS_compare_with_5X ) )
# endif
2018-10-06 17:36:25 +00:00
{
check_results_carrier_phase_double_diff ( true_obs_vec . at ( n ) ,
true_obs_vec . at ( min_pr_ch_id ) ,
true_TOW_ch_s ,
true_TOW_ref_ch_s ,
measured_obs_vec . at ( n ) ,
measured_obs_vec . at ( min_pr_ch_id ) ,
" [CH " + std : : to_string ( n ) + " ] PRN " + std : : to_string ( gnss_synchro_vec . at ( n ) . PRN ) + " " ) ;
check_results_carrier_doppler_double_diff ( true_obs_vec . at ( n ) ,
true_obs_vec . at ( min_pr_ch_id ) ,
true_TOW_ch_s ,
true_TOW_ref_ch_s ,
measured_obs_vec . at ( n ) ,
measured_obs_vec . at ( min_pr_ch_id ) ,
" [CH " + std : : to_string ( n ) + " ] PRN " + std : : to_string ( gnss_synchro_vec . at ( n ) . PRN ) + " " ) ;
}
}
else
{
2020-07-07 16:53:50 +00:00
std : : cout < < " [CH " < < std : : to_string ( n ) < < " ] PRN " < < std : : to_string ( gnss_synchro_vec . at ( n ) . PRN ) < < " is the reference satellite \n " ;
2018-10-06 17:36:25 +00:00
}
2024-04-29 06:27:33 +00:00
# if USE_GLOG_AND_GFLAGS
2018-10-06 17:36:25 +00:00
if ( FLAGS_compute_single_diffs )
2024-04-29 06:27:33 +00:00
# else
if ( absl : : GetFlag ( FLAGS_compute_single_diffs ) )
# endif
2018-10-06 17:36:25 +00:00
{
check_results_carrier_phase ( true_obs_vec . at ( n ) ,
true_TOW_ch_s ,
measured_obs_vec . at ( n ) ,
" [CH " + std : : to_string ( n ) + " ] PRN " + std : : to_string ( gnss_synchro_vec . at ( n ) . PRN ) + " " ) ;
check_results_carrier_doppler ( true_obs_vec . at ( n ) ,
2018-08-27 16:08:31 +00:00
true_TOW_ch_s ,
measured_obs_vec . at ( n ) ,
" [CH " + std : : to_string ( n ) + " ] PRN " + std : : to_string ( gnss_synchro_vec . at ( n ) . PRN ) + " " ) ;
}
2018-08-07 18:16:43 +00:00
}
else
{
2018-10-06 17:36:25 +00:00
std : : cout < < " PRN " < < gnss_synchro_vec . at ( n ) . PRN < < " has NO observations! \n " ;
2018-08-07 18:16:43 +00:00
}
2018-07-26 17:25:10 +00:00
}
}
2020-07-07 16:53:50 +00:00
std : : cout < < " Test completed in " < < elapsed_seconds . count ( ) < < " [s] \n " ;
2017-04-12 15:04:51 +00:00
}