1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-06-25 22:43:14 +00:00

Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into fpga

This commit is contained in:
Marc Majoral 2019-01-30 10:28:52 +01:00
commit bb0fae98c7
59 changed files with 7066 additions and 99 deletions

View File

@ -2,18 +2,20 @@
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
**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:
In the L1 band:
- 🛰 BeiDou B1I (centered at 1561.098 MHz) :white_check_mark:
- 🛰 GPS L1 C/A (centered at 1575.42 MHz) :white_check_mark:
- 🛰 Galileo E1b/c (centered at 1575.42 MHz) :white_check_mark:
- 🛰 GLONASS L1 C/A (centered at 1601.72 MHz) :white_check_mark:
- 🛰 GLONASS L1 C/A (centered at 1602.00 MHz) :white_check_mark:
In the L2 band:
- 🛰 GPS L2C (centered at 1227.60 MHz) :white_check_mark:
- 🛰 GLONASS L2 C/A (centered at 1246 MHz) :white_check_mark:
- 🛰 GLONASS L2 C/A (centered at 1246.00 MHz) :white_check_mark:
In the L5 band:
- 🛰 GPS L5 (centered at 1176.45 MHz) :white_check_mark:
@ -187,9 +189,9 @@ $ sudo apt-get install libblas-dev liblapack-dev # For Debian/Ubuntu/Linux
$ sudo yum install lapack-devel blas-devel # For Fedora/CentOS/RHEL
$ sudo zypper install lapack-devel blas-devel # For OpenSUSE
$ sudo pacman -S blas lapack # For Arch Linux
$ wget https://sourceforge.net/projects/arma/files/armadillo-9.100.5.tar.xz
$ tar xvfz armadillo-9.100.5.tar.xz
$ cd armadillo-9.100.5
$ wget https://sourceforge.net/projects/arma/files/armadillo-9.200.7.tar.xz
$ tar xvfz armadillo-9.200.7.tar.xz
$ cd armadillo-9.200.7
$ cmake .
$ make
$ sudo make install
@ -1116,6 +1118,7 @@ Each channel must be assigned to a GNSS signal, according to the following ident
| GPS L1 C/A | 1C |
| Galileo E1b/c | 1B |
| Glonass L1 C/A | 1G |
| Beidou B1I | B1 |
| GPS L2 L2C(M) | 2S |
| Glonass L2 C/A | 2G |
| GPS L5 | L5 |

View File

@ -0,0 +1,121 @@
; 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/dmiralles/Documents/GNSS-Metadata-Standard/install/BdsB1IStr01.dat
SignalSource.item_type=byte
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=Byte_To_Short
InputFilter.implementation=Freq_Xlating_Fir_Filter
InputFilter.input_item_type=short
InputFilter.output_item_type=gr_complex
InputFilter.taps_item_type=float
InputFilter.number_of_taps=5
InputFilter.number_of_bands=2
InputFilter.band1_begin=0.0
InputFilter.band1_end=0.70
InputFilter.band2_begin=0.80
InputFilter.band2_end=1.0
InputFilter.ampl1_begin=1.0
InputFilter.ampl1_end=1.0
InputFilter.ampl2_begin=0.0
InputFilter.ampl2_end=0.0
InputFilter.band1_error=1.0
InputFilter.band2_error=1.0
InputFilter.filter_type=bandpass
InputFilter.grid_density=16
InputFilter.sampling_frequency=25000000
InputFilter.IF=6250000
Resampler.implementation=Pass_Through
Resampler.sample_freq_in=25000000
Resampler.sample_freq_out=25000000
Resampler.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channels_B1.count=10
Channels.in_acquisition=1
Channel.signal=B1
Channel0.satellite = 6;
Channel1.satellite = 8;
Channel2.satellite = 9;
Channel3.satellite = 13;
Channel4.satellite = 17;
Channel5.satellite = 1;
Channel6.satellite = 2;
Channel7.satellite = 3;
Channel8.satellite = 4;
Channel9.satellite = 5;
;######### 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=0.0038
;Acquisition_B1.pfa=0.0000001;
Acquisition_B1.doppler_max=15000
Acquisition_B1.doppler_step=100
Acquisition_B1.dump=true
Acquisition_B1.dump_filename=./bds_acq
Acquisition_B1.blocking=false;
Acquisition_B1.use_CFAR_algorithm=true;
Acquisition_B1.bit_transition_flag = false;
;######### TRACKING GLOBAL CONFIG ############
Tracking_B1.implementation=BEIDOU_B1I_DLL_PLL_Tracking
Tracking_B1.item_type=gr_complex
Tracking_B1.pll_bw_hz=25.0;
Tracking_B1.dll_bw_hz=2.50;
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=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=true
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=Single ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=OFF ; 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=true

View File

@ -0,0 +1,100 @@
; 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 [Hz].
GNSS-SDR.internal_fs_sps=6625000
;######### CONTROL_THREAD CONFIG ############
ControlThread.wait_for_flowgraph=false
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=/home/dmiralles/Documents/GSOC/GSOC2017/gnss-sdr/data/dmirallesNT1065_L2_20160831_fs6625e6_60e3_schar_1H.bin
SignalSource.item_type=ibyte
SignalSource.sampling_frequency=6625000
SignalSource.freq=1602000000
SignalSource.samples=0
SignalSource.repeat=false
SignalSource.sample_type=iq
SignalSource.seconds_to_skip=0
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
DataTypeAdapter.implementation=Ibyte_To_Complex
InputFilter.implementation=Pass_Through
;InputFilter.input_item_type=gr_complex
;InputFilter.output_item_type=gr_complex
InputFilter.item_type=gr_complex
;Resampler.implementation=Pass_Through
;Resampler.item_type=gr_complex
Resampler.implementation=Pass_Through
;Resampler.sample_freq_in=4000000
;Resampler.sample_freq_out=2000000
;Resampler.item_type=gr_complex
Resampler.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channels_1R.count=8 ;Assuming here that identifier `1r=R` defines GLONASS SP signals
Channels.in_acquisition=1
Channel.signal=1R
;Channel.item_type=cshort
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1R.dump=false
Acquisition_1R.dump_filename=./acq_dump.dat
Acquisition_1R.item_type=cshort
Acquisition_1R.sampled_ms=1
Acquisition_1R.implementation=GLONASS_L1_CA_PCPS_Acquisition
Acquisition_1R.threshold=0.008
;Acquisition_1C.pfa=0.000001
Acquisition_1R.doppler_max=10000
Acquisition_1R.doppler_step=250
Acquisition_1R.tong_init_val=2
Acquisition_1R.tong_max_val=10
Acquisition_1R.tong_max_dwells=20
;######### TRACKING GLOBAL CONFIG ############
Tracking_1R.implementation=GLONASS_L1_CA_DLL_PLL_C_Aid_Tracking
Tracking_1R.item_type=cshort
Tracking_1R.dump=false
Tracking_1R.dump_filename=../data/epl_tracking_ch_
Tracking_1R.pll_bw_hz=40.0;
Tracking_1R.dll_bw_hz=4.0;
Tracking_1R.order=3;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1R.implementation=GLONASS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1R.dump=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false
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

@ -1,3 +1,10 @@
## [Unreleased](https://github.com/gnss-sdr/gnss-sdr/tree/next)
### Improvements in Interoperability:
- Added the BeiDou B1I receiver chain.
## [0.0.10](https://github.com/gnss-sdr/gnss-sdr/releases/tag/v0.0.10)
This release has several improvements in different dimensions, addition of new features and bug fixes:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

@ -170,6 +170,15 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration,
* 26 | GPS L1 C/A + GLONASS L1 C/A
* 27 | Galileo E1B + GLONASS L1 C/A
* 28 | GPS L2C + GLONASS L1 C/A
*
*
* Skipped previous values to avoid overlapping
* 50 | Beidou B1I
* 51 | Beidou B1I + GPS L1 C/A
* 52 | Beidou B1I + Galileo E1B
* 53 | Beidou B1I + GLONASS L1 C/A
* 54 | Beidou B1I + GPS L1 C/A + Galileo E1B
* 55 | Beidou B1I + GPS L1 C/A + GLONASS L1 C/A + Galileo E1B
*/
int gps_1C_count = configuration->property("Channels_1C.count", 0);
int gps_2S_count = configuration->property("Channels_2S.count", 0);
@ -179,42 +188,49 @@ 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);
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)) pvt_output_parameters.type_of_receiver = 1; // L1
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)) pvt_output_parameters.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)) pvt_output_parameters.type_of_receiver = 3; // L5
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)) pvt_output_parameters.type_of_receiver = 4; // E1
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)) pvt_output_parameters.type_of_receiver = 5; // E5a
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)) pvt_output_parameters.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)) pvt_output_parameters.type_of_receiver = 1; // L1
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)) pvt_output_parameters.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)) pvt_output_parameters.type_of_receiver = 3; // L5
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)) pvt_output_parameters.type_of_receiver = 4; // E1
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)) pvt_output_parameters.type_of_receiver = 5; // E5a
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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.type_of_receiver = 8; // L1+L5
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)) pvt_output_parameters.type_of_receiver = 9; // L1+E1
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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.type_of_receiver = 13; // L5+E5a
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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.type_of_receiver = 8; // L1+L5
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)) pvt_output_parameters.type_of_receiver = 9; // L1+E1
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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.type_of_receiver = 13; // L5+E5a
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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.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)) pvt_output_parameters.type_of_receiver = 32; // L1+E1+L5+E5a
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)) pvt_output_parameters.type_of_receiver = 33; // L1+E1+E5a
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)) pvt_output_parameters.type_of_receiver = 32; // L1+E1+L5+E5a
// BeiDou B1I Receiver
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)) pvt_output_parameters.type_of_receiver = 50;
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)) pvt_output_parameters.type_of_receiver = 51;
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)) pvt_output_parameters.type_of_receiver = 52;
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)) pvt_output_parameters.type_of_receiver = 53;
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)) pvt_output_parameters.type_of_receiver = 54;
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)) pvt_output_parameters.type_of_receiver = 55;
// RTKLIB PVT solver options
// Settings 1
@ -239,7 +255,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;
@ -326,6 +342,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

@ -221,6 +221,45 @@ 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_Dnav_Ephemeris>))
{
// ### Beidou EPHEMERIS ###
std::shared_ptr<Beidou_Dnav_Ephemeris> bds_dnav_eph;
bds_dnav_eph = boost::any_cast<std::shared_ptr<Beidou_Dnav_Ephemeris>>(pmt::any_ref(msg));
DLOG(INFO) << "Ephemeris record has arrived from SAT ID "
<< bds_dnav_eph->i_satellite_PRN << " (Block "
<< bds_dnav_eph->satelliteBlock[bds_dnav_eph->i_satellite_PRN] << ")"
<< "inserted with Toe=" << bds_dnav_eph->d_Toe << " and BDS Week="
<< bds_dnav_eph->i_BEIDOU_week;
// update/insert new ephemeris record to the global ephemeris map
d_pvt_solver->beidou_dnav_ephemeris_map[bds_dnav_eph->i_satellite_PRN] = *bds_dnav_eph;
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Beidou_Dnav_Iono>))
{
// ### BeiDou IONO ###
std::shared_ptr<Beidou_Dnav_Iono> bds_dnav_iono;
bds_dnav_iono = boost::any_cast<std::shared_ptr<Beidou_Dnav_Iono>>(pmt::any_ref(msg));
d_pvt_solver->beidou_dnav_iono = *bds_dnav_iono;
DLOG(INFO) << "New BeiDou DNAV IONO record has arrived ";
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Beidou_Dnav_Utc_Model>))
{
// ### GPS UTC MODEL ###
std::shared_ptr<Beidou_Dnav_Utc_Model> bds_dnav_utc_model;
bds_dnav_utc_model = boost::any_cast<std::shared_ptr<Beidou_Dnav_Utc_Model>>(pmt::any_ref(msg));
d_pvt_solver->beidou_dnav_utc_model = *bds_dnav_utc_model;
DLOG(INFO) << "New BeiDou DNAV UTC record has arrived ";
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Beidou_Dnav_Almanac>))
{
// ### GPS ALMANAC ###
std::shared_ptr<Beidou_Dnav_Almanac> bds_dnav_almanac;
bds_dnav_almanac = boost::any_cast<std::shared_ptr<Beidou_Dnav_Almanac>>(pmt::any_ref(msg));
d_pvt_solver->beidou_dnav_almanac_map[bds_dnav_almanac->i_satellite_PRN] = *bds_dnav_almanac;
DLOG(INFO) << "New BeiDou DNAV almanac record has arrived ";
}
else
{
LOG(WARNING) << "msg_handler_telemetry unknown object type!";
@ -257,12 +296,25 @@ std::map<int, Galileo_Almanac> rtklib_pvt_cc::get_galileo_almanac_map() const
}
std::map<int, Beidou_Dnav_Ephemeris> rtklib_pvt_cc::get_beidou_dnav_ephemeris_map() const
{
return d_pvt_solver->beidou_dnav_ephemeris_map;
}
std::map<int, Beidou_Dnav_Almanac> rtklib_pvt_cc::get_beidou_dnav_almanac_map() const
{
return d_pvt_solver->beidou_dnav_almanac_map;
}
void rtklib_pvt_cc::clear_ephemeris()
{
d_pvt_solver->gps_ephemeris_map.clear();
d_pvt_solver->gps_almanac_map.clear();
d_pvt_solver->galileo_ephemeris_map.clear();
d_pvt_solver->galileo_almanac_map.clear();
d_pvt_solver->beidou_dnav_ephemeris_map.clear();
d_pvt_solver->beidou_dnav_almanac_map.clear();
}
@ -832,6 +884,94 @@ rtklib_pvt_cc::~rtklib_pvt_cc()
{
LOG(INFO) << "Failed to save GLONASS GNAV ephemeris, not valid data";
}
// save BeiDou DNAV ephemeris to XML file
file_name = xml_base_path + "bds_dnav_ephemeris.xml";
if (d_pvt_solver->beidou_dnav_ephemeris_map.empty() == false)
{
std::ofstream ofs;
try
{
ofs.open(file_name.c_str(), std::ofstream::trunc | std::ofstream::out);
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_bds_dnav_ephemeris_map", d_pvt_solver->beidou_dnav_ephemeris_map);
LOG(INFO) << "Saved BeiDou DNAV Ephemeris map data";
}
catch (const std::exception& e)
{
LOG(WARNING) << e.what();
}
}
else
{
LOG(INFO) << "Failed to save BeiDou DNAV Ephemeris, map is empty";
}
// Save BeiDou DNAV iono parameters
file_name = xml_base_path + "bds_dnav_iono.xml";
if (d_pvt_solver->beidou_dnav_iono.valid)
{
std::ofstream ofs;
try
{
ofs.open(file_name.c_str(), std::ofstream::trunc | std::ofstream::out);
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_bds_dnav_iono_model", d_pvt_solver->beidou_dnav_iono);
LOG(INFO) << "Saved BeiDou DNAV ionospheric model parameters";
}
catch (std::exception& e)
{
LOG(WARNING) << e.what();
}
}
else
{
LOG(INFO) << "Failed to save BeiDou DNAV ionospheric model parameters, not valid data";
}
// save BeiDou DNAV almanac to XML file
file_name = xml_base_path + "bds_dnav_almanac.xml";
if (d_pvt_solver->beidou_dnav_almanac_map.empty() == false)
{
std::ofstream ofs;
try
{
ofs.open(file_name.c_str(), std::ofstream::trunc | std::ofstream::out);
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_bds_dnav_almanac_map", d_pvt_solver->beidou_dnav_almanac_map);
LOG(INFO) << "Saved BeiDou DNAV almanac map data";
}
catch (const std::exception& e)
{
LOG(WARNING) << e.what();
}
}
else
{
LOG(INFO) << "Failed to save BeiDou DNAV almanac, map is empty";
}
// Save BeiDou UTC model parameters
file_name = xml_base_path + "bds_dnav_utc_model.xml";
if (d_pvt_solver->beidou_dnav_utc_model.valid)
{
std::ofstream ofs;
try
{
ofs.open(file_name.c_str(), std::ofstream::trunc | std::ofstream::out);
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_bds_dnav_utc_model", d_pvt_solver->beidou_dnav_utc_model);
LOG(INFO) << "Saved BeiDou DNAV UTC model parameters";
}
catch (std::exception& e)
{
LOG(WARNING) << e.what();
}
}
else
{
LOG(INFO) << "Failed to save BeiDou DNAV UTC model parameters, not valid data";
}
}
}
@ -955,13 +1095,16 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
std::map<int, Galileo_Ephemeris>::const_iterator tmp_eph_iter_gal = d_pvt_solver->galileo_ephemeris_map.find(in[i][epoch].PRN);
std::map<int, Gps_CNAV_Ephemeris>::const_iterator tmp_eph_iter_cnav = d_pvt_solver->gps_cnav_ephemeris_map.find(in[i][epoch].PRN);
std::map<int, Glonass_Gnav_Ephemeris>::const_iterator tmp_eph_iter_glo_gnav = d_pvt_solver->glonass_gnav_ephemeris_map.find(in[i][epoch].PRN);
std::map<int, Beidou_Dnav_Ephemeris>::const_iterator tmp_eph_iter_bds_dnav = d_pvt_solver->beidou_dnav_ephemeris_map.find(in[i][epoch].PRN);
if (((tmp_eph_iter_gps->second.i_satellite_PRN == in[i][epoch].PRN) and (std::string(in[i][epoch].Signal) == "1C")) or
((tmp_eph_iter_cnav->second.i_satellite_PRN == in[i][epoch].PRN) and (std::string(in[i][epoch].Signal) == "2S")) or
((tmp_eph_iter_gal->second.i_satellite_PRN == in[i][epoch].PRN) and (std::string(in[i][epoch].Signal) == "1B")) or
((tmp_eph_iter_gal->second.i_satellite_PRN == in[i][epoch].PRN) and (std::string(in[i][epoch].Signal) == "5X")) or
((tmp_eph_iter_glo_gnav->second.i_satellite_PRN == in[i][epoch].PRN) and (std::string(in[i][epoch].Signal) == "1G")) or
((tmp_eph_iter_glo_gnav->second.i_satellite_PRN == in[i][epoch].PRN) and (std::string(in[i][epoch].Signal) == "2G")) or
((tmp_eph_iter_cnav->second.i_satellite_PRN == in[i][epoch].PRN) and (std::string(in[i][epoch].Signal) == "L5")))
((tmp_eph_iter_cnav->second.i_satellite_PRN == in[i][epoch].PRN) and (std::string(in[i][epoch].Signal) == "L5")) or
((tmp_eph_iter_bds_dnav->second.i_satellite_PRN == in[i][epoch].PRN) and (std::string(in[i][epoch].Signal) == "B1")))
{
// store valid observables in a map.
gnss_observables_map.insert(std::pair<int, Gnss_Synchro>(i, in[i][epoch]));
@ -1170,12 +1313,14 @@ 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_Dnav_Ephemeris>::const_iterator beidou_dnav_ephemeris_iter;
if (!b_rinex_header_written) // & we have utc data in nav message!
{
galileo_ephemeris_iter = d_pvt_solver->galileo_ephemeris_map.cbegin();
gps_ephemeris_iter = d_pvt_solver->gps_ephemeris_map.cbegin();
gps_cnav_ephemeris_iter = d_pvt_solver->gps_cnav_ephemeris_map.cbegin();
glonass_gnav_ephemeris_iter = d_pvt_solver->glonass_gnav_ephemeris_map.cbegin();
beidou_dnav_ephemeris_iter = d_pvt_solver->beidou_dnav_ephemeris_map.cbegin();
switch (type_of_rx)
{
case 1: // GPS L1 C/A only
@ -1420,6 +1565,15 @@ 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
}
break;
case 50: // BDS B1I only
if (beidou_dnav_ephemeris_iter != d_pvt_solver->beidou_dnav_ephemeris_map.cend())
{
rp->rinex_obs_header(rp->obsFile, beidou_dnav_ephemeris_iter->second, d_rx_time, "B1");
rp->rinex_nav_header(rp->navFile, d_pvt_solver->beidou_dnav_iono, d_pvt_solver->beidou_dnav_utc_model);
b_rinex_header_written = true; // do not write header anymore
}
break;
default:
break;
}
@ -1503,6 +1657,9 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
case 33: // L1+E1+E5a
rp->log_rinex_nav(rp->navMixFile, d_pvt_solver->gps_ephemeris_map, d_pvt_solver->galileo_ephemeris_map);
break;
case 50: // BDS B1I only
rp->log_rinex_nav(rp->navFile, d_pvt_solver->beidou_dnav_ephemeris_map);
break;
default:
break;
}
@ -1511,6 +1668,7 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
gps_ephemeris_iter = d_pvt_solver->gps_ephemeris_map.cbegin();
gps_cnav_ephemeris_iter = d_pvt_solver->gps_cnav_ephemeris_map.cbegin();
glonass_gnav_ephemeris_iter = d_pvt_solver->glonass_gnav_ephemeris_map.cbegin();
beidou_dnav_ephemeris_iter = d_pvt_solver->beidou_dnav_ephemeris_map.cbegin();
// Log observables into the RINEX file
if (flag_write_RINEX_obs_output)
@ -1809,6 +1967,18 @@ 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
}
break;
case 50: // BDS B1I only
if (beidou_dnav_ephemeris_iter != d_pvt_solver->beidou_dnav_ephemeris_map.cend())
{
rp->log_rinex_obs(rp->obsFile, beidou_dnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, "B1");
}
if (!b_rinex_header_updated and (d_pvt_solver->beidou_dnav_utc_model.d_A0_UTC != 0))
{
rp->update_obs_header(rp->obsFile, d_pvt_solver->beidou_dnav_utc_model);
rp->update_nav_header(rp->navFile, d_pvt_solver->beidou_dnav_utc_model, d_pvt_solver->beidou_dnav_iono);
b_rinex_header_updated = true;
}
break;
default:
break;
}
@ -1922,7 +2092,7 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
std::string system(&gnss_observables_iter->second.System, 1);
if (gps_channel == 0)
{
if (system == "G")
if (system.compare("G") == 0)
{
// This is a channel with valid GPS signal
gps_eph_iter = d_pvt_solver->gps_ephemeris_map.find(gnss_observables_iter->second.PRN);
@ -1934,7 +2104,7 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
}
if (gal_channel == 0)
{
if (system == "E")
if (system.compare("E") == 0)
{
gal_eph_iter = d_pvt_solver->galileo_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (gal_eph_iter != d_pvt_solver->galileo_ephemeris_map.cend())

View File

@ -161,6 +161,10 @@ public:
std::map<int, Galileo_Almanac> get_galileo_almanac_map() const;
std::map<int, Beidou_Dnav_Ephemeris> get_beidou_dnav_ephemeris_map() const;
std::map<int, Beidou_Dnav_Almanac> get_beidou_dnav_almanac_map() const;
/*!
* \brief Clear all ephemeris information and the almanacs for GPS and Galileo
*

View File

@ -89,6 +89,7 @@ Rinex_Printer::Rinex_Printer(int32_t conf_version, const std::string& base_path)
navGalfilename = base_rinex_path + boost::filesystem::path::preferred_separator + Rinex_Printer::createFilename("RINEX_FILE_TYPE_GAL_NAV");
navMixfilename = base_rinex_path + boost::filesystem::path::preferred_separator + Rinex_Printer::createFilename("RINEX_FILE_TYPE_MIXED_NAV");
navGlofilename = base_rinex_path + boost::filesystem::path::preferred_separator + Rinex_Printer::createFilename("RINEX_FILE_TYPE_GLO_NAV");
navBdsfilename = base_rinex_path + boost::filesystem::path::preferred_separator + Rinex_Printer::createFilename("RINEX_FILE_TYPE_BDS_NAV");
Rinex_Printer::navFile.open(navfilename, std::ios::out | std::ios::in | std::ios::app);
Rinex_Printer::obsFile.open(obsfilename, std::ios::out | std::ios::in | std::ios::app);
@ -96,6 +97,8 @@ Rinex_Printer::Rinex_Printer(int32_t conf_version, const std::string& base_path)
Rinex_Printer::navGalFile.open(navGalfilename, std::ios::out | std::ios::in | std::ios::app);
Rinex_Printer::navMixFile.open(navMixfilename, std::ios::out | std::ios::in | std::ios::app);
Rinex_Printer::navGloFile.open(navGlofilename, std::ios::out | std::ios::in | std::ios::app);
Rinex_Printer::navBdsFile.open(navBdsfilename, std::ios::out | std::ios::in | std::ios::app);
if (!Rinex_Printer::navFile.is_open() or !Rinex_Printer::obsFile.is_open() or
!Rinex_Printer::sbsFile.is_open() or !Rinex_Printer::navGalFile.is_open() or
@ -167,6 +170,8 @@ Rinex_Printer::Rinex_Printer(int32_t conf_version, const std::string& base_path)
observationCode["COMPASS_E6_I"] = "6I";
observationCode["COMPASS_E6_Q"] = "6Q";
observationCode["COMPASS_E6_IQ"] = "6X";
observationCode["BEIDOU_B1_I"] = "1I";
observationCode["BEIDOU_B1_Q"] = "1Q";
observationType["PSEUDORANGE"] = "C";
observationType["CARRIER_PHASE"] = "L";
@ -201,19 +206,21 @@ Rinex_Printer::Rinex_Printer(int32_t conf_version, const std::string& base_path)
Rinex_Printer::~Rinex_Printer()
{
// close RINEX files
int64_t posn, poso, poss, posng, posmn, posnr;
int64_t posn, poso, poss, posng, posmn, posnr, posnc;
posn = navFile.tellp();
poso = obsFile.tellp();
poss = sbsFile.tellp();
posng = navGalFile.tellp();
posmn = navMixFile.tellp();
posnr = navGloFile.tellp();
posnc = navBdsFile.tellp();
Rinex_Printer::navFile.close();
Rinex_Printer::obsFile.close();
Rinex_Printer::sbsFile.close();
Rinex_Printer::navGalFile.close();
Rinex_Printer::navGloFile.close();
Rinex_Printer::navBdsFile.close();
// If nothing written, erase the files.
if (posn == 0)
{
@ -239,6 +246,10 @@ Rinex_Printer::~Rinex_Printer()
{
if (remove(navGlofilename.c_str()) != 0) LOG(INFO) << "Error deleting temporary file";
}
if (posnc == 0)
{
if (remove(navBdsfilename.c_str()) != 0) LOG(INFO) << "Error deleting temporary file";
}
}
@ -276,6 +287,8 @@ std::string Rinex_Printer::createFilename(const std::string& type)
fileType.insert(std::pair<std::string, std::string>("RINEX_FILE_TYPE_SBAS", "B")); // B - SBAS broadcast data file.
fileType.insert(std::pair<std::string, std::string>("RINEX_FILE_TYPE_CLK", "C")); // C - Clock file.
fileType.insert(std::pair<std::string, std::string>("RINEX_FILE_TYPE_SUMMARY", "S")); // S - Summary file (used e.g., by IGS, not a standard!).
fileType.insert(std::pair<std::string, std::string>("RINEX_FILE_TYPE_BDS_NAV", "F")); // G - GLONASS navigation file.
boost::posix_time::ptime pt = boost::posix_time::second_clock::local_time();
tm pt_tm = boost::posix_time::to_tm(pt);
@ -1542,6 +1555,120 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono
}
void Rinex_Printer::rinex_nav_header(std::fstream& out, const Beidou_Dnav_Iono& iono, const Beidou_Dnav_Utc_Model& utc_model)
{
std::string line;
// -------- Line 1
line = std::string(5, ' ');
line += stringVersion;
line += std::string(11, ' ');
if (version == 3)
{
line += std::string("N: GNSS NAV DATA");
line += std::string(4, ' ');
//! \todo Add here other systems...
line += std::string("F: BDS");
line += std::string(14, ' ');
// ...
}
line += std::string("RINEX VERSION / TYPE");
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line 2
line.clear();
line += Rinex_Printer::getLocalTime();
line += std::string("PGM / RUN BY / DATE");
line += std::string(1, ' ');
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line 3
line.clear();
line += Rinex_Printer::leftJustify("BDS NAVIGATION MESSAGE FILE GENERATED BY GNSS-SDR", 60);
line += Rinex_Printer::leftJustify("COMMENT", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line COMMENT
line.clear();
std::string gnss_sdr_version(GNSS_SDR_VERSION);
line += "GNSS-SDR VERSION ";
line += Rinex_Printer::leftJustify(gnss_sdr_version, 43);
line += Rinex_Printer::leftJustify("COMMENT", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line COMMENT
line.clear();
line += Rinex_Printer::leftJustify("See https://gnss-sdr.org", 60);
line += Rinex_Printer::leftJustify("COMMENT", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line ionospheric info 1, only version 3 supported
line.clear();
line += std::string("BDSA");
line += std::string(1, ' ');
line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_alpha0, 10, 2), 12);
line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_alpha1, 10, 2), 12);
line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_alpha2, 10, 2), 12);
line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_alpha3, 10, 2), 12);
line += std::string(7, ' ');
line += Rinex_Printer::leftJustify("IONOSPHERIC CORR", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line ionospheric info 2
line.clear();
line += std::string("BDSB");
line += std::string(1, ' ');
line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_beta0, 10, 2), 12);
line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_beta1, 10, 2), 12);
line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_beta2, 10, 2), 12);
line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_beta3, 10, 2), 12);
line += std::string(7, ' ');
line += Rinex_Printer::leftJustify("IONOSPHERIC CORR", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line 5 system time correction
line.clear();
line += std::string("BDUT");
line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(utc_model.d_A0_UTC, 16, 2), 18);
line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(utc_model.d_A1_UTC, 15, 2), 16);
line += std::string(22, ' ');
line += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line 6 leap seconds
// For leap second information, see http://www.endruntechnologies.com/leap.htm
line.clear();
line += Rinex_Printer::rightJustify(boost::lexical_cast<std::string>(utc_model.d_DeltaT_LS), 6);
line += Rinex_Printer::rightJustify(boost::lexical_cast<std::string>(utc_model.d_DeltaT_LSF), 6);
line += Rinex_Printer::rightJustify(std::to_string(utc_model.i_WN_LSF), 6);
line += Rinex_Printer::rightJustify(std::to_string(utc_model.i_DN), 6);
line += std::string(36, ' ');
line += Rinex_Printer::leftJustify("LEAP SECONDS", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- End of Header
line.clear();
line += std::string(60, ' ');
line += Rinex_Printer::leftJustify("END OF HEADER", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
}
void Rinex_Printer::rinex_sbs_header(std::fstream& out)
{
std::string line;
@ -2643,6 +2770,98 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Galileo_Iono& gal
}
void Rinex_Printer::update_nav_header(std::fstream& out, const Beidou_Dnav_Utc_Model& utc_model, const Beidou_Dnav_Iono& iono)
{
std::vector<std::string> data;
std::string line_aux;
int64_t pos = out.tellp();
out.seekp(0);
data.clear();
bool no_more_finds = false;
std::string line_str;
while (!out.eof())
{
std::getline(out, line_str);
if (!no_more_finds)
{
line_aux.clear();
if (line_str.find("BDSA", 0) != std::string::npos)
{
line_aux += std::string("GPSA");
line_aux += std::string(1, ' ');
line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_alpha0, 10, 2), 12);
line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_alpha1, 10, 2), 12);
line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_alpha2, 10, 2), 12);
line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_alpha3, 10, 2), 12);
line_aux += std::string(7, ' ');
line_aux += Rinex_Printer::leftJustify("IONOSPHERIC CORR", 20);
data.push_back(line_aux);
}
else if (line_str.find("BDSB", 0) != std::string::npos)
{
line_aux += std::string("GPSB");
line_aux += std::string(1, ' ');
line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_beta0, 10, 2), 12);
line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_beta1, 10, 2), 12);
line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_beta2, 10, 2), 12);
line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.d_beta3, 10, 2), 12);
line_aux += std::string(7, ' ');
line_aux += Rinex_Printer::leftJustify("IONOSPHERIC CORR", 20);
data.push_back(line_aux);
}
else if (line_str.find("BDUT", 0) != std::string::npos)
{
line_aux += std::string("GPUT");
line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(utc_model.d_A0_UTC, 16, 2), 18);
line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(utc_model.d_A1_UTC, 15, 2), 16);
line_aux += std::string(22, ' ');
line_aux += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20);
data.push_back(line_aux);
}
else if (line_str.find("LEAP SECONDS", 59) != std::string::npos)
{
line_aux += Rinex_Printer::rightJustify(boost::lexical_cast<std::string>(utc_model.d_DeltaT_LS), 6);
line_aux += Rinex_Printer::rightJustify(boost::lexical_cast<std::string>(utc_model.d_DeltaT_LSF), 6);
line_aux += Rinex_Printer::rightJustify(std::to_string(utc_model.i_WN_LSF), 6);
line_aux += Rinex_Printer::rightJustify(std::to_string(utc_model.i_DN), 6);
line_aux += std::string(36, ' ');
line_aux += Rinex_Printer::leftJustify("LEAP SECONDS", 20);
data.push_back(line_aux);
}
else if (line_str.find("END OF HEADER", 59) != std::string::npos)
{
data.push_back(line_str);
no_more_finds = true;
}
else
{
data.push_back(line_str);
}
}
else
{
data.push_back(line_str);
}
}
out.close();
out.open(navfilename, std::ios::out | std::ios::trunc);
out.seekp(0);
for (int32_t i = 0; i < static_cast<int32_t>(data.size()) - 1; i++)
{
out << data[i] << std::endl;
}
out.close();
out.open(navfilename, std::ios::out | std::ios::app);
out.seekp(pos);
std::cout << "The RINEX Navigation file header has been updated with UTC and IONO info." << std::endl;
}
void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map<int32_t, Gps_Ephemeris>& eph_map)
{
std::string line;
@ -3529,6 +3748,146 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map<int32_t, Gal
}
void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map<int32_t, Beidou_Dnav_Ephemeris>& eph_map)
{
std::string line;
std::map<int32_t, Beidou_Dnav_Ephemeris>::const_iterator bds_ephemeris_iter;
for (bds_ephemeris_iter = eph_map.cbegin();
bds_ephemeris_iter != eph_map.cend();
bds_ephemeris_iter++)
{
// -------- SV / EPOCH / SV CLK
boost::posix_time::ptime p_utc_time = Rinex_Printer::compute_BDS_time(bds_ephemeris_iter->second, bds_ephemeris_iter->second.d_Toc);
std::string timestring = boost::posix_time::to_iso_string(p_utc_time);
std::string month(timestring, 4, 2);
std::string day(timestring, 6, 2);
std::string hour(timestring, 9, 2);
std::string minutes(timestring, 11, 2);
std::string seconds(timestring, 13, 2);
line += satelliteSystem["Beidou"];
if (bds_ephemeris_iter->second.i_satellite_PRN < 10) line += std::string("0");
line += std::to_string(bds_ephemeris_iter->second.i_satellite_PRN);
std::string year(timestring, 0, 4);
line += std::string(1, ' ');
line += year;
line += std::string(1, ' ');
line += month;
line += std::string(1, ' ');
line += day;
line += std::string(1, ' ');
line += hour;
line += std::string(1, ' ');
line += minutes;
line += std::string(1, ' ');
line += seconds;
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_A_f0, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_A_f1, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_A_f2, 18, 2);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- BROADCAST ORBIT - 1
line.clear();
line += std::string(5, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_AODE, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_Crs, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_Delta_n, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_M_0, 18, 2);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- BROADCAST ORBIT - 2
line.clear();
line += std::string(5, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_Cuc, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_eccentricity, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_Cus, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_sqrt_A, 18, 2);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- BROADCAST ORBIT - 3
line.clear();
line += std::string(5, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_Toe, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_Cic, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_OMEGA0, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_Cis, 18, 2);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- BROADCAST ORBIT - 4
line.clear();
line += std::string(5, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_i_0, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_Crc, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_OMEGA, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_OMEGA_DOT, 18, 2);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- BROADCAST ORBIT - 5
line.clear();
line += std::string(5, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_IDOT, 18, 2);
line += std::string(1, ' ');
line += std::string(18, ' '); // spare
line += std::string(1, ' ');
auto BDS_week_continuous_number = static_cast<double>(bds_ephemeris_iter->second.i_BEIDOU_week);
line += Rinex_Printer::doub2for(BDS_week_continuous_number, 18, 2);
line += std::string(1, ' ');
line += std::string(18, ' '); // spare
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- BROADCAST ORBIT - 6
line.clear();
line += std::string(5, ' ');
line += Rinex_Printer::doub2for(static_cast<double>(bds_ephemeris_iter->second.i_SV_accuracy), 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(static_cast<double>(bds_ephemeris_iter->second.i_SV_health), 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_TGD1, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_TGD2, 18, 2);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- BROADCAST ORBIT - 7
line.clear();
line += std::string(5, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_TOW, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(bds_ephemeris_iter->second.d_AODC, 18, 2);
line += std::string(1, ' ');
line += std::string(18, ' '); // spare
line += std::string(1, ' ');
line += std::string(18, ' '); // spare
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
line.clear();
}
}
void Rinex_Printer::rinex_obs_header(std::fstream& out, const Glonass_Gnav_Ephemeris& eph, const double d_TOW_first_observation, const std::string& glonass_bands)
{
if (eph.d_m)
@ -6841,6 +7200,235 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps
}
void Rinex_Printer::rinex_obs_header(std::fstream& out, const Beidou_Dnav_Ephemeris& eph, const double d_TOW_first_observation, const std::string& bands)
{
std::string line;
version = 3;
// -------- Line 1
line = std::string(5, ' ');
line += "3.02";
line += std::string(11, ' ');
line += Rinex_Printer::leftJustify("OBSERVATION DATA", 20);
line += satelliteSystem["Beidou"];
line += std::string(19, ' ');
line += std::string("RINEX VERSION / TYPE");
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line 2
line.clear();
line += Rinex_Printer::leftJustify("G = GPS R = GLONASS E = GALILEO C = BEIDOU S = GEO M = MIXED", 60);
line += Rinex_Printer::leftJustify("COMMENT", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line 3
line.clear();
line += Rinex_Printer::getLocalTime();
line += std::string("PGM / RUN BY / DATE");
line += std::string(1, ' ');
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line COMMENT
line.clear();
line += Rinex_Printer::leftJustify("BEIDOU OBSERVATION DATA FILE GENERATED BY GNSS-SDR", 60);
line += Rinex_Printer::leftJustify("COMMENT", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line COMMENT
line.clear();
std::string gnss_sdr_version(GNSS_SDR_VERSION);
line += "GNSS-SDR VERSION ";
line += Rinex_Printer::leftJustify(gnss_sdr_version, 43);
line += Rinex_Printer::leftJustify("COMMENT", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line COMMENT
line.clear();
line += Rinex_Printer::leftJustify("See https://gnss-sdr.org", 60);
line += Rinex_Printer::leftJustify("COMMENT", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line MARKER NAME
line.clear();
line += Rinex_Printer::leftJustify("DEFAULT MARKER NAME", 60); // put a flag or a property,
line += Rinex_Printer::leftJustify("MARKER NAME", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line OBSERVER / AGENCY
line.clear();
std::string username;
char c_username[20] = {0};
int32_t nGet = getlogin_r(c_username, sizeof(c_username) - 1);
if (nGet == 0)
{
username = c_username;
}
else
{
username = "UNKNOWN USER";
}
line += leftJustify(username, 20);
line += Rinex_Printer::leftJustify("CTTC", 40); // add flag and property
line += Rinex_Printer::leftJustify("OBSERVER / AGENCY", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Line REC / TYPE VERS
line.clear();
line += Rinex_Printer::leftJustify("GNSS-SDR", 20); // add flag and property
line += Rinex_Printer::leftJustify("Software Receiver", 20); // add flag and property
//line += Rinex_Printer::leftJustify(google::VersionString(), 20); // add flag and property
if (gnss_sdr_version.length() > 20) gnss_sdr_version.resize(9, ' ');
line += Rinex_Printer::leftJustify(gnss_sdr_version, 20);
line += Rinex_Printer::leftJustify("REC # / TYPE / VERS", 20);
lengthCheck(line);
out << line << std::endl;
// -------- ANTENNA TYPE
line.clear();
line += Rinex_Printer::leftJustify("Antenna number", 20); // add flag and property
line += Rinex_Printer::leftJustify("Antenna type", 20); // add flag and property
line += std::string(20, ' ');
line += Rinex_Printer::leftJustify("ANT # / TYPE", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- APPROX POSITION (optional for moving platforms)
// put here real data!
double antena_x = 0.0;
double antena_y = 0.0;
double antena_z = 0.0;
line.clear();
line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_x, 4), 14);
line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_y, 4), 14);
line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_z, 4), 14);
line += std::string(18, ' ');
line += Rinex_Printer::leftJustify("APPROX POSITION XYZ", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- ANTENNA: DELTA H/E/N
// put here real data!
double antena_h = 0.0;
double antena_e = 0.0;
double antena_n = 0.0;
line.clear();
line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_h, 4), 14);
line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_e, 4), 14);
line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_n, 4), 14);
line += std::string(18, ' ');
line += Rinex_Printer::leftJustify("ANTENNA: DELTA H/E/N", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- SYS / OBS TYPES
// one line per available system
uint32_t number_of_observations = 0;
std::string signal_("B1");
std::size_t found_B1 = bands.find(signal_);
if (found_B1 != std::string::npos)
{
number_of_observations = number_of_observations + 4;
}
signal_ = "B3";
std::size_t found_B3 = bands.find(signal_);
if (found_B3 != std::string::npos)
{
number_of_observations = number_of_observations + 4;
}
line.clear();
line += satelliteSystem["Beidou"];
line += std::string(2, ' ');
line += Rinex_Printer::rightJustify(std::to_string(number_of_observations), 3);
if (found_B1 != std::string::npos)
{
line += std::string(1, ' ');
line += observationType["PSEUDORANGE"];
line += observationCode["BEIDOU_B1_I"];
line += std::string(1, ' ');
line += observationType["CARRIER_PHASE"];
line += observationCode["BEIDOU_B1_I"];
line += std::string(1, ' ');
line += observationType["DOPPLER"];
line += observationCode["BEIDOU_B1_I"];
line += std::string(1, ' ');
line += observationType["SIGNAL_STRENGTH"];
line += observationCode["BEIDOU_B1_I"];
}
if (found_B3 != std::string::npos)
{
line += std::string(1, ' ');
line += observationType["PSEUDORANGE"];
line += observationCode["BEIDOU_B3_I"];
line += std::string(1, ' ');
line += observationType["CARRIER_PHASE"];
line += observationCode["BEIDOU_B3_I"];
line += std::string(1, ' ');
line += observationType["DOPPLER"];
line += observationCode["BEIDOU_B3_I"];
line += std::string(1, ' ');
line += observationType["SIGNAL_STRENGTH"];
line += observationCode["BEIDOU_B3_I"];
}
line += std::string(60 - line.size(), ' ');
line += Rinex_Printer::leftJustify("SYS / # / OBS TYPES", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- Signal Strength units
line.clear();
line += Rinex_Printer::leftJustify("DBHZ", 20);
line += std::string(40, ' ');
line += Rinex_Printer::leftJustify("SIGNAL STRENGTH UNIT", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- TIME OF FIRST OBS
line.clear();
boost::posix_time::ptime p_bds_time = Rinex_Printer::compute_BDS_time(eph, d_TOW_first_observation);
std::string timestring = boost::posix_time::to_iso_string(p_bds_time);
std::string year(timestring, 0, 4);
std::string month(timestring, 4, 2);
std::string day(timestring, 6, 2);
std::string hour(timestring, 9, 2);
std::string minutes(timestring, 11, 2);
double beidou_t = d_TOW_first_observation;
double seconds = fmod(beidou_t, 60);
line += Rinex_Printer::rightJustify(year, 6);
line += Rinex_Printer::rightJustify(month, 6);
line += Rinex_Printer::rightJustify(day, 6);
line += Rinex_Printer::rightJustify(hour, 6);
line += Rinex_Printer::rightJustify(minutes, 6);
line += Rinex_Printer::rightJustify(asString(seconds, 7), 13);
line += Rinex_Printer::rightJustify(std::string("BDT"), 8);
line += std::string(9, ' ');
line += Rinex_Printer::leftJustify("TIME OF FIRST OBS", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
// -------- SYS /PHASE SHIFTS
// -------- end of header
line.clear();
line += std::string(60, ' ');
line += Rinex_Printer::leftJustify("END OF HEADER", 20);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
}
void Rinex_Printer::update_obs_header(std::fstream& out __attribute__((unused)), const Glonass_Gnav_Utc_Model& utc_model)
{
if (utc_model.d_N_4)
@ -7050,6 +7638,65 @@ void Rinex_Printer::update_obs_header(std::fstream& out, const Galileo_Utc_Model
}
void Rinex_Printer::update_obs_header(std::fstream& out, const Beidou_Dnav_Utc_Model& utc_model)
{
std::vector<std::string> data;
std::string line_aux;
out.seekp(0);
data.clear();
bool no_more_finds = false;
std::string line_str;
while (!out.eof())
{
std::getline(out, line_str);
if (!no_more_finds)
{
line_aux.clear();
if (line_str.find("TIME OF FIRST OBS", 59) != std::string::npos)
{
data.push_back(line_str);
line_aux += Rinex_Printer::rightJustify(boost::lexical_cast<std::string>(utc_model.d_DeltaT_LS), 6);
line_aux += Rinex_Printer::rightJustify(boost::lexical_cast<std::string>(utc_model.d_DeltaT_LSF), 6);
line_aux += Rinex_Printer::rightJustify(std::to_string(utc_model.i_WN_LSF), 6);
line_aux += Rinex_Printer::rightJustify(std::to_string(utc_model.i_DN), 6);
line_aux += std::string(36, ' ');
line_aux += Rinex_Printer::leftJustify("LEAP SECONDS", 20);
data.push_back(line_aux);
}
else if (line_str.find("END OF HEADER", 59) != std::string::npos)
{
data.push_back(line_str);
no_more_finds = true;
}
else
{
data.push_back(line_str);
}
}
else
{
data.push_back(line_str);
}
}
out.close();
out.open(obsfilename, std::ios::out | std::ios::trunc);
out.seekp(0);
for (int32_t i = 0; i < static_cast<int32_t>(data.size()) - 1; i++)
{
out << data[i] << std::endl;
}
out.close();
out.open(obsfilename, std::ios::out | std::ios::in | std::ios::app);
out.seekp(0, std::ios_base::end);
}
void Rinex_Printer::log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeris& eph, const double obs_time, const std::map<int32_t, Gnss_Synchro>& observables, const std::string& glonass_band)
{
// RINEX observations timestamps are GPS timestamps.
@ -9760,6 +10407,176 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Gps_Ephemeris& gps_ep
}
void Rinex_Printer::log_rinex_obs(std::fstream& out, const Beidou_Dnav_Ephemeris& eph, double obs_time, const std::map<int32_t, Gnss_Synchro>& observables, const std::string& bds_bands)
{
std::string line;
boost::posix_time::ptime p_bds_time = Rinex_Printer::compute_BDS_time(eph, obs_time);
std::string timestring = boost::posix_time::to_iso_string(p_bds_time);
//double utc_t = nav_msg.utc_time(nav_msg.sv_clock_correction(obs_time));
//double gps_t = eph.sv_clock_correction(obs_time);
double bds_t = obs_time;
std::string month(timestring, 4, 2);
std::string day(timestring, 6, 2);
std::string hour(timestring, 9, 2);
std::string minutes(timestring, 11, 2);
std::string year(timestring, 0, 4);
line += std::string(1, '>');
line += std::string(1, ' ');
line += year;
line += std::string(1, ' ');
line += month;
line += std::string(1, ' ');
line += day;
line += std::string(1, ' ');
line += hour;
line += std::string(1, ' ');
line += minutes;
line += std::string(1, ' ');
double seconds = fmod(bds_t, 60);
// Add extra 0 if seconds are < 10
if (seconds < 10)
{
line += std::string(1, '0');
}
line += Rinex_Printer::asString(seconds, 7);
line += std::string(2, ' ');
// Epoch flag 0: OK 1: power failure between previous and current epoch <1: Special event
line += std::string(1, '0');
//Number of satellites observed in current epoch
//Get maps with BeiDou observations
std::map<int32_t, Gnss_Synchro> observablesB1I;
std::map<int32_t, Gnss_Synchro> observablesB3I;
std::map<int32_t, Gnss_Synchro>::const_iterator observables_iter;
for (observables_iter = observables.cbegin();
observables_iter != observables.cend();
observables_iter++)
{
std::string system_(&observables_iter->second.System, 1);
std::string sig_(observables_iter->second.Signal);
if ((system_ == "C") && (sig_ == "B1"))
{
observablesB1I.insert(std::pair<int32_t, Gnss_Synchro>(observables_iter->first, observables_iter->second));
}
if ((system_ == "C") && (sig_ == "B3"))
{
observablesB3I.insert(std::pair<int32_t, Gnss_Synchro>(observables_iter->first, observables_iter->second));
}
}
std::size_t found_B1 = bds_bands.find("B1");
std::size_t found_B3 = bds_bands.find("B3");
std::multimap<uint32_t, Gnss_Synchro> total_map;
std::set<uint32_t> available_prns;
std::set<uint32_t>::iterator it;
if (found_B1 != std::string::npos)
{
for (observables_iter = observablesB1I.cbegin();
observables_iter != observablesB1I.cend();
observables_iter++)
{
uint32_t prn_ = observables_iter->second.PRN;
total_map.insert(std::pair<uint32_t, Gnss_Synchro>(prn_, observables_iter->second));
it = available_prns.find(prn_);
if (it == available_prns.end())
{
available_prns.insert(prn_);
}
}
}
if (found_B3 != std::string::npos)
{
for (observables_iter = observablesB3I.cbegin();
observables_iter != observablesB3I.cend();
observables_iter++)
{
uint32_t prn_ = observables_iter->second.PRN;
it = available_prns.find(prn_);
if (it == available_prns.end())
{
available_prns.insert(prn_);
if (found_B1 != std::string::npos)
{
Gnss_Synchro gs = Gnss_Synchro();
std::string sys = "C";
gs.System = *sys.c_str();
std::string sig = "B1";
std::memcpy(static_cast<void*>(gs.Signal), sig.c_str(), 3);
gs.PRN = prn_;
total_map.insert(std::pair<uint32_t, Gnss_Synchro>(prn_, gs));
}
}
total_map.insert(std::pair<uint32_t, Gnss_Synchro>(prn_, observables_iter->second));
}
}
int32_t numSatellitesObserved = available_prns.size();
line += Rinex_Printer::rightJustify(std::to_string(numSatellitesObserved), 3);
// Receiver clock offset (optional)
//line += rightJustify(asString(clockOffset, 12), 15);
line += std::string(80 - line.size(), ' ');
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
std::string lineObs;
std::pair<std::multimap<uint32_t, Gnss_Synchro>::iterator, std::multimap<uint32_t, Gnss_Synchro>::iterator> ret;
for (it = available_prns.begin();
it != available_prns.end();
it++)
{
lineObs.clear();
lineObs += satelliteSystem["Beidou"];
if (static_cast<int32_t>(*it) < 10) lineObs += std::string(1, '0');
lineObs += std::to_string(static_cast<int32_t>(*it));
ret = total_map.equal_range(*it);
for (auto iter = ret.first; iter != ret.second; ++iter)
{
lineObs += Rinex_Printer::rightJustify(asString(iter->second.Pseudorange_m, 3), 14);
//Loss of lock indicator (LLI)
int32_t lli = 0; // Include in the observation!!
if (lli == 0)
{
lineObs += std::string(1, ' ');
}
// Signal Strength Indicator (SSI)
int32_t ssi = Rinex_Printer::signalStrength(iter->second.CN0_dB_hz);
lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString<int32_t>(ssi), 1);
// CARRIER PHASE
lineObs += Rinex_Printer::rightJustify(asString(iter->second.Carrier_phase_rads / (BEIDOU_TWO_PI), 3), 14);
if (lli == 0)
{
lineObs += std::string(1, ' ');
}
lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString<int32_t>(ssi), 1);
// DOPPLER
lineObs += Rinex_Printer::rightJustify(asString(iter->second.Carrier_Doppler_hz, 3), 14);
if (lli == 0)
{
lineObs += std::string(1, ' ');
}
lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString<int32_t>(ssi), 1);
// SIGNAL STRENGTH
lineObs += Rinex_Printer::rightJustify(asString(iter->second.CN0_dB_hz, 3), 14);
}
if (lineObs.size() < 80) lineObs += std::string(80 - lineObs.size(), ' ');
out << lineObs << std::endl;
}
}
void Rinex_Printer::to_date_time(int32_t gps_week, int32_t gps_tow, int& year, int& month, int& day, int& hour, int& minute, int& second)
{
// represents GPS time (week, TOW) in the date time format of the Gregorian calendar.
@ -9932,6 +10749,19 @@ boost::posix_time::ptime Rinex_Printer::compute_UTC_time(const Gps_Navigation_Me
}
boost::posix_time::ptime Rinex_Printer::compute_BDS_time(const Beidou_Dnav_Ephemeris& eph, const double obs_time)
{
// The RINEX v2.11 v3.00 format uses GPS time for the observations epoch, not UTC time, thus, no leap seconds needed here.
// (see Section 3 in http://igscb.jpl.nasa.gov/igscb/data/format/rinex211.txt)
// (see Pag. 17 in http://igscb.jpl.nasa.gov/igscb/data/format/rinex300.pdf)
// --??? No time correction here, since it will be done in the RINEX processor
const double bds_t = obs_time;
boost::posix_time::time_duration t = boost::posix_time::milliseconds(static_cast<int64_t>((bds_t + 604800 * static_cast<double>(eph.i_BEIDOU_week % 8192)) * 1000));
boost::posix_time::ptime p_time(boost::gregorian::date(2006, 1, 1), t);
return p_time;
}
boost::posix_time::ptime Rinex_Printer::compute_GPS_time(const Gps_Ephemeris& eph, const double obs_time)
{
// The RINEX v2.11 v3.00 format uses GPS time for the observations epoch, not UTC time, thus, no leap seconds needed here.

View File

@ -51,9 +51,11 @@
#ifndef GNSS_SDR_RINEX_PRINTER_H_
#define GNSS_SDR_RINEX_PRINTER_H_
#include "Beidou_B1I.h"
#include "GLONASS_L1_L2_CA.h"
#include "GPS_L1_CA.h"
#include "Galileo_E1.h"
#include "beidou_dnav_navigation_message.h"
#include "galileo_navigation_message.h"
#include "glonass_gnav_navigation_message.h"
#include "gnss_synchro.h"
@ -91,6 +93,7 @@ public:
std::fstream sbsFile; //<! Output file stream for RINEX SBAS raw data file
std::fstream navGalFile; //<! Output file stream for RINEX Galileo navigation data file
std::fstream navGloFile; //<! Output file stream for RINEX GLONASS navigation data file
std::fstream navBdsFile; //<! Output file stream for RINEX Galileo navigation data file
std::fstream navMixFile; //<! Output file stream for RINEX Mixed navigation data file
/*!
@ -138,6 +141,8 @@ public:
*/
void rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono& gps_iono, const Gps_CNAV_Utc_Model& gps_utc_model, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac);
void rinex_nav_header(std::fstream& out, const Beidou_Dnav_Iono& iono, const Beidou_Dnav_Utc_Model& utc_model);
/*!
* \brief Generates the GPS Observation data header
*/
@ -193,11 +198,25 @@ public:
*/
void rinex_obs_header(std::fstream& out, const Gps_CNAV_Ephemeris& gps_cnav_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, const double d_TOW_first_observation, const std::string& glo_bands = "1G");
/*!
* \brief Generates the a Beidou B1I Observation data header. Example: beidou_bands("B1")
*/
void rinex_obs_header(std::fstream& out, const Beidou_Dnav_Ephemeris& eph, const double d_TOW_first_observation, const std::string& bands);
/*!
* \brief Generates the SBAS raw data header
*/
void rinex_sbs_header(std::fstream& out);
/*!
* \brief Computes the BDS Time and returns a boost::posix_time::ptime object
* \details Function used to convert the observation time into BDT time which is used
* as the default time for RINEX files
* \param eph BeiDou DNAV Ephemeris object
* \param obs_time Observation time in BDT seconds of week
*/
boost::posix_time::ptime compute_BDS_time(const Beidou_Dnav_Ephemeris& eph, const double obs_time);
/*!
* \brief Computes the UTC time and returns a boost::posix_time::ptime object
*/
@ -279,6 +298,11 @@ public:
*/
void log_rinex_nav(std::fstream& out, const std::map<int32_t, Galileo_Ephemeris>& galileo_eph_map, const std::map<int32_t, Glonass_Gnav_Ephemeris>& glonass_gnav_eph_map);
/*!
* \brief Writes data from the Beidou B1I navigation message into the RINEX file
*/
void log_rinex_nav(std::fstream& out, const std::map<int32_t, Beidou_Dnav_Ephemeris>& eph_map);
/*!
* \brief Writes GPS L1 observables into the RINEX file
*/
@ -334,6 +358,12 @@ public:
*/
void log_rinex_obs(std::fstream& out, const Galileo_Ephemeris& galileo_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, const double gps_obs_time, const std::map<int32_t, Gnss_Synchro>& observables);
/*!
* \brief Writes BDS B1I observables into the RINEX file
*/
void log_rinex_obs(std::fstream& out, const Beidou_Dnav_Ephemeris& eph, double obs_time, const std::map<int32_t, Gnss_Synchro>& observables, const std::string& bds_bands);
/*!
* \brief Represents GPS time in the date time format. Leap years are considered, but leap seconds are not.
*/
@ -362,6 +392,8 @@ public:
void update_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac);
void update_nav_header(std::fstream& out, const Beidou_Dnav_Utc_Model& beidou_dnav_utc, const Beidou_Dnav_Iono& beidou_dnav_iono);
void update_obs_header(std::fstream& out, const Gps_Utc_Model& utc_model);
void update_obs_header(std::fstream& out, const Gps_CNAV_Utc_Model& utc_model);
@ -370,7 +402,9 @@ public:
void update_obs_header(std::fstream& out, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model);
std::map<std::string, std::string> satelliteSystem; //<! GPS, GLONASS, SBAS payload, Galileo or Compass
void update_obs_header(std::fstream& out, const Beidou_Dnav_Utc_Model& utc_model);
std::map<std::string, std::string> satelliteSystem; //<! GPS, GLONASS, SBAS payload, Galileo or Beidou
std::map<std::string, std::string> observationType; //<! PSEUDORANGE, CARRIER_PHASE, DOPPLER, SIGNAL_STRENGTH
std::map<std::string, std::string> observationCode; //<! GNSS observation descriptors
std::string stringVersion; //<! RINEX version (2.10/2.11 or 3.01/3.02)
@ -380,6 +414,7 @@ public:
std::string sbsfilename;
std::string navGalfilename;
std::string navGlofilename;
std::string navBdsfilename;
std::string navMixfilename;
private:

View File

@ -52,6 +52,7 @@
* -----------------------------------------------------------------------*/
#include "rtklib_solver.h"
#include "Beidou_B1I.h"
#include "GLONASS_L1_L2_CA.h"
#include "GPS_L1_CA.h"
#include "Galileo_E1.h"
@ -447,6 +448,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_Dnav_Ephemeris>::const_iterator beidou_ephemeris_iter;
const Glonass_Gnav_Utc_Model gnav_utc = this->glonass_gnav_utc_model;
this->set_averaging_flag(flag_averaging);
@ -756,6 +759,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_ == "B1")
{
beidou_ephemeris_iter = beidou_dnav_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (beidou_ephemeris_iter != beidou_dnav_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 + 1356,
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

@ -55,6 +55,7 @@
#define GNSS_SDR_RTKLIB_SOLVER_H_
#include "beidou_dnav_navigation_message.h"
#include "galileo_almanac.h"
#include "galileo_navigation_message.h"
#include "glonass_gnav_navigation_message.h"
@ -101,6 +102,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 Ephemeris
std::map<int, Beidou_Dnav_Ephemeris> beidou_dnav_ephemeris_map; //!< Map storing new GLONASS GNAV Ephmeris
Galileo_Utc_Model galileo_utc_model;
Galileo_Iono galileo_iono;
@ -116,6 +118,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_Dnav_Utc_Model beidou_dnav_utc_model;
Beidou_Dnav_Iono beidou_dnav_iono;
std::map<int, Beidou_Dnav_Almanac> beidou_dnav_almanac_map;
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,342 @@
/*!
* \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 "Beidou_B1I.h"
#include "acq_conf.h"
#include "beidou_b1i_signal_processing.h"
#include "configuration_interface.h"
#include "gnss_sdr_flags.h"
#include <boost/math/distributions/exponential.hpp>
#include <glog/logging.h>
using google::LogMessage;
BeidouB1iPcpsAcquisition::BeidouB1iPcpsAcquisition(
ConfigurationInterface* configuration,
const 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);
int64_t 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_ == "cshort")
{
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_ == "cbyte")
{
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_ = nullptr;
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::stop_acquisition()
{
}
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()
{
auto* 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);
auto lambda = static_cast<double>(vector_length_);
boost::math::exponential_distribution<double> mydist(lambda);
auto threshold = static_cast<float>(quantile(mydist, val));
return threshold;
}
void BeidouB1iPcpsAcquisition::connect(gr::top_block_sptr top_block)
{
if (item_type_ == "gr_complex")
{
// nothing to connect
}
else if (item_type_ == "cshort")
{
// nothing to connect
}
else if (item_type_ == "cbyte")
{
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_ == "gr_complex")
{
// nothing to disconnect
}
else if (item_type_ == "cshort")
{
// nothing to disconnect
}
else if (item_type_ == "cbyte")
{
// 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_ == "gr_complex")
{
return acquisition_;
}
else if (item_type_ == "cshort")
{
return acquisition_;
}
else if (item_type_ == "cbyte")
{
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_;
}
void BeidouB1iPcpsAcquisition::set_resampler_latency(uint32_t latency_samples)
{
acquisition_->set_resampler_latency(latency_samples);
}

View File

@ -0,0 +1,180 @@
/*!
* \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 "acq_conf.h"
#include "acquisition_interface.h"
#include "complex_byte_to_float_x2.h"
#include "gnss_synchro.h"
#include "pcps_acquisition.h"
#include <gnuradio/blocks/float_to_complex.h>
#include <gnuradio/blocks/stream_to_vector.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,
const 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) override;
/*!
* \brief Stop running acquisition
*/
void stop_acquisition() override;
/*!
* \brief Sets the resampler latency to account it in the acquisition code delay estimation
*/
void set_resampler_latency(uint32_t latency_samples) override;
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

@ -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
@ -54,6 +55,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

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] = {false, true, false, true, false, true, false, true, false, true, false};
bool G2_register[11] = {false, true, false, true, false, true, false, true, false, true, false};
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, const std::str
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

@ -221,10 +221,11 @@ const int NSATQZS = 0;
const int NSYSQZS = 0;
#endif
#define ENABDS
#ifdef ENABDS
const int MINPRNBDS = 1; //!< min satellite sat number of BeiDou
const int MAXPRNBDS = 35; //!< max satellite sat number of BeiDou
const int NSATBDS = (MAXPRNBDS - MINPRNCM + 1); //!< number of BeiDou satellites
const int MINPRNBDS = 1; //!< min satellite sat number of BeiDou
const int MAXPRNBDS = 35; //!< max satellite sat number of BeiDou
const int NSATBDS = (MAXPRNBDS - MINPRNBDS + 1); //!< number of BeiDou satellites
const int NSYSBDS = 1;
#else
const int MINPRNBDS = 0;

View File

@ -65,10 +65,25 @@ 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 + NSATQZS;
break;
default:
rtklib_obs.sat = gnss_synchro.PRN;
}
// Mote that BeiDou week numbers do not need adjustment for foreseeable future. Consider change
// to more elegant solution
// if(gnss_synchro.System == 'C')
// {
// rtklib_obs.time = bdt2gpst(bdt2time(week, gnss_synchro.RX_time));
// }
// else
// {
// rtklib_obs.time = gpst2time(adjgpsweek(week), gnss_synchro.RX_time);
// }
//
rtklib_obs.time = gpst2time(adjgpsweek(week), gnss_synchro.RX_time);
rtklib_obs.rcv = 1;
return rtklib_obs;
@ -227,6 +242,69 @@ eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph)
return rtklib_sat;
}
eph_t eph_to_rtklib(const Beidou_Dnav_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 + NSATGPS + NSATGLO + NSATGAL + NSATQZS;
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_eccentricity;
rtklib_sat.Adot = 0; //only in CNAV;
rtklib_sat.ndot = 0; //only in CNAV;
rtklib_sat.code = bei_eph.i_sig_type; /*B1I data*/
rtklib_sat.flag = bei_eph.i_nav_type; /*MEO/IGSO satellite*/
rtklib_sat.iode = static_cast<int32_t>(bei_eph.d_AODE); /* AODE */
rtklib_sat.iodc = static_cast<int32_t>(bei_eph.d_AODC); /* AODC */
rtklib_sat.week = 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] = bei_eph.d_TGD2;
rtklib_sat.tgd[2] = 0.0;
rtklib_sat.tgd[3] = 0.0;
rtklib_sat.toes = bei_eph.d_Toe;
rtklib_sat.toe = bdt2gpst(bdt2time(rtklib_sat.week, bei_eph.d_Toe));
rtklib_sat.toc = bdt2gpst(bdt2time(rtklib_sat.week, bei_eph.d_Toc));
rtklib_sat.ttr = bdt2gpst(bdt2time(rtklib_sat.week, bei_eph.d_TOW));
/* adjustment for week handover */
double tow, toc, toe;
tow = time2gpst(rtklib_sat.ttr, &rtklib_sat.week);
toc = time2gpst(rtklib_sat.toc, nullptr);
toe = time2gpst(rtklib_sat.toe, nullptr);
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, toe);
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 "beidou_dnav_ephemeris.h"
#include "galileo_almanac.h"
#include "galileo_ephemeris.h"
#include "glonass_gnav_ephemeris.h"
@ -44,6 +45,7 @@
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_Dnav_Ephemeris& bei_eph);
alm_t alm_to_rtklib(const Gps_Almanac& gps_alm);
alm_t alm_to_rtklib(const Galileo_Almanac& gal_alm);

View File

@ -31,6 +31,7 @@
#include "signal_generator.h"
#include "Beidou_B1I.h"
#include "GLONASS_L1_L2_CA.h"
#include "GPS_L1_CA.h"
#include "Galileo_E1.h"
@ -112,6 +113,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_ == "gr_complex")
{
item_size_ = sizeof(gr_complex);

View File

@ -26,6 +26,7 @@ set(TELEMETRY_DECODER_ADAPTER_SOURCES
galileo_e5a_telemetry_decoder.cc
glonass_l1_ca_telemetry_decoder.cc
glonass_l2_ca_telemetry_decoder.cc
beidou_b1i_telemetry_decoder.cc
)
set(TELEMETRY_DECODER_ADAPTER_HEADERS
@ -37,6 +38,7 @@ set(TELEMETRY_DECODER_ADAPTER_HEADERS
galileo_e5a_telemetry_decoder.h
glonass_l1_ca_telemetry_decoder.h
glonass_l2_ca_telemetry_decoder.h
beidou_b1i_telemetry_decoder.h
)
include_directories(

View File

@ -0,0 +1,110 @@
/*!
* \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 "beidou_dnav_almanac.h"
#include "beidou_dnav_ephemeris.h"
#include "beidou_dnav_iono.h"
#include "beidou_dnav_utc_model.h"
#include "configuration_interface.h"
#include <glog/logging.h>
#include <gnuradio/io_signature.h>
using google::LogMessage;
BeidouB1iTelemetryDecoder::BeidouB1iTelemetryDecoder(ConfigurationInterface* configuration,
const 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() = default;
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,96 @@
/*!
* \file beidou_b1i_telemetry_decoder.h
* \brief Interface of an adapter of a Beidou B1I NAV data decoder block
* to a TelemetryDecoderInterface
* \author Damian Miralles, 2018. dmiralles2009@gmail.com
* \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 BEIDOU B1I
*/
class BeidouB1iTelemetryDecoder : public TelemetryDecoderInterface
{
public:
BeidouB1iTelemetryDecoder(ConfigurationInterface* configuration,
const std::string& role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~BeidouB1iTelemetryDecoder();
inline std::string role() override
{
return role_;
}
//! Returns "BEIDOU_B1I_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,592 @@
/*!
* \file beidou_b1i_telemetry_decoder_cc.cc
* \brief Implementation of an adapter of a BEIDOU BI1 DNAV data decoder block
* to a TelemetryDecoderInterface
* \note Code added as part of GSoC 2018 program
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.es
*
* -------------------------------------------------------------------------
*
* 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_telemetry_decoder_cc.h"
#include "control_message_factory.h"
#include "convolutional.h"
#include "display.h"
#include "gnss_synchro.h"
#include <boost/lexical_cast.hpp>
#include <glog/logging.h>
#include <gnuradio/io_signature.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <iostream>
#define CRC_ERROR_LIMIT 8
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_b1i_telemetry_decoder_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());
LOG(INFO) << "Initializing BeiDou B1i Telemetry Decoding for satellite " << this->d_satellite;
d_samples_per_symbol = (BEIDOU_B1I_CODE_RATE_HZ / BEIDOU_B1I_CODE_LENGTH_CHIPS) / BEIDOU_D1NAV_SYMBOL_RATE_SPS;
d_symbols_per_preamble = BEIDOU_DNAV_PREAMBLE_LENGTH_SYMBOLS;
d_samples_per_preamble = BEIDOU_DNAV_PREAMBLE_LENGTH_SYMBOLS * d_samples_per_symbol;
d_secondary_code_symbols = static_cast<int32_t *>(volk_gnsssdr_malloc(BEIDOU_B1I_SECONDARY_CODE_LENGTH * sizeof(int32_t), volk_gnsssdr_get_alignment()));
d_preamble_samples = static_cast<int32_t *>(volk_gnsssdr_malloc(d_samples_per_preamble * sizeof(int32_t), volk_gnsssdr_get_alignment()));
d_preamble_period_samples = BEIDOU_DNAV_PREAMBLE_PERIOD_SYMBOLS * d_samples_per_symbol;
d_subframe_length_symbols = BEIDOU_DNAV_PREAMBLE_PERIOD_SYMBOLS;
// Setting samples of secondary code
for (int32_t i = 0; i < BEIDOU_B1I_SECONDARY_CODE_LENGTH; i++)
{
if (BEIDOU_B1I_SECONDARY_CODE.at(i) == '1')
{
d_secondary_code_symbols[i] = 1;
}
else
{
d_secondary_code_symbols[i] = -1;
}
}
// Setting samples of preamble code
int32_t n = 0;
for (int32_t i = 0; i < d_symbols_per_preamble; i++)
{
int32_t m = 0;
if (BEIDOU_DNAV_PREAMBLE.at(i) == '1')
{
for (uint32_t j = 0; j < d_samples_per_symbol; j++)
{
d_preamble_samples[n] = d_secondary_code_symbols[m];
n++;
m++;
m = m % BEIDOU_B1I_SECONDARY_CODE_LENGTH;
}
}
else
{
for (uint32_t j = 0; j < d_samples_per_symbol; j++)
{
d_preamble_samples[n] = -d_secondary_code_symbols[m];
n++;
m++;
m = m % BEIDOU_B1I_SECONDARY_CODE_LENGTH;
}
}
}
d_subframe_symbols = static_cast<double *>(volk_gnsssdr_malloc(d_subframe_length_symbols * sizeof(double), volk_gnsssdr_get_alignment()));
d_required_symbols = BEIDOU_DNAV_SUBFRAME_SYMBOLS * d_samples_per_symbol + d_samples_per_preamble;
// Generic settings
d_sample_counter = 0;
d_stat = 0;
d_preamble_index = 0;
d_flag_frame_sync = false;
d_TOW_at_current_symbol_ms = 0;
Flag_valid_word = false;
d_CRC_error_counter = 0;
d_flag_preamble = false;
d_channel = 0;
flag_SOW_set = false;
}
beidou_b1i_telemetry_decoder_cc::~beidou_b1i_telemetry_decoder_cc()
{
volk_gnsssdr_free(d_preamble_samples);
volk_gnsssdr_free(d_secondary_code_symbols);
volk_gnsssdr_free(d_subframe_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::decode_bch15_11_01(const int32_t *bits, int32_t *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(
int32_t word_counter,
const double *enc_word_symbols,
int32_t *dec_word_symbols)
{
int32_t bitsbch[30], first_branch[15], second_branch[15];
if (word_counter == 1)
{
for (unsigned int j = 0; j < 30; j++)
{
dec_word_symbols[j] = (int32_t)(enc_word_symbols[j] > 0) ? (1) : (-1);
}
}
else
{
for (unsigned int r = 0; r < 2; r++)
{
for (unsigned int c = 0; c < 15; c++)
{
bitsbch[r * 15 + c] = (int32_t)(enc_word_symbols[c * 2 + r] > 0) ? (1) : (-1);
}
}
decode_bch15_11_01(&bitsbch[0], first_branch);
decode_bch15_11_01(&bitsbch[15], second_branch);
for (unsigned int j = 0; j < 11; j++)
{
dec_word_symbols[j] = first_branch[j];
dec_word_symbols[j + 11] = second_branch[j];
}
for (unsigned int j = 0; j < 4; j++)
{
dec_word_symbols[j + 22] = first_branch[11 + j];
dec_word_symbols[j + 26] = second_branch[11 + j];
}
}
}
void beidou_b1i_telemetry_decoder_cc::decode_subframe(double *frame_symbols, int32_t frame_length)
{
// 1. Transform from symbols to bits
std::string data_bits;
int32_t dec_word_bits[30];
// Decode each word in subframe
for (uint32_t ii = 0; ii < BEIDOU_DNAV_WORDS_SUBFRAME; ii++)
{
// decode the word
decode_word((ii + 1), &frame_symbols[ii * 30], dec_word_bits);
// Save word to string format
for (uint32_t jj = 0; jj < (BEIDOU_DNAV_WORD_LENGTH_BITS); jj++)
{
data_bits.push_back((dec_word_bits[jj] > 0) ? ('1') : ('0'));
}
}
if (d_satellite.get_PRN() > 0 and d_satellite.get_PRN() < 6)
{
d_nav.d2_subframe_decoder(data_bits);
}
else
{
d_nav.d1_subframe_decoder(data_bits);
}
// 3. Check operation executed correctly
if (d_nav.flag_crc_test == true)
{
LOG(INFO) << "BeiDou DNAV CRC correct in channel " << d_channel << " from satellite " << d_satellite;
}
else
{
LOG(INFO) << "BeiDou DNAV CRC error in channel " << d_channel << " from satellite " << d_satellite;
}
// 4. Push the new navigation data to the queues
if (d_nav.have_new_ephemeris() == true)
{
// get object for this SV (mandatory)
std::shared_ptr<Beidou_Dnav_Ephemeris> tmp_obj = std::make_shared<Beidou_Dnav_Ephemeris>(d_nav.get_ephemeris());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
LOG(INFO) << "BEIDOU DNAV Ephemeris have been received in channel" << d_channel << " from satellite " << d_satellite;
std::cout << "New BEIDOU B1I DNAV message received in channel " << d_channel << ": ephemeris from satellite " << d_satellite << std::endl;
}
if (d_nav.have_new_utc_model() == true)
{
// get object for this SV (mandatory)
std::shared_ptr<Beidou_Dnav_Utc_Model> tmp_obj = std::make_shared<Beidou_Dnav_Utc_Model>(d_nav.get_utc_model());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
LOG(INFO) << "BEIDOU DNAV UTC Model have been received in channel" << d_channel << " from satellite " << d_satellite;
std::cout << "New BEIDOU B1I DNAV utc model message received in channel " << d_channel << ": UTC model parameters from satellite " << d_satellite << std::endl;
}
if (d_nav.have_new_iono() == true)
{
// get object for this SV (mandatory)
std::shared_ptr<Beidou_Dnav_Iono> tmp_obj = std::make_shared<Beidou_Dnav_Iono>(d_nav.get_iono());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
LOG(INFO) << "BEIDOU DNAV Iono have been received in channel" << d_channel << " from satellite " << d_satellite;
std::cout << "New BEIDOU B1I DNAV Iono message received in channel " << d_channel << ": Iono model parameters from satellite " << d_satellite << std::endl;
}
if (d_nav.have_new_almanac() == true)
{
// unsigned int slot_nbr = d_nav.i_alm_satellite_PRN;
// std::shared_ptr<Beidou_Dnav_Almanac> tmp_obj = std::make_shared<Beidou_Dnav_Almanac>(d_nav.get_almanac(slot_nbr));
// this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
LOG(INFO) << "BEIDOU DNAV Almanac have been received in channel" << d_channel << " from satellite " << d_satellite << std::endl;
std::cout << "New BEIDOU B1I DNAV almanac received in channel " << d_channel << " from satellite " << d_satellite << std::endl;
}
}
void beidou_b1i_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satellite)
{
uint32_t sat_prn = 0;
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite;
DLOG(INFO) << "Navigation Satellite set to " << d_satellite;
// Update satellite information for DNAV decoder
sat_prn = d_satellite.get_PRN();
d_nav.i_satellite_PRN = sat_prn;
// Update tel dec parameters for D2 NAV Messages
if (sat_prn > 0 and sat_prn < 6)
{
// Clear values from previous declaration
volk_gnsssdr_free(d_preamble_samples);
volk_gnsssdr_free(d_secondary_code_symbols);
volk_gnsssdr_free(d_subframe_symbols);
d_samples_per_symbol = (BEIDOU_B1I_CODE_RATE_HZ / BEIDOU_B1I_CODE_LENGTH_CHIPS) / BEIDOU_D2NAV_SYMBOL_RATE_SPS;
d_symbols_per_preamble = BEIDOU_DNAV_PREAMBLE_LENGTH_SYMBOLS;
d_samples_per_preamble = BEIDOU_DNAV_PREAMBLE_LENGTH_SYMBOLS * d_samples_per_symbol;
d_secondary_code_symbols = nullptr;
d_preamble_samples = static_cast<int32_t *>(volk_gnsssdr_malloc(d_samples_per_preamble * sizeof(int32_t), volk_gnsssdr_get_alignment()));
d_preamble_period_samples = BEIDOU_DNAV_PREAMBLE_PERIOD_SYMBOLS * d_samples_per_symbol;
d_subframe_length_symbols = BEIDOU_DNAV_PREAMBLE_PERIOD_SYMBOLS;
// Setting samples of preamble code
int32_t n = 0;
for (int32_t i = 0; i < d_symbols_per_preamble; i++)
{
if (BEIDOU_DNAV_PREAMBLE.at(i) == '1')
{
for (uint32_t j = 0; j < d_samples_per_symbol; j++)
{
d_preamble_samples[n] = 1;
n++;
}
}
else
{
for (uint32_t j = 0; j < d_samples_per_symbol; j++)
{
d_preamble_samples[n] = -1;
n++;
}
}
}
d_subframe_symbols = static_cast<double *>(volk_gnsssdr_malloc(d_subframe_length_symbols * sizeof(double), volk_gnsssdr_get_alignment()));
d_required_symbols = BEIDOU_DNAV_SUBFRAME_SYMBOLS * d_samples_per_symbol + d_samples_per_preamble;
}
}
void beidou_b1i_telemetry_decoder_cc::set_channel(int channel)
{
d_channel = channel;
LOG(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(std::to_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 Beidou TLM dump file. " << e.what();
}
}
}
}
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)
{
int32_t corr_value = 0;
int32_t preamble_diff = 0;
auto **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]); // Get the output buffer pointer
const auto **in = reinterpret_cast<const Gnss_Synchro **>(&input_items[0]); // Get the input buffer pointer
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];
d_symbol_history.push_back(current_symbol.Prompt_I); //add new symbol to the symbol queue
d_sample_counter++; //count for the processed samples
consume_each(1);
d_flag_preamble = false;
if (d_symbol_history.size() > d_required_symbols)
{
//******* preamble correlation ********
for (int i = 0; i < d_samples_per_preamble; i++)
{
if (d_symbol_history.at(i) < 0) // symbols clipping
{
corr_value -= d_preamble_samples[i];
}
else
{
corr_value += d_preamble_samples[i];
}
}
}
//******* frame sync ******************
if (d_stat == 0) //no preamble information
{
if (abs(corr_value) >= d_samples_per_preamble)
{
// Record the preamble sample stamp
d_preamble_index = d_sample_counter;
LOG(INFO) << "Preamble detection for BEIDOU B1I SAT " << this->d_satellite;
// Enter into frame pre-detection status
d_stat = 1;
}
}
else if (d_stat == 1) // possible preamble lock
{
if (abs(corr_value) >= d_samples_per_preamble)
{
//check preamble separation
preamble_diff = static_cast<int32_t>(d_sample_counter - d_preamble_index);
if (abs(preamble_diff - d_preamble_period_samples) == 0)
{
//try to decode frame
LOG(INFO) << "Starting BeiDou DNAV frame decoding for BeiDou B1I SAT " << this->d_satellite;
d_preamble_index = d_sample_counter; //record the preamble sample stamp
d_stat = 2;
}
else
{
if (preamble_diff > d_preamble_period_samples)
{
d_stat = 0; // start again
}
DLOG(INFO) << "Failed BeiDou DNAV frame decoding for BeiDou B1I SAT " << this->d_satellite;
}
}
}
else if (d_stat == 2) // preamble acquired
{
if (d_sample_counter == d_preamble_index + static_cast<uint64_t>(d_preamble_period_samples))
{
//******* SAMPLES TO SYMBOLS *******
if (corr_value > 0) //normal PLL lock
{
int k = 0;
for (uint32_t i = 0; i < d_subframe_length_symbols; i++)
{
d_subframe_symbols[i] = 0;
//integrate samples into symbols
for (uint32_t m = 0; m < d_samples_per_symbol; m++)
{
if (d_satellite.get_PRN() > 0 and d_satellite.get_PRN() < 6)
{
// because last symbol of the preamble is just received now!
d_subframe_symbols[i] += d_symbol_history.at(i * d_samples_per_symbol + m);
}
else
{
// because last symbol of the preamble is just received now!
d_subframe_symbols[i] += static_cast<float>(d_secondary_code_symbols[k]) * d_symbol_history.at(i * d_samples_per_symbol + m);
k++;
k = k % BEIDOU_B1I_SECONDARY_CODE_LENGTH;
}
}
}
}
else //180 deg. inverted carrier phase PLL lock
{
int k = 0;
for (uint32_t i = 0; i < d_subframe_length_symbols; i++)
{
d_subframe_symbols[i] = 0;
//integrate samples into symbols
for (uint32_t m = 0; m < d_samples_per_symbol; m++)
{
if (d_satellite.get_PRN() > 0 and d_satellite.get_PRN() < 6)
{
// because last symbol of the preamble is just received now!
d_subframe_symbols[i] -= d_symbol_history.at(i * d_samples_per_symbol + m);
}
else
{
// because last symbol of the preamble is just received now!
d_subframe_symbols[i] -= static_cast<float>(d_secondary_code_symbols[k]) * d_symbol_history.at(i * d_samples_per_symbol + m);
k++;
k = k % BEIDOU_B1I_SECONDARY_CODE_LENGTH;
}
}
}
}
//call the decoder
decode_subframe(d_subframe_symbols, d_subframe_length_symbols);
if (d_nav.flag_crc_test == true)
{
d_CRC_error_counter = 0;
d_flag_preamble = true; //valid preamble indicator (initialized to false every work())
d_preamble_index = d_sample_counter; //record the preamble sample stamp (t_P)
if (!d_flag_frame_sync)
{
d_flag_frame_sync = true;
DLOG(INFO) << "BeiDou DNAV frame sync found for SAT " << this->d_satellite;
}
}
else
{
d_CRC_error_counter++;
d_preamble_index = d_sample_counter; //record the preamble sample stamp
if (d_CRC_error_counter > CRC_ERROR_LIMIT)
{
LOG(INFO) << "BeiDou DNAV frame sync lost for SAT " << this->d_satellite;
d_flag_frame_sync = false;
d_stat = 0;
flag_SOW_set = false;
}
}
}
}
// UPDATE GNSS SYNCHRO DATA
//2. Add the telemetry decoder information
if (this->d_flag_preamble == true and d_nav.flag_new_SOW_available == true)
//update TOW at the preamble instant
{
// Reporting sow as gps time of week
d_TOW_at_Preamble_ms = static_cast<uint32_t>((d_nav.d_SOW + 14) * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((d_required_symbols + 1) * BEIDOU_B1I_CODE_PERIOD_MS);
flag_SOW_set = true;
d_nav.flag_new_SOW_available = false;
}
else //if there is not a new preamble, we define the TOW of the current symbol
{
d_TOW_at_current_symbol_ms += static_cast<uint32_t>(BEIDOU_B1I_CODE_PERIOD_MS);
}
if (d_flag_frame_sync == true and flag_SOW_set == true)
{
current_symbol.Flag_valid_word = true;
}
else
{
current_symbol.Flag_valid_word = false;
}
current_symbol.PRN = this->d_satellite.get_PRN();
current_symbol.TOW_at_current_symbol_ms = d_TOW_at_current_symbol_ms;
if (d_dump == true)
{
// MULTIPLEXED FILE RECORDING - Record results to file
try
{
double tmp_double;
unsigned long int tmp_ulong_int;
tmp_double = d_TOW_at_current_symbol_ms;
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 = 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();
}
}
// remove used symbols from history
if (d_symbol_history.size() > d_required_symbols)
{
d_symbol_history.pop_front();
}
//3. Make the output (copy the object contents to the GNURadio reserved memory)
*out[0] = current_symbol;
return 1;
}

View File

@ -0,0 +1,126 @@
/*!
* \file beidou_b1i_telemetry_decoder_cc.h
* \brief Implementation of an adapter of a BEIDOU BI1 DNAV data decoder block
* to a TelemetryDecoderInterface
* \details Code added as part of GSoC 2018 program. However new modifications included to mimic
* decoding of existing signals
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.es
*
* -------------------------------------------------------------------------
*
* 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_TELEMETRY_DECODER_CC_H
#define GNSS_SDR_BEIDOU_B1I_TELEMETRY_DECODER_CC_H
#include "Beidou_B1I.h"
#include "beidou_dnav_almanac.h"
#include "beidou_dnav_ephemeris.h"
#include "beidou_dnav_navigation_message.h"
#include "beidou_dnav_utc_model.h"
#include "gnss_satellite.h"
#include "gnss_synchro.h"
#include <gnuradio/block.h>
#include <fstream>
#include <string>
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);
//!!!! edit
/*!
* \brief This class implements a block that decodes the GNAV data defined in BEIDOU ICD v5.1
* \note Code added as part of GSoC 2018 program
* \see <a href="http://russianspacesystems.ru/wp-content/uploads/2016/08/ICD_GLONASS_eng_v5.1.pdf">GLONASS ICD</a>
*
*/
class beidou_b1i_telemetry_decoder_cc : public gr::block
{
public:
~beidou_b1i_telemetry_decoder_cc(); //!< Class destructor
void set_satellite(const Gnss_Satellite &satellite); //!< Set satellite PRN
void set_channel(int channel); //!< Set receiver's channel
/*!
* \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);
void decode_subframe(double *symbols, int32_t frame_length);
void decode_word(int32_t word_counter, const double *enc_word_symbols, int32_t *dec_word_symbols);
void decode_bch15_11_01(const int32_t *bits, int32_t *decbits);
//!< Preamble decoding
unsigned short int d_preambles_symbols[BEIDOU_DNAV_PREAMBLE_LENGTH_SYMBOLS];
int32_t *d_preamble_samples;
int32_t *d_secondary_code_symbols;
uint32_t d_samples_per_symbol;
int32_t d_symbols_per_preamble;
int32_t d_samples_per_preamble;
int32_t d_preamble_period_samples;
double *d_subframe_symbols;
uint32_t d_subframe_length_symbols;
uint32_t d_required_symbols;
//!< Storage for incoming data
std::deque<float> d_symbol_history;
//!< Variables for internal functionality
uint64_t d_sample_counter; //!< Sample counter as an index (1,2,3,..etc) indicating number of samples processed
uint64_t d_preamble_index; //!< Index of sample number where preamble was found
uint32_t d_stat; //!< Status of decoder
bool d_flag_frame_sync; //!< Indicate when a frame sync is achieved
bool d_flag_preamble; //!< Flag indicating when preamble was found
int32_t d_CRC_error_counter; //!< Number of failed CRC operations
bool flag_SOW_set; //!< Indicates when time of week is set
//!< Navigation Message variable
Beidou_Dnav_Navigation_Message d_nav;
//!< Values to populate gnss synchronization structure
uint32_t d_TOW_at_Preamble_ms;
uint32_t d_TOW_at_current_symbol_ms;
bool Flag_valid_word;
//!< Satellite Information and logging capacity
Gnss_Satellite d_satellite;
int32_t d_channel;
bool d_dump;
std::string d_dump_filename;
std::ofstream d_dump_file;
};
#endif

View File

@ -65,6 +65,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}
)
@ -82,23 +83,24 @@ 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}
)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src/core/system_parameters
${CMAKE_SOURCE_DIR}/src/core/interfaces
${CMAKE_SOURCE_DIR}/src/core/receiver
${CMAKE_SOURCE_DIR}/src/algorithms/tracking/gnuradio_blocks
${CMAKE_SOURCE_DIR}/src/algorithms/tracking/libs
${CMAKE_SOURCE_DIR}/src/algorithms/libs
${ARMADILLO_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS}
${GNURADIO_RUNTIME_INCLUDE_DIRS}
${VOLK_GNSSSDR_INCLUDE_DIRS}
${OPT_TRACKING_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src/core/system_parameters
${CMAKE_SOURCE_DIR}/src/core/interfaces
${CMAKE_SOURCE_DIR}/src/core/receiver
${CMAKE_SOURCE_DIR}/src/algorithms/tracking/gnuradio_blocks
${CMAKE_SOURCE_DIR}/src/algorithms/tracking/libs
${CMAKE_SOURCE_DIR}/src/algorithms/libs
${ARMADILLO_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS}
${GNURADIO_RUNTIME_INCLUDE_DIRS}
${VOLK_GNSSSDR_INCLUDE_DIRS}
${OPT_TRACKING_INCLUDE_DIRS}
)
list(SORT TRACKING_ADAPTER_HEADERS)

View File

@ -0,0 +1,201 @@
/*!
* \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 "beidou_b1i_dll_pll_tracking.h"
#include "Beidou_B1I.h"
#include "configuration_interface.h"
#include "display.h"
#include "dll_pll_conf.h"
#include "gnss_sdr_flags.h"
#include <glog/logging.h>
using google::LogMessage;
BeidouB1iDllPllTracking::BeidouB1iDllPllTracking(
ConfigurationInterface* configuration, const 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 == "gr_complex")
{
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() = default;
void BeidouB1iDllPllTracking::start_tracking()
{
tracking_->start_tracking();
}
void BeidouB1iDllPllTracking::stop_tracking()
{
tracking_->stop_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,106 @@
/*!
* \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 "dll_pll_veml_tracking.h"
#include "tracking_interface.h"
#include <string>
class ConfigurationInterface;
/*!
* \brief This class implements a code DLL + carrier PLL tracking loop
*/
class BeidouB1iDllPllTracking : public TrackingInterface
{
public:
BeidouB1iDllPllTracking(ConfigurationInterface* configuration,
const 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;
/*!
* \brief Stop running tracking
*/
void stop_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

@ -35,12 +35,14 @@
*/
#include "dll_pll_veml_tracking.h"
#include "Beidou_B1I.h"
#include "GPS_L1_CA.h"
#include "GPS_L2C.h"
#include "GPS_L5.h"
#include "Galileo_E1.h"
#include "Galileo_E5a.h"
#include "MATH_CONSTANTS.h"
#include "beidou_b1i_signal_processing.h"
#include "control_message_factory.h"
#include "galileo_e1_signal_processing.h"
#include "galileo_e5_signal_processing.h"
@ -96,7 +98,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
d_code_chip_rate = 0.0;
d_secondary_code_length = 0U;
d_secondary_code_string = nullptr;
d_gps_l1ca_preambles_symbols = nullptr;
d_preambles_symbols = nullptr;
signal_type = std::string(trk_parameters.signal);
std::map<std::string, std::string> map_signal_pretty_name;
@ -107,6 +109,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];
@ -131,7 +134,8 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
uint16_t preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS] = GPS_PREAMBLE;
// preamble bits to sampled symbols
d_gps_l1ca_preambles_symbols = static_cast<int32_t *>(volk_gnsssdr_malloc(GPS_CA_PREAMBLE_LENGTH_SYMBOLS * sizeof(int32_t), volk_gnsssdr_get_alignment()));
d_preamble_length_symbols = GPS_CA_PREAMBLE_LENGTH_SYMBOLS;
d_preambles_symbols = static_cast<int32_t *>(volk_gnsssdr_malloc(GPS_CA_PREAMBLE_LENGTH_SYMBOLS * sizeof(int32_t), volk_gnsssdr_get_alignment()));
int32_t n = 0;
for (uint16_t preambles_bit : preambles_bits)
{
@ -139,11 +143,11 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
{
if (preambles_bit == 1)
{
d_gps_l1ca_preambles_symbols[n] = 1;
d_preambles_symbols[n] = 1;
}
else
{
d_gps_l1ca_preambles_symbols[n] = -1;
d_preambles_symbols[n] = -1;
}
n++;
}
@ -270,6 +274,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 == "B1")
{
// GEO Satellites use different secondary code
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_SECONDARY_CODE_LENGTH);
d_secondary_code_string = const_cast<std::string *>(&BEIDOU_B1I_SECONDARY_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";
@ -533,6 +571,45 @@ void dll_pll_veml_tracking::start_tracking()
}
volk_gnsssdr_free(aux_code);
}
else if (systemName == "Beidou" and signal_type == "B1")
{
beidou_b1i_code_gen_float(d_tracking_code, d_acquisition_gnss_synchro->PRN, 0);
// Update secondary code settings for geo satellites
if (d_acquisition_gnss_synchro->PRN > 0 and d_acquisition_gnss_synchro->PRN < 6)
{
d_symbols_per_bit = 2;
d_correlation_length_ms = 1;
d_code_samples_per_chip = 1;
d_secondary = false;
trk_parameters.track_pilot = false;
interchange_iq = false;
d_secondary_code_length = 0;
d_secondary_code_string = const_cast<std::string *>(&BEIDOU_B1I_D2_SECONDARY_CODE_STR);
// preamble bits to sampled symbols
d_preamble_length_symbols = 22;
d_preambles_symbols = static_cast<int32_t *>(volk_gnsssdr_malloc(22 * sizeof(int32_t), volk_gnsssdr_get_alignment()));
int32_t n = 0;
uint16_t preambles_bits[BEIDOU_B1I_PREAMBLE_LENGTH_BITS] = {1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0};
for (uint16_t preambles_bit : preambles_bits)
{
for (int32_t j = 0; j < d_symbols_per_bit; j++)
{
if (preambles_bit == 1)
{
d_preambles_symbols[n] = 1;
}
else
{
d_preambles_symbols[n] = -1;
}
n++;
}
}
d_symbol_history.resize(22); // Change fixed buffer size
d_symbol_history.clear();
}
}
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));
@ -580,7 +657,7 @@ dll_pll_veml_tracking::~dll_pll_veml_tracking()
{
if (signal_type == "1C")
{
volk_gnsssdr_free(d_gps_l1ca_preambles_symbols);
volk_gnsssdr_free(d_preambles_symbols);
}
if (d_dump_file.is_open())
@ -1414,6 +1491,8 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
next_state = acquire_secondary();
if (next_state)
{
LOG(INFO) << systemName << " " << signal_pretty_name << " secondary code locked in channel " << d_channel
<< " for satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
std::cout << systemName << " " << signal_pretty_name << " secondary code locked in channel " << d_channel
<< " for satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
}
@ -1429,23 +1508,24 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
d_symbol_history.push_back(d_Prompt->real());
//******* preamble correlation ********
int32_t corr_value = 0;
if ((d_symbol_history.size() == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)) // and (d_make_correlation or !d_flag_frame_sync))
if ((static_cast<int32_t>(d_symbol_history.size()) == d_preamble_length_symbols)) // and (d_make_correlation or !d_flag_frame_sync))
{
for (uint32_t i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++)
for (int32_t i = 0; i < d_preamble_length_symbols; i++)
{
if (d_symbol_history.at(i) < 0) // symbols clipping
{
corr_value -= d_gps_l1ca_preambles_symbols[i];
corr_value -= d_preambles_symbols[i];
}
else
{
corr_value += d_gps_l1ca_preambles_symbols[i];
corr_value += d_preambles_symbols[i];
}
}
}
if (corr_value == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
if (corr_value == d_preamble_length_symbols)
{
//std::cout << "Preamble detected at tracking!" << std::endl;
LOG(INFO) << systemName << " " << signal_pretty_name << " tracking preamble detected in channel " << d_channel
<< " for satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
next_state = true;
}
else
@ -1492,6 +1572,7 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
}
}
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;

View File

@ -107,7 +107,8 @@ private:
std::string *d_secondary_code_string;
std::string signal_pretty_name;
int32_t *d_gps_l1ca_preambles_symbols;
int32_t *d_preambles_symbols;
int32_t d_preamble_length_symbols;
boost::circular_buffer<float> d_symbol_history;
//tracking state machine

View File

@ -38,6 +38,9 @@
#include "gnss_block_factory.h"
#include "array_signal_conditioner.h"
#include "beamformer_filter.h"
#include "beidou_b1i_dll_pll_tracking.h"
#include "beidou_b1i_pcps_acquisition.h"
#include "beidou_b1i_telemetry_decoder.h"
#include "byte_to_short.h"
#include "channel.h"
#include "configuration_interface.h"
@ -279,15 +282,19 @@ 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);
Glonass_channels += configuration->property("Channels_2G.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);
}
@ -302,7 +309,10 @@ 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);
Glonass_channels += configuration->property("Channels_2G.count", 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);
}
@ -775,6 +785,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 != "W")
{
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 != "W")
{
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 != "W")
{
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 != 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<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(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)
{
@ -792,6 +868,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 +
@ -799,7 +876,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
@ -1009,6 +1087,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)
{
@ -1487,6 +1595,13 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
out_streams));
block = std::move(block_);
}
else if (implementation == "BEIDOU_B1I_PCPS_Acquisition")
{
std::unique_ptr<AcquisitionInterface> block_(new BeidouB1iPcpsAcquisition(configuration.get(), role, in_streams,
out_streams));
block = std::move(block_);
}
// TRACKING BLOCKS -------------------------------------------------------------
else if (implementation == "GPS_L1_CA_DLL_PLL_Tracking")
{
@ -1614,6 +1729,12 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
out_streams));
block = std::move(block_);
}
else if (implementation == "BEIDOU_B1I_DLL_PLL_Tracking")
{
std::unique_ptr<GNSSBlockInterface> block_(new BeidouB1iDllPllTracking(configuration.get(), role, in_streams,
out_streams));
block = std::move(block_);
}
// TELEMETRY DECODERS ----------------------------------------------------------
else if (implementation == "GPS_L1_CA_Telemetry_Decoder")
{
@ -1663,6 +1784,13 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
out_streams));
block = std::move(block_);
}
else if (implementation == "BEIDOU_B1I_Telemetry_Decoder")
{
std::unique_ptr<GNSSBlockInterface> block_(new BeidouB1iTelemetryDecoder(configuration.get(), role, in_streams,
out_streams));
block = std::move(block_);
}
// OBSERVABLES -----------------------------------------------------------------
else if ((implementation == "Hybrid_Observables") || (implementation == "GPS_L1_CA_Observables") || (implementation == "GPS_L2C_Observables") ||
(implementation == "Galileo_E5A_Observables"))
@ -1851,6 +1979,13 @@ std::unique_ptr<AcquisitionInterface> GNSSBlockFactory::GetAcqBlock(
out_streams));
block = std::move(block_);
}
else if (implementation == "BEIDOU_B1I_PCPS_Acquisition")
{
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.
@ -1995,6 +2130,13 @@ std::unique_ptr<TrackingInterface> GNSSBlockFactory::GetTrkBlock(
out_streams));
block = std::move(block_);
}
else if (implementation == "BEIDOU_B1I_DLL_PLL_Tracking")
{
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.
@ -2061,6 +2203,14 @@ std::unique_ptr<TelemetryDecoderInterface> GNSSBlockFactory::GetTlmBlock(
out_streams));
block = std::move(block_);
}
else if (implementation == "BEIDOU_B1I_Telemetry_Decoder")
{
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

@ -289,8 +289,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
}
@ -403,6 +402,9 @@ void GNSSFlowgraph::connect()
case evGLO_2G:
acq_fs = fs;
break;
case evBDS_B1:
acq_fs = fs;
break;
}
if (acq_fs < fs)
@ -598,6 +600,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";
@ -1015,6 +1023,10 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
available_GLO_2G_signals_.push_back(gs);
break;
case evBDS_B1:
available_BDS_B1_signals_.push_back(channels_[who]->get_signal());
break;
default:
LOG(ERROR) << "This should not happen :-(";
break;
@ -1083,6 +1095,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;
@ -1163,6 +1179,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;
@ -1492,6 +1512,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();
@ -1538,6 +1559,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, 36, 37};
std::string sv_list = configuration_->property("Galileo.prns", std::string(""));
if (sv_list.length() > 0)
@ -1601,6 +1626,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)
{
@ -1705,6 +1747,21 @@ 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")));
}
}
}
@ -1934,6 +1991,32 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(const std::string& searched_signal
}
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();

View File

@ -55,7 +55,6 @@
#include <queue>
#include <string>
#include <vector>
#include <map>
#if ENABLE_FPGA
#include "gnss_sdr_fpga_sample_counter.h"
@ -184,6 +183,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,
@ -193,7 +193,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,346 @@
/*!
* \file beidou_b1I.h
* \brief Defines system parameters for BeiDou B1I signal and DNAV data
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
* \author Damian Miralles, 2018. dmiralles2009@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 "MATH_CONSTANTS.h"
#include <utility> // std::pair
#include <vector>
// 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]
const int BEIDOU_B1I_SECONDARY_CODE_LENGTH = 20;
const std::string BEIDOU_B1I_SECONDARY_CODE = "00000100110101001110";
const std::string BEIDOU_B1I_SECONDARY_CODE_STR = "00000100110101001110";
const std::string BEIDOU_B1I_D2_SECONDARY_CODE_STR = "00";
/*!
* \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
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_DNAV_SUBFRAME_DATA_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 std::string BEIDOU_DNAV_PREAMBLE = "11100010010";
const int BEIDOU_DNAV_PREAMBLE_LENGTH_BITS = 11;
const int BEIDOU_DNAV_PREAMBLE_LENGTH_SYMBOLS = 11; // **************
const double BEIDOU_DNAV_PREAMBLE_PERIOD_SYMBOLS = 300;
const double BEIDOU_DNAV_SUBFRAME_SYMBOLS = 300;
const double BEIDOU_DNAV_DATA_BITS = 300;
const double BEIDOU_DNAV_WORDS_SUBFRAME = 10;
const double BEIDOU_DNAV_WORD_LENGTH_BITS = 30;
const double BEIDOU_D1NAV_SYMBOL_RATE_SPS = 50;
const double BEIDOU_D2NAV_SYMBOL_RATE_SPS = 500;
const double BEIDOU_B1I_PREAMBLE_PERIOD_SYMBOLS = 300;
// 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}});
// DNAV SCALE FACTORS
// EPH
const double D1_TOC_LSB = TWO_P3;
const double D1_TGD1_LSB = 0.1e-9;
const double D1_TGD2_LSB = 0.1e-9;
const double D1_ALPHA0_LSB = TWO_N30;
const double D1_ALPHA1_LSB = TWO_N27;
const double D1_ALPHA2_LSB = TWO_N24;
const double D1_ALPHA3_LSB = TWO_N24;
const double D1_BETA0_LSB = TWO_P11;
const double D1_BETA1_LSB = TWO_P14;
const double D1_BETA2_LSB = TWO_P16;
const double D1_BETA3_LSB = TWO_P16;
const double D1_A2_LSB = TWO_N66;
const double D1_A0_LSB = TWO_N33;
const double D1_A1_LSB = TWO_N50;
const double D1_DELTA_N_LSB = PI_TWO_N43;
const double D1_CUC_LSB = TWO_N31;
const double D1_M0_LSB = PI_TWO_N31;
const double D1_E_LSB = TWO_N33;
const double D1_CUS_LSB = TWO_N31;
const double D1_CRC_LSB = TWO_N6;
const double D1_CRS_LSB = TWO_N6;
const double D1_SQRT_A_LSB = TWO_N19;
const double D1_TOE_LSB = TWO_P3;
const double D1_I0_LSB = PI_TWO_N31;
const double D1_CIC_LSB = TWO_N31;
const double D1_OMEGA_DOT_LSB = PI_TWO_N43;
const double D1_CIS_LSB = TWO_N31;
const double D1_IDOT_LSB = PI_TWO_N43;
const double D1_OMEGA0_LSB = PI_TWO_N31;
const double D1_OMEGA_LSB = PI_TWO_N31;
//ALM
const double D1_SQRT_A_ALMANAC_LSB = TWO_N11;
const double D1_A1_ALMANAC_LSB = TWO_N38;
const double D1_A0_ALMANAC_LSB = TWO_N20;
const double D1_OMEGA0_ALMANAC_LSB = PI_TWO_N23;
const double D1_E_ALMANAC_LSB = TWO_N21;
const double D1_DELTA_I_LSB = PI_TWO_N19;
const double D1_TOA_LSB = TWO_P12;
const double D1_OMEGA_DOT_ALMANAC_LSB = PI_TWO_N38;
const double D1_OMEGA_ALMANAC_LSB = PI_TWO_N23;
const double D1_M0_ALMANAC_LSB = PI_TWO_N23;
const double D1_A0GPS_LSB = 0.1e-9;
const double D1_A1GPS_LSB = 0.1e-9;
const double D1_A0GAL_LSB = 0.1e-9;
const double D1_A1GAL_LSB = 0.1e-9;
const double D1_A0GLO_LSB = 0.1e-9;
const double D1_A1GLO_LSB = 0.1e-9;
const double D1_A0UTC_LSB = TWO_N30;
const double D1_A1UTC_LSB = TWO_N50;
// 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 std::vector<std::pair<int, int> > D1_TGD1({{99, 10}});
const std::vector<std::pair<int, int> > D1_TGD2({{121, 6}});
const std::vector<std::pair<int, int> > D1_ALPHA0({{127, 8}});
const std::vector<std::pair<int, int> > D1_ALPHA1({{135, 8}});
const std::vector<std::pair<int, int> > D1_ALPHA2({{151, 8}});
const std::vector<std::pair<int, int> > D1_ALPHA3({{159, 8}});
const std::vector<std::pair<int, int> > D1_BETA0({{167, 6}, {181, 2}});
const std::vector<std::pair<int, int> > D1_BETA1({{183, 8}});
const std::vector<std::pair<int, int> > D1_BETA2({{191, 8}});
const std::vector<std::pair<int, int> > D1_BETA3({{199, 4}, {211, 4}});
const std::vector<std::pair<int, int> > D1_A2({{215, 11}});
const std::vector<std::pair<int, int> > D1_A0({{226, 7}, {241, 17}});
const std::vector<std::pair<int, int> > D1_A1({{258, 5}, {271, 17}});
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 std::vector<std::pair<int, int> > D1_CUC({{67, 16}, {91, 2}});
const std::vector<std::pair<int, int> > D1_M0({{93, 20}, {121, 12}});
const std::vector<std::pair<int, int> > D1_E({{133, 10}, {151, 22}});
const std::vector<std::pair<int, int> > D1_CUS({{181, 18}});
const std::vector<std::pair<int, int> > D1_CRC({{199, 4}, {211, 14}});
const std::vector<std::pair<int, int> > D1_CRS({{225, 8}, {241, 10}});
const std::vector<std::pair<int, int> > D1_SQRT_A({{251, 12}, {271, 20}});
const std::vector<std::pair<int, int> > D1_TOE_SF2({{291, 2}});
//SUBFRAME 3
const std::vector<std::pair<int, int> > D1_TOE_SF3({{43, 10}, {61, 5}});
const std::vector<std::pair<int, int> > D1_I0({{66, 17}, {91, 15}});
const std::vector<std::pair<int, int> > D1_CIC({{106, 7}, {121, 11}});
const std::vector<std::pair<int, int> > D1_OMEGA_DOT({{132, 11}, {151, 13}});
const std::vector<std::pair<int, int> > D1_CIS({{164, 9}, {181, 9}});
const std::vector<std::pair<int, int> > D1_IDOT({{190, 13}, {211, 1}});
const std::vector<std::pair<int, int> > D1_OMEGA0({{212, 21}, {241, 11}});
const std::vector<std::pair<int, int> > D1_OMEGA({{252, 11}, {271, 21}});
//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 std::vector<std::pair<int, int> > D1_A1_ALMANAC({{91, 11}});
const std::vector<std::pair<int, int> > D1_A0_ALMANAC({{102, 11}});
const std::vector<std::pair<int, int> > D1_OMEGA0_ALMANAC({{121, 22}, {151, 2}});
const std::vector<std::pair<int, int> > D1_E_ALMANAC({{153, 17}});
const std::vector<std::pair<int, int> > D1_DELTA_I({{170, 3}, {181, 13}});
const std::vector<std::pair<int, int> > D1_TOA({{194, 8}});
const std::vector<std::pair<int, int> > D1_OMEGA_DOT_ALMANAC({{202, 1}, {211, 16}});
const std::vector<std::pair<int, int> > D1_OMEGA_ALMANAC({{227, 6}, {241, 18}});
const std::vector<std::pair<int, int> > D1_M0_ALMANAC({{259, 4}, {271, 20}});
//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 std::vector<std::pair<int, int> > D1_A1GPS({{111, 2}, {121, 14}});
const std::vector<std::pair<int, int> > D1_A0GAL({{135, 8}, {151, 6}});
const std::vector<std::pair<int, int> > D1_A1GAL({{157, 16}});
const std::vector<std::pair<int, int> > D1_A0GLO({{181, 14}});
const std::vector<std::pair<int, int> > D1_A1GLO({{195, 8}, {211, 8}});
//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 std::vector<std::pair<int, int> > D1_A1UTC({{131, 12}, {151, 12}});
const std::vector<std::pair<int, int> > D1_DN({{163, 8}});
// D2 NAV Message Decoding Information
const std::vector<std::pair<int, int> > D2_PRE({{1, 11}});
const std::vector<std::pair<int, int> > D2_FRAID({{16, 3}});
const std::vector<std::pair<int, int> > D2_SOW({{19, 8}, {31, 12}});
const std::vector<std::pair<int, int> > D2_PNUM({{43, 4}});
// D2 NAV, SUBFRAME 1, PAGE 1
const std::vector<std::pair<int, int> > D2_SAT_H1({{47, 1}});
const std::vector<std::pair<int, int> > D2_AODC({{48, 5}});
const std::vector<std::pair<int, int> > D2_URAI({{61, 4}});
const std::vector<std::pair<int, int> > D2_WN({{65, 13}});
const std::vector<std::pair<int, int> > D2_TOC({{78, 5}, {91, 12}});
const std::vector<std::pair<int, int> > D2_TGD1({{103, 10}});
const std::vector<std::pair<int, int> > D2_TGD2({{121, 10}});
// D2 NAV, SUBFRAME 1, PAGE 2
const std::vector<std::pair<int, int> > D2_ALPHA0({{47, 6}, {61, 2}});
const std::vector<std::pair<int, int> > D2_ALPHA1({{63, 8}});
const std::vector<std::pair<int, int> > D2_ALPHA2({{71, 8}});
const std::vector<std::pair<int, int> > D2_ALPHA3({{79, 4}, {91, 4}});
const std::vector<std::pair<int, int> > D2_BETA0({{95, 8}});
const std::vector<std::pair<int, int> > D2_BETA1({{103, 8}});
const std::vector<std::pair<int, int> > D2_BETA2({{111, 2}, {121, 6}});
const std::vector<std::pair<int, int> > D2_BETA3({{127, 8}});
// D2 NAV, SUBFRAME 1, PAGE 3
const std::vector<std::pair<int, int> > D2_A0({{101, 12}, {121, 12}});
const std::vector<std::pair<int, int> > D2_A1_MSB({{133, 4}});
const std::vector<std::pair<int, int> > D2_A1_LSB({{47, 6}, {61, 12}});
const std::vector<std::pair<int, int> > D2_A1({{279, 22}});
// D2 NAV, SUBFRAME 1, PAGE 4
const std::vector<std::pair<int, int> > D2_A2({{73, 10}, {91, 1}});
const std::vector<std::pair<int, int> > D2_AODE({{92, 5}});
const std::vector<std::pair<int, int> > D2_DELTA_N({{97, 16}});
const std::vector<std::pair<int, int> > D2_CUC_MSB({{121, 14}});
const std::vector<std::pair<int, int> > D2_CUC_LSB({{47, 4}});
const std::vector<std::pair<int, int> > D2_CUC({{283, 18}});
// D2 NAV, SUBFRAME 1, PAGE 5
const std::vector<std::pair<int, int> > D2_M0({{51, 2}, {61, 22}, {91, 8}});
const std::vector<std::pair<int, int> > D2_CUS({{99, 14}, {121, 4}});
const std::vector<std::pair<int, int> > D2_E_MSB({{125, 10}});
// D2 NAV, SUBFRAME 1, PAGE 6
const std::vector<std::pair<int, int> > D2_E_LSB({{47, 6}, {61, 16}});
const std::vector<std::pair<int, int> > D2_SQRT_A({{77, 6}, {91, 22}, {121, 4}});
const std::vector<std::pair<int, int> > D2_CIC_MSB({{125, 10}});
const std::vector<std::pair<int, int> > D2_CIC_LSB({{47, 6}, {61, 2}});
const std::vector<std::pair<int, int> > D2_CIC({{283, 18}});
// D2 NAV, SUBFRAME 1, PAGE 7
const std::vector<std::pair<int, int> > D2_CIS({{63, 18}});
const std::vector<std::pair<int, int> > D2_TOE({{81, 2}, {91, 15}});
const std::vector<std::pair<int, int> > D2_I0_MSB({{106, 7}, {121, 14}});
const std::vector<std::pair<int, int> > D2_I0_LSB({{47, 6}, {61, 5}});
const std::vector<std::pair<int, int> > D2_I0({{269, 32}});
// D2 NAV, SUBFRAME 1, PAGE 8
const std::vector<std::pair<int, int> > D2_CRC({{66, 17}, {91, 1}});
const std::vector<std::pair<int, int> > D2_CRS({{92, 18}});
const std::vector<std::pair<int, int> > D2_OMEGA_DOT_MSB({{110, 3}, {121, 16}});
const std::vector<std::pair<int, int> > D2_OMEGA_DOT_LSB({{47, 5}});
const std::vector<std::pair<int, int> > D2_OMEGA_DOT({{277, 24}});
// D2 NAV, SUBFRAME 1, PAGE 9
const std::vector<std::pair<int, int> > D2_OMEGA0({{52, 1}, {61, 22}, {91, 9}});
const std::vector<std::pair<int, int> > D2_OMEGA_MSB({{100, 13}, {121, 14}});
const std::vector<std::pair<int, int> > D2_OMEGA_LSB({{47, 5}});
const std::vector<std::pair<int, int> > D2_OMEGA({{269, 32}});
// D2 NAV, SUBFRAME 1, PAGE 10
const std::vector<std::pair<int, int> > D2_IDOT({{52, 1}, {61, 13}});
#endif /* GNSS_SDR_BEIDOU_B1I_H_ */

View File

@ -34,6 +34,11 @@ set(SYSTEM_PARAMETERS_SOURCES
galileo_almanac_helper.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
@ -75,6 +80,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
@ -86,6 +96,7 @@ set(SYSTEM_PARAMETERS_HEADERS
GPS_L1_CA.h
GPS_L2C.h
GPS_L5.h
Beidou_B1I.h
MATH_CONSTANTS.h
)

View File

@ -98,7 +98,6 @@ const int32_t GALILEO_E1_CODE_PERIOD_MS = 4;
const std::vector<std::pair<int32_t, int32_t>> type({{1, 6}});
const std::vector<std::pair<int32_t, int32_t>> PAGE_TYPE_bit({{1, 6}});
;
/*Page 1 - Word type 1: Ephemeris (1/4)*/
const std::vector<std::pair<int32_t, int32_t>> IOD_nav_1_bit({{7, 10}});

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
@ -91,13 +92,14 @@ const double TWO_N44 = (5.684341886080802e-14); //!< 2^-44
const double TWO_N46 = (1.4210854715202e-014); //!< 2^-46
const double TWO_N48 = (3.552713678800501e-15); //!< 2^-46
const double TWO_N50 = (8.881784197001252e-016); //!< 2^-50
const double TWO_N51 = (4.44089209850063e-016); //!< 2^-51
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_N68 = (3.388131789017201e-21); //!< 2^-68
const double TWO_N50 = (8.881784197001252e-016); //!< 2^-50
const double TWO_N51 = (4.44089209850063e-016); //!< 2^-51
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
const double PI_TWO_N19 = (5.992112452678286e-006); //!< Pi*2^-19

View File

@ -0,0 +1,49 @@
/*!
* \file beidou_dnav_almanac.cc
* \brief Interface of a Beidou DNAV 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_Dnav_Almanac::Beidou_Dnav_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,88 @@
/*!
* \file beidou_dnav_almanac.h
* \brief Interface of a Beidou DNAV Almanac storage
*
* \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_DNAV_ALMANAC_H_
#define GNSS_SDR_BEIDOU_DNAV_ALMANAC_H_
#include <boost/serialization/nvp.hpp>
#include <cstdint>
/*!
* \brief This class is a storage for the BeiDou D1 almanac
*/
class Beidou_Dnav_Almanac
{
public:
unsigned int i_satellite_PRN; //!< SV PRN NUMBER
double d_Delta_i;
double d_Toa; //!< Almanac data reference time of week [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_Dnav_Almanac();
template <class Archive>
void serialize(Archive& ar, const unsigned int version)
{
if (version)
{
};
ar& BOOST_SERIALIZATION_NVP(i_satellite_PRN);
ar& BOOST_SERIALIZATION_NVP(d_Delta_i);
ar& BOOST_SERIALIZATION_NVP(d_Toa);
//ar& BOOST_SERIALIZATION_NVP(i_WNa);
ar& BOOST_SERIALIZATION_NVP(d_M_0);
ar& BOOST_SERIALIZATION_NVP(d_e_eccentricity);
ar& BOOST_SERIALIZATION_NVP(d_sqrt_A);
ar& BOOST_SERIALIZATION_NVP(d_OMEGA0);
ar& BOOST_SERIALIZATION_NVP(d_OMEGA);
ar& BOOST_SERIALIZATION_NVP(d_OMEGA_DOT);
ar& BOOST_SERIALIZATION_NVP(i_SV_health);
//ar& BOOST_SERIALIZATION_NVP(i_AS_status);
ar& BOOST_SERIALIZATION_NVP(d_A_f0);
ar& BOOST_SERIALIZATION_NVP(d_A_f1);
}
};
#endif

View File

@ -0,0 +1,282 @@
/*!
* \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 "Beidou_B1I.h"
#include "gnss_satellite.h"
#include <cmath>
Beidou_Dnav_Ephemeris::Beidou_Dnav_Ephemeris()
{
i_satellite_PRN = 0;
d_TOW = 0;
d_Crs = 0;
d_Delta_n = 0;
d_M_0 = 0;
d_Cuc = 0;
d_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;
i_sig_type = 0;
i_nav_type = 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_Dnav_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_Dnav_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_Dnav_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_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_eccentricity * d_sqrt_A * sin(E);
return d_dtr;
}
double Beidou_Dnav_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_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_eccentricity * d_eccentricity) * sin(E);
double tmp_X = cos(E) - d_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_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_eccentricity * sin(E) / (BEIDOU_C_m_s * BEIDOU_C_m_s);
return dtr_s;
}

View File

@ -0,0 +1,208 @@
/*!
* \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_DNAV_EPHEMERIS_H_
#define GNSS_SDR_BEIDOU_DNAV_EPHEMERIS_H_
#include "boost/assign.hpp"
#include <boost/serialization/nvp.hpp>
#include <map>
#include <string>
/*!
* \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_Dnav_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_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]
int i_sig_type; //!< BDS: data source (0:unknown,1:B1I,2:B1Q,3:B2I,4:B2Q,5:B3I,6:B3Q) */
int i_nav_type; //!< BDS: nav type (0:unknown,1:IGSO/MEO,2:GEO) */
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]
/*! \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_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_Dnav_Ephemeris();
};
#endif

View File

@ -0,0 +1,45 @@
/*!
* \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_Dnav_Iono::Beidou_Dnav_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,82 @@
/*!
* \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_DNAV_IONO_H_
#define GNSS_SDR_BEIDOU_DNAV_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_Dnav_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_Dnav_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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,328 @@
/*!
* \file beidou_navigation_message.h
* \brief Interface of a BeiDou DNAV Data message decoder
* \author Sergi Segura, 2018. sergi.segura.munoz(at)gmail.com
* \author Damian Miralles, 2018. dmiralles2009@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_DNAV_NAVIGATION_MESSAGE_H_
#define GNSS_SDR_BEIDOU_DNAV_NAVIGATION_MESSAGE_H_
#include "Beidou_B1I.h"
#include "beidou_dnav_almanac.h"
#include "beidou_dnav_ephemeris.h"
#include "beidou_dnav_iono.h"
#include "beidou_dnav_utc_model.h"
#include <bitset>
#include <map>
#include <string>
#include <utility>
#include <vector>
/*!
* \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_Dnav_Navigation_Message
{
private:
unsigned long int read_navigation_unsigned(std::bitset<BEIDOU_DNAV_SUBFRAME_DATA_BITS> bits, const std::vector<std::pair<int, int>>& parameter);
signed long int read_navigation_signed(std::bitset<BEIDOU_DNAV_SUBFRAME_DATA_BITS> bits, const std::vector<std::pair<int, int>>& parameter);
bool read_navigation_bool(std::bitset<BEIDOU_DNAV_SUBFRAME_DATA_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:
// System flags for data processing
bool flag_eph_valid;
bool flag_utc_model_valid;
bool flag_iono_valid;
bool flag_d1_sf1;
bool flag_d1_sf2;
bool flag_d1_sf3;
bool flag_d1_sf4;
bool flag_d1_sf5;
bool flag_new_SOW_available;
bool flag_crc_test;
double d_previous_aode;
bool flag_d1_sf5_p7; //!< D1 NAV Message, Subframe 5, Page 09 decoded indicator
bool flag_d1_sf5_p8; //!< D1 NAV Message, Subframe 5, Page 09 decoded indicator
bool flag_d1_sf5_p9; //!< D1 NAV Message, Subframe 5, Page 09 decoded indicator
bool flag_d1_sf5_p10; //!< D1 NAV Message, Subframe 5, Page 10 decoded indicator
bool flag_sf1_p1; //!< D2 NAV Message, Subframe 1, Page 1 decoded indicator
bool flag_sf1_p2; //!< D2 NAV Message, Subframe 1, Page 2 decoded indicator
bool flag_sf1_p3; //!< D2 NAV Message, Subframe 1, Page 3 decoded indicator
bool flag_sf1_p4; //!< D2 NAV Message, Subframe 1, Page 4 decoded indicator
bool flag_sf1_p5; //!< D2 NAV Message, Subframe 1, Page 5 decoded indicator
bool flag_sf1_p6; //!< D2 NAV Message, Subframe 1, Page 6 decoded indicator
bool flag_sf1_p7; //!< D2 NAV Message, Subframe 1, Page 7 decoded indicator
bool flag_sf1_p8; //!< D2 NAV Message, Subframe 1, Page 8 decoded indicator
bool flag_sf1_p9; //!< D2 NAV Message, Subframe 1, Page 9 decoded indicator
bool flag_sf1_p10; //!< D2 NAV Message, Subframe 1, Page 10 decoded indicator
//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_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_sf2; //!< Ephemeris data reference time of week in subframe 2, D1 Message
double d_Toe_sf3; //!< Ephemeris data reference time of week in subframe 3, D1 Message
double d_Toe; //!< Ephemeris data reference time of week in subframe 1, D2 Message
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 [s]
double d_TGD2; //!< Estimated Group Delay Differential in B2 [s]
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; //!< Clock correction parameters. Coefficient 0 of code phase offset model [s]
double d_A_f1; //!< Clock correction parameters. Coefficient 1 of code phase offset model [s/s]
double d_A_f2; //!< Clock correction parameters. Coefficient 2 of code phase offset model [s/s^2]
// D2 NAV Message Decoding
unsigned long int d_A_f1_msb_bits; //!< Clock correction parameters, D2 NAV MSB
unsigned long int d_A_f1_lsb_bits; //!< Clock correction parameters, D2 NAV LSB
unsigned long int d_Cuc_msb_bits; //!< Amplitude of the Cosine Harmonic Correction Term to the Argument of Latitude [rad]
unsigned long int d_Cuc_lsb_bits; //!< Amplitude of the Cosine Harmonic Correction Term to the Argument of Latitude [rad]
unsigned long int d_eccentricity_msb; //!< Eccentricity [dimensionless]
unsigned long int d_eccentricity_lsb; //!< Eccentricity [dimensionless]
unsigned long int d_Cic_msb_bits; //!< Amplitude of the Cosine Harmonic Correction Term to the Argument of Latitude [rad]
unsigned long int d_Cic_lsb_bits; //!< Amplitude of the Cosine Harmonic Correction Term to the Argument of Latitude [rad]
unsigned long int d_eccentricity_msb_bits; //!< Eccentricity [dimensionless]
unsigned long int d_eccentricity_lsb_bits;
unsigned long int d_i_0_msb_bits; //!< Inclination Angle at Reference Time [semi-circles]
unsigned long int d_i_0_lsb_bits; //!< Inclination Angle at Reference Time [semi-circles]
unsigned long int d_OMEGA_msb_bits; //!< Argument of Perigee [semi-cicles]
unsigned long int d_OMEGA_lsb_bits; //!< Argument of Perigee [semi-cicles]
unsigned long int d_OMEGA_DOT_msb_bits; //!< Rate of Right Ascension [semi-circles/s]
unsigned long int d_OMEGA_DOT_lsb_bits; //!< Rate of Right Ascension [semi-circles/s]
// 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
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
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_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_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_Dnav_Ephemeris get_ephemeris();
/*!
* \brief Obtain a GPS ionospheric correction parameters class filled with current SV data
*/
Beidou_Dnav_Iono get_iono();
/*!
* \brief Obtain a GPS UTC model parameters class filled with current SV data
*/
Beidou_Dnav_Utc_Model get_utc_model();
/*!
* \brief Decodes the BDS D1 NAV message
*/
int d1_subframe_decoder(std::string const& subframe);
/*!
* \brief Decodes the BDS D2 NAV message
*/
int d2_subframe_decoder(std::string const& 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();
/*
* \brief Returns true if new Ephemeris has arrived. The flag is set to false when the function is executed
*/
bool have_new_ephemeris();
/*
* \brief Returns true if new Iono model has arrived. The flag is set to false when the function is executed
*/
bool have_new_iono();
/*
* \brief Returns true if new UTC model has arrived. The flag is set to false when the function is executed
*/
bool have_new_utc_model();
/*
* \brief Returns true if new UTC model has arrived. The flag is set to false when the function is executed
*/
bool have_new_almanac();
/*!
* Default constructor
*/
Beidou_Dnav_Navigation_Message();
};
#endif

View File

@ -0,0 +1,51 @@
/*!
* \file beidou_dnav_utc_model.c
* \brief Interface of a BeiDou UTC Model storage
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
* \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_utc_model.h"
Beidou_Dnav_Utc_Model::Beidou_Dnav_Utc_Model()
{
valid = false;
d_A1_UTC = 0;
d_A0_UTC = 0;
d_DeltaT_LS = 0;
i_WN_LSF = 0;
i_DN = 0;
d_DeltaT_LSF = 0;
d_A0_GPS = 0;
d_A1_GPS = 0;
d_A0_GAL = 0;
d_A1_GAL = 0;
d_A0_GLO = 0;
d_A1_GLO = 0;
}

View File

@ -0,0 +1,98 @@
/*!
* \file beidou_dnav_utc_model.h
* \brief Interface of a BeiDou UTC MODEL storage
* \author Damian Miralles, 2018. dmiralles2009@gmail.com
* \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_DNAV_UTC_MODEL_H_
#define GNSS_SDR_BEIDOU_DNAV_UTC_MODEL_H_
#include <boost/assign.hpp>
#include <boost/serialization/nvp.hpp>
/*!
* \brief This class is a storage for the BeiDou DNAV UTC Model.
* \details Implementation follows the interface described in the Open Service Signal (Version 2.1)
*
*/
class Beidou_Dnav_Utc_Model
{
public:
bool valid;
// BeiDou UTC parameters
double d_A0_UTC; //!< BDT clock bias relative to UTC [s]
double d_A1_UTC; //!< BDT clock rate relative to UTC [s/s]
double d_DeltaT_LS; //!< Delta time due to leap seconds before the new leap second effective
int i_WN_LSF; //!< Week number of the new leap second
int i_DN; //!< Day number of week of the new leap second
double d_DeltaT_LSF; //!< Delta time due to leap seconds after the new leap second effective [s]
// BeiDou to GPS time corrections
double d_A0_GPS; //!< BDT clock bias relative to GPS time [s]
double d_A1_GPS; //!< BDT clock rate relative to GPS time [s/s]
// BeiDou to Galileo time corrections
double d_A0_GAL; //!< BDT clock bias relative to GAL time [s]
double d_A1_GAL; //!< BDT clock rate relative to GAL time [s/s]
// BeiDou to GLONASS time corrections
double d_A0_GLO; //!< BDT clock bias relative to GLO time [s]
double d_A1_GLO; //!< BDT clock rate relative to GLO time [s/s]
Beidou_Dnav_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_UTC);
archive& make_nvp("d_A0", d_A0_UTC);
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);
archive& make_nvp("d_A0_GPS", d_A0_GPS);
archive& make_nvp("d_A0_GPS", d_A1_GPS);
archive& make_nvp("d_A0_GPS", d_A0_GAL);
archive& make_nvp("d_A0_GPS", d_A1_GAL);
archive& make_nvp("d_A0_GPS", d_A0_GLO);
archive& make_nvp("d_A0_GPS", d_A1_GLO);
}
};
#endif

View File

@ -224,6 +224,19 @@ void Gnss_Satellite::set_PRN(uint32_t PRN_)
PRN = PRN_;
}
}
else if (system == "Beidou")
{
if (PRN_ < 1 or PRN_ > 37)
{
DLOG(INFO) << "This PRN is not defined";
PRN = 0;
}
else
{
PRN = PRN_;
}
}
else
{
DLOG(INFO) << "System " << system << " is not defined";
@ -603,6 +616,57 @@ std::string Gnss_Satellite::what_block(const std::string& system_, uint32_t PRN_
block_ = std::string("Unknown(Simulated)");
}
}
if (system_ == "Beidou")
{
// Check https://en.wikipedia.org/wiki/List_of_BeiDou_satellites
switch (PRN_)
{
case 19:
block_ = std::string("BEIDOU-3 M1"); //!<Slot B-7; launched 2017/11/05
break;
case 20:
block_ = std::string("BEIDOU-3 M2"); //!<Slot B-5; launched 2017/11/05
break;
case 21:
block_ = std::string("BEIDOU 3M5"); //!<Slot B-?; launched 2018/02/12
break;
case 22:
block_ = std::string("BEIDOU 3M6"); //!<Slot B-6; launched 2018/02/12
break;
case 23:
block_ = std::string("BEIDOU 3M9"); //!<Slot C-7; launched 2018/07/29
break;
case 24:
block_ = std::string("BEIDOU 3M10"); //!<Slot C-1; launched 2018/07/29
break;
case 25:
block_ = std::string("BEIDOU 3M12"); //!<Slot C-8; launched 2018/08/24
break;
case 26:
block_ = std::string("BEIDOU 3M11"); //!<Slot C-2; launched 2018/08/24
break;
case 27:
block_ = std::string("BEIDOU 3M3"); //!<Slot A-?; launched 2018/01/11
break;
case 28:
block_ = std::string("BEIDOU 3M4"); //!<Slot A-?; launched 2018/01/11
break;
case 29:
block_ = std::string("BEIDOU 3M7"); //!<Slot A-?; launched 2018/03/29
break;
case 30:
block_ = std::string("BEIDOU 3M8"); //!<Slot A-?; launched 2018/03/29
break;
case 32:
block_ = std::string("BEIDOU 3M13"); //!<Slot B-1?; launched 2018/09/19
break;
case 33:
block_ = std::string("BEIDOU 3M14"); //!<Slot B-3; launched 2018/09/19
break;
default:
block_ = std::string("Unknown(Simulated)");
}
}
return block_;
}

View File

@ -119,6 +119,7 @@ DECLARE_string(log_dir);
#include "unit-tests/signal-processing-blocks/sources/gnss_sdr_valve_test.cc"
#include "unit-tests/signal-processing-blocks/sources/unpack_2bit_samples_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 "Beidou_B1I.h"
#include "acquisition_dump_reader.h"
#include "beidou_b1i_pcps_acquisition.h"
#include "gnss_block_factory.h"
#include "gnss_block_interface.h"
#include "gnss_sdr_valve.h"
#include "gnss_synchro.h"
#include "gnuplot_i.h"
#include "in_memory_configuration.h"
#include "test_flags.h"
#include <boost/filesystem.hpp>
#include <boost/make_shared.hpp>
#include <glog/logging.h>
#include <gnuradio/analog/sig_source_c.h>
#include <gnuradio/analog/sig_source_waveform.h>
#include <gnuradio/blocks/file_source.h>
#include <gnuradio/blocks/null_sink.h>
#include <gnuradio/msg_queue.h>
#include <gnuradio/top_block.h>
#include <gtest/gtest.h>
#include <chrono>
// ######## 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

@ -31,7 +31,6 @@
#include "file_signal_source.h"
#include "in_memory_configuration.h"
#include <gnuradio/blocks/null_sink.h>
#include <gnuradio/msg_queue.h>
#include <gnuradio/top_block.h>
#include <gtest/gtest.h>

View File

@ -70,7 +70,7 @@
#define FIVE_SECONDS 5000000 // five seconds in microseconds
void send_tracking_gps_input_samples(FILE *rx_signal_file,
int num_remaining_samples, const gr::top_block_sptr& top_block)
int num_remaining_samples, const gr::top_block_sptr &top_block)
{
int num_samples_transferred = 0; // number of samples that have been transferred to the DMA so far
static int flowgraph_stopped = 0; // flag to indicate if the flowgraph is stopped already

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'];

View File

@ -28,13 +28,13 @@
%%%%%%%%% ?????? CONFIGURE !!! %%%%%%%%%%%%%
path = '/archive/';
file = 'acq';
path = '/home/dmiralles/Documents/gnss-sdr/';
file = 'bds_acq';
sat = 7;
sat = 32;
channel = 0;
execution = 1;
execution = 3;
% Signal:
% 1 GPS L1
% 2 GPS L2M
@ -42,10 +42,11 @@ execution = 1;
% 4 Gal. E1B
% 5 Gal. E5
% 6 Glo. 1G
% 7 BDS B1
signal_type = 1;
signal_type = 7;
%%% True for light grid representation
%%% True for light acq_grid representation
lite_view = true;
%%% If lite_view, it sets the number of samples per chip in the graphical representation
@ -78,21 +79,25 @@ switch(signal_type)
n_chips = 511;
system = 'R';
signal = '1G';
case 7
n_chips = 2046;
system = 'C';
signal = 'B1';
end
filename = [path file '_' system '_' signal '_ch_' num2str(channel) '_' num2str(execution) '_sat_' num2str(sat) '.mat'];
load(filename);
[n_fft n_dop_bins] = size(grid);
[d_max f_max] = find(grid == max(max(grid)));
[n_fft n_dop_bins] = size(acq_grid);
[d_max f_max] = find(acq_grid == max(max(acq_grid)));
freq = (0 : n_dop_bins - 1) * doppler_step - doppler_max;
delay = (0 : n_fft - 1) / n_fft * n_chips;
figure(1)
if(lite_view == false)
surf(freq, delay, grid, 'FaceColor', 'interp', 'LineStyle', 'none')
surf(freq, delay, acq_grid, 'FaceColor', 'interp', 'LineStyle', 'none')
ylim([min(delay) max(delay)])
else
delay_interp = (0 : n_samples_per_chip * n_chips - 1) / n_samples_per_chip;
grid_interp = spline(delay, grid', delay_interp)';
surf(freq, delay_interp, grid_interp, 'FaceColor', 'interp', 'LineStyle', 'none')
acq_grid_interp = spline(delay, acq_grid', delay_interp)';
surf(freq, delay_interp, acq_grid_interp, 'FaceColor', 'interp', 'LineStyle', 'none')
ylim([min(delay_interp) max(delay_interp)])
end
xlabel('Doppler shift / Hz')
@ -101,14 +106,14 @@ ylabel('Code delay / chips')
zlabel('Test statistics')
figure(2)
subplot(2,1,1)
plot(freq, grid(d_max, :))
plot(freq, acq_grid(d_max, :))
xlim([min(freq) max(freq)])
xlabel('Doppler shift / Hz')
ylabel('Test statistics')
title(['Fixed code delay to ' num2str((d_max - 1) / n_fft * n_chips) ' chips'])
subplot(2,1,2)
normalization = (d_samples_per_code^4) * input_power;
plot(delay, acq_grid(:, f_max)./normalization)
plot(delay, acq_acq_grid(:, f_max)./normalization)
xlim([min(delay) max(delay)])
xlabel('Code delay / chips')
ylabel('Test statistics')