2018-06-19 07:15:46 +00:00
/*!
2018-07-10 16:43:36 +00:00
* \ file acq_performance_test . cc
2018-06-19 07:15:46 +00:00
* \ brief This class implements an acquisition performance test
* \ author Carles Fernandez - Prades , 2018. cfernandez ( at ) cttc . cat
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Copyright ( C ) 2010 - 2018 ( see AUTHORS file for a list of contributors )
*
* GNSS - SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS - SDR .
*
* GNSS - SDR is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* GNSS - SDR is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with GNSS - SDR . If not , see < https : //www.gnu.org/licenses/>.
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2018-12-09 21:00:09 +00:00
# include "acquisition_dump_reader.h"
# include "display.h"
# include "file_configuration.h"
2018-07-10 16:43:36 +00:00
# include "galileo_e1_pcps_ambiguous_acquisition.h"
# include "galileo_e5a_pcps_acquisition.h"
# include "glonass_l1_ca_pcps_acquisition.h"
# include "glonass_l2_ca_pcps_acquisition.h"
2018-12-09 21:00:09 +00:00
# include "gnss_sdr_valve.h"
# include "gnuplot_i.h"
# include "gps_l1_ca_pcps_acquisition.h"
# include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
2018-07-10 16:43:36 +00:00
# include "gps_l2_m_pcps_acquisition.h"
# include "gps_l5i_pcps_acquisition.h"
2018-09-07 12:36:11 +00:00
# include "in_memory_configuration.h"
2018-07-10 16:43:36 +00:00
# include "signal_generator_flags.h"
# include "test_flags.h"
# include "tracking_true_obs_reader.h"
# include "true_observables_reader.h"
2018-09-07 12:36:11 +00:00
# include <gnuradio/blocks/file_source.h>
# include <gnuradio/blocks/interleaved_char_to_complex.h>
2018-07-16 18:58:33 +00:00
# include <gnuradio/blocks/skiphead.h>
2018-12-09 21:00:09 +00:00
# include <gnuradio/top_block.h>
2019-02-24 22:11:19 +00:00
# include <thread>
2019-02-11 17:38:42 +00:00
# include <utility>
2018-07-10 16:43:36 +00:00
2019-06-10 19:41:13 +00:00
# if HAS_STD_FILESYSTEM
# include <filesystem>
# include <system_error>
namespace fs = std : : filesystem ;
namespace errorlib = std ;
# else
# include <boost/filesystem.hpp>
# include <boost/system/error_code.hpp>
namespace fs = boost : : filesystem ;
namespace errorlib = boost : : system ;
# endif
2018-06-19 07:15:46 +00:00
2018-06-29 18:43:09 +00:00
DEFINE_string ( config_file_ptest , std : : string ( " " ) , " File containing alternative configuration parameters for the acquisition performance test. " ) ;
DEFINE_string ( acq_test_input_file , std : : string ( " " ) , " File containing raw signal data, must be in int8_t format. The signal generator will not be used. " ) ;
2018-07-10 16:43:36 +00:00
DEFINE_string ( acq_test_implementation , std : : string ( " GPS_L1_CA_PCPS_Acquisition " ) , " Acquisition block implementation under test. Alternatives: GPS_L1_CA_PCPS_Acquisition, GPS_L1_CA_PCPS_Acquisition_Fine_Doppler, Galileo_E1_PCPS_Ambiguous_Acquisition, GLONASS_L1_CA_PCPS_Acquisition, GLONASS_L2_CA_PCPS_Acquisition, GPS_L2_M_PCPS_Acquisition, Galileo_E5a_Pcps_Acquisition, GPS_L5i_PCPS_Acquisition " ) ;
2018-06-29 18:43:09 +00:00
DEFINE_int32 ( acq_test_doppler_max , 5000 , " Maximum Doppler, in Hz " ) ;
DEFINE_int32 ( acq_test_doppler_step , 125 , " Doppler step, in Hz. " ) ;
2018-06-29 11:33:53 +00:00
DEFINE_int32 ( acq_test_coherent_time_ms , 1 , " Acquisition coherent time, in ms " ) ;
2018-07-13 09:50:31 +00:00
DEFINE_int32 ( acq_test_max_dwells , 1 , " Number of non-coherent integrations. " ) ;
DEFINE_bool ( acq_test_use_CFAR_algorithm , true , " Use CFAR algorithm. " ) ;
DEFINE_bool ( acq_test_bit_transition_flag , false , " Bit transition flag. " ) ;
DEFINE_bool ( acq_test_make_two_steps , false , " Perform second step in a thinner grid. " ) ;
DEFINE_int32 ( acq_test_second_nbins , 4 , " If --acq_test_make_two_steps is set to true, this parameter sets the number of bins done in the acquisition refinement stage. " ) ;
DEFINE_int32 ( acq_test_second_doppler_step , 10 , " If --acq_test_make_two_steps is set to true, this parameter sets the Doppler step applied in the acquisition refinement stage, in Hz. " ) ;
2018-06-29 18:43:09 +00:00
DEFINE_int32 ( acq_test_signal_duration_s , 2 , " Generated signal duration, in s " ) ;
DEFINE_int32 ( acq_test_num_meas , 0 , " Number of measurements per run. 0 means the complete file. " ) ;
2018-08-24 10:34:36 +00:00
DEFINE_double ( acq_test_cn0_init , 30.0 , " Initial CN0, in dBHz. " ) ;
2018-06-29 18:43:09 +00:00
DEFINE_double ( acq_test_cn0_final , 45.0 , " Final CN0, in dBHz. " ) ;
DEFINE_double ( acq_test_cn0_step , 3.0 , " CN0 step, in dB. " ) ;
2018-07-12 22:16:57 +00:00
DEFINE_double ( acq_test_threshold_init , 3.0 , " Initial acquisition threshold " ) ;
DEFINE_double ( acq_test_threshold_final , 4.0 , " Final acquisition threshold " ) ;
DEFINE_double ( acq_test_threshold_step , 0.5 , " Acquisition threshold step " ) ;
2018-06-29 18:43:09 +00:00
DEFINE_double ( acq_test_pfa_init , 1e-5 , " Set initial threshold via probability of false alarm. Disable with -1.0 " ) ;
2018-06-29 11:33:53 +00:00
DEFINE_int32 ( acq_test_PRN , 1 , " PRN number of a present satellite " ) ;
DEFINE_int32 ( acq_test_fake_PRN , 33 , " PRN number of a non-present satellite " ) ;
2018-06-29 18:43:09 +00:00
DEFINE_int32 ( acq_test_iterations , 1 , " Number of iterations (same signal, different noise realization) " ) ;
2018-06-29 11:33:53 +00:00
DEFINE_bool ( plot_acq_test , false , " Plots results with gnuplot, if available " ) ;
2018-07-16 18:58:33 +00:00
DEFINE_int32 ( acq_test_skiphead , 0 , " Number of samples to skip in the input file " ) ;
2018-06-19 07:15:46 +00:00
2018-12-12 00:23:05 +00:00
DEFINE_bool ( acq_test_dump , false , " Dump the results of an acquisition block into .mat files. " ) ;
2018-06-19 07:15:46 +00:00
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
2018-06-21 07:53:47 +00:00
class AcqPerfTest_msg_rx ;
2018-06-24 22:56:11 +00:00
2019-02-28 20:45:30 +00:00
using AcqPerfTest_msg_rx_sptr = boost : : shared_ptr < AcqPerfTest_msg_rx > ;
2018-06-24 22:56:11 +00:00
2019-02-22 14:57:15 +00:00
AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make ( Concurrent_Queue < int > & queue ) ;
2018-06-24 22:56:11 +00:00
2018-06-21 07:53:47 +00:00
class AcqPerfTest_msg_rx : public gr : : block
{
private :
2019-02-22 14:57:15 +00:00
friend AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make ( Concurrent_Queue < int > & queue ) ;
2018-06-21 07:53:47 +00:00
void msg_handler_events ( pmt : : pmt_t msg ) ;
2019-02-22 14:57:15 +00:00
AcqPerfTest_msg_rx ( Concurrent_Queue < int > & queue ) ;
Concurrent_Queue < int > & channel_internal_queue ;
2018-06-21 07:53:47 +00:00
public :
int rx_message ;
2018-06-24 22:56:11 +00:00
~ AcqPerfTest_msg_rx ( ) ;
2018-06-21 07:53:47 +00:00
} ;
2019-02-22 14:57:15 +00:00
AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make ( Concurrent_Queue < int > & queue )
2018-06-21 07:53:47 +00:00
{
2018-06-24 08:53:12 +00:00
return AcqPerfTest_msg_rx_sptr ( new AcqPerfTest_msg_rx ( queue ) ) ;
2018-06-21 07:53:47 +00:00
}
void AcqPerfTest_msg_rx : : msg_handler_events ( pmt : : pmt_t msg )
{
try
{
2019-02-11 17:38:42 +00:00
int64_t message = pmt : : to_long ( std : : move ( msg ) ) ;
2018-06-21 07:53:47 +00:00
rx_message = message ;
2018-06-24 08:53:12 +00:00
channel_internal_queue . push ( rx_message ) ;
2018-06-21 07:53:47 +00:00
}
catch ( boost : : bad_any_cast & e )
{
LOG ( WARNING ) < < " msg_handler_telemetry Bad any cast! " ;
rx_message = 0 ;
}
}
2019-02-22 14:57:15 +00:00
AcqPerfTest_msg_rx : : AcqPerfTest_msg_rx ( Concurrent_Queue < int > & queue ) : gr : : block ( " AcqPerfTest_msg_rx " , gr : : io_signature : : make ( 0 , 0 , 0 ) , gr : : io_signature : : make ( 0 , 0 , 0 ) ) , channel_internal_queue ( queue )
2018-06-21 07:53:47 +00:00
{
this - > message_port_register_in ( pmt : : mp ( " events " ) ) ;
this - > set_msg_handler ( pmt : : mp ( " events " ) , boost : : bind ( & AcqPerfTest_msg_rx : : msg_handler_events , this , _1 ) ) ;
rx_message = 0 ;
}
2019-02-11 20:13:02 +00:00
AcqPerfTest_msg_rx : : ~ AcqPerfTest_msg_rx ( ) = default ;
2018-06-21 07:53:47 +00:00
// -----------------------------------------
2018-06-19 07:15:46 +00:00
class AcquisitionPerformanceTest : public : : testing : : Test
{
protected :
AcquisitionPerformanceTest ( )
{
config = std : : make_shared < InMemoryConfiguration > ( ) ;
item_size = sizeof ( gr_complex ) ;
gnss_synchro = Gnss_Synchro ( ) ;
2018-06-29 18:43:09 +00:00
doppler_max = static_cast < unsigned int > ( FLAGS_acq_test_doppler_max ) ;
doppler_step = static_cast < unsigned int > ( FLAGS_acq_test_doppler_step ) ;
2018-06-24 08:53:12 +00:00
stop = false ;
2018-06-29 18:43:09 +00:00
if ( FLAGS_acq_test_input_file . empty ( ) )
{
cn0_vector . push_back ( FLAGS_acq_test_cn0_init ) ;
double aux = FLAGS_acq_test_cn0_init + FLAGS_acq_test_cn0_step ;
while ( aux < = FLAGS_acq_test_cn0_final )
{
cn0_vector . push_back ( aux ) ;
aux = aux + FLAGS_acq_test_cn0_step ;
}
}
else
{
cn0_vector = { 0.0 } ;
}
2018-07-10 16:43:36 +00:00
2019-02-11 17:38:42 +00:00
if ( implementation = = " GPS_L1_CA_PCPS_Acquisition " )
2018-07-10 16:43:36 +00:00
{
signal_id = " 1C " ;
system_id = ' G ' ;
2018-07-11 12:51:34 +00:00
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms ;
2018-07-12 22:16:57 +00:00
min_integration_ms = 1 ;
2018-07-10 16:43:36 +00:00
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GPS_L1_CA_PCPS_Acquisition_Fine_Doppler " )
2018-07-10 16:43:36 +00:00
{
signal_id = " 1C " ;
system_id = ' G ' ;
2018-07-11 12:51:34 +00:00
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms ;
2018-07-12 22:16:57 +00:00
min_integration_ms = 1 ;
2018-07-10 16:43:36 +00:00
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " Galileo_E1_PCPS_Ambiguous_Acquisition " )
2018-07-10 16:43:36 +00:00
{
signal_id = " 1B " ;
system_id = ' E ' ;
2018-07-12 22:16:57 +00:00
min_integration_ms = 4 ;
2018-07-11 12:51:34 +00:00
if ( FLAGS_acq_test_coherent_time_ms = = 1 )
{
coherent_integration_time_ms = 4 ;
}
else
{
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms ;
}
2018-07-10 16:43:36 +00:00
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GLONASS_L1_CA_PCPS_Acquisition " )
2018-07-10 16:43:36 +00:00
{
signal_id = " 1G " ;
system_id = ' R ' ;
2018-07-11 12:51:34 +00:00
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms ;
2018-07-12 22:16:57 +00:00
min_integration_ms = 1 ;
2018-07-10 16:43:36 +00:00
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GLONASS_L2_CA_PCPS_Acquisition " )
2018-07-10 16:43:36 +00:00
{
signal_id = " 2G " ;
system_id = ' R ' ;
2018-07-11 12:51:34 +00:00
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms ;
2018-07-12 22:16:57 +00:00
min_integration_ms = 1 ;
2018-07-10 16:43:36 +00:00
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GPS_L2_M_PCPS_Acquisition " )
2018-07-10 16:43:36 +00:00
{
signal_id = " 2S " ;
system_id = ' G ' ;
2018-07-11 12:51:34 +00:00
if ( FLAGS_acq_test_coherent_time_ms = = 1 )
{
coherent_integration_time_ms = 20 ;
}
else
{
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms ;
}
2018-07-12 22:16:57 +00:00
min_integration_ms = 20 ;
2018-07-10 16:43:36 +00:00
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " Galileo_E5a_Pcps_Acquisition " )
2018-07-10 16:43:36 +00:00
{
signal_id = " 5X " ;
system_id = ' E ' ;
2018-07-11 12:51:34 +00:00
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms ;
2018-07-12 22:16:57 +00:00
min_integration_ms = 1 ;
2018-07-10 16:43:36 +00:00
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GPS_L5i_PCPS_Acquisition " )
2018-07-10 16:43:36 +00:00
{
signal_id = " L5 " ;
system_id = ' G ' ;
2018-07-11 12:51:34 +00:00
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms ;
2018-07-10 16:43:36 +00:00
}
else
{
signal_id = " 1C " ;
system_id = ' G ' ;
2018-07-11 12:51:34 +00:00
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms ;
2018-07-12 22:16:57 +00:00
min_integration_ms = 1 ;
2018-07-10 16:43:36 +00:00
}
2018-06-24 08:53:12 +00:00
init ( ) ;
2018-06-29 18:43:09 +00:00
if ( FLAGS_acq_test_pfa_init > 0.0 )
2018-06-29 11:33:53 +00:00
{
2018-06-29 18:43:09 +00:00
pfa_vector . push_back ( FLAGS_acq_test_pfa_init ) ;
float aux = 1.0 ;
while ( ( FLAGS_acq_test_pfa_init * std : : pow ( 10 , aux ) ) < 1 )
{
pfa_vector . push_back ( FLAGS_acq_test_pfa_init * std : : pow ( 10 , aux ) ) ;
aux = aux + 1.0 ;
}
pfa_vector . push_back ( 1.0 ) ;
2018-06-29 11:33:53 +00:00
}
2018-06-29 18:43:09 +00:00
else
{
2019-02-11 17:38:42 +00:00
auto aux = static_cast < float > ( FLAGS_acq_test_threshold_init ) ;
2018-06-29 18:43:09 +00:00
pfa_vector . push_back ( aux ) ;
aux = aux + static_cast < float > ( FLAGS_acq_test_threshold_step ) ;
while ( aux < = static_cast < float > ( FLAGS_acq_test_threshold_final ) )
{
pfa_vector . push_back ( aux ) ;
aux = aux + static_cast < float > ( FLAGS_acq_test_threshold_step ) ;
}
}
2018-06-29 11:33:53 +00:00
num_thresholds = pfa_vector . size ( ) ;
2018-06-29 18:43:09 +00:00
2018-07-10 15:20:37 +00:00
int aux2 = ( ( generated_signal_duration_s * 1000 - ( FLAGS_acq_test_coherent_time_ms * FLAGS_acq_test_max_dwells ) ) / ( FLAGS_acq_test_coherent_time_ms * FLAGS_acq_test_max_dwells ) ) ;
2018-06-29 18:43:09 +00:00
if ( ( FLAGS_acq_test_num_meas > 0 ) and ( FLAGS_acq_test_num_meas < aux2 ) )
{
num_of_measurements = static_cast < unsigned int > ( FLAGS_acq_test_num_meas ) ;
}
else
{
num_of_measurements = static_cast < unsigned int > ( aux2 ) ;
}
2018-06-29 11:33:53 +00:00
Pd . resize ( cn0_vector . size ( ) ) ;
2019-02-11 20:13:02 +00:00
for ( int i = 0 ; i < static_cast < int > ( cn0_vector . size ( ) ) ; i + + )
{
Pd [ i ] . reserve ( num_thresholds ) ;
}
2018-06-29 11:33:53 +00:00
Pfa . resize ( cn0_vector . size ( ) ) ;
2019-02-11 20:13:02 +00:00
for ( int i = 0 ; i < static_cast < int > ( cn0_vector . size ( ) ) ; i + + )
{
Pfa [ i ] . reserve ( num_thresholds ) ;
}
2018-06-29 11:33:53 +00:00
Pd_correct . resize ( cn0_vector . size ( ) ) ;
2019-02-11 20:13:02 +00:00
for ( int i = 0 ; i < static_cast < int > ( cn0_vector . size ( ) ) ; i + + )
{
Pd_correct [ i ] . reserve ( num_thresholds ) ;
}
2018-06-19 07:15:46 +00:00
}
2019-02-11 20:13:02 +00:00
~ AcquisitionPerformanceTest ( ) = default ;
2018-06-19 07:15:46 +00:00
2018-06-29 18:43:09 +00:00
std : : vector < double > cn0_vector ;
2018-06-29 11:33:53 +00:00
std : : vector < float > pfa_vector ;
2018-06-27 06:07:42 +00:00
int N_iterations = FLAGS_acq_test_iterations ;
2018-06-19 07:15:46 +00:00
void init ( ) ;
int configure_generator ( double cn0 ) ;
int generate_signal ( ) ;
2018-06-26 06:43:22 +00:00
int configure_receiver ( double cn0 , float pfa , unsigned int iter ) ;
2018-06-24 08:53:12 +00:00
void start_queue ( ) ;
void wait_message ( ) ;
void process_message ( ) ;
void stop_queue ( ) ;
2018-06-19 07:15:46 +00:00
int run_receiver ( ) ;
2018-06-24 22:56:11 +00:00
int count_executions ( const std : : string & basename , unsigned int sat ) ;
2018-06-19 07:15:46 +00:00
void check_results ( ) ;
2018-06-28 14:30:36 +00:00
void plot_results ( ) ;
2018-06-24 08:53:12 +00:00
2019-02-22 14:57:15 +00:00
Concurrent_Queue < int > channel_internal_queue ;
2018-06-24 08:53:12 +00:00
gr : : msg_queue : : sptr queue ;
2018-06-19 07:15:46 +00:00
gr : : top_block_sptr top_block ;
2018-07-05 19:33:08 +00:00
std : : shared_ptr < AcquisitionInterface > acquisition ;
2018-06-24 08:53:12 +00:00
std : : shared_ptr < InMemoryConfiguration > config ;
std : : shared_ptr < FileConfiguration > config_f ;
2018-06-19 07:15:46 +00:00
Gnss_Synchro gnss_synchro ;
size_t item_size ;
unsigned int doppler_max ;
unsigned int doppler_step ;
2018-06-24 08:53:12 +00:00
bool stop ;
int message ;
2019-02-24 22:11:19 +00:00
std : : thread ch_thread ;
2018-06-24 08:53:12 +00:00
2018-07-04 11:05:44 +00:00
std : : string implementation = FLAGS_acq_test_implementation ;
2018-06-24 08:53:12 +00:00
2018-06-22 10:24:39 +00:00
const double baseband_sampling_freq = static_cast < double > ( FLAGS_fs_gen_sps ) ;
2018-07-11 12:51:34 +00:00
int coherent_integration_time_ms ;
2018-06-24 08:53:12 +00:00
const int in_acquisition = 1 ;
2018-06-24 22:56:11 +00:00
const int dump_channel = 0 ;
2018-06-24 08:53:12 +00:00
2018-06-24 22:56:11 +00:00
int generated_signal_duration_s = FLAGS_acq_test_signal_duration_s ;
2018-06-29 18:43:09 +00:00
unsigned int num_of_measurements ;
unsigned int measurement_counter = 0 ;
2018-06-19 07:15:46 +00:00
2018-06-24 22:56:11 +00:00
unsigned int observed_satellite = FLAGS_acq_test_PRN ;
2018-06-26 06:43:22 +00:00
std : : string path_str = " ./acq-perf-test " ;
2018-06-29 11:33:53 +00:00
int num_thresholds ;
2018-07-12 22:16:57 +00:00
unsigned int min_integration_ms ;
2018-06-26 06:43:22 +00:00
std : : vector < std : : vector < float > > Pd ;
std : : vector < std : : vector < float > > Pfa ;
2018-06-27 06:07:42 +00:00
std : : vector < std : : vector < float > > Pd_correct ;
2018-06-26 06:43:22 +00:00
2018-07-10 16:43:36 +00:00
std : : string signal_id ;
2018-06-19 07:15:46 +00:00
private :
std : : string generator_binary ;
std : : string p1 ;
std : : string p2 ;
std : : string p3 ;
std : : string p4 ;
std : : string p5 ;
std : : string p6 ;
std : : string filename_rinex_obs = FLAGS_filename_rinex_obs ;
std : : string filename_raw_data = FLAGS_filename_raw_data ;
2018-07-10 16:43:36 +00:00
char system_id ;
2018-06-19 07:15:46 +00:00
double compute_stdev_precision ( const std : : vector < double > & vec ) ;
double compute_stdev_accuracy ( const std : : vector < double > & vec , double ref ) ;
} ;
void AcquisitionPerformanceTest : : init ( )
{
gnss_synchro . Channel_ID = 0 ;
2018-07-10 16:43:36 +00:00
gnss_synchro . System = system_id ;
std : : string signal = signal_id ;
2018-06-19 07:15:46 +00:00
signal . copy ( gnss_synchro . Signal , 2 , 0 ) ;
2018-06-24 22:56:11 +00:00
gnss_synchro . PRN = observed_satellite ;
2018-06-24 08:53:12 +00:00
message = 0 ;
2018-06-29 18:43:09 +00:00
measurement_counter = 0 ;
2018-06-24 08:53:12 +00:00
}
void AcquisitionPerformanceTest : : start_queue ( )
{
stop = false ;
2019-02-24 22:11:19 +00:00
ch_thread = std : : thread ( & AcquisitionPerformanceTest : : wait_message , this ) ;
2018-06-24 08:53:12 +00:00
}
void AcquisitionPerformanceTest : : wait_message ( )
{
while ( ! stop )
{
channel_internal_queue . wait_and_pop ( message ) ;
process_message ( ) ;
}
}
void AcquisitionPerformanceTest : : process_message ( )
{
2018-06-29 18:43:09 +00:00
measurement_counter + + ;
2018-06-24 22:56:11 +00:00
acquisition - > reset ( ) ;
2018-07-05 19:33:08 +00:00
acquisition - > set_state ( 1 ) ;
2018-06-29 18:43:09 +00:00
std : : cout < < " Progress: " < < round ( static_cast < float > ( measurement_counter ) / static_cast < float > ( num_of_measurements ) * 100.0 ) < < " % \r " < < std : : flush ;
if ( measurement_counter = = num_of_measurements )
2018-06-24 08:53:12 +00:00
{
stop_queue ( ) ;
top_block - > stop ( ) ;
}
}
void AcquisitionPerformanceTest : : stop_queue ( )
{
stop = true ;
2018-06-19 07:15:46 +00:00
}
int AcquisitionPerformanceTest : : configure_generator ( double cn0 )
{
// Configure signal generator
generator_binary = FLAGS_generator_binary ;
p1 = std : : string ( " -rinex_nav_file= " ) + FLAGS_rinex_nav_file ;
if ( FLAGS_dynamic_position . empty ( ) )
{
2018-06-24 08:53:12 +00:00
p2 = std : : string ( " -static_position= " ) + FLAGS_static_position + std : : string ( " , " ) + std : : to_string ( std : : min ( generated_signal_duration_s * 10 , 3000 ) ) ;
2018-06-19 07:15:46 +00:00
}
else
{
p2 = std : : string ( " -obs_pos_file= " ) + std : : string ( FLAGS_dynamic_position ) ;
}
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
p5 = std : : string ( " -sampling_freq= " ) + std : : to_string ( baseband_sampling_freq ) ; // Baseband sampling frequency [MSps]
p6 = std : : string ( " -CN0_dBHz= " ) + std : : to_string ( cn0 ) ;
return 0 ;
}
int AcquisitionPerformanceTest : : generate_signal ( )
{
pid_t wait_result ;
int child_status ;
std : : cout < < " Generating signal for " < < p6 < < " ... " < < std : : endl ;
2019-02-11 17:38:42 +00:00
char * const parmList [ ] = { & generator_binary [ 0 ] , & generator_binary [ 0 ] , & p1 [ 0 ] , & p2 [ 0 ] , & p3 [ 0 ] , & p4 [ 0 ] , & p5 [ 0 ] , & p6 [ 0 ] , nullptr } ;
2018-06-19 07:15:46 +00:00
int pid ;
if ( ( pid = fork ( ) ) = = - 1 )
2019-02-11 20:13:02 +00:00
{
perror ( " fork error " ) ;
}
2018-06-19 07:15:46 +00:00
else if ( pid = = 0 )
{
execv ( & generator_binary [ 0 ] , parmList ) ;
std : : cout < < " Return not expected. Must be an execv error. " < < std : : endl ;
std : : terminate ( ) ;
}
wait_result = waitpid ( pid , & child_status , 0 ) ;
2019-02-11 20:13:02 +00:00
if ( wait_result = = - 1 )
{
perror ( " waitpid error " ) ;
}
2018-06-19 07:15:46 +00:00
return 0 ;
}
2018-06-26 06:43:22 +00:00
int AcquisitionPerformanceTest : : configure_receiver ( double cn0 , float pfa , unsigned int iter )
2018-06-19 07:15:46 +00:00
{
if ( FLAGS_config_file_ptest . empty ( ) )
{
config = std : : make_shared < InMemoryConfiguration > ( ) ;
const int sampling_rate_internal = baseband_sampling_freq ;
config - > set_property ( " GNSS-SDR.internal_fs_sps " , std : : to_string ( sampling_rate_internal ) ) ;
// Set Acquisition
2018-07-10 16:43:36 +00:00
config - > set_property ( " Acquisition.implementation " , implementation ) ;
config - > set_property ( " Acquisition.item_type " , " gr_complex " ) ;
config - > set_property ( " Acquisition.doppler_max " , std : : to_string ( doppler_max ) ) ;
config - > set_property ( " Acquisition.doppler_min " , std : : to_string ( - doppler_max ) ) ;
config - > set_property ( " Acquisition.doppler_step " , std : : to_string ( doppler_step ) ) ;
config - > set_property ( " Acquisition.threshold " , std : : to_string ( pfa ) ) ;
//if (FLAGS_acq_test_pfa_init > 0.0) config->supersede_property("Acquisition.pfa", std::to_string(pfa));
2018-06-29 18:43:09 +00:00
if ( FLAGS_acq_test_pfa_init > 0.0 )
{
2018-07-10 16:43:36 +00:00
config - > supersede_property ( " Acquisition.pfa " , std : : to_string ( pfa ) ) ;
2018-06-29 18:43:09 +00:00
}
2018-06-29 11:33:53 +00:00
if ( FLAGS_acq_test_use_CFAR_algorithm )
{
2018-07-10 16:43:36 +00:00
config - > set_property ( " Acquisition.use_CFAR_algorithm " , " true " ) ;
2018-06-29 11:33:53 +00:00
}
else
{
2018-07-10 16:43:36 +00:00
config - > set_property ( " Acquisition.use_CFAR_algorithm " , " false " ) ;
2018-06-29 11:33:53 +00:00
}
2018-06-19 07:15:46 +00:00
2018-07-10 16:43:36 +00:00
config - > set_property ( " Acquisition.coherent_integration_time_ms " , std : : to_string ( coherent_integration_time_ms ) ) ;
2018-06-24 22:56:11 +00:00
if ( FLAGS_acq_test_bit_transition_flag )
{
2018-07-10 16:43:36 +00:00
config - > set_property ( " Acquisition.bit_transition_flag " , " true " ) ;
2018-06-24 22:56:11 +00:00
}
else
{
2018-07-10 16:43:36 +00:00
config - > set_property ( " Acquisition.bit_transition_flag " , " false " ) ;
2018-06-24 22:56:11 +00:00
}
2018-06-19 07:15:46 +00:00
2018-07-10 16:43:36 +00:00
config - > set_property ( " Acquisition.max_dwells " , std : : to_string ( FLAGS_acq_test_max_dwells ) ) ;
2018-06-19 07:15:46 +00:00
2018-07-10 16:43:36 +00:00
config - > set_property ( " Acquisition.repeat_satellite " , " true " ) ;
2018-06-19 07:15:46 +00:00
2018-07-10 16:43:36 +00:00
config - > set_property ( " Acquisition.blocking " , " true " ) ;
2018-07-13 09:50:31 +00:00
if ( FLAGS_acq_test_make_two_steps )
{
config - > set_property ( " Acquisition.make_two_steps " , " true " ) ;
config - > set_property ( " Acquisition.second_nbins " , std : : to_string ( FLAGS_acq_test_second_nbins ) ) ;
config - > set_property ( " Acquisition.second_doppler_step " , std : : to_string ( FLAGS_acq_test_second_doppler_step ) ) ;
}
else
{
config - > set_property ( " Acquisition.make_two_steps " , " false " ) ;
}
2018-12-12 00:23:05 +00:00
if ( FLAGS_acq_test_dump )
{
config - > set_property ( " Acquisition.dump " , " true " ) ;
}
else
{
config - > set_property ( " Acquisition.dump " , " false " ) ;
}
2018-06-24 22:56:11 +00:00
2018-06-26 06:43:22 +00:00
std : : string dump_file = path_str + std : : string ( " /acquisition_ " ) + std : : to_string ( cn0 ) + " _ " + std : : to_string ( iter ) + " _ " + std : : to_string ( pfa ) ;
2018-07-10 16:43:36 +00:00
config - > set_property ( " Acquisition.dump_filename " , dump_file ) ;
config - > set_property ( " Acquisition.dump_channel " , std : : to_string ( dump_channel ) ) ;
config - > set_property ( " Acquisition.blocking_on_standby " , " true " ) ;
2018-06-19 07:15:46 +00:00
2019-02-11 17:38:42 +00:00
config_f = nullptr ;
2018-06-19 07:15:46 +00:00
}
else
{
config_f = std : : make_shared < FileConfiguration > ( FLAGS_config_file_ptest ) ;
2019-02-11 17:38:42 +00:00
config = nullptr ;
2018-06-19 07:15:46 +00:00
}
return 0 ;
}
int AcquisitionPerformanceTest : : run_receiver ( )
2018-06-21 07:53:47 +00:00
{
2018-06-29 18:43:09 +00:00
std : : string file ;
if ( FLAGS_acq_test_input_file . empty ( ) )
{
file = " ./ " + filename_raw_data ;
}
else
{
file = FLAGS_acq_test_input_file ;
}
2018-06-21 07:53:47 +00:00
const char * file_name = file . c_str ( ) ;
gr : : blocks : : file_source : : sptr file_source = gr : : blocks : : file_source : : make ( sizeof ( int8_t ) , file_name , false ) ;
2018-06-24 08:53:12 +00:00
gr : : blocks : : interleaved_char_to_complex : : sptr gr_interleaved_char_to_complex = gr : : blocks : : interleaved_char_to_complex : : make ( ) ;
2018-06-21 07:53:47 +00:00
2018-06-24 08:53:12 +00:00
top_block = gr : : make_top_block ( " Acquisition test " ) ;
boost : : shared_ptr < AcqPerfTest_msg_rx > msg_rx = AcqPerfTest_msg_rx_make ( channel_internal_queue ) ;
2018-07-16 18:58:33 +00:00
gr : : blocks : : skiphead : : sptr skiphead = gr : : blocks : : skiphead : : make ( sizeof ( gr_complex ) , FLAGS_acq_test_skiphead ) ;
2018-06-21 07:53:47 +00:00
2018-06-24 08:53:12 +00:00
queue = gr : : msg_queue : : make ( 0 ) ;
gnss_synchro = Gnss_Synchro ( ) ;
init ( ) ;
2018-06-24 22:56:11 +00:00
2018-06-24 08:53:12 +00:00
int nsamples = floor ( config - > property ( " GNSS-SDR.internal_fs_sps " , 2000000 ) * generated_signal_duration_s ) ;
boost : : shared_ptr < gr : : block > valve = gnss_sdr_make_valve ( sizeof ( gr_complex ) , nsamples , queue ) ;
2019-02-11 17:38:42 +00:00
if ( implementation = = " GPS_L1_CA_PCPS_Acquisition " )
2018-07-04 11:05:44 +00:00
{
2018-07-10 16:43:36 +00:00
acquisition = std : : make_shared < GpsL1CaPcpsAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GPS_L1_CA_PCPS_Acquisition_Fine_Doppler " )
2018-07-10 16:43:36 +00:00
{
acquisition = std : : make_shared < GpsL1CaPcpsAcquisitionFineDoppler > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " Galileo_E1_PCPS_Ambiguous_Acquisition " )
2018-07-10 16:43:36 +00:00
{
acquisition = std : : make_shared < GalileoE1PcpsAmbiguousAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GLONASS_L1_CA_PCPS_Acquisition " )
2018-07-10 16:43:36 +00:00
{
acquisition = std : : make_shared < GlonassL1CaPcpsAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GLONASS_L2_CA_PCPS_Acquisition " )
2018-07-10 16:43:36 +00:00
{
acquisition = std : : make_shared < GlonassL2CaPcpsAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GPS_L2_M_PCPS_Acquisition " )
2018-07-10 16:43:36 +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_Pcps_Acquisition " )
2018-07-10 16:43:36 +00:00
{
acquisition = std : : make_shared < GalileoE5aPcpsAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
}
2019-02-11 17:38:42 +00:00
else if ( implementation = = " GPS_L5i_PCPS_Acquisition " )
2018-07-10 16:43:36 +00:00
{
acquisition = std : : make_shared < GpsL5iPcpsAcquisition > ( config . get ( ) , " Acquisition " , 1 , 0 ) ;
2018-07-04 11:05:44 +00:00
}
else
{
2018-07-10 16:43:36 +00:00
bool aux = false ;
EXPECT_EQ ( true , aux ) ;
2018-07-04 11:05:44 +00:00
}
2018-06-24 08:53:12 +00:00
acquisition - > set_gnss_synchro ( & gnss_synchro ) ;
acquisition - > set_channel ( 0 ) ;
2018-07-10 16:43:36 +00:00
acquisition - > set_doppler_max ( config - > property ( " Acquisition.doppler_max " , 10000 ) ) ;
acquisition - > set_doppler_step ( config - > property ( " Acquisition.doppler_step " , 500 ) ) ;
acquisition - > set_threshold ( config - > property ( " Acquisition.threshold " , 0.0 ) ) ;
2018-07-05 19:33:08 +00:00
acquisition - > init ( ) ;
acquisition - > set_local_code ( ) ;
acquisition - > set_state ( 1 ) ; // Ensure that acquisition starts at the first sample
2018-06-24 08:53:12 +00:00
acquisition - > connect ( top_block ) ;
2018-07-05 08:51:23 +00:00
acquisition - > reset ( ) ;
2018-06-24 08:53:12 +00:00
top_block - > connect ( file_source , 0 , gr_interleaved_char_to_complex , 0 ) ;
2018-07-16 18:58:33 +00:00
top_block - > connect ( gr_interleaved_char_to_complex , 0 , skiphead , 0 ) ;
top_block - > connect ( skiphead , 0 , valve , 0 ) ;
2018-06-24 08:53:12 +00:00
top_block - > connect ( valve , 0 , acquisition - > get_left_block ( ) , 0 ) ;
2018-07-05 08:51:23 +00:00
top_block - > msg_connect ( acquisition - > get_right_block ( ) , pmt : : mp ( " events " ) , msg_rx , pmt : : mp ( " events " ) ) ;
2018-06-24 22:56:11 +00:00
2018-06-24 08:53:12 +00:00
start_queue ( ) ;
2018-06-24 22:56:11 +00:00
2018-06-24 08:53:12 +00:00
top_block - > run ( ) ; // Start threads and wait
2018-06-24 22:56:11 +00:00
2019-02-24 22:11:19 +00:00
ch_thread . join ( ) ;
2018-06-21 07:53:47 +00:00
return 0 ;
}
2018-06-24 22:56:11 +00:00
int AcquisitionPerformanceTest : : count_executions ( const std : : string & basename , unsigned int sat )
{
FILE * fp ;
2018-06-29 11:33:53 +00:00
std : : string argum2 = std : : string ( " /usr/bin/find " ) + path_str + std : : string ( " -maxdepth 1 -name " ) + basename . substr ( path_str . length ( ) + 1 , basename . length ( ) - path_str . length ( ) ) + std : : string ( " * | grep sat_ " ) + std : : to_string ( sat ) + std : : string ( " | wc -l " ) ;
2018-06-24 22:56:11 +00:00
char buffer [ 1024 ] ;
fp = popen ( & argum2 [ 0 ] , " r " ) ;
int num_executions = 1 ;
2019-02-11 17:38:42 +00:00
if ( fp = = nullptr )
2018-06-24 22:56:11 +00:00
{
std : : cout < < " Failed to run command: " < < argum2 < < std : : endl ;
return 0 ;
}
2019-02-11 17:38:42 +00:00
while ( fgets ( buffer , sizeof ( buffer ) , fp ) ! = nullptr )
2018-06-24 22:56:11 +00:00
{
std : : string aux = std : : string ( buffer ) ;
EXPECT_EQ ( aux . empty ( ) , false ) ;
num_executions = std : : stoi ( aux ) ;
}
pclose ( fp ) ;
return num_executions ;
}
2018-06-28 14:30:36 +00:00
void AcquisitionPerformanceTest : : plot_results ( )
{
if ( FLAGS_plot_acq_test = = true )
{
const std : : string gnuplot_executable ( FLAGS_gnuplot_executable ) ;
if ( gnuplot_executable . empty ( ) )
{
std : : cout < < " WARNING: Although the flag plot_gps_l1_tracking_test has been set to TRUE, " < < std : : endl ;
std : : cout < < " gnuplot has not been found in your system. " < < std : : endl ;
std : : cout < < " Test results will not be plotted. " < < std : : endl ;
}
else
{
try
{
2019-06-10 19:41:13 +00:00
fs : : path p ( gnuplot_executable ) ;
fs : : path dir = p . parent_path ( ) ;
2019-02-11 17:38:42 +00:00
const std : : string & gnuplot_path = dir . native ( ) ;
2018-06-28 14:30:36 +00:00
Gnuplot : : set_GNUPlotPath ( gnuplot_path ) ;
Gnuplot g1 ( " linespoints " ) ;
2018-07-05 19:33:08 +00:00
if ( FLAGS_show_plots )
{
g1 . showonscreen ( ) ; // window output
}
else
{
g1 . disablescreen ( ) ;
}
2018-06-29 18:43:09 +00:00
g1 . cmd ( " set font \" Times,18 \" " ) ;
g1 . set_title ( " Receiver Operating Characteristic for GPS L1 C/A acquisition " ) ;
2019-02-11 17:38:42 +00:00
g1 . cmd ( " set label 1 \" " + std : : string ( " Coherent integration time: " ) + std : : to_string ( config - > property ( " Acquisition.coherent_integration_time_ms " , 1 ) ) + " ms, Non-coherent integrations: " + std : : to_string ( config - > property ( " Acquisition.max_dwells " , 1 ) ) + R " ( " at screen 0.12 , 0.83 font " Times,16 " ) " );
2018-06-28 14:30:36 +00:00
g1 . cmd ( " set logscale x " ) ;
g1 . cmd ( " set yrange [0:1] " ) ;
2018-06-29 18:43:09 +00:00
g1 . cmd ( " set xrange[0.0001:1] " ) ;
g1 . cmd ( " set grid mxtics " ) ;
g1 . cmd ( " set grid ytics " ) ;
2018-06-28 14:30:36 +00:00
g1 . set_xlabel ( " Pfa " ) ;
g1 . set_ylabel ( " Pd " ) ;
2018-06-29 11:33:53 +00:00
g1 . set_grid ( ) ;
g1 . cmd ( " show grid " ) ;
for ( int i = 0 ; i < static_cast < int > ( cn0_vector . size ( ) ) ; i + + )
2018-06-28 14:30:36 +00:00
{
std : : vector < float > Pd_i ;
std : : vector < float > Pfa_i ;
for ( int k = 0 ; k < num_thresholds ; k + + )
{
Pd_i . push_back ( Pd [ i ] [ k ] ) ;
2018-06-29 18:43:09 +00:00
Pfa_i . push_back ( Pfa [ i ] [ k ] ) ;
2018-06-28 14:30:36 +00:00
}
2018-06-29 11:33:53 +00:00
g1 . plot_xy ( Pfa_i , Pd_i , " CN0 = " + std : : to_string ( static_cast < int > ( cn0_vector [ i ] ) ) + " dBHz " ) ;
2018-06-28 14:30:36 +00:00
}
g1 . set_legend ( ) ;
g1 . savetops ( " ROC " ) ;
g1 . savetopdf ( " ROC " , 18 ) ;
2018-06-29 11:33:53 +00:00
Gnuplot g2 ( " linespoints " ) ;
2018-07-05 19:33:08 +00:00
if ( FLAGS_show_plots )
{
g2 . showonscreen ( ) ; // window output
}
else
{
g2 . disablescreen ( ) ;
}
2018-06-29 18:43:09 +00:00
g2 . cmd ( " set font \" Times,18 \" " ) ;
g2 . set_title ( " Receiver Operating Characteristic for GPS L1 C/A valid acquisition " ) ;
2019-02-11 17:38:42 +00:00
g2 . cmd ( " set label 1 \" " + std : : string ( " Coherent integration time: " ) + std : : to_string ( config - > property ( " Acquisition.coherent_integration_time_ms " , 1 ) ) + " ms, Non-coherent integrations: " + std : : to_string ( config - > property ( " Acquisition.max_dwells " , 1 ) ) + R " ( " at screen 0.12 , 0.83 font " Times,16 " ) " );
2018-06-29 11:33:53 +00:00
g2 . cmd ( " set logscale x " ) ;
g2 . cmd ( " set yrange [0:1] " ) ;
2018-06-29 18:43:09 +00:00
g2 . cmd ( " set xrange[0.0001:1] " ) ;
g2 . cmd ( " set grid mxtics " ) ;
g2 . cmd ( " set grid ytics " ) ;
2018-06-29 11:33:53 +00:00
g2 . set_xlabel ( " Pfa " ) ;
g2 . set_ylabel ( " Valid Pd " ) ;
g2 . set_grid ( ) ;
g2 . cmd ( " show grid " ) ;
for ( int i = 0 ; i < static_cast < int > ( cn0_vector . size ( ) ) ; i + + )
2018-06-28 14:30:36 +00:00
{
2018-06-29 11:33:53 +00:00
std : : vector < float > Pd_i_correct ;
std : : vector < float > Pfa_i ;
for ( int k = 0 ; k < num_thresholds ; k + + )
2018-06-28 14:30:36 +00:00
{
2018-06-29 11:33:53 +00:00
Pd_i_correct . push_back ( Pd_correct [ i ] [ k ] ) ;
2018-06-29 18:43:09 +00:00
Pfa_i . push_back ( Pfa [ i ] [ k ] ) ;
2018-06-28 14:30:36 +00:00
}
2018-06-29 11:33:53 +00:00
g2 . plot_xy ( Pfa_i , Pd_i_correct , " CN0 = " + std : : to_string ( static_cast < int > ( cn0_vector [ i ] ) ) + " dBHz " ) ;
2018-06-28 14:30:36 +00:00
}
2018-06-29 11:33:53 +00:00
g2 . set_legend ( ) ;
g2 . savetops ( " ROC-valid-detection " ) ;
g2 . savetopdf ( " ROC-valid-detection " , 18 ) ;
2018-06-28 14:30:36 +00:00
}
catch ( const GnuplotException & ge )
{
std : : cout < < ge . what ( ) < < std : : endl ;
}
}
}
}
TEST_F ( AcquisitionPerformanceTest , ROC )
2018-06-19 07:15:46 +00:00
{
2019-02-22 14:57:15 +00:00
Tracking_True_Obs_Reader true_trk_data ;
2018-06-26 06:43:22 +00:00
2019-06-10 19:41:13 +00:00
if ( fs : : exists ( path_str ) )
2018-06-26 06:43:22 +00:00
{
2019-06-10 19:41:13 +00:00
fs : : remove_all ( path_str ) ;
2018-06-26 06:43:22 +00:00
}
2019-06-10 19:41:13 +00:00
errorlib : : error_code ec ;
ASSERT_TRUE ( fs : : create_directory ( path_str , ec ) ) < < " Could not create the " < < path_str < < " folder. " ;
2018-06-27 06:07:42 +00:00
2018-06-26 06:43:22 +00:00
unsigned int cn0_index = 0 ;
2019-02-11 17:38:42 +00:00
for ( double it : cn0_vector )
2018-06-19 07:15:46 +00:00
{
2018-06-26 06:43:22 +00:00
std : : vector < double > meas_Pd_ ;
std : : vector < double > meas_Pd_correct_ ;
std : : vector < double > meas_Pfa_ ;
2018-06-22 10:24:39 +00:00
2019-02-11 20:13:02 +00:00
if ( FLAGS_acq_test_input_file . empty ( ) )
{
std : : cout < < " Execution for CN0 = " < < it < < " dB-Hz " < < std : : endl ;
}
2018-06-29 11:33:53 +00:00
// Do N_iterations of the experiment
for ( int pfa_iter = 0 ; pfa_iter < static_cast < int > ( pfa_vector . size ( ) ) ; pfa_iter + + )
2018-06-27 06:07:42 +00:00
{
2018-06-29 18:43:09 +00:00
if ( FLAGS_acq_test_pfa_init > 0.0 )
{
std : : cout < < " Setting threshold for Pfa = " < < pfa_vector [ pfa_iter ] < < std : : endl ;
}
else
{
std : : cout < < " Setting threshold to " < < pfa_vector [ pfa_iter ] < < std : : endl ;
}
2018-06-29 11:33:53 +00:00
// Configure the signal generator
2019-02-11 20:13:02 +00:00
if ( FLAGS_acq_test_input_file . empty ( ) )
{
configure_generator ( it ) ;
}
2018-06-29 18:43:09 +00:00
2018-06-27 06:07:42 +00:00
for ( int iter = 0 ; iter < N_iterations ; iter + + )
2018-06-21 17:26:46 +00:00
{
2018-06-26 06:43:22 +00:00
// Generate signal raw signal samples and observations RINEX file
2019-02-11 20:13:02 +00:00
if ( FLAGS_acq_test_input_file . empty ( ) )
{
generate_signal ( ) ;
}
2018-06-22 10:24:39 +00:00
2018-06-26 06:43:22 +00:00
for ( unsigned k = 0 ; k < 2 ; k + + )
2018-06-22 10:24:39 +00:00
{
2018-06-26 06:43:22 +00:00
if ( k = = 0 )
2018-06-24 22:56:11 +00:00
{
2018-06-26 06:43:22 +00:00
observed_satellite = FLAGS_acq_test_PRN ;
2018-06-24 22:56:11 +00:00
}
else
{
2018-06-26 06:43:22 +00:00
observed_satellite = FLAGS_acq_test_fake_PRN ;
2018-06-24 22:56:11 +00:00
}
2018-06-26 06:43:22 +00:00
init ( ) ;
2018-06-24 22:56:11 +00:00
2018-06-26 06:43:22 +00:00
// Configure the receiver
2019-02-11 17:38:42 +00:00
configure_receiver ( it , pfa_vector [ pfa_iter ] , iter ) ;
2018-06-22 10:24:39 +00:00
2018-06-26 06:43:22 +00:00
// Run it
run_receiver ( ) ;
2018-06-22 10:24:39 +00:00
2018-06-26 06:43:22 +00:00
// count executions
2019-02-11 17:38:42 +00:00
std : : string basename = path_str + std : : string ( " /acquisition_ " ) + std : : to_string ( it ) + " _ " + std : : to_string ( iter ) + " _ " + std : : to_string ( pfa_vector [ pfa_iter ] ) + " _ " + gnss_synchro . System + " _ " + signal_id ;
2018-06-26 06:43:22 +00:00
int num_executions = count_executions ( basename , observed_satellite ) ;
2018-06-22 10:24:39 +00:00
2018-06-26 06:43:22 +00:00
// Read measured data
2018-07-10 16:43:36 +00:00
int ch = config - > property ( " Acquisition.dump_channel " , 0 ) ;
2018-06-26 06:43:22 +00:00
arma : : vec meas_timestamp_s = arma : : zeros ( num_executions , 1 ) ;
arma : : vec meas_doppler = arma : : zeros ( num_executions , 1 ) ;
arma : : vec positive_acq = arma : : zeros ( num_executions , 1 ) ;
arma : : vec meas_acq_delay_chips = arma : : zeros ( num_executions , 1 ) ;
2018-07-10 16:43:36 +00:00
double coh_time_ms = config - > property ( " Acquisition.coherent_integration_time_ms " , 1 ) ;
2018-06-26 06:43:22 +00:00
std : : cout < < " Num executions: " < < num_executions < < std : : endl ;
2018-07-12 22:16:57 +00:00
unsigned int fft_size = 0 ;
unsigned int d_consumed_samples = coh_time_ms * config - > property ( " GNSS-SDR.internal_fs_sps " , 0 ) * 0.001 ; // * (config->property("Acquisition.bit_transition_flag", false) ? 2 : 1);
if ( coh_time_ms = = min_integration_ms )
{
fft_size = d_consumed_samples ;
}
else
{
fft_size = d_consumed_samples * 2 ;
}
2018-06-26 06:43:22 +00:00
for ( int execution = 1 ; execution < = num_executions ; execution + + )
2018-06-24 22:56:11 +00:00
{
2019-02-22 14:57:15 +00:00
Acquisition_Dump_Reader acq_dump ( basename ,
2018-07-12 22:16:57 +00:00
observed_satellite ,
config - > property ( " Acquisition.doppler_max " , 0 ) ,
config - > property ( " Acquisition.doppler_step " , 0 ) ,
fft_size ,
ch ,
execution ) ;
2018-06-26 06:43:22 +00:00
acq_dump . read_binary_acq ( ) ;
if ( acq_dump . positive_acq )
2018-06-24 22:56:11 +00:00
{
2018-06-26 06:43:22 +00:00
//std::cout << "Meas acq_delay_samples: " << acq_dump.acq_delay_samples << " chips: " << acq_dump.acq_delay_samples / (baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS) << std::endl;
meas_timestamp_s ( execution - 1 ) = acq_dump . sample_counter / baseband_sampling_freq ;
meas_doppler ( execution - 1 ) = acq_dump . acq_doppler_hz ;
meas_acq_delay_chips ( execution - 1 ) = acq_dump . acq_delay_samples / ( baseband_sampling_freq * GPS_L1_CA_CODE_PERIOD / GPS_L1_CA_CODE_LENGTH_CHIPS ) ;
positive_acq ( execution - 1 ) = acq_dump . positive_acq ;
2018-06-24 22:56:11 +00:00
}
2018-06-26 06:43:22 +00:00
else
2018-06-24 22:56:11 +00:00
{
2018-06-26 06:43:22 +00:00
//std::cout << "Failed acquisition." << std::endl;
meas_timestamp_s ( execution - 1 ) = arma : : datum : : inf ;
meas_doppler ( execution - 1 ) = arma : : datum : : inf ;
meas_acq_delay_chips ( execution - 1 ) = arma : : datum : : inf ;
positive_acq ( execution - 1 ) = acq_dump . positive_acq ;
2018-06-24 22:56:11 +00:00
}
}
2018-06-26 06:43:22 +00:00
// Read reference data
std : : string true_trk_file = std : : string ( " ./gps_l1_ca_obs_prn " ) ;
true_trk_file . append ( std : : to_string ( observed_satellite ) ) ;
true_trk_file . append ( " .dat " ) ;
true_trk_data . close_obs_file ( ) ;
true_trk_data . open_obs_file ( true_trk_file ) ;
// load the true values
2018-08-10 19:16:10 +00:00
int64_t n_true_epochs = true_trk_data . num_epochs ( ) ;
2018-06-26 06:43:22 +00:00
arma : : vec true_timestamp_s = arma : : zeros ( n_true_epochs , 1 ) ;
arma : : vec true_acc_carrier_phase_cycles = arma : : zeros ( n_true_epochs , 1 ) ;
arma : : vec true_Doppler_Hz = arma : : zeros ( n_true_epochs , 1 ) ;
arma : : vec true_prn_delay_chips = arma : : zeros ( n_true_epochs , 1 ) ;
arma : : vec true_tow_s = arma : : zeros ( n_true_epochs , 1 ) ;
2018-08-10 19:16:10 +00:00
int64_t epoch_counter = 0 ;
2018-06-26 06:43:22 +00:00
int num_clean_executions = 0 ;
while ( true_trk_data . read_binary_obs ( ) )
2018-06-24 22:56:11 +00:00
{
2018-06-26 06:43:22 +00:00
true_timestamp_s ( epoch_counter ) = true_trk_data . signal_timestamp_s ;
true_acc_carrier_phase_cycles ( epoch_counter ) = true_trk_data . acc_carrier_phase_cycles ;
true_Doppler_Hz ( epoch_counter ) = true_trk_data . doppler_l1_hz ;
true_prn_delay_chips ( epoch_counter ) = GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data . prn_delay_chips ;
true_tow_s ( epoch_counter ) = true_trk_data . tow ;
epoch_counter + + ;
//std::cout << "True PRN_Delay chips = " << GPS_L1_CA_CODE_LENGTH_CHIPS - true_trk_data.prn_delay_chips << " at " << true_trk_data.signal_timestamp_s << std::endl;
2018-06-24 22:56:11 +00:00
}
2018-06-26 06:43:22 +00:00
// Process results
arma : : vec clean_doppler_estimation_error ;
arma : : vec clean_delay_estimation_error ;
2018-06-27 06:07:42 +00:00
2018-06-26 06:43:22 +00:00
if ( epoch_counter > 2 )
2018-06-24 22:56:11 +00:00
{
2018-06-26 06:43:22 +00:00
arma : : vec true_interpolated_doppler = arma : : zeros ( num_executions , 1 ) ;
arma : : vec true_interpolated_prn_delay_chips = arma : : zeros ( num_executions , 1 ) ;
interp1 ( true_timestamp_s , true_Doppler_Hz , meas_timestamp_s , true_interpolated_doppler ) ;
interp1 ( true_timestamp_s , true_prn_delay_chips , meas_timestamp_s , true_interpolated_prn_delay_chips ) ;
2018-06-24 22:56:11 +00:00
2018-06-26 06:43:22 +00:00
arma : : vec doppler_estimation_error = true_interpolated_doppler - meas_doppler ;
arma : : vec delay_estimation_error = true_interpolated_prn_delay_chips - ( meas_acq_delay_chips - ( ( 1.0 / baseband_sampling_freq ) / GPS_L1_CA_CHIP_PERIOD ) ) ; // compensate 1 sample delay
// Cut measurements without reference
2018-06-27 06:07:42 +00:00
for ( int i = 0 ; i < num_executions ; i + + )
2018-06-26 06:43:22 +00:00
{
if ( ! std : : isnan ( doppler_estimation_error ( i ) ) and ! std : : isnan ( delay_estimation_error ( i ) ) )
{
num_clean_executions + + ;
}
}
clean_doppler_estimation_error = arma : : zeros ( num_clean_executions , 1 ) ;
clean_delay_estimation_error = arma : : zeros ( num_clean_executions , 1 ) ;
num_clean_executions = 0 ;
2018-06-27 06:07:42 +00:00
for ( int i = 0 ; i < num_executions ; i + + )
2018-06-26 06:43:22 +00:00
{
if ( ! std : : isnan ( doppler_estimation_error ( i ) ) and ! std : : isnan ( delay_estimation_error ( i ) ) )
{
clean_doppler_estimation_error ( num_clean_executions ) = doppler_estimation_error ( i ) ;
clean_delay_estimation_error ( num_clean_executions ) = delay_estimation_error ( i ) ;
num_clean_executions + + ;
}
}
2018-06-29 11:33:53 +00:00
/* std::cout << "Doppler estimation error [Hz]: ";
2018-06-26 06:43:22 +00:00
for ( int i = 0 ; i < num_executions - 1 ; i + + )
{
std : : cout < < doppler_estimation_error ( i ) < < " " ;
}
std : : cout < < std : : endl ;
2018-06-24 22:56:11 +00:00
2018-06-26 06:43:22 +00:00
std : : cout < < " Delay estimation error [chips]: " ;
for ( int i = 0 ; i < num_executions - 1 ; i + + )
{
std : : cout < < delay_estimation_error ( i ) < < " " ;
2018-06-29 11:33:53 +00:00
2018-06-26 06:43:22 +00:00
}
2018-06-29 11:33:53 +00:00
std : : cout < < std : : endl ; */
2018-06-26 06:43:22 +00:00
}
if ( k = = 0 )
{
double detected = arma : : accu ( positive_acq ) ;
2018-06-27 06:07:42 +00:00
double computed_Pd = detected / static_cast < double > ( num_executions ) ;
if ( num_executions > 0 )
{
meas_Pd_ . push_back ( computed_Pd ) ;
}
else
{
meas_Pd_ . push_back ( 0.0 ) ;
}
2019-02-11 17:38:42 +00:00
std : : cout < < TEXT_BOLD_BLACK < < " Probability of detection for channel= " < < ch < < " , CN0= " < < it < < " dBHz "
2018-06-27 06:07:42 +00:00
< < " : " < < ( num_executions > 0 ? computed_Pd : 0.0 ) < < TEXT_RESET < < std : : endl ;
2018-06-26 06:43:22 +00:00
}
if ( num_clean_executions > 0 )
2018-06-22 10:24:39 +00:00
{
2018-06-26 06:43:22 +00:00
arma : : vec correct_acq = arma : : zeros ( num_executions , 1 ) ;
double correctly_detected = 0.0 ;
for ( int i = 0 ; i < num_clean_executions - 1 ; i + + )
2018-06-24 22:56:11 +00:00
{
2018-07-10 16:43:36 +00:00
if ( abs ( clean_delay_estimation_error ( i ) ) < 0.5 and abs ( clean_doppler_estimation_error ( i ) ) < static_cast < float > ( config - > property ( " Acquisition.doppler_step " , 1 ) ) / 2.0 )
2018-06-26 06:43:22 +00:00
{
correctly_detected = correctly_detected + 1.0 ;
}
2018-06-24 22:56:11 +00:00
}
2018-06-27 06:07:42 +00:00
double computed_Pd_correct = correctly_detected / static_cast < double > ( num_clean_executions ) ;
meas_Pd_correct_ . push_back ( computed_Pd_correct ) ;
2019-02-11 17:38:42 +00:00
std : : cout < < TEXT_BOLD_BLACK < < " Probability of correct detection for channel= " < < ch < < " , CN0= " < < it < < " dBHz "
2018-06-27 06:07:42 +00:00
< < " : " < < computed_Pd_correct < < TEXT_RESET < < std : : endl ;
2018-06-22 10:24:39 +00:00
}
2018-06-26 06:43:22 +00:00
else
{
2018-06-28 07:18:37 +00:00
//std::cout << "No reference data has been found. Maybe a non-present satellite?" << num_executions << std::endl;
2018-06-26 06:43:22 +00:00
if ( k = = 1 )
{
double wrongly_detected = arma : : accu ( positive_acq ) ;
2018-06-27 06:07:42 +00:00
double computed_Pfa = wrongly_detected / static_cast < double > ( num_executions ) ;
if ( num_executions > 0 )
{
meas_Pfa_ . push_back ( computed_Pfa ) ;
}
else
{
meas_Pfa_ . push_back ( 0.0 ) ;
}
2019-02-11 17:38:42 +00:00
std : : cout < < TEXT_BOLD_BLACK < < " Probability of false alarm for channel= " < < ch < < " , CN0= " < < it < < " dBHz "
2018-06-27 06:07:42 +00:00
< < " : " < < ( num_executions > 0 ? computed_Pfa : 0.0 ) < < TEXT_RESET < < std : : endl ;
2018-06-26 06:43:22 +00:00
}
}
true_trk_data . restart ( ) ;
2018-06-22 10:24:39 +00:00
}
2018-06-27 06:07:42 +00:00
}
true_trk_data . close_obs_file ( ) ;
float sum_pd = static_cast < float > ( std : : accumulate ( meas_Pd_ . begin ( ) , meas_Pd_ . end ( ) , 0.0 ) ) ;
float sum_pd_correct = static_cast < float > ( std : : accumulate ( meas_Pd_correct_ . begin ( ) , meas_Pd_correct_ . end ( ) , 0.0 ) ) ;
float sum_pfa = static_cast < float > ( std : : accumulate ( meas_Pfa_ . begin ( ) , meas_Pfa_ . end ( ) , 0.0 ) ) ;
2019-02-11 17:38:42 +00:00
if ( ! meas_Pd_ . empty ( ) and ! meas_Pfa_ . empty ( ) )
2018-06-27 06:07:42 +00:00
{
Pd [ cn0_index ] [ pfa_iter ] = sum_pd / static_cast < float > ( meas_Pd_ . size ( ) ) ;
Pfa [ cn0_index ] [ pfa_iter ] = sum_pfa / static_cast < float > ( meas_Pfa_ . size ( ) ) ;
}
else
{
2019-02-11 17:38:42 +00:00
if ( ! meas_Pd_ . empty ( ) )
2018-06-27 06:07:42 +00:00
{
Pd [ cn0_index ] [ pfa_iter ] = sum_pd / static_cast < float > ( meas_Pd_ . size ( ) ) ;
}
else
{
Pd [ cn0_index ] [ pfa_iter ] = 0.0 ;
}
2019-02-11 17:38:42 +00:00
if ( ! meas_Pfa_ . empty ( ) )
2018-06-27 06:07:42 +00:00
{
Pfa [ cn0_index ] [ pfa_iter ] = sum_pfa / static_cast < float > ( meas_Pfa_ . size ( ) ) ;
}
else
{
Pfa [ cn0_index ] [ pfa_iter ] = 0.0 ;
}
}
2019-02-11 17:38:42 +00:00
if ( ! meas_Pd_correct_ . empty ( ) )
2018-06-27 06:07:42 +00:00
{
Pd_correct [ cn0_index ] [ pfa_iter ] = sum_pd_correct / static_cast < float > ( meas_Pd_correct_ . size ( ) ) ;
}
else
{
Pd_correct [ cn0_index ] [ pfa_iter ] = 0.0 ;
2018-06-24 08:53:12 +00:00
}
2018-06-28 07:18:37 +00:00
meas_Pd_ . clear ( ) ;
meas_Pfa_ . clear ( ) ;
meas_Pd_correct_ . clear ( ) ;
2018-06-19 07:15:46 +00:00
}
2018-06-27 06:07:42 +00:00
cn0_index + + ;
2018-06-22 10:24:39 +00:00
}
2018-06-27 06:07:42 +00:00
// Compute results
2018-06-26 06:43:22 +00:00
unsigned int aux_index = 0 ;
2019-02-11 17:38:42 +00:00
for ( double it : cn0_vector )
2018-06-26 06:43:22 +00:00
{
2019-02-11 17:38:42 +00:00
std : : cout < < " Results for CN0 = " < < it < < " dBHz: " < < std : : endl ;
2018-06-26 06:43:22 +00:00
std : : cout < < " Pd = " ;
2018-06-27 06:07:42 +00:00
for ( int pfa_iter = 0 ; pfa_iter < num_thresholds ; pfa_iter + + )
2018-06-26 06:43:22 +00:00
{
std : : cout < < Pd [ aux_index ] [ pfa_iter ] < < " " ;
}
std : : cout < < std : : endl ;
2018-06-27 06:07:42 +00:00
std : : cout < < " Pd_correct = " ;
for ( int pfa_iter = 0 ; pfa_iter < num_thresholds ; pfa_iter + + )
{
std : : cout < < Pd_correct [ aux_index ] [ pfa_iter ] < < " " ;
}
std : : cout < < std : : endl ;
std : : cout < < " Pfa = " ;
for ( int pfa_iter = 0 ; pfa_iter < num_thresholds ; pfa_iter + + )
{
std : : cout < < Pfa [ aux_index ] [ pfa_iter ] < < " " ;
}
std : : cout < < std : : endl ;
2018-06-26 06:43:22 +00:00
aux_index + + ;
}
2018-06-28 14:30:36 +00:00
plot_results ( ) ;
2018-06-19 07:15:46 +00:00
}