beidou b1i: Merging new changes and adding bug fixes to code

This commit is contained in:
Damian Miralles 2018-10-22 14:16:38 -05:00
commit 8c16d945f8
57 changed files with 6545 additions and 60 deletions

View File

@ -2,6 +2,8 @@
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
link to website: https://gnsssdrbeidoub1igsoc2018.wordpress.com/
**Welcome to GNSS-SDR!**
This program is a software-defined receiver which is able to process (that is, to perform detection, synchronization, demodulation and decoding of the navigation message, computation of observables and, finally, computation of position fixes) the following Global Navigation Satellite System's signals:

View File

@ -0,0 +1,92 @@
; This is a GNSS-SDR configuration file
; The configuration API is described at https://gnss-sdr.org/docs/sp-blocks/
; You can define your own receiver and invoke it by doing
; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf
;
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [samples per second].
GNSS-SDR.internal_fs_sps=25000000
;######### CONTROL_THREAD CONFIG ############
ControlThread.wait_for_flowgraph=false
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=/home/sergi/gnss-sdr/data/USRP_BDS_B1I_201805171123_fs_25e6_if0e3_ishort.bin
SignalSource.item_type=ishort
SignalSource.sampling_frequency=25000000
SignalSource.samples=0
SignalSource.repeat=false
SignalSource.dump=false
SignalSource.enable_throttle_control=false
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Signal_Conditioner
DataTypeAdapter.implementation=Ishort_To_Complex
InputFilter.implementation=Pass_Through
InputFilter.item_type=gr_complex
Resampler.implementation=Direct_Resampler
Resampler.sample_freq_in=25000000
Resampler.sample_freq_out=25000000
Resampler.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channels_B1.count=2
Channels.in_acquisition=1
Channel.signal=B1
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_B1.implementation=BEIDOU_B1I_PCPS_Acquisition
Acquisition_B1.item_type=gr_complex
Acquisition_B1.coherent_integration_time_ms=1
Acquisition_B1.threshold=20
;Acquisition_B1.pfa=0.000001
Acquisition_B1.doppler_max=10000
Acquisition_B1.doppler_step=2500
Acquisition_B1.dump=true
Acquisition_B1.dump_filename=./acq_dump.dat
Acquisition_B1.blocking=false;
Acquisition_B1.use_CFAR_algorithm=false
;######### TRACKING GLOBAL CONFIG ############
Tracking_B1.implementation=BEIDOU_B1I_DLL_PLL_Tracking
Tracking_B1.item_type=gr_complex
Tracking_B1.pll_bw_hz=40.0;
Tracking_B1.dll_bw_hz=8.0;
Tracking_B1.order=3;
Tracking_B1.dump=true;
Tracking_B1.dump_filename=./epl_tracking_ch_
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_B1.implementation=BEIDOU_B1I_Telemetry_Decoder
TelemetryDecoder_B1.dump=true
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=true
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.dump_filename=./PVT
PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea;
PVT.flag_nmea_tty_port=false;
PVT.nmea_dump_devname=/dev/pts/4
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=false

View File

@ -0,0 +1,94 @@
; This is a GNSS-SDR configuration file
; The configuration API is described at https://gnss-sdr.org/docs/sp-blocks/
; You can define your own receiver and invoke it by doing
; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf
;
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [samples per second].
GNSS-SDR.internal_fs_sps=5000000
;######### CONTROL_THREAD CONFIG ############
ControlThread.wait_for_flowgraph=false
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=/home/sergi/gnss/gnss-sdr/data/stereo_l1_b1.datz
SignalSource.item_type=ishort
SignalSource.sampling_frequency=5000000
SignalSource.samples=0
SignalSource.repeat=false
SignalSource.dump=false
;SignalSource.dump_filename=../data/signal_source.dat
SignalSource.enable_throttle_control=false
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Signal_Conditioner
DataTypeAdapter.implementation=Ishort_To_Complex
InputFilter.implementation=Pass_Through
InputFilter.item_type=gr_complex
Resampler.implementation=Direct_Resampler
Resampler.sample_freq_in=5000000
Resampler.sample_freq_out=5000000
Resampler.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channels_B1.count=3
Channels.in_acquisition=1
Channel.signal=B1
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_B1.implementation=BEIDOU_B1I_PCPS_Acquisition
Acquisition_B1.item_type=gr_complex
Acquisition_B1.coherent_integration_time_ms=1
Acquisition_B1.threshold=20
;Acquisition_B1.pfa=0.000001
Acquisition_B1.doppler_max=10000
Acquisition_B1.doppler_step=2500
Acquisition_B1.dump=true
Acquisition_B1.dump_filename=./acq_dump.dat
Acquisition_B1.blocking=false;
Acquisition_B1.use_CFAR_algorithm=false
;######### TRACKING GLOBAL CONFIG ############
Tracking_B1.implementation=BEIDOU_B1I_DLL_PLL_Tracking
Tracking_B1.item_type=gr_complex
Tracking_B1.pll_bw_hz=40.0;
Tracking_B1.dll_bw_hz=8.0;
Tracking_B1.order=3;
Tracking_B1.dump=true;
Tracking_B1.dump_filename=./epl_tracking_ch_
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_B1.implementation=BEIDOU_B1I_Telemetry_Decoder
TelemetryDecoder_B1.dump=true
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=true
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.dump_filename=./PVT
PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea;
PVT.flag_nmea_tty_port=false;
PVT.nmea_dump_devname=/dev/pts/4
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=false

View File

@ -16,7 +16,7 @@ ControlThread.wait_for_flowgraph=false
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=/archive/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat ; <- PUT YOUR FILE HERE
SignalSource.filename=/home/sergi/gnss/gnss-sdr/data/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat ; <- PUT YOUR FILE HERE
SignalSource.item_type=ishort
SignalSource.sampling_frequency=4000000
SignalSource.samples=0
@ -29,13 +29,14 @@ SignalSource.enable_throttle_control=false
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Signal_Conditioner
DataTypeAdapter.implementation=Ishort_To_Cshort
DataTypeAdapter.implementation=Ishort_To_Complex
InputFilter.implementation=Pass_Through
InputFilter.item_type=cshort
InputFilter.item_type=gr_complex
Resampler.implementation=Direct_Resampler
Resampler.sample_freq_in=4000000
Resampler.sample_freq_out=2000000
Resampler.item_type=cshort
Resampler.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=8
@ -45,19 +46,19 @@ Channel.signal=1C
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=cshort
Acquisition_1C.item_type=gr_complex
Acquisition_1C.coherent_integration_time_ms=1
Acquisition_1C.threshold=0.008
;Acquisition_1C.pfa=0.000001
Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=250
Acquisition_1C.dump=false
Acquisition_1C.dump=true
Acquisition_1C.dump_filename=./acq_dump.dat
Acquisition_1C.blocking=false;
;######### TRACKING GLOBAL CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_C_Aid_Tracking
Tracking_1C.item_type=cshort
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.pll_bw_hz=40.0;
Tracking_1C.dll_bw_hz=4.0;
Tracking_1C.order=3;

56
conf/prova.conf Normal file
View File

@ -0,0 +1,56 @@
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_hz=2000000
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=/home/sergi/gnss/gnss-sdr/data/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat
SignalSource.item_type=ishort
SignalSource.sampling_frequency=4000000
SignalSource.freq=1575420000
SignalSource.samples=0
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Signal_Conditioner
DataTypeAdapter.implementation=Ishort_To_Complex
InputFilter.implementation=Pass_Through
InputFilter.item_type=gr_complex
Resampler.implementation=Direct_Resampler
Resampler.sample_freq_in=4000000
Resampler.sample_freq_out=2000000
Resampler.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=8
Channels.in_acquisition=1
Channel.signal=1C
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=gr_complex
Acquisition_1C.threshold=0.008
Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=250
;######### TRACKING GLOBAL CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.pll_bw_hz=40.0;
Tracking_1C.dll_bw_hz=4.0;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
;######### PVT CONFIG ############
PVT.implementation=GPS_L1_CA_PVT
PVT.averaging_depth=100
PVT.flag_averaging=true
PVT.output_rate_ms=10
PVT.display_rate_ms=500

View File

@ -175,43 +175,46 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration,
int gal_E5b_count = configuration->property("Channels_7X.count", 0);
int glo_1G_count = configuration->property("Channels_1G.count", 0);
int glo_2G_count = configuration->property("Channels_2G.count", 0);
int bds_B1_count = configuration->property("Channels_B1.count", 0);
unsigned int type_of_receiver = 0;
// *******************WARNING!!!!!!!***********
// GPS L5 only configurable for single frequency, single system at the moment!!!!!!
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 1;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 2;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 3;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 4;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 5;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 6;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 1;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 2;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 3;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 4;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 5;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 6;
if ((gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 7;
if ((gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 7;
//if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 8;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 9;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 10;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 11;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 12;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 9;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 10;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 11;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 12;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 13;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 14;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 15;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 14;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 15;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 16;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 17;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 18;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 17;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 18;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 19;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 20;
if ((gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 21;
if ((gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 21;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count = 0)) type_of_receiver = 22;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 23;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 24;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count != 0)) type_of_receiver = 25;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0)) type_of_receiver = 26;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0)) type_of_receiver = 27;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0)) type_of_receiver = 28;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 29;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 30;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 31;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (bds_B1_count == 0)) type_of_receiver = 23;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0) && (bds_B1_count == 0)) type_of_receiver = 24;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count != 0) && (bds_B1_count == 0)) type_of_receiver = 25;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 26;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 27;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0) && (bds_B1_count == 0)) type_of_receiver = 28;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0) && (bds_B1_count == 0)) type_of_receiver = 29;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0) && (bds_B1_count == 0)) type_of_receiver = 30;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0) && (bds_B1_count == 0)) type_of_receiver = 31;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0) && (bds_B1_count != 0)) type_of_receiver = 32;
//RTKLIB PVT solver options
// Settings 1
int positioning_mode = -1;
@ -235,7 +238,7 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration,
int num_bands = 0;
if ((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) num_bands = 1;
if ((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0) || (bds_B1_count > 0)) num_bands = 1;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && ((gps_2S_count > 0) || (glo_2G_count > 0))) num_bands = 2;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && ((gal_E5a_count > 0) || (gal_E5b_count > 0) || (gps_L5_count > 0))) num_bands = 2;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && ((gps_2S_count > 0) || (glo_2G_count > 0)) && ((gal_E5a_count > 0) || (gal_E5b_count > 0) || (gps_L5_count > 0))) num_bands = 3;
@ -322,6 +325,8 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration,
if ((gps_1C_count > 0) || (gps_2S_count > 0) || (gps_L5_count > 0)) nsys += SYS_GPS;
if ((gal_1B_count > 0) || (gal_E5a_count > 0) || (gal_E5b_count > 0)) nsys += SYS_GAL;
if ((glo_1G_count > 0) || (glo_2G_count > 0)) nsys += SYS_GLO;
if ((bds_B1_count > 0)) nsys += SYS_BDS;
int navigation_system = configuration->property(role + ".navigation_system", nsys); /* (SYS_XXX) see src/algorithms/libs/rtklib/rtklib.h */
if ((navigation_system < 1) || (navigation_system > 255)) /* GPS: 1 SBAS: 2 GPS+SBAS: 3 Galileo: 8 Galileo+GPS: 9 GPS+SBAS+Galileo: 11 All: 255 */
{

View File

@ -0,0 +1,561 @@
/*!
* \file rtklib_pvt.cc
* \brief Interface of a Position Velocity and Time computation block
* \author Javier Arribas, 2017. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#include "rtklib_pvt.h"
#include "configuration_interface.h"
#include "gnss_sdr_flags.h"
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/math/common_factor_rt.hpp>
#include <boost/serialization/map.hpp>
#include <glog/logging.h>
using google::LogMessage;
RtklibPvt::RtklibPvt(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams) : role_(role),
in_streams_(in_streams),
out_streams_(out_streams)
{
// dump parameters
std::string default_dump_filename = "./pvt.dat";
std::string default_nmea_dump_filename = "./nmea_pvt.nmea";
std::string default_nmea_dump_devname = "/dev/tty1";
std::string default_rtcm_dump_devname = "/dev/pts/1";
DLOG(INFO) << "role " << role;
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
// output rate
int output_rate_ms = configuration->property(role + ".output_rate_ms", 500);
// display rate
int display_rate_ms = configuration->property(role + ".display_rate_ms", 500);
// NMEA Printer settings
bool flag_nmea_tty_port = configuration->property(role + ".flag_nmea_tty_port", false);
std::string nmea_dump_filename = configuration->property(role + ".nmea_dump_filename", default_nmea_dump_filename);
std::string nmea_dump_devname = configuration->property(role + ".nmea_dump_devname", default_nmea_dump_devname);
// RINEX version
int rinex_version = configuration->property(role + ".rinex_version", 3);
if (FLAGS_RINEX_version.compare("3.01") == 0)
{
rinex_version = 3;
}
else if (FLAGS_RINEX_version.compare("3.02") == 0)
{
rinex_version = 3;
}
else if (FLAGS_RINEX_version.compare("3") == 0)
{
rinex_version = 3;
}
else if (FLAGS_RINEX_version.compare("2.11") == 0)
{
rinex_version = 2;
}
else if (FLAGS_RINEX_version.compare("2.10") == 0)
{
rinex_version = 2;
}
else if (FLAGS_RINEX_version.compare("2") == 0)
{
rinex_version = 2;
}
int rinexobs_rate_ms = boost::math::lcm(configuration->property(role + ".rinexobs_rate_ms", 1000), output_rate_ms);
int rinexnav_rate_ms = boost::math::lcm(configuration->property(role + ".rinexnav_rate_ms", 6000), output_rate_ms);
// RTCM Printer settings
bool flag_rtcm_tty_port = configuration->property(role + ".flag_rtcm_tty_port", false);
std::string rtcm_dump_devname = configuration->property(role + ".rtcm_dump_devname", default_rtcm_dump_devname);
bool flag_rtcm_server = configuration->property(role + ".flag_rtcm_server", false);
unsigned short rtcm_tcp_port = configuration->property(role + ".rtcm_tcp_port", 2101);
unsigned short rtcm_station_id = configuration->property(role + ".rtcm_station_id", 1234);
// RTCM message rates: least common multiple with output_rate_ms
int rtcm_MT1019_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1019_rate_ms", 5000), output_rate_ms);
int rtcm_MT1020_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1020_rate_ms", 5000), output_rate_ms);
int rtcm_MT1045_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1045_rate_ms", 5000), output_rate_ms);
int rtcm_MSM_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MSM_rate_ms", 1000), output_rate_ms);
int rtcm_MT1077_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1077_rate_ms", rtcm_MSM_rate_ms), output_rate_ms);
int rtcm_MT1087_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1087_rate_ms", rtcm_MSM_rate_ms), output_rate_ms);
int rtcm_MT1097_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1097_rate_ms", rtcm_MSM_rate_ms), output_rate_ms);
std::map<int, int> rtcm_msg_rate_ms;
rtcm_msg_rate_ms[1019] = rtcm_MT1019_rate_ms;
rtcm_msg_rate_ms[1020] = rtcm_MT1020_rate_ms;
rtcm_msg_rate_ms[1045] = rtcm_MT1045_rate_ms;
for (int k = 1071; k < 1078; k++) // All GPS MSM
{
rtcm_msg_rate_ms[k] = rtcm_MT1077_rate_ms;
}
for (int k = 1081; k < 1088; k++) // All GLONASS MSM
{
rtcm_msg_rate_ms[k] = rtcm_MT1087_rate_ms;
}
for (int k = 1091; k < 1098; k++) // All Galileo MSM
{
rtcm_msg_rate_ms[k] = rtcm_MT1097_rate_ms;
}
// getting names from the config file, if available
// default filename for assistance data
const std::string eph_default_xml_filename = "./gps_ephemeris.xml";
const std::string utc_default_xml_filename = "./gps_utc_model.xml";
const std::string iono_default_xml_filename = "./gps_iono.xml";
const std::string ref_time_default_xml_filename = "./gps_ref_time.xml";
const std::string ref_location_default_xml_filename = "./gps_ref_location.xml";
eph_xml_filename_ = configuration->property("GNSS-SDR.SUPL_gps_ephemeris_xml", eph_default_xml_filename);
//std::string utc_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_utc_model.xml", utc_default_xml_filename);
//std::string iono_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_iono_xml", iono_default_xml_filename);
//std::string ref_time_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_ref_time_xml", ref_time_default_xml_filename);
//std::string ref_location_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_ref_location_xml", ref_location_default_xml_filename);
// Infer the type of receiver
/*
* TYPE | RECEIVER
* 0 | Unknown
* 1 | GPS L1 C/A
* 2 | GPS L2C
* 3 | GPS L5
* 4 | Galileo E1B
* 5 | Galileo E5a
* 6 | Galileo E5b
* 7 | GPS L1 C/A + GPS L2C
* 8 | GPS L1 C/A + GPS L5
* 9 | GPS L1 C/A + Galileo E1B
* 10 | GPS L1 C/A + Galileo E5a
* 11 | GPS L1 C/A + Galileo E5b
* 12 | Galileo E1B + GPS L2C
* 13 | Galileo E1B + GPS L5
* 14 | Galileo E1B + Galileo E5a
* 15 | Galileo E1B + Galileo E5b
* 16 | GPS L2C + GPS L5
* 17 | GPS L2C + Galileo E5a
* 18 | GPS L2C + Galileo E5b
* 19 | GPS L5 + Galileo E5a
* 20 | GPS L5 + Galileo E5b
* 21 | GPS L1 C/A + Galileo E1B + GPS L2C
* 22 | GPS L1 C/A + Galileo E1B + GPS L5
* 23 | GLONASS L1 C/A
* 24 | GLONASS L2 C/A
* 25 | GLONASS L1 C/A + GLONASS L2 C/A
* 26 | GPS L1 C/A + GLONASS L1 C/A
* 27 | Galileo E1B + GLONASS L1 C/A
* 28 | GPS L2C + GLONASS L1 C/A
*/
int gps_1C_count = configuration->property("Channels_1C.count", 0);
int gps_2S_count = configuration->property("Channels_2S.count", 0);
int gps_L5_count = configuration->property("Channels_L5.count", 0);
int gal_1B_count = configuration->property("Channels_1B.count", 0);
int gal_E5a_count = configuration->property("Channels_5X.count", 0);
int gal_E5b_count = configuration->property("Channels_7X.count", 0);
int glo_1G_count = configuration->property("Channels_1G.count", 0);
int glo_2G_count = configuration->property("Channels_2G.count", 0);
unsigned int type_of_receiver = 0;
// *******************WARNING!!!!!!!***********
// GPS L5 only configurable for single frequency, single system at the moment!!!!!!
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 1;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 2;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 3;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 4;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 5;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 6;
if ((gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 7;
//if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 8;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 9;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 10;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 11;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 12;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 13;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 14;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 15;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 16;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 17;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 18;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 19;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 20;
if ((gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 21;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count = 0)) type_of_receiver = 22;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 23;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 24;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count != 0)) type_of_receiver = 25;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0)) type_of_receiver = 26;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0)) type_of_receiver = 27;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0)) type_of_receiver = 28;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 29;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 30;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 31;
//RTKLIB PVT solver options
// Settings 1
int positioning_mode = -1;
std::string default_pos_mode("Single");
std::string positioning_mode_str = configuration->property(role + ".positioning_mode", default_pos_mode); /* (PMODE_XXX) see src/algorithms/libs/rtklib/rtklib.h */
if (positioning_mode_str.compare("Single") == 0) positioning_mode = PMODE_SINGLE;
if (positioning_mode_str.compare("Static") == 0) positioning_mode = PMODE_STATIC;
if (positioning_mode_str.compare("Kinematic") == 0) positioning_mode = PMODE_KINEMA;
if (positioning_mode_str.compare("PPP_Static") == 0) positioning_mode = PMODE_PPP_STATIC;
if (positioning_mode_str.compare("PPP_Kinematic") == 0) positioning_mode = PMODE_PPP_KINEMA;
if (positioning_mode == -1)
{
//warn user and set the default
std::cout << "WARNING: Bad specification of positioning mode." << std::endl;
std::cout << "positioning_mode possible values: Single / Static / Kinematic / PPP_Static / PPP_Kinematic" << std::endl;
std::cout << "positioning_mode specified value: " << positioning_mode_str << std::endl;
std::cout << "Setting positioning_mode to Single" << std::endl;
positioning_mode = PMODE_SINGLE;
}
int num_bands = 0;
if ((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) num_bands = 1;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && ((gps_2S_count > 0) || (glo_2G_count > 0))) num_bands = 2;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && ((gal_E5a_count > 0) || (gal_E5b_count > 0) || (gps_L5_count > 0))) num_bands = 2;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && ((gps_2S_count > 0) || (glo_2G_count > 0)) && ((gal_E5a_count > 0) || (gal_E5b_count > 0) || (gps_L5_count > 0))) num_bands = 3;
int number_of_frequencies = configuration->property(role + ".num_bands", num_bands); /* (1:L1, 2:L1+L2, 3:L1+L2+L5) */
if ((number_of_frequencies < 1) || (number_of_frequencies > 3))
{
//warn user and set the default
number_of_frequencies = num_bands;
}
double elevation_mask = configuration->property(role + ".elevation_mask", 15.0);
if ((elevation_mask < 0.0) || (elevation_mask > 90.0))
{
//warn user and set the default
LOG(WARNING) << "Erroneous Elevation Mask. Setting to default value of 15.0 degrees";
elevation_mask = 15.0;
}
int dynamics_model = configuration->property(role + ".dynamics_model", 0); /* dynamics model (0:none, 1:velocity, 2:accel) */
if ((dynamics_model < 0) || (dynamics_model > 2))
{
//warn user and set the default
LOG(WARNING) << "Erroneous Dynamics Model configuration. Setting to default value of (0:none)";
dynamics_model = 0;
}
std::string default_iono_model("OFF");
std::string iono_model_str = configuration->property(role + ".iono_model", default_iono_model); /* (IONOOPT_XXX) see src/algorithms/libs/rtklib/rtklib.h */
int iono_model = -1;
if (iono_model_str.compare("OFF") == 0) iono_model = IONOOPT_OFF;
if (iono_model_str.compare("Broadcast") == 0) iono_model = IONOOPT_BRDC;
if (iono_model_str.compare("SBAS") == 0) iono_model = IONOOPT_SBAS;
if (iono_model_str.compare("Iono-Free-LC") == 0) iono_model = IONOOPT_IFLC;
if (iono_model_str.compare("Estimate_STEC") == 0) iono_model = IONOOPT_EST;
if (iono_model_str.compare("IONEX") == 0) iono_model = IONOOPT_TEC;
if (iono_model == -1)
{
//warn user and set the default
std::cout << "WARNING: Bad specification of ionospheric model." << std::endl;
std::cout << "iono_model possible values: OFF / Broadcast / SBAS / Iono-Free-LC / Estimate_STEC / IONEX" << std::endl;
std::cout << "iono_model specified value: " << iono_model_str << std::endl;
std::cout << "Setting iono_model to OFF" << std::endl;
iono_model = IONOOPT_OFF; /* 0: ionosphere option: correction off */
}
std::string default_trop_model("OFF");
int trop_model = -1;
std::string trop_model_str = configuration->property(role + ".trop_model", default_trop_model); /* (TROPOPT_XXX) see src/algorithms/libs/rtklib/rtklib.h */
if (trop_model_str.compare("OFF") == 0) trop_model = TROPOPT_OFF;
if (trop_model_str.compare("Saastamoinen") == 0) trop_model = TROPOPT_SAAS;
if (trop_model_str.compare("SBAS") == 0) trop_model = TROPOPT_SBAS;
if (trop_model_str.compare("Estimate_ZTD") == 0) trop_model = TROPOPT_EST;
if (trop_model_str.compare("Estimate_ZTD_Grad") == 0) trop_model = TROPOPT_ESTG;
if (trop_model == -1)
{
//warn user and set the default
std::cout << "WARNING: Bad specification of tropospheric model." << std::endl;
std::cout << "trop_model possible values: OFF / Saastamoinen / SBAS / Estimate_ZTD / Estimate_ZTD_Grad" << std::endl;
std::cout << "trop_model specified value: " << trop_model_str << std::endl;
std::cout << "Setting trop_model to OFF" << std::endl;
trop_model = TROPOPT_OFF;
}
/* RTKLIB positioning options */
int sat_PCV = 0; /* Set whether the satellite antenna PCV (phase center variation) model is used or not. This feature requires a Satellite Antenna PCV File. */
int rec_PCV = 0; /* Set whether the receiver antenna PCV (phase center variation) model is used or not. This feature requires a Receiver Antenna PCV File. */
/* Set whether the phase windup correction for PPP modes is applied or not. Only applicable to PPP* modes.*/
int phwindup = configuration->property(role + ".phwindup", 0);
/* Set whether the GPS Block IIA satellites in eclipse are excluded or not.
The eclipsing Block IIA satellites often degrade the PPP solutions due to unpredicted behavior of yawattitude. Only applicable to PPP* modes.*/
int reject_GPS_IIA = configuration->property(role + ".reject_GPS_IIA", 0);
/* Set whether RAIM (receiver autonomous integrity monitoring) FDE (fault detection and exclusion) feature is enabled or not.
In case of RAIM FDE enabled, a satellite is excluded if SSE (sum of squared errors) of residuals is over a threshold.
The excluded satellite is selected to indicate the minimum SSE. */
int raim_fde = configuration->property(role + ".raim_fde", 0);
int earth_tide = configuration->property(role + ".earth_tide", 0);
int nsys = 0;
if ((gps_1C_count > 0) || (gps_2S_count > 0) || (gps_L5_count > 0)) nsys += SYS_GPS;
if ((gal_1B_count > 0) || (gal_E5a_count > 0) || (gal_E5b_count > 0)) nsys += SYS_GAL;
if ((glo_1G_count > 0) || (glo_2G_count > 0)) nsys += SYS_GLO;
int navigation_system = configuration->property(role + ".navigation_system", nsys); /* (SYS_XXX) see src/algorithms/libs/rtklib/rtklib.h */
if ((navigation_system < 1) || (navigation_system > 255)) /* GPS: 1 SBAS: 2 GPS+SBAS: 3 Galileo: 8 Galileo+GPS: 9 GPS+SBAS+Galileo: 11 All: 255 */
{
//warn user and set the default
LOG(WARNING) << "Erroneous Navigation System. Setting to default value of (0:none)";
navigation_system = nsys;
}
// Settings 2
std::string default_gps_ar("Continuous");
std::string integer_ambiguity_resolution_gps_str = configuration->property(role + ".AR_GPS", default_gps_ar); /* Integer Ambiguity Resolution mode for GPS (0:off,1:continuous,2:instantaneous,3:fix and hold,4:ppp-ar) */
int integer_ambiguity_resolution_gps = -1;
if (integer_ambiguity_resolution_gps_str.compare("OFF") == 0) integer_ambiguity_resolution_gps = ARMODE_OFF;
if (integer_ambiguity_resolution_gps_str.compare("Continuous") == 0) integer_ambiguity_resolution_gps = ARMODE_CONT;
if (integer_ambiguity_resolution_gps_str.compare("Instantaneous") == 0) integer_ambiguity_resolution_gps = ARMODE_INST;
if (integer_ambiguity_resolution_gps_str.compare("Fix-and-Hold") == 0) integer_ambiguity_resolution_gps = ARMODE_FIXHOLD;
if (integer_ambiguity_resolution_gps_str.compare("PPP-AR") == 0) integer_ambiguity_resolution_gps = ARMODE_PPPAR;
if (integer_ambiguity_resolution_gps == -1)
{
//warn user and set the default
std::cout << "WARNING: Bad specification of GPS ambiguity resolution method." << std::endl;
std::cout << "AR_GPS possible values: OFF / Continuous / Instantaneous / Fix-and-Hold / PPP-AR" << std::endl;
std::cout << "AR_GPS specified value: " << integer_ambiguity_resolution_gps_str << std::endl;
std::cout << "Setting AR_GPS to OFF" << std::endl;
integer_ambiguity_resolution_gps = ARMODE_OFF;
}
int integer_ambiguity_resolution_glo = configuration->property(role + ".AR_GLO", 1); /* Integer Ambiguity Resolution mode for GLONASS (0:off,1:on,2:auto cal,3:ext cal) */
if ((integer_ambiguity_resolution_glo < 0) || (integer_ambiguity_resolution_glo > 3))
{
//warn user and set the default
LOG(WARNING) << "Erroneous Integer Ambiguity Resolution for GLONASS . Setting to default value of (1:on)";
integer_ambiguity_resolution_glo = 1;
}
int integer_ambiguity_resolution_bds = configuration->property(role + ".AR_DBS", 1); /* Integer Ambiguity Resolution mode for BEIDOU (0:off,1:on) */
if ((integer_ambiguity_resolution_bds < 0) || (integer_ambiguity_resolution_bds > 1))
{
//warn user and set the default
LOG(WARNING) << "Erroneous Integer Ambiguity Resolution for BEIDOU . Setting to default value of (1:on)";
integer_ambiguity_resolution_bds = 1;
}
double min_ratio_to_fix_ambiguity = configuration->property(role + ".min_ratio_to_fix_ambiguity", 3.0); /* Set the integer ambiguity validation threshold for ratiotest,
which uses the ratio of squared residuals of the best integer vector to the secondbest vector. */
int min_lock_to_fix_ambiguity = configuration->property(role + ".min_lock_to_fix_ambiguity", 0); /* Set the minimum lock count to fix integer ambiguity.
If the lock count is less than the value, the ambiguity is excluded from the fixed integer vector. */
double min_elevation_to_fix_ambiguity = configuration->property(role + ".min_elevation_to_fix_ambiguity", 0.0); /* Set the minimum elevation (deg) to fix integer ambiguity.
If the elevation of the satellite is less than the value, the ambiguity is excluded from the fixed integer vector. */
int outage_reset_ambiguity = configuration->property(role + ".outage_reset_ambiguity", 5); /* Set the outage count to reset ambiguity. If the data outage count is over the value, the estimated ambiguity is reset to the initial value. */
double slip_threshold = configuration->property(role + ".slip_threshold", 0.05); /* set the cycleslip threshold (m) of geometryfree LC carrierphase difference between epochs */
double threshold_reject_gdop = configuration->property(role + ".threshold_reject_gdop", 30.0); /* reject threshold of GDOP. If the GDOP is over the value, the observable is excluded for the estimation process as an outlier. */
double threshold_reject_innovation = configuration->property(role + ".threshold_reject_innovation", 30.0); /* reject threshold of innovation (m). If the innovation is over the value, the observable is excluded for the estimation process as an outlier. */
int number_filter_iter = configuration->property(role + ".number_filter_iter", 1); /* Set the number of iteration in the measurement update of the estimation filter.
If the baseline length is very short like 1 m, the iteration may be effective to handle
the nonlinearity of measurement equation. */
/// Statistics
double bias_0 = configuration->property(role + ".bias_0", 30.0);
double iono_0 = configuration->property(role + ".iono_0", 0.03);
double trop_0 = configuration->property(role + ".trop_0", 0.3);
double sigma_bias = configuration->property(role + ".sigma_bias", 1e-4); /* Set the process noise standard deviation of carrierphase
bias (ambiguity) (cycle/sqrt(s)) */
double sigma_iono = configuration->property(role + ".sigma_iono", 1e-3); /* Set the process noise standard deviation of vertical ionospheric delay per 10 km baseline (m/sqrt(s)). */
double sigma_trop = configuration->property(role + ".sigma_trop", 1e-4); /* Set the process noise standard deviation of zenith tropospheric delay (m/sqrt(s)). */
double sigma_acch = configuration->property(role + ".sigma_acch", 1e-1); /* Set the process noise standard deviation of the receiver acceleration as
the horizontal component. (m/s2/sqrt(s)). If Receiver Dynamics is set to OFF, they are not used. */
double sigma_accv = configuration->property(role + ".sigma_accv", 1e-2); /* Set the process noise standard deviation of the receiver acceleration as
the vertical component. (m/s2/sqrt(s)). If Receiver Dynamics is set to OFF, they are not used. */
double sigma_pos = configuration->property(role + ".sigma_pos", 0.0);
double code_phase_error_ratio_l1 = configuration->property(role + ".code_phase_error_ratio_l1", 100.0);
double code_phase_error_ratio_l2 = configuration->property(role + ".code_phase_error_ratio_l2", 100.0);
double code_phase_error_ratio_l5 = configuration->property(role + ".code_phase_error_ratio_l5", 100.0);
double carrier_phase_error_factor_a = configuration->property(role + ".carrier_phase_error_factor_a", 0.003);
double carrier_phase_error_factor_b = configuration->property(role + ".carrier_phase_error_factor_b", 0.003);
snrmask_t snrmask = {{}, {{}, {}}};
prcopt_t rtklib_configuration_options = {
positioning_mode, /* positioning mode (PMODE_XXX) see src/algorithms/libs/rtklib/rtklib.h */
0, /* solution type (0:forward,1:backward,2:combined) */
number_of_frequencies, /* number of frequencies (1:L1, 2:L1+L2, 3:L1+L2+L5)*/
navigation_system, /* navigation system */
elevation_mask * D2R, /* elevation mask angle (degrees) */
snrmask, /* snrmask_t snrmask SNR mask */
0, /* satellite ephemeris/clock (EPHOPT_XXX) */
integer_ambiguity_resolution_gps, /* AR mode (0:off,1:continuous,2:instantaneous,3:fix and hold,4:ppp-ar) */
integer_ambiguity_resolution_glo, /* GLONASS AR mode (0:off,1:on,2:auto cal,3:ext cal) */
integer_ambiguity_resolution_bds, /* BeiDou AR mode (0:off,1:on) */
outage_reset_ambiguity, /* obs outage count to reset bias */
min_lock_to_fix_ambiguity, /* min lock count to fix ambiguity */
10, /* min fix count to hold ambiguity */
1, /* max iteration to resolve ambiguity */
iono_model, /* ionosphere option (IONOOPT_XXX) */
trop_model, /* troposphere option (TROPOPT_XXX) */
dynamics_model, /* dynamics model (0:none, 1:velocity, 2:accel) */
earth_tide, /* earth tide correction (0:off,1:solid,2:solid+otl+pole) */
number_filter_iter, /* number of filter iteration */
0, /* code smoothing window size (0:none) */
0, /* interpolate reference obs (for post mission) */
0, /* sbssat_t sbssat SBAS correction options */
0, /* sbsion_t sbsion[MAXBAND+1] SBAS satellite selection (0:all) */
0, /* rover position for fixed mode */
0, /* base position for relative mode */
/* 0:pos in prcopt, 1:average of single pos, */
/* 2:read from file, 3:rinex header, 4:rtcm pos */
{code_phase_error_ratio_l1, code_phase_error_ratio_l2, code_phase_error_ratio_l5}, /* eratio[NFREQ] code/phase error ratio */
{100.0, carrier_phase_error_factor_a, carrier_phase_error_factor_b, 0.0, 1.0}, /* err[5]: measurement error factor [0]:reserved, [1-3]:error factor a/b/c of phase (m) , [4]:doppler frequency (hz) */
{bias_0, iono_0, trop_0}, /* std[3]: initial-state std [0]bias,[1]iono [2]trop*/
{sigma_bias, sigma_iono, sigma_trop, sigma_acch, sigma_accv, sigma_pos}, /* prn[6] process-noise std */
5e-12, /* sclkstab: satellite clock stability (sec/sec) */
{min_ratio_to_fix_ambiguity, 0.9999, 0.25, 0.1, 0.05, 0.0, 0.0, 0.0}, /* thresar[8]: AR validation threshold */
min_elevation_to_fix_ambiguity, /* elevation mask of AR for rising satellite (deg) */
0.0, /* elevation mask to hold ambiguity (deg) */
slip_threshold, /* slip threshold of geometry-free phase (m) */
30.0, /* max difference of time (sec) */
threshold_reject_innovation, /* reject threshold of innovation (m) */
threshold_reject_gdop, /* reject threshold of gdop */
{}, /* double baseline[2] baseline length constraint {const,sigma} (m) */
{}, /* double ru[3] rover position for fixed mode {x,y,z} (ecef) (m) */
{}, /* double rb[3] base position for relative mode {x,y,z} (ecef) (m) */
{"", ""}, /* char anttype[2][MAXANT] antenna types {rover,base} */
{{}, {}}, /* double antdel[2][3] antenna delta {{rov_e,rov_n,rov_u},{ref_e,ref_n,ref_u}} */
{}, /* pcv_t pcvr[2] receiver antenna parameters {rov,base} */
{}, /* unsigned char exsats[MAXSAT] excluded satellites (1:excluded, 2:included) */
0, /* max averaging epoches */
0, /* initialize by restart */
1, /* output single by dgps/float/fix/ppp outage */
{"", ""}, /* char rnxopt[2][256] rinex options {rover,base} */
{sat_PCV, rec_PCV, phwindup, reject_GPS_IIA, raim_fde}, /* posopt[6] positioning options [0]: satellite and receiver antenna PCV model; [1]: interpolate antenna parameters; [2]: apply phase wind-up correction for PPP modes; [3]: exclude measurements of GPS Block IIA satellites satellite [4]: RAIM FDE (fault detection and exclusion) [5]: handle day-boundary clock jump */
0, /* solution sync mode (0:off,1:on) */
{{}, {}}, /* odisp[2][6*11] ocean tide loading parameters {rov,base} */
{{}, {{}, {}}, {{}, {}}, {}, {}}, /* exterr_t exterr extended receiver error model */
0, /* disable L2-AR */
{} /* char pppopt[256] ppp option "-GAP_RESION=" default gap to reset iono parameters (ep) */
};
rtkinit(&rtk, &rtklib_configuration_options);
// make PVT object
pvt_ = rtklib_make_pvt_cc(in_streams_, dump_, dump_filename_, output_rate_ms, display_rate_ms, flag_nmea_tty_port, nmea_dump_filename, nmea_dump_devname, rinex_version, rinexobs_rate_ms, rinexnav_rate_ms, flag_rtcm_server, flag_rtcm_tty_port, rtcm_tcp_port, rtcm_station_id, rtcm_msg_rate_ms, rtcm_dump_devname, type_of_receiver, rtk);
DLOG(INFO) << "pvt(" << pvt_->unique_id() << ")";
if (out_streams_ > 0)
{
LOG(ERROR) << "The PVT block does not have an output stream";
}
}
bool RtklibPvt::save_assistance_to_XML()
{
LOG(INFO) << "SUPL: Try to save GPS ephemeris to XML file " << eph_xml_filename_;
std::map<int, Gps_Ephemeris> eph_map = pvt_->get_GPS_L1_ephemeris_map();
if (eph_map.size() > 0)
{
try
{
std::ofstream ofs(eph_xml_filename_.c_str(), std::ofstream::trunc | std::ofstream::out);
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_ephemeris_map", eph_map);
ofs.close();
LOG(INFO) << "Saved GPS L1 Ephemeris map data";
}
catch (const std::exception& e)
{
LOG(WARNING) << e.what();
return false;
}
return true; // return variable (true == succeeded)
}
else
{
LOG(WARNING) << "Failed to save Ephemeris, map is empty";
return false;
}
}
RtklibPvt::~RtklibPvt()
{
rtkfree(&rtk);
save_assistance_to_XML();
}
void RtklibPvt::connect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
// Nothing to connect internally
DLOG(INFO) << "nothing to connect internally";
}
void RtklibPvt::disconnect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
// Nothing to disconnect
}
gr::basic_block_sptr RtklibPvt::get_left_block()
{
return pvt_;
}
gr::basic_block_sptr RtklibPvt::get_right_block()
{
return pvt_; // this is a sink, nothing downstream
}

View File

@ -231,6 +231,37 @@ void rtklib_pvt_cc::msg_handler_telemetry(pmt::pmt_t msg)
DLOG(INFO) << "New GLONASS GNAV Almanac has arrived "
<< ", GLONASS GNAV Slot Number =" << glonass_gnav_almanac->d_n_A;
}
// ************* BEIDOU telemetry *****************
if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Beidou_Ephemeris>))
{
// ### BEIDOU EPHEMERIS ###
std::shared_ptr<Beidou_Ephemeris> beidou_eph;
beidou_eph = boost::any_cast<std::shared_ptr<Beidou_Ephemeris>>(pmt::any_ref(msg));
DLOG(INFO) << "Ephemeris record has arrived from SAT ID "
<< beidou_eph->i_satellite_PRN << " (Block "
<< beidou_eph->satelliteBlock[beidou_eph->i_satellite_PRN] << ")"
<< "inserted with Toe=" << beidou_eph->d_Toe << " and BEIDOU Week="
<< beidou_eph->i_BEIDOU_week;
// update/insert new ephemeris record to the global ephemeris map
d_ls_pvt->beidou_ephemeris_map[beidou_eph->i_satellite_PRN] = *beidou_eph;
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Beidou_Iono>))
{
// ### BEIDOU IONO ###
std::shared_ptr<Beidou_Iono> beidou_iono;
beidou_iono = boost::any_cast<std::shared_ptr<Beidou_Iono>>(pmt::any_ref(msg));
d_ls_pvt->beidou_iono = *beidou_iono;
DLOG(INFO) << "New IONO record has arrived ";
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Beidou_Utc_Model>))
{
// ### BEIDOU UTC MODEL ###
std::shared_ptr<Beidou_Utc_Model> beidou_utc_model;
beidou_utc_model = boost::any_cast<std::shared_ptr<Beidou_Utc_Model>>(pmt::any_ref(msg));
d_ls_pvt->beidou_utc_model = *beidou_utc_model;
DLOG(INFO) << "New UTC record has arrived ";
}
else
{
LOG(WARNING) << "msg_handler_telemetry unknown object type!";
@ -482,6 +513,28 @@ rtklib_pvt_cc::~rtklib_pvt_cc()
{
LOG(INFO) << "Failed to save GLONASS GNAV Ephemeris, map is empty";
}
// save Beidou B1I ephemeris to XML file
file_name = "eph_BEIDOU_b1I.xml";
if (d_ls_pvt->beidou_ephemeris_map.size() > 0)
{
try
{
std::ofstream ofs(file_name.c_str(), std::ofstream::trunc | std::ofstream::out);
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_ephemeris_map", d_ls_pvt->beidou_ephemeris_map);
ofs.close();
LOG(INFO) << "Saved BEIDOU Ephemeris map data";
}
catch (std::exception& e)
{
LOG(WARNING) << e.what();
}
}
else
{
LOG(WARNING) << "Failed to save BEIDOU Ephemeris, map is empty";
}
// Save GPS UTC model parameters
file_name = "gps_utc_model.xml";
@ -728,6 +781,14 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
d_rtcm_printer->lock_time(d_ls_pvt->glonass_gnav_ephemeris_map.find(in[i][epoch].PRN)->second, in[i][epoch].RX_time, in[i][epoch]); // keep track of locking time
}
}
/* if (d_ls_pvt->beidou_ephemeris_map.size() > 0)
{
if (tmp_eph_iter_bds != d_ls_pvt->beidou_ephemeris_map.end())
{
d_rtcm_printer->lock_time(d_ls_pvt->beidou_ephemeris_map.find(in[i][epoch].PRN)->second, in[i][epoch].RX_time, in[i][epoch]); // keep track of locking time
}
}
*/
}
catch (const boost::exception& ex)
{
@ -872,6 +933,7 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
* 29 | GPS L1 C/A + GLONASS L2 C/A
* 30 | Galileo E1B + GLONASS L2 C/A
* 31 | GPS L2C + GLONASS L2 C/A
* 32 | Beidou B1I
*/
// ####################### RINEX FILES #################
@ -880,6 +942,8 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
std::map<int, Gps_Ephemeris>::const_iterator gps_ephemeris_iter;
std::map<int, Gps_CNAV_Ephemeris>::const_iterator gps_cnav_ephemeris_iter;
std::map<int, Glonass_Gnav_Ephemeris>::const_iterator glonass_gnav_ephemeris_iter;
std::map<int, Beidou_Ephemeris>::const_iterator beidou_ephemeris_iter;
std::map<int, Gnss_Synchro>::const_iterator gnss_observables_iter;
if (!b_rinex_header_written) // & we have utc data in nav message!
@ -888,6 +952,7 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.cbegin();
gps_cnav_ephemeris_iter = d_ls_pvt->gps_cnav_ephemeris_map.cbegin();
glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin();
beidou_ephemeris_iter = d_ls_pvt->beidou_ephemeris_map.cbegin();
if (type_of_rx == 1) // GPS L1 C/A only
{
@ -1110,6 +1175,17 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
b_rinex_header_written = true; // do not write header anymore
}
}
/* if (type_of_rx == 32) // Beidou B1I only
{
if (beidou_ephemeris_iter != d_ls_pvt->beidou_ephemeris_map.cend())
{
rp->rinex_obs_header(rp->obsFile, beidou_ephemeris_iter->second, d_rx_time);
rp->rinex_nav_header(rp->navFile, d_ls_pvt->beidou_iono, d_ls_pvt->beidou_utc_model);
b_rinex_header_written = true; // do not write header anymore
}
}
*/
}
if (b_rinex_header_written) // The header is already written, we can now log the navigation message data
{
@ -1183,11 +1259,17 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
{
rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_cnav_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map);
}
/* if (type_of_rx == 32) // GPS L1 C/A only
{
rp->log_rinex_nav(rp->navFile, d_ls_pvt->beidou_ephemeris_map);
}
*/
}
galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.cbegin();
gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.cbegin();
gps_cnav_ephemeris_iter = d_ls_pvt->gps_cnav_ephemeris_map.cbegin();
glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin();
beidou_ephemeris_iter = d_ls_pvt->beidou_ephemeris_map.cbegin();
// Log observables into the RINEX file
if (flag_write_RINEX_obs_output)
@ -1439,6 +1521,21 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
b_rinex_header_updated = true; // do not write header anymore
}
}
/* if (type_of_rx == 32) // Beidou
{
if (beidou_ephemeris_iter != d_ls_pvt->beidou_ephemeris_map.end())
{
rp->log_rinex_obs(rp->obsFile, beidou_ephemeris_iter->second, d_rx_time, gnss_observables_map);
}
if (!b_rinex_header_updated and (d_ls_pvt->beidou_utc_model.d_A0 != 0))
{
rp->update_obs_header(rp->obsFile, d_ls_pvt->beidou_utc_model);
rp->update_nav_header(rp->navFile, d_ls_pvt->beidou_utc_model, d_ls_pvt->beidou_iono);
b_rinex_header_updated = true;
}
}
*/
}
}
@ -2244,8 +2341,8 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
// std::cout << TEXT_MAGENTA << "Observable RX time (GPST) " << boost::posix_time::to_simple_string(p_time) << TEXT_RESET << std::endl;
DLOG(INFO) << "Position at " << boost::posix_time::to_simple_string(d_ls_pvt->get_position_UTC_time())
<< " UTC using " << d_ls_pvt->get_num_valid_observations() << " observations is Lat = " << d_ls_pvt->get_latitude() << " [deg], Long = " << d_ls_pvt->get_longitude()
<< " [deg], Height = " << d_ls_pvt->get_height() << " [m]";
<< " UTC using " << d_ls_pvt->get_num_valid_observations() << " observations is Lat = " << d_ls_pvt->get_latitude() << " [deg], Long = " << d_ls_pvt->get_longitude()
<< " [deg], Height = " << d_ls_pvt->get_height() << " [m]";
/* std::cout << "Dilution of Precision at " << boost::posix_time::to_simple_string(d_ls_pvt->get_position_UTC_time())
<< " UTC using "<< d_ls_pvt->get_num_valid_observations() <<" observations is HDOP = " << d_ls_pvt->get_hdop() << " VDOP = "

View File

@ -57,6 +57,7 @@
#include "Galileo_E1.h"
#include "GLONASS_L1_L2_CA.h"
#include <glog/logging.h>
#include "../../../core/system_parameters/Beidou_B1I.h"
using google::LogMessage;
@ -140,6 +141,8 @@ bool rtklib_solver::get_PVT(const std::map<int, Gnss_Synchro>& gnss_observables_
std::map<int, Gps_Ephemeris>::const_iterator gps_ephemeris_iter;
std::map<int, Gps_CNAV_Ephemeris>::const_iterator gps_cnav_ephemeris_iter;
std::map<int, Glonass_Gnav_Ephemeris>::const_iterator glonass_gnav_ephemeris_iter;
std::map<int, Beidou_Ephemeris>::const_iterator beidou_ephemeris_iter;
const Glonass_Gnav_Utc_Model gnav_utc = this->glonass_gnav_utc_model;
this->set_averaging_flag(flag_averaging);
@ -449,6 +452,34 @@ bool rtklib_solver::get_PVT(const std::map<int, Gnss_Synchro>& gnss_observables_
}
break;
}
case 'C':
{
// BEIDOU B1I
// - find the ephemeris for the current BEIDOU SV observation. The SV PRN ID is the map key
std::string sig_(gnss_observables_iter->second.Signal);
if (sig_.compare("B1") == 0)
{
beidou_ephemeris_iter = beidou_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (beidou_ephemeris_iter != beidou_ephemeris_map.cend())
{
// convert ephemeris from GNSS-SDR class to RTKLIB structure
eph_data[valid_obs] = eph_to_rtklib(beidou_ephemeris_iter->second);
// convert observation from GNSS-SDR class to RTKLIB structure
obsd_t newobs = {{0, 0}, '0', '0', {}, {}, {}, {}, {}, {}};
obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second,
beidou_ephemeris_iter->second.i_BEIDOU_week,
0);
valid_obs++;
}
else // the ephemeris are not available for this SV
{
DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->first;
}
}
break;
}
default:
DLOG(INFO) << "Hybrid observables: Unknown GNSS";
break;

View File

@ -65,6 +65,7 @@
#include <fstream>
#include <map>
#include <string>
#include "../../../core/system_parameters/beidou_dnav_navigation_message.h"
/*!
@ -96,6 +97,7 @@ public:
std::map<int, Gps_Ephemeris> gps_ephemeris_map; //!< Map storing new GPS_Ephemeris
std::map<int, Gps_CNAV_Ephemeris> gps_cnav_ephemeris_map; //!< Map storing new GPS_CNAV_Ephemeris
std::map<int, Glonass_Gnav_Ephemeris> glonass_gnav_ephemeris_map; //!< Map storing new GLONASS GNAV Ephmeris
std::map<int, Beidou_Ephemeris> beidou_ephemeris_map; //!< Map storing new GLONASS GNAV Ephmeris
Galileo_Utc_Model galileo_utc_model;
Galileo_Iono galileo_iono;
@ -110,6 +112,10 @@ public:
Glonass_Gnav_Utc_Model glonass_gnav_utc_model; //!< Map storing GLONASS GNAV UTC Model
Glonass_Gnav_Almanac glonass_gnav_almanac; //!< Map storing GLONASS GNAV Almanac Model
Beidou_Utc_Model beidou_utc_model;
Beidou_Iono beidou_iono;
Beidou_Almanac beidou_almanac;
int count_valid_position;
};

View File

@ -34,6 +34,7 @@ set(ACQ_ADAPTER_SOURCES
galileo_e5a_pcps_acquisition.cc
glonass_l1_ca_pcps_acquisition.cc
glonass_l2_ca_pcps_acquisition.cc
beidou_b1i_pcps_acquisition.cc
)
set(ACQ_ADAPTER_HEADERS

View File

@ -0,0 +1,329 @@
/*!
* \file beidou_b1i_pcps_acquisition.cc
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* BeiDou B1I signals
* \authors <ul>
* <li> Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "beidou_b1i_pcps_acquisition.h"
#include "configuration_interface.h"
#include "beidou_b1I_signal_processing.h"
#include "gnss_sdr_flags.h"
#include "acq_conf.h"
#include <boost/math/distributions/exponential.hpp>
#include <glog/logging.h>
#include "Beidou_B1I.h"
using google::LogMessage;
BeidouB1iPcpsAcquisition::BeidouB1iPcpsAcquisition(
ConfigurationInterface* configuration, std::string role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
Acq_Conf acq_parameters = Acq_Conf();
configuration_ = configuration;
std::string default_item_type = "gr_complex";
std::string default_dump_filename = "./data/acquisition.dat";
DLOG(INFO) << "role " << role;
item_type_ = configuration_->property(role + ".item_type", default_item_type);
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in_;
dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_;
blocking_ = configuration_->property(role + ".blocking", true);
acq_parameters.blocking = blocking_;
doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
acq_parameters.doppler_max = doppler_max_;
sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1);
acq_parameters.sampled_ms = sampled_ms_;
bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
acq_parameters.bit_transition_flag = bit_transition_flag_;
use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions
acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_;
max_dwells_ = configuration_->property(role + ".max_dwells", 1);
acq_parameters.max_dwells = max_dwells_;
dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
acq_parameters.dump_filename = dump_filename_;
//--- Find number of samples per spreading code -------------------------
code_length_ = static_cast<unsigned int>(std::round(static_cast<double>(fs_in_) / ( BEIDOU_B1I_CODE_RATE_HZ / BEIDOU_B1I_CODE_LENGTH_CHIPS)));
vector_length_ = code_length_ * sampled_ms_;
if (bit_transition_flag_)
{
vector_length_ *= 2;
}
code_ = new gr_complex[vector_length_];
if (item_type_.compare("cshort") == 0)
{
item_size_ = sizeof(lv_16sc_t);
}
else
{
item_size_ = sizeof(gr_complex);
}
acq_parameters.it_size = item_size_;
acq_parameters.sampled_ms = sampled_ms_;
acq_parameters.samples_per_ms = code_length_;
acq_parameters.samples_per_code = code_length_;
acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4);
acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);
acquisition_ = pcps_make_acquisition(acq_parameters);
DLOG(INFO) << "acquisition(" << acquisition_->unique_id() << ")";
stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_);
DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")";
if (item_type_.compare("cbyte") == 0)
{
cbyte_to_float_x2_ = make_complex_byte_to_float_x2();
float_to_complex_ = gr::blocks::float_to_complex::make();
}
channel_ = 0;
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = 0;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";
}
if (out_streams_ > 0)
{
LOG(ERROR) << "This implementation does not provide an output stream";
}
}
BeidouB1iPcpsAcquisition::~BeidouB1iPcpsAcquisition()
{
delete[] code_;
}
void BeidouB1iPcpsAcquisition::set_channel(unsigned int channel)
{
channel_ = channel;
acquisition_->set_channel(channel_);
}
void BeidouB1iPcpsAcquisition::set_threshold(float threshold)
{
float pfa = configuration_->property(role_ + ".pfa", 0.0);
if (pfa == 0.0)
{
threshold_ = threshold;
}
else
{
threshold_ = calculate_threshold(pfa);
}
DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_;
acquisition_->set_threshold(threshold_);
}
void BeidouB1iPcpsAcquisition::set_doppler_max(unsigned int doppler_max)
{
doppler_max_ = doppler_max;
acquisition_->set_doppler_max(doppler_max_);
}
void BeidouB1iPcpsAcquisition::set_doppler_step(unsigned int doppler_step)
{
doppler_step_ = doppler_step;
acquisition_->set_doppler_step(doppler_step_);
}
void BeidouB1iPcpsAcquisition::set_gnss_synchro(Gnss_Synchro* gnss_synchro)
{
gnss_synchro_ = gnss_synchro;
acquisition_->set_gnss_synchro(gnss_synchro_);
}
signed int BeidouB1iPcpsAcquisition::mag()
{
return acquisition_->mag();
}
void BeidouB1iPcpsAcquisition::init()
{
acquisition_->init();
set_local_code();
}
void BeidouB1iPcpsAcquisition::set_local_code()
{
std::complex<float>* code = new std::complex<float>[code_length_];
beidou_b1i_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_, 0);
for (unsigned int i = 0; i < sampled_ms_; i++)
{
memcpy(&(code_[i * code_length_]), code,
sizeof(gr_complex) * code_length_);
}
acquisition_->set_local_code(code_);
delete[] code;
}
void BeidouB1iPcpsAcquisition::reset()
{
acquisition_->set_active(true);
}
void BeidouB1iPcpsAcquisition::set_state(int state)
{
acquisition_->set_state(state);
}
float BeidouB1iPcpsAcquisition::calculate_threshold(float pfa)
{
//Calculate the threshold
unsigned int frequency_bins = 0;
/*
for (int doppler = (int)(-doppler_max_); doppler <= (int)doppler_max_; doppler += doppler_step_)
{
frequency_bins++;
}
*/
frequency_bins = (2 * doppler_max_ + doppler_step_) / doppler_step_;
DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa;
unsigned int ncells = vector_length_ * frequency_bins;
double exponent = 1 / static_cast<double>(ncells);
double val = pow(1.0 - pfa, exponent);
double lambda = static_cast<double>(vector_length_);
boost::math::exponential_distribution<double> mydist(lambda);
float threshold = static_cast<float>(quantile(mydist, val));
return threshold;
}
void BeidouB1iPcpsAcquisition::connect(gr::top_block_sptr top_block)
{
if (item_type_.compare("gr_complex") == 0)
{
// nothing to connect
}
else if (item_type_.compare("cshort") == 0)
{
// nothing to connect
}
else if (item_type_.compare("cbyte") == 0)
{
top_block->connect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
top_block->connect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
top_block->connect(float_to_complex_, 0, stream_to_vector_, 0);
}
else
{
LOG(WARNING) << item_type_ << " unknown acquisition item type";
}
}
void BeidouB1iPcpsAcquisition::disconnect(gr::top_block_sptr top_block)
{
if (item_type_.compare("gr_complex") == 0)
{
// nothing to disconnect
}
else if (item_type_.compare("cshort") == 0)
{
// nothing to disconnect
}
else if (item_type_.compare("cbyte") == 0)
{
// Since a byte-based acq implementation is not available,
// we just convert cshorts to gr_complex
top_block->disconnect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
top_block->disconnect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
top_block->disconnect(float_to_complex_, 0, stream_to_vector_, 0);
}
else
{
LOG(WARNING) << item_type_ << " unknown acquisition item type";
}
}
gr::basic_block_sptr BeidouB1iPcpsAcquisition::get_left_block()
{
if (item_type_.compare("gr_complex") == 0)
{
return acquisition_;
}
else if (item_type_.compare("cshort") == 0)
{
return acquisition_;
}
else if (item_type_.compare("cbyte") == 0)
{
return cbyte_to_float_x2_;
}
else
{
LOG(WARNING) << item_type_ << " unknown acquisition item type";
return nullptr;
}
}
gr::basic_block_sptr BeidouB1iPcpsAcquisition::get_right_block()
{
return acquisition_;
}

View File

@ -0,0 +1,168 @@
/*!
* \file beidou_bi1_pcps_acquisition.h
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* Beidou B1I signals
* \authors <ul>
* <li> Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_B1I_PCPS_ACQUISITION_H_
#define GNSS_SDR_BEIDOU_B1I_PCPS_ACQUISITION_H_
#include "acquisition_interface.h"
#include "gnss_synchro.h"
#include "pcps_acquisition.h"
#include "complex_byte_to_float_x2.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <gnuradio/blocks/float_to_complex.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <string>
class ConfigurationInterface;
/*!
* \brief This class adapts a PCPS acquisition block to an AcquisitionInterface
* for GPS L1 C/A signals
*/
class BeidouB1iPcpsAcquisition : public AcquisitionInterface
{
public:
BeidouB1iPcpsAcquisition(ConfigurationInterface* configuration,
std::string role, unsigned int in_streams,
unsigned int out_streams);
virtual ~BeidouB1iPcpsAcquisition();
inline std::string role() override
{
return role_;
}
/*!
* \brief Returns "BEIDOU_B1I_PCPS_Acquisition"
*/
inline std::string implementation() override
{
return "BEIDOU_B1I_PCPS_Acquisition";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and
* tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
/*!
* \brief Set acquisition channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set statistics threshold of PCPS algorithm
*/
void set_threshold(float threshold) override;
/*!
* \brief Set maximum Doppler off grid search
*/
void set_doppler_max(unsigned int doppler_max) override;
/*!
* \brief Set Doppler steps for the grid search
*/
void set_doppler_step(unsigned int doppler_step) override;
/*!
* \brief Initializes acquisition algorithm.
*/
void init() override;
/*!
* \brief Sets local code for GPS L1/CA PCPS acquisition algorithm.
*/
void set_local_code() override;
/*!
* \brief Returns the maximum peak of grid search
*/
signed int mag() override;
/*!
* \brief Restart acquisition algorithm
*/
void reset() override;
/*!
* \brief If state = 1, it forces the block to start acquiring from the first sample
*/
void set_state(int state);
private:
ConfigurationInterface* configuration_;
pcps_acquisition_sptr acquisition_;
gr::blocks::stream_to_vector::sptr stream_to_vector_;
gr::blocks::float_to_complex::sptr float_to_complex_;
complex_byte_to_float_x2_sptr cbyte_to_float_x2_;
size_t item_size_;
std::string item_type_;
unsigned int vector_length_;
unsigned int code_length_;
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
unsigned int channel_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;
unsigned int sampled_ms_;
unsigned int max_dwells_;
long fs_in_;
bool dump_;
bool blocking_;
std::string dump_filename_;
std::complex<float>* code_;
Gnss_Synchro* gnss_synchro_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
float calculate_threshold(float pfa);
};
#endif /* GNSS_SDR_BEIDOU_B1I_PCPS_ACQUISITION_H_ */

View File

@ -18,7 +18,7 @@
add_subdirectory(rtklib)
set(GNSS_SPLIBS_SOURCES
set(GNSS_SPLIBS_SOURCES
gps_l2c_signal.cc
gps_l5_signal.cc
galileo_e1_signal_processing.cc
@ -30,6 +30,7 @@ set(GNSS_SPLIBS_SOURCES
glonass_l2_signal_processing.cc
pass_through.cc
galileo_e5_signal_processing.cc
beidou_b1I_signal_processing.cc
complex_byte_to_float_x2.cc
byte_x2_to_complex_byte.cc
cshort_to_float_x2.cc
@ -38,7 +39,7 @@ set(GNSS_SPLIBS_SOURCES
conjugate_cc.cc
conjugate_sc.cc
conjugate_ic.cc
)
)
set(GNSS_SPLIBS_HEADERS
gps_l2c_signal.h
@ -52,6 +53,7 @@ set(GNSS_SPLIBS_HEADERS
glonass_l2_signal_processing.h
pass_through.h
galileo_e5_signal_processing.h
beidou_b1I_signal_processing.h
complex_byte_to_float_x2.h
byte_x2_to_complex_byte.h
cshort_to_float_x2.h
@ -61,7 +63,7 @@ set(GNSS_SPLIBS_HEADERS
conjugate_sc.h
conjugate_ic.h
gnss_circular_deque.h
)
)
if(ENABLE_FPGA)
@ -82,7 +84,7 @@ if(OPENCL_FOUND)
opencl/fft_execute.cc # Needs OpenCL
opencl/fft_setup.cc # Needs OpenCL
opencl/fft_kernelstring.cc # Needs OpenCL
)
)
set(GNSS_SPLIBS_HEADERS ${GNSS_SPLIBS_HEADERS}
opencl/fft_execute.h # Needs OpenCL

View File

@ -0,0 +1,189 @@
/*!
* \file beidou_b1I_signal_processing.cc
* \brief This class implements various functions for BeiDou B1I signal
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* Detailed description of the file here if needed.
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "beidou_b1I_signal_processing.h"
auto auxCeil = [](float x) { return static_cast<int>(static_cast<long>((x) + 1)); };
void beidou_b1i_code_gen_int(int* _dest, signed int _prn, unsigned int _chip_shift)
{
const unsigned int _code_length = 2046;
bool G1[_code_length];
bool G2[_code_length];
bool G1_register[11] = {0,1,0,1,0,1,0,1,0,1,0};
bool G2_register[11] = {0,1,0,1,0,1,0,1,0,1,0};
bool feedback1, feedback2;
bool aux;
unsigned int lcv, lcv2;
unsigned int delay;
signed int prn_idx;
/* G2 Delays as defined in GPS-ISD-200D */
const signed int delays[33] = {712 /*PRN1*/, 1581, 1414, 1550, 581, 771, 1311, 1043, 1549, 359, 710, 1579, 1548, 1103, 579, 769, 358, 709, 1411, 1547,
1102, 578, 357, 1577, 1410, 1546, 1101, 707, 1576, 1409, 1545, 354 /*PRN32*/,
705};
const signed int phase1[37] = {1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 8, 8, 8, 9, 9, 10};
const signed int phase2[37] = {3, 4, 5, 6, 8, 9, 10, 11, 7, 4, 5, 6, 8, 9, 10, 11, 5, 6, 8, 9, 10, 11, 6, 8, 9, 10, 11, 8, 9, 10, 11, 9, 10, 11, 10, 11, 11};
// compute delay array index for given PRN number
prn_idx = _prn - 1;
/* A simple error check */
if ((prn_idx < 0) || (prn_idx > 51))
return;
/*for (lcv = 0; lcv < 11; lcv++)
{
G1_register[lcv] = 1;
G2_register[lcv] = 1;
}*/
/* Generate G1 & G2 Register */
for (lcv = 0; lcv < _code_length; lcv++)
{
G1[lcv] = G1_register[0];
G2[lcv] = G2_register[-(phase1[prn_idx] - 11) ] ^ G2_register[-(phase2[prn_idx] - 11) ];
feedback1 = (G1_register[0] + G1_register[1] + G1_register[2] + G1_register[3] + G1_register[4] + G1_register[10]) & 0x1;
feedback2 = (G2_register[0] + G2_register[2] + G2_register[3] + G2_register[6] + G2_register[7] + G2_register[8] + G2_register[9] + G2_register[10]) & 0x1;
for (lcv2 = 0; lcv2 < 10; lcv2++)
{
G1_register[lcv2] = G1_register[lcv2 + 1];
G2_register[lcv2] = G2_register[lcv2 + 1];
}
G1_register[10] = feedback1;
G2_register[10] = feedback2;
}
/* Set the delay */
delay = _code_length - delays[prn_idx]*0; //**********************************
delay += _chip_shift;
delay %= _code_length;
/* Generate PRN from G1 and G2 Registers */
for (lcv = 0; lcv < _code_length; lcv++)
{
aux = G1[(lcv + _chip_shift) % _code_length] ^ G2[delay];
if (aux == true)
{
_dest[lcv] = 1;
}
else
{
_dest[lcv] = -1;
}
delay++;
//std::cout << _dest[lcv] << " ";
delay %= _code_length;
}
}
void beidou_b1i_code_gen_float(float* _dest, signed int _prn, unsigned int _chip_shift)
{
unsigned int _code_length = 2046;
int b1i_code_int[_code_length];
beidou_b1i_code_gen_int(b1i_code_int, _prn, _chip_shift);
for (unsigned int ii = 0; ii < _code_length; ++ii)
{
_dest[ii] = static_cast<float>(b1i_code_int[ii]);
}
}
void beidou_b1i_code_gen_complex(std::complex<float>* _dest, signed int _prn, unsigned int _chip_shift)
{
unsigned int _code_length = 2046;
int b1i_code_int[_code_length];
beidou_b1i_code_gen_int(b1i_code_int, _prn, _chip_shift);
for (unsigned int ii = 0; ii < _code_length; ++ii)
{
_dest[ii] = std::complex<float>(static_cast<float>(b1i_code_int[ii]), 0.0f);
}
}
/*
* Generates complex GPS L1 C/A code for the desired SV ID and sampled to specific sampling frequency
*/
void beidou_b1i_code_gen_complex_sampled(std::complex<float>* _dest, unsigned int _prn, int _fs, unsigned int _chip_shift)
{
// This function is based on the GNU software GPS for MATLAB in the Kay Borre book
std::complex<float> _code[2046];
signed int _samplesPerCode, _codeValueIndex;
float _ts;
float _tc;
float aux;
const signed int _codeFreqBasis = 2046000; //Hz
const signed int _codeLength = 2046;
//--- Find number of samples per spreading code ----------------------------
_samplesPerCode = static_cast<signed int>(static_cast<double>(_fs) / static_cast<double>(_codeFreqBasis / _codeLength));
//--- Find time constants --------------------------------------------------
_ts = 1.0 / static_cast<float>(_fs); // Sampling period in sec
_tc = 1.0 / static_cast<float>(_codeFreqBasis); // C/A chip period in sec
beidou_b1i_code_gen_complex(_code, _prn, _chip_shift); //generate C/A code 1 sample per chip
for (signed int i = 0; i < _samplesPerCode; i++)
{
//=== Digitizing =======================================================
//--- Make index array to read C/A code values -------------------------
// The length of the index array depends on the sampling frequency -
// number of samples per millisecond (because one C/A code period is one
// millisecond).
// _codeValueIndex = ceil((_ts * ((float)i + 1)) / _tc) - 1;
aux = (_ts * (i + 1)) / _tc;
_codeValueIndex = auxCeil(aux) - 1;
//--- Make the digitized version of the C/A code -----------------------
// The "upsampled" code is made by selecting values form the CA code
// chip array (caCode) for the time instances of each sample.
if (i == _samplesPerCode - 1)
{
//--- Correct the last index (due to number rounding issues) -----------
_dest[i] = _code[_codeLength - 1];
}
else
{
_dest[i] = _code[_codeValueIndex]; //repeat the chip -> upsample
}
}
}

View File

@ -0,0 +1,54 @@
/*!
* \file beidou_b1I_signal_processing.h
* \brief This class implements various functions for BeiDou B1I signals
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* Detailed description of the file here if needed.
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef BEIDOU_B1I_SDR_SIGNAL_PROCESSING_H_
#define BEIDOU_B1I_SDR_SIGNAL_PROCESSING_H_
#include <complex>
#include <iostream>
//!Generates int GPS L1 C/A code for the desired SV ID and code shift
void beidou_b1i_code_gen_int(int* _dest, signed int _prn, unsigned int _chip_shift);
//!Generates float GPS L1 C/A code for the desired SV ID and code shift
void beidou_b1i_code_gen_float(float* _dest, signed int _prn, unsigned int _chip_shift);
//!Generates complex GPS L1 C/A code for the desired SV ID and code shift, and sampled to specific sampling frequency
void beidou_b1i_code_gen_complex(std::complex<float>* _dest, signed int _prn, unsigned int _chip_shift);
//! Generates N complex GPS L1 C/A codes for the desired SV ID and code shift
void beidou_b1i_code_gen_complex_sampled(std::complex<float>* _dest, unsigned int _prn, int _fs, unsigned int _chip_shift, unsigned int _ncodes);
//! Generates complex GPS L1 C/A code for the desired SV ID and code shift
void beidou_b1i_code_gen_complex_sampled(std::complex<float>* _dest, unsigned int _prn, int _fs, unsigned int _chip_shift);
#endif /* BEIDOU_B1I_SDR_SIGNAL_PROCESSING_H_ */

View File

@ -112,10 +112,12 @@ Pass_Through::Pass_Through(ConfigurationInterface* configuration, std::string ro
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";
LOG(ERROR) << in_streams_;
}
if (out_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one output stream";
LOG(ERROR) << out_streams_;
}
}

View File

@ -65,6 +65,9 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro
case 'R':
rtklib_obs.sat = gnss_synchro.PRN + NSATGPS;
break;
case 'C':
rtklib_obs.sat = gnss_synchro.PRN + NSATGPS + NSATGLO + NSATGAL;
break;
default:
rtklib_obs.sat = gnss_synchro.PRN;
@ -227,6 +230,62 @@ eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph)
return rtklib_sat;
}
eph_t eph_to_rtklib(const Beidou_Ephemeris& bei_eph)
{
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0 };
rtklib_sat.sat = bei_eph.i_satellite_PRN;
rtklib_sat.A = bei_eph.d_sqrt_A * bei_eph.d_sqrt_A;
rtklib_sat.M0 = bei_eph.d_M_0;
rtklib_sat.deln = bei_eph.d_Delta_n;
rtklib_sat.OMG0 = bei_eph.d_OMEGA0;
rtklib_sat.OMGd = bei_eph.d_OMEGA_DOT;
rtklib_sat.omg = bei_eph.d_OMEGA;
rtklib_sat.i0 = bei_eph.d_i_0;
rtklib_sat.idot = bei_eph.d_IDOT;
rtklib_sat.e = bei_eph.d_e_eccentricity;
rtklib_sat.Adot = 0; //only in CNAV;
rtklib_sat.ndot = 0; //only in CNAV;
rtklib_sat.week = adjgpsweek(bei_eph.i_BEIDOU_week); /* week of tow */
rtklib_sat.cic = bei_eph.d_Cic;
rtklib_sat.cis = bei_eph.d_Cis;
rtklib_sat.cuc = bei_eph.d_Cuc;
rtklib_sat.cus = bei_eph.d_Cus;
rtklib_sat.crc = bei_eph.d_Crc;
rtklib_sat.crs = bei_eph.d_Crs;
rtklib_sat.f0 = bei_eph.d_A_f0;
rtklib_sat.f1 = bei_eph.d_A_f1;
rtklib_sat.f2 = bei_eph.d_A_f2;
rtklib_sat.tgd[0] = bei_eph.d_TGD1;
rtklib_sat.tgd[1] = 0.0;
rtklib_sat.tgd[2] = 0.0;
rtklib_sat.tgd[3] = 0.0;
rtklib_sat.toes = bei_eph.d_Toe;
rtklib_sat.toc = gpst2time(rtklib_sat.week, bei_eph.d_Toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, bei_eph.d_TOW);
/* adjustment for week handover */
double tow, toc;
tow = time2gpst(rtklib_sat.ttr, &rtklib_sat.week);
toc = time2gpst(rtklib_sat.toc, NULL);
if (rtklib_sat.toes < tow - 302400.0)
{
rtklib_sat.week++;
tow -= 604800.0;
}
else if (rtklib_sat.toes > tow + 302400.0)
{
rtklib_sat.week--;
tow += 604800.0;
}
rtklib_sat.toe = gpst2time(rtklib_sat.week, rtklib_sat.toes);
rtklib_sat.toc = gpst2time(rtklib_sat.week, toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow);
return rtklib_sat;
}
eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris& gps_cnav_eph)
{

View File

@ -31,6 +31,7 @@
#ifndef GNSS_SDR_RTKLIB_CONVERSIONS_H_
#define GNSS_SDR_RTKLIB_CONVERSIONS_H_
#include "../../../core/system_parameters/beidou_dnav_ephemeris.h"
#include "rtklib.h"
#include "gnss_synchro.h"
#include "galileo_ephemeris.h"
@ -42,6 +43,8 @@
eph_t eph_to_rtklib(const Galileo_Ephemeris& gal_eph);
eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph);
eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris& gps_cnav_eph);
eph_t eph_to_rtklib(const Beidou_Ephemeris& bei_eph);
/*!
* \brief Transforms a Glonass_Gnav_Ephemeris to its RTKLIB counterpart
* \param glonass_gnav_eph GLONASS GNAV Ephemeris structure

View File

@ -37,6 +37,7 @@
#include "Galileo_E5a.h"
#include "GLONASS_L1_L2_CA.h"
#include <glog/logging.h>
#include "../../../core/system_parameters/Beidou_B1I.h"
using google::LogMessage;
@ -110,6 +111,12 @@ SignalGenerator::SignalGenerator(ConfigurationInterface* configuration,
}
}
else if (std::find(system.begin(), system.end(), "B") != system.end())
{
vector_length = round(static_cast<float>(fs_in) / (BEIDOU_B1I_CODE_RATE_HZ / BEIDOU_B1I_CODE_LENGTH_CHIPS));
}
if (item_type_.compare("gr_complex") == 0)
{
item_size_ = sizeof(gr_complex);

View File

@ -25,7 +25,8 @@ set(TELEMETRY_DECODER_ADAPTER_SOURCES
sbas_l1_telemetry_decoder.cc
galileo_e5a_telemetry_decoder.cc
glonass_l1_ca_telemetry_decoder.cc
glonass_l2_ca_telemetry_decoder.cc
glonass_l2_ca_telemetry_decoder.cc
beidou_b1i_telemetry_decoder.cc
)
set(TELEMETRY_DECODER_ADAPTER_HEADERS

View File

@ -0,0 +1,112 @@
/*!
* \file beidou_b1i_telemetry_decoder.cc
* \brief Implementation of an adapter of a Beidou B1I NAV data decoder block
* to a TelemetryDecoderInterface
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#include "beidou_b1i_telemetry_decoder.h"
#include "configuration_interface.h"
#include <gnuradio/io_signature.h>
#include <glog/logging.h>
#include "../../../core/system_parameters/beidou_dnav_almanac.h"
#include "../../../core/system_parameters/beidou_dnav_ephemeris.h"
#include "../../../core/system_parameters/beidou_dnav_iono.h"
#include "../../../core/system_parameters/beidou_dnav_utc_model.h"
using google::LogMessage;
BeidouB1iTelemetryDecoder::BeidouB1iTelemetryDecoder(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams) : role_(role),
in_streams_(in_streams),
out_streams_(out_streams)
{
std::string default_dump_filename = "./navigation.dat";
DLOG(INFO) << "role " << role;
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
// make telemetry decoder object
telemetry_decoder_ = beidou_b1i_make_telemetry_decoder_cc(satellite_, dump_); // TODO fix me
DLOG(INFO) << "telemetry_decoder(" << telemetry_decoder_->unique_id() << ")";
channel_ = 0;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";
}
if (out_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one output stream";
}
}
BeidouB1iTelemetryDecoder::~BeidouB1iTelemetryDecoder()
{
}
void BeidouB1iTelemetryDecoder::set_satellite(const Gnss_Satellite& satellite)
{
satellite_ = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
telemetry_decoder_->set_satellite(satellite_);
DLOG(INFO) << "TELEMETRY DECODER: satellite set to " << satellite_;
}
void BeidouB1iTelemetryDecoder::connect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
// Nothing to connect internally
DLOG(INFO) << "nothing to connect internally";
}
void BeidouB1iTelemetryDecoder::disconnect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
// Nothing to disconnect
}
gr::basic_block_sptr BeidouB1iTelemetryDecoder::get_left_block()
{
return telemetry_decoder_;
}
gr::basic_block_sptr BeidouB1iTelemetryDecoder::get_right_block()
{
return telemetry_decoder_;
}

View File

@ -0,0 +1,95 @@
/*!
* \file beidou_b1i_telemetry_decoder.h
* \brief Interface of an adapter of a Beidou B1I NAV data decoder block
* to a TelemetryDecoderInterface
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_B1I_TELEMETRY_DECODER_H_
#define GNSS_SDR_BEIDOU_B1I_TELEMETRY_DECODER_H_
#include "beidou_b1i_telemetry_decoder_cc.h"
#include "telemetry_decoder_interface.h"
#include <string>
class ConfigurationInterface;
/*!
* \brief This class implements a NAV data decoder for GPS L1 C/A
*/
class BeidouB1iTelemetryDecoder : public TelemetryDecoderInterface
{
public:
BeidouB1iTelemetryDecoder(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~BeidouB1iTelemetryDecoder();
inline std::string role() override
{
return role_;
}
//! Returns "GPS_L1_CA_Telemetry_Decoder"
inline std::string implementation() override
{
return "BEIDOU_B1I_Telemetry_Decoder";
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
void set_satellite(const Gnss_Satellite& satellite) override;
inline void set_channel(int channel) override { telemetry_decoder_->set_channel(channel); }
inline void reset() override
{
return;
}
inline size_t item_size() override
{
return 0;
}
private:
beidou_b1i_telemetry_decoder_cc_sptr telemetry_decoder_;
Gnss_Satellite satellite_;
int channel_;
bool dump_;
std::string dump_filename_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
};
#endif

View File

@ -24,6 +24,7 @@ set(TELEMETRY_DECODER_GR_BLOCKS_SOURCES
glonass_l1_ca_telemetry_decoder_cc.cc
glonass_l2_ca_telemetry_decoder_cc.cc
galileo_telemetry_decoder_cc.cc
beidou_b1i_telemetry_decoder_cc.cc
)
set(TELEMETRY_DECODER_GR_BLOCKS_HEADERS
@ -34,6 +35,7 @@ set(TELEMETRY_DECODER_GR_BLOCKS_HEADERS
glonass_l1_ca_telemetry_decoder_cc.h
glonass_l2_ca_telemetry_decoder_cc.h
galileo_telemetry_decoder_cc.h
beidou_b1i_telemetry_decoder_cc.h
)
include_directories(

View File

@ -0,0 +1,543 @@
/*!
* \file beidou_b1i_telemetry_decoder_cc.cc
* \brief Implementation of a NAV message demodulator block based on
* Kay Borre book MATLAB-based GPS receiver
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.es
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#include "beidou_b1i_telemetry_decoder_cc.h"
#include "control_message_factory.h"
#include <boost/lexical_cast.hpp>
#include <glog/logging.h>
#include <gnuradio/io_signature.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
using google::LogMessage;
beidou_b1i_telemetry_decoder_cc_sptr
beidou_b1i_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump)
{
return beidou_b1i_telemetry_decoder_cc_sptr(new beidou_b1i_telemetry_decoder_cc(satellite, dump));
}
beidou_b1i_telemetry_decoder_cc::beidou_b1i_telemetry_decoder_cc(
const Gnss_Satellite &satellite,
bool dump) : gr::block("beidou_navigation_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)),
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
{
// Ephemeris data port out
this->message_port_register_out(pmt::mp("telemetry"));
// initialize internal vars
d_dump = dump;
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
// set the preamble
unsigned short int preambles_bits[BEIDOU_B1I_PREAMBLE_LENGTH_BITS] = BEIDOU_PREAMBLE;
// preamble bits to sampled symbols
d_preambles_symbols = static_cast<int *>(volk_gnsssdr_malloc(BEIDOU_B1I_PREAMBLE_LENGTH_SYMBOLS * sizeof(int), volk_gnsssdr_get_alignment()));
int n = 0;
for (int i = 0; i < BEIDOU_B1I_PREAMBLE_LENGTH_BITS; i++)
{
if (preambles_bits[i] == 1)
{
d_preambles_symbols[n] = 1;
}
else
{
d_preambles_symbols[n] = -1;
}
n++;
}
d_stat = 0;
d_symbol_accumulator = 0;
d_symbol_accumulator_counter = 0;
d_frame_bit_index = 0;
d_flag_frame_sync = false;
d_BEIDOU_frame_4bytes = 0;
d_prev_BEIDOU_frame_4bytes = 0;
d_flag_parity = false;
d_TOW_at_Preamble_ms = 0;
flag_TOW_set = false;
d_flag_preamble = false;
d_flag_new_tow_available = false;
word_number = 0;
d_channel = 0;
flag_PLL_180_deg_phase_locked = false;
d_preamble_time_samples = 0;
d_TOW_at_current_symbol_ms = 0;
d_symbol_history.resize(BEIDOU_B1I_PREAMBLE_LENGTH_BITS); // Change fixed buffer size
d_symbol_nh_history.resize(BEIDOU_B1I_NH_CODE_LENGTH); // Change fixed buffer size
d_bit_buffer.resize(30); // Change fixed buffer size
d_symbol_history.clear(); // Clear all the elements in the buffer
d_symbol_nh_history.clear();
d_bit_buffer.clear();
d_make_correlation = true;
d_symbol_counter_corr = 0;
for (int aux = 0; aux < BEIDOU_B1I_NH_CODE_LENGTH; aux++)
{
if (BEIDOU_B1I_NH_CODE[aux] == 0)
{
bits_NH[aux] = -1.0;
}
else
{
bits_NH[aux] = 1.0;
}
}
sync_NH = false;
new_sym = false;
}
beidou_b1i_telemetry_decoder_cc::~beidou_b1i_telemetry_decoder_cc()
{
volk_gnsssdr_free(d_preambles_symbols);
if (d_dump_file.is_open() == true)
{
try
{
d_dump_file.close();
}
catch (const std::exception &ex)
{
LOG(WARNING) << "Exception in destructor closing the dump file " << ex.what();
}
}
}
void beidou_b1i_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satellite)
{
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite;
d_BEIDOU_FSM.i_satellite_PRN = d_satellite.get_PRN();
DLOG(INFO) << "Navigation Satellite set to " << d_satellite;
}
void beidou_b1i_telemetry_decoder_cc::set_channel(int channel)
{
d_channel = channel;
d_BEIDOU_FSM.i_channel_ID = channel;
DLOG(INFO) << "Navigation channel set to " << channel;
// ############# ENABLE DATA FILE LOG #################
if (d_dump == true)
{
if (d_dump_file.is_open() == false)
{
try
{
d_dump_filename = "telemetry";
d_dump_filename.append(boost::lexical_cast<std::string>(d_channel));
d_dump_filename.append(".dat");
d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
LOG(INFO) << "Telemetry decoder dump enabled on channel " << d_channel
<< " Log file: " << d_dump_filename.c_str();
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e.what();
}
}
}
}
void beidou_b1i_telemetry_decoder_cc::decodebch_bi1(int *bits, int *decbits)
{
int bit, err, reg[4] = {1, 1, 1, 1};
int errind[15] = {14, 13, 10, 12, 6, 9, 4, 11, 0, 5, 7, 8, 1, 3, 2};
for (unsigned int i = 0; i < 15; i++)
{
decbits[i] = bits[i];
}
for (unsigned int i = 0; i < 15; i++)
{
bit = reg[3];
reg[3] = reg[2];
reg[2] = reg[1];
reg[1] = reg[0];
reg[0] = bits[i] * bit;
reg[1] *= bit;
}
err = errind[reg[0] + reg[1]*2 + reg[2]*4 + reg[3]*8];
if (err > 0)
{
decbits[err - 1] *= -1;
}
}
void beidou_b1i_telemetry_decoder_cc::decode_word(int word_counter, boost::circular_buffer<signed int> *d_bit_buffer, unsigned int& d_BEIDOU_frame_4bytes)
{
d_BEIDOU_frame_4bytes = 0;
int bitsdec[30], bitsbch[30], first_branch[15], second_branch[15];
if (word_counter == 1)
{
for (unsigned int j = 0; j < 30; j++)
{
bitsdec[j] = d_bit_buffer->at(j);
}
}
else
{
for (unsigned int r = 0; r < 2; r++)
{
for (unsigned int c = 0; c < 15; c++)
{
bitsbch[r*15 + c] = d_bit_buffer->at(c*2 + r);
}
}
decodebch_bi1(&bitsbch[0], first_branch);
decodebch_bi1(&bitsbch[15], second_branch);
for (unsigned int j = 0; j < 11; j++)
{
bitsdec[j] = first_branch[j];
bitsdec[j + 11] = second_branch[j];
}
for (unsigned int j = 0; j < 4; j++)
{
bitsdec[j + 22] = first_branch[11 + j];
bitsdec[j + 26] = second_branch[11 + j];
}
}
for (unsigned int k = 0; k < 30 ; k++)
{
if (bitsdec[k] == 1)
{
d_BEIDOU_frame_4bytes++;
}
d_BEIDOU_frame_4bytes <<= 1;
}
d_BEIDOU_frame_4bytes >>= 1;
}
int beidou_b1i_telemetry_decoder_cc::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
int corr_value = 0;
int preamble_diff_ms = 0;
int corr_NH = 0;
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]); // Get the output buffer pointer
const Gnss_Synchro **in = reinterpret_cast<const Gnss_Synchro **>(&input_items[0]); // Get the input buffer pointer
new_sym = false;
Gnss_Synchro current_symbol; //structure to save the synchronization information and send the output object to the next block
//1. Copy the current tracking output
current_symbol = in[0][0];
double current_time_samples = current_symbol.Tracking_sample_counter;
double current_samples_fs = current_symbol.fs;
int symbol_value = 0;
d_symbol_nh_history.push_back(current_symbol.Prompt_I); //add new symbol to the symbol queue
consume_each(1);
if (d_symbol_nh_history.size() == BEIDOU_B1I_NH_CODE_LENGTH)
{
for (int i = 0; i < BEIDOU_B1I_NH_CODE_LENGTH; i++)
{
if ((bits_NH[i] * d_symbol_nh_history.at(i)) > 0.0)
{
corr_NH += 1;
}
else
{
corr_NH -= 1;
}
}
if (abs(corr_NH) == BEIDOU_B1I_NH_CODE_LENGTH)
{
sync_NH = true;
if (corr_NH > 0)
{
symbol_value = 1;
}
else
{
symbol_value = -1;
}
//std::cout << symbol_value << std::endl;
d_symbol_history.push_back(symbol_value);
new_sym = true;
d_symbol_nh_history.clear();
}
else
{
d_symbol_nh_history.pop_front();
sync_NH = false;
new_sym = false;
}
}
if ((d_symbol_history.size() >= BEIDOU_B1I_PREAMBLE_LENGTH_BITS) and (d_make_correlation or !d_flag_frame_sync))
{
//******* preamble correlation ********
for (unsigned int i = 0; i < BEIDOU_B1I_PREAMBLE_LENGTH_BITS; i++)
{
if (d_symbol_history.at(i) < 0) // symbols clipping
{
corr_value -= d_preambles_symbols[i];
}
else
{
corr_value += d_preambles_symbols[i];
}
}
//std::cout << corr_value << std::endl;
if (std::abs(corr_value) >= BEIDOU_B1I_PREAMBLE_LENGTH_BITS)
{
/* for (unsigned int i = 0; i < d_symbol_history.size() ; i++)
{
std::cout << d_symbol_history.at(i);
}
std::cout << std::endl;
*/
// std::cout << "SUCCESSFUL PREAMBLE CORRELATION" << std::endl;
d_symbol_history.clear();
d_symbol_counter_corr++;
}
}
/*if (new_sym and )
{
flag_new_cnav_frame = beidou_nav_msg_decoder_add_symbol(&d_cnav_decoder, symbol_clip, &msg, &delay);
new_sym = false;
}*/
d_flag_preamble = false;
//******* frame sync ******************
if (std::abs(corr_value) == BEIDOU_B1I_PREAMBLE_LENGTH_BITS)
{
// std::cout << "FRAME SYNC" << std::endl;
//TODO: Rewrite with state machine
if (d_stat == 0)
{
// std::cout << "STATE MACHINE" << std::endl;
d_BEIDOU_FSM.Event_beidou_word_preamble();
//record the preamble sample stamp
d_preamble_time_samples = current_time_samples; // record the preamble sample stamp
DLOG(INFO) << "Preamble detection for SAT " << this->d_satellite << "current_time_samples=" << current_time_samples;
//sync the symbol to bits integrator
d_symbol_accumulator = 0;
d_symbol_accumulator_counter = 0;
d_stat = 1; // enter into frame pre-detection status
}
else if (d_stat == 1) //check 6 seconds of preamble separation
{
// std::cout << "6 SECONDS" << std::endl;
preamble_diff_ms = std::round(((static_cast<double>(current_time_samples) - d_preamble_time_samples) / static_cast<double>(current_samples_fs)) * 1000.0);
if (std::abs(preamble_diff_ms - BEIDOU_SUBFRAME_MS) < 1)
{
std::cout << "Preamble confirmation for SAT" << std::endl;
DLOG(INFO) << "Preamble confirmation for SAT " << this->d_satellite;
d_BEIDOU_FSM.Event_beidou_word_preamble();
d_flag_preamble = true;
d_make_correlation = false;
d_symbol_counter_corr = 0;
d_preamble_time_samples = current_time_samples; // record the PRN start sample index associated to the preamble
if (!d_flag_frame_sync)
{
d_flag_frame_sync = true;
if (corr_value < 0)
{
flag_PLL_180_deg_phase_locked = true; // PLL is locked to opposite phase!
DLOG(INFO) << " PLL in opposite phase for Sat " << this->d_satellite.get_PRN();
}
else
{
flag_PLL_180_deg_phase_locked = false;
}
DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at "
<< static_cast<double>(d_preamble_time_samples) / static_cast<double>(current_samples_fs) << " [s]";
}
}
d_frame_bit_index = 10;
d_symbol_history.clear();
for (int i = 0; i < BEIDOU_B1I_PREAMBLE_LENGTH_BITS; i++)
{
d_bit_buffer.push_back(d_preambles_symbols[i]);
}
word_number = 0;
}
}
else
{
d_symbol_counter_corr++;
if (d_symbol_counter_corr > (BEIDOU_SUBFRAME_MS - BEIDOU_B1I_TELEMETRY_SYMBOLS_PER_BIT))
{
d_make_correlation = true;
}
if (d_stat == 1)
{
preamble_diff_ms = round(((static_cast<double>(current_time_samples) - static_cast<double>(d_preamble_time_samples)) / static_cast<double>(current_samples_fs)) * 1000.0);
if (preamble_diff_ms > BEIDOU_SUBFRAME_MS + 1)
{
DLOG(INFO) << "Lost of frame sync SAT " << this->d_satellite << " preamble_diff= " << preamble_diff_ms;
d_stat = 0; //lost of frame sync
d_flag_frame_sync = false;
flag_TOW_set = false;
d_make_correlation = true;
d_symbol_counter_corr = 0;
}
}
}
if (d_flag_frame_sync and new_sym)
{
// std::cout << symbol_value << std::endl;
if (flag_PLL_180_deg_phase_locked)
{
d_bit_buffer.push_back(-symbol_value);
}
else
{
d_bit_buffer.push_back(symbol_value);
}
//******* bits to words ******
d_frame_bit_index++;
if (d_frame_bit_index == 30)
{
word_number++;
beidou_b1i_telemetry_decoder_cc::decode_word(word_number, &d_bit_buffer, d_BEIDOU_frame_4bytes);
// std::cout << d_BEIDOU_frame_4bytes << std::endl;
d_bit_buffer.clear();
d_frame_bit_index = 0;
memcpy(&d_BEIDOU_FSM.d_BEIDOU_frame_4bytes, &d_BEIDOU_frame_4bytes, sizeof(char) * 4);
//d_BEIDOU_FSM.d_preamble_time_ms = d_preamble_time_seconds * 1000.0;
d_BEIDOU_FSM.Event_beidou_word_valid();
// send TLM data to PVT using asynchronous message queues
if (d_BEIDOU_FSM.d_flag_new_subframe == true)
{
/* switch (d_BEIDOU_FSM.d_subframe_ID)
{
case 3: //we have a new set of ephemeris data for the current SV
*/ if (d_BEIDOU_FSM.d_nav.satellite_validation() == true)
{
// get ephemeris object for this SV (mandatory)
std::shared_ptr<Beidou_Ephemeris> tmp_obj = std::make_shared<Beidou_Ephemeris>(d_BEIDOU_FSM.d_nav.get_ephemeris());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
/* break;
case 4: // Possible IONOSPHERE and UTC model update (page 18)
*/ if (d_BEIDOU_FSM.d_nav.flag_iono_valid == true)
{
std::shared_ptr<Beidou_Iono> tmp_obj = std::make_shared<Beidou_Iono>(d_BEIDOU_FSM.d_nav.get_iono());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_BEIDOU_FSM.d_nav.flag_utc_model_valid == true)
{
std::cout << " we have a new set of utc data for the current SV "<< std::endl;
std::shared_ptr<Beidou_Utc_Model> tmp_obj = std::make_shared<Beidou_Utc_Model>(d_BEIDOU_FSM.d_nav.get_utc_model());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
/* break;
case 5:
// get almanac (if available)
//TODO: implement almanac reader in navigation_message
break;
default:
break;
}
*/ d_BEIDOU_FSM.clear_flag_new_subframe();
d_flag_new_tow_available = true;
}
}
}
//2. Add the telemetry decoder information
if (this->d_flag_preamble == true and d_flag_new_tow_available == true)
{
d_TOW_at_current_symbol_ms = static_cast<unsigned int>(d_BEIDOU_FSM.d_nav.d_SOW) * 1000 + 599;
d_TOW_at_Preamble_ms = d_TOW_at_current_symbol_ms;
flag_TOW_set = true;
d_flag_new_tow_available = false;
}
else
{
d_TOW_at_current_symbol_ms += BEIDOU_B1I_CODE_PERIOD_MS;
}
current_symbol.TOW_at_current_symbol_ms = d_TOW_at_current_symbol_ms;
current_symbol.Flag_valid_word = flag_TOW_set;
if (flag_PLL_180_deg_phase_locked == true)
{
//correct the accumulated phase for the Costas loop phase shift, if required
current_symbol.Carrier_phase_rads += BEIDOU_PI;
}
if (d_dump == true)
{
// MULTIPLEXED FILE RECORDING - Record results to file
try
{
double tmp_double;
unsigned long int tmp_ulong_int;
tmp_double = static_cast<double>(d_TOW_at_current_symbol_ms) / 1000.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
tmp_ulong_int = current_symbol.Tracking_sample_counter;
d_dump_file.write(reinterpret_cast<char *>(&tmp_ulong_int), sizeof(unsigned long int));
tmp_double = static_cast<double>(d_TOW_at_Preamble_ms) * 1000.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "Exception writing observables dump file " << e.what();
}
}
//3. Make the output (copy the object contents to the GNURadio reserved memory)
*out[0] = current_symbol;
return 1;
}

View File

@ -0,0 +1,130 @@
/*!
* \file beidou_b1i_telemetry_decoder_cc.h
* \brief Interface of a NAV message demodulator block based on
* Kay Borre book MATLAB-based GPS receiver
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_B1I_TELEMETRY_DECODER_CC_H
#define GNSS_SDR_BEIDOU_B1I_TELEMETRY_DECODER_CC_H
#include "beidou_b1i_subframe_fsm.h"
#include "gnss_satellite.h"
#include "gnss_synchro.h"
#include <gnuradio/block.h>
#include <fstream>
#include <string>
#include <boost/circular_buffer.hpp>
#include "../../../core/system_parameters/Beidou_B1I.h"
class beidou_b1i_telemetry_decoder_cc;
typedef boost::shared_ptr<beidou_b1i_telemetry_decoder_cc> beidou_b1i_telemetry_decoder_cc_sptr;
beidou_b1i_telemetry_decoder_cc_sptr
beidou_b1i_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump);
/*!
* \brief This class implements a block that decodes the NAV data defined in IS-GPS-200E
*
*/
class beidou_b1i_telemetry_decoder_cc : public gr::block
{
public:
~beidou_b1i_telemetry_decoder_cc();
void set_satellite(const Gnss_Satellite &satellite); //!< Set satellite PRN
void set_channel(int channel);
void decode_word(int word_counter, boost::circular_buffer<signed int> *d_bit_buffer, unsigned int& d_BEIDOU_frame_4bytes);
void decodebch_bi1(int *bits, int *decbits);
unsigned int getbitu(const unsigned char *buff, int pos, int len);
void bits2byte(int *bits, int nbits, int nbin, int right, uint8_t *bin);
/*!
* \brief This is where all signal processing takes place
*/
int general_work(int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
private:
friend beidou_b1i_telemetry_decoder_cc_sptr
beidou_b1i_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump);
beidou_b1i_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump);
bool beidou_word_parityCheck(unsigned int beidouword);
// class private vars
int *d_preambles_symbols;
unsigned int d_stat;
bool d_flag_frame_sync;
// symbols
boost::circular_buffer<signed int> d_symbol_history;
boost::circular_buffer<signed int> d_symbol_nh_history;
boost::circular_buffer<signed int> d_bit_buffer;
double d_symbol_accumulator;
short int d_symbol_accumulator_counter;
// symbol counting
bool d_make_correlation;
unsigned int d_symbol_counter_corr;
//bits and frame
unsigned short int d_frame_bit_index;
double bits_NH[BEIDOU_B1I_NH_CODE_LENGTH];
unsigned int d_BEIDOU_frame_4bytes;
unsigned int d_prev_BEIDOU_frame_4bytes;
bool d_flag_parity;
bool d_flag_preamble;
bool d_flag_new_tow_available;
int d_word_number;
// navigation message vars
Beidou_Navigation_Message_D1 d_nav;
BeidouB1iSubframeFsm d_BEIDOU_FSM;
bool d_dump;
Gnss_Satellite d_satellite;
int d_channel;
unsigned long int d_preamble_time_samples;
unsigned int d_TOW_at_Preamble_ms;
unsigned int d_TOW_at_current_symbol_ms;
unsigned int word_number;
bool flag_TOW_set;
bool flag_PLL_180_deg_phase_locked;
std::string d_dump_filename;
std::ofstream d_dump_file;
bool sync_NH;
bool new_sym;
};
#endif

View File

@ -18,13 +18,15 @@
add_subdirectory(libswiftcnav)
set(TELEMETRY_DECODER_LIB_SOURCES
set(TELEMETRY_DECODER_LIB_SOURCES
beidou_b1i_subframe_fsm.cc
viterbi_decoder.cc
)
set(TELEMETRY_DECODER_LIB_HEADERS
viterbi_decoder.h
convolutional.h
beidou_b1i_subframe_fsm.h
)
include_directories(

View File

@ -0,0 +1,289 @@
/*!
* \file beidou_b1i_subframe_fsm.cc
* \brief Implementation of a BEIDOU NAV message word-to-subframe decoder state machine
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#include "beidou_b1i_subframe_fsm.h"
#include "gnss_satellite.h"
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/state.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/statechart/custom_reaction.hpp>
#include <boost/mpl/list.hpp>
#include <cstring>
#include <iostream>
//************ GPS WORD TO SUBFRAME DECODER STATE MACHINE **********
struct Ev_beidou_word_valid : sc::event<Ev_beidou_word_valid>
{
};
struct Ev_beidou_word_invalid : sc::event<Ev_beidou_word_invalid>
{
};
struct Ev_beidou_word_preamble : sc::event<Ev_beidou_word_preamble>
{
};
struct beidou_subframe_fsm_S0 : public sc::state<beidou_subframe_fsm_S0, BeidouB1iSubframeFsm>
{
public:
// sc::transition(event,next_status)
typedef sc::transition<Ev_beidou_word_preamble, beidou_subframe_fsm_S1> reactions;
beidou_subframe_fsm_S0(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S0 "<<std::endl;
}
};
struct beidou_subframe_fsm_S1 : public sc::state<beidou_subframe_fsm_S1, BeidouB1iSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_beidou_word_invalid, beidou_subframe_fsm_S0>,
sc::transition<Ev_beidou_word_valid, beidou_subframe_fsm_S2> >
reactions;
beidou_subframe_fsm_S1(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S1 "<<std::endl;
}
};
struct beidou_subframe_fsm_S2 : public sc::state<beidou_subframe_fsm_S2, BeidouB1iSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_beidou_word_invalid, beidou_subframe_fsm_S0>,
sc::transition<Ev_beidou_word_valid, beidou_subframe_fsm_S3> >
reactions;
beidou_subframe_fsm_S2(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S2 "<<std::endl;
context<BeidouB1iSubframeFsm>().beidou_word_to_subframe(0);
}
};
struct beidou_subframe_fsm_S3 : public sc::state<beidou_subframe_fsm_S3, BeidouB1iSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_beidou_word_invalid, beidou_subframe_fsm_S0>,
sc::transition<Ev_beidou_word_valid, beidou_subframe_fsm_S4> >
reactions;
beidou_subframe_fsm_S3(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S3 "<<std::endl;
context<BeidouB1iSubframeFsm>().beidou_word_to_subframe(1);
}
};
struct beidou_subframe_fsm_S4 : public sc::state<beidou_subframe_fsm_S4, BeidouB1iSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_beidou_word_invalid, beidou_subframe_fsm_S0>,
sc::transition<Ev_beidou_word_valid, beidou_subframe_fsm_S5> >
reactions;
beidou_subframe_fsm_S4(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S4 "<<std::endl;
context<BeidouB1iSubframeFsm>().beidou_word_to_subframe(2);
}
};
struct beidou_subframe_fsm_S5 : public sc::state<beidou_subframe_fsm_S5, BeidouB1iSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_beidou_word_invalid, beidou_subframe_fsm_S0>,
sc::transition<Ev_beidou_word_valid, beidou_subframe_fsm_S6> >
reactions;
beidou_subframe_fsm_S5(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S5 "<<std::endl;
context<BeidouB1iSubframeFsm>().beidou_word_to_subframe(3);
}
};
struct beidou_subframe_fsm_S6 : public sc::state<beidou_subframe_fsm_S6, BeidouB1iSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_beidou_word_invalid, beidou_subframe_fsm_S0>,
sc::transition<Ev_beidou_word_valid, beidou_subframe_fsm_S7> >
reactions;
beidou_subframe_fsm_S6(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S6 "<<std::endl;
context<BeidouB1iSubframeFsm>().beidou_word_to_subframe(4);
}
};
struct beidou_subframe_fsm_S7 : public sc::state<beidou_subframe_fsm_S7, BeidouB1iSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_beidou_word_invalid, beidou_subframe_fsm_S0>,
sc::transition<Ev_beidou_word_valid, beidou_subframe_fsm_S8> >
reactions;
beidou_subframe_fsm_S7(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S7 "<<std::endl;
context<BeidouB1iSubframeFsm>().beidou_word_to_subframe(5);
}
};
struct beidou_subframe_fsm_S8 : public sc::state<beidou_subframe_fsm_S8, BeidouB1iSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_beidou_word_invalid, beidou_subframe_fsm_S0>,
sc::transition<Ev_beidou_word_valid, beidou_subframe_fsm_S9> >
reactions;
beidou_subframe_fsm_S8(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S8 "<<std::endl;
context<BeidouB1iSubframeFsm>().beidou_word_to_subframe(6);
}
};
struct beidou_subframe_fsm_S9 : public sc::state<beidou_subframe_fsm_S9, BeidouB1iSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_beidou_word_invalid, beidou_subframe_fsm_S0>,
sc::transition<Ev_beidou_word_valid, beidou_subframe_fsm_S10> >
reactions;
beidou_subframe_fsm_S9(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S9 "<<std::endl;
context<BeidouB1iSubframeFsm>().beidou_word_to_subframe(7);
}
};
struct beidou_subframe_fsm_S10 : public sc::state<beidou_subframe_fsm_S10, BeidouB1iSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_beidou_word_invalid, beidou_subframe_fsm_S0>,
sc::transition<Ev_beidou_word_valid, beidou_subframe_fsm_S11> >
reactions;
beidou_subframe_fsm_S10(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S10 "<<std::endl;
context<BeidouB1iSubframeFsm>().beidou_word_to_subframe(8);
}
};
struct beidou_subframe_fsm_S11 : public sc::state<beidou_subframe_fsm_S11, BeidouB1iSubframeFsm>
{
public:
typedef sc::transition<Ev_beidou_word_preamble, beidou_subframe_fsm_S1> reactions;
beidou_subframe_fsm_S11(my_context ctx) : my_base(ctx)
{
//std::cout<<"Completed GPS Subframe!"<<std::endl;
context<BeidouB1iSubframeFsm>().beidou_word_to_subframe(9);
context<BeidouB1iSubframeFsm>().beidou_subframe_to_nav_msg(); //decode the subframe
// DECODE SUBFRAME
//std::cout<<"Enter S11"<<std::endl;
}
};
BeidouB1iSubframeFsm::BeidouB1iSubframeFsm()
{
d_nav.reset();
i_channel_ID = 0;
i_satellite_PRN = 0;
d_subframe_ID = 0;
d_flag_new_subframe = false;
initiate(); //start the FSM
}
void BeidouB1iSubframeFsm::beidou_word_to_subframe(int position)
{
// insert the word in the correct position of the subframe
std::memcpy(&d_subframe[position * BEIDOU_WORD_LENGTH], &d_BEIDOU_frame_4bytes, sizeof(char) * BEIDOU_WORD_LENGTH);
}
void BeidouB1iSubframeFsm::clear_flag_new_subframe()
{
d_flag_new_subframe = false;
}
void BeidouB1iSubframeFsm::beidou_subframe_to_nav_msg()
{
//int subframe_ID;
// NEW GPS SUBFRAME HAS ARRIVED!
d_subframe_ID = d_nav.subframe_decoder(this->d_subframe); //decode the subframe
std::cout << "New BEIDOU NAV message received in channel " << i_channel_ID << ": "
<< "subframe "
<< d_subframe_ID << " from satellite "
<< Gnss_Satellite(std::string("Beidou"), i_satellite_PRN) << std::endl;
d_nav.i_satellite_PRN = i_satellite_PRN;
d_nav.i_channel_ID = i_channel_ID;
d_flag_new_subframe = true;
}
void BeidouB1iSubframeFsm::Event_beidou_word_valid()
{
this->process_event(Ev_beidou_word_valid());
}
void BeidouB1iSubframeFsm::Event_beidou_word_invalid()
{
this->process_event(Ev_beidou_word_invalid());
}
void BeidouB1iSubframeFsm::Event_beidou_word_preamble()
{
this->process_event(Ev_beidou_word_preamble());
}

View File

@ -0,0 +1,100 @@
/*!
* \file beidou_b1i_subframe_fsm.h
* \brief Interface of a BEIDOU NAV message word-to-subframe decoder state machine
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_B1I_SUBFRAME_FSM_H_
#define GNSS_SDR_BEIDOU_B1I_SUBFRAME_FSM_H_
#include <boost/statechart/state_machine.hpp>
#include "../../../core/system_parameters/beidou_dnav_almanac.h"
#include "../../../core/system_parameters/beidou_dnav_ephemeris.h"
#include "../../../core/system_parameters/beidou_dnav_iono.h"
#include "../../../core/system_parameters/beidou_dnav_navigation_message.h"
#include "../../../core/system_parameters/beidou_dnav_utc_model.h"
#include "../../../core/system_parameters/Beidou_B1I.h"
namespace sc = boost::statechart;
namespace mpl = boost::mpl;
struct beidou_subframe_fsm_S0;
struct beidou_subframe_fsm_S1;
struct beidou_subframe_fsm_S2;
struct beidou_subframe_fsm_S3;
struct beidou_subframe_fsm_S4;
struct beidou_subframe_fsm_S5;
struct beidou_subframe_fsm_S6;
struct beidou_subframe_fsm_S7;
struct beidou_subframe_fsm_S8;
struct beidou_subframe_fsm_S9;
struct beidou_subframe_fsm_S10;
struct beidou_subframe_fsm_S11;
/*!
* \brief This class implements a Finite State Machine that handles the decoding
* of the GPS L1 C/A NAV message
*/
class BeidouB1iSubframeFsm : public sc::state_machine<BeidouB1iSubframeFsm, beidou_subframe_fsm_S0>
{
public:
BeidouB1iSubframeFsm(); //!< The constructor starts the Finite State Machine
void clear_flag_new_subframe();
// channel and satellite info
int i_channel_ID; //!< Channel id
unsigned int i_satellite_PRN; //!< Satellite PRN number
Beidou_Navigation_Message_D1 d_nav; //!< GPS L1 C/A navigation message object
// GPS SV and System parameters
Beidou_Ephemeris ephemeris; //!< Object that handles GPS ephemeris parameters
Beidou_Almanac almanac; //!< Object that handles GPS almanac data
Beidou_Utc_Model utc_model; //!< Object that handles UTM model parameters
Beidou_Iono iono; //!< Object that handles ionospheric parameters
char d_subframe[BEIDOU_SUBFRAME_LENGTH];
int d_subframe_ID;
bool d_flag_new_subframe;
char d_BEIDOU_frame_4bytes[BEIDOU_WORD_LENGTH];
//double d_preamble_time_ms;
void beidou_word_to_subframe(int position); //!< inserts the word in the correct position of the subframe
/*!
* \brief This function decodes a NAv message subframe and pushes the information to the right queues
*/
void beidou_subframe_to_nav_msg();
//FSM EVENTS
void Event_beidou_word_valid(); //!< FSM event: the received word is valid
void Event_beidou_word_invalid(); //!< FSM event: the received word is not valid
void Event_beidou_word_preamble(); //!< FSM event: word preamble detected
};
#endif

View File

@ -52,6 +52,7 @@ set(TRACKING_ADAPTER_SOURCES
gps_l5_dll_pll_tracking.cc
glonass_l2_ca_dll_pll_tracking.cc
glonass_l2_ca_dll_pll_c_aid_tracking.cc
beidou_b1i_dll_pll_tracking.cc
${OPT_TRACKING_ADAPTERS_SOURCES}
)
@ -69,6 +70,7 @@ set(TRACKING_ADAPTER_HEADERS
gps_l5_dll_pll_tracking.h
glonass_l2_ca_dll_pll_tracking.h
glonass_l2_ca_dll_pll_c_aid_tracking.h
beidou_b1i_dll_pll_tracking.h
${OPT_TRACKING_ADAPTERS_HEADERS}
)

View File

@ -0,0 +1,198 @@
/*!
* \file beidou_b1i_dll_pll_tracking.cc
* \brief Implementation of an adapter of a DLL+PLL tracking loop block
* for Beidou B1I to a TrackingInterface
* \author Sergi Segura, 2018. sergi.segura.munoz@gmail.com
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkhauser, 2007
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#include "dll_pll_conf.h"
#include "beidou_b1i_dll_pll_tracking.h"
#include "configuration_interface.h"
#include "gnss_sdr_flags.h"
#include "display.h"
#include <glog/logging.h>
#include "Beidou_B1I.h"
using google::LogMessage;
BeidouB1iDllPllTracking::BeidouB1iDllPllTracking(
ConfigurationInterface* configuration, std::string role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
Dll_Pll_Conf trk_param = Dll_Pll_Conf();
DLOG(INFO) << "role " << role;
//################# CONFIGURATION PARAMETERS ########################
std::string default_item_type = "gr_complex";
std::string item_type = configuration->property(role + ".item_type", default_item_type);
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
trk_param.fs_in = fs_in;
bool dump = configuration->property(role + ".dump", false);
trk_param.dump = dump;
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0);
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
trk_param.pll_bw_hz = pll_bw_hz;
float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 20.0);
trk_param.pll_bw_narrow_hz = pll_bw_narrow_hz;
float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 2.0);
trk_param.dll_bw_narrow_hz = dll_bw_narrow_hz;
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0);
if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
trk_param.dll_bw_hz = dll_bw_hz;
float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5);
trk_param.early_late_space_chips = early_late_space_chips;
float early_late_space_narrow_chips = configuration->property(role + ".early_late_space_narrow_chips", 0.5);
trk_param.early_late_space_narrow_chips = early_late_space_narrow_chips;
std::string default_dump_filename = "./track_ch";
std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename);
trk_param.dump_filename = dump_filename;
int vector_length = std::round(fs_in / (BEIDOU_B1I_CODE_RATE_HZ / BEIDOU_B1I_CODE_LENGTH_CHIPS));
trk_param.vector_length = vector_length;
int symbols_extended_correlator = configuration->property(role + ".extend_correlation_symbols", 1);
if (symbols_extended_correlator < 1)
{
symbols_extended_correlator = 1;
std::cout << TEXT_RED << "WARNING: BEIDOU B1I. extend_correlation_symbols must be bigger than 1. Coherent integration has been set to 1 symbol (1 ms)" << TEXT_RESET << std::endl;
}
else if (symbols_extended_correlator > 20)
{
symbols_extended_correlator = 20;
std::cout << TEXT_RED << "WARNING: BEIDOU B1I. extend_correlation_symbols must be lower than 21. Coherent integration has been set to 20 symbols (20 ms)" << TEXT_RESET << std::endl;
}
trk_param.extend_correlation_symbols = symbols_extended_correlator;
bool track_pilot = configuration->property(role + ".track_pilot", false);
if (track_pilot)
{
std::cout << TEXT_RED << "WARNING: BEIDOU B1I does not have pilot signal. Data tracking has been enabled" << TEXT_RESET << std::endl;
}
if ((symbols_extended_correlator > 1) and (pll_bw_narrow_hz > pll_bw_hz or dll_bw_narrow_hz > dll_bw_hz))
{
std::cout << TEXT_RED << "WARNING: BEIDOU B1I. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << std::endl;
}
trk_param.very_early_late_space_chips = 0.0;
trk_param.very_early_late_space_narrow_chips = 0.0;
trk_param.track_pilot = false;
trk_param.system = 'C';
char sig_[3] = "B1";
std::memcpy(trk_param.signal, sig_, 3);
int cn0_samples = configuration->property(role + ".cn0_samples", 20);
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
trk_param.cn0_samples = cn0_samples;
int cn0_min = configuration->property(role + ".cn0_min", 25);
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
trk_param.cn0_min = cn0_min;
int max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail;
trk_param.max_lock_fail = max_lock_fail;
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85);
if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th;
trk_param.carrier_lock_th = carrier_lock_th;
//################# MAKE TRACKING GNURadio object ###################
if (item_type.compare("gr_complex") == 0)
{
item_size_ = sizeof(gr_complex);
tracking_ = dll_pll_veml_make_tracking(trk_param);
}
else
{
item_size_ = sizeof(gr_complex);
LOG(WARNING) << item_type << " unknown tracking item type.";
}
channel_ = 0;
DLOG(INFO) << "tracking(" << tracking_->unique_id() << ")";
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";
}
if (out_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one output stream";
}
}
BeidouB1iDllPllTracking::~BeidouB1iDllPllTracking()
{
}
void BeidouB1iDllPllTracking::start_tracking()
{
tracking_->start_tracking();
}
/*
* Set tracking channel unique ID
*/
void BeidouB1iDllPllTracking::set_channel(unsigned int channel)
{
channel_ = channel;
tracking_->set_channel(channel);
}
void BeidouB1iDllPllTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{
tracking_->set_gnss_synchro(p_gnss_synchro);
}
void BeidouB1iDllPllTracking::connect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
//nothing to connect, now the tracking uses gr_sync_decimator
}
void BeidouB1iDllPllTracking::disconnect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
//nothing to disconnect, now the tracking uses gr_sync_decimator
}
gr::basic_block_sptr BeidouB1iDllPllTracking::get_left_block()
{
return tracking_;
}
gr::basic_block_sptr BeidouB1iDllPllTracking::get_right_block()
{
return tracking_;
}

View File

@ -0,0 +1,101 @@
/*!
* \file beidou_b1i_dll_pll_tracking.h
* \brief Interface of an adapter of a DLL+PLL tracking loop block
* for Beidou B1I to a TrackingInterface
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkhauser, 2007
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_B1I_DLL_PLL_TRACKING_H_
#define GNSS_SDR_BEIDOU_B1I_DLL_PLL_TRACKING_H_
#include "tracking_interface.h"
#include "dll_pll_veml_tracking.h"
#include <string>
class ConfigurationInterface;
/*!
* \brief This class implements a code DLL + carrier PLL tracking loop
*/
class BeidouB1iDllPllTracking : public TrackingInterface
{
public:
BeidouB1iDllPllTracking(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~BeidouB1iDllPllTracking();
inline std::string role() override
{
return role_;
}
inline std::string implementation() override
{
return "BEIDOU_B1I_DLL_PLL_Tracking";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set tracking channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
void start_tracking() override;
private:
dll_pll_veml_tracking_sptr tracking_;
size_t item_size_;
unsigned int channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
};
#endif // GNSS_SDR_BEIDOU_B1I_DLL_PLL_TRACKING_H_

View File

@ -49,6 +49,7 @@
#include "gps_l2c_signal.h"
#include "GPS_L5.h"
#include "gps_l5_signal.h"
#include "beidou_b1I_signal_processing.h"
#include <boost/lexical_cast.hpp>
#include <glog/logging.h>
#include <gnuradio/io_signature.h>
@ -59,6 +60,7 @@
#include <iostream>
#include <sstream>
#include <numeric>
#include "../../../core/system_parameters/Beidou_B1I.h"
using google::LogMessage;
@ -106,6 +108,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
map_signal_pretty_name["2G"] = "L2 C/A";
map_signal_pretty_name["5X"] = "E5a";
map_signal_pretty_name["L5"] = "L5";
map_signal_pretty_name["B1"] = "B1I";
signal_pretty_name = map_signal_pretty_name[signal_type];
@ -269,6 +272,40 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
d_symbols_per_bit = 0;
}
}
else if (trk_parameters.system == 'C')
{
systemName = "Beidou";
if (signal_type.compare("B1") == 0)
{
d_signal_carrier_freq = BEIDOU_B1I_FREQ_HZ;
d_code_period = BEIDOU_B1I_CODE_PERIOD;
d_code_chip_rate = BEIDOU_B1I_CODE_RATE_HZ;
d_code_length_chips = static_cast<unsigned int>(BEIDOU_B1I_CODE_LENGTH_CHIPS);
d_symbols_per_bit = BEIDOU_B1I_TELEMETRY_SYMBOLS_PER_BIT;
d_correlation_length_ms = 1;
d_code_samples_per_chip = 1;
d_secondary = true;
trk_parameters.track_pilot = false;
interchange_iq = false;
d_secondary_code_length = static_cast<unsigned int>(BEIDOU_B1I_NH_CODE_LENGTH);
d_secondary_code_string = const_cast<std::string *>(&BEIDOU_B1I_NH_CODE_STR);
}
else
{
LOG(WARNING) << "Invalid Signal argument when instantiating tracking blocks";
std::cout << "Invalid Signal argument when instantiating tracking blocks" << std::endl;
d_correlation_length_ms = 1;
d_secondary = false;
interchange_iq = false;
d_signal_carrier_freq = 0.0;
d_code_period = 0.0;
d_code_length_chips = 0;
d_code_samples_per_chip = 0;
d_symbols_per_bit = 0;
}
}
else
{
LOG(WARNING) << "Invalid System argument when instantiating tracking blocks";
@ -527,6 +564,10 @@ void dll_pll_veml_tracking::start_tracking()
}
volk_gnsssdr_free(aux_code);
}
else if (systemName.compare("Beidou") == 0 and signal_type.compare("B1") == 0)
{
beidou_b1i_code_gen_float(d_tracking_code, d_acquisition_gnss_synchro->PRN, 0);
}
multicorrelator_cpu.set_local_code_and_taps(d_code_samples_per_chip * d_code_length_chips, d_tracking_code, d_local_code_shift_chips);
std::fill_n(d_correlator_outs, d_n_correlator_taps, gr_complex(0.0, 0.0));

View File

@ -82,6 +82,7 @@
#include "galileo_e5a_pcps_acquisition.h"
#include "glonass_l1_ca_pcps_acquisition.h"
#include "glonass_l2_ca_pcps_acquisition.h"
#include "beidou_b1i_pcps_acquisition.h"
#include "gps_l1_ca_dll_pll_tracking.h"
#include "gps_l1_ca_dll_pll_c_aid_tracking.h"
#include "gps_l1_ca_tcp_connector_tracking.h"
@ -94,6 +95,7 @@
#include "glonass_l2_ca_dll_pll_tracking.h"
#include "glonass_l2_ca_dll_pll_c_aid_tracking.h"
#include "gps_l5_dll_pll_tracking.h"
#include "beidou_b1i_dll_pll_tracking.h"
#include "gps_l1_ca_telemetry_decoder.h"
#include "gps_l2c_telemetry_decoder.h"
#include "gps_l5_telemetry_decoder.h"
@ -101,6 +103,7 @@
#include "galileo_e5a_telemetry_decoder.h"
#include "glonass_l1_ca_telemetry_decoder.h"
#include "glonass_l2_ca_telemetry_decoder.h"
#include "beidou_b1i_telemetry_decoder.h"
#include "sbas_l1_telemetry_decoder.h"
#include "hybrid_observables.h"
#include "rtklib_pvt.h"
@ -280,15 +283,18 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetObservables(std::shared
GPS_channels += configuration->property("Channels_2S.count", 0);
GPS_channels += configuration->property("Channels_L5.count", 0);
unsigned int Glonass_channels = configuration->property("Channels_1G.count", 0);
unsigned int Beidou_channels = configuration->property("Channels_B1.count", 0);
unsigned int extra_channels = 1; // For monitor channel sample counter
return GetBlock(configuration, "Observables", implementation,
Galileo_channels +
GPS_channels +
Glonass_channels +
Beidou_channels +
extra_channels,
Galileo_channels +
GPS_channels +
Glonass_channels);
Glonass_channels +
Beidou_channels);
}
@ -303,7 +309,8 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetPVT(std::shared_ptr<Con
GPS_channels += configuration->property("Channels_2S.count", 0);
GPS_channels += configuration->property("Channels_L5.count", 0);
unsigned int Glonass_channels = configuration->property("Channels_1G.count", 0);
return GetBlock(configuration, "PVT", implementation, Galileo_channels + GPS_channels + Glonass_channels, 0);
unsigned int Beidou_channels = configuration->property("Channels_B1.count", 0);
return GetBlock(configuration, "PVT", implementation, Galileo_channels + GPS_channels + Glonass_channels + Beidou_channels, 0);
}
@ -783,6 +790,72 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetChannel_L5(
}
//********* BeiDou B1I CHANNEL *****************
std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetChannel_B1(
std::shared_ptr<ConfigurationInterface> configuration,
std::string acq, std::string trk, std::string tlm, int channel,
gr::msg_queue::sptr queue)
{
std::stringstream stream;
stream << channel;
std::string id = stream.str();
LOG(INFO) << "Instantiating Channel " << id << " with Acquisition Implementation: "
<< acq << ", Tracking Implementation: " << trk << ", Telemetry Decoder implementation: " << tlm;
std::string aux = configuration->property("Acquisition_B1" + std::to_string(channel) + ".implementation", std::string("W"));
std::string appendix1;
if (aux.compare("W") != 0)
{
appendix1 = std::to_string(channel);
}
else
{
appendix1 = "";
}
aux = configuration->property("Tracking_B1" + std::to_string(channel) + ".implementation", std::string("W"));
std::string appendix2;
if (aux.compare("W") != 0)
{
appendix2 = std::to_string(channel);
}
else
{
appendix2 = "";
}
aux = configuration->property("TelemetryDecoder_B1" + std::to_string(channel) + ".implementation", std::string("W"));
std::string appendix3;
if (aux.compare("W") != 0)
{
appendix3 = std::to_string(channel);
}
else
{
appendix3 = "";
}
// Automatically detect input data type
std::shared_ptr<InMemoryConfiguration> config;
config = std::make_shared<InMemoryConfiguration>();
std::string default_item_type = "gr_complex";
std::string acq_item_type = configuration->property("Acquisition_B1" + appendix1 + ".item_type", default_item_type);
std::string trk_item_type = configuration->property("Tracking_B1" + appendix2 + ".item_type", default_item_type);
if (acq_item_type.compare(trk_item_type))
{
LOG(ERROR) << "Acquisition and Tracking blocks must have the same input data type!";
}
config->set_property("Channel.item_type", acq_item_type);
std::unique_ptr<GNSSBlockInterface> pass_through_ = GetBlock(configuration, "Channel", "Pass_Through", 1, 1, queue);
std::unique_ptr<AcquisitionInterface> acq_ = GetAcqBlock(configuration, "Acquisition_B1" + appendix1, acq, 1, 0);
std::unique_ptr<TrackingInterface> trk_ = GetTrkBlock(configuration, "Tracking_B1" + appendix2, trk, 1, 1);
std::unique_ptr<TelemetryDecoderInterface> tlm_ = GetTlmBlock(configuration, "TelemetryDecoder_B1" + appendix3, tlm, 1, 1);
std::unique_ptr<GNSSBlockInterface> channel_(new Channel(configuration.get(), channel, std::move(pass_through_),
std::move(acq_),
std::move(trk_),
std::move(tlm_),
"Channel", "B1", queue));
return channel_;
}
std::unique_ptr<std::vector<std::unique_ptr<GNSSBlockInterface>>> GNSSBlockFactory::GetChannels(
std::shared_ptr<ConfigurationInterface> configuration, gr::msg_queue::sptr queue)
{
@ -800,6 +873,7 @@ std::unique_ptr<std::vector<std::unique_ptr<GNSSBlockInterface>>> GNSSBlockFacto
unsigned int Channels_2S_count = configuration->property("Channels_2S.count", 0);
unsigned int Channels_5X_count = configuration->property("Channels_5X.count", 0);
unsigned int Channels_L5_count = configuration->property("Channels_L5.count", 0);
unsigned int Channels_B1_count = configuration->property("Channels_B1.count", 0);
unsigned int total_channels = Channels_1C_count +
Channels_1B_count +
@ -807,7 +881,8 @@ std::unique_ptr<std::vector<std::unique_ptr<GNSSBlockInterface>>> GNSSBlockFacto
Channels_2S_count +
Channels_2G_count +
Channels_5X_count +
Channels_L5_count;
Channels_L5_count +
Channels_B1_count;
std::unique_ptr<std::vector<std::unique_ptr<GNSSBlockInterface>>> channels(new std::vector<std::unique_ptr<GNSSBlockInterface>>(total_channels));
try
@ -1017,6 +1092,36 @@ std::unique_ptr<std::vector<std::unique_ptr<GNSSBlockInterface>>> GNSSBlockFacto
queue);
channel_absolute_id++;
}
//**************** BEIDOU B1I CHANNELS **********************
LOG(INFO) << "Getting " << Channels_B1_count << " BEIDOU B1I channels";
acquisition_implementation = configuration->property("Acquisition_B1.implementation", default_implementation);
tracking_implementation = configuration->property("Tracking_B1.implementation", default_implementation);
telemetry_decoder_implementation = configuration->property("TelemetryDecoder_B1.implementation", default_implementation);
for (unsigned int i = 0; i < Channels_B1_count; i++)
{
//(i.e. Acquisition_2G0.implementation=xxxx)
std::string acquisition_implementation_specific = configuration->property(
"Acquisition_B1" + std::to_string(channel_absolute_id) + ".implementation",
acquisition_implementation);
//(i.e. Tracking_2G0.implementation=xxxx)
std::string tracking_implementation_specific = configuration->property(
"Tracking_B1" + std::to_string(channel_absolute_id) + ".implementation",
tracking_implementation);
std::string telemetry_decoder_implementation_specific = configuration->property(
"TelemetryDecoder_B1" + std::to_string(channel_absolute_id) + ".implementation",
telemetry_decoder_implementation);
// Push back the channel to the vector of channels
channels->at(channel_absolute_id) = GetChannel_B1(configuration,
acquisition_implementation_specific,
tracking_implementation_specific,
telemetry_decoder_implementation_specific,
channel_absolute_id,
queue);
channel_absolute_id++;
}
}
catch (const std::exception &e)
{
@ -1048,6 +1153,7 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
if (implementation.compare("Pass_Through") == 0)
{
std::unique_ptr<GNSSBlockInterface> block_(new Pass_Through(configuration.get(), role, in_streams, out_streams));
block = std::move(block_);
}
@ -1495,6 +1601,13 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
out_streams));
block = std::move(block_);
}
else if (implementation.compare("BEIDOU_B1I_PCPS_Acquisition") == 0)
{
std::unique_ptr<AcquisitionInterface> block_(new BeidouB1iPcpsAcquisition(configuration.get(), role, in_streams,
out_streams));
block = std::move(block_);
}
// TRACKING BLOCKS -------------------------------------------------------------
else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking") == 0)
{
@ -1622,6 +1735,12 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
out_streams));
block = std::move(block_);
}
else if (implementation.compare("BEIDOU_B1I_DLL_PLL_Tracking") == 0)
{
std::unique_ptr<GNSSBlockInterface> block_(new BeidouB1iDllPllTracking(configuration.get(), role, in_streams,
out_streams));
block = std::move(block_);
}
// TELEMETRY DECODERS ----------------------------------------------------------
else if (implementation.compare("GPS_L1_CA_Telemetry_Decoder") == 0)
{
@ -1671,6 +1790,13 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
out_streams));
block = std::move(block_);
}
else if (implementation.compare("BEIDOU_B1I_Telemetry_Decoder") == 0)
{
std::unique_ptr<GNSSBlockInterface> block_(new BeidouB1iTelemetryDecoder(configuration.get(), role, in_streams,
out_streams));
block = std::move(block_);
}
// OBSERVABLES -----------------------------------------------------------------
else if ((implementation.compare("Hybrid_Observables") == 0) || (implementation.compare("GPS_L1_CA_Observables") == 0) || (implementation.compare("GPS_L2C_Observables") == 0) ||
(implementation.compare("Galileo_E5A_Observables") == 0))
@ -1859,6 +1985,13 @@ std::unique_ptr<AcquisitionInterface> GNSSBlockFactory::GetAcqBlock(
out_streams));
block = std::move(block_);
}
else if (implementation.compare("BEIDOU_B1I_PCPS_Acquisition") == 0)
{
std::unique_ptr<AcquisitionInterface> block_(new BeidouB1iPcpsAcquisition(configuration.get(), role, in_streams,
out_streams));
block = std::move(block_);
}
else
{
// Log fatal. This causes execution to stop.
@ -2003,6 +2136,13 @@ std::unique_ptr<TrackingInterface> GNSSBlockFactory::GetTrkBlock(
out_streams));
block = std::move(block_);
}
else if (implementation.compare("BEIDOU_B1I_DLL_PLL_Tracking") == 0)
{
std::unique_ptr<TrackingInterface> block_(new BeidouB1iDllPllTracking(configuration.get(), role, in_streams,
out_streams));
block = std::move(block_);
}
else
{
// Log fatal. This causes execution to stop.
@ -2069,6 +2209,14 @@ std::unique_ptr<TelemetryDecoderInterface> GNSSBlockFactory::GetTlmBlock(
out_streams));
block = std::move(block_);
}
else if (implementation.compare("BEIDOU_B1I_Telemetry_Decoder") == 0)
{
std::unique_ptr<TelemetryDecoderInterface> block_(new BeidouB1iTelemetryDecoder(configuration.get(), role, in_streams,
out_streams));
block = std::move(block_);
}
else
{
// Log fatal. This causes execution to stop.

View File

@ -106,6 +106,10 @@ private:
std::string acq, std::string trk, std::string tlm, int channel,
boost::shared_ptr<gr::msg_queue> queue);
std::unique_ptr<GNSSBlockInterface> GetChannel_B1(std::shared_ptr<ConfigurationInterface> configuration,
std::string acq, std::string trk, std::string tlm, int channel,
boost::shared_ptr<gr::msg_queue> queue);
std::unique_ptr<AcquisitionInterface> GetAcqBlock(
std::shared_ptr<ConfigurationInterface> configuration,
std::string role,

View File

@ -277,8 +277,7 @@ void GNSSFlowgraph::connect()
std::cout << "Set GNSS-SDR.internal_fs_sps in configuration file" << std::endl;
throw(std::invalid_argument("Set GNSS-SDR.internal_fs_sps in configuration"));
}
int observable_interval_ms = static_cast<double>(configuration_->property("GNSS-SDR.observable_interval_ms", 20));
ch_out_sample_counter = gnss_sdr_make_sample_counter(fs, observable_interval_ms, sig_conditioner_.at(0)->get_right_block()->output_signature()->sizeof_stream_item(0));
ch_out_sample_counter = gnss_sdr_make_sample_counter(fs, sig_conditioner_.at(0)->get_right_block()->output_signature()->sizeof_stream_item(0));
top_block_->connect(sig_conditioner_.at(0)->get_right_block(), 0, ch_out_sample_counter, 0);
top_block_->connect(ch_out_sample_counter, 0, observables_->get_left_block(), channels_count_); //extra port for the sample counter pulse
}
@ -473,6 +472,12 @@ void GNSSFlowgraph::connect()
available_GLO_2G_signals_.remove(signal_value);
break;
case evBDS_B1:
gnss_system = "Beidou";
signal_value = Gnss_Signal(Gnss_Satellite(gnss_system, sat), gnss_signal);
available_BDS_B1_signals_.remove(signal_value);
break;
default:
LOG(ERROR) << "This should not happen :-(";
gnss_system = "GPS";
@ -863,10 +868,14 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
available_GLO_2G_signals_.push_back(channels_[who]->get_signal());
break;
case evBDS_B1:
available_BDS_B1_signals_.push_back(channels_[who]->get_signal());
break;
default:
LOG(ERROR) << "This should not happen :-(";
break;
}
}
}
channels_state_[who] = 0;
acq_channels_count_--;
@ -931,6 +940,10 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
available_GLO_2G_signals_.remove(channels_[who]->get_signal());
break;
case evBDS_B1:
available_BDS_B1_signals_.remove(channels_[who]->get_signal());
break;
default:
LOG(ERROR) << "This should not happen :-(";
break;
@ -1011,6 +1024,10 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
available_GLO_2G_signals_.push_back(channels_[who]->get_signal());
break;
case evBDS_B1:
available_BDS_B1_signals_.push_back(channels_[who]->get_signal());
break;
default:
LOG(ERROR) << "This should not happen :-(";
break;
@ -1145,6 +1162,7 @@ void GNSSFlowgraph::init()
mapStringValues_["5X"] = evGAL_5X;
mapStringValues_["1G"] = evGLO_1G;
mapStringValues_["2G"] = evGLO_2G;
mapStringValues_["B1"] = evBDS_B1;
// fill the signals queue with the satellites ID's to be searched by the acquisition
set_signals_list();
@ -1191,6 +1209,10 @@ void GNSSFlowgraph::set_signals_list()
// Removing satellites sharing same frequency number(1 and 5, 2 and 6, 3 and 7, 4 and 6, 11 and 15, 12 and 16, 14 and 18, 17 and 21
std::set<unsigned int> available_glonass_prn = {1, 2, 3, 4, 9, 10, 11, 12, 18, 19, 20, 21, 24};
std::set<unsigned int> available_beidou_prn = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35};
std::string sv_list = configuration_->property("Galileo.prns", std::string(""));
if (sv_list.length() > 0)
@ -1254,6 +1276,23 @@ void GNSSFlowgraph::set_signals_list()
available_glonass_prn = tmp_set;
}
}
sv_list = configuration_->property("Beidou.prns", std::string(""));
if (sv_list.length() > 0)
{
// Reset the available prns:
std::set<unsigned int> tmp_set;
boost::tokenizer<> tok(sv_list);
std::transform(tok.begin(), tok.end(), std::inserter(tmp_set, tmp_set.begin()),
boost::lexical_cast<unsigned int, std::string>);
if (tmp_set.size() > 0)
{
available_beidou_prn = tmp_set;
}
}
if (configuration_->property("Channels_1C.count", 0) > 0)
{
@ -1358,6 +1397,23 @@ void GNSSFlowgraph::set_signals_list()
std::string("2G")));
}
}
if (configuration_->property("Channels_B1.count", 0) > 0)
{
/*
* Loop to create the list of BeiDou B1C signals
*/
for (available_gnss_prn_iter = available_beidou_prn.cbegin();
available_gnss_prn_iter != available_beidou_prn.cend();
available_gnss_prn_iter++)
{
available_BDS_B1_signals_.push_back(Gnss_Signal(
Gnss_Satellite(std::string("Beidou"), *available_gnss_prn_iter),
std::string("B1")));
}
}
}
@ -1400,7 +1456,7 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
if (!pop)
{
available_GPS_1C_signals_.push_back(result);
}
}
if (tracked)
{
if ((configuration_->property("Channels_2S.count", 0) > 0) or (configuration_->property("Channels_L5.count", 0) > 0))
@ -1587,11 +1643,37 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
}
break;
case evBDS_B1:
result = available_BDS_B1_signals_.front();
available_BDS_B1_signals_.pop_front();
if (!pop)
{
available_BDS_B1_signals_.push_back(result);
}
if (tracked)
{
// In the near future Beidou B2a will be added
// if (configuration_->property("Channels_5C.count", 0) > 0)
// {
// for (unsigned int ch = 0; ch < channels_count_; ch++)
// {
// if ((channels_[ch]->get_signal().get_satellite() == result.get_satellite()) and (channels_[ch]->get_signal().get_signal_str().compare("5C") != 0)) untracked_satellite = false;
// }
// if (untracked_satellite)
// {
// Gnss_Signal gs = Gnss_Signal(result.get_satellite(), "5C");
// available_BDS_5C_signals_.remove(gs);
// available_BDS_5C_signals_.push_front(gs);
// }
// }
}
break;
default:
LOG(ERROR) << "This should not happen :-(";
result = available_GPS_1C_signals_.front();
if (pop)
{
if (pop)
{
available_GPS_1C_signals_.pop_front();
}
break;

View File

@ -168,6 +168,7 @@ private:
std::list<Gnss_Signal> available_GAL_5X_signals_;
std::list<Gnss_Signal> available_GLO_1G_signals_;
std::list<Gnss_Signal> available_GLO_2G_signals_;
std::list<Gnss_Signal> available_BDS_B1_signals_;
enum StringValue
{
evGPS_1C,
@ -177,7 +178,8 @@ private:
evGAL_1B,
evGAL_5X,
evGLO_1G,
evGLO_2G
evGLO_2G,
evBDS_B1
};
std::map<std::string, StringValue> mapStringValues_;

View File

@ -0,0 +1,258 @@
/*!
* \file beidou_b1I.h
* \brief Defines system parameters for BeiDou B1I signal and D1 NAV data
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_B1I_H_
#define GNSS_SDR_BEIDOU_B1I_H_
#include <vector>
#include <utility> // std::pair
#include "MATH_CONSTANTS.h"
// Physical constants
const double BEIDOU_C_m_s = 299792458.0; //!< The speed of light, [m/s]
const double BEIDOU_C_m_ms = 299792.4580; //!< The speed of light, [m/ms]
const double BEIDOU_PI = 3.1415926535898; //!< Pi
const double BEIDOU_TWO_PI = 6.283185307179586;//!< 2Pi
const double BEIDOU_OMEGA_EARTH_DOT = 7.2921150e-5; //!< Earth rotation rate, [rad/s] as defined in CGCS2000
const double BEIDOU_GM = 3.986004418e14; //!< Universal gravitational constant times the mass of the Earth, [m^3/s^2] as defined in CGCS2000
const double BEIDOU_F = -4.442807309e-10; //!< Constant, [s/(m)^(1/2)] F=-2(GM)^.5/C^2
// carrier and code frequencies
const double BEIDOU_B1I_FREQ_HZ = 1.561098e9; //!< b1I [Hz]
const double BEIDOU_B1I_CODE_RATE_HZ = 2.046e6; //!< beidou b1I code rate [chips/s]
const double BEIDOU_B1I_CODE_LENGTH_CHIPS = 2046.0; //!< beidou b1I code length [chips]
const double BEIDOU_B1I_CODE_PERIOD = 0.001; //!< beidou b1I code period [seconds]
const unsigned int BEIDOU_B1I_CODE_PERIOD_MS = 1; //!< GPS L1 C/A code period [ms]
const double BEIDOU_B1I_CHIP_PERIOD = 4.8875e-07; //!< beidou b1I chip period [seconds]
/*!
* \brief Maximum Time-Of-Arrival (TOA) difference between satellites for a receiver operated on Earth surface is 20 ms
*
* According to the GPS orbit model described in [1] Pag. 32.
* It should be taken into account to set the buffer size for the PRN start timestamp in the pseudoranges block.
* [1] J. Bao-Yen Tsui, Fundamentals of Global Positioning System Receivers. A Software Approach, John Wiley & Sons,
* Inc., Hoboken, NJ, 2nd edition, 2005.
*/
const double BEIDOU_MAX_TOA_DELAY_MS = 20; //******************
//#define NAVIGATION_SOLUTION_RATE_MS 1000 // this cannot go here
const double BEIDOU_STARTOFFSET_ms = 68.802; //**************[ms] Initial sign. travel time (this cannot go here)
// OBSERVABLE HISTORY DEEP FOR INTERPOLATION
const int BEIDOU_B1I_HISTORY_DEEP = 100; // ****************
// NAVIGATION MESSAGE DEMODULATION AND DECODING
#define BEIDOU_PREAMBLE {1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0}
const int BEIDOU_B1I_PREAMBLE_LENGTH_BITS = 11;
const int BEIDOU_B1I_PREAMBLE_LENGTH_SYMBOLS = 220; // **************
const double BEIDOU_B1I_PREAMBLE_DURATION_S = 0.220;
const int BEIDOU_B1I_PREAMBLE_DURATION_MS = 220;
const int BEIDOU_B1I_TELEMETRY_RATE_BITS_SECOND = 50; //!< D1 NAV message bit rate [bits/s]
const int BEIDOU_B1I_TELEMETRY_SYMBOLS_PER_BIT = 20; // *************
const int BEIDOU_B1I_TELEMETRY_RATE_SYMBOLS_SECOND = BEIDOU_B1I_TELEMETRY_RATE_BITS_SECOND*BEIDOU_B1I_TELEMETRY_SYMBOLS_PER_BIT; //************!< NAV message bit rate [symbols/s]
const int BEIDOU_WORD_LENGTH = 4; //**************!< CRC + BEIDOU WORD (-2 -1 0 ... 29) Bits = 4 bytes
const int BEIDOU_SUBFRAME_LENGTH = 40; //**************!< BEIDOU_WORD_LENGTH x 10 = 40 bytes
const int BEIDOU_SUBFRAME_BITS = 300; //!< Number of bits per subframe in the NAV message [bits]
const int BEIDOU_SUBFRAME_SECONDS = 6; //!< Subframe duration [seconds]
const int BEIDOU_SUBFRAME_MS = 6000; //!< Subframe duration [miliseconds]
const int BEIDOU_WORD_BITS = 30; //!< Number of bits per word in the NAV message [bits]
const int BEIDOU_B1I_NH_CODE_LENGTH = 20;
const int BEIDOU_B1I_NH_CODE[20] = {0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0};
const std::string BEIDOU_B1I_NH_CODE_STR = "00000100110101001110";
// BEIDOU D1 NAVIGATION MESSAGE STRUCTURE
// GENERAL
const std::vector<std::pair<int,int> > D1_PRE( { {1,11} } );
const std::vector<std::pair<int,int> > D1_FRAID( { {16,3} } );
const std::vector<std::pair<int,int> > D1_SOW( { {19,8},{31,12} } );
const std::vector<std::pair<int,int> > D1_PNUM( { {44,7} } );
// SUBFRAME 1
const std::vector<std::pair<int,int> > D1_SAT_H1( { {43,1} } );
const std::vector<std::pair<int,int> > D1_AODC( { {44,5} } );
const std::vector<std::pair<int,int> > D1_URAI( { {49,4} } );
const std::vector<std::pair<int,int> > D1_WN( { {61,13} } );
const std::vector<std::pair<int,int> > D1_TOC( { {74,9},{91,8} } );
const double D1_TOC_LSB = TWO_P3;
const std::vector<std::pair<int,int> > D1_TGD1( { {99,10} } );
const double D1_TGD1_LSB = 0.1;
const std::vector<std::pair<int,int> > D1_TGD2( { {121,6} } );
const double D1_TGD2_LSB = 0.1;
const std::vector<std::pair<int,int> > D1_ALPHA0( { {127,8} } );
const double D1_ALPHA0_LSB = TWO_N30;
const std::vector<std::pair<int,int> > D1_ALPHA1( { {135,8} } );
const double D1_ALPHA1_LSB = TWO_N27;
const std::vector<std::pair<int,int> > D1_ALPHA2( { {151,8} } );
const double D1_ALPHA2_LSB = TWO_N24;
const std::vector<std::pair<int,int> > D1_ALPHA3( { {159,8} } );
const double D1_ALPHA3_LSB = TWO_N24;
const std::vector<std::pair<int,int> > D1_BETA0( { {167,6}, {181,2} } );
const double D1_BETA0_LSB = TWO_P11;
const std::vector<std::pair<int,int> > D1_BETA1( { {183,8} } );
const double D1_BETA1_LSB = TWO_P14;
const std::vector<std::pair<int,int> > D1_BETA2( { {191,8} } );
const double D1_BETA2_LSB = TWO_P16;
const std::vector<std::pair<int,int> > D1_BETA3( { {199,4},{211,4} } );
const double D1_BETA3_LSB = TWO_P16;
const std::vector<std::pair<int,int> > D1_A2( { {215,11} } );
const double D1_A2_LSB = TWO_N66;
const std::vector<std::pair<int,int> > D1_A0( { {226,7},{241,17} } );
const double D1_A0_LSB = TWO_N33;
const std::vector<std::pair<int,int> > D1_A1( { {258,5},{271,17} } );
const double D1_A1_LSB = TWO_N50;
const std::vector<std::pair<int,int> > D1_AODE( { {288,5} } );
//SUBFRAME 2
const std::vector<std::pair<int,int> > D1_DELTA_N( { {43,10},{61,6} } );
const double D1_DELTA_N_LSB = PI_TWO_N43;
const std::vector<std::pair<int,int> > D1_CUC( { {67,16},{91,2} } );
const double D1_CUC_LSB = TWO_N31;
const std::vector<std::pair<int,int> > D1_M0( { {93,20}, {121,12} } );
const double D1_M0_LSB = PI_TWO_N31;
const std::vector<std::pair<int,int> > D1_E( { {133,10},{151,22} } );
const double D1_E_LSB = TWO_N33;
const std::vector<std::pair<int,int> > D1_CUS( { {181,18} } );
const double D1_CUS_LSB = TWO_N31;
const std::vector<std::pair<int,int> > D1_CRC( { {199,4},{211,14} } );
const double D1_CRC_LSB = TWO_N6;
const std::vector<std::pair<int,int> > D1_CRS( { {225,8},{241,10} } );
const double D1_CRS_LSB = TWO_N6;
const std::vector<std::pair<int,int> > D1_SQRT_A( { {251,12},{271,20} } );
const double D1_SQRT_A_LSB = TWO_N19;
const std::vector<std::pair<int,int> > D1_TOE( { {291,2} } );
const double D1_TOE_LSB = TWO_P3;
//SUBFRAME 3
const std::vector<std::pair<int,int> > D1_TOE_MSB2( { {43,10},{61,5} } );
const std::vector<std::pair<int,int> > D1_I0( { {66,17},{91,15} } );
const double D1_I0_LSB = PI_TWO_N31;
const std::vector<std::pair<int,int> > D1_CIC( { {106,7},{121,11} } );
const double D1_CIC_LSB = TWO_N31;
const std::vector<std::pair<int,int> > D1_OMEGA_DOT( { {132,11},{151,13} } );
const double D1_OMEGA_DOT_LSB = PI_TWO_N43;
const std::vector<std::pair<int,int> > D1_CIS( { {164,9},{181,9} } );
const double D1_CIS_LSB = TWO_N31;
const std::vector<std::pair<int,int> > D1_IDOT( { {190,13},{211,1} } );
const double D1_IDOT_LSB = PI_TWO_N43;
const std::vector<std::pair<int,int> > D1_OMEGA0( { {212,21},{241,11} } );
const double D1_OMEGA0_LSB = PI_TWO_N31;
const std::vector<std::pair<int,int> > D1_OMEGA( { {252,11},{271,21} } );
const double D1_OMEGA_LSB = PI_TWO_N31;
//SUBFRAME 4 AND PAGES 1 THROUGH 6 IN SUBFRAME 5
const std::vector<std::pair<int,int> > D1_SQRT_A_ALMANAC( { {51,2},{61,22} } );
const double D1_SQRT_A_ALMANAC_LSB = TWO_N11;
const std::vector<std::pair<int,int> > D1_A1_ALMANAC( { {91,11} } );
const double D1_A1_ALMANAC_LSB = TWO_N38;
const std::vector<std::pair<int,int> > D1_A0_ALMANAC( { {102,11} } );
const double D1_A0_ALMANAC_LSB = TWO_N20;
const std::vector<std::pair<int,int> > D1_OMEGA0_ALMANAC( { {121,22},{151,2} } );
const double D1_OMEGA0_ALMANAC_LSB = PI_TWO_N23;
const std::vector<std::pair<int,int> > D1_E_ALMANAC( { {153,17} } );
const double D1_E_ALMANAC_LSB = TWO_N21;
const std::vector<std::pair<int,int> > D1_DELTA_I( { {170,3},{181,13} } );
const double D1_DELTA_I_LSB = PI_TWO_N19;
const std::vector<std::pair<int,int> > D1_TOA( { {194,8} } );
const double D1_TOA_LSB = TWO_P12;
const std::vector<std::pair<int,int> > D1_OMEGA_DOT_ALMANAC( { {202,1}, {211,16} } );
const double D1_OMEGA_DOT_ALMANAC_LSB = PI_TWO_N38;
const std::vector<std::pair<int,int> > D1_OMEGA_ALMANAC( { {227,6},{241,18} } );
const double D1_OMEGA_ALMANAC_LSB = PI_TWO_N23;
const std::vector<std::pair<int,int> > D1_M0_ALMANAC( { {259,4},{271,20} } );
const double D1_M0_ALMANAC_LSB = PI_TWO_N23;
//SUBFRAME 5 PAGE 7
const std::vector<std::pair<int,int> > D1_HEA1( { {51,2},{61,7} } );
const std::vector<std::pair<int,int> > D1_HEA2( { {68,9} } );
const std::vector<std::pair<int,int> > D1_HEA3( { {77,6},{91,3} } );
const std::vector<std::pair<int,int> > D1_HEA4( { {94,9} } );
const std::vector<std::pair<int,int> > D1_HEA5( { {103,9} } );
const std::vector<std::pair<int,int> > D1_HEA6( { {112,1},{121,8} } );
const std::vector<std::pair<int,int> > D1_HEA7( { {129,9} } );
const std::vector<std::pair<int,int> > D1_HEA8( { {138,5},{151,4} } );
const std::vector<std::pair<int,int> > D1_HEA9( { {155,9} } );
const std::vector<std::pair<int,int> > D1_HEA10( { {164,9} } );
const std::vector<std::pair<int,int> > D1_HEA11( { {181,9} } );
const std::vector<std::pair<int,int> > D1_HEA12( { {190,9} } );
const std::vector<std::pair<int,int> > D1_HEA13( { {199,4},{211,5} } );
const std::vector<std::pair<int,int> > D1_HEA14( { {216,9} } );
const std::vector<std::pair<int,int> > D1_HEA15( { {225,8},{241,1} } );
const std::vector<std::pair<int,int> > D1_HEA16( { {242,9} } );
const std::vector<std::pair<int,int> > D1_HEA17( { {251,9} } );
const std::vector<std::pair<int,int> > D1_HEA18( { {260,3},{271,6} } );
const std::vector<std::pair<int,int> > D1_HEA19( { {277,9} } );
//SUBFRAME 5 PAGE 8
const std::vector<std::pair<int,int> > D1_HEA20( { {51,2},{61,7} } );
const std::vector<std::pair<int,int> > D1_HEA21( { {68,9} } );
const std::vector<std::pair<int,int> > D1_HEA22( { {77,6},{91,3} } );
const std::vector<std::pair<int,int> > D1_HEA23( { {94,9} } );
const std::vector<std::pair<int,int> > D1_HEA24( { {103,9} } );
const std::vector<std::pair<int,int> > D1_HEA25( { {112,1},{121,8} } );
const std::vector<std::pair<int,int> > D1_HEA26( { {129,9} } );
const std::vector<std::pair<int,int> > D1_HEA27( { {138,5},{151,4} } );
const std::vector<std::pair<int,int> > D1_HEA28( { {155,9} } );
const std::vector<std::pair<int,int> > D1_HEA29( { {164,9} } );
const std::vector<std::pair<int,int> > D1_HEA30( { {181,9} } );
const std::vector<std::pair<int,int> > D1_WNA( { {190,8} } );
const std::vector<std::pair<int,int> > D1_TOA2( { {198,5},{211,3} } );
//SUBFRAME 5 PAGE 9
const std::vector<std::pair<int,int> > D1_A0GPS( { {97,14} } );
const double D1_A0GPS_LSB = 0.1;
const std::vector<std::pair<int,int> > D1_A1GPS( { {111,2},{121,14} } );
const double D1_A1GPS_LSB = 0.1;
const std::vector<std::pair<int,int> > D1_A0GAL( { {135,8},{151,6} } );
const double D1_A0GAL_LSB = 0.1;
const std::vector<std::pair<int,int> > D1_A1GAL( { {157,16} } );
const double D1_A1GAL_LSB = 0.1;
const std::vector<std::pair<int,int> > D1_A0GLO( { {181,14} } );
const double D1_A0GLO_LSB = 0.1;
const std::vector<std::pair<int,int> > D1_A1GLO( { {195,8},{211,8} } );
const double D1_A1GLO_LSB = 0.1;
//SUBFRAME 5 PAGE 10
const std::vector<std::pair<int,int> > D1_DELTA_T_LS( { {51,2},{61,6} } );
const std::vector<std::pair<int,int> > D1_DELTA_T_LSF( { {67,8} } );
const std::vector<std::pair<int,int> > D1_WN_LSF( { {75,8} } );
const std::vector<std::pair<int,int> > D1_A0UTC( { {91,22},{121,10} } );
const double D1_A0UTC_LSB = TWO_N30;
const std::vector<std::pair<int,int> > D1_A1UTC( { {131,12},{151,12} } );
const double D1_A1UTC_LSB = TWO_N50;
const std::vector<std::pair<int,int> > D1_DN( { {163,8} } );
#endif /* GNSS_SDR_BEIDOU_B1I_H_ */

View File

@ -32,6 +32,11 @@ set(SYSTEM_PARAMETERS_SOURCES
galileo_almanac.cc
galileo_iono.cc
galileo_navigation_message.cc
beidou_dnav_navigation_message.cc
beidou_dnav_ephemeris.cc
beidou_dnav_iono.cc
beidou_dnav_almanac.cc
beidou_dnav_utc_model.cc
sbas_ephemeris.cc
galileo_fnav_message.cc
gps_cnav_ephemeris.cc
@ -72,6 +77,11 @@ set(SYSTEM_PARAMETERS_HEADERS
glonass_gnav_almanac.h
glonass_gnav_utc_model.h
glonass_gnav_navigation_message.h
beidou_dnav_navigation_message.h
beidou_dnav_ephemeris.h
beidou_dnav_iono.h
beidou_dnav_almanac.h
beidou_dnav_utc_model.h
display.h
Galileo_E1.h
Galileo_E5a.h
@ -83,6 +93,7 @@ set(SYSTEM_PARAMETERS_HEADERS
GPS_L1_CA.h
GPS_L2C.h
GPS_L5.h
Beidou_B1I.h
MATH_CONSTANTS.h
)

View File

@ -46,6 +46,7 @@
const double PI = 3.1415926535897932; //!< pi
const double PI_2 = 2.0 * PI; //!< 2 * pi
const double TWO_P3 = (8); //!< 2^3
const double TWO_P4 = (16); //!< 2^4
const double TWO_P11 = (2048); //!< 2^11
const double TWO_P12 = (4096); //!< 2^12
@ -97,6 +98,7 @@ const double TWO_N55 = (2.775557561562891e-017); //!< 2^-55
const double TWO_N57 = (6.938893903907228e-18); //!< 2^-57
const double TWO_N59 = (1.73472347597681e-018); //!< 2^-59
const double TWO_N60 = (8.673617379884036e-19); //!< 2^-60
const double TWO_N66 = (1.3552527156068805425093160010874271392822265625e-20); //!< 2^-66
const double TWO_N68 = (3.388131789017201e-21); //!< 2^-68

View File

@ -0,0 +1,49 @@
/*!
* \file gps_almanac.cc
* \brief Interface of a BEIDOU ALMANAC storage
*
* See http://www.gps.gov/technical/icwg/IS-GPS-200E.pdf Appendix II
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#include "beidou_dnav_almanac.h"
Beidou_Almanac::Beidou_Almanac()
{
i_satellite_PRN = 0;
d_Delta_i = 0.0;
d_Toa = 0.0;
d_M_0 = 0.0;
d_e_eccentricity = 0.0;
d_sqrt_A = 0.0;
d_OMEGA0 = 0.0;
d_OMEGA = 0.0;
d_OMEGA_DOT = 0.0;
i_SV_health = 0;
d_A_f0 = 0.0;
d_A_f1 = 0.0;
}

View File

@ -0,0 +1,63 @@
/*!
* \file gps_almanac.h
* \brief Interface of a GPS ALMANAC storage
* \author Javier Arribas, 2013. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_DNAV_ALMANAC_H_
#define GNSS_SDR_BEIDOU_DNAV_ALMANAC_H_
/*!
* \brief This class is a storage for the GPS SV ALMANAC data as described in IS-GPS-200E
*
* See http://www.gps.gov/technical/icwg/IS-GPS-200E.pdf Appendix II
*/
class Beidou_Almanac
{
public:
unsigned int i_satellite_PRN; //!< SV PRN NUMBER
double d_Delta_i;
double d_Toa; //!< Almanac data reference time of week (Ref. 20.3.3.4.3 IS-GPS-200E) [s]
double d_M_0; //!< Mean Anomaly at Reference Time [semi-circles]
double d_e_eccentricity; //!< Eccentricity [dimensionless]
double d_sqrt_A; //!< Square Root of the Semi-Major Axis [sqrt(m)]
double d_OMEGA0; //!< Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles]
double d_OMEGA; //!< Argument of Perigee [semi-cicles]
double d_OMEGA_DOT; //!< Rate of Right Ascension [semi-circles/s]
int i_SV_health; // SV Health
double d_A_f0; //!< Coefficient 0 of code phase offset model [s]
double d_A_f1; //!< Coefficient 1 of code phase offset model [s/s]
/*!
* Default constructor
*/
Beidou_Almanac();
};
#endif

View File

@ -0,0 +1,281 @@
/*!
* \file beidou_ephemeris.cc
* \brief Interface of a BeiDou EPHEMERIS storage and orbital model functions
*
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "beidou_dnav_ephemeris.h"
#include <cmath>
#include "Beidou_B1I.h"
#include "gnss_satellite.h"
Beidou_Ephemeris::Beidou_Ephemeris()
{
i_satellite_PRN = 0;
d_TOW = 0;
d_Crs = 0;
d_Delta_n = 0;
d_M_0 = 0;
d_Cuc = 0;
d_e_eccentricity = 0;
d_Cus = 0;
d_sqrt_A = 0;
d_Toe = 0;
d_Toc = 0;
d_Cic = 0;
d_OMEGA0 = 0;
d_Cis = 0;
d_i_0 = 0;
d_Crc = 0;
d_OMEGA = 0;
d_OMEGA_DOT = 0;
d_IDOT = 0;
i_BEIDOU_week = 0;
i_SV_accuracy = 0;
i_SV_health = 0;
d_AODE = 0;
d_TGD1 = 0;
d_TGD2 = 0;
d_AODC = 0; // Issue of Data, Clock
i_AODO = 0; // Age of Data Offset (AODO) term for the navigation message correction table (NMCT) contained in subframe 4 (reference paragraph 20.3.3.5.1.9) [s]
d_AODC = 0;
b_fit_interval_flag = false; // indicates the curve-fit interval used by the CS (Block II/IIA/IIR/IIR-M/IIF) and SS (Block IIIA) in determining the ephemeris parameters, as follows: 0 = 4 hours, 1 = greater than 4 hours.
d_spare1 = 0;
d_spare2 = 0;
d_A_f0 = 0; // Coefficient 0 of code phase offset model [s]
d_A_f1 = 0; // Coefficient 1 of code phase offset model [s/s]
d_A_f2 = 0; // Coefficient 2 of code phase offset model [s/s^2]
b_integrity_status_flag = false;
b_alert_flag = false; // If true, indicates that the SV URA may be worse than indicated in d_SV_accuracy, use that SV at our own risk.
b_antispoofing_flag = false; // If true, the AntiSpoofing mode is ON in that SV
auto gnss_sat = Gnss_Satellite();
std::string _system ("Beidou");
for(unsigned int i = 1; i < 36; i++)
{
satelliteBlock[i] = gnss_sat.what_block(_system, i);
}
d_satClkDrift = 0.0;
d_dtr = 0.0;
d_satpos_X = 0.0;
d_satpos_Y = 0.0;
d_satpos_Z = 0.0;
d_satvel_X = 0.0;
d_satvel_Y = 0.0;
d_satvel_Z = 0.0;
}
double Beidou_Ephemeris::check_t(double time)
{
double corrTime;
double half_week = 302400.0; // seconds
corrTime = time;
if (time > half_week)
{
corrTime = time - 2.0 * half_week;
}
else if (time < -half_week)
{
corrTime = time + 2.0 * half_week;
}
return corrTime;
}
// 20.3.3.3.3.1 User Algorithm for SV Clock Correction.
double Beidou_Ephemeris::sv_clock_drift(double transmitTime)
{
double dt;
dt = check_t(transmitTime - d_Toc);
for (int i = 0; i < 2; i++)
{
dt -= d_A_f0 + d_A_f1 * dt + d_A_f2 * (dt * dt);
}
d_satClkDrift = d_A_f0 + d_A_f1 * dt + d_A_f2 * (dt * dt);
return d_satClkDrift;
}
// compute the relativistic correction term
double Beidou_Ephemeris::sv_clock_relativistic_term(double transmitTime)
{
double tk;
double a;
double n;
double n0;
double E;
double E_old;
double dE;
double M;
// Restore semi-major axis
a = d_sqrt_A * d_sqrt_A;
// Time from ephemeris reference epoch
tk = check_t(transmitTime - d_Toe);
// Computed mean motion
n0 = sqrt(BEIDOU_GM / (a * a * a));
// Corrected mean motion
n = n0 + d_Delta_n;
// Mean anomaly
M = d_M_0 + n * tk;
// Reduce mean anomaly to between 0 and 2pi
M = fmod((M + 2.0 * BEIDOU_PI), (2.0 * BEIDOU_PI));
// Initial guess of eccentric anomaly
E = M;
// --- Iteratively compute eccentric anomaly ----------------------------
for (int ii = 1; ii < 20; ii++)
{
E_old = E;
E = M + d_e_eccentricity * sin(E);
dE = fmod(E - E_old, 2.0 * BEIDOU_PI);
if (fabs(dE) < 1e-12)
{
//Necessary precision is reached, exit from the loop
break;
}
}
// Compute relativistic correction term
d_dtr = BEIDOU_F * d_e_eccentricity * d_sqrt_A * sin(E);
return d_dtr;
}
double Beidou_Ephemeris::satellitePosition(double transmitTime)
{
double tk;
double a;
double n;
double n0;
double M;
double E;
double E_old;
double dE;
double nu;
double phi;
double u;
double r;
double i;
double Omega;
// Find satellite's position ----------------------------------------------
// Restore semi-major axis
a = d_sqrt_A * d_sqrt_A;
// Time from ephemeris reference epoch
tk = check_t(transmitTime - d_Toe);
// Computed mean motion
n0 = sqrt(BEIDOU_GM / (a * a * a));
// Corrected mean motion
n = n0 + d_Delta_n;
// Mean anomaly
M = d_M_0 + n * tk;
// Reduce mean anomaly to between 0 and 2pi
M = fmod((M + 2.0 * BEIDOU_PI), (2.0 * BEIDOU_PI));
// Initial guess of eccentric anomaly
E = M;
// --- Iteratively compute eccentric anomaly ----------------------------
for (int ii = 1; ii < 20; ii++)
{
E_old = E;
E = M + d_e_eccentricity * sin(E);
dE = fmod(E - E_old, 2.0 * BEIDOU_PI);
if (fabs(dE) < 1e-12)
{
//Necessary precision is reached, exit from the loop
break;
}
}
// Compute the true anomaly
double tmp_Y = sqrt(1.0 - d_e_eccentricity * d_e_eccentricity) * sin(E);
double tmp_X = cos(E) - d_e_eccentricity;
nu = atan2(tmp_Y, tmp_X);
// Compute angle phi (argument of Latitude)
phi = nu + d_OMEGA;
// Reduce phi to between 0 and 2*pi rad
phi = fmod((phi), (2.0 * BEIDOU_PI));
// Correct argument of latitude
u = phi + d_Cuc * cos(2.0 * phi) + d_Cus * sin(2.0 * phi);
// Correct radius
r = a * (1.0 - d_e_eccentricity*cos(E)) + d_Crc * cos(2.0 * phi) + d_Crs * sin(2.0 * phi);
// Correct inclination
i = d_i_0 + d_IDOT * tk + d_Cic * cos(2.0 * phi) + d_Cis * sin(2.0 * phi);
// Compute the angle between the ascending node and the Greenwich meridian
Omega = d_OMEGA0 + (d_OMEGA_DOT - BEIDOU_OMEGA_EARTH_DOT)*tk - BEIDOU_OMEGA_EARTH_DOT * d_Toe;
// Reduce to between 0 and 2*pi rad
Omega = fmod((Omega + 2.0 * BEIDOU_PI), (2.0 * BEIDOU_PI));
// --- Compute satellite coordinates in Earth-fixed coordinates
d_satpos_X = cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega);
d_satpos_Y = cos(u) * r * sin(Omega) + sin(u) * r * cos(i) * cos(Omega);
d_satpos_Z = sin(u) * r * sin(i);
// Satellite's velocity. Can be useful for Vector Tracking loops
double Omega_dot = d_OMEGA_DOT - BEIDOU_OMEGA_EARTH_DOT;
d_satvel_X = - Omega_dot * (cos(u) * r + sin(u) * r * cos(i)) + d_satpos_X * cos(Omega) - d_satpos_Y * cos(i) * sin(Omega);
d_satvel_Y = Omega_dot * (cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega)) + d_satpos_X * sin(Omega) + d_satpos_Y * cos(i) * cos(Omega);
d_satvel_Z = d_satpos_Y * sin(i);
// Time from ephemeris reference clock
tk = check_t(transmitTime - d_Toc);
double dtr_s = d_A_f0 + d_A_f1 * tk + d_A_f2 * tk * tk;
/* relativity correction */
dtr_s -= 2.0 * sqrt(BEIDOU_GM * a) * d_e_eccentricity * sin(E) / (BEIDOU_C_m_s * BEIDOU_C_m_s);
return dtr_s;
}

View File

@ -0,0 +1,205 @@
/*!
* \file beidou_ephemeris.h
* \brief Interface of a BEIDOU EPHEMERIS storage
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_EPHEMERIS_H_
#define GNSS_SDR_BEIDOU_EPHEMERIS_H_
#include <map>
#include <string>
#include "boost/assign.hpp"
#include <boost/serialization/nvp.hpp>
/*!
* \brief This class is a storage and orbital model functions for the GPS SV ephemeris data as described in IS-GPS-200E
*
* See http://www.gps.gov/technical/icwg/IS-GPS-200E.pdf Appendix II
*/
class Beidou_Ephemeris
{
private:
/*
* Accounts for the beginning or end of week crossover
*
* See paragraph 20.3.3.3.3.1 (IS-GPS-200E)
* \param[in] - time in seconds
* \param[out] - corrected time, in seconds
*/
double check_t(double time);
public:
unsigned int i_satellite_PRN; // SV PRN NUMBER
double d_TOW; //!< Time of BEIDOU Week of the ephemeris set (taken from subframes TOW) [s]
double d_Crs; //!< Amplitude of the Sine Harmonic Correction Term to the Orbit Radius [m]
double d_Delta_n; //!< Mean Motion Difference From Computed Value [semi-circles/s]
double d_M_0; //!< Mean Anomaly at Reference Time [semi-circles]
double d_Cuc; //!< Amplitude of the Cosine Harmonic Correction Term to the Argument of Latitude [rad]
double d_e_eccentricity; //!< Eccentricity [dimensionless]
double d_Cus; //!< Amplitude of the Sine Harmonic Correction Term to the Argument of Latitude [rad]
double d_sqrt_A; //!< Square Root of the Semi-Major Axis [sqrt(m)]
double d_Toe; //!< Ephemeris data reference time of week (Ref. 20.3.3.4.3 IS-GPS-200E) [s]
double d_Toc; //!< clock data reference time (Ref. 20.3.3.3.3.1 IS-GPS-200E) [s]
double d_Cic; //!< Amplitude of the Cosine Harmonic Correction Term to the Angle of Inclination [rad]
double d_OMEGA0; //!< Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles]
double d_Cis; //!< Amplitude of the Sine Harmonic Correction Term to the Angle of Inclination [rad]
double d_i_0; //!< Inclination Angle at Reference Time [semi-circles]
double d_Crc; //!< Amplitude of the Cosine Harmonic Correction Term to the Orbit Radius [m]
double d_OMEGA; //!< Argument of Perigee [semi-cicles]
double d_OMEGA_DOT; //!< Rate of Right Ascension [semi-circles/s]
double d_IDOT; //!< Rate of Inclination Angle [semi-circles/s]
int i_BEIDOU_week; //!< BEIDOU week number, aka WN [week]
int i_SV_accuracy; //!< User Range Accuracy (URA) index of the SV (reference paragraph 6.2.1) for the standard positioning service user (Ref 20.3.3.3.1.3 IS-GPS-200E)
int i_SV_health;
double d_TGD1; //!< Estimated Group Delay Differential on B1I [s]
double d_TGD2; //!< Estimated Group Delay Differential on B2I [s]
double d_AODC; //!< Age of Data, Clock
double d_AODE; //!< Age of Data, Ephemeris
int i_AODO; //!< Age of Data Offset (AODO) term for the navigation message correction table (NMCT) contained in subframe 4 (reference paragraph 20.3.3.5.1.9) [s]
bool b_fit_interval_flag;//!< indicates the curve-fit interval used by the CS (Block II/IIA/IIR/IIR-M/IIF) and SS (Block IIIA) in determining the ephemeris parameters, as follows: 0 = 4 hours, 1 = greater than 4 hours.
double d_spare1;
double d_spare2;
double d_A_f0; //!< Coefficient 0 of code phase offset model [s]
double d_A_f1; //!< Coefficient 1 of code phase offset model [s/s]
double d_A_f2; //!< Coefficient 2 of code phase offset model [s/s^2]
// Flags
/*! \brief If true, enhanced level of integrity assurance.
*
* If false, indicates that the conveying signal is provided with the legacy level of integrity assurance.
* That is, the probability that the instantaneous URE of the conveying signal exceeds 4.42 times the upper bound
* value of the current broadcast URA index, for more than 5.2 seconds, without an accompanying alert, is less
* than 1E-5 per hour. If true, indicates that the conveying signal is provided with an enhanced level of
* integrity assurance. That is, the probability that the instantaneous URE of the conveying signal exceeds 5.73
* times the upper bound value of the current broadcast URA index, for more than 5.2 seconds, without an
* accompanying alert, is less than 1E-8 per hour.
*/
bool b_integrity_status_flag;
bool b_alert_flag; //!< If true, indicates that the SV URA may be worse than indicated in d_SV_accuracy, use that SV at our own risk.
bool b_antispoofing_flag; //!< If true, the AntiSpoofing mode is ON in that SV
// clock terms derived from ephemeris data
double d_satClkDrift; //!< GPS clock error
double d_dtr; //!< relativistic clock correction term
// satellite positions
double d_satpos_X; //!< Earth-fixed coordinate x of the satellite [m]. Intersection of the IERS Reference Meridian (IRM) and the plane passing through the origin and normal to the Z-axis.
double d_satpos_Y; //!< Earth-fixed coordinate y of the satellite [m]. Completes a right-handed, Earth-Centered, Earth-Fixed orthogonal coordinate system.
double d_satpos_Z; //!< Earth-fixed coordinate z of the satellite [m]. The direction of the IERS (International Earth Rotation and Reference Systems Service) Reference Pole (IRP).
// Satellite velocity
double d_satvel_X; //!< Earth-fixed velocity coordinate x of the satellite [m]
double d_satvel_Y; //!< Earth-fixed velocity coordinate y of the satellite [m]
double d_satvel_Z; //!< Earth-fixed velocity coordinate z of the satellite [m]
std::map<int,std::string> satelliteBlock; //!< Map that stores to which block the PRN belongs http://www.navcen.uscg.gov/?Do=constellationStatus
template<class Archive>
/*!
* \brief Serialize is a boost standard method to be called by the boost XML serialization. Here is used to save the ephemeris data on disk file.
*/
void serialize(Archive& archive, const unsigned int version)
{
using boost::serialization::make_nvp;
if(version){};
archive & make_nvp("i_satellite_PRN", i_satellite_PRN); // SV PRN NUMBER
archive & make_nvp("d_TOW", d_TOW); //!< Time of GPS Week of the ephemeris set (taken from subframes TOW) [s]
archive & make_nvp("d_AODE", d_AODE);
archive & make_nvp("d_Crs", d_Crs); //!< Amplitude of the Sine Harmonic Correction Term to the Orbit Radius [m]
archive & make_nvp("d_Delta_n", d_Delta_n); //!< Mean Motion Difference From Computed Value [semi-circles/s]
archive & make_nvp("d_M_0", d_M_0); //!< Mean Anomaly at Reference Time [semi-circles]
archive & make_nvp("d_Cuc", d_Cuc); //!< Amplitude of the Cosine Harmonic Correction Term to the Argument of Latitude [rad]
archive & make_nvp("d_e_eccentricity", d_e_eccentricity); //!< Eccentricity [dimensionless]
archive & make_nvp("d_Cus", d_Cus); //!< Amplitude of the Sine Harmonic Correction Term to the Argument of Latitude [rad]
archive & make_nvp("d_sqrt_A", d_sqrt_A); //!< Square Root of the Semi-Major Axis [sqrt(m)]
archive & make_nvp("d_Toe", d_Toe); //!< Ephemeris data reference time of week (Ref. 20.3.3.4.3 IS-GPS-200E) [s]
archive & make_nvp("d_Toc", d_Toe); //!< clock data reference time (Ref. 20.3.3.3.3.1 IS-GPS-200E) [s]
archive & make_nvp("d_Cic", d_Cic); //!< Amplitude of the Cosine Harmonic Correction Term to the Angle of Inclination [rad]
archive & make_nvp("d_OMEGA0", d_OMEGA0); //!< Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles]
archive & make_nvp("d_Cis", d_Cis); //!< Amplitude of the Sine Harmonic Correction Term to the Angle of Inclination [rad]
archive & make_nvp("d_i_0", d_i_0); //!< Inclination Angle at Reference Time [semi-circles]
archive & make_nvp("d_Crc", d_Crc); //!< Amplitude of the Cosine Harmonic Correction Term to the Orbit Radius [m]
archive & make_nvp("d_OMEGA", d_OMEGA); //!< Argument of Perigee [semi-cicles]
archive & make_nvp("d_OMEGA_DOT", d_OMEGA_DOT); //!< Rate of Right Ascension [semi-circles/s]
archive & make_nvp("d_IDOT", d_IDOT); //!< Rate of Inclination Angle [semi-circles/s]
archive & make_nvp("i_BEIDOU_week", i_BEIDOU_week); //!< GPS week number, aka WN [week]
archive & make_nvp("i_SV_accuracy", i_SV_accuracy); //!< User Range Accuracy (URA) index of the SV (reference paragraph 6.2.1) for the standard positioning service user (Ref 20.3.3.3.1.3 IS-GPS-200E)
archive & make_nvp("i_SV_health", i_SV_health);
archive & make_nvp("d_AODC", d_AODC); //!< Issue of Data, Clock
archive & make_nvp("d_TGD1", d_TGD1); //!< Estimated Group Delay Differential: L1-L2 correction term only for the benefit of "L1 P(Y)" or "L2 P(Y)" s users [s]
archive & make_nvp("d_TGD2", d_TGD2); //!< Estimated Group Delay Differential: L1-L2 correction term only for the benefit of "L1 P(Y)" or "L2 P(Y)" s users [s]
archive & make_nvp("i_AODO", i_AODO); //!< Age of Data Offset (AODO) term for the navigation message correction table (NMCT) contained in subframe 4 (reference paragraph 20.3.3.5.1.9) [s]
archive & make_nvp("b_fit_interval_flag", b_fit_interval_flag);//!< indicates the curve-fit interval used by the CS (Block II/IIA/IIR/IIR-M/IIF) and SS (Block IIIA) in determining the ephemeris parameters, as follows: 0 = 4 hours, 1 = greater than 4 hours.
archive & make_nvp("d_spare1", d_spare1);
archive & make_nvp("d_spare2", d_spare2);
archive & make_nvp("d_A_f0", d_A_f0); //!< Coefficient 0 of code phase offset model [s]
archive & make_nvp("d_A_f1", d_A_f1); //!< Coefficient 1 of code phase offset model [s/s]
archive & make_nvp("d_A_f2", d_A_f2); //!< Coefficient 2 of code phase offset model [s/s^2]
archive & make_nvp("b_integrity_status_flag", b_integrity_status_flag);
archive & make_nvp("b_alert_flag", b_alert_flag); //!< If true, indicates that the SV URA may be worse than indicated in d_SV_accuracy, use that SV at our own risk.
archive & make_nvp("b_antispoofing_flag", b_antispoofing_flag); //!< If true, the AntiSpoofing mode is ON in that SV
}
/*!
* \brief Compute the ECEF SV coordinates and ECEF velocity
* Implementation of Table 20-IV (IS-GPS-200E)
* and compute the clock bias term including relativistic effect (return value)
*/
double satellitePosition(double transmitTime);
/*!
* \brief Sets (\a d_satClkDrift)and returns the clock drift in seconds according to the User Algorithm for SV Clock Correction
* (IS-GPS-200E, 20.3.3.3.3.1)
*/
double sv_clock_drift(double transmitTime);
/*!
* \brief Sets (\a d_dtr) and returns the clock relativistic correction term in seconds according to the User Algorithm for SV Clock Correction
* (IS-GPS-200E, 20.3.3.3.3.1)
*/
double sv_clock_relativistic_term(double transmitTime);
/*!
* Default constructor
*/
Beidou_Ephemeris();
};
#endif

View File

@ -0,0 +1,46 @@
/*!
* \file beidou_iono.cc
* \brief Interface of a BEIDOU IONOSPHERIC MODEL storage
*
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "beidou_dnav_iono.h"
Beidou_Iono::Beidou_Iono()
{
valid = false;
d_alpha0 = 0.0;
d_alpha1 = 0.0;
d_alpha2 = 0.0;
d_alpha3 = 0.0;
d_beta0 = 0.0;
d_beta1 = 0.0;
d_beta2 = 0.0;
d_beta3 = 0.0;
}

View File

@ -0,0 +1,80 @@
/*!
* \file beidou_iono.h
* \brief Interface of a BEIDOU IONOSPHERIC MODEL storage
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_IONO_H_
#define GNSS_SDR_BEIDOU_IONO_H_
#include "boost/assign.hpp"
#include <boost/serialization/nvp.hpp>
/*!
* \brief This class is a storage for the BEIDOU IONOSPHERIC data as described in ICD v2.1
*
*/
class Beidou_Iono
{
public:
bool valid; //!< Valid flag
// Ionospheric parameters
double d_alpha0; //!< Coefficient 0 of a cubic equation representing the amplitude of the vertical delay [s]
double d_alpha1; //!< Coefficient 1 of a cubic equation representing the amplitude of the vertical delay [s/semi-circle]
double d_alpha2; //!< Coefficient 2 of a cubic equation representing the amplitude of the vertical delay [s(semi-circle)^2]
double d_alpha3; //!< Coefficient 3 of a cubic equation representing the amplitude of the vertical delay [s(semi-circle)^3]
double d_beta0; //!< Coefficient 0 of a cubic equation representing the period of the model [s]
double d_beta1; //!< Coefficient 1 of a cubic equation representing the period of the model [s/semi-circle]
double d_beta2; //!< Coefficient 2 of a cubic equation representing the period of the model [s(semi-circle)^2]
double d_beta3; //!< Coefficient 3 of a cubic equation representing the period of the model [s(semi-circle)^3]
Beidou_Iono(); //!< Default constructor
template<class Archive>
/*!
* \brief Serialize is a boost standard method to be called by the boost XML serialization. Here is used to save the ephemeris data on disk file.
*/
void serialize(Archive& archive, const unsigned int version)
{
using boost::serialization::make_nvp;
if(version){};
archive & make_nvp("d_alpha0",d_alpha0);
archive & make_nvp("d_alpha1",d_alpha1);
archive & make_nvp("d_alpha2",d_alpha2);
archive & make_nvp("d_alpha3",d_alpha3);
archive & make_nvp("d_beta0",d_beta0);
archive & make_nvp("d_beta1",d_beta1);
archive & make_nvp("d_beta2",d_beta2);
archive & make_nvp("d_beta3",d_beta3);
}
};
#endif

View File

@ -0,0 +1,947 @@
/*!
m * \file beidou_navigation_message.cc
* \brief Implementation of a BeiDou D1 NAV Data message decoder as described in BeiDou ICD Version 2.1
*
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "beidou_dnav_navigation_message.h"
#include <cmath>
#include <iostream>
#include <gnss_satellite.h>
void Beidou_Navigation_Message_D1::reset()
{
b_valid_ephemeris_set_flag = false;
d_SOW = 0;
d_SOW_SF1 = 0;
d_SOW_SF2 = 0;
d_SOW_SF3 = 0;
d_SOW_SF4 = 0;
d_SOW_SF5 = 0;
d_AODE = 0;
d_Crs = 0;
d_Delta_n = 0;
d_M_0 = 0;
d_Cuc = 0;
d_e_eccentricity = 0;
d_Cus = 0;
d_sqrt_A = 0;
d_Toe = 0;
d_Toc = 0;
d_Cic = 0;
d_OMEGA0 = 0;
d_Cis = 0;
d_i_0 = 0;
d_Crc = 0;
d_OMEGA = 0;
d_OMEGA_DOT = 0;
d_IDOT = 0;
i_BEIDOU_week = 0;
i_SV_accuracy = 0;
i_SV_health = 0;
d_TGD1 = 0;
d_TGD2 = 0;
d_AODC = -1;
// i_AODO = 0;
b_fit_interval_flag = false;
d_spare1 = 0;
d_spare2 = 0;
d_A_f0 = 0;
d_A_f1 = 0;
d_A_f2 = 0;
//clock terms
//d_master_clock=0;
d_dtr = 0;
d_satClkCorr = 0;
d_satClkDrift = 0;
// satellite positions
d_satpos_X = 0;
d_satpos_Y = 0;
d_satpos_Z = 0;
// info
i_channel_ID = 0;
i_satellite_PRN = 0;
// time synchro
d_subframe_timestamp_ms = 0;
// flags
b_alert_flag = false;
b_integrity_status_flag = false;
b_antispoofing_flag = false;
// Ionosphere and UTC
flag_iono_valid = false;
flag_utc_model_valid = false;
d_alpha0 = 0;
d_alpha1 = 0;
d_alpha2 = 0;
d_alpha3 = 0;
d_beta0 = 0;
d_beta1 = 0;
d_beta2 = 0;
d_beta3 = 0;
d_A1UTC = 0;
d_A0UTC = 0;
d_t_OT = 0;
i_WN_T = 0;
d_DeltaT_LS = 0;
i_WN_LSF = 0;
i_DN = 0;
d_DeltaT_LSF= 0;
//Almanac
d_Toa = 0;
i_WN_A = 0;
for (int i=1; i < 36; i++ )
{
almanacHealth[i] = 0;
}
// Satellite velocity
d_satvel_X = 0;
d_satvel_Y = 0;
d_satvel_Z = 0;
d_A1GPS = 0;
d_A0GPS = 0;
d_A1GAL = 0;
d_A0GAL = 0;
d_A1GLO = 0;
d_A0GLO = 0;
d_AODE_SF1 = 0;
d_SQRT_A_ALMANAC = 0;
d_A1_ALMANAC = 0;
d_A0_ALMANAC = 0;
d_OMEGA0_ALMANAC = 0;
d_E_ALMANAC = 0;
d_DELTA_I = 0;
d_TOA = 0;
d_OMEGA_DOT_ALMANAC = 0;
d_OMEGA_ALMANAC = 0;
d_M0_ALMANAC = 0;
almanac_WN = 0;
d_toa2 = 0;
d_a0 = 0;
d_a1 = 0;
d_a2 = 0;
auto gnss_sat = Gnss_Satellite();
std::string _system ("Beidou");
for(unsigned int i = 1; i < 36; i++)
{
satelliteBlock[i] = gnss_sat.what_block(_system, i);
}
}
Beidou_Navigation_Message_D1::Beidou_Navigation_Message_D1()
{
reset();
}
void Beidou_Navigation_Message_D1::print_beidou_word_bytes(unsigned int BEIDOU_word)
{
std::cout << " Word =";
std::cout << std::bitset<32>(BEIDOU_word);
std::cout << std::endl;
}
bool Beidou_Navigation_Message_D1::read_navigation_bool(std::bitset<BEIDOU_SUBFRAME_BITS> bits, const std::vector<std::pair<int,int>> parameter)
{
bool value;
if (bits[BEIDOU_SUBFRAME_BITS - parameter[0].first] == 1)
{
value = true;
}
else
{
value = false;
}
return value;
}
unsigned long int Beidou_Navigation_Message_D1::read_navigation_unsigned(std::bitset<BEIDOU_SUBFRAME_BITS> bits, const std::vector<std::pair<int,int>> parameter)
{
unsigned long int value = 0;
int num_of_slices = parameter.size();
for (int i = 0; i < num_of_slices; i++)
{
for (int j = 0; j < parameter[i].second; j++)
{
value <<= 1; //shift left
if (bits[BEIDOU_SUBFRAME_BITS - parameter[i].first - j] == 1)
{
value += 1; // insert the bit
}
}
}
return value;
}
signed long int Beidou_Navigation_Message_D1::read_navigation_signed(std::bitset<BEIDOU_SUBFRAME_BITS> bits, const std::vector<std::pair<int,int>> parameter)
{
signed long int value = 0;
int num_of_slices = parameter.size();
// Discriminate between 64 bits and 32 bits compiler
int long_int_size_bytes = sizeof(signed long int);
if (long_int_size_bytes == 8) // if a long int takes 8 bytes, we are in a 64 bits system
{
// read the MSB and perform the sign extension
if (bits[BEIDOU_SUBFRAME_BITS - parameter[0].first] == 1)
{
value ^= 0xFFFFFFFFFFFFFFFF; //64 bits variable
}
else
{
value &= 0;
}
for (int i = 0; i < num_of_slices; i++)
{
for (int j = 0; j < parameter[i].second; j++)
{
value <<= 1; //shift left
value &= 0xFFFFFFFFFFFFFFFE; //reset the corresponding bit (for the 64 bits variable)
if (bits[BEIDOU_SUBFRAME_BITS - parameter[i].first - j] == 1)
{
value += 1; // insert the bit
}
}
}
}
else // we assume we are in a 32 bits system
{
// read the MSB and perform the sign extension
if (bits[BEIDOU_SUBFRAME_BITS - parameter[0].first] == 1)
{
value ^= 0xFFFFFFFF;
}
else
{
value &= 0;
}
for (int i = 0; i < num_of_slices; i++)
{
for (int j = 0; j < parameter[i].second; j++)
{
value <<= 1; //shift left
value &= 0xFFFFFFFE; //reset the corresponding bit
if (bits[BEIDOU_SUBFRAME_BITS - parameter[i].first - j] == 1)
{
value += 1; // insert the bit
}
}
}
}
return value;
}
double Beidou_Navigation_Message_D1::check_t(double time)
{
double corrTime;
double half_week = 302400; // seconds
corrTime = time;
if (time > half_week)
{
corrTime = time - 2 * half_week;
}
else if (time < -half_week)
{
corrTime = time + 2 * half_week;
}
return corrTime;
}
// User Algorithm for SV Clock Correction.
double Beidou_Navigation_Message_D1::sv_clock_correction(double transmitTime)
{
double dt;
dt = check_t(transmitTime - d_Toc);
d_satClkCorr = (d_A_f2 * dt + d_A_f1) * dt + d_A_f0 + d_dtr;
double correctedTime = transmitTime - d_satClkCorr;
return correctedTime;
}
void Beidou_Navigation_Message_D1::satellitePosition(double transmitTime)
{
double tk;
double a;
double n;
double n0;
double M;
double E;
double E_old;
double dE;
double nu;
double phi;
double u;
double r;
double i;
double Omega;
// Find satellite's position ----------------------------------------------
// Restore semi-major axis
a = d_sqrt_A * d_sqrt_A;
// Time from ephemeris reference epoch
tk = check_t(transmitTime - d_Toe);
// Computed mean motion
n0 = sqrt(BEIDOU_GM / (a * a * a));
// Corrected mean motion
n = n0 + d_Delta_n;
// Mean anomaly
M = d_M_0 + n * tk;
// Reduce mean anomaly to between 0 and 2pi
M = fmod((M + 2 * BEIDOU_PI), (2 * BEIDOU_PI));
// Initial guess of eccentric anomaly
E = M;
// --- Iteratively compute eccentric anomaly ----------------------------
for (int ii = 1; ii < 20; ii++)
{
E_old = E;
E = M + d_e_eccentricity * sin(E);
dE = fmod(E - E_old, 2 * BEIDOU_PI);
if (fabs(dE) < 1e-12)
{
//Necessary precision is reached, exit from the loop
break;
}
}
// Compute relativistic correction term
d_dtr = BEIDOU_F * d_e_eccentricity * d_sqrt_A * sin(E);
// Compute the true anomaly
double tmp_Y = sqrt(1.0 - d_e_eccentricity * d_e_eccentricity) * sin(E);
double tmp_X = cos(E) - d_e_eccentricity;
nu = atan2(tmp_Y, tmp_X);
// Compute angle phi (argument of Latitude)
phi = nu + d_OMEGA;
// Reduce phi to between 0 and 2*pi rad
phi = fmod((phi), (2 * BEIDOU_PI));
// Correct argument of latitude
u = phi + d_Cuc * cos(2 * phi) + d_Cus * sin(2 * phi);
// Correct radius
r = a * (1 - d_e_eccentricity * cos(E)) + d_Crc * cos(2 * phi) + d_Crs * sin(2 * phi);
// Correct inclination
i = d_i_0 + d_IDOT * tk + d_Cic * cos(2 * phi) + d_Cis * sin(2 * phi);
// Compute the angle between the ascending node and the Greenwich meridian
Omega = d_OMEGA0 + (d_OMEGA_DOT - BEIDOU_OMEGA_EARTH_DOT) * tk - BEIDOU_OMEGA_EARTH_DOT * d_Toe;
// Reduce to between 0 and 2*pi rad
Omega = fmod((Omega + 2 * BEIDOU_PI), (2 * BEIDOU_PI));
// --- Compute satellite coordinates in Earth-fixed coordinates
d_satpos_X = cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega);
d_satpos_Y = cos(u) * r * sin(Omega) + sin(u) * r * cos(i) * cos(Omega);
d_satpos_Z = sin(u) * r * sin(i);
// Satellite's velocity. Can be useful for Vector Tracking loops
double Omega_dot = d_OMEGA_DOT - BEIDOU_OMEGA_EARTH_DOT;
d_satvel_X = - Omega_dot * (cos(u) * r + sin(u) * r * cos(i)) + d_satpos_X * cos(Omega) - d_satpos_Y * cos(i) * sin(Omega);
d_satvel_Y = Omega_dot * (cos(u) * r * cos(Omega) - sin(u) * r * cos(i) * sin(Omega)) + d_satpos_X * sin(Omega) + d_satpos_Y * cos(i) * cos(Omega);
d_satvel_Z = d_satpos_Y * sin(i);
}
int Beidou_Navigation_Message_D1::subframe_decoder(char *subframe)
{
int subframe_ID = 0;
std::bitset<BEIDOU_SUBFRAME_BITS> mysubframe_bits;
unsigned int beidou_word;
std::bitset<BEIDOU_SUBFRAME_BITS> subframe_bits;
std::bitset<BEIDOU_WORD_BITS + 2> word_bits;
for (int i = 0; i < 10; i++)
{
memcpy(&beidou_word, &subframe[i * 4], sizeof(char) * 4);
word_bits = std::bitset<(BEIDOU_WORD_BITS + 2) > (beidou_word);
for (int j = 0; j < BEIDOU_WORD_BITS; j++)
{
subframe_bits[BEIDOU_WORD_BITS * (9 - i) + j] = word_bits[j];
}
}
subframe_ID = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_FRAID));
// Decode all 5 sub-frames
switch (subframe_ID)
{
//--- Decode the sub-frame id ------------------------------------------
case 1:
//--- It is subframe 1 -------------------------------------
// Compute the time of week (SOW) of the first sub-frames in the array ====
// The transmitted SOW is actual SOW of the next subframe
// (the variable subframe at this point contains bits of the last subframe).
//SOW = bin2dec(subframe(31:47)) * 6;
//we are in the first subframe (the transmitted SOW is the start time of the next subframe) !
//d_SOW_SF1 = d_SOW_SF1 * 6;
//b_integrity_status_flag = read_navigation_bool(subframe_bits, INTEGRITY_STATUS_FLAG);
//b_alert_flag = read_navigation_bool(subframe_bits, ALERT_FLAG);
//b_antispoofing_flag = read_navigation_bool(subframe_bits, ANTI_SPOOFING_FLAG);
//i_SV_accuracy = static_cast<int>(read_navigation_unsigned(subframe_bits, SV_ACCURACY)); // (20.3.3.3.1.3)
// b_L2_P_data_flag = read_navigation_bool(subframe_bits, L2_P_DATA_FLAG); //
//i_code_on_L2 = static_cast<int>(read_navigation_unsigned(subframe_bits, CA_OR_P_ON_L2));
d_SOW_SF1 = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_SOW));
d_SOW = d_SOW_SF1; // Set transmission time
i_SV_health = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_SAT_H1));
d_AODC = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_AODC));
i_SV_accuracy = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_URAI)); // (20.3.3.3.1.3)
i_BEIDOU_week = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_WN));
d_Toc = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_TOC));
d_Toc = d_Toc * D1_TOC_LSB;
d_TGD1 = static_cast<double>(read_navigation_signed(subframe_bits, D1_TGD1));
d_TGD1 = d_TGD1 * D1_TGD1_LSB;
d_TGD2 = static_cast<double>(read_navigation_signed(subframe_bits, D1_TGD2));
d_TGD2 = d_TGD2 * D1_TGD2_LSB;
d_alpha0 = static_cast<double>(read_navigation_signed(subframe_bits, D1_ALPHA0));
d_alpha0 = d_alpha0 * D1_ALPHA0_LSB;
d_alpha1 = static_cast<double>(read_navigation_signed(subframe_bits, D1_ALPHA1));
d_alpha1 = d_alpha1 * D1_ALPHA1_LSB;
d_alpha2 = static_cast<double>(read_navigation_signed(subframe_bits, D1_ALPHA2));
d_alpha2 = d_alpha2 * D1_ALPHA2_LSB;
d_alpha3 = static_cast<double>(read_navigation_signed(subframe_bits, D1_ALPHA3));
d_alpha3 = d_alpha3 * D1_ALPHA3_LSB;
d_beta0 = static_cast<double>(read_navigation_signed(subframe_bits, D1_BETA0));
d_beta0 = d_beta0 * D1_BETA0_LSB;
d_beta1 = static_cast<double>(read_navigation_signed(subframe_bits, D1_BETA1));
d_beta1 = d_beta1 * D1_BETA1_LSB;
d_beta2 = static_cast<double>(read_navigation_signed(subframe_bits, D1_BETA2));
d_beta2 = d_beta2 * D1_BETA2_LSB;
d_beta3 = static_cast<double>(read_navigation_signed(subframe_bits, D1_BETA3));
d_beta3 = d_beta3 * D1_BETA3_LSB;
d_a2 = static_cast<double>(read_navigation_signed(subframe_bits, D1_A2));
d_a2 = d_a2 * D1_A2_LSB;
d_a0 = static_cast<double>(read_navigation_signed(subframe_bits, D1_A0));
d_a0 = d_a0 * D1_A0_LSB;
d_a1 = static_cast<double>(read_navigation_signed(subframe_bits, D1_A1));
d_a1 = d_a1 * D1_A1_LSB;
d_AODE_SF1 = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_AODE));
flag_iono_valid = true;
//d_A_f0 = static_cast<double>(read_navigation_signed(subframe_bits, A_F0));
//d_A_f0 = d_A_f0 * A_F0_LSB;
//d_A_f1 = static_cast<double>(read_navigation_signed(subframe_bits, A_F1));
//d_A_f1 = d_A_f1 * A_F1_LSB;
//d_A_f2 = static_cast<double>(read_navigation_signed(subframe_bits, A_F2));
//d_A_f2 = d_A_f2 * A_F2_LSB;
break;
case 2: //--- It is subframe 2 -------------------
d_SOW_SF2 = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_SOW));
d_SOW = d_SOW_SF2; // Set transmission time
d_Cuc = static_cast<double>(read_navigation_signed(subframe_bits, D1_CUC));
d_Cuc = d_Cuc * D1_CUC_LSB;
d_M_0 = static_cast<double>(read_navigation_signed(subframe_bits, D1_M0));
d_M_0 = d_M_0 * D1_M0_LSB;
d_e_eccentricity = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_E));
d_e_eccentricity = d_e_eccentricity * D1_E_LSB;
d_Cus = static_cast<double>(read_navigation_signed(subframe_bits, D1_CUS));
d_Cus = d_Cus * D1_CUS_LSB;
d_Crc = static_cast<double>(read_navigation_signed(subframe_bits, D1_CRC));
d_Crc = d_Crc * D1_CRC_LSB;
d_Crs = static_cast<double>(read_navigation_signed(subframe_bits, D1_CRS));
d_Crs = d_Crs * D1_CRS_LSB;
d_sqrt_A = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_SQRT_A));
d_sqrt_A = d_sqrt_A * D1_SQRT_A_LSB;
d_Toe = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_TOE));
d_Toe = d_Toe * D1_TOE_LSB;
// d_SOW = d_SOW_SF2; // Set transmission time
// b_integrity_status_flag = read_navigation_bool(subframe_bits, INTEGRITY_STATUS_FLAG);
// b_alert_flag = read_navigation_bool(subframe_bits, ALERT_FLAG);
// b_antispoofing_flag = read_navigation_bool(subframe_bits, ANTI_SPOOFING_FLAG);
// b_fit_interval_flag = read_navigation_bool(subframe_bits, FIT_INTERVAL_FLAG);
// i_AODO = static_cast<int>(read_navigation_unsigned(subframe_bits, AODO));
// i_AODO = i_AODO * AODO_LSB;
break;
case 3: // --- It is subframe 3 -------------------------------------
d_SOW_SF3 = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_SOW));
d_SOW = d_SOW_SF3; // Set transmission time
d_Toe = d_Toe * D1_TOE_LSB;
d_i_0 = static_cast<double>(read_navigation_signed(subframe_bits, D1_I0));
d_i_0 = d_i_0 * D1_I0_LSB;
d_Cic = static_cast<double>(read_navigation_signed(subframe_bits, D1_CIC));
d_Cic = d_Cic * D1_CIC_LSB;
d_OMEGA_DOT = static_cast<double>(read_navigation_signed(subframe_bits, D1_OMEGA_DOT));
d_OMEGA_DOT = d_OMEGA_DOT * D1_OMEGA_DOT_LSB;
d_Cis = static_cast<double>(read_navigation_signed(subframe_bits, D1_CIS));
d_Cis = d_Cis * D1_CIS_LSB;
d_IDOT = static_cast<double>(read_navigation_signed(subframe_bits, D1_IDOT));
d_IDOT = d_IDOT * D1_IDOT_LSB;
d_OMEGA0 = static_cast<double>(read_navigation_signed(subframe_bits, D1_OMEGA0));
d_OMEGA0 = d_OMEGA0 * D1_OMEGA0_LSB;
d_OMEGA = static_cast<double>(read_navigation_signed(subframe_bits, D1_OMEGA));
d_OMEGA = d_OMEGA * D1_OMEGA_LSB;
//d_SOW_SF3 = static_cast<double>(read_navigation_unsigned(subframe_bits, SOW));
//d_SOW_SF3 = d_SOW_SF3 * 6;
//d_SOW = d_SOW_SF3; // Set transmission time
//b_integrity_status_flag = read_navigation_bool(subframe_bits, INTEGRITY_STATUS_FLAG);
//b_alert_flag = read_navigation_bool(subframe_bits, ALERT_FLAG);
//b_antispoofing_flag = read_navigation_bool(subframe_bits, ANTI_SPOOFING_FLAG);
//d_AODE_SF3 = static_cast<double>(read_navigation_unsigned(subframe_bits, AODE_SF3));
break;
case 4: // --- It is subframe 4 ---------- Almanac, ionospheric model, UTC parameters, SV health (PRN: 25-32)
d_SOW_SF4 = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_SOW));
d_SOW = d_SOW_SF4; // Set transmission time
d_SQRT_A_ALMANAC = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_SQRT_A_ALMANAC));
d_SQRT_A_ALMANAC = d_SQRT_A_ALMANAC * D1_SQRT_A_ALMANAC_LSB;
d_A1_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_A1_ALMANAC));
d_A1_ALMANAC = d_A1_ALMANAC * D1_A1_ALMANAC_LSB;
d_A0_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_A0_ALMANAC));
d_A0_ALMANAC = d_A0_ALMANAC * D1_A0_ALMANAC_LSB;
d_OMEGA0_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_OMEGA0_ALMANAC));
d_OMEGA0_ALMANAC = d_OMEGA0_ALMANAC * D1_OMEGA0_ALMANAC_LSB;
d_E_ALMANAC = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_E));
d_E_ALMANAC = d_E_ALMANAC * D1_E_ALMANAC_LSB;
d_DELTA_I = static_cast<double>(read_navigation_signed(subframe_bits, D1_DELTA_I));
d_DELTA_I = D1_DELTA_I_LSB;
d_TOA = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_TOA));
d_TOA = d_TOA * D1_TOA_LSB;
d_OMEGA_DOT_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_OMEGA_DOT_ALMANAC));
d_OMEGA_DOT_ALMANAC = D1_OMEGA_DOT_ALMANAC_LSB;
d_OMEGA_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_OMEGA_ALMANAC));
d_OMEGA_ALMANAC = d_OMEGA_ALMANAC * D1_OMEGA_ALMANAC_LSB;
d_M0_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_M0));
d_M0_ALMANAC = d_M0_ALMANAC * D1_M0_ALMANAC_LSB;
/* b_integrity_status_flag = read_navigation_bool(subframe_bits, INTEGRITY_STATUS_FLAG);
b_alert_flag = read_navigation_bool(subframe_bits, ALERT_FLAG);
b_antispoofing_flag = read_navigation_bool(subframe_bits, ANTI_SPOOFING_FLAG);
SV_data_ID = static_cast<int>(read_navigation_unsigned(subframe_bits, SV_DATA_ID));
SV_page = static_cast<int>(read_navigation_unsigned(subframe_bits, SV_PAGE));
if (SV_page > 24 && SV_page < 33) // Page 4 (from Table 20-V. Data IDs and SV IDs in Subframes 4 and 5, IS-GPS-200H, page 110)
{
//! \TODO read almanac
if(SV_data_ID){}
}
if (SV_page == 52) // Page 13 (from Table 20-V. Data IDs and SV IDs in Subframes 4 and 5, IS-GPS-200H, page 110)
{
//! \TODO read Estimated Range Deviation (ERD) values
}
if (SV_page == 56) // Page 18 (from Table 20-V. Data IDs and SV IDs in Subframes 4 and 5, IS-GPS-200H, page 110)
{
// Page 18 - Ionospheric and UTC data
d_t_OT = static_cast<double>(read_navigation_unsigned(subframe_bits, T_OT));
d_t_OT = d_t_OT * T_OT_LSB;
i_WN_T = static_cast<int>(read_navigation_unsigned(subframe_bits, WN_T));
d_DeltaT_LS = static_cast<double>(read_navigation_signed(subframe_bits, DELTAT_LS));
i_WN_LSF = static_cast<int>(read_navigation_unsigned(subframe_bits, WN_LSF));
i_DN = static_cast<int>(read_navigation_unsigned(subframe_bits, DN)); // Right-justified ?
d_DeltaT_LSF = static_cast<double>(read_navigation_signed(subframe_bits, DELTAT_LSF));
flag_iono_valid = true;
}
if (SV_page == 57)
{
// Reserved
}
if (SV_page == 63) // Page 25 (from Table 20-V. Data IDs and SV IDs in Subframes 4 and 5, IS-GPS-200H, page 110)
{
// Page 25 Anti-Spoofing, SV config and almanac health (PRN: 25-32)
//! \TODO Read Anti-Spoofing, SV config
almanacHealth[25] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA25));
almanacHealth[26] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA26));
almanacHealth[27] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA27));
almanacHealth[28] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA28));
almanacHealth[29] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA29));
almanacHealth[30] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA30));
almanacHealth[31] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA31));
almanacHealth[32] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA32));
}
break;
*/
case 5://--- It is subframe 5 -----------------almanac health (PRN: 1-24) and Almanac reference week number and time.
int SV_page_5;
d_SOW_SF5 = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_SOW));
d_SOW = d_SOW_SF5; // Set transmission time
SV_page_5 = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_PNUM));
if (SV_page_5 < 7)
{
d_SOW_SF4 = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_SOW));
d_SQRT_A_ALMANAC = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_SQRT_A_ALMANAC));
d_SQRT_A_ALMANAC = d_SQRT_A_ALMANAC * D1_SQRT_A_ALMANAC_LSB;
d_A1_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_A1_ALMANAC));
d_A1_ALMANAC = d_A1_ALMANAC * D1_A1_ALMANAC_LSB;
d_A0_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_A0_ALMANAC));
d_A0_ALMANAC = d_A0_ALMANAC * D1_A0_ALMANAC_LSB;
d_OMEGA0_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_OMEGA0_ALMANAC));
d_OMEGA0_ALMANAC = d_OMEGA0_ALMANAC * D1_OMEGA0_ALMANAC_LSB;
d_E_ALMANAC = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_E));
d_E_ALMANAC = d_E_ALMANAC * D1_E_ALMANAC_LSB;
d_DELTA_I = static_cast<double>(read_navigation_signed(subframe_bits, D1_DELTA_I));
d_DELTA_I = D1_DELTA_I_LSB;
d_TOA = static_cast<double>(read_navigation_unsigned(subframe_bits, D1_TOA));
d_TOA = d_TOA * D1_TOA_LSB;
d_OMEGA_DOT_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_OMEGA_DOT_ALMANAC));
d_OMEGA_DOT_ALMANAC = D1_OMEGA_DOT_ALMANAC_LSB;
d_OMEGA_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_OMEGA_ALMANAC));
d_OMEGA_ALMANAC = d_OMEGA_ALMANAC * D1_OMEGA_ALMANAC_LSB;
d_M0_ALMANAC = static_cast<double>(read_navigation_signed(subframe_bits, D1_M0));
d_M0_ALMANAC = d_M0_ALMANAC * D1_M0_ALMANAC_LSB;
}
if (SV_page_5 == 7)
{
//! \TODO read almanac
almanacHealth[1] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA1));
almanacHealth[2] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA2));
almanacHealth[3] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA3));
almanacHealth[4] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA4));
almanacHealth[5] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA5));
almanacHealth[6] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA6));
almanacHealth[7] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA7));
almanacHealth[8] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA8));
almanacHealth[9] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA9));
almanacHealth[10] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA10));
almanacHealth[11] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA11));
almanacHealth[12] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA12));
almanacHealth[13] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA13));
almanacHealth[14] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA14));
almanacHealth[15] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA15));
almanacHealth[16] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA16));
almanacHealth[17] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA17));
almanacHealth[18] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA18));
almanacHealth[19] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA19));
}
if (SV_page_5 == 8) // Page 25 (from Table 20-V. Data IDs and SV IDs in Subframes 4 and 5, IS-GPS-200H, page 110)
{
almanacHealth[20] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA20));
almanacHealth[21] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA21));
almanacHealth[22] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA22));
almanacHealth[23] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA23));
almanacHealth[24] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA24));
almanacHealth[25] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA25));
almanacHealth[26] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA26));
almanacHealth[27] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA27));
almanacHealth[28] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA28));
almanacHealth[29] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA29));
almanacHealth[30] = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_HEA30));
almanac_WN = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_WNA));
d_toa2 = static_cast<int>(read_navigation_unsigned(subframe_bits, D1_TOA2));
}
if (SV_page_5 == 9) // Page 25 (from Table 20-V. Data IDs and SV IDs in Subframes 4 and 5, IS-GPS-200H, page 110)
{
d_A0GPS = static_cast<double>(read_navigation_signed(subframe_bits, D1_A0GPS));
d_A0GPS = d_A0GPS * D1_A0GPS_LSB;
d_A1GPS = static_cast<double>(read_navigation_signed(subframe_bits, D1_A1GPS));
d_A1GPS = d_A1GPS * D1_A1GPS_LSB;
d_A0GAL = static_cast<double>(read_navigation_signed(subframe_bits, D1_A0GAL));
d_A0GAL = d_A0GAL * D1_A0GAL_LSB;
d_A1GAL = static_cast<double>(read_navigation_signed(subframe_bits, D1_A1GAL));
d_A1GAL = d_A1GAL* D1_A1GAL_LSB;
d_A0GLO = static_cast<double>(read_navigation_signed(subframe_bits, D1_A0GLO));
d_A0GLO = d_A0GLO * D1_A0GLO_LSB;
d_A1GLO = static_cast<double>(read_navigation_signed(subframe_bits, D1_A1GLO));
d_A1GLO = d_A1GLO* D1_A1GLO_LSB;
}
if (SV_page_5 == 10)
{
d_DeltaT_LS = static_cast<double>(read_navigation_signed(subframe_bits, D1_DELTA_T_LS));
d_DeltaT_LSF = static_cast<double>(read_navigation_signed(subframe_bits, D1_DELTA_T_LSF));
i_WN_LSF = static_cast<double>(read_navigation_signed(subframe_bits, D1_WN_LSF));
d_A0UTC = static_cast<double>(read_navigation_signed(subframe_bits, D1_A0UTC));
d_A0UTC = d_A0GPS * D1_A0GPS_LSB;
d_A1UTC = static_cast<double>(read_navigation_signed(subframe_bits, D1_A1UTC));
d_A1UTC = d_A1UTC * D1_A1UTC_LSB;
}
break;
default:
break;
} // switch subframeID ...
return subframe_ID;
}
double Beidou_Navigation_Message_D1::utc_time(const double beidoutime_corrected) const
{
double t_utc;
double t_utc_daytime;
double Delta_t_UTC = d_DeltaT_LS + d_A0UTC + d_A1UTC * (beidoutime_corrected);
// Determine if the effectivity time of the leap second event is in the past
int weeksToLeapSecondEvent = i_WN_LSF - i_BEIDOU_week;
if ((weeksToLeapSecondEvent) >= 0) // is not in the past
{
//Detect if the effectivity time and user's time is within six hours = 6 * 60 *60 = 21600 s
int secondOfLeapSecondEvent = i_DN * 24 * 60 * 60;
if (weeksToLeapSecondEvent > 0)
{
t_utc_daytime = fmod(beidoutime_corrected - Delta_t_UTC, 86400);
}
else //we are in the same week than the leap second event
{
if ((beidoutime_corrected - secondOfLeapSecondEvent) < (2/3) * 24 * 60 * 60)
{
t_utc_daytime = fmod(beidoutime_corrected - Delta_t_UTC, 86400);
}
else
{
if ((beidoutime_corrected - secondOfLeapSecondEvent) < (5/4) * 24 * 60 * 60)
{
int W = fmod(beidoutime_corrected - Delta_t_UTC - 43200, 86400) + 43200;
t_utc_daytime = fmod(W, 86400 + d_DeltaT_LSF - d_DeltaT_LS);
}
else
{
t_utc_daytime = fmod(beidoutime_corrected - Delta_t_UTC, 86400);
}
}
}
}
else // the effectivity time is in the past
{
t_utc_daytime = fmod(beidoutime_corrected - Delta_t_UTC, 86400);
}
double secondsOfWeekBeforeToday = 43200 * floor(beidoutime_corrected / 43200);
t_utc = secondsOfWeekBeforeToday + t_utc_daytime;
return t_utc;
}
Beidou_Ephemeris Beidou_Navigation_Message_D1::get_ephemeris()
{
Beidou_Ephemeris ephemeris;
ephemeris.i_satellite_PRN = i_satellite_PRN;
ephemeris.d_TOW = d_SOW;
ephemeris.d_Crs = d_Crs;
ephemeris.d_Delta_n = d_Delta_n;
ephemeris.d_M_0 = d_M_0;
ephemeris.d_Cuc = d_Cuc;
ephemeris.d_e_eccentricity = d_e_eccentricity;
ephemeris.d_Cus = d_Cus;
ephemeris.d_sqrt_A = d_sqrt_A;
ephemeris.d_Toe =static_cast<float>( (static_cast<int>(d_Toe) << 15) | static_cast<int>(d_Toe2)) ;
ephemeris.d_Toc = d_Toc;
ephemeris.d_Cic = d_Cic;
ephemeris.d_OMEGA0 = d_OMEGA0;
ephemeris.d_Cis = d_Cis;
ephemeris.d_i_0 = d_i_0;
ephemeris.d_Crc = d_Crc;
ephemeris.d_OMEGA = d_OMEGA;
ephemeris.d_OMEGA_DOT = d_OMEGA_DOT;
ephemeris.d_IDOT = d_IDOT;
ephemeris.i_BEIDOU_week = i_BEIDOU_week;
ephemeris.i_SV_accuracy = i_SV_accuracy;
ephemeris.i_SV_health = i_SV_health;
ephemeris.d_TGD1 = d_TGD1;
ephemeris.d_AODC = d_AODC;
//ephemeris.d_AODE_SF2 = d_AODE_SF2;
//ephemeris.d_AODE_SF3 = d_AODE_SF3;
//ephemeris.i_AODO = i_AODO;
ephemeris.b_fit_interval_flag = b_fit_interval_flag;
ephemeris.d_spare1 = d_spare1;
ephemeris.d_spare2 = d_spare2;
ephemeris.d_A_f0 = d_A_f0;
ephemeris.d_A_f1 = d_A_f1;
ephemeris.d_A_f2 = d_A_f2;
ephemeris.b_integrity_status_flag = b_integrity_status_flag;
ephemeris.b_alert_flag = b_alert_flag;
ephemeris.b_antispoofing_flag = b_antispoofing_flag;
ephemeris.d_satClkDrift = d_satClkDrift;
ephemeris.d_dtr = d_dtr;
ephemeris.d_satpos_X = d_satpos_X;
ephemeris.d_satpos_Y = d_satpos_Y;
ephemeris.d_satpos_Z = d_satpos_Z;
ephemeris.d_satvel_X = d_satvel_X;
ephemeris.d_satvel_Y = d_satvel_Y;
ephemeris.d_satvel_Z = d_satvel_Z;
return ephemeris;
}
Beidou_Iono Beidou_Navigation_Message_D1::get_iono()
{
Beidou_Iono iono;
iono.d_alpha0 = d_alpha0;
iono.d_alpha1 = d_alpha1;
iono.d_alpha2 = d_alpha2;
iono.d_alpha3 = d_alpha3;
iono.d_beta0 = d_beta0;
iono.d_beta1 = d_beta1;
iono.d_beta2 = d_beta2;
iono.d_beta3 = d_beta3;
iono.valid = flag_iono_valid;
//WARNING: We clear flag_utc_model_valid in order to not re-send the same information to the ionospheric parameters queue
flag_iono_valid = false;
return iono;
}
Beidou_Utc_Model Beidou_Navigation_Message_D1::get_utc_model()
{
Beidou_Utc_Model utc_model;
utc_model.valid = flag_utc_model_valid;
// UTC parameters
utc_model.d_A1 = d_A1UTC;
utc_model.d_A0 = d_A0UTC;
utc_model.d_t_OT = d_t_OT;
utc_model.i_WN_T = i_WN_T;
utc_model.d_DeltaT_LS = d_DeltaT_LS;
utc_model.i_WN_LSF = i_WN_LSF;
utc_model.i_DN = i_DN;
utc_model.d_DeltaT_LSF = d_DeltaT_LSF;
// warning: We clear flag_utc_model_valid in order to not re-send the same information to the ionospheric parameters queue
flag_utc_model_valid = false;
return utc_model;
}
bool Beidou_Navigation_Message_D1::satellite_validation()
{
bool flag_data_valid = false;
b_valid_ephemeris_set_flag = false;
// First Step:
// check Issue Of Ephemeris Data (AODE AODC..) to find a possible interrupted reception
// and check if the data have been filled (!=0)
if (d_SOW_SF1 != 0 and d_SOW_SF2 != 0 and d_SOW_SF3 != 0)
{
if (d_AODC!= -1)
{
flag_data_valid = true;
b_valid_ephemeris_set_flag = true;
}
}
return flag_data_valid;
}

View File

@ -0,0 +1,272 @@
/*!
* \file beidou_navigation_message.h
* \brief Interface of a BeiDou D1 NAV Data message decoder
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_NAVIGATION_MESSAGE_H_
#define GNSS_SDR_BEIDOU_NAVIGATION_MESSAGE_H_
#include <bitset>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "beidou_dnav_almanac.h"
#include "beidou_dnav_ephemeris.h"
#include "beidou_dnav_iono.h"
#include "beidou_dnav_utc_model.h"
#include "Beidou_B1I.h"
/*!
* \brief This class decodes a BeiDou D1 NAV Data message as described in IS-GPS-200E
*
* See http://www.gps.gov/technical/icwg/IS-GPS-200E.pdf Appendix II
*/
class Beidou_Navigation_Message_D1
{
private:
unsigned long int read_navigation_unsigned(std::bitset<BEIDOU_SUBFRAME_BITS> bits, const std::vector<std::pair<int,int>> parameter);
signed long int read_navigation_signed(std::bitset<BEIDOU_SUBFRAME_BITS> bits, const std::vector<std::pair<int,int>> parameter);
bool read_navigation_bool(std::bitset<BEIDOU_SUBFRAME_BITS> bits, const std::vector<std::pair<int,int>> parameter);
void print_beidou_word_bytes(unsigned int BEIDOU_word);
/*
* Accounts for the beginning or end of week crossover
*
* See paragraph 20.3.3.3.3.1 (IS-GPS-200E)
* \param[in] - time in seconds
* \param[out] - corrected time, in seconds
*/
double check_t(double time);
public:
bool b_valid_ephemeris_set_flag; // flag indicating that this ephemeris set have passed the validation check
//broadcast orbit 1
double d_SOW; //!< Time of BeiDou Week of the ephemeris set (taken from subframes SOW) [s]
double d_SOW_SF1; //!< Time of BeiDou Week from HOW word of Subframe 1 [s]
double d_SOW_SF2; //!< Time of BeiDou Week from HOW word of Subframe 2 [s]
double d_SOW_SF3; //!< Time of BeiDou Week from HOW word of Subframe 3 [s]
double d_SOW_SF4; //!< Time of BeiDou Week from HOW word of Subframe 4 [s]
double d_SOW_SF5; //!< Time of BeiDou Week from HOW word of Subframe 5 [s]
double d_AODE;
double d_Crs; //!< Amplitude of the Sine Harmonic Correction Term to the Orbit Radius [m]
double d_Delta_n; //!< Mean Motion Difference From Computed Value [semi-circles/s]
double d_M_0; //!< Mean Anomaly at Reference Time [semi-circles]
//broadcast orbit 2
double d_Cuc; //!< Amplitude of the Cosine Harmonic Correction Term to the Argument of Latitude [rad]
double d_e_eccentricity; //!< Eccentricity [dimensionless]
double d_Cus; //!< Amplitude of the Sine Harmonic Correction Term to the Argument of Latitude [rad]
double d_sqrt_A; //!< Square Root of the Semi-Major Axis [sqrt(m)]
//broadcast orbit 3
double d_Toe; //!< Ephemeris data reference time of week (Ref. 20.3.3.4.3 IS-GPS-200E) [s]
double d_Toe2;
double d_Toc; //!< clock data reference time (Ref. 20.3.3.3.3.1 IS-GPS-200E) [s]
double d_Cic; //!< Amplitude of the Cosine Harmonic Correction Term to the Angle of Inclination [rad]
double d_OMEGA0; //!< Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles]
double d_Cis; //!< Amplitude of the Sine Harmonic Correction Term to the Angle of Inclination [rad]
//broadcast orbit 4
double d_i_0; //!< Inclination Angle at Reference Time [semi-circles]
double d_Crc; //!< Amplitude of the Cosine Harmonic Correction Term to the Orbit Radius [m]
double d_OMEGA; //!< Argument of Perigee [semi-cicles]
double d_OMEGA_DOT; //!< Rate of Right Ascension [semi-circles/s]
//broadcast orbit 5
double d_IDOT; //!< Rate of Inclination Angle [semi-circles/s]
int i_BEIDOU_week; //!< BeiDou week number, aka WN [week]
//broadcast orbit 6
int i_SV_accuracy; //!< User Range Accuracy (URA) index of the SV
int i_SV_health;
double d_TGD1; //!< Estimated Group Delay Differential in B1
double d_TGD2; //!< Estimated Group Delay Differential in B2
double d_AODC; //!< Age of Data, Clock
//broadcast orbit 7
// int i_AODO; //!< Age of Data Offset (AODO) term for the navigation message correction table (NMCT) contained in subframe 4 (reference paragraph 20.3.3.5.1.9) [s]
bool b_fit_interval_flag;//!< indicates the curve-fit interval used by the CS (Block II/IIA/IIR/IIR-M/IIF) and SS (Block IIIA) in determining the ephemeris parameters, as follows: 0 = 4 hours, 1 = greater than 4 hours.
double d_spare1;
double d_spare2;
double d_A_f0; //!< Coefficient 0 of code phase offset model [s]
double d_A_f1; //!< Coefficient 1 of code phase offset model [s/s]
double d_A_f2; //!< Coefficient 2 of code phase offset model [s/s^2]
double d_a0;
double d_a1;
double d_a2;
// Almanac
double d_Toa; //!< Almanac reference time [s]
int i_WN_A; //!< Modulo 256 of the GPS week number to which the almanac reference time (d_Toa) is referenced
std::map<int,int> almanacHealth; //!< Map that stores the health information stored in the almanac
std::map<int,std::string> satelliteBlock; //!< Map that stores to which block the PRN belongs http://www.navcen.uscg.gov/?Do=constellationStatus
// Flags
/*! \brief If true, enhanced level of integrity assurance.
*
* If false, indicates that the conveying signal is provided with the legacy level of integrity assurance.
* That is, the probability that the instantaneous URE of the conveying signal exceeds 4.42 times the upper bound
* value of the current broadcast URA index, for more than 5.2 seconds, without an accompanying alert, is less
* than 1E-5 per hour. If true, indicates that the conveying signal is provided with an enhanced level of
* integrity assurance. That is, the probability that the instantaneous URE of the conveying signal exceeds 5.73
* times the upper bound value of the current broadcast URA index, for more than 5.2 seconds, without an
* accompanying alert, is less than 1E-8 per hour.
*/
bool b_integrity_status_flag;
bool b_alert_flag; //!< If true, indicates that the SV URA may be worse than indicated in d_SV_accuracy, use that SV at our own risk.
bool b_antispoofing_flag; //!< If true, the AntiSpoofing mode is ON in that SV
// clock terms
//double d_master_clock; // GPS transmission time
double d_satClkCorr; // GPS clock error
double d_dtr; // relativistic clock correction term
double d_satClkDrift;
// satellite positions
double d_satpos_X; //!< Earth-fixed coordinate x of the satellite [m]. Intersection of the IERS Reference Meridian (IRM) and the plane passing through the origin and normal to the Z-axis.
double d_satpos_Y; //!< Earth-fixed coordinate y of the satellite [m]. Completes a right-handed, Earth-Centered, Earth-Fixed orthogonal coordinate system.
double d_satpos_Z; //!< Earth-fixed coordinate z of the satellite [m]. The direction of the IERS (International Earth Rotation and Reference Systems Service) Reference Pole (IRP).
// satellite identification info
int i_channel_ID;
unsigned int i_satellite_PRN;
// time synchro
double d_subframe_timestamp_ms; //[ms]
// Ionospheric parameters
bool flag_iono_valid; //!< If set, it indicates that the ionospheric parameters are filled (page 18 has arrived and decoded)
double d_alpha0; //!< Coefficient 0 of a cubic equation representing the amplitude of the vertical delay [s]
double d_alpha1; //!< Coefficient 1 of a cubic equation representing the amplitude of the vertical delay [s/semi-circle]
double d_alpha2; //!< Coefficient 2 of a cubic equation representing the amplitude of the vertical delay [s(semi-circle)^2]
double d_alpha3; //!< Coefficient 3 of a cubic equation representing the amplitude of the vertical delay [s(semi-circle)^3]
double d_beta0; //!< Coefficient 0 of a cubic equation representing the period of the model [s]
double d_beta1; //!< Coefficient 1 of a cubic equation representing the period of the model [s/semi-circle]
double d_beta2; //!< Coefficient 2 of a cubic equation representing the period of the model [s(semi-circle)^2]
double d_beta3; //!< Coefficient 3 of a cubic equation representing the period of the model [s(semi-circle)^3]
// UTC parameters
bool flag_utc_model_valid; //!< If set, it indicates that the UTC model parameters are filled
double d_A2UTC;
double d_A1UTC; //!< 1st order term of a model that relates GPS and UTC time (ref. 20.3.3.5.2.4 IS-GPS-200E) [s/s]
double d_A0UTC; //!< Constant of a model that relates GPS and UTC time (ref. 20.3.3.5.2.4 IS-GPS-200E) [s]
double d_t_OT; //!< Reference time for UTC data (reference 20.3.4.5 and 20.3.3.5.2.4 IS-GPS-200E) [s]
int i_WN_T; //!< UTC reference week number [weeks]
double d_DeltaT_LS; //!< delta time due to leap seconds [s]. Number of leap seconds since 6-Jan-1980 as transmitted by the GPS almanac.
int i_WN_LSF; //!< Week number at the end of which the leap second becomes effective [weeks]
int i_DN; //!< Day number (DN) at the end of which the leap second becomes effective [days]
double d_DeltaT_LSF; //!< Scheduled future or recent past (relative to NAV message upload) value of the delta time due to leap seconds [s]
double d_A1GPS;
double d_A0GPS;
double d_A1GAL;
double d_A0GAL;
double d_A1GLO;
double d_A0GLO;
double d_AODE_SF1;
double d_SQRT_A_ALMANAC;
double d_A1_ALMANAC;
double d_A0_ALMANAC;
double d_OMEGA0_ALMANAC;
double d_E_ALMANAC;
double d_DELTA_I;
double d_TOA;
double d_OMEGA_DOT_ALMANAC;
double d_OMEGA_ALMANAC;
double d_M0_ALMANAC;
int almanac_WN;
double d_toa2;
// Satellite velocity
double d_satvel_X; //!< Earth-fixed velocity coordinate x of the satellite [m]
double d_satvel_Y; //!< Earth-fixed velocity coordinate y of the satellite [m]
double d_satvel_Z; //!< Earth-fixed velocity coordinate z of the satellite [m]
// public functions
void reset();
/*!
* \brief Obtain a GPS SV Ephemeris class filled with current SV data
*/
Beidou_Ephemeris get_ephemeris();
/*!
* \brief Obtain a GPS ionospheric correction parameters class filled with current SV data
*/
Beidou_Iono get_iono();
/*!
* \brief Obtain a GPS UTC model parameters class filled with current SV data
*/
Beidou_Utc_Model get_utc_model();
/*!
* \brief Decodes the GPS NAV message
*/
int subframe_decoder(char *subframe);
/*!
* \brief Computes the position of the satellite
*
* Implementation of Table 20-IV (IS-GPS-200E)
*/
void satellitePosition(double transmitTime);
/*!
* \brief Sets (\a d_satClkCorr) according to the User Algorithm for SV Clock Correction
* and returns the corrected clock (IS-GPS-200E, 20.3.3.3.3.1)
*/
double sv_clock_correction(double transmitTime);
/*!
* \brief Computes the Coordinated Universal Time (UTC) and
* returns it in [s] (IS-GPS-200E, 20.3.3.5.2.4)
*/
double utc_time(const double gpstime_corrected) const;
bool satellite_validation();
/*!
* Default constructor
*/
Beidou_Navigation_Message_D1();
};
#endif

View File

@ -0,0 +1,112 @@
/*
* \file gps_utc_model.h
* \brief Interface of a GPS UTC MODEL storage
* \author Javier Arribas, 2013. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#include "beidou_dnav_utc_model.h"
#include <cmath>
Beidou_Utc_Model::Beidou_Utc_Model()
{
valid = false;
d_A1 = 0;
d_A0 = 0;
d_t_OT = 0;
i_WN_T = 0;
d_DeltaT_LS = 0;
i_WN_LSF = 0;
i_DN = 0;
d_DeltaT_LSF = 0;
}
double Beidou_Utc_Model::utc_time(double beidoutime_corrected, int i_BEIDOU_week)
{
double t_utc;
double t_utc_daytime;
double Delta_t_UTC = d_DeltaT_LS + d_A0 + d_A1 * (beidoutime_corrected - d_t_OT + 604800 * static_cast<double>(i_BEIDOU_week - i_WN_T));
// Determine if the effectivity time of the leap second event is in the past
int weeksToLeapSecondEvent = i_WN_LSF - i_BEIDOU_week;
if (weeksToLeapSecondEvent >= 0) // is not in the past
{
//Detect if the effectivity time and user's time is within six hours = 6 * 60 *60 = 21600 s
int secondOfLeapSecondEvent = i_DN * 24 * 60 * 60;
if (weeksToLeapSecondEvent > 0)
{
t_utc_daytime = fmod(beidoutime_corrected - Delta_t_UTC, 86400);
}
else //we are in the same week than the leap second event
{
if (std::abs(beidoutime_corrected - secondOfLeapSecondEvent) > 21600)
{
/* 20.3.3.5.2.4a
* Whenever the effectivity time indicated by the WN_LSF and the DN values
* is not in the past (relative to the user's present time), and the user's
* present time does not fall in the time span which starts at six hours prior
* to the effectivity time and ends at six hours after the effectivity time,
* the UTC/GPS-time relationship is given by
*/
t_utc_daytime = fmod(beidoutime_corrected - Delta_t_UTC, 86400);
}
else
{
/* 20.3.3.5.2.4b
* Whenever the user's current time falls within the time span of six hours
* prior to the effectivity time to six hours after the effectivity time,
* proper accommodation of the leap second event with a possible week number
* transition is provided by the following expression for UTC:
*/
int W = fmod(beidoutime_corrected - Delta_t_UTC - 43200, 86400) + 43200;
t_utc_daytime = fmod(W, 86400 + d_DeltaT_LSF - d_DeltaT_LS);
//implement something to handle a leap second event!
}
if ((beidoutime_corrected - secondOfLeapSecondEvent) > 21600)
{
Delta_t_UTC = d_DeltaT_LSF + d_A0 + d_A1 * (beidoutime_corrected - d_t_OT + 604800 * static_cast<double>(i_BEIDOU_week - i_WN_T));
t_utc_daytime = fmod(beidoutime_corrected - Delta_t_UTC, 86400);
}
}
}
else // the effectivity time is in the past
{
/* 20.3.3.5.2.4c
* Whenever the effectivity time of the leap second event, as indicated by the
* WNLSF and DN values, is in the "past" (relative to the user's current time),
* and the user's current time does not fall in the time span as given above
* in 20.3.3.5.2.4b,*/
Delta_t_UTC = d_DeltaT_LSF + d_A0 + d_A1 * (beidoutime_corrected - d_t_OT + 604800 * static_cast<double>(i_BEIDOU_week - i_WN_T));
t_utc_daytime = fmod(beidoutime_corrected - Delta_t_UTC, 86400);
}
double secondsOfWeekBeforeToday = 86400 * floor(beidoutime_corrected / 86400);
t_utc = secondsOfWeekBeforeToday + t_utc_daytime;
return t_utc;
}

View File

@ -0,0 +1,91 @@
/*!
* \file gps_utc_model.h
* \brief Interface of a GPS UTC MODEL storage
* \author Javier Arribas, 2013. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_UTC_MODEL_H_
#define GNSS_SDR_BEIDOU_UTC_MODEL_H_
#include <boost/assign.hpp>
#include <boost/serialization/nvp.hpp>
/*!
* \brief This class is a storage for the GPS UTC MODEL data as described in IS-GPS-200E
*
* See http://www.gps.gov/technical/icwg/IS-GPS-200E.pdf Appendix II
*/
class Beidou_Utc_Model
{
public:
bool valid;
// UTC parameters
double d_A1; //!< 1st order term of a model that relates GPS and UTC time (ref. 20.3.3.5.2.4 IS-GPS-200E) [s/s]
double d_A0; //!< Constant of a model that relates GPS and UTC time (ref. 20.3.3.5.2.4 IS-GPS-200E) [s]
double d_t_OT; //!< Reference time for UTC data (reference 20.3.4.5 and 20.3.3.5.2.4 IS-GPS-200E) [s]
int i_WN_T; //!< UTC reference week number [weeks]
double d_DeltaT_LS; //!< delta time due to leap seconds [s]. Number of leap seconds since 6-Jan-1980 as transmitted by the GPS almanac.
int i_WN_LSF; //!< Week number at the end of which the leap second becomes effective [weeks]
int i_DN; //!< Day number (DN) at the end of which the leap second becomes effective [days]
double d_DeltaT_LSF; //!< Scheduled future or recent past (relative to NAV message upload) value of the delta time due to leap seconds [s]
/*!
* Default constructor
*/
Beidou_Utc_Model();
template <class Archive>
/*
* \brief Serialize is a boost standard method to be called by the boost XML serialization. Here is used to save the ephemeris data on disk file.
*/
inline void serialize(Archive& archive, const unsigned int version)
{
using boost::serialization::make_nvp;
if (version)
{
};
archive& make_nvp("valid", valid);
archive& make_nvp("d_A1", d_A1);
archive& make_nvp("d_A0", d_A0);
archive& make_nvp("d_t_OT", d_t_OT);
archive& make_nvp("i_WN_T", i_WN_T);
archive& make_nvp("d_DeltaT_LS", d_DeltaT_LS);
archive& make_nvp("i_WN_LSF", i_WN_LSF);
archive& make_nvp("i_DN", i_DN);
archive& make_nvp("d_DeltaT_LSF", d_DeltaT_LSF);
}
/*!
* \brief Computes the Coordinated Universal Time (UTC) and
* returns it in [s] (IS-GPS-200E, 20.3.3.5.2.4)
*/
double utc_time(double beidoutime_corrected, int i_BEIDOU_week);
};
#endif

View File

@ -226,6 +226,19 @@ void Gnss_Satellite::set_PRN(uint32_t PRN_)
PRN = PRN_;
}
}
else if (system.compare("Beidou") == 0)
{
if (PRN_ < 1 or PRN_ > 36)
{
DLOG(INFO) << "This PRN is not defined";
PRN = 0;
}
else
{
PRN = PRN_;
}
}
else
{
DLOG(INFO) << "System " << system << " is not defined";
@ -605,6 +618,99 @@ std::string Gnss_Satellite::what_block(const std::string& system_, uint32_t PRN_
block_ = std::string("Unknown(Simulated)");
}
}
if (system_.compare("Beidou") == 0)
{
// Check https://en.wikipedia.org/wiki/List_of_BeiDou_satellites
switch ( PRN_ )
{
case 1:
block_ = std::string("Compass-G1");
break;
case 2:
block_ = std::string("Compass-G6");
break;
case 3:
block_ = std::string("Compass-G3");
break;
case 4:
block_ = std::string("Compass-G4");
break;
case 5:
block_ = std::string("Compass-G5");
break;
case 6:
block_ = std::string("Compass-IGSO1");
break;
case 7:
block_ = std::string("Compass-IGSO2");
break;
case 8:
block_ = std::string("Compass-IGSO3");
break;
case 9:
block_ = std::string("Compass-IGSO4");
break;
case 10:
block_ = std::string("Compass-IGSO5");
break;
case 11:
block_ = std::string("Compass-M3");
break;
case 12:
block_ = std::string("Compass-M4");
break;
case 13:
block_ = std::string("Compass-M2");
break;
case 14:
block_ = std::string("Compass-M5");
break;
case 17:
block_ = std::string("Compass-G7");
break;
case 19:
block_ = std::string("BeiDou-3 M1");
break;
case 20:
block_ = std::string("BeiDou-3 M2");
break;
case 21:
block_ = std::string("BeiDou-3 M3");
break;
case 22:
block_ = std::string("BeiDou-3 M4");
break;
case 27:
block_ = std::string("BeiDou-3 M7");
break;
case 28:
block_ = std::string("BeiDou-3 M8");
break;
case 29:
block_ = std::string("BeiDou-3 M9");
break;
case 30:
block_ = std::string("BeiDou-3 M10");
break;
case 31:
block_ = std::string("BDS I1-S");
break;
case 32:
block_ = std::string("BDS I2-S");
break;
case 33:
block_ = std::string("BDS M1-S");
break;
case 34:
block_ = std::string("BDS M2-S");
break;
case 35:
block_ = std::string("BDS M3-S");
break;
default:
block_ = std::string("Unknown(Simulated)");
}
}
return block_;
}

View File

@ -130,6 +130,7 @@ DECLARE_string(log_dir);
#include "unit-tests/signal-processing-blocks/acquisition/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc"
#include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc"
// #include "unit-tests/signal-processing-blocks/acquisition/glonass_l2_ca_pcps_acquisition_test.cc"
#include "unit-tests/signal-processing-blocks/acquisition/beidou_b1i_pcps_acquisition_test.cc"
#if OPENCL_BLOCKS_TEST
#include "unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_opencl_acquisition_gsoc2013_test.cc"

View File

@ -0,0 +1,350 @@
/*!
* \file beidou_b1i_pcps_acquisition_test.cc
* \brief This class implements an acquisition test for
* BeidouB1iPcpsAcquisition class based on some input parameters.
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
*
*
* -------------------------------------------------------------------------
*
* 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/>.
*
* -------------------------------------------------------------------------
*/
#include <chrono>
#include <boost/filesystem.hpp>
#include <boost/make_shared.hpp>
#include <glog/logging.h>
#include <gnuradio/top_block.h>
#include <gnuradio/blocks/file_source.h>
#include <gnuradio/analog/sig_source_waveform.h>
#include <gnuradio/analog/sig_source_c.h>
#include <gnuradio/msg_queue.h>
#include <gnuradio/blocks/null_sink.h>
#include <gtest/gtest.h>
#include "gnss_block_factory.h"
#include "gnss_block_interface.h"
#include "in_memory_configuration.h"
#include "gnss_sdr_valve.h"
#include "gnss_synchro.h"
#include "gnuplot_i.h"
#include "test_flags.h"
#include "acquisition_dump_reader.h"
#include "beidou_b1i_pcps_acquisition.h"
#include "../../../../core/system_parameters/Beidou_B1I.h"
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
class BeidouB1iPcpsAcquisitionTest_msg_rx;
typedef boost::shared_ptr<BeidouB1iPcpsAcquisitionTest_msg_rx> BeidouB1iPcpsAcquisitionTest_msg_rx_sptr;
BeidouB1iPcpsAcquisitionTest_msg_rx_sptr BeidouB1iPcpsAcquisitionTest_msg_rx_make();
class BeidouB1iPcpsAcquisitionTest_msg_rx : public gr::block
{
private:
friend BeidouB1iPcpsAcquisitionTest_msg_rx_sptr BeidouB1iPcpsAcquisitionTest_msg_rx_make();
void msg_handler_events(pmt::pmt_t msg);
BeidouB1iPcpsAcquisitionTest_msg_rx();
public:
int rx_message;
~BeidouB1iPcpsAcquisitionTest_msg_rx(); //!< Default destructor
};
BeidouB1iPcpsAcquisitionTest_msg_rx_sptr BeidouB1iPcpsAcquisitionTest_msg_rx_make()
{
return BeidouB1iPcpsAcquisitionTest_msg_rx_sptr(new BeidouB1iPcpsAcquisitionTest_msg_rx());
}
void BeidouB1iPcpsAcquisitionTest_msg_rx::msg_handler_events(pmt::pmt_t msg)
{
try
{
long int message = pmt::to_long(msg);
rx_message = message;
}
catch (boost::bad_any_cast &e)
{
LOG(WARNING) << "msg_handler_telemetry Bad any cast!";
rx_message = 0;
}
}
BeidouB1iPcpsAcquisitionTest_msg_rx::BeidouB1iPcpsAcquisitionTest_msg_rx() : gr::block("BeidouB1iPcpsAcquisitionTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0))
{
this->message_port_register_in(pmt::mp("events"));
this->set_msg_handler(pmt::mp("events"), boost::bind(&BeidouB1iPcpsAcquisitionTest_msg_rx::msg_handler_events, this, _1));
rx_message = 0;
}
BeidouB1iPcpsAcquisitionTest_msg_rx::~BeidouB1iPcpsAcquisitionTest_msg_rx()
{
}
// ###########################################################
class BeidouB1iPcpsAcquisitionTest : public ::testing::Test
{
protected:
BeidouB1iPcpsAcquisitionTest()
{
factory = std::make_shared<GNSSBlockFactory>();
config = std::make_shared<InMemoryConfiguration>();
item_size = sizeof(gr_complex);
gnss_synchro = Gnss_Synchro();
doppler_max = 5000;
doppler_step = 100;
}
~BeidouB1iPcpsAcquisitionTest()
{
}
void init();
void plot_grid();
gr::top_block_sptr top_block;
std::shared_ptr<GNSSBlockFactory> factory;
std::shared_ptr<InMemoryConfiguration> config;
Gnss_Synchro gnss_synchro;
size_t item_size;
unsigned int doppler_max;
unsigned int doppler_step;
};
void BeidouB1iPcpsAcquisitionTest::init()
{
gnss_synchro.Channel_ID = 0;
gnss_synchro.System = 'C';
std::string signal = "B1";
signal.copy(gnss_synchro.Signal, 2, 0);
gnss_synchro.PRN = 1;
config->set_property("GNSS-SDR.internal_fs_sps", "25000000");
config->set_property("Acquisition_B1.implementation", "BEIDOU_B1I_PCPS_Acquisition");
config->set_property("Acquisition_B1.item_type", "gr_complex");
config->set_property("Acquisition_B1.coherent_integration_time_ms", "1");
if (FLAGS_plot_acq_grid == true)
{
config->set_property("Acquisition_B1.dump", "true");
}
else
{
config->set_property("Acquisition_B1.dump", "false");
}
config->set_property("Acquisition_B1.dump_filename", "./tmp-acq-beidou1/acquisition");
config->set_property("Acquisition_B1.threshold", "0.00001");
config->set_property("Acquisition_B1.doppler_max", std::to_string(doppler_max));
config->set_property("Acquisition_B1.doppler_step", std::to_string(doppler_step));
config->set_property("Acquisition_B1.repeat_satellite", "false");
//config->set_property("Acquisition_B1.pfa", "0.0");
}
void BeidouB1iPcpsAcquisitionTest::plot_grid()
{
//load the measured values
std::string basename = "./tmp-acq-beidou1/acquisition_C_B1";
unsigned int sat = static_cast<unsigned int>(gnss_synchro.PRN);
unsigned int samples_per_code = static_cast<unsigned int>(round(4000000 / (BEIDOU_B1I_CODE_RATE_HZ / BEIDOU_B1I_CODE_LENGTH_CHIPS))); // !!
acquisition_dump_reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code);
if (!acq_dump.read_binary_acq()) std::cout << "Error reading files" << std::endl;
std::vector<int> *doppler = &acq_dump.doppler;
std::vector<unsigned int> *samples = &acq_dump.samples;
std::vector<std::vector<float> > *mag = &acq_dump.mag;
const std::string gnuplot_executable(FLAGS_gnuplot_executable);
if (gnuplot_executable.empty())
{
std::cout << "WARNING: Although the flag plot_acq_grid has been set to TRUE," << std::endl;
std::cout << "gnuplot has not been found in your system." << std::endl;
std::cout << "Test results will not be plotted." << std::endl;
}
else
{
std::cout << "Plotting the acquisition grid. This can take a while..." << std::endl;
try
{
boost::filesystem::path p(gnuplot_executable);
boost::filesystem::path dir = p.parent_path();
std::string gnuplot_path = dir.native();
Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("lines");
g1.set_title("BeiDou signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN));
g1.set_xlabel("Doppler [Hz]");
g1.set_ylabel("Sample");
//g1.cmd("set view 60, 105, 1, 1");
g1.plot_grid3d(*doppler, *samples, *mag);
g1.savetops("BEIDOU_B1I_acq_grid");
g1.savetopdf("BEIDOU_BI1_acq_grid");
g1.showonscreen();
}
catch (const GnuplotException &ge)
{
std::cout << ge.what() << std::endl;
}
}
std::string data_str = "./tmp-acq-beidou1";
if (boost::filesystem::exists(data_str))
{
boost::filesystem::remove_all(data_str);
}
}
TEST_F(BeidouB1iPcpsAcquisitionTest, Instantiate)
{
init();
boost::shared_ptr<BeidouB1iPcpsAcquisition> acquisition = boost::make_shared<BeidouB1iPcpsAcquisition>(config.get(), "Acquisition_B1", 1, 0);
}
TEST_F(BeidouB1iPcpsAcquisitionTest, ConnectAndRun)
{
int fs_in = 25000000;
int nsamples = 4000;
std::chrono::time_point<std::chrono::system_clock> start, end;
std::chrono::duration<double> elapsed_seconds(0);
gr::msg_queue::sptr queue = gr::msg_queue::make(0);
top_block = gr::make_top_block("Acquisition test");
init();
boost::shared_ptr<BeidouB1iPcpsAcquisition> acquisition = boost::make_shared<BeidouB1iPcpsAcquisition>(config.get(), "Acquisition_B1", 1, 0);
boost::shared_ptr<BeidouB1iPcpsAcquisitionTest_msg_rx> msg_rx = BeidouB1iPcpsAcquisitionTest_msg_rx_make();
ASSERT_NO_THROW({
acquisition->connect(top_block);
boost::shared_ptr<gr::analog::sig_source_c> source = gr::analog::sig_source_c::make(fs_in, gr::analog::GR_SIN_WAVE, 1000, 1, gr_complex(0));
boost::shared_ptr<gr::block> valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue);
top_block->connect(source, 0, valve, 0);
top_block->connect(valve, 0, acquisition->get_left_block(), 0);
top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
}) << "Failure connecting the blocks of acquisition test.";
EXPECT_NO_THROW({
start = std::chrono::system_clock::now();
top_block->run(); // Start threads and wait
end = std::chrono::system_clock::now();
elapsed_seconds = end - start;
}) << "Failure running the top_block.";
std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl;
}
TEST_F(BeidouB1iPcpsAcquisitionTest, ValidationOfResults)
{
std::chrono::time_point<std::chrono::system_clock> start, end;
std::chrono::duration<double> elapsed_seconds(0.0);
top_block = gr::make_top_block("Acquisition test");
double expected_delay_samples = 524;
double expected_doppler_hz = 1680;
init();
if (FLAGS_plot_acq_grid == true)
{
std::string data_str = "./tmp-acq-beidou1";
if (boost::filesystem::exists(data_str))
{
boost::filesystem::remove_all(data_str);
}
boost::filesystem::create_directory(data_str);
}
std::shared_ptr<BeidouB1iPcpsAcquisition> acquisition = std::make_shared<BeidouB1iPcpsAcquisition>(config.get(), "Acquisition_B1", 1, 0);
boost::shared_ptr<BeidouB1iPcpsAcquisitionTest_msg_rx> msg_rx = BeidouB1iPcpsAcquisitionTest_msg_rx_make();
ASSERT_NO_THROW({
acquisition->set_channel(1);
}) << "Failure setting channel.";
ASSERT_NO_THROW({
acquisition->set_gnss_synchro(&gnss_synchro);
}) << "Failure setting gnss_synchro.";
ASSERT_NO_THROW({
acquisition->set_threshold(0.001);
}) << "Failure setting threshold.";
ASSERT_NO_THROW({
acquisition->set_doppler_max(doppler_max);
}) << "Failure setting doppler_max.";
ASSERT_NO_THROW({
acquisition->set_doppler_step(doppler_step);
}) << "Failure setting doppler_step.";
ASSERT_NO_THROW({
acquisition->connect(top_block);
}) << "Failure connecting acquisition to the top_block.";
ASSERT_NO_THROW({
std::string path = std::string(TEST_PATH);
std::string file = path + "signal_samples/BEIDOU_B1I_ID_1_Fs_4Msps_2ms.dat";
const char *file_name = file.c_str();
gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false);
top_block->connect(file_source, 0, acquisition->get_left_block(), 0);
top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
}) << "Failure connecting the blocks of acquisition test.";
acquisition->set_local_code();
acquisition->set_state(1); // Ensure that acquisition starts at the first sample
acquisition->init();
EXPECT_NO_THROW({
start = std::chrono::system_clock::now();
top_block->run(); // Start threads and wait
end = std::chrono::system_clock::now();
elapsed_seconds = end - start;
}) << "Failure running the top_block.";
unsigned long int nsamples = gnss_synchro.Acq_samplestamp_samples;
std::cout << "Acquired " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl;
ASSERT_EQ(1, msg_rx->rx_message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS.";
double delay_error_samples = std::abs(expected_delay_samples - gnss_synchro.Acq_delay_samples);
float delay_error_chips = static_cast<float>(delay_error_samples * 1023 / 4000);
double doppler_error_hz = std::abs(expected_doppler_hz - gnss_synchro.Acq_doppler_hz);
EXPECT_LE(doppler_error_hz, 666) << "Doppler error exceeds the expected value: 666 Hz = 2/(3*integration period)";
EXPECT_LT(delay_error_chips, 0.5) << "Delay error exceeds the expected value: 0.5 chips";
if (FLAGS_plot_acq_grid == true)
{
plot_grid();
}
}

View File

@ -34,15 +34,15 @@ if ~exist('dll_pll_veml_read_tracking_dump.m', 'file')
addpath('./libs')
end
samplingFreq = 5000000; %[Hz]
coherent_integration_time_ms = 20; %[ms]
channels = 5; % Number of channels
samplingFreq = 25000000; %[Hz]
coherent_integration_time_ms = 1; %[ms]
channels = 8; % Number of channels
first_channel = 0; % Number of the first channel
path = '/dump_dir/'; %% CHANGE THIS PATH
path = '/home/sergi/gnss/gnss-sdr/install/'; %% CHANGE THIS PATH
for N=1:1:channels
tracking_log_path = [path 'track_ch_' num2str(N+first_channel-1) '.dat']; %% CHANGE track_ch_ BY YOUR dump_filename
tracking_log_path = [path 'epl_tracking_ch_' num2str(N+first_channel-1) '.dat']; %% CHANGE track_ch_ BY YOUR dump_filename
GNSS_tracking(N) = dll_pll_veml_read_tracking_dump(tracking_log_path);
end

View File

@ -38,7 +38,7 @@ samplingFreq = 6625000; %[Hz]
channels = 5;
first_channel = 0;
path = '/archive/'; %% CHANGE THIS PATH
path = '/home/sergi/gnss/gnss-sdr/install/'; %% CHANGE THIS PATH
for N=1:1:channels
tracking_log_path = [path 'epl_tracking_ch_' num2str(N+first_channel-1) '.dat']; %% CHANGE epl_tracking_ch_ BY YOUR dump_filename
@ -65,7 +65,7 @@ for N=1:1:channels
trackResults(N).Q_L = zeros(1,length(GNSS_tracking(N).E));
trackResults(N).PRN = ones(1,length(GNSS_tracking(N).E));
trackResults(N).CNo = GNSS_tracking(N).CN0_SNV_dB_Hz.';
% Use original MATLAB tracking plot function
settings.numberOfChannels = channels;
settings.msToProcess = length(GNSS_tracking(N).E);

View File

@ -30,7 +30,7 @@
%clear all;
samplingFreq = 64e6/16; %[Hz]
channels=4;
path='/home/javier/workspace/gnss-sdr-ref/trunk/install/';
path='/home/sergi/gnss/gnss-sdr/install/';
clear PRN_absolute_sample_start;
for N=1:1:channels
telemetry_log_path=[path 'telemetry' num2str(N-1) '.dat'];

Binary file not shown.