diff --git a/README.md b/README.md index 1b513a25e..554a9428a 100644 --- a/README.md +++ b/README.md @@ -375,7 +375,7 @@ $ sudo make install ###### Build FMCOMMS2 based SDR Hardware support (OPTIONAL): -Install the [libiio](https://github.com/analogdevicesinc/libiio.git) (>=v0.11), [libad9361](https://github.com/analogdevicesinc/libad9361-iio.git) (>=v0.1-1) libraries and [gr-iio](https://github.com/analogdevicesinc/gr-iio.git) (>v0.2) gnuradio block: +Install the [libiio](https://github.com/analogdevicesinc/libiio.git) (>=v0.11), [libad9361](https://github.com/analogdevicesinc/libad9361-iio.git) (>=v0.1-1) libraries and [gr-iio](https://github.com/analogdevicesinc/gr-iio.git) (>v0.3) gnuradio block: ~~~~~~ $ sudo apt-get install libxml2-dev bison flex @@ -1046,9 +1046,12 @@ Each channel must be assigned to a GNSS signal, according to the following ident | **Signal** | **Identifier** | |:------------------|:---------------:| | GPS L1 C/A | 1C | +| Galileo E1b/c | 1B | +| Glonass L1 C/A | 1G | | GPS L2 L2C(M) | 2S | -| Galileo E1B | 1B | -| Galileo E5a (I+Q) | 5X | +| GPS L5 | L5 | +| Galileo E5a | 5X | + Example: Eight GPS L1 C/A channels. diff --git a/conf/front-end-cal.conf b/conf/front-end-cal.conf index af9221936..8b09a2065 100644 --- a/conf/front-end-cal.conf +++ b/conf/front-end-cal.conf @@ -41,17 +41,10 @@ GNSS-SDR.SUPL_LAC=861 GNSS-SDR.SUPL_CI=40184 ;######### SIGNAL_SOURCE CONFIG ############ -;#implementation: Use [File_Signal_Source] or [UHD_Signal_Source] or [GN3S_Signal_Source] or [Osmosdr_Signal_Source] SignalSource.implementation=Osmosdr_Signal_Source -SignalSource.AGC_enabled=false - -;#filename: path to file with the captured GNSS signal samples to be processed -;SignalSource.filename=/datalogger/signals/RTL-SDR/cap_-90dBm_IF15_RF40_EzCap.dat -SignalSource.filename=/datalogger/signals/Agilent/New York/2msps.dat -;SignalSource.filename=/datalogger/signals/RTL-SDR/geo/pmt4_no_amp.dat -;SignalSource.filename=/datalogger/signals/RTL-SDR/geo/pmt4_no_amp_mini.dat -;SignalSource.filename=/datalogger/signals/RTL-SDR/mozoncillo/cap_mozon_ezcap.dat +;#freq: RF front-end center frequency in [Hz] +SignalSource.freq=1575420000 ;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. SignalSource.item_type=gr_complex @@ -59,18 +52,26 @@ SignalSource.item_type=gr_complex ;#sampling_frequency: Original Signal sampling frequency in [Hz] SignalSource.sampling_frequency=2000000 -;#freq: RF front-end center frequency in [Hz] -SignalSource.freq=1575420000 - ;#gain: Front-end Gain in [dB] SignalSource.gain=40 SignalSource.rf_gain=40 SignalSource.if_gain=30 +SignalSource.AGC_enabled=false -;#subdevice: UHD subdevice specification (for USRP1 use A:0 or B:0) -SignalSource.subdevice=B:0 +;# Please note that the new RTL-SDR Blog V3 dongles ship a < 1 PPM +;# temperature compensated oscillator (TCXO), which is well suited for GNSS +;# signal processing, and a 4.5 V powered bias-tee to feed an active antenna. +;# Whether the bias-tee is turned off before reception depends on which version +;# of gr-osmosdr was used when compiling GNSS-SDR. With an old version +;# (for example, v0.1.4-8), the utility rtl_biast may be used to switch the +;# bias-tee, and then call gnss-sdr. +;# See https://github.com/rtlsdrblog/rtl_biast +;# After reception the bias-tee is switched off automatically by the program. +;# With newer versions of gr-osmosdr (>= 0.1.4-13), the bias-tee can be +;# activated by uncommenting the following line: +;SignalSource.osmosdr_args=rtl,bias=1 -;#samples: Number of samples to be processed. Notice that 0 indicates the entire file. +;#samples: Number of samples to be processed. Notice that 0 means infinite samples. SignalSource.samples=0 ;#repeat: Repeat the processing file. diff --git a/conf/gnss-sdr_GLONASS_L1_CA_ibyte_coh_trk.conf b/conf/gnss-sdr_GLONASS_L1_CA_ibyte_coh_trk.conf index ad49d03e0..7e9a9d279 100644 --- a/conf/gnss-sdr_GLONASS_L1_CA_ibyte_coh_trk.conf +++ b/conf/gnss-sdr_GLONASS_L1_CA_ibyte_coh_trk.conf @@ -26,10 +26,10 @@ Resampler.item_type=gr_complex ;######### CHANNELS GLOBAL CONFIG ############ Channel.signal=1G -Channels.in_acquisition=1 +Channels.in_acquisition=2 Channels_1G.count=8 -Channel0.satellite=24 ; k= +Channel0.satellite=24 ; k=2 Channel1.satellite=1 ; k=1 Channel2.satellite=2 ; k=-4 Channel3.satellite=20 ; k=-5 @@ -53,9 +53,9 @@ Tracking_1G.implementation=GLONASS_L1_CA_DLL_PLL_C_Aid_Tracking Tracking_1G.item_type=gr_complex Tracking_1G.if=0 Tracking_1G.early_late_space_chips=0.5 -Tracking_1G.pll_bw_hz=25.0; +Tracking_1G.pll_bw_hz=40.0; Tracking_1G.dll_bw_hz=3.0; -Tracking_1G.pll_bw_narrow_hz = 20.0; +Tracking_1G.pll_bw_narrow_hz = 25.0; Tracking_1G.dll_bw_narrow_hz = 2.0; Tracking_1G.extend_correlation_ms = 1; Tracking_1G.dump=true; diff --git a/conf/gnss-sdr_GPS_L1_fmcomms2_realtime.conf b/conf/gnss-sdr_GPS_L1_fmcomms2_realtime.conf index ae832f901..6c8d8d85c 100644 --- a/conf/gnss-sdr_GPS_L1_fmcomms2_realtime.conf +++ b/conf/gnss-sdr_GPS_L1_fmcomms2_realtime.conf @@ -27,13 +27,11 @@ GNSS-SDR.SUPL_CI=0x31b0 ;######### SIGNAL_SOURCE CONFIG ############ SignalSource.implementation=Fmcomms2_Signal_Source -;SignalSource.filename=/media/DATALOGGER_/signals/RTL-SDR/geo/pmt4.dat SignalSource.item_type=gr_complex SignalSource.device_address=10.42.0.196 SignalSource.sampling_frequency=2000000 SignalSource.freq=1575420000 SignalSource.bandwidth=2000000 -SignalSource.decimation=0 SignalSource.rx1_enable=true SignalSource.gain_mode_rx1=manual SignalSource.rf_port_select=A_BALANCED diff --git a/conf/gnss-sdr_GPS_L1_plutosdr_realtime.conf b/conf/gnss-sdr_GPS_L1_plutosdr_realtime.conf index 97c9deded..83f808645 100644 --- a/conf/gnss-sdr_GPS_L1_plutosdr_realtime.conf +++ b/conf/gnss-sdr_GPS_L1_plutosdr_realtime.conf @@ -27,13 +27,11 @@ GNSS-SDR.SUPL_CI=0x31b0 ;######### SIGNAL_SOURCE CONFIG ############ SignalSource.implementation=Plutosdr_Signal_Source -;SignalSource.filename=/media/DATALOGGER_/signals/RTL-SDR/geo/pmt4.dat SignalSource.item_type=gr_complex SignalSource.device_address=192.168.2.1 SignalSource.sampling_frequency=3000000 SignalSource.freq=1575420000 SignalSource.bandwidth=2600000 -SignalSource.decimation=0 SignalSource.gain_mode=manual SignalSource.gain=30 SignalSource.samples=0 diff --git a/conf/gnss-sdr_GPS_L1_rtlsdr_realtime.conf b/conf/gnss-sdr_GPS_L1_rtlsdr_realtime.conf index 8c5f9022a..2c10ea684 100644 --- a/conf/gnss-sdr_GPS_L1_rtlsdr_realtime.conf +++ b/conf/gnss-sdr_GPS_L1_rtlsdr_realtime.conf @@ -27,9 +27,8 @@ GNSS-SDR.SUPL_CI=0x31b0 ;######### SIGNAL_SOURCE CONFIG ############ SignalSource.implementation=Osmosdr_Signal_Source -;SignalSource.filename=/media/DATALOGGER_/signals/RTL-SDR/geo/pmt4.dat SignalSource.item_type=gr_complex -;FOR USE GNSS-SDR WITH RTLSDR DONGLES USER MUST SET THE CALIBRATED SAMPLE RATE HERE +; FOR USE GNSS-SDR WITH RTLSDR DONGLES USER MUST SET THE CALIBRATED SAMPLE RATE HERE ; i.e. using front-end-cal as reported here:http://www.cttc.es/publication/turning-a-television-into-a-gnss-receiver/ SignalSource.sampling_frequency=2000000 SignalSource.freq=1575420000 @@ -43,6 +42,19 @@ SignalSource.dump=false SignalSource.dump_filename=../data/signal_source.dat SignalSource.enable_throttle_control=false +;# Please note that the new RTL-SDR Blog V3 dongles ship a < 1 PPM +;# temperature compensated oscillator (TCXO), which is well suited for GNSS +;# signal processing, and a 4.5 V powered bias-tee to feed an active antenna. +;# Whether the bias-tee is turned off before reception depends on which version +;# of gr-osmosdr was used when compiling GNSS-SDR. With an old version +;# (for example, v0.1.4-8), the utility rtl_biast may be used to switch the +;# bias-tee, and then call gnss-sdr. +;# See https://github.com/rtlsdrblog/rtl_biast +;# After reception the bias-tee is switched off automatically by the program. +;# With newer versions of gr-osmosdr (>= 0.1.4-13), the bias-tee can be +;# activated by uncommenting the following line: +;SignalSource.osmosdr_args=rtl,bias=1 + ;######### SIGNAL_CONDITIONER CONFIG ############ SignalConditioner.implementation=Signal_Conditioner diff --git a/conf/gnss-sdr_galileo_E1_extended_correlator_byte.conf b/conf/gnss-sdr_galileo_E1_extended_correlator_byte.conf new file mode 100644 index 000000000..fb6a08fc0 --- /dev/null +++ b/conf/gnss-sdr_galileo_E1_extended_correlator_byte.conf @@ -0,0 +1,269 @@ +; Default configuration file +; 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=20000000 + + +;######### SIGNAL_SOURCE CONFIG ############ +;#implementation: Use [File_Signal_Source] or [UHD_Signal_Source] or [GN3S_Signal_Source] (experimental) +SignalSource.implementation=File_Signal_Source + +;#filename: path to file with the captured GNSS signal samples to be processed +;SignalSource.filename=/home/javier/signals/L125_III1b_210s_L1_2msps.bin ; <- PUT YOUR FILE HERE + +SignalSource.filename=/media/javier/SISTEMA/signals/fraunhofer/L125_III1b_210s_L1.bin + +;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. +SignalSource.item_type=byte + +;#sampling_frequency: Original Signal sampling frequency in [Hz] +SignalSource.sampling_frequency=20000000 + +;#freq: RF front-end center frequency in [Hz] +SignalSource.freq=1575420000 + +;#samples: Number of samples to be processed. Notice that 0 indicates the entire file. +SignalSource.samples=0 + +;#repeat: Repeat the processing file. Disable this option in this version +SignalSource.repeat=false + +;#dump: Dump the Signal source data to a file. Disable this option in this version +SignalSource.dump=false + +SignalSource.dump_filename=../data/signal_source.dat + +;#enable_throttle_control: Enabling this option tells the signal source to keep the delay between samples in post processing. +; it helps to not overload the CPU, but the processing time will be longer. +SignalSource.enable_throttle_control=false + + +;######### SIGNAL_CONDITIONER CONFIG ############ +;## It holds blocks to change data type, filter and resample input data. + +;#implementation: Use [Pass_Through] or [Signal_Conditioner] +;#[Pass_Through] disables this block and the [DataTypeAdapter], [InputFilter] and [Resampler] blocks +;#[Signal_Conditioner] enables this block. Then you have to configure [DataTypeAdapter], [InputFilter] and [Resampler] blocks +SignalConditioner.implementation=Signal_Conditioner + +;######### DATA_TYPE_ADAPTER CONFIG ############ +;## Changes the type of input data. Please disable it in this version. +;#implementation: [Pass_Through] disables this block +DataTypeAdapter.implementation=Ibyte_To_Complex + +;######### INPUT_FILTER CONFIG ############ +;## Filter the input data. Can be combined with frequency translation for IF signals + +InputFilter.implementation=Pass_Through + + +;######### RESAMPLER CONFIG ############ +;## Resamples the input data. + +;#implementation: Use [Pass_Through] or [Direct_Resampler] +;#[Pass_Through] disables this block +;#[Direct_Resampler] enables a resampler that implements a nearest neigbourhood interpolation +;Resampler.implementation=Direct_Resampler +Resampler.implementation=Pass_Through + + +;######### CHANNELS GLOBAL CONFIG ############ +;#count: Number of available GPS satellite channels. +Channels_1C.count=0 +;#count: Number of available Galileo satellite channels. +Channels_1B.count=1 +;#in_acquisition: Number of channels simultaneously acquiring for the whole receiver +Channels.in_acquisition=1 + +;#signal: +;#if the option is disabled by default is assigned "1C" GPS L1 C/A +Channel1.signal=1B +Channel2.signal=1B +Channel3.signal=1B +Channel4.signal=1B +Channel5.signal=1B +Channel6.signal=1B +Channel7.signal=1B +Channel8.signal=1B +Channel9.signal=1B +Channel10.signal=1B +Channel11.signal=1B +Channel12.signal=1B +Channel13.signal=1B +Channel14.signal=1B +Channel15.signal=1B + + +;######### GPS ACQUISITION CONFIG ############ + +;#dump: Enable or disable the acquisition internal data file logging [true] or [false] +Acquisition_1C.dump=false +;#filename: Log path and filename +Acquisition_1C.dump_filename=./acq_dump.dat +;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. +Acquisition_1C.item_type=gr_complex +;#if: Signal intermediate frequency in [Hz] +Acquisition_1C.if=0 +;#sampled_ms: Signal block duration for the acquisition signal detection [ms] +Acquisition_1C.sampled_ms=1 +;#implementation: Acquisition algorithm selection for this channel: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] +Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition +Acquisition_1C.use_CFAR_algorithm=false; +;#threshold: Acquisition threshold +Acquisition_1C.threshold=18 +;#doppler_max: Maximum expected Doppler shift [Hz] +Acquisition_1C.doppler_max=5000 +;#doppler_max: Doppler step in the grid search [Hz] +Acquisition_1C.doppler_step=500 + + +;######### GALILEO ACQUISITION CONFIG ############ + +;#dump: Enable or disable the acquisition internal data file logging [true] or [false] +Acquisition_1B.dump=false +;#filename: Log path and filename +Acquisition_1B.dump_filename=../data/acq_dump.dat +;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. +Acquisition_1B.item_type=gr_complex +;#if: Signal intermediate frequency in [Hz] +Acquisition_1B.if=0 +;#sampled_ms: Signal block duration for the acquisition signal detection [ms] +Acquisition_1B.sampled_ms=4 +;#implementation: Acquisition algorithm selection for this channel: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] +Acquisition_1B.implementation=Galileo_E1_PCPS_Ambiguous_Acquisition +Acquisition_1B.acquire_pilot=true +Acquisition_1B.use_CFAR_algorithm=false +;#threshold: Acquisition threshold +Acquisition_1B.threshold=21 +;#doppler_max: Maximum expected Doppler shift [Hz] +Acquisition_1B.doppler_max=5000 +;#doppler_max: Doppler step in the grid search [Hz] +Acquisition_1B.doppler_step=125 +Acquisition_1B.bit_transition_flag=true + +;######### TRACKING GPS CONFIG ############ + +;#implementation: Selected tracking algorithm: [GPS_L1_CA_DLL_PLL_Tracking] or [GPS_L1_CA_DLL_PLL_C_Aid_Tracking] or [GPS_L1_CA_TCP_CONNECTOR_Tracking] or [Galileo_E1_DLL_PLL_VEML_Tracking] +Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking +;#item_type: Type and resolution for each of the signal samples. Use only [gr_complex] in this version. +Tracking_1C.item_type=gr_complex + +;#sampling_frequency: Signal Intermediate Frequency in [Hz] +Tracking_1C.if=0 + +;#dump: Enable or disable the Tracking internal binary data file logging [true] or [false] +Tracking_1C.dump=false + +;#dump_filename: Log path and filename. Notice that the tracking channel will add "x.dat" where x is the channel number. +Tracking_1C.dump_filename=../data/epl_tracking_ch_ + +;#pll_bw_hz: PLL loop filter bandwidth [Hz] +Tracking_1C.pll_bw_hz=30.0; + +;#dll_bw_hz: DLL loop filter bandwidth [Hz] +Tracking_1C.dll_bw_hz=2.0; + +;#order: PLL/DLL loop filter order [2] or [3] +Tracking_1C.order=3; + +;######### TRACKING GALILEO CONFIG ############ + +;#implementation: Selected tracking algorithm: [GPS_L1_CA_DLL_PLL_Tracking] or [GPS_L1_CA_DLL_PLL_C_Aid_Tracking] or [GPS_L1_CA_TCP_CONNECTOR_Tracking] or [Galileo_E1_DLL_PLL_VEML_Tracking] +Tracking_1B.implementation=Galileo_E1_DLL_PLL_VEML_Tracking +;#item_type: Type and resolution for each of the signal samples. +Tracking_1B.item_type=gr_complex + +;#sampling_frequency: Signal Intermediate Frequency in [Hz] +Tracking_1B.if=0 + +;#dump: Enable or disable the Tracking internal binary data file logging [true] or [false] +Tracking_1B.dump=true + +;#dump_filename: Log path and filename. Notice that the tracking channel will add "x.dat" where x is the channel number. +Tracking_1B.dump_filename=../data/veml_tracking_ch_ + +Tracking_1B.track_pilot=true + +;#pll_bw_hz: PLL loop filter bandwidth [Hz] +Tracking_1B.pll_bw_hz=4.0; + +;#dll_bw_hz: DLL loop filter bandwidth [Hz] +Tracking_1B.dll_bw_hz=0.5; + +;#pll_bw_hz: PLL loop filter bandwidth [Hz] +Tracking_1B.pll_bw_narrow_hz=2.0; + +;#dll_bw_hz: DLL loop filter bandwidth [Hz] +Tracking_1B.dll_bw_narrow_hz=0.25; + +Tracking_1B.extend_correlation_symbols=4; + +;#order: PLL/DLL loop filter order [2] or [3] +Tracking_1B.order=3; + +;#early_late_space_chips: correlator early-late space [chips]. Use [0.5] for GPS and [0.15] for Galileo +Tracking_1B.early_late_space_chips=0.15; + +;#very_early_late_space_chips: only for [Galileo_E1_DLL_PLL_VEML_Tracking], correlator very early-late space [chips]. Use [0.6] +Tracking_1B.very_early_late_space_chips=0.6; + +;#early_late_space_chips: correlator early-late space [chips]. Use [0.5] for GPS and [0.15] for Galileo +Tracking_1B.early_late_space_narrow_chips=0.06; + +;#very_early_late_space_chips: only for [Galileo_E1_DLL_PLL_VEML_Tracking], correlator very early-late space [chips]. Use [0.6] +Tracking_1B.very_early_late_space_narrow_chips=0.25; + + + +;######### TELEMETRY DECODER GPS CONFIG ############ +;#implementation: Use [GPS_L1_CA_Telemetry_Decoder] for GPS L1 C/A +TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder +TelemetryDecoder_1C.dump=false +;#decimation factor +TelemetryDecoder_1C.decimation_factor=4; + +;######### TELEMETRY DECODER GALILEO CONFIG ############ +;#implementation: Use [Galileo_E1B_Telemetry_Decoder] for Galileo E1B +TelemetryDecoder_1B.implementation=Galileo_E1B_Telemetry_Decoder +TelemetryDecoder_1B.dump=false + +;######### OBSERVABLES CONFIG ############ +;#implementation: +Observables.implementation=Hybrid_Observables + +;#dump: Enable or disable the Observables internal binary data file logging [true] or [false] +Observables.dump=false + +;#dump_filename: Log path and filename. +Observables.dump_filename=./observables.dat + + +;######### PVT CONFIG ############ +;#implementation: Position Velocity and Time (PVT) implementation: +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 + +;#output_rate_ms: Period between two PVT outputs. Notice that the minimum period is equal to the tracking integration time (for GPS CA L1 is 1ms) [ms] +PVT.output_rate_ms=100; + +;#display_rate_ms: Position console print (std::out) interval [ms]. Notice that output_rate_ms<=display_rate_ms. +PVT.display_rate_ms=500; + +;#dump: Enable or disable the PVT internal binary data file logging [true] or [false] +PVT.dump=false + +PVT.flag_rtcm_server=false +PVT.flag_rtcm_tty_port=false +PVT.rtcm_dump_devname=/dev/pts/1 + +;#dump_filename: Log path and filename without extension. Notice that PVT will add ".dat" to the binary dump and ".kml" to GoogleEarth dump. +PVT.dump_filename=./PVT diff --git a/conf/gnss-sdr_galileo_E1_extended_correlator_labsat.conf b/conf/gnss-sdr_galileo_E1_extended_correlator_labsat.conf new file mode 100644 index 000000000..094f15ebe --- /dev/null +++ b/conf/gnss-sdr_galileo_E1_extended_correlator_labsat.conf @@ -0,0 +1,333 @@ +; Default configuration file +; 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_hz: Internal signal sampling frequency after the signal conditioning stage [Hz]. +GNSS-SDR.internal_fs_hz=5456000 + +;######### SIGNAL_SOURCE CONFIG ############ +;#implementation: Use [File_Signal_Source] [Nsr_File_Signal_Source] or [UHD_Signal_Source] or [GN3S_Signal_Source] (experimental) +SignalSource.implementation=Labsat_Signal_Source + +SignalSource.selected_channel=1 + +;#filename: path to file with the captured GNSS signal samples to be processed +;# Labsat sile source automatically increments the file name when the signal is splitted in several files +;# the adapter adds "_0000.LS3" to this base path and filename. Next file will be "_0001.LS3" and so on +;# in this example, the first file complete path will be ../signals/GPS_025_0000.LS3 + +SignalSource.filename=../signals/GPS_025 ; <- PUT YOUR FILE HERE + +;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. +SignalSource.item_type=gr_complex + +;#sampling_frequency: Original Signal sampling frequency in [Hz] +SignalSource.sampling_frequency=16368000 + +;#freq: RF front-end center frequency in [Hz] +SignalSource.freq=1575420000 + +;#samples: Number of samples to be processed. Notice that 0 indicates the entire file. +SignalSource.samples=0 + +;#repeat: Repeat the processing file. Disable this option in this version +SignalSource.repeat=false + +;#dump: Dump the Signal source data to a file. Disable this option in this version +SignalSource.dump=false + +SignalSource.dump_filename=../data/signal_source.dat + + +;#enable_throttle_control: Enabling this option tells the signal source to keep the delay between samples in post processing. +; it helps to not overload the CPU, but the processing time will be longer. +SignalSource.enable_throttle_control=false + +;######### SIGNAL_CONDITIONER CONFIG ############ +;## It holds blocks to change data type, filter and resample input data. + +;#implementation: Use [Pass_Through] or [Signal_Conditioner] +;#[Pass_Through] disables this block and the [DataTypeAdapter], [InputFilter] and [Resampler] blocks +;#[Signal_Conditioner] enables this block. Then you have to configure [DataTypeAdapter], [InputFilter] and [Resampler] blocks +SignalConditioner.implementation=Signal_Conditioner + +;######### DATA_TYPE_ADAPTER CONFIG ############ +;## Changes the type of input data. +;#implementation: [Pass_Through] disables this block +DataTypeAdapter.implementation=Pass_Through +DataTypeAdapter.item_type=gr_complex + +;######### INPUT_FILTER CONFIG ############ +;## Filter the input data. Can be combined with frequency translation for IF signals + +;#implementation: Use [Pass_Through] or [Fir_Filter] or [Freq_Xlating_Fir_Filter] +;#[Freq_Xlating_Fir_Filter] enables FIR filter and a composite frequency translation +;# that shifts IF down to zero Hz. + +InputFilter.implementation=Freq_Xlating_Fir_Filter + +;#dump: Dump the filtered data to a file. +InputFilter.dump=false + +;#dump_filename: Log path and filename. +InputFilter.dump_filename=../data/input_filter.dat + +;#The following options are used in the filter design of Fir_Filter and Freq_Xlating_Fir_Filter implementation. +;#These options are based on parameters of gnuradio's function: gr_remez. +;#These function calculates the optimal (in the Chebyshev/minimax sense) FIR filter inpulse +;#reponse given a set of band edges, the desired reponse on those bands, +;#and the weight given to the error in those bands. + +;#input_item_type: Type and resolution for input signal samples. Use only gr_complex in this version. +InputFilter.input_item_type=gr_complex + +;#outut_item_type: Type and resolution for output filtered signal samples. Use only gr_complex in this version. +InputFilter.output_item_type=gr_complex + +;#taps_item_type: Type and resolution for the taps of the filter. Use only float in this version. +InputFilter.taps_item_type=float + +;#number_of_taps: Number of taps in the filter. Increasing this parameter increases the processing time +InputFilter.number_of_taps=5 + +;#number_of _bands: Number of frequency bands in the filter. +InputFilter.number_of_bands=2 + +;#bands: frequency at the band edges [ b1 e1 b2 e2 b3 e3 ...]. +;#Frequency is in the range [0, 1], with 1 being the Nyquist frequency (Fs/2) +;#The number of band_begin and band_end elements must match the number of bands + +InputFilter.band1_begin=0.0 +InputFilter.band1_end=0.45 +InputFilter.band2_begin=0.55 +InputFilter.band2_end=1.0 + +;#ampl: desired amplitude at the band edges [ a(b1) a(e1) a(b2) a(e2) ...]. +;#The number of ampl_begin and ampl_end elements must match the number of bands + +InputFilter.ampl1_begin=1.0 +InputFilter.ampl1_end=1.0 +InputFilter.ampl2_begin=0.0 +InputFilter.ampl2_end=0.0 + +;#band_error: weighting applied to each band (usually 1). +;#The number of band_error elements must match the number of bands +InputFilter.band1_error=1.0 +InputFilter.band2_error=1.0 + +;#filter_type: one of "bandpass", "hilbert" or "differentiator" +InputFilter.filter_type=bandpass + +;#grid_density: determines how accurately the filter will be constructed. +;The minimum value is 16; higher values are slower to compute the filter. +InputFilter.grid_density=16 + +;# Original sampling frequency stored in the signal file +InputFilter.sampling_frequency=16368000 + +;#The following options are used only in Freq_Xlating_Fir_Filter implementation. +;#InputFilter.IF is the intermediate frequency (in Hz) shifted down to zero Hz + +InputFilter.IF=0 + +;# Decimation factor after the frequency tranaslating block +InputFilter.decimation_factor=3 + + +;######### CHANNELS GLOBAL CONFIG ############ +;#count: Number of available GPS satellite channels. +Channels_1C.count=0 +;#count: Number of available Galileo satellite channels. +Channels_1B.count=6 +;#in_acquisition: Number of channels simultaneously acquiring for the whole receiver +Channels.in_acquisition=1 + +;#signal: +;#if the option is disabled by default is assigned "1C" GPS L1 C/A +Channel0.signal=1B +Channel1.signal=1B +Channel2.signal=1B +Channel3.signal=1B +Channel4.signal=1B +Channel5.signal=1B +Channel6.signal=1B +Channel7.signal=1B +Channel8.signal=1B +Channel9.signal=1B +Channel10.signal=1B +Channel11.signal=1B +Channel12.signal=1B +Channel13.signal=1B +Channel14.signal=1B +Channel15.signal=1B + + +;######### GPS ACQUISITION CONFIG ############ + +;#dump: Enable or disable the acquisition internal data file logging [true] or [false] +Acquisition_1C.dump=false +;#filename: Log path and filename +Acquisition_1C.dump_filename=./acq_dump.dat +;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. +Acquisition_1C.item_type=gr_complex +;#if: Signal intermediate frequency in [Hz] +Acquisition_1C.if=0 +;#sampled_ms: Signal block duration for the acquisition signal detection [ms] +Acquisition_1C.sampled_ms=1 +;#implementation: Acquisition algorithm selection for this channel: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] +Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition +Acquisition_1C.use_CFAR_algorithm=false; +;#threshold: Acquisition threshold +Acquisition_1C.threshold=22 +;#doppler_max: Maximum expected Doppler shift [Hz] +Acquisition_1C.doppler_max=5000 +;#doppler_max: Doppler step in the grid search [Hz] +Acquisition_1C.doppler_step=250 + + +;######### GALILEO ACQUISITION CONFIG ############ + +;#dump: Enable or disable the acquisition internal data file logging [true] or [false] +Acquisition_1B.dump=false +;#filename: Log path and filename +Acquisition_1B.dump_filename=../data/acq_dump.dat +;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. +Acquisition_1B.item_type=gr_complex +;#if: Signal intermediate frequency in [Hz] +Acquisition_1B.if=0 +;#sampled_ms: Signal block duration for the acquisition signal detection [ms] +Acquisition_1B.sampled_ms=4 +;#implementation: Acquisition algorithm selection for this channel: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] +Acquisition_1B.implementation=Galileo_E1_PCPS_Ambiguous_Acquisition +Acquisition_1B.acquire_pilot=true +Acquisition_1B.use_CFAR_algorithm=false +;#threshold: Acquisition threshold +Acquisition_1B.threshold=22 +;#doppler_max: Maximum expected Doppler shift [Hz] +Acquisition_1B.doppler_max=5000 +;#doppler_max: Doppler step in the grid search [Hz] +Acquisition_1B.doppler_step=125 +Acquisition_1B.bit_transition_flag=true + +;######### TRACKING GPS CONFIG ############ + +;#implementation: Selected tracking algorithm: [GPS_L1_CA_DLL_PLL_Tracking] or [GPS_L1_CA_DLL_PLL_C_Aid_Tracking] or [GPS_L1_CA_TCP_CONNECTOR_Tracking] or [Galileo_E1_DLL_PLL_VEML_Tracking] +Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking +;#item_type: Type and resolution for each of the signal samples. Use only [gr_complex] in this version. +Tracking_1C.item_type=gr_complex + +;#sampling_frequency: Signal Intermediate Frequency in [Hz] +Tracking_1C.if=0 + +;#dump: Enable or disable the Tracking internal binary data file logging [true] or [false] +Tracking_1C.dump=true + +;#dump_filename: Log path and filename. Notice that the tracking channel will add "x.dat" where x is the channel number. +Tracking_1C.dump_filename=../data/epl_tracking_ch_ + +;#pll_bw_hz: PLL loop filter bandwidth [Hz] +Tracking_1C.pll_bw_hz=40.0; + +;#dll_bw_hz: DLL loop filter bandwidth [Hz] +Tracking_1C.dll_bw_hz=2.0; + +;#order: PLL/DLL loop filter order [2] or [3] +Tracking_1C.order=3; + +;######### TRACKING GALILEO CONFIG ############ + +;#implementation: Selected tracking algorithm: [GPS_L1_CA_DLL_PLL_Tracking] or [GPS_L1_CA_DLL_PLL_C_Aid_Tracking] or [GPS_L1_CA_TCP_CONNECTOR_Tracking] or [Galileo_E1_DLL_PLL_VEML_Tracking] +Tracking_1B.implementation=Galileo_E1_DLL_PLL_VEML_Tracking +;#item_type: Type and resolution for each of the signal samples. +Tracking_1B.item_type=gr_complex + +;#sampling_frequency: Signal Intermediate Frequency in [Hz] +Tracking_1B.if=0 + +;#dump: Enable or disable the Tracking internal binary data file logging [true] or [false] +Tracking_1B.dump=true + +;#dump_filename: Log path and filename. Notice that the tracking channel will add "x.dat" where x is the channel number. +Tracking_1B.dump_filename=../data/veml_tracking_ch_ + +Tracking_1B.track_pilot=true + +;#pll_bw_hz: PLL loop filter bandwidth [Hz] +Tracking_1B.pll_bw_hz=7.5; + +;#dll_bw_hz: DLL loop filter bandwidth [Hz] +Tracking_1B.dll_bw_hz=0.5; + +;#pll_bw_hz: PLL loop filter bandwidth [Hz] +Tracking_1B.pll_bw_narrow_hz=2.5; + +;#dll_bw_hz: DLL loop filter bandwidth [Hz] +Tracking_1B.dll_bw_narrow_hz=0.25; + +Tracking_1B.extend_correlation_symbols=4; + +;#order: PLL/DLL loop filter order [2] or [3] +Tracking_1B.order=3; + +;#early_late_space_chips: correlator early-late space [chips]. Use [0.5] for GPS and [0.15] for Galileo +Tracking_1B.early_late_space_chips=0.15; + +;#very_early_late_space_chips: only for [Galileo_E1_DLL_PLL_VEML_Tracking], correlator very early-late space [chips]. Use [0.6] +Tracking_1B.very_early_late_space_chips=0.6; + +;#early_late_space_chips: correlator early-late space [chips]. Use [0.5] for GPS and [0.15] for Galileo +Tracking_1B.early_late_space_narrow_chips=0.15; + +;#very_early_late_space_chips: only for [Galileo_E1_DLL_PLL_VEML_Tracking], correlator very early-late space [chips]. Use [0.6] +Tracking_1B.very_early_late_space_narrow_chips=0.30; + + + +;######### TELEMETRY DECODER GPS CONFIG ############ +;#implementation: Use [GPS_L1_CA_Telemetry_Decoder] for GPS L1 C/A +TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder +TelemetryDecoder_1C.dump=false + +;######### TELEMETRY DECODER GALILEO CONFIG ############ +;#implementation: Use [Galileo_E1B_Telemetry_Decoder] for Galileo E1B +TelemetryDecoder_1B.implementation=Galileo_E1B_Telemetry_Decoder +TelemetryDecoder_1B.dump=false + +;######### OBSERVABLES CONFIG ############ +;#implementation: +Observables.implementation=Hybrid_Observables + +;#dump: Enable or disable the Observables internal binary data file logging [true] or [false] +Observables.dump=false + +;#dump_filename: Log path and filename. +Observables.dump_filename=./observables.dat + + +;######### PVT CONFIG ############ +;#implementation: Position Velocity and Time (PVT) implementation: +PVT.implementation=RTKLIB_PVT + +PVT.positioning_mode=Single ; 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 + +;#output_rate_ms: Period between two PVT outputs. Notice that the minimum period is equal to the tracking integration time (for GPS CA L1 is 1ms) [ms] +PVT.output_rate_ms=100; + +;#display_rate_ms: Position console print (std::out) interval [ms]. Notice that output_rate_ms<=display_rate_ms. +PVT.display_rate_ms=500; + +;#dump: Enable or disable the PVT internal binary data file logging [true] or [false] +PVT.dump=false + +PVT.flag_rtcm_server=false +PVT.flag_rtcm_tty_port=false +PVT.rtcm_dump_devname=/dev/pts/1 + +;#dump_filename: Log path and filename without extension. Notice that PVT will add ".dat" to the binary dump and ".kml" to GoogleEarth dump. +PVT.dump_filename=./PVT diff --git a/src/algorithms/PVT/adapters/rtklib_pvt.cc b/src/algorithms/PVT/adapters/rtklib_pvt.cc index 4c425b471..c21303ab3 100644 --- a/src/algorithms/PVT/adapters/rtklib_pvt.cc +++ b/src/algorithms/PVT/adapters/rtklib_pvt.cc @@ -154,41 +154,45 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration, */ int gps_1C_count = configuration->property("Channels_1C.count", 0); int gps_2S_count = configuration->property("Channels_2S.count", 0); + int gps_L5_count = configuration->property("Channels_L5.count", 0); int gal_1B_count = configuration->property("Channels_1B.count", 0); - int gal_E5a_count = configuration->property("Channels_5X.count", 0); // GPS L5 or Galileo E5a ? + int gal_E5a_count = configuration->property("Channels_5X.count", 0); int gal_E5b_count = configuration->property("Channels_7X.count", 0); int glo_1G_count = configuration->property("Channels_1G.count", 0); unsigned int type_of_receiver = 0; - if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 1; - if( (gps_1C_count == 0) && (gps_2S_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 2; - if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 4; - if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 5; - if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0)) type_of_receiver = 6; + // *******************WARNING!!!!!!!*********** + // GPS L5 only configurable for single frequency, single system at the moment!!!!!! + if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 1; + if( (gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) 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)) type_of_receiver = 3; + if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 4; + if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 5; + if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0)) type_of_receiver = 6; - if( (gps_1C_count != 0) && (gps_2S_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 7; - //if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 8; - if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 9; - if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 10; - if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0)) type_of_receiver = 11; - if( (gps_1C_count == 0) && (gps_2S_count != 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 12; + if( (gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 7; + //if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 8; + if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 9; + if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) 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)) 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)) type_of_receiver = 12; //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 13; - if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 14; - if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0)) type_of_receiver = 15; - //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 16; - if( (gps_1C_count == 0) && (gps_2S_count != 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 17; - if( (gps_1C_count == 0) && (gps_2S_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0)) type_of_receiver = 18; - //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 19; - //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 20; - if( (gps_1C_count != 0) && (gps_2S_count != 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 21; - //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count = 0)) type_of_receiver = 22; - if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 23; - //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2R_count != 0)) type_of_receiver = 24; - //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_1G_count != 0)) type_of_receiver = 25; - if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 26; - if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 27; - if( (gps_1C_count == 0) && (gps_2S_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 28; + if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) 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)) type_of_receiver = 15; + //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 16; + if( (gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) 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)) type_of_receiver = 18; + //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 19; + //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 20; + if( (gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 21; + //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count = 0)) type_of_receiver = 22; + if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 23; + //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2R_count != 0)) type_of_receiver = 24; + //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_1G_count != 0)) type_of_receiver = 25; + if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) 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)) 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)) type_of_receiver = 28; //RTKLIB PVT solver options // Settings 1 int positioning_mode = -1; @@ -214,8 +218,8 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration, if ((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) num_bands = 1; if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && (gps_2S_count > 0) ) num_bands = 2; - if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && ((gal_E5a_count > 0) || (gal_E5b_count > 0)) ) num_bands = 2; - if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && (gps_2S_count > 0) && ((gal_E5a_count > 0) || (gal_E5b_count > 0))) num_bands = 3; + 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) && ((gal_E5a_count > 0) || (gal_E5b_count > 0) || (gps_L5_count > 0))) num_bands = 3; int number_of_frequencies = configuration->property(role + ".num_bands", num_bands); /* (1:L1, 2:L1+L2, 3:L1+L2+L5) */ if( (number_of_frequencies < 1) || (number_of_frequencies > 3) ) @@ -296,7 +300,7 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration, int earth_tide = configuration->property(role + ".earth_tide", 0); int nsys = 0; - if ((gps_1C_count > 0) || (gps_2S_count > 0)) nsys += SYS_GPS; + 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)) nsys += SYS_GLO; int navigation_system = configuration->property(role + ".navigation_system", nsys); /* (SYS_XXX) see src/algorithms/libs/rtklib/rtklib.h */ diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc index 9b6169e50..85290da73 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc @@ -123,7 +123,7 @@ void rtklib_pvt_cc::msg_handler_telemetry(pmt::pmt_t msg) gps_cnav_ephemeris = boost::any_cast>(pmt::any_ref(msg)); // update/insert new ephemeris record to the global ephemeris map d_ls_pvt->gps_cnav_ephemeris_map[gps_cnav_ephemeris->i_satellite_PRN] = *gps_cnav_ephemeris; - LOG(INFO) << "New GPS CNAV ephemeris record has arrived "; + DLOG(INFO) << "New GPS CNAV ephemeris record has arrived "; } else if(pmt::any_ref(msg).type() == typeid(std::shared_ptr) ) { @@ -386,7 +386,7 @@ rtklib_pvt_cc::~rtklib_pvt_cc() msgctl(sysv_msqid, IPC_RMID, NULL); //save GPS L2CM ephemeris to XML file - std::string file_name="eph_GPS_L2CM.xml"; + std::string file_name = "eph_GPS_L2CM_L5.xml"; if (d_ls_pvt->gps_cnav_ephemeris_map.size() > 0) { @@ -396,7 +396,7 @@ rtklib_pvt_cc::~rtklib_pvt_cc() boost::archive::xml_oarchive xml(ofs); xml << boost::serialization::make_nvp("GNSS-SDR_ephemeris_map", d_ls_pvt->gps_cnav_ephemeris_map); ofs.close(); - LOG(INFO) << "Saved GPS L2CM Ephemeris map data"; + LOG(INFO) << "Saved GPS L2CM or L5 Ephemeris map data"; } catch (std::exception& e) { @@ -405,7 +405,7 @@ rtklib_pvt_cc::~rtklib_pvt_cc() } else { - LOG(WARNING) << "Failed to save GPS L2CM Ephemeris, map is empty"; + LOG(WARNING) << "Failed to save GPS L2CM or L5 Ephemeris, map is empty"; } //save GPS L1 CA ephemeris to XML file @@ -522,9 +522,6 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite bool flag_write_RTCM_1019_output = false; bool flag_write_RTCM_1020_output = false; bool flag_write_RTCM_1045_output = false; - bool flag_write_RTCM_1077_output = false; - bool flag_write_RTCM_1087_output = false; - bool flag_write_RTCM_1097_output = false; bool flag_write_RTCM_MSM_output = false; bool flag_write_RINEX_obs_output = false; bool flag_write_RINEX_nav_output = false; @@ -549,7 +546,8 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite || ((tmp_eph_iter_gal->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("1B") == 0)) || ((tmp_eph_iter_gal->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("5X") == 0)) || ((tmp_eph_iter_glo_gnav->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("1G") == 0)) - || ((tmp_eph_iter_glo_gnav->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("2G") == 0))) + || ((tmp_eph_iter_glo_gnav->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("2G") == 0)) + || ((tmp_eph_iter_cnav->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("L5") == 0))) { // store valid observables in a map. gnss_observables_map.insert(std::pair(i, in[i][epoch])); @@ -629,17 +627,14 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite if ((std::fabs(current_RX_time - last_RTCM_1077_output_time) * 1000.0 >= static_cast(d_rtcm_MT1077_rate_ms)) && (d_rtcm_MT1077_rate_ms != 0) ) { - flag_write_RTCM_1077_output = true; last_RTCM_1077_output_time = current_RX_time; } if ((std::fabs(current_RX_time - last_RTCM_1087_output_time) * 1000.0 >= static_cast(d_rtcm_MT1087_rate_ms)) && (d_rtcm_MT1087_rate_ms != 0) ) { - flag_write_RTCM_1087_output = true; last_RTCM_1087_output_time = current_RX_time; } if ((std::fabs(current_RX_time - last_RTCM_1097_output_time) * 1000.0 >= static_cast(d_rtcm_MT1097_rate_ms)) && (d_rtcm_MT1097_rate_ms != 0) ) { - flag_write_RTCM_1097_output = true; last_RTCM_1097_output_time = current_RX_time; } @@ -669,8 +664,8 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite if(first_fix == true) { std::cout << "First position fix at " << boost::posix_time::to_simple_string(d_ls_pvt->get_position_UTC_time()) - << " UTC is Lat = " << d_ls_pvt->get_latitude() << " [deg], Long = " << d_ls_pvt->get_longitude() - << " [deg], Height= " << d_ls_pvt->get_height() << " [m]" << std::endl; + << " UTC is Lat = " << d_ls_pvt->get_latitude() << " [deg], Long = " << d_ls_pvt->get_longitude() + << " [deg], Height= " << d_ls_pvt->get_height() << " [m]" << std::endl; ttff_msgbuf ttff; ttff.mtype = 1; end = std::chrono::system_clock::now(); @@ -721,7 +716,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite std::map::const_iterator galileo_ephemeris_iter; std::map::const_iterator gps_ephemeris_iter; std::map::const_iterator gps_cnav_ephemeris_iter; - std::map::const_iterator glonass_gnav_ephemeris_iter; + std::map::const_iterator glonass_gnav_ephemeris_iter; std::map::const_iterator gnss_observables_iter; if (!b_rinex_header_written) // & we have utc data in nav message! @@ -729,7 +724,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.cbegin(); gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.cbegin(); gps_cnav_ephemeris_iter = d_ls_pvt->gps_cnav_ephemeris_map.cbegin(); - glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); + glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); if(type_of_rx == 1) // GPS L1 C/A only { @@ -750,6 +745,15 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite b_rinex_header_written = true; // do not write header anymore } } + if(type_of_rx == 3) // GPS L5 only + { + if (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.cend()) + { + rp->rinex_obs_header(rp->obsFile, gps_cnav_ephemeris_iter->second, d_rx_time); + rp->rinex_nav_header(rp->navFile, d_ls_pvt->gps_cnav_iono, d_ls_pvt->gps_cnav_utc_model); + b_rinex_header_written = true; // do not write header anymore + } + } if(type_of_rx == 4) // Galileo E1B only { if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend()) @@ -877,12 +881,12 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite std::string glo_signal("1G"); rp->rinex_obs_header(rp->obsFile, gps_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, glo_signal); if(d_rinex_version == 3) - rp->rinex_nav_header(rp->navMixFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); + rp->rinex_nav_header(rp->navMixFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); if(d_rinex_version == 2) - { - rp->rinex_nav_header(rp->navFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model); - rp->rinex_nav_header(rp->navGloFile, d_ls_pvt->glonass_gnav_utc_model, glonass_gnav_ephemeris_iter->second); - } + { + rp->rinex_nav_header(rp->navFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model); + rp->rinex_nav_header(rp->navGloFile, d_ls_pvt->glonass_gnav_utc_model, glonass_gnav_ephemeris_iter->second); + } b_rinex_header_written = true; // do not write header anymore } } @@ -898,15 +902,15 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite } } if(type_of_rx == 28) // GPS L2C + GLONASS L1 C/A - { - if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) && (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.cend()) ) - { - std::string glo_signal("1G"); - rp->rinex_obs_header(rp->obsFile, gps_cnav_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, glo_signal); - rp->rinex_nav_header(rp->navMixFile, d_ls_pvt->gps_cnav_iono, d_ls_pvt->gps_cnav_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); - b_rinex_header_written = true; // do not write header anymore - } - } + { + if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) && (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.cend()) ) + { + std::string glo_signal("1G"); + rp->rinex_obs_header(rp->obsFile, gps_cnav_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, glo_signal); + rp->rinex_nav_header(rp->navMixFile, d_ls_pvt->gps_cnav_iono, d_ls_pvt->gps_cnav_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); + b_rinex_header_written = true; // do not write header anymore + } + } } if(b_rinex_header_written) // The header is already written, we can now log the navigation message data { @@ -920,6 +924,10 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite { rp->log_rinex_nav(rp->navFile, d_ls_pvt->gps_cnav_ephemeris_map); } + if(type_of_rx == 3) // GPS L5 only + { + rp->log_rinex_nav(rp->navFile, d_ls_pvt->gps_cnav_ephemeris_map); + } if( (type_of_rx == 4) || (type_of_rx == 5) || (type_of_rx == 6) ) // Galileo { rp->log_rinex_nav(rp->navGalFile, d_ls_pvt->galileo_ephemeris_map); @@ -942,13 +950,13 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite } if(type_of_rx == 26) // GPS L1 C/A + GLONASS L1 C/A { - if(d_rinex_version == 3) - rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map); - if(d_rinex_version == 2) - { - rp->log_rinex_nav(rp->navFile, d_ls_pvt->gps_ephemeris_map); - rp->log_rinex_nav(rp->navGloFile, d_ls_pvt->glonass_gnav_ephemeris_map); - } + if(d_rinex_version == 3) + rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map); + if(d_rinex_version == 2) + { + rp->log_rinex_nav(rp->navFile, d_ls_pvt->gps_ephemeris_map); + rp->log_rinex_nav(rp->navGloFile, d_ls_pvt->glonass_gnav_ephemeris_map); + } } if(type_of_rx == 27) // Galileo E1B + GLONASS L1 C/A @@ -956,9 +964,9 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->galileo_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map); } if(type_of_rx == 28) // GPS L2C + GLONASS L1 C/A - { - rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_cnav_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map); - } + { + rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_cnav_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map); + } } galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.cbegin(); gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.cbegin(); @@ -994,6 +1002,19 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite b_rinex_header_updated = true; } } + if(type_of_rx == 3) // GPS L5 + { + if (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.end()) + { + rp->log_rinex_obs(rp->obsFile, gps_cnav_ephemeris_iter->second, d_rx_time, gnss_observables_map); + } + if (!b_rinex_header_updated && (d_ls_pvt->gps_cnav_utc_model.d_A0 != 0)) + { + rp->update_obs_header(rp->obsFile, d_ls_pvt->gps_cnav_utc_model); + rp->update_nav_header(rp->navFile, d_ls_pvt->gps_cnav_utc_model, d_ls_pvt->gps_cnav_iono); + b_rinex_header_updated = true; + } + } if(type_of_rx == 4) // Galileo E1B only { if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end()) @@ -1128,7 +1149,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite { if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) && (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.end()) ) { - rp->log_rinex_obs(rp->obsFile, gps_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map); + rp->log_rinex_obs(rp->obsFile, gps_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map); } if (!b_rinex_header_updated && (d_ls_pvt->gps_utc_model.d_A0 != 0)) { @@ -1155,7 +1176,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite { if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) && (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.end()) ) { - rp->log_rinex_obs(rp->obsFile, gps_cnav_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map); + rp->log_rinex_obs(rp->obsFile, gps_cnav_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map); } if (!b_rinex_header_updated && (d_ls_pvt->gps_cnav_utc_model.d_A0 != 0)) { @@ -1412,7 +1433,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.find(gnss_observables_iter->second.PRN); if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend()) { - gal_channel = i; + gal_channel = i; } } } @@ -1556,30 +1577,30 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite b_rtcm_writing_started = true; } if((type_of_rx == 23) || (type_of_rx == 24) || (type_of_rx == 25)) // GLONASS - { - for(std::map::const_iterator glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend(); glonass_gnav_ephemeris_iter++ ) - { - d_rtcm_printer->Print_Rtcm_MT1020(glonass_gnav_ephemeris_iter->second, d_ls_pvt->glonass_gnav_utc_model); - } + { + for(std::map::const_iterator glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend(); glonass_gnav_ephemeris_iter++ ) + { + d_rtcm_printer->Print_Rtcm_MT1020(glonass_gnav_ephemeris_iter->second, d_ls_pvt->glonass_gnav_utc_model); + } - std::map::const_iterator glo_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); + std::map::const_iterator glo_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); - if (glo_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) - { - d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glo_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0); - } - b_rtcm_writing_started = true; - } + if (glo_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) + { + d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glo_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0); + } + b_rtcm_writing_started = true; + } if(type_of_rx == 26) // GPS L1 C/A + GLONASS L1 C/A { - if(d_rtcm_MT1019_rate_ms != 0) // allows deactivating messages by setting rate = 0 + if(d_rtcm_MT1019_rate_ms != 0) // allows deactivating messages by setting rate = 0 { for(gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.cbegin(); gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend(); gps_ephemeris_iter++ ) { d_rtcm_printer->Print_Rtcm_MT1019(gps_ephemeris_iter->second); } } - if(d_rtcm_MT1020_rate_ms != 0) // allows deactivating messages by setting rate = 0 + if(d_rtcm_MT1020_rate_ms != 0) // allows deactivating messages by setting rate = 0 { for(std::map::const_iterator glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend(); glonass_gnav_ephemeris_iter++ ) { @@ -1587,108 +1608,104 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite } } - //gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.end(); - //galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.end(); - unsigned int i = 0; - for (gnss_observables_iter = gnss_observables_map.cbegin(); gnss_observables_iter != gnss_observables_map.cend(); gnss_observables_iter++) - { - std::string system(&gnss_observables_iter->second.System, 1); - if(gps_channel == 0) - { - if(system.compare("G") == 0) - { - // This is a channel with valid GPS signal - gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.find(gnss_observables_iter->second.PRN); - if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend()) - { - gps_channel = i; - } - } - } - if(glo_channel == 0) - { - if(system.compare("R") == 0) - { - glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN); - if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) - { - glo_channel = i; - } - } - } - i++; - } - if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) - { - d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0); - } + //gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.end(); + //galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.end(); + unsigned int i = 0; + for (gnss_observables_iter = gnss_observables_map.cbegin(); gnss_observables_iter != gnss_observables_map.cend(); gnss_observables_iter++) + { + std::string system(&gnss_observables_iter->second.System, 1); + if(gps_channel == 0) + { + if(system.compare("G") == 0) + { + // This is a channel with valid GPS signal + gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.find(gnss_observables_iter->second.PRN); + if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend()) + { + gps_channel = i; + } + } + } + if(glo_channel == 0) + { + if(system.compare("R") == 0) + { + glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN); + if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) + { + glo_channel = i; + } + } + } + i++; + } + if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) + { + d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0); + } - if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend()) - { - d_rtcm_printer->Print_Rtcm_MSM(7, gps_ephemeris_iter->second, {}, {}, {}, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0); - } - - b_rtcm_writing_started = true; + if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend()) + { + d_rtcm_printer->Print_Rtcm_MSM(7, gps_ephemeris_iter->second, {}, {}, {}, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0); + } + b_rtcm_writing_started = true; } if(type_of_rx == 27) // GLONASS L1 C/A + Galileo E1B - { - if(d_rtcm_MT1020_rate_ms != 0) // allows deactivating messages by setting rate = 0 - { - for(std::map::const_iterator glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend(); glonass_gnav_ephemeris_iter++ ) - { - d_rtcm_printer->Print_Rtcm_MT1020(glonass_gnav_ephemeris_iter->second, d_ls_pvt->glonass_gnav_utc_model); - } - } - if(d_rtcm_MT1045_rate_ms != 0) // allows deactivating messages by setting rate = 0 - { - for(galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.cbegin(); galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend(); galileo_ephemeris_iter++ ) - { - d_rtcm_printer->Print_Rtcm_MT1045(galileo_ephemeris_iter->second); - } - } - - unsigned int i = 0; - for (gnss_observables_iter = gnss_observables_map.cbegin(); gnss_observables_iter != gnss_observables_map.cend(); gnss_observables_iter++) - { - std::string system(&gnss_observables_iter->second.System, 1); - if(gal_channel == 0) - { - if(system.compare("E") == 0) - { - // This is a channel with valid GPS signal - galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.find(gnss_observables_iter->second.PRN); - if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend()) - { - gal_channel = i; - } - } - } - if(glo_channel == 0) - { - if(system.compare("R") == 0) - { - glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN); - if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) - { - glo_channel = i; - } - } - } - i++; - } - if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end()) - { - d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, galileo_ephemeris_iter->second, {}, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0); - } - if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) - { - d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0); - } - - - } + { + if(d_rtcm_MT1020_rate_ms != 0) // allows deactivating messages by setting rate = 0 + { + for(std::map::const_iterator glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend(); glonass_gnav_ephemeris_iter++ ) + { + d_rtcm_printer->Print_Rtcm_MT1020(glonass_gnav_ephemeris_iter->second, d_ls_pvt->glonass_gnav_utc_model); + } + } + if(d_rtcm_MT1045_rate_ms != 0) // allows deactivating messages by setting rate = 0 + { + for(galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.cbegin(); galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend(); galileo_ephemeris_iter++ ) + { + d_rtcm_printer->Print_Rtcm_MT1045(galileo_ephemeris_iter->second); + } + } + unsigned int i = 0; + for (gnss_observables_iter = gnss_observables_map.cbegin(); gnss_observables_iter != gnss_observables_map.cend(); gnss_observables_iter++) + { + std::string system(&gnss_observables_iter->second.System, 1); + if(gal_channel == 0) + { + if(system.compare("E") == 0) + { + // This is a channel with valid GPS signal + galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.find(gnss_observables_iter->second.PRN); + if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend()) + { + gal_channel = i; + } + } + } + if(glo_channel == 0) + { + if(system.compare("R") == 0) + { + glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN); + if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) + { + glo_channel = i; + } + } + } + i++; + } + if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end()) + { + d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, galileo_ephemeris_iter->second, {}, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0); + } + if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) + { + d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0); + } + } } } } diff --git a/src/algorithms/PVT/libs/rinex_printer.cc b/src/algorithms/PVT/libs/rinex_printer.cc index f07d3fd00..0eabf724f 100644 --- a/src/algorithms/PVT/libs/rinex_printer.cc +++ b/src/algorithms/PVT/libs/rinex_printer.cc @@ -621,7 +621,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono 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(); @@ -642,6 +641,7 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono out << line << std::endl; } + void Rinex_Printer::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) { if(glonass_gnav_almanac.i_satellite_freq_channel){} //Avoid compiler warning @@ -743,7 +743,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono& gps 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(); @@ -764,6 +763,7 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono& gps out << line << std::endl; } + void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Galileo_Almanac& galileo_almanac, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) { if(glonass_gnav_almanac.i_satellite_freq_channel){} //Avoid compiler warning @@ -828,7 +828,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& gali Rinex_Printer::lengthCheck(line); out << line << std::endl; - // -------- Line system time correction line.clear(); line += std::string("GAUT"); @@ -874,6 +873,7 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& gali out << line << std::endl; } + void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& iono, const Galileo_Utc_Model& utc_model, const Galileo_Almanac& galileo_almanac) { std::string line; @@ -921,7 +921,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& iono Rinex_Printer::lengthCheck(line); out << line << std::endl; - // -------- Line ionospheric info 1 line.clear(); line += std::string("GAL "); @@ -936,7 +935,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& iono Rinex_Printer::lengthCheck(line); out << line << std::endl; - // -------- Line system time correction line.clear(); line += std::string("GAUT"); @@ -961,7 +959,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& iono 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(); @@ -982,6 +979,7 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& iono out << line << std::endl; } + void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono & iono, const Gps_CNAV_Utc_Model & utc_model) { std::string line; @@ -1097,6 +1095,7 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono & io out << line << std::endl; } + void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& iono, const Gps_Utc_Model& utc_model) { std::string line; @@ -1120,7 +1119,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& iono, co line += std::string("G: GPS"); line += std::string(14, ' '); // ... - } line += std::string("RINEX VERSION / TYPE"); @@ -1266,7 +1264,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& iono, co Rinex_Printer::lengthCheck(line); out << line << std::endl; - // -------- End of Header line.clear(); line += std::string(60, ' '); @@ -1275,6 +1272,7 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& iono, co out << line << std::endl; } + void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono, const Gps_Utc_Model& gps_utc_model, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Galileo_Almanac& galileo_almanac) { std::string line; @@ -1322,7 +1320,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono Rinex_Printer::lengthCheck(line); out << line << std::endl; - // -------- Line ionospheric info 1 line.clear(); line += std::string("GAL "); @@ -1386,7 +1383,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono 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(); @@ -1589,6 +1585,7 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Glonass_Gnav_Utc_ std::cout << "The RINEX Navigation file header has been updated with UTC info." << std::endl; } + void Rinex_Printer::update_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& utc_model, const Galileo_Almanac& galileo_almanac) { std::vector data; @@ -1684,6 +1681,7 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Galileo_Iono& gal std::cout << "The RINEX Navigation file header has been updated with UTC and IONO info." << std::endl; } + void Rinex_Printer::update_nav_header(std::fstream& out, const Gps_Utc_Model& utc_model, const Gps_Iono& iono) { std::vector data; @@ -2039,7 +2037,6 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Gps_Iono& gps_ion { data.push_back(line_str); } - } else { @@ -2253,7 +2250,6 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Gps_CNAV_Iono& gp { data.push_back(line_str); } - } else { @@ -2274,11 +2270,12 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Gps_CNAV_Iono& gp std::cout << "The RINEX Navigation file header has been updated with UTC and IONO info." << std::endl; } + void Rinex_Printer::update_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Galileo_Almanac& galileo_almanac, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) { if(glonass_gnav_almanac.i_satellite_freq_channel){} //Avoid compiler warning //Avoid compiler warning, there is not time system correction between Galileo and GLONASS - if(galileo_almanac.A_0G_10){} + if(galileo_almanac.A_0G_10){} std::vector data; std::string line_aux; @@ -2373,7 +2370,6 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Galileo_Iono& gal } - void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& eph_map) { std::string line; @@ -2382,7 +2378,7 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::mapsecond, gps_ephemeris_iter->second.d_Toc); std::string timestring = boost::posix_time::to_iso_string(p_utc_time); @@ -2490,7 +2486,6 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::mapsecond.glot_to_utc(glonass_gnav_ephemeris_iter->second.d_t_b, 0.0); std::string timestring = boost::posix_time::to_iso_string(p_utc_time); @@ -3164,7 +3137,6 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& gps_eph_map, const std::map& galileo_eph_map) { version = 3; @@ -3262,12 +3232,14 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& gps_eph_map, const std::map& glonass_gnav_eph_map) { Rinex_Printer::log_rinex_nav(out, gps_eph_map); Rinex_Printer::log_rinex_nav(out, glonass_gnav_eph_map); } + void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& galileo_eph_map, const std::map& glonass_gnav_eph_map) { version = 3; @@ -3277,7 +3249,6 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& observables, const std::string glonass_band) { // RINEX observations timestamps are GPS timestamps. @@ -6128,7 +6098,6 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeri Rinex_Printer::lengthCheck(line); out << line << std::endl; - for(observables_iter = observables.begin(); observables_iter != observables.end(); observables_iter++) @@ -7160,7 +7129,6 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Gps_Ephemeris& eph, c Rinex_Printer::lengthCheck(line); out << line << std::endl; - for(observables_iter = observables.cbegin(); observables_iter != observables.cend(); observables_iter++) diff --git a/src/algorithms/PVT/libs/rinex_printer.h b/src/algorithms/PVT/libs/rinex_printer.h index ee90ef3a4..8f4580208 100644 --- a/src/algorithms/PVT/libs/rinex_printer.h +++ b/src/algorithms/PVT/libs/rinex_printer.h @@ -204,20 +204,20 @@ public: boost::posix_time::ptime compute_Galileo_time(const Galileo_Ephemeris & eph, const double obs_time); /*! - * \brief Computes the UTC Time and returns a boost::posix_time::ptime object - * \details Function used as a method to convert the observation time into UTC time which is used - * as the default time for RINEX files - * \param eph GLONASS GNAV Ephemeris object - * \param obs_time Observation time in GPS seconds of week - */ - boost::posix_time::ptime compute_UTC_time(const Glonass_Gnav_Ephemeris & eph, const double obs_time); + * \brief Computes the UTC Time and returns a boost::posix_time::ptime object + * \details Function used as a method to convert the observation time into UTC time which is used + * as the default time for RINEX files + * \param eph GLONASS GNAV Ephemeris object + * \param obs_time Observation time in GPS seconds of week + */ + boost::posix_time::ptime compute_UTC_time(const Glonass_Gnav_Ephemeris & eph, const double obs_time); - /*! - * \brief Computes number of leap seconds of GPS relative to UTC - * \param eph GLONASS GNAV Ephemeris object - * \param gps_obs_time Observation time in GPS seconds of week - */ - double get_leap_second(const Glonass_Gnav_Ephemeris& eph, const double gps_obs_time); + /*! + * \brief Computes number of leap seconds of GPS relative to UTC + * \param eph GLONASS GNAV Ephemeris object + * \param gps_obs_time Observation time in GPS seconds of week + */ + double get_leap_second(const Glonass_Gnav_Ephemeris& eph, const double gps_obs_time); /*! * \brief Writes data from the GPS L1 C/A navigation message into the RINEX file diff --git a/src/algorithms/PVT/libs/rtklib_solver.cc b/src/algorithms/PVT/libs/rtklib_solver.cc index 5c469de97..897150a87 100644 --- a/src/algorithms/PVT/libs/rtklib_solver.cc +++ b/src/algorithms/PVT/libs/rtklib_solver.cc @@ -150,7 +150,7 @@ bool rtklib_solver::get_PVT(const std::map & gnss_observables_ eph_data[valid_obs] = eph_to_rtklib(galileo_ephemeris_iter->second); //convert observation from GNSS-SDR class to RTKLIB structure obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}}; - obs_data[valid_obs] = insert_obs_to_rtklib(newobs, + obs_data[valid_obs+glo_valid_obs] = insert_obs_to_rtklib(newobs, gnss_observables_iter->second, galileo_ephemeris_iter->second.WN_5, 0); @@ -262,7 +262,10 @@ bool rtklib_solver::get_PVT(const std::map & gnss_observables_ //convert ephemeris from GNSS-SDR class to RTKLIB structure eph_data[valid_obs] = eph_to_rtklib(gps_cnav_ephemeris_iter->second); //convert observation from GNSS-SDR class to RTKLIB structure - obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}}; + unsigned char default_code_ = static_cast(CODE_NONE); + obsd_t newobs = {{0,0}, '0', '0', {}, {}, + {default_code_, default_code_, default_code_}, + {}, {0.0, 0.0, 0.0}, {}}; obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs, gnss_observables_iter->second, gps_cnav_ephemeris_iter->second.i_GPS_week, @@ -275,6 +278,53 @@ bool rtklib_solver::get_PVT(const std::map & gnss_observables_ DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN; } } + //GPS L5 + if(sig_.compare("L5") == 0) + { + gps_cnav_ephemeris_iter = gps_cnav_ephemeris_map.find(gnss_observables_iter->second.PRN); + if (gps_cnav_ephemeris_iter != gps_cnav_ephemeris_map.cend()) + { + // 1. Find the same satellite in GPS L1 band + gps_ephemeris_iter = gps_ephemeris_map.find(gnss_observables_iter->second.PRN); + if (gps_ephemeris_iter != gps_ephemeris_map.cend()) + { + // 2. If found, replace the existing GPS L1 ephemeris with the GPS L5 ephemeris + // (more precise!), and attach the L5 observation to the L1 observation in RTKLIB structure + for (int i = 0; i < valid_obs; i++) + { + if (eph_data[i].sat == static_cast(gnss_observables_iter->second.PRN)) + { + eph_data[i] = eph_to_rtklib(gps_cnav_ephemeris_iter->second); + obs_data[i+glo_valid_obs] = insert_obs_to_rtklib(obs_data[i], + gnss_observables_iter->second, + gps_cnav_ephemeris_iter->second.i_GPS_week, + 2);//Band 3 (L5) + break; + } + } + } + else + { + // 3. If not found, insert the GPS L5 ephemeris and the observation + //convert ephemeris from GNSS-SDR class to RTKLIB structure + eph_data[valid_obs] = eph_to_rtklib(gps_cnav_ephemeris_iter->second); + //convert observation from GNSS-SDR class to RTKLIB structure + unsigned char default_code_ = static_cast(CODE_NONE); + obsd_t newobs = {{0,0}, '0', '0', {}, {}, + {default_code_, default_code_, default_code_}, + {}, {0.0, 0.0, 0.0}, {}}; + obs_data[valid_obs+glo_valid_obs] = insert_obs_to_rtklib(newobs, + gnss_observables_iter->second, + gps_cnav_ephemeris_iter->second.i_GPS_week, + 2);//Band 3 (L5) + valid_obs++; + } + } + else // the ephemeris are not available for this SV + { + DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN; + } + } break; } case 'R': //TODO This should be using rtk lib nomenclature @@ -374,9 +424,10 @@ bool rtklib_solver::get_PVT(const std::map & gnss_observables_ } result = rtkpos(&rtk_, obs_data, valid_obs + glo_valid_obs, &nav_data); + if(result == 0) { - LOG(INFO) << "RTKLIB rtkpos error message: " << rtk_.errbuf; + DLOG(INFO) << "RTKLIB rtkpos error message: " << rtk_.errbuf; this->set_time_offset_s(0.0); //reset rx time estimation this->set_num_valid_observations(0); } diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc index f9712824c..5ac10bcd8 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc @@ -70,6 +70,7 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions + acquire_pilot_ = configuration_->property(role + ".acquire_pilot", false); //will be true in future versions max_dwells_ = configuration_->property(role + ".max_dwells", 1); @@ -95,7 +96,6 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; - } else { @@ -252,8 +252,19 @@ void GalileoE1PcpsAmbiguousAcquisition::set_local_code() std::complex * code = new std::complex[code_length_]; - galileo_e1_code_gen_complex_sampled(code, gnss_synchro_->Signal, + if (acquire_pilot_ == true) + { + //set local signal generator to Galileo E1 pilot component (1C) + char pilot_signal[3] = "1C"; + galileo_e1_code_gen_complex_sampled(code, pilot_signal, cboc, gnss_synchro_->PRN, fs_in_, 0, false); + } + else + { + galileo_e1_code_gen_complex_sampled(code, gnss_synchro_->Signal, + cboc, gnss_synchro_->PRN, fs_in_, 0, false); + } + for (unsigned int i = 0; i < sampled_ms_ / 4; i++) { diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h index da8d2e742..71727cecd 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h @@ -146,6 +146,7 @@ private: unsigned int code_length_; bool bit_transition_flag_; bool use_CFAR_algorithm_flag_; + bool acquire_pilot_; unsigned int channel_; float threshold_; unsigned int doppler_max_; diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc index 5afc7e073..9bbc9475f 100644 --- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc @@ -1,3 +1,36 @@ +/*! + * \file glonass_l1_ca_pcps_acquisition.cc + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Glonass L1 C/A signals + * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com + * \author Luis Esteve, 2017. luis(at)epsilon-formacion.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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 . + * + * ------------------------------------------------------------------------- + */ + #include "glonass_l1_ca_pcps_acquisition.h" #include #include @@ -7,10 +40,11 @@ using google::LogMessage; + GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : - role_(role), in_streams_(in_streams), out_streams_(out_streams) + role_(role), in_streams_(in_streams), out_streams_(out_streams) { configuration_ = configuration; std::string default_item_type = "gr_complex"; @@ -55,12 +89,14 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition( bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; - }else{ - item_size_ = sizeof(gr_complex); - acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, max_dwells_, - doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); - DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() << ")"; + } + else + { + item_size_ = sizeof(gr_complex); + acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, max_dwells_, + doppler_max_, if_, fs_in_, code_length_, code_length_, + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); + DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() << ")"; } stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); @@ -260,7 +296,7 @@ float GlonassL1CaPcpsAcquisition::calculate_threshold(float pfa) { frequency_bins++; } - */ + */ frequency_bins = (2*doppler_max_ + doppler_step_)/doppler_step_; diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h index 65f6b9874..f338a1504 100644 --- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h @@ -1,3 +1,35 @@ +/*! + * \file glonass_l1_ca_pcps_acquisition.h + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Glonass L1 C/A signals + * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com + * \author Luis Esteve, 2017. luis(at)epsilon-formacion.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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 . + * + * ------------------------------------------------------------------------- + */ #ifndef GNSS_SDR_GLONASS_L1_CA_PCPS_ACQUISITION_H_ #define GNSS_SDR_GLONASS_L1_CA_PCPS_ACQUISITION_H_ diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc index cf8ec8936..726fd0d48 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc @@ -130,13 +130,9 @@ pcps_acquisition_cc::pcps_acquisition_cc( // For dumping samples into a file d_dump = dump; d_dump_filename = dump_filename; - d_gnss_synchro = 0; d_grid_doppler_wipeoffs = 0; - - d_done = false; d_blocking = blocking; - d_new_data_available = false; d_worker_active = false; d_data_buffer = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); } @@ -163,19 +159,6 @@ pcps_acquisition_cc::~pcps_acquisition_cc() { d_dump_file.close(); } - - // Let the worker thread know that we are done and then wait to join - if( d_worker_thread.joinable() ) - { - { - std::lock_guard lk( d_mutex ); - d_done = true; - d_cond.notify_one(); - } - - d_worker_thread.join(); - } - volk_gnsssdr_free( d_data_buffer ); } @@ -259,9 +242,6 @@ void pcps_acquisition_cc::init() int doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_freq + doppler); } - - d_new_data_available = false; - d_done = false; d_worker_active = false; } @@ -293,6 +273,7 @@ void pcps_acquisition_cc::set_state(int state) d_mag = 0.0; d_input_power = 0.0; d_test_statistics = 0.0; + d_active = true; } else if (d_state == 0) {} @@ -339,7 +320,7 @@ void pcps_acquisition_cc::send_negative_acquisition() } -int pcps_acquisition_cc::general_work(int noutput_items, +int pcps_acquisition_cc::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items __attribute__((unused))) { @@ -354,193 +335,157 @@ int pcps_acquisition_cc::general_work(int noutput_items, * 6. Declare positive or negative acquisition using a message port */ - switch (d_state) + gr::thread::scoped_lock lk(d_setlock); + if(!d_active || d_worker_active) + { + d_sample_counter += d_fft_size * ninput_items[0]; + consume_each(ninput_items[0]); + return 0; + } + + switch(d_state) { case 0: { - if (d_active) - { - //restart acquisition variables - d_gnss_synchro->Acq_delay_samples = 0.0; - d_gnss_synchro->Acq_doppler_hz = 0.0; - d_gnss_synchro->Acq_samplestamp_samples = 0; - d_well_count = 0; - d_mag = 0.0; - d_input_power = 0.0; - d_test_statistics = 0.0; - d_state = 1; - } - + //restart acquisition variables + d_gnss_synchro->Acq_delay_samples = 0.0; + d_gnss_synchro->Acq_doppler_hz = 0.0; + d_gnss_synchro->Acq_samplestamp_samples = 0; + d_well_count = 0; + d_mag = 0.0; + d_input_power = 0.0; + d_test_statistics = 0.0; + d_state = 1; d_sample_counter += d_fft_size * ninput_items[0]; // sample counter consume_each(ninput_items[0]); - break; } case 1: { - std::unique_lock lk( d_mutex ); - - int num_items_consumed = 1; - - if( d_worker_active ) + // Copy the data to the core and let it know that new data is available + memcpy(d_data_buffer, input_items[0], d_fft_size * sizeof(gr_complex)); + if(d_blocking) { - if( d_blocking ) - { - // Should never get here: - std::string msg = "pcps_acquisition_cc: Entered general work with worker active in blocking mode, should never happen"; - LOG(WARNING) << msg; - std::cout << msg << std::endl; - d_cond.wait( lk, [&]{ return !this->d_worker_active; } ); - } - else - { - num_items_consumed = ninput_items[0]; - d_sample_counter += d_fft_size * num_items_consumed; - } + lk.unlock(); + acquisition_core(d_sample_counter); } else { - // Copy the data to the core and let it know that new data is available - memcpy( d_data_buffer, input_items[0], d_fft_size * sizeof( gr_complex ) ); - d_new_data_available = true; - d_cond.notify_one(); - - if( d_blocking ) - { - d_cond.wait( lk, [&]{ return !this->d_new_data_available; } ); - - } + gr::thread::thread d_worker(&pcps_acquisition_cc::acquisition_core, this, d_sample_counter); + d_worker_active = true; } - - consume_each(num_items_consumed); - + d_sample_counter += d_fft_size; + consume_each(1); break; - } // case 1, switch d_state - - } // switch d_state - - return noutput_items; + } + } + return 0; } -void pcps_acquisition_cc::acquisition_core( void ) +void pcps_acquisition_cc::acquisition_core( unsigned long int samp_count ) { - d_worker_active = false; - while( 1 ) + gr::thread::scoped_lock lk(d_setlock); + + // initialize acquisition algorithm + int doppler; + uint32_t indext = 0; + float magt = 0.0; + const gr_complex *in = d_data_buffer; //Get the input samples pointer + + int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size ); + + float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); + + d_input_power = 0.0; + d_mag = 0.0; + d_well_count++; + + DLOG(INFO) << "Channel: " << d_channel + << " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << " ,sample stamp: " << samp_count << ", threshold: " + << d_threshold << ", doppler_max: " << d_doppler_max + << ", doppler_step: " << d_doppler_step + << ", use_CFAR_algorithm_flag: " << ( d_use_CFAR_algorithm_flag ? "true" : "false" ); + + lk.unlock(); + if (d_use_CFAR_algorithm_flag) { - std::unique_lock lk( d_mutex ); - d_cond.wait( lk, [&]{ return this->d_new_data_available or this->d_done; } ); - d_worker_active = !d_done; - unsigned long int sample_counter = d_sample_counter; // sample counter - lk.unlock(); + // 1- (optional) Compute the input signal power estimation + volk_32fc_magnitude_squared_32f(d_magnitude, in, d_fft_size); + volk_32f_accumulator_s32f(&d_input_power, d_magnitude, d_fft_size); + d_input_power /= static_cast(d_fft_size); + } + // 2- Doppler frequency search loop + for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) + { + // doppler search steps + doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; - if( d_done ) + volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, d_grid_doppler_wipeoffs[doppler_index], d_fft_size); + + // 3- Perform the FFT-based convolution (parallel time search) + // Compute the FFT of the carrier wiped--off incoming signal + d_fft_if->execute(); + + // Multiply carrier wiped--off, Fourier transformed incoming signal + // with the local FFT'd code reference using SIMD operations with VOLK library + volk_32fc_x2_multiply_32fc(d_ifft->get_inbuf(), d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); + + // compute the inverse FFT + d_ifft->execute(); + + // Search maximum + size_t offset = ( d_bit_transition_flag ? effective_fft_size : 0 ); + volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf() + offset, effective_fft_size); + volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size); + magt = d_magnitude[indext]; + + if (d_use_CFAR_algorithm_flag) { - break; + // Normalize the maximum value to correct the scale factor introduced by FFTW + magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); } - - // initialize acquisition algorithm - int doppler; - uint32_t indext = 0; - float magt = 0.0; - const gr_complex *in = d_data_buffer; //Get the input samples pointer - - int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size ); - - float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); - - d_input_power = 0.0; - d_mag = 0.0; - d_well_count++; - - DLOG(INFO) << "Channel: " << d_channel - << " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN - << " ,sample stamp: " << sample_counter << ", threshold: " - << d_threshold << ", doppler_max: " << d_doppler_max - << ", doppler_step: " << d_doppler_step - << ", use_CFAR_algorithm_flag: " << ( d_use_CFAR_algorithm_flag ? "true" : "false" ); - - if (d_use_CFAR_algorithm_flag == true) + // 4- record the maximum peak and the associated synchronization parameters + if (d_mag < magt) { - // 1- (optional) Compute the input signal power estimation - volk_32fc_magnitude_squared_32f(d_magnitude, in, d_fft_size); - volk_32f_accumulator_s32f(&d_input_power, d_magnitude, d_fft_size); - d_input_power /= static_cast(d_fft_size); - } - // 2- Doppler frequency search loop - for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) - { - // doppler search steps - doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; + d_mag = magt; - volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, - d_grid_doppler_wipeoffs[doppler_index], d_fft_size); - - // 3- Perform the FFT-based convolution (parallel time search) - // Compute the FFT of the carrier wiped--off incoming signal - d_fft_if->execute(); - - // Multiply carrier wiped--off, Fourier transformed incoming signal - // with the local FFT'd code reference using SIMD operations with VOLK library - volk_32fc_x2_multiply_32fc(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); - - // compute the inverse FFT - d_ifft->execute(); - - // Search maximum - size_t offset = ( d_bit_transition_flag ? effective_fft_size : 0 ); - volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf() + offset, effective_fft_size); - volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size); - magt = d_magnitude[indext]; - - if (d_use_CFAR_algorithm_flag == true) + if (!d_use_CFAR_algorithm_flag) { - // Normalize the maximum value to correct the scale factor introduced by FFTW - magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); - } - // 4- record the maximum peak and the associated synchronization parameters - if (d_mag < magt) - { - d_mag = magt; - - if (d_use_CFAR_algorithm_flag == false) - { - // Search grid noise floor approximation for this doppler line - volk_32f_accumulator_s32f(&d_input_power, d_magnitude, effective_fft_size); - d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1); - } - - // In case that d_bit_transition_flag = true, we compare the potentially - // new maximum test statistics (d_mag/d_input_power) with the value in - // d_test_statistics. When the second dwell is being processed, the value - // of d_mag/d_input_power could be lower than d_test_statistics (i.e, - // the maximum test statistics in the previous dwell is greater than - // current d_mag/d_input_power). Note that d_test_statistics is not - // restarted between consecutive dwells in multidwell operation. - - if (d_test_statistics < (d_mag / d_input_power) || !d_bit_transition_flag) - { - d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); - d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); - d_gnss_synchro->Acq_samplestamp_samples = sample_counter; - - // 5- Compute the test statistics and compare to the threshold - //d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; - d_test_statistics = d_mag / d_input_power; - } + // Search grid noise floor approximation for this doppler line + volk_32f_accumulator_s32f(&d_input_power, d_magnitude, effective_fft_size); + d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1); } - // Record results to file if required - if (d_dump) - { - std::stringstream filename; - std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write - filename.str(""); + // In case that d_bit_transition_flag = true, we compare the potentially + // new maximum test statistics (d_mag/d_input_power) with the value in + // d_test_statistics. When the second dwell is being processed, the value + // of d_mag/d_input_power could be lower than d_test_statistics (i.e, + // the maximum test statistics in the previous dwell is greater than + // current d_mag/d_input_power). Note that d_test_statistics is not + // restarted between consecutive dwells in multidwell operation. - boost::filesystem::path p = d_dump_filename; - filename << p.parent_path().string() + if (d_test_statistics < (d_mag / d_input_power) || !d_bit_transition_flag) + { + d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); + d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); + d_gnss_synchro->Acq_samplestamp_samples = samp_count; + + // 5- Compute the test statistics and compare to the threshold + //d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; + d_test_statistics = d_mag / d_input_power; + } + } + // Record results to file if required + if (d_dump) + { + std::stringstream filename; + std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write + filename.str(""); + boost::filesystem::path p = d_dump_filename; + filename << p.parent_path().string() << boost::filesystem::path::preferred_separator << p.stem().string() << "_" << d_gnss_synchro->System @@ -549,15 +494,32 @@ void pcps_acquisition_cc::acquisition_core( void ) << doppler << p.extension().string(); - DLOG(INFO) << "Writing ACQ out to " << filename.str(); + DLOG(INFO) << "Writing ACQ out to " << filename.str(); - d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); - d_dump_file.write(reinterpret_cast(d_ifft->get_outbuf()), n); //write directly |abs(x)|^2 in this Doppler bin? - d_dump_file.close(); - } + d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); + d_dump_file.write(reinterpret_cast(d_ifft->get_outbuf()), n); //write directly |abs(x)|^2 in this Doppler bin? + d_dump_file.close(); } - - if (!d_bit_transition_flag) + } + lk.lock(); + if (!d_bit_transition_flag) + { + if (d_test_statistics > d_threshold) + { + d_state = 0; // Positive acquisition + d_active = false; + send_positive_acquisition(); + } + else if (d_well_count == d_max_dwells) + { + d_state = 0; + d_active = false; + send_negative_acquisition(); + } + } + else + { + if (d_well_count == d_max_dwells) // d_max_dwells = 2 { if (d_test_statistics > d_threshold) { @@ -565,66 +527,13 @@ void pcps_acquisition_cc::acquisition_core( void ) d_active = false; send_positive_acquisition(); } - else if (d_well_count == d_max_dwells) + else { - d_state = 0; + d_state = 0; // Negative acquisition d_active = false; send_negative_acquisition(); } } - else - { - if (d_well_count == d_max_dwells) // d_max_dwells = 2 - { - if (d_test_statistics > d_threshold) - { - d_state = 0; // Positive acquisition - d_active = false; - send_positive_acquisition(); - } - else - { - d_state = 0; // Negative acquisition - d_active = false; - send_negative_acquisition(); - } - } - } - - lk.lock(); - d_worker_active = false; - d_new_data_available = false; - lk.unlock(); - d_cond.notify_one(); } -} - - -bool pcps_acquisition_cc::start( void ) -{ d_worker_active = false; - d_done = false; - - // Start the worker thread and wait for it to acknowledge: - d_worker_thread = std::move( std::thread( &pcps_acquisition_cc::acquisition_core, this ) ); - - return gr::block::start(); } - - -bool pcps_acquisition_cc::stop( void ) -{ - // Let the worker thread know that we are done and then wait to join - if( d_worker_thread.joinable() ) - { - { - std::lock_guard lk( d_mutex ); - d_done = true; - d_cond.notify_one(); - } - - d_worker_thread.join(); - } - return gr::block::stop(); -} - diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h index c3d525d37..5a88aa6f1 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h @@ -21,6 +21,7 @@ *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com *
  • Marc Molina, 2013. marc.molina.pena@gmail.com *
  • Cillian O'Driscoll, 2017. cillian(at)ieee.org + *
  • Antonio Ramos, 2017. antonio.ramos@cttc.es * * * ------------------------------------------------------------------------- @@ -53,14 +54,10 @@ #include #include -#include -#include -#include #include #include #include #include "gnss_synchro.h" -#include "GLONASS_L1_CA.h" //GLONASS_TWO_PI class pcps_acquisition_cc; @@ -102,7 +99,7 @@ private: void update_grid_doppler_wipeoffs(); bool is_fdma(); - void acquisition_core( void ); + void acquisition_core( unsigned long int samp_count ); void send_negative_acquisition(); void send_positive_acquisition(); @@ -113,7 +110,6 @@ private: int d_samples_per_code; //unsigned int d_doppler_resolution; float d_threshold; - std::string d_satellite_str; unsigned int d_doppler_max; unsigned int d_doppler_step; unsigned int d_sampled_ms; @@ -141,16 +137,8 @@ private: bool d_dump; unsigned int d_channel; std::string d_dump_filename; - - std::thread d_worker_thread; - std::mutex d_mutex; - - std::condition_variable d_cond; - bool d_done; - bool d_new_data_available; bool d_worker_active; bool d_blocking; - gr_complex *d_data_buffer; public: @@ -255,15 +243,6 @@ public: gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); - /*! - * Called by the flowgraph when processing is about to start. - */ - bool start( void ); - - /*! - * Called by the flowgraph when processing is done. - */ - bool stop( void ); }; #endif /* GNSS_SDR_PCPS_ACQUISITION_CC_H_*/ diff --git a/src/algorithms/channel/adapters/channel.cc b/src/algorithms/channel/adapters/channel.cc index 425dbb968..e66074b7a 100644 --- a/src/algorithms/channel/adapters/channel.cc +++ b/src/algorithms/channel/adapters/channel.cc @@ -40,7 +40,7 @@ using google::LogMessage; Channel::Channel(ConfigurationInterface *configuration, unsigned int channel, std::shared_ptr pass_through, std::shared_ptr acq, std::shared_ptr trk, std::shared_ptr nav, - std::string role, std::string implementation, boost::shared_ptr queue) + std::string role, std::string implementation, gr::msg_queue::sptr queue) { pass_through_ = pass_through; acq_ = acq; @@ -50,6 +50,7 @@ Channel::Channel(ConfigurationInterface *configuration, unsigned int channel, implementation_ = implementation; channel_ = channel; queue_ = queue; + channel_fsm_ = std::make_shared(); flag_enable_fpga = configuration->property("Channel.enable_FPGA", false); acq_->set_channel(channel_); @@ -89,24 +90,21 @@ Channel::Channel(ConfigurationInterface *configuration, unsigned int channel, repeat_ = configuration->property("Acquisition_" + implementation_ + boost::lexical_cast(channel_) + ".repeat_satellite", false); DLOG(INFO) << "Channel " << channel_ << " satellite repeat = " << repeat_; - channel_fsm_.set_acquisition(acq_); - channel_fsm_.set_tracking(trk_); - channel_fsm_.set_channel(channel_); - channel_fsm_.set_queue(queue_); + channel_fsm_->set_acquisition(acq_); + channel_fsm_->set_tracking(trk_); + channel_fsm_->set_channel(channel_); + channel_fsm_->set_queue(queue_); connected_ = false; gnss_signal_ = Gnss_Signal(implementation_); - channel_msg_rx = channel_msg_receiver_make_cc(&channel_fsm_, repeat_); + channel_msg_rx = channel_msg_receiver_make_cc(channel_fsm_, repeat_); } // Destructor -Channel::~Channel() -{ - channel_fsm_.terminate(); -} +Channel::~Channel(){} void Channel::connect(gr::top_block_sptr top_block) @@ -139,7 +137,6 @@ void Channel::connect(gr::top_block_sptr top_block) top_block->msg_connect(nav_->get_left_block(), pmt::mp("preamble_timestamp_s"), trk_->get_right_block(), pmt::mp("preamble_timestamp_s")); DLOG(INFO) << "MSG FEEDBACK CHANNEL telemetry_decoder -> tracking"; - //std::cout<<"has port: "<get_right_block()->has_msg_port(pmt::mp("events"))<msg_connect(acq_->get_right_block(), pmt::mp("events"), channel_msg_rx, pmt::mp("events")); top_block->msg_connect(trk_->get_right_block(), pmt::mp("events"), channel_msg_rx, pmt::mp("events")); @@ -187,6 +184,7 @@ gr::basic_block_sptr Channel::get_right_block() void Channel::set_signal(const Gnss_Signal& gnss_signal) { + std::lock_guard lk(mx); gnss_signal_ = gnss_signal; std::string str_aux = gnss_signal_.get_signal_str(); const char * str = str_aux.c_str(); // get a C style null terminated string @@ -201,6 +199,14 @@ void Channel::set_signal(const Gnss_Signal& gnss_signal) void Channel::start_acquisition() { - channel_fsm_.Event_start_acquisition(); + std::lock_guard lk(mx); + bool result = false; + result = channel_fsm_->Event_start_acquisition(); + if(!result) + { + LOG(WARNING) << "Invalid channel event"; + return; + } + DLOG(INFO) << "Channel start_acquisition()"; } diff --git a/src/algorithms/channel/adapters/channel.h b/src/algorithms/channel/adapters/channel.h index a05697eed..8740b5ad9 100644 --- a/src/algorithms/channel/adapters/channel.h +++ b/src/algorithms/channel/adapters/channel.h @@ -37,6 +37,7 @@ #include #include +#include #include #include #include "channel_interface.h" @@ -63,8 +64,7 @@ public: Channel(ConfigurationInterface *configuration, unsigned int channel, std::shared_ptr pass_through, std::shared_ptr acq, std::shared_ptr trk, std::shared_ptr nav, - std::string role, std::string implementation, - boost::shared_ptr queue); + std::string role, std::string implementation, gr::msg_queue::sptr queue); //! Virtual destructor virtual ~Channel(); @@ -79,6 +79,7 @@ public: inline std::string implementation() override { return implementation_; } inline size_t item_size() override { return 0; } + inline Gnss_Signal get_signal() const override { return gnss_signal_; } void start_acquisition() override; //!< Start the State Machine @@ -104,8 +105,9 @@ private: Gnss_Signal gnss_signal_; bool connected_; bool repeat_; - ChannelFsm channel_fsm_; - boost::shared_ptr queue_; + std::shared_ptr channel_fsm_; + gr::msg_queue::sptr queue_; + std::mutex mx; }; #endif /*GNSS_SDR_CHANNEL_H_*/ diff --git a/src/algorithms/channel/libs/channel_fsm.cc b/src/algorithms/channel/libs/channel_fsm.cc index 187d419f4..b6f23cbeb 100644 --- a/src/algorithms/channel/libs/channel_fsm.cc +++ b/src/algorithms/channel/libs/channel_fsm.cc @@ -1,11 +1,12 @@ /*! * \file channel_fsm.cc - * \brief Implementation of a State Machine for channel using boost::statechart - * \author Luis Esteve, 2011. luis(at)epsilon-formacion.com + * \brief Implementation of a State Machine for channel + * \authors Antonio Ramos, 2017. antonio.ramos(at)cttc.es + * Luis Esteve, 2011. luis(at)epsilon-formacion.com * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -29,109 +30,16 @@ */ #include "channel_fsm.h" -#include -#include -#include -#include -#include -#include #include #include "control_message_factory.h" -struct Ev_channel_start_acquisition: sc::event -{}; - -struct Ev_channel_valid_acquisition: sc::event -{}; - -struct Ev_channel_failed_acquisition_repeat: sc::event -{}; - -struct Ev_channel_failed_acquisition_no_repeat: sc::event -{}; - -struct Ev_channel_failed_tracking_standby: sc::event -{}; - -//struct Ev_channel_failed_tracking_reacq: sc::event -//{}; - -struct channel_idle_fsm_S0: public sc::state -{ -public: - // sc::transition(event, next state) - typedef sc::transition reactions; - channel_idle_fsm_S0(my_context ctx) : my_base(ctx) - { - //std::cout << "Enter Channel_Idle_S0 " << std::endl; - } -}; - - -struct channel_acquiring_fsm_S1: public sc::state -{ -public: - typedef mpl::list, - sc::transition, - sc::transition > reactions; - - channel_acquiring_fsm_S1(my_context ctx) : my_base(ctx) - { - //std::cout << "Enter Channel_Acq_S1 " << std::endl; - context ().start_acquisition(); - } - ~channel_acquiring_fsm_S1() - { - //std::cout << "Exit Channel_Acq_S1 " << std::endl; - } -}; - - -struct channel_tracking_fsm_S2: public sc::state -{ -public: - typedef mpl::list, - sc::transition> reactions; - - channel_tracking_fsm_S2(my_context ctx) : my_base(ctx) - { - //std::cout << "Enter Channel_tracking_S2 " << std::endl; - context ().start_tracking(); - } - - ~channel_tracking_fsm_S2() - { - //std::cout << "Exit Channel_tracking_S2 " << std::endl; - context ().notify_stop_tracking(); - } - -}; - - -struct channel_waiting_fsm_S3: public sc::state -{ -public: - typedef sc::transition reactions; - - channel_waiting_fsm_S3(my_context ctx) : - my_base(ctx) - { - //std::cout << "Enter Channel_waiting_S3 " << std::endl; - context ().request_satellite(); - } - // ~channel_waiting_fsm_S3(){} -}; - - - ChannelFsm::ChannelFsm() { acq_ = nullptr; trk_ = nullptr; channel_ = 0; - initiate(); //start the FSM + d_state = 0; } @@ -141,62 +49,115 @@ ChannelFsm::ChannelFsm(std::shared_ptr acquisition) : { trk_ = nullptr; channel_ = 0; - initiate(); //start the FSM + d_state = 0; } - -void ChannelFsm::Event_start_acquisition() +bool ChannelFsm::Event_start_acquisition() { - this->process_event(Ev_channel_start_acquisition()); - //std::cout<<"Ev_channel_start_acquisition launched"< lk(mx); + if((d_state == 1) || (d_state == 2)) + { + return false; + } + else + { + d_state = 1; + start_acquisition(); + DLOG(INFO) << "CH = " << channel_ << ". Ev start acquisition"; + return true; + } } -void ChannelFsm::Event_valid_acquisition() +bool ChannelFsm::Event_valid_acquisition() { - this->process_event(Ev_channel_valid_acquisition()); + std::lock_guard lk(mx); + if(d_state != 1) + { + return false; + } + else + { + d_state = 2; + start_tracking(); + DLOG(INFO) << "CH = " << channel_ << ". Ev valid acquisition"; + return true; + } } -void ChannelFsm::Event_failed_acquisition_repeat() +bool ChannelFsm::Event_failed_acquisition_repeat() { - this->process_event(Ev_channel_failed_acquisition_repeat()); + std::lock_guard lk(mx); + if(d_state != 1) + { + return false; + } + else + { + d_state = 1; + start_acquisition(); + DLOG(INFO) << "CH = " << channel_ << ". Ev failed acquisition repeat"; + return true; + } } -void ChannelFsm::Event_failed_acquisition_no_repeat() + +bool ChannelFsm::Event_failed_acquisition_no_repeat() { - this->process_event(Ev_channel_failed_acquisition_no_repeat()); + std::lock_guard lk(mx); + if(d_state != 1) + { + return false; + } + else + { + d_state = 3; + request_satellite(); + DLOG(INFO) << "CH = " << channel_ << ". Ev failed acquisition no repeat"; + return true; + } } -// Something is wrong here, we are using a memory after it ts freed -void ChannelFsm::Event_failed_tracking_standby() +bool ChannelFsm::Event_failed_tracking_standby() { - this->process_event(Ev_channel_failed_tracking_standby()); + std::lock_guard lk(mx); + if(d_state != 2) + { + return false; + } + else + { + d_state = 0; + notify_stop_tracking(); + DLOG(INFO) << "CH = " << channel_ << ". Ev failed tracking standby"; + return true; + } } -//void ChannelFsm::Event_failed_tracking_reacq() { -// this->process_event(Ev_channel_failed_tracking_reacq()); -//} - void ChannelFsm::set_acquisition(std::shared_ptr acquisition) { + std::lock_guard lk(mx); acq_ = acquisition; } void ChannelFsm::set_tracking(std::shared_ptr tracking) { + std::lock_guard lk(mx); trk_ = tracking; } -void ChannelFsm::set_queue(boost::shared_ptr queue) +void ChannelFsm::set_queue(gr::msg_queue::sptr queue) { + std::lock_guard lk(mx); queue_ = queue; } void ChannelFsm::set_channel(unsigned int channel) { + std::lock_guard lk(mx); channel_ = channel; } diff --git a/src/algorithms/channel/libs/channel_fsm.h b/src/algorithms/channel/libs/channel_fsm.h index 868388b7b..23b92c394 100644 --- a/src/algorithms/channel/libs/channel_fsm.h +++ b/src/algorithms/channel/libs/channel_fsm.h @@ -1,12 +1,12 @@ /*! * \file channel_fsm.h - * \brief Interface of the State Machine for channel using boost::statechart - * \author Luis Esteve, 2011. luis(at)epsilon-formacion.com - * + * \brief Interface of the State Machine for channel + * \authors Antonio Ramos, 2017. antonio.ramos(at)cttc.es + * Luis Esteve, 2011. luis(at)epsilon-formacion.com * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -32,26 +32,17 @@ #ifndef GNSS_SDR_CHANNEL_FSM_H #define GNSS_SDR_CHANNEL_FSM_H - -#include +#include +#include #include #include "acquisition_interface.h" #include "tracking_interface.h" #include "telemetry_decoder_interface.h" - -namespace sc = boost::statechart; -namespace mpl = boost::mpl; - -struct channel_idle_fsm_S0; -struct channel_acquiring_fsm_S1; -struct channel_tracking_fsm_S2; -struct channel_waiting_fsm_S3; - /*! - * \brief This class implements a State Machine for channel using boost::statechart + * \brief This class implements a State Machine for channel */ -class ChannelFsm: public sc::state_machine +class ChannelFsm { public: ChannelFsm(); @@ -59,26 +50,29 @@ public: void set_acquisition(std::shared_ptr acquisition); void set_tracking(std::shared_ptr tracking); - void set_queue(boost::shared_ptr queue); + void set_queue(gr::msg_queue::sptr queue); void set_channel(unsigned int channel); + + //FSM EVENTS + bool Event_start_acquisition(); + bool Event_valid_acquisition(); + bool Event_failed_acquisition_repeat(); + bool Event_failed_acquisition_no_repeat(); + bool Event_failed_tracking_standby(); + +private: + void start_acquisition(); void start_tracking(); void request_satellite(); void notify_stop_tracking(); - //FSM EVENTS - void Event_start_acquisition(); - void Event_valid_acquisition(); - void Event_failed_acquisition_repeat(); - void Event_failed_acquisition_no_repeat(); - //void Event_gps_failed_tracking_reacq(); - void Event_failed_tracking_standby(); - -private: std::shared_ptr acq_; std::shared_ptr trk_; - boost::shared_ptr queue_; + gr::msg_queue::sptr queue_; unsigned int channel_; + unsigned int d_state; + std::mutex mx; }; #endif /*GNSS_SDR_CHANNEL_FSM_H*/ diff --git a/src/algorithms/channel/libs/channel_msg_receiver_cc.cc b/src/algorithms/channel/libs/channel_msg_receiver_cc.cc index 573c1aa84..7a80cfceb 100644 --- a/src/algorithms/channel/libs/channel_msg_receiver_cc.cc +++ b/src/algorithms/channel/libs/channel_msg_receiver_cc.cc @@ -37,37 +37,34 @@ using google::LogMessage; -channel_msg_receiver_cc_sptr channel_msg_receiver_make_cc(ChannelFsm* channel_fsm, bool repeat) +channel_msg_receiver_cc_sptr channel_msg_receiver_make_cc(std::shared_ptr channel_fsm, bool repeat) { return channel_msg_receiver_cc_sptr(new channel_msg_receiver_cc(channel_fsm, repeat)); } void channel_msg_receiver_cc::msg_handler_events(pmt::pmt_t msg) { + bool result = false; try { long int message = pmt::to_long(msg); switch (message) { case 1: //positive acquisition - //DLOG(INFO) << "Channel " << channel_ << " ACQ SUCCESS satellite " << - // gnss_synchro_.System << " " << gnss_synchro_.PRN; - d_channel_fsm->Event_valid_acquisition(); + result = d_channel_fsm->Event_valid_acquisition(); break; case 2: //negative acquisition - //DLOG(INFO) << "Channel " << channel_ - // << " ACQ FAILED satellite " << gnss_synchro_.System << " " << gnss_synchro_.PRN; if (d_repeat == true) { - d_channel_fsm->Event_failed_acquisition_repeat(); + result = d_channel_fsm->Event_failed_acquisition_repeat(); } else { - d_channel_fsm->Event_failed_acquisition_no_repeat(); + result = d_channel_fsm->Event_failed_acquisition_no_repeat(); } break; case 3: // tracking loss of lock event - d_channel_fsm->Event_failed_tracking_standby(); + result = d_channel_fsm->Event_failed_tracking_standby(); break; default: LOG(WARNING) << "Default case, invalid message."; @@ -78,10 +75,14 @@ void channel_msg_receiver_cc::msg_handler_events(pmt::pmt_t msg) { LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; } + if(!result) + { + LOG(WARNING) << "msg_handler_telemetry invalid event"; + } } -channel_msg_receiver_cc::channel_msg_receiver_cc(ChannelFsm* channel_fsm, bool repeat) : +channel_msg_receiver_cc::channel_msg_receiver_cc(std::shared_ptr channel_fsm, bool repeat) : gr::block("channel_msg_receiver_cc", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) { this->message_port_register_in(pmt::mp("events")); diff --git a/src/algorithms/channel/libs/channel_msg_receiver_cc.h b/src/algorithms/channel/libs/channel_msg_receiver_cc.h index 195d41e7c..77a91379a 100644 --- a/src/algorithms/channel/libs/channel_msg_receiver_cc.h +++ b/src/algorithms/channel/libs/channel_msg_receiver_cc.h @@ -38,7 +38,7 @@ class channel_msg_receiver_cc; typedef boost::shared_ptr channel_msg_receiver_cc_sptr; -channel_msg_receiver_cc_sptr channel_msg_receiver_make_cc(ChannelFsm* channel_fsm, bool repeat); +channel_msg_receiver_cc_sptr channel_msg_receiver_make_cc(std::shared_ptr channel_fsm, bool repeat); /*! * \brief GNU Radio block that receives asynchronous channel messages from acquisition and tracking blocks @@ -46,11 +46,11 @@ channel_msg_receiver_cc_sptr channel_msg_receiver_make_cc(ChannelFsm* channel_fs class channel_msg_receiver_cc : public gr::block { private: - ChannelFsm* d_channel_fsm; + std::shared_ptr d_channel_fsm; bool d_repeat; // todo: change FSM to include repeat value - friend channel_msg_receiver_cc_sptr channel_msg_receiver_make_cc(ChannelFsm* channel_fsm, bool repeat); + friend channel_msg_receiver_cc_sptr channel_msg_receiver_make_cc(std::shared_ptr channel_fsm, bool repeat); void msg_handler_events(pmt::pmt_t msg); - channel_msg_receiver_cc(ChannelFsm* channel_fsm, bool repeat); + channel_msg_receiver_cc(std::shared_ptr channel_fsm, bool repeat); public: ~channel_msg_receiver_cc (); //!< Default destructor diff --git a/src/algorithms/libs/gps_l5_signal.cc b/src/algorithms/libs/gps_l5_signal.cc index 33396ca23..5aa15b96c 100644 --- a/src/algorithms/libs/gps_l5_signal.cc +++ b/src/algorithms/libs/gps_l5_signal.cc @@ -186,7 +186,7 @@ void gps_l5i_code_gen_complex(std::complex* _dest, unsigned int _prn) if (_prn > 0 and _prn < 51) { - make_l5i(_code, _prn); + make_l5i(_code, _prn - 1); } for (signed int i = 0; i < GPS_L5i_CODE_LENGTH_CHIPS; i++) @@ -206,7 +206,7 @@ void gps_l5i_code_gen_complex_sampled(std::complex* _dest, unsigned int _ int32_t* _code = new int32_t[GPS_L5i_CODE_LENGTH_CHIPS]; if (_prn > 0 and _prn < 51) { - make_l5i(_code, _prn); + make_l5i(_code, _prn - 1); } signed int _samplesPerCode, _codeValueIndex; @@ -253,7 +253,7 @@ void gps_l5q_code_gen_complex(std::complex* _dest, unsigned int _prn) if (_prn > 0 and _prn < 51) { - make_l5q(_code, _prn); + make_l5q(_code, _prn - 1); } for (signed int i = 0; i < GPS_L5q_CODE_LENGTH_CHIPS; i++) @@ -273,7 +273,7 @@ void gps_l5q_code_gen_complex_sampled(std::complex* _dest, unsigned int _ int32_t* _code = new int32_t[GPS_L5q_CODE_LENGTH_CHIPS]; if (_prn > 0 and _prn < 51) { - make_l5q(_code, _prn); + make_l5q(_code, _prn - 1); } signed int _samplesPerCode, _codeValueIndex; diff --git a/src/algorithms/libs/rtklib/rtklib_conversions.cc b/src/algorithms/libs/rtklib/rtklib_conversions.cc index 1664d16fb..7f1d933a6 100644 --- a/src/algorithms/libs/rtklib/rtklib_conversions.cc +++ b/src/algorithms/libs/rtklib/rtklib_conversions.cc @@ -35,7 +35,7 @@ obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synch { rtklib_obs.D[band] = gnss_synchro.Carrier_Doppler_hz; rtklib_obs.P[band] = gnss_synchro.Pseudorange_m; - rtklib_obs.L[band] = gnss_synchro.Carrier_phase_rads / (2.0 * PI); + rtklib_obs.L[band] = gnss_synchro.Carrier_phase_rads / PI_2; switch(band) { case 0: @@ -209,8 +209,6 @@ eph_t eph_to_rtklib(const Gps_Ephemeris & gps_eph) rtklib_sat.toc = gpst2time(rtklib_sat.week, toc); rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow); - //printf("EPHEMERIS TIME [%i]: %s,%f\n\r",rtklib_sat.sat,time_str(rtklib_sat.toe,3),rtklib_sat.toe.sec); - return rtklib_sat; } @@ -227,7 +225,7 @@ eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris & gps_cnav_eph) rtklib_sat.OMG0 = gps_cnav_eph.d_OMEGA0; // Compute the angle between the ascending node and the Greenwich meridian const double OMEGA_DOT_REF = -2.6e-9; // semicircles / s, see IS-GPS-200H pp. 164 - double d_OMEGA_DOT = OMEGA_DOT_REF * GPS_L2_PI + gps_cnav_eph.d_DELTA_OMEGA_DOT; + double d_OMEGA_DOT = OMEGA_DOT_REF * PI + gps_cnav_eph.d_DELTA_OMEGA_DOT; rtklib_sat.OMGd = d_OMEGA_DOT; rtklib_sat.omg = gps_cnav_eph.d_OMEGA; rtklib_sat.i0 = gps_cnav_eph.d_i_0; diff --git a/src/algorithms/libs/rtklib/rtklib_pntpos.cc b/src/algorithms/libs/rtklib/rtklib_pntpos.cc index 056dc2901..4199dcb96 100644 --- a/src/algorithms/libs/rtklib/rtklib_pntpos.cc +++ b/src/algorithms/libs/rtklib/rtklib_pntpos.cc @@ -97,7 +97,13 @@ double prange(const obsd_t *obs, const nav_t *nav, const double *azel, /* L1-L2 for GPS/GLO/QZS, L1-L5 for GAL/SBS */ - if (NFREQ >= 3 && (sys & (SYS_GAL | SYS_SBS))) j = 2; + if (sys & (SYS_GAL | SYS_SBS)) {j = 2;} + + if (sys == SYS_GPS) + { + if(obs->code[1] != CODE_NONE) {j = 1;} + else if(obs->code[2] != CODE_NONE) {j = 2;} + } if (NFREQ<2 || lam[i] == 0.0 || lam[j] == 0.0) { @@ -132,7 +138,7 @@ double prange(const obsd_t *obs, const nav_t *nav, const double *azel, P2_C2 = nav->cbias[obs->sat-1][2]; /* if no P1-P2 DCB, use TGD instead */ - if (P1_P2 == 0.0 && (sys & (SYS_GPS | SYS_GAL | SYS_QZS))) + if (P1_P2 == 0.0 && (sys & (SYS_GPS | SYS_GAL | SYS_QZS))) //CHECK! { P1_P2 = (1.0 - gamma_) * gettgd(obs->sat, nav); } diff --git a/src/algorithms/observables/gnuradio_blocks/hybrid_observables_cc.cc b/src/algorithms/observables/gnuradio_blocks/hybrid_observables_cc.cc index d63570996..66cd0fce0 100644 --- a/src/algorithms/observables/gnuradio_blocks/hybrid_observables_cc.cc +++ b/src/algorithms/observables/gnuradio_blocks/hybrid_observables_cc.cc @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include #include "Galileo_E1.h" @@ -52,8 +54,8 @@ hybrid_observables_cc_sptr hybrid_make_observables_cc(unsigned int nchannels, bo hybrid_observables_cc::hybrid_observables_cc(unsigned int nchannels, bool dump, std::string dump_filename, unsigned int deep_history) : - gr::block("hybrid_observables_cc", gr::io_signature::make(nchannels, nchannels, sizeof(Gnss_Synchro)), - gr::io_signature::make(nchannels, nchannels, sizeof(Gnss_Synchro))) + gr::block("hybrid_observables_cc", gr::io_signature::make(nchannels, nchannels, sizeof(Gnss_Synchro)), + gr::io_signature::make(nchannels, nchannels, sizeof(Gnss_Synchro))) { // initialize internal vars d_dump = dump; @@ -66,11 +68,6 @@ hybrid_observables_cc::hybrid_observables_cc(unsigned int nchannels, bool dump, { d_gnss_synchro_history_queue.push_back(std::deque()); } - // todo: this is a gnuradio scheduler hack. - // Migrate the queues to gnuradio set_history to see if the scheduler can handle - // the multiple output flow - d_max_noutputs = 100; - this->set_min_noutput_items(100); // ############# ENABLE DATA FILE LOG ################# if (d_dump == true) @@ -313,7 +310,7 @@ bool Hybrid_valueCompare_gnss_synchro_sample_counter(const Gnss_Synchro& a, unsi bool Hybrid_valueCompare_gnss_synchro_receiver_time(const Gnss_Synchro& a, double b) { - return (((double)a.Tracking_sample_counter+a.Code_phase_samples)/(double)a.fs) < (b); + return ((static_cast(a.Tracking_sample_counter) + static_cast(a.Code_phase_samples)) / static_cast(a.fs) ) < (b); } @@ -329,7 +326,27 @@ bool Hybrid_valueCompare_gnss_synchro_d_TOW(const Gnss_Synchro& a, double b) } -int hybrid_observables_cc::general_work (int noutput_items __attribute__((unused)), +void hybrid_observables_cc::forecast (int noutput_items __attribute__((unused)), gr_vector_int &ninput_items_required) +{ + bool zero_samples = true; + for(unsigned int i = 0; i < d_nchannels; i++) + { + int items = detail()->input(i)->items_available(); + if (items > 0) zero_samples = false; + ninput_items_required[i] = items; // set the required available samples in each call + } + + if (zero_samples == true) + { + for(unsigned int i = 0; i < d_nchannels; i++) + { + ninput_items_required[i] = 1; // set the required available samples in each call + } + } +} + + +int hybrid_observables_cc::general_work (int noutput_items , gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) @@ -353,7 +370,7 @@ int hybrid_observables_cc::general_work (int noutput_items __attribute__((unused */ for (unsigned int i = 0; i < d_nchannels; i++) { - n_consume[i] = ninput_items[i];// full throttle + n_consume[i] = ninput_items[i]; // full throttle for (int j = 0; j < n_consume[i]; j++) { d_gnss_synchro_history_queue[i].push_back(in[i][j]); @@ -436,6 +453,7 @@ int hybrid_observables_cc::general_work (int noutput_items __attribute__((unused d_gnss_synchro_history_queue[i].at(distance - 1))); } } + } else { @@ -461,7 +479,8 @@ int hybrid_observables_cc::general_work (int noutput_items __attribute__((unused // compute interpolated TOW value at T_rx_s int ref_channel_key = gnss_synchro_map_iter->second.Channel_ID; - Gnss_Synchro adj_obs = adjacent_gnss_synchro_map.at(ref_channel_key); + Gnss_Synchro adj_obs; + adj_obs = adjacent_gnss_synchro_map.at(ref_channel_key); double ref_adj_T_rx_s = static_cast(adj_obs.Tracking_sample_counter) / ref_fs_hz + adj_obs.Code_phase_samples / ref_fs_hz; double d_TOW_reference = gnss_synchro_map_iter->second.TOW_at_current_symbol_s; @@ -487,7 +506,12 @@ int hybrid_observables_cc::general_work (int noutput_items __attribute__((unused // two points linear interpolation using adjacent (adj) values: y=y1+(x-x1)*(y2-y1)/(x2-x1) // TOW at the selected receiver time T_rx_s int element_key = gnss_synchro_map_iter->second.Channel_ID; - adj_obs = adjacent_gnss_synchro_map.at(element_key); + try{ + adj_obs = adjacent_gnss_synchro_map.at(element_key); + }catch(const std::exception & ex) + { + continue; + } double adj_T_rx_s = static_cast(adj_obs.Tracking_sample_counter) / channel_fs_hz + adj_obs.Code_phase_samples / channel_fs_hz; @@ -561,7 +585,7 @@ int hybrid_observables_cc::general_work (int noutput_items __attribute__((unused } } } - } while(channel_history_ok == true && d_max_noutputs > n_outputs); + } while(channel_history_ok == true && noutput_items > n_outputs); // Multi-rate consume! for (unsigned int i = 0; i < d_nchannels; i++) diff --git a/src/algorithms/observables/gnuradio_blocks/hybrid_observables_cc.h b/src/algorithms/observables/gnuradio_blocks/hybrid_observables_cc.h index 4d7e67338..494f84e75 100644 --- a/src/algorithms/observables/gnuradio_blocks/hybrid_observables_cc.h +++ b/src/algorithms/observables/gnuradio_blocks/hybrid_observables_cc.h @@ -55,7 +55,7 @@ public: ~hybrid_observables_cc (); int general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); - + void forecast (int noutput_items, gr_vector_int &ninput_items_required); private: friend hybrid_observables_cc_sptr hybrid_make_observables_cc(unsigned int nchannels, bool dump, std::string dump_filename, unsigned int deep_history); @@ -66,7 +66,6 @@ private: double T_rx_s; double T_rx_step_s; - int d_max_noutputs; bool d_dump; unsigned int d_nchannels; unsigned int history_deep; diff --git a/src/algorithms/signal_source/adapters/CMakeLists.txt b/src/algorithms/signal_source/adapters/CMakeLists.txt index bac9aee3d..2fb8f4be8 100644 --- a/src/algorithms/signal_source/adapters/CMakeLists.txt +++ b/src/algorithms/signal_source/adapters/CMakeLists.txt @@ -139,7 +139,9 @@ set(SIGNAL_SOURCE_ADAPTER_SOURCES file_signal_source.cc gen_signal_source.cc nsr_file_signal_source.cc spir_file_signal_source.cc + spir_gss6450_file_signal_source.cc rtl_tcp_signal_source.cc + labsat_signal_source.cc ${OPT_DRIVER_SOURCES} ) diff --git a/src/algorithms/signal_source/adapters/file_signal_source.cc b/src/algorithms/signal_source/adapters/file_signal_source.cc index 42591ec79..ea2bd190f 100644 --- a/src/algorithms/signal_source/adapters/file_signal_source.cc +++ b/src/algorithms/signal_source/adapters/file_signal_source.cc @@ -37,7 +37,6 @@ #include #include #include -#include #include "gnss_sdr_valve.h" #include "configuration_interface.h" @@ -51,7 +50,7 @@ DEFINE_string(signal_source, "-", FileSignalSource::FileSignalSource(ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams, boost::shared_ptr queue) : - role_(role), in_streams_(in_streams), out_streams_(out_streams), queue_(queue) + role_(role), in_streams_(in_streams), out_streams_(out_streams), queue_(queue) { std::string default_filename = "./example_capture.dat"; std::string default_item_type = "short"; @@ -71,8 +70,7 @@ FileSignalSource::FileSignalSource(ConfigurationInterface* configuration, dump_ = configuration->property(role + ".dump", false); dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename); enable_throttle_control_ = configuration->property(role + ".enable_throttle_control", false); - std::string s = "InputFilter"; - //double IF = configuration->property(s + ".IF", 0.0); + double seconds_to_skip = configuration->property(role + ".seconds_to_skip", default_seconds_to_skip ); header_size = configuration->property( role + ".header_size", 0 ); long samples_to_skip = 0; @@ -116,29 +114,27 @@ FileSignalSource::FileSignalSource(ConfigurationInterface* configuration, file_source_ = gr::blocks::file_source::make(item_size_, filename_.c_str(), repeat_); if( seconds_to_skip > 0 ) - { - samples_to_skip = static_cast< long >( - seconds_to_skip * sampling_frequency_ ); - - if( is_complex ) { - samples_to_skip *= 2; + samples_to_skip = static_cast< long >( seconds_to_skip * sampling_frequency_ ); + + if( is_complex ) + { + samples_to_skip *= 2; + } } - } if( header_size > 0 ) - { - samples_to_skip += header_size; - } + { + samples_to_skip += header_size; + } if( samples_to_skip > 0 ) - { - LOG(INFO) << "Skipping " << samples_to_skip << " samples of the input file"; - if( not file_source_->seek( samples_to_skip, SEEK_SET ) ) { - LOG(INFO) << "Error skipping bytes!"; + LOG(INFO) << "Skipping " << samples_to_skip << " samples of the input file"; + if( not file_source_->seek( samples_to_skip, SEEK_SET ) ) + { + LOG(INFO) << "Error skipping bytes!"; + } } - } - } catch (const std::exception &e) { @@ -171,7 +167,6 @@ FileSignalSource::FileSignalSource(ConfigurationInterface* configuration, << std::endl << GNSSSDR_INSTALL_DIR "/share/gnss-sdr/conf/" << std::endl; - } LOG(INFO) << "file_signal_source: Unable to open the samples file " @@ -238,8 +233,8 @@ FileSignalSource::FileSignalSource(ConfigurationInterface* configuration, if (enable_throttle_control_) { throttle_ = gr::blocks::throttle::make(item_size_, sampling_frequency_); - } + DLOG(INFO) << "File source filename " << filename_; DLOG(INFO) << "Samples " << samples_; DLOG(INFO) << "Sampling frequency " << sampling_frequency_; @@ -251,14 +246,10 @@ FileSignalSource::FileSignalSource(ConfigurationInterface* configuration, } - - FileSignalSource::~FileSignalSource() {} - - void FileSignalSource::connect(gr::top_block_sptr top_block) { if (samples_ > 0) @@ -310,10 +301,6 @@ void FileSignalSource::connect(gr::top_block_sptr top_block) } - - - - void FileSignalSource::disconnect(gr::top_block_sptr top_block) { if (samples_ > 0) @@ -365,9 +352,6 @@ void FileSignalSource::disconnect(gr::top_block_sptr top_block) } - - - gr::basic_block_sptr FileSignalSource::get_left_block() { LOG(WARNING) << "Left block of a signal source should not be retrieved"; @@ -375,9 +359,6 @@ gr::basic_block_sptr FileSignalSource::get_left_block() } - - - gr::basic_block_sptr FileSignalSource::get_right_block() { if (samples_ > 0) diff --git a/src/algorithms/signal_source/adapters/fmcomms2_signal_source.cc b/src/algorithms/signal_source/adapters/fmcomms2_signal_source.cc index 5c354e500..52916a19e 100644 --- a/src/algorithms/signal_source/adapters/fmcomms2_signal_source.cc +++ b/src/algorithms/signal_source/adapters/fmcomms2_signal_source.cc @@ -53,7 +53,6 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration rx1_en_ = configuration->property(role + ".rx1_enable", true); rx2_en_ = configuration->property(role + ".rx2_enable", false); buffer_size_ = configuration->property(role + ".buffer_size", 0xA0000); - decimation_ = configuration->property(role + ".decimation", 1); quadrature_ = configuration->property(role + ".quadrature", true); rf_dc_ = configuration->property(role + ".rf_dc", true); bb_dc_ = configuration->property(role + ".bb_dc", true); @@ -79,7 +78,7 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration { fmcomms2_source_f32c_ = gr::iio::fmcomms2_source_f32c::make( uri_.c_str(), freq_, sample_rate_, - decimation_, bandwidth_, + bandwidth_, rx1_en_, rx2_en_, buffer_size_, quadrature_, rf_dc_, bb_dc_, gain_mode_rx1_.c_str(), rf_gain_rx1_, diff --git a/src/algorithms/signal_source/adapters/fmcomms2_signal_source.h b/src/algorithms/signal_source/adapters/fmcomms2_signal_source.h index fb62a12cb..78f3ebb58 100644 --- a/src/algorithms/signal_source/adapters/fmcomms2_signal_source.h +++ b/src/algorithms/signal_source/adapters/fmcomms2_signal_source.h @@ -83,7 +83,6 @@ private: unsigned long sample_rate_; unsigned long bandwidth_; unsigned long buffer_size_; //reception buffer - unsigned int decimation_; bool rx1_en_; bool rx2_en_; bool quadrature_; diff --git a/src/algorithms/signal_source/adapters/gn3s_signal_source.h b/src/algorithms/signal_source/adapters/gn3s_signal_source.h index af6ab2714..b8b61cbdb 100644 --- a/src/algorithms/signal_source/adapters/gn3s_signal_source.h +++ b/src/algorithms/signal_source/adapters/gn3s_signal_source.h @@ -29,8 +29,8 @@ */ -#ifndef GN3S_SIGNAL_SOURCE_H_ -#define GN3S_SIGNAL_SOURCE_H_ +#ifndef GNSS_SDR_GN3S_SIGNAL_SOURCE_H_ +#define GNSS_SDR_GN3S_SIGNAL_SOURCE_H_ #include #include @@ -90,4 +90,4 @@ private: boost::shared_ptr queue_; }; -#endif /*GN3S_SIGNAL_SOURCE_H_*/ +#endif /*GNSS_SDR_GN3S_SIGNAL_SOURCE_H_*/ diff --git a/src/algorithms/signal_source/adapters/labsat_signal_source.cc b/src/algorithms/signal_source/adapters/labsat_signal_source.cc new file mode 100644 index 000000000..ddd0805c2 --- /dev/null +++ b/src/algorithms/signal_source/adapters/labsat_signal_source.cc @@ -0,0 +1,119 @@ +/*! + * \file labsat_signal_source.cc + * \brief Labsat 2 and 3 front-end signal sampler driver + * \author Javier Arribas, jarribas(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "labsat_signal_source.h" +#include +#include "labsat23_source.h" +#include "configuration_interface.h" + + +using google::LogMessage; + +LabsatSignalSource::LabsatSignalSource(ConfigurationInterface* configuration, + std::string role, unsigned int in_stream, unsigned int out_stream, gr::msg_queue::sptr queue) : + role_(role), in_stream_(in_stream), out_stream_(out_stream), queue_(queue) +{ + std::string default_item_type = "gr_complex"; + std::string default_dump_file = "./data/source.bin"; + item_type_ = configuration->property(role + ".item_type", default_item_type); + dump_ = configuration->property(role + ".dump", false); + dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file); + + int channel_selector = configuration->property(role + ".selected_channel", 1); + std::string default_filename = "./example_capture.LS3"; + + samples_ = configuration->property(role + ".samples", 0); + filename_ = configuration->property(role + ".filename", default_filename); + + if (item_type_.compare("gr_complex") == 0) + { + item_size_ = sizeof(gr_complex); + labsat23_source_ = labsat23_make_source(filename_.c_str(),channel_selector); + DLOG(INFO) << "Item size " << item_size_; + DLOG(INFO) << "labsat23_source_(" << labsat23_source_->unique_id() << ")"; + } + else + { + LOG(WARNING) << item_type_ << " unrecognized item type for LabSat source"; + item_size_ = sizeof(short); + } + if (dump_) + { + DLOG(INFO) << "Dumping output into file " << dump_filename_; + file_sink_ = gr::blocks::file_sink::make(item_size_, dump_filename_.c_str()); + } + if (dump_) + { + DLOG(INFO) << "file_sink(" << file_sink_->unique_id() << ")"; + } +} + + + +LabsatSignalSource::~LabsatSignalSource() +{} + + + +void LabsatSignalSource::connect(gr::top_block_sptr top_block) +{ + if (dump_) + { + top_block->connect(labsat23_source_, 0, file_sink_, 0); + DLOG(INFO) << "connected labsat23_source_ to file sink"; + } + else + { + DLOG(INFO) << "nothing to connect internally"; + } +} + + + +void LabsatSignalSource::disconnect(gr::top_block_sptr top_block) +{ + if (dump_) + { + top_block->disconnect(labsat23_source_, 0, file_sink_, 0); + } +} + + +gr::basic_block_sptr LabsatSignalSource::get_left_block() +{ + LOG(WARNING) << "Left block of a signal source should not be retrieved"; + return gr::block_sptr(); +} + + +gr::basic_block_sptr LabsatSignalSource::get_right_block() +{ + return labsat23_source_; +} diff --git a/src/algorithms/signal_source/adapters/labsat_signal_source.h b/src/algorithms/signal_source/adapters/labsat_signal_source.h new file mode 100644 index 000000000..43821e8e8 --- /dev/null +++ b/src/algorithms/signal_source/adapters/labsat_signal_source.h @@ -0,0 +1,94 @@ +/*! + * \file labsat_signal_source.h + * \brief Labsat 2 and 3 front-end signal sampler driver + * \author Javier Arribas, jarribas(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + + +#ifndef GNSS_SDR_LABSAT_SIGNAL_SOURCE_H_ +#define GNSS_SDR_LABSAT_SIGNAL_SOURCE_H_ + +#include +#include +#include +#include +#include "gnss_block_interface.h" + + +class ConfigurationInterface; + +/*! + * \brief This class reads samples stored by a LabSat 2 or LabSat 3 device + */ +class LabsatSignalSource: public GNSSBlockInterface +{ +public: + LabsatSignalSource(ConfigurationInterface* configuration, + std::string role, unsigned int in_stream, + unsigned int out_stream, gr::msg_queue::sptr queue); + + virtual ~LabsatSignalSource(); + + inline std::string role() override + { + return role_; + } + + /*! + * \brief Returns "Labsat_Signal_Source". + */ + inline std::string implementation() override + { + return "Labsat_Signal_Source"; + } + + 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; + +private: + std::string role_; + unsigned int in_stream_; + unsigned int out_stream_; + std::string item_type_; + size_t item_size_; + long samples_; + std::string filename_; + bool dump_; + std::string dump_filename_; + gr::block_sptr labsat23_source_; + gr::blocks::file_sink::sptr file_sink_; + boost::shared_ptr queue_; +}; + +#endif /*GNSS_SDR_LABSAT_SIGNAL_SOURCE_H_*/ diff --git a/src/algorithms/signal_source/adapters/plutosdr_signal_source.cc b/src/algorithms/signal_source/adapters/plutosdr_signal_source.cc index 34526f6a5..4e7e37b3e 100644 --- a/src/algorithms/signal_source/adapters/plutosdr_signal_source.cc +++ b/src/algorithms/signal_source/adapters/plutosdr_signal_source.cc @@ -52,7 +52,6 @@ PlutosdrSignalSource::PlutosdrSignalSource(ConfigurationInterface* configuration sample_rate_ = configuration->property(role + ".sampling_frequency", 3000000); bandwidth_ = configuration->property(role + ".bandwidth", 2000000); buffer_size_ = configuration->property(role + ".buffer_size", 0xA0000); - decimation_ = configuration->property(role + ".decimation", 1); quadrature_ = configuration->property(role + ".quadrature", true); rf_dc_ = configuration->property(role + ".rf_dc", true); bb_dc_ = configuration->property(role + ".bb_dc", true); @@ -81,7 +80,7 @@ PlutosdrSignalSource::PlutosdrSignalSource(ConfigurationInterface* configuration std::cout << "item type: " << item_type_ << std::endl; plutosdr_source_ = gr::iio::pluto_source::make(uri_, freq_, sample_rate_, - decimation_, bandwidth_, buffer_size_, quadrature_, rf_dc_, bb_dc_, + bandwidth_, buffer_size_, quadrature_, rf_dc_, bb_dc_, gain_mode_.c_str(), rf_gain_,filter_file_.c_str(), filter_auto_); if (samples_ != 0) diff --git a/src/algorithms/signal_source/adapters/plutosdr_signal_source.h b/src/algorithms/signal_source/adapters/plutosdr_signal_source.h index 9bbdb4511..56c2334c8 100644 --- a/src/algorithms/signal_source/adapters/plutosdr_signal_source.h +++ b/src/algorithms/signal_source/adapters/plutosdr_signal_source.h @@ -83,7 +83,6 @@ private: unsigned long sample_rate_; unsigned long bandwidth_; unsigned long buffer_size_; // reception buffer - unsigned int decimation_; bool quadrature_; bool rf_dc_; bool bb_dc_; diff --git a/src/algorithms/signal_source/adapters/spir_gss6450_file_signal_source.cc b/src/algorithms/signal_source/adapters/spir_gss6450_file_signal_source.cc new file mode 100644 index 000000000..75d30b9f5 --- /dev/null +++ b/src/algorithms/signal_source/adapters/spir_gss6450_file_signal_source.cc @@ -0,0 +1,284 @@ +/*! + * \file spir_gss6450_file_signal_source.cc + * \brief Implementation of a class that reads signals samples from a SPIR file + * and adapts it to a SignalSourceInterface. + * \author Antonio Ramos, 2017 antonio.ramos(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is not 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 . + * + * ------------------------------------------------------------------------- + */ + +#include "spir_gss6450_file_signal_source.h" +#include +#include +#include +#include +#include +#include +#include "configuration_interface.h" + +using google::LogMessage; + + +SpirGSS6450FileSignalSource::SpirGSS6450FileSignalSource(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, unsigned int out_streams, gr::msg_queue::sptr queue) : + role_(role), in_streams_(in_streams), out_streams_(out_streams), queue_(queue) +{ + std::string default_filename = "../data/my_capture.dat"; + std::string default_dump_filename = "../data/my_capture_dump.dat"; + item_type_ = "int"; + + samples_ = configuration->property(role + ".samples", 0); + sampling_frequency_ = configuration->property(role + ".sampling_frequency", 0.0); + filename_ = configuration->property(role + ".filename", default_filename); + repeat_ = configuration->property(role + ".repeat", false); + dump_ = configuration->property(role + ".dump", false); + endian_swap_ = configuration->property(role + ".endian", false); + dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename); + enable_throttle_control_ = configuration->property(role + ".enable_throttle_control", false); + adc_bits_ = configuration->property(role + ".adc_bits", 4); + n_channels_ = configuration->property(role + ".total_channels", 1); + sel_ch_ = configuration->property(role + ".sel_ch", 1); + item_size_ = sizeof(int); + long bytes_seek = configuration->property(role + ".bytes_to_skip", 65536); + double sample_size_byte = static_cast(adc_bits_) / 4.0; + + if(sel_ch_ > n_channels_) { LOG(WARNING) << "Invalid RF channel selection"; } + if(n_channels_ > 1) + { + for(unsigned int i = 0; i < (n_channels_ - 1); i++) + { + null_sinks_.push_back(gr::blocks::null_sink::make(item_size_)); + } + DLOG(INFO)<< "NUMBER OF NULL SINKS = " << null_sinks_.size(); + } + try + { + file_source_ = gr::blocks::file_source::make(item_size_, filename_.c_str(), repeat_); + file_source_->seek(bytes_seek / item_size_, SEEK_SET); + unpack_spir_ = make_unpack_spir_gss6450_samples(adc_bits_); + deint_ = gr::blocks::deinterleave::make(item_size_); + } + catch (const std::exception &e) + { + std::cerr + << "The receiver was configured to work with a file signal source " + << std::endl + << "but the specified file is unreachable by GNSS-SDR." + << std::endl + << "Please modify your configuration file" + << std::endl + << "and point SignalSource.filename to a valid raw data file. Then:" + << std::endl + << "$ gnss-sdr --config_file=/path/to/my_GNSS_SDR_configuration.conf" + << std::endl + << "Examples of configuration files available at:" + << std::endl + << GNSSSDR_INSTALL_DIR "/share/gnss-sdr/conf/" + << std::endl; + + LOG(WARNING) << "file_signal_source: Unable to open the samples file " + << filename_.c_str() << ", exiting the program."; + throw(e); + } + DLOG(INFO) << "file_source(" << file_source_->unique_id() << ")"; + + if(samples_ == 0) // read all file + { + /*! + * BUG workaround: The GNU Radio file source does not stop the receiver after reaching the End of File. + * A possible solution is to compute the file length in samples using file size, excluding the last 2 milliseconds, and enable always the + * valve block + */ + std::ifstream file (filename_.c_str(), std::ios::in | std::ios::binary | std::ios::ate); + std::ifstream::pos_type size; + + if (file.is_open()) + { + size = file.tellg(); + LOG(INFO) << "Total samples in the file= " << floor(static_cast(size) / static_cast(item_size_)); + } + else + { + std::cout << "file_signal_source: Unable to open the samples file " << filename_.c_str() << std::endl; + LOG(ERROR) << "file_signal_source: Unable to open the samples file " << filename_.c_str(); + } + std::streamsize ss = std::cout.precision(); + std::cout << std::setprecision(16); + std::cout << "Processing file " << filename_ << ", which contains " << size << " [bytes]" << std::endl; + std::cout.precision (ss); + + if(size > 0) + { + samples_ = static_cast(floor(static_cast(static_cast(size) - static_cast(bytes_seek)) / (sample_size_byte * static_cast(n_channels_)))); + samples_ = samples_- static_cast(ceil(0.002 * sampling_frequency_)); //process all the samples available in the file excluding the last 2 ms + } + } + + CHECK(samples_ > 0) << "File does not contain enough samples to process."; + double signal_duration_s = static_cast(samples_) / sampling_frequency_; + LOG(INFO) << "Total number samples to be processed= " << samples_ << " GNSS signal duration= " << signal_duration_s << " [s]"; + std::cout << "GNSS signal recorded time to be processed: " << signal_duration_s << " [s]" << std::endl; + + valve_ = gnss_sdr_make_valve(sizeof(gr_complex), samples_, queue_); + DLOG(INFO) << "valve(" << valve_->unique_id() << ")"; + + if (dump_) + { + sink_ = gr::blocks::file_sink::make(sizeof(gr_complex), dump_filename_.c_str()); + DLOG(INFO) << "file_sink(" << sink_->unique_id() << ")"; + } + if (enable_throttle_control_) + { + throttle_ = gr::blocks::throttle::make(sizeof(gr_complex), sampling_frequency_); + } + if (endian_swap_) + { + endian_ = gr::blocks::endian_swap::make(item_size_); + } + DLOG(INFO) << "File source filename " << filename_; + DLOG(INFO) << "Samples " << samples_; + DLOG(INFO) << "Sampling frequency " << sampling_frequency_; + DLOG(INFO) << "Item type " << item_type_; + DLOG(INFO) << "Item size " << item_size_; + DLOG(INFO) << "Repeat " << repeat_; + DLOG(INFO) << "Dump " << dump_; + DLOG(INFO) << "Dump filename " << dump_filename_; +} + + +SpirGSS6450FileSignalSource::~SpirGSS6450FileSignalSource() +{} + + +void SpirGSS6450FileSignalSource::connect(gr::top_block_sptr top_block) +{ + if (samples_ > 0) + { + top_block->connect(file_source_, 0, deint_, 0); + if(endian_swap_) + { + top_block->connect(deint_, sel_ch_ - 1, endian_ ,0); + top_block->connect(endian_, 0, unpack_spir_, 0); + } + else + { + top_block->connect(deint_, sel_ch_ - 1, unpack_spir_, 0); + } + if(n_channels_ > 1) + { + unsigned int aux = 0; + for(unsigned int i = 0; i < n_channels_; i++) + { + if(i != (sel_ch_ - 1)) + { + top_block->connect(deint_, i, null_sinks_.at(aux), 0); + aux++; + } + } + } + if (enable_throttle_control_) + { + top_block->connect(unpack_spir_, 0, throttle_, 0); + top_block->connect(throttle_, 0, valve_, 0); + } + else + { + top_block->connect(unpack_spir_, 0, valve_, 0); + } + if(dump_) + { + top_block->connect(valve_, 0, sink_, 0); + } + } + else + { + LOG(WARNING) << "0 samples to read"; + } +} + + +void SpirGSS6450FileSignalSource::disconnect(gr::top_block_sptr top_block) +{ + if (samples_ > 0) + { + top_block->disconnect(file_source_, 0, deint_, 0); + if(endian_swap_) + { + top_block->disconnect(deint_, sel_ch_ - 1, endian_ ,0); + top_block->disconnect(endian_, 0, unpack_spir_, 0); + } + else + { + top_block->disconnect(deint_, sel_ch_ - 1, unpack_spir_, 0); + } + if(n_channels_ > 1) + { + unsigned int aux = 0; + for(unsigned int i = 0; i < n_channels_; i++) + { + if(i != (sel_ch_ - 1)) + { + top_block->disconnect(deint_, i, null_sinks_.at(aux), 0); + aux++; + } + } + } + if (enable_throttle_control_) + { + top_block->disconnect(unpack_spir_, 0, throttle_, 0); + top_block->disconnect(throttle_, 0, valve_, 0); + } + else + { + top_block->disconnect(unpack_spir_, 0, valve_, 0); + } + if(dump_) + { + top_block->disconnect(valve_, 0, sink_, 0); + } + } + else + { + LOG(WARNING) << "Nothing to disconnect"; + } +} + + +gr::basic_block_sptr SpirGSS6450FileSignalSource::get_left_block() +{ + LOG(WARNING) << "Left block of a signal source should not be retrieved"; + return gr::blocks::file_source::sptr(); +} + + +gr::basic_block_sptr SpirGSS6450FileSignalSource::get_right_block() +{ + if(samples_ > 0) { return valve_; } + else + { + if(enable_throttle_control_) { return throttle_; } + else { return unpack_spir_; } + } +} diff --git a/src/algorithms/signal_source/adapters/spir_gss6450_file_signal_source.h b/src/algorithms/signal_source/adapters/spir_gss6450_file_signal_source.h new file mode 100644 index 000000000..caa26c8fb --- /dev/null +++ b/src/algorithms/signal_source/adapters/spir_gss6450_file_signal_source.h @@ -0,0 +1,137 @@ +/*! + * \file spir_gss6450_file_signal_source.h + * \brief Implementation of a class that reads signals samples from a SPIR file + * and adapts it to a SignalSourceInterface. + * \author Antonio Ramos, 2017 antonio.ramos(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is not 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 . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_SPIR_GSS6450_FILE_SIGNAL_SOURCE_H_ +#define GNSS_SDR_SPIR_GSS6450_FILE_SIGNAL_SOURCE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gnss_block_interface.h" +#include "gnss_sdr_valve.h" +#include "unpack_spir_gss6450_samples.h" + + +class ConfigurationInterface; + +/*! + * \brief Class that reads signals samples from a file + * and adapts it to a SignalSourceInterface + */ +class SpirGSS6450FileSignalSource: public GNSSBlockInterface +{ +public: + SpirGSS6450FileSignalSource(ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams, gr::msg_queue::sptr queue); + + virtual ~SpirGSS6450FileSignalSource(); + inline std::string role() override + { + return role_; + } + + inline std::string implementation() override + { + return "Spir_GSS6450_File_Signal_Source"; + } + + 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; + + inline std::string filename() const + { + return filename_; + } + + inline std::string item_type() const + { + return item_type_; + } + + inline bool repeat() const + { + return repeat_; + } + + inline long sampling_frequency() const + { + return sampling_frequency_; + } + + inline long samples() const + { + return samples_; + } + +private: + unsigned long long samples_; + double sampling_frequency_; + std::string filename_; + bool repeat_; + bool dump_; //Enables dumping the gr_complex sample output + bool enable_throttle_control_; + bool endian_swap_; + std::string dump_filename_; + std::string role_; + std::string item_type_; + unsigned int in_streams_; + unsigned int out_streams_; + unsigned int adc_bits_; + unsigned int n_channels_; + unsigned int sel_ch_; + gr::blocks::file_source::sptr file_source_; + gr::blocks::deinterleave::sptr deint_; + gr::blocks::endian_swap::sptr endian_; + std::vector null_sinks_; + unpack_spir_gss6450_samples_sptr unpack_spir_; + boost::shared_ptr valve_; + gr::blocks::file_sink::sptr sink_; + gr::blocks::throttle::sptr throttle_; + gr::msg_queue::sptr queue_; + size_t item_size_; +}; + +#endif /*GNSS_SDR_SPIR_GSS6450_FILE_SIGNAL_SOURCE_H_*/ diff --git a/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt b/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt index 4159321f3..a9252edb0 100644 --- a/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt @@ -23,6 +23,8 @@ set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES unpack_intspir_1bit_samples.cc rtl_tcp_signal_source_c.cc unpack_2bit_samples.cc + unpack_spir_gss6450_samples.cc + labsat23_source.cc ) include_directories( diff --git a/src/algorithms/signal_source/gnuradio_blocks/labsat23_source.cc b/src/algorithms/signal_source/gnuradio_blocks/labsat23_source.cc new file mode 100644 index 000000000..fe9a9c4f7 --- /dev/null +++ b/src/algorithms/signal_source/gnuradio_blocks/labsat23_source.cc @@ -0,0 +1,497 @@ +/*! + * \file labsat23_source.cc + * + * \brief Unpacks the Labsat 2 (ls2) and (ls3) capture files + * \author Javier Arribas jarribas (at) cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) + * ------------------------------------------------------------------------- + * + * 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 . + * + * ------------------------------------------------------------------------- + */ + + +#include "labsat23_source.h" +#include +#include + + +labsat23_source_sptr labsat23_make_source(const char *signal_file_basename, int channel_selector) +{ + return labsat23_source_sptr(new labsat23_source(signal_file_basename, channel_selector)); +} + + +std::string labsat23_source::generate_filename() +{ + std::ostringstream ss; + ss << std::setw(4) << std::setfill('0') << d_current_file_number; + return d_signal_file_basename + "_" + ss.str()+".LS3"; +} + + +labsat23_source::labsat23_source(const char *signal_file_basename, int channel_selector) : gr::block("labsat23_source", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(1, 1, sizeof(gr_complex))) +{ + if (channel_selector < 1 or channel_selector > 2) + { + std::cout << "Labsat source config error: channel selection out of bounds, check gnss-sdr config file" << std::endl; + exit(1); + } + d_channel_selector_config = channel_selector; + d_header_parsed = false; + d_bits_per_sample = 0; + d_current_file_number = 0; + d_labsat_version = 0; + d_ref_clock = 0; + d_channel_selector = 0; + d_signal_file_basename = std::string(signal_file_basename); + + std::string signal_file; + this->set_output_multiple(8); + signal_file = generate_filename(); + binary_input_file = new std::ifstream (signal_file.c_str(), std::ios::in|std::ios::binary); + + if (binary_input_file->is_open()) + { + std::cout << "Labsat file source is reading samples from " << signal_file << std::endl; + } + else + { + std::cout << "Labsat file " << signal_file << " could not be opened!" << std::endl; + delete binary_input_file; + exit(1); + } +} + + +labsat23_source::~labsat23_source() +{ + if (binary_input_file->is_open()) + { + binary_input_file->close(); + } + delete binary_input_file; +} + + +int labsat23_source::getBit(uint8_t byte, int position) +{ + return (byte >> position) & 0x01; +} + + +void labsat23_source::decode_samples_one_channel(int16_t input_short, gr_complex* out, int type) +{ + std::bitset<16> bs(input_short); + switch(type) + { + case 2: + //two bits per sample, 8 samples per int16 + for (int i = 0; i < 8; i++) + { + out[i] = gr_complex(static_cast(bs[15-(2*i)]), + static_cast(bs[14-(2*i)])); + out[i] = out[i]*gr_complex(2,0)-gr_complex(1,1); + } + break; + case 4: + //four bits per sample, 4 samples per int16 + for (int i = 0; i < 4; i++) + { + out[i] = gr_complex(0.0,0.0); + //In-Phase + if (bs[15-4*i]) + { + if (bs[13-4*i]) //11 + { + out[i] += gr_complex(-1,0); + } + else //10 + { + out[i] += gr_complex(-2,0); + } + } + else + { + if (bs[13-4*i]) //01 + { + out[i] += gr_complex(1,0); + } + } + + //Quadrature + if (bs[14-4*i]) + { + if (bs[12-4*i]) //11 + { + out[i] += gr_complex(0,-1); + } + else //10 + { + out[i] += gr_complex(0,-2); + } + } + else + { + if (bs[12-4*i]) //01 + { + out[i] += gr_complex(0,1); + } + } + out[i] += gr_complex(0.5,0.5); + } + break; + } +} + + +int labsat23_source::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) +{ + gr_complex *out = reinterpret_cast(output_items[0]); + + if (d_header_parsed == false) + { + if (binary_input_file->eof() == false) + { + char memblock[1024]; + binary_input_file->read(memblock, 1024); + //parse Labsat header + //check preamble + int byte_counter = 0; + bool preamble_ok = true; + for (int i = 0; i < 8; i++) + { + if (memblock[byte_counter] != 0x00) preamble_ok = false; + //std::cout << "H[" << i << "]:" << (int)memblock[byte_counter] << std::endl; + byte_counter++; + } + + if (preamble_ok == false) + { + std::cout << "Labsat source do not detect the preamble in the selected file" << std::endl; + return -1; + } + + // check Labsat version + if (memblock[byte_counter] == 0x4C and memblock[byte_counter+1] == 0x53 and memblock[byte_counter+2] == 0x32) + { + d_labsat_version = 2; + std::cout << "Labsat file version 2 detected" << std::endl; + } + + if (memblock[byte_counter] == 0x4C and memblock[byte_counter+1] == 0x53 and memblock[byte_counter+2] == 0x33) + { + d_labsat_version = 3; + std::cout << "Labsat file version 3 detected" << std::endl; + } + + if (d_labsat_version == 0) + { + std::cout << "Labsat source do not detect the labsat version in file header" << std::endl; + return -1; + } + + byte_counter += 3; + + int sub_version = static_cast(memblock[byte_counter]); + + std::cout << "Labsat file sub version " << sub_version << std::endl; + + byte_counter++; + + int header_bytes = 0; + header_bytes += memblock[byte_counter] | (memblock[byte_counter+1] << 8) | (memblock[byte_counter+2] << 16) | (memblock[byte_counter+3] << 24); + + byte_counter += 4; + //std::cout << "header_bytes=" << header_bytes << std::endl; + + // read first section + // section ID (little-endian) + uint8_t section_id = static_cast(memblock[byte_counter]) + static_cast(memblock[byte_counter+1]) * 256; + //std::cout << "Section ID: " << (int)section_id << std::endl; + byte_counter += 2; + + uint8_t section_lenght_bytes = 0; + section_lenght_bytes += memblock[byte_counter] | (memblock[byte_counter+1] << 8) | (memblock[byte_counter+2] << 16) | (memblock[byte_counter+3] << 24); + //std::cout << "section_lenght_bytes=" << (int)section_lenght_bytes << std::endl; + + byte_counter += 4; + if (section_id == 2) + { + d_ref_clock = static_cast(memblock[byte_counter]); + switch(d_ref_clock) + { + case 0: + std::cout << "Labsat reference clock: internal OXCO" << std::endl; + break; + case 1: + std::cout << "Labsat reference clock: internal TXCO" << std::endl; + break; + case 2: + std::cout << "Labsat reference clock: external 10 MHz" << std::endl; + break; + case 3: + std::cout << "Labsat reference clock: external 16.386 MHz" << std::endl; + break; + default: + std::cout << "Labsat Unknown reference clock ID " << static_cast(d_ref_clock) << std::endl; + } + byte_counter++; + d_bits_per_sample = static_cast(memblock[byte_counter]); + switch(d_bits_per_sample) + { + case 2: + std::cout << "Labsat is using 2 bits per sample" << std::endl; + break; + case 4: + std::cout << "Labsat is using 4 bits per sample" << std::endl; + break; + default: + std::cout << "Labsat Unknown bits per sample ID " << static_cast(d_bits_per_sample) << std::endl; + return -1; + } + + byte_counter++; + d_channel_selector = static_cast(memblock[byte_counter]); + switch(d_channel_selector) + { + case 0: + std::cout << "Available channels: Channel A + B, 1 bit quantisation" << std::endl; + break; + case 1: + std::cout << "Available channels: Channel A, 1 bit quantisation" << std::endl; + break; + case 2: + std::cout << "Available channels: Channel B, 1 bit quantisation" << std::endl; + break; + case 3: + std::cout << "Available channels: Channel A, 2 bit quantisation" << std::endl; + break; + case 4: + std::cout << "Available channels: Channel B, 2 bit quantisation" << std::endl; + break; + default: + std::cout << "Unknown channel selection ID " << static_cast(d_channel_selector) << std::endl; + return -1; + } + + //check if the selected channel in config file match the file encoding + if (d_channel_selector_config == 2 and d_channel_selector != 0) + { + std::cout << "Labsat source channel config inconsistency: channel 2 is selected but the file has only one channel" << std::endl; + return -1; + } + + //todo: Add support for dual channel files + if (d_channel_selector == 0) + { + std::cout << "ERROR: Labsat file contains more than one channel and it is not currently supported by Labsat signal source." << std::endl; + return -1; + } + byte_counter++; + uint8_t quantization = static_cast(memblock[byte_counter]); + switch(quantization) + { + case 1: + std::cout << "1 bit per sample" << std::endl; + break; + case 2: + std::cout << "2 bit per sample" << std::endl; + break; + default: + std::cout << "Unknown quantization ID " << static_cast(quantization) << std::endl; + } + byte_counter++; + uint8_t channel_a_constellation = static_cast(memblock[byte_counter]); + switch(channel_a_constellation) + { + case 0: + std::cout << "Labsat Channel A is GPS" << std::endl; + break; + case 1: + std::cout << "Labsat Channel A is GLONASS" << std::endl; + break; + case 2: + std::cout << "Labsat Channel A is BDS" << std::endl; + break; + default: + std::cout << "Unknown channel A constellation ID " << static_cast(channel_a_constellation) << std::endl; + } + byte_counter++; + uint8_t channel_b_constellation = static_cast(memblock[byte_counter]); + switch(channel_b_constellation) + { + case 0: + std::cout << "Labsat Channel B is GPS" << std::endl; + break; + case 1: + std::cout << "Labsat Channel B is GLONASS" << std::endl; + break; + case 2: + std::cout << "Labsat Channel B is BDS" << std::endl; + break; + default: + std::cout << "Unknown channel B constellation ID " << static_cast(channel_b_constellation) << std::endl; + } + + //end of header + d_header_parsed = true; + //seek file to the first signal sample + binary_input_file->clear(); + binary_input_file->seekg(header_bytes, binary_input_file->beg); + return 0; + } + else + { + std::cout << "Labsat file header error: section 2 is not available." << std::endl; + return -1; + } + } + else + { + std::cout << "Labsat file read error: file is empty." << std::endl; + return -1; + } + } + else + { + //ready to start reading samples + switch(d_bits_per_sample) + { + case 2: + { + switch(d_channel_selector) + { + case 0: + // dual channel 2 bits per complex sample + break; + default: + //single channel 2 bits per complex sample (1 bit I + 1 bit Q, 8 samples per int16) + int n_int16_to_read = noutput_items / 8; + if (n_int16_to_read > 0) + { + int16_t memblock[n_int16_to_read]; + binary_input_file->read(reinterpret_cast(memblock), n_int16_to_read * 2); + n_int16_to_read = binary_input_file->gcount() / 2; //from bytes to int16 + if (n_int16_to_read > 0) + { + int output_pointer = 0; + for (int i = 0; i < n_int16_to_read; i++) + { + decode_samples_one_channel(memblock[i], &out[output_pointer], d_bits_per_sample); + output_pointer += 8; + } + return output_pointer; + } + else + { + //trigger the read of the next file in the sequence + std::cout << "End of current file, reading the next Labsat file in sequence: " << generate_filename() << std::endl; + + d_current_file_number++; + binary_input_file->close(); + binary_input_file->open(generate_filename().c_str(), std::ios::in|std::ios::binary); + if (binary_input_file->is_open()) + { + std::cout << "Labsat file source is reading samples from " << generate_filename() << std::endl; + } + else + { + std::cout << "Last file reached, LabSat source stop" << std::endl; + return -1; + } + } + } + else + { + return 0; + } + }; + break; + } + case 4: + { + switch(d_channel_selector) + { + case 0: + // dual channel + break; + default: + //single channel 4 bits per complex sample (2 bit I + 2 bit Q, 4 samples per int16) + int n_int16_to_read = noutput_items / 4; + if (n_int16_to_read > 0) + { + int16_t memblock[n_int16_to_read]; + binary_input_file->read(reinterpret_cast(memblock), n_int16_to_read * 2); + n_int16_to_read = binary_input_file->gcount() / 2; //from bytes to int16 + if (n_int16_to_read > 0) + { + int output_pointer = 0; + for (int i = 0; i < n_int16_to_read; i++) + { + decode_samples_one_channel(memblock[i], &out[output_pointer], d_bits_per_sample); + output_pointer += 4; + } + return output_pointer; + } + else + { + //trigger the read of the next file in the sequence + std::cout << "End of current file, reading the next Labsat file in sequence: " << generate_filename() << std::endl; + + d_current_file_number++; + binary_input_file->close(); + binary_input_file->open(generate_filename().c_str(), std::ios::in|std::ios::binary); + if (binary_input_file->is_open()) + { + std::cout << "Labsat file source is reading samples from " << generate_filename() << std::endl; + } + else + { + std::cout << "Last file reached, LabSat source stop" << std::endl; + return -1; + } + } + } + else + { + return 0; + } + } + break; + } + default: + { + return -1; + } + } + } + std::cout << "Warning!!" << std::endl; + return 0; +} diff --git a/src/algorithms/signal_source/gnuradio_blocks/labsat23_source.h b/src/algorithms/signal_source/gnuradio_blocks/labsat23_source.h new file mode 100644 index 000000000..ffc1b440b --- /dev/null +++ b/src/algorithms/signal_source/gnuradio_blocks/labsat23_source.h @@ -0,0 +1,75 @@ +/*! + * \file labsat23_source.h + * + * \brief Unpacks the Labsat 2 (ls2) and (ls3) capture files + * \author Javier Arribas jarribas (at) cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_LABSAT23_SOURCE_H +#define GNSS_SDR_LABSAT23_SOURCE_H + +#include +#include +#include +#include +#include + +class labsat23_source; + +typedef boost::shared_ptr labsat23_source_sptr; + +labsat23_source_sptr labsat23_make_source(const char *signal_file_basename, int channel_selector); + +/*! + * \brief This class implements conversion between Labsat2 and 3 format byte packet samples to gr_complex + */ +class labsat23_source: public gr::block +{ +private: + friend labsat23_source_sptr labsat23_make_source_sptr(const char *signal_file_basename, int channel_selector); + std::string generate_filename(); + void decode_samples_one_channel(int16_t input_short, gr_complex* out, int type); + int getBit(uint8_t byte, int position); + bool d_header_parsed; + uint8_t d_channel_selector; + int d_channel_selector_config; + int d_current_file_number; + uint8_t d_labsat_version; + std::string d_signal_file_basename; + std::ifstream *binary_input_file; + uint8_t d_ref_clock; + uint8_t d_bits_per_sample; + +public: + labsat23_source(const char *signal_file_basename, int channel_selector); + ~labsat23_source(); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/src/algorithms/signal_source/gnuradio_blocks/unpack_spir_gss6450_samples.cc b/src/algorithms/signal_source/gnuradio_blocks/unpack_spir_gss6450_samples.cc new file mode 100644 index 000000000..6a7bf869a --- /dev/null +++ b/src/algorithms/signal_source/gnuradio_blocks/unpack_spir_gss6450_samples.cc @@ -0,0 +1,106 @@ +/*! + * \file unpack_spir_gss6450_samples.cc + * + * \brief Unpacks SPIR int samples + * \author Antonio Ramos, antonio(at)cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is not 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 . + * + * ------------------------------------------------------------------------- + */ + + +#include "unpack_spir_gss6450_samples.h" +#include + + + +unpack_spir_gss6450_samples_sptr make_unpack_spir_gss6450_samples(unsigned int adc_nbit) +{ + return unpack_spir_gss6450_samples_sptr(new unpack_spir_gss6450_samples(adc_nbit)); +} + + +unpack_spir_gss6450_samples::unpack_spir_gss6450_samples(unsigned int adc_nbit) : gr::sync_interpolator("unpack_spir_gss6450_samples", + gr::io_signature::make(1, 1, sizeof(int)), + gr::io_signature::make(1, 1, sizeof(gr_complex)), 16 / adc_nbit) +{ + adc_bits = adc_nbit; + i_data = 0; + q_data = 0; + samples_per_int = 16 / adc_bits; + if(adc_bits == 2) + { + mask_data = 0x00000003; + map_ = {0, 1, -2, -1}; + } + else + { + mask_data = 0x0000000F; + map_ = {0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}; + } +} + + +unpack_spir_gss6450_samples::~unpack_spir_gss6450_samples() +{} + +void unpack_spir_gss6450_samples::process_sample(gr_complex& out) +{ + out = gr_complex(0.5, 0.5); + compute_two_complement(i_data); + compute_two_complement(q_data); + out += gr_complex(static_cast(i_data), static_cast(q_data)); +} + + +int unpack_spir_gss6450_samples::work(int noutput_items, + gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) +{ + const int* in = reinterpret_cast(input_items[0]); + gr_complex* out = reinterpret_cast(output_items[0]); + unsigned int n_sample = 0; + unsigned int in_counter = 0; + for(int i = 0; i < noutput_items; i++) + { + int sample_aux = in[in_counter]; + int aux_i = sample_aux; + int aux_q = sample_aux; + int i_shift = adc_bits * 2 * (samples_per_int - n_sample - 1) + adc_bits; + int q_shift = adc_bits * 2 * (samples_per_int - n_sample - 1); + i_data = (aux_i >> i_shift) & mask_data; + q_data = (aux_q >> q_shift) & mask_data; + process_sample(out[samples_per_int * in_counter + samples_per_int - n_sample - 1]); + n_sample++; + if(n_sample == samples_per_int) + { + n_sample = 0; + in_counter++; + } + } + return noutput_items; +} + +void unpack_spir_gss6450_samples::compute_two_complement(int& data) +{ + data = map_[data]; +} diff --git a/src/algorithms/signal_source/gnuradio_blocks/unpack_spir_gss6450_samples.h b/src/algorithms/signal_source/gnuradio_blocks/unpack_spir_gss6450_samples.h new file mode 100644 index 000000000..25db1a9d6 --- /dev/null +++ b/src/algorithms/signal_source/gnuradio_blocks/unpack_spir_gss6450_samples.h @@ -0,0 +1,64 @@ +/*! + * \file unpack_spir_gss6450_samples.h + * + * \brief Unpacks SPIR int samples + * \author Antonio Ramos, antonio.ramos(at)cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is not 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 . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_UNPACK_SPIR_GSS6450_SAMPLES_H +#define GNSS_SDR_UNPACK_SPIR_GSS6450_SAMPLES_H + +#include +#include + +class unpack_spir_gss6450_samples; + +typedef boost::shared_ptr unpack_spir_gss6450_samples_sptr; + +unpack_spir_gss6450_samples_sptr make_unpack_spir_gss6450_samples(unsigned int adc_nbit); + + +class unpack_spir_gss6450_samples: public gr::sync_interpolator +{ +public: + int work(int noutput_items, + gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + friend unpack_spir_gss6450_samples_sptr make_unpack_spir_gss6450_samples_sptr(unsigned int adc_nbit); + unpack_spir_gss6450_samples(unsigned int adc_nbit); + ~unpack_spir_gss6450_samples(); + +private: + unsigned int adc_bits; + unsigned int samples_per_int; + void process_sample(gr_complex& out); + void compute_two_complement(int& data); + int i_data; + int q_data; + int mask_data; + std::vector map_; +}; + +#endif diff --git a/src/algorithms/telemetry_decoder/adapters/CMakeLists.txt b/src/algorithms/telemetry_decoder/adapters/CMakeLists.txt index 41e9bffd1..cf09a7cde 100644 --- a/src/algorithms/telemetry_decoder/adapters/CMakeLists.txt +++ b/src/algorithms/telemetry_decoder/adapters/CMakeLists.txt @@ -16,9 +16,11 @@ # along with GNSS-SDR. If not, see . # + set(TELEMETRY_DECODER_ADAPTER_SOURCES gps_l1_ca_telemetry_decoder.cc gps_l2c_telemetry_decoder.cc + gps_l5_telemetry_decoder.cc galileo_e1b_telemetry_decoder.cc sbas_l1_telemetry_decoder.cc galileo_e5a_telemetry_decoder.cc diff --git a/src/algorithms/telemetry_decoder/adapters/gps_l5_telemetry_decoder.cc b/src/algorithms/telemetry_decoder/adapters/gps_l5_telemetry_decoder.cc new file mode 100644 index 000000000..fe4f356f1 --- /dev/null +++ b/src/algorithms/telemetry_decoder/adapters/gps_l5_telemetry_decoder.cc @@ -0,0 +1,99 @@ +/*! + * \file gps_l5_telemetry_decoder.cc + * \brief Implementation of an adapter of a GPS L5 NAV data decoder block + * to a TelemetryDecoderInterface + * \author Antonio Ramos, 2017. antonio.ramos(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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 . + * + * ------------------------------------------------------------------------- + */ + + +#include "gps_l5_telemetry_decoder.h" +#include +#include +#include "concurrent_queue.h" +#include "configuration_interface.h" + + +using google::LogMessage; + +GpsL5TelemetryDecoder::GpsL5TelemetryDecoder(ConfigurationInterface* configuration, + std::string role, + unsigned int in_streams, + unsigned int out_streams) : + role_(role), + in_streams_(in_streams), + out_streams_(out_streams) +{ + std::string default_dump_filename = "./navigation.dat"; + DLOG(INFO) << "role " << role; + dump_ = configuration->property(role + ".dump", false); + dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename); + // make telemetry decoder object + telemetry_decoder_ = gps_l5_make_telemetry_decoder_cc(satellite_, dump_); + DLOG(INFO) << "telemetry_decoder(" << telemetry_decoder_->unique_id() << ")"; + + LOG(INFO) << "global navigation message queue assigned to telemetry_decoder (" << telemetry_decoder_->unique_id() << ")" << "role " << role; + channel_ = 0; +} + + +GpsL5TelemetryDecoder::~GpsL5TelemetryDecoder() +{} + + +void GpsL5TelemetryDecoder::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 GpsL5TelemetryDecoder::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 GpsL5TelemetryDecoder::disconnect(gr::top_block_sptr top_block) +{ + if(top_block) { /* top_block is not null */}; + // Nothing to disconnect +} + + +gr::basic_block_sptr GpsL5TelemetryDecoder::get_left_block() +{ + return telemetry_decoder_; +} + + +gr::basic_block_sptr GpsL5TelemetryDecoder::get_right_block() +{ + return telemetry_decoder_; +} diff --git a/src/algorithms/telemetry_decoder/adapters/gps_l5_telemetry_decoder.h b/src/algorithms/telemetry_decoder/adapters/gps_l5_telemetry_decoder.h new file mode 100644 index 000000000..4041e253e --- /dev/null +++ b/src/algorithms/telemetry_decoder/adapters/gps_l5_telemetry_decoder.h @@ -0,0 +1,96 @@ +/*! + * \file gps_l5_telemetry_decoder.h + * \brief Interface of an adapter of a GPS L5 (CNAV) data decoder block + * to a TelemetryDecoderInterface + * \author Antonio Ramos, 2017. antonio.ramos(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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 . + * + * ------------------------------------------------------------------------- + */ + + +#ifndef GNSS_SDR_GPS_L5_TELEMETRY_DECODER_H_ +#define GNSS_SDR_GPS_L5_TELEMETRY_DECODER_H_ + +#include +#include "telemetry_decoder_interface.h" +#include "gps_l5_telemetry_decoder_cc.h" +#include "gnss_satellite.h" + + +class ConfigurationInterface; + +/*! + * \brief This class implements a NAV data decoder for GPS L5 + */ +class GpsL5TelemetryDecoder : public TelemetryDecoderInterface +{ +public: + GpsL5TelemetryDecoder(ConfigurationInterface* configuration, + std::string role, + unsigned int in_streams, + unsigned int out_streams); + + virtual ~GpsL5TelemetryDecoder(); + + inline std::string role() override + { + return role_; + } + + //! Returns "GPS_L5_Telemetry_Decoder" + inline std::string implementation() override + { + return "GPS_L5_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: + gps_l5_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 diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/CMakeLists.txt b/src/algorithms/telemetry_decoder/gnuradio_blocks/CMakeLists.txt index 043440927..29e83b79c 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/CMakeLists.txt @@ -19,6 +19,7 @@ set(TELEMETRY_DECODER_GR_BLOCKS_SOURCES gps_l1_ca_telemetry_decoder_cc.cc gps_l2c_telemetry_decoder_cc.cc + gps_l5_telemetry_decoder_cc.cc galileo_e1b_telemetry_decoder_cc.cc sbas_l1_telemetry_decoder_cc.cc galileo_e5a_telemetry_decoder_cc.cc diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.cc index a058f169b..d390ee7ee 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.cc @@ -297,14 +297,8 @@ int galileo_e5a_telemetry_decoder_cc::general_work (int noutput_items __attribut d_symbol_counter = 0; flag_bit_start = true; corr_value = 0; - while(d_preamble_init.size() > 0) - { //Clear preamble correlating queue - d_preamble_init.pop_front(); - } - while(d_symbol_history.size() > 0) - { //Clear symbol queue in order to prevent possible symbol discontinuities - d_symbol_history.pop_front(); - } + d_preamble_init.clear(); + d_symbol_history.clear(); LOG(INFO) << "Bit start sync for Galileo E5a satellite " << d_satellite; } else diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/glonass_l1_ca_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/glonass_l1_ca_telemetry_decoder_cc.cc index 846b3cd26..a2a7b70ad 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/glonass_l1_ca_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/glonass_l1_ca_telemetry_decoder_cc.cc @@ -32,15 +32,9 @@ #include "glonass_l1_ca_telemetry_decoder_cc.h" -#include -#include -#include #include #include #include -#include "control_message_factory.h" -#include "gnss_synchro.h" -#include "convolutional.h" #define CRC_ERROR_LIMIT 6 @@ -78,10 +72,10 @@ glonass_l1_ca_telemetry_decoder_cc::glonass_l1_ca_telemetry_decoder_cc( // Since preamble rate is different than navigation data rate we use a constant d_symbols_per_preamble = GLONASS_GNAV_PREAMBLE_LENGTH_SYMBOLS; - memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, GLONASS_GNAV_PREAMBLE_LENGTH_BITS*sizeof(unsigned short int)); + memcpy(static_cast(this->d_preambles_bits), static_cast(preambles_bits), GLONASS_GNAV_PREAMBLE_LENGTH_BITS * sizeof(unsigned short int)); // preamble bits to sampled symbols - d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * d_symbols_per_preamble); + d_preambles_symbols = static_cast(malloc(sizeof(signed int) * d_symbols_per_preamble)); int n = 0; for (int i = 0; i < GLONASS_GNAV_PREAMBLE_LENGTH_BITS; i++) { @@ -150,39 +144,39 @@ void glonass_l1_ca_telemetry_decoder_cc::decode_string(double *frame_symbols,int chip_acc_counter += 1; if(chip_acc_counter == (GLONASS_GNAV_TELEMETRY_SYMBOLS_PER_BIT)) - { - if (chip_acc > 0) - { - bi_binary_code.push_back('1'); - chip_acc_counter = 0; - chip_acc = 0; - } - else - { - bi_binary_code.push_back('0'); - chip_acc_counter = 0; - chip_acc = 0; - } - } + { + if (chip_acc > 0) + { + bi_binary_code.push_back('1'); + chip_acc_counter = 0; + chip_acc = 0; + } + else + { + bi_binary_code.push_back('0'); + chip_acc_counter = 0; + chip_acc = 0; + } + } } // Convert from bi-binary code to relative code for(int i = 0; i < (GLONASS_GNAV_STRING_BITS); i++) { if(bi_binary_code[2*i] == '1' && bi_binary_code[2*i + 1] == '0') - { - relative_code.push_back('1'); - } + { + relative_code.push_back('1'); + } else - { - relative_code.push_back('0'); - } + { + relative_code.push_back('0'); + } } // Convert from relative code to data bits data_bits.push_back('0'); for(int i = 1; i < (GLONASS_GNAV_STRING_BITS); i++) - { - data_bits.push_back(((relative_code[i-1]-'0') ^ (relative_code[i]-'0')) + '0'); - } + { + data_bits.push_back(((relative_code[i-1]-'0') ^ (relative_code[i]-'0')) + '0'); + } // 2. Call the GLONASS GNAV string decoder d_nav.string_decoder(data_bits); @@ -204,7 +198,6 @@ void glonass_l1_ca_telemetry_decoder_cc::decode_string(double *frame_symbols,int std::shared_ptr tmp_obj = std::make_shared(d_nav.get_ephemeris()); this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj)); LOG(INFO) << "GLONASS GNAV Ephemeris have been received on channel" << d_channel << " from satellite " << d_satellite; - } if (d_nav.have_new_utc_model() == true) { @@ -237,8 +230,8 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attrib int corr_value = 0; int preamble_diff = 0; - Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; - const Gnss_Synchro **in = (const Gnss_Synchro **) &input_items[0]; //Get the input samples pointer + Gnss_Synchro **out = reinterpret_cast(&output_items[0]); // Get the output buffer pointer + const Gnss_Synchro **in = reinterpret_cast(&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 @@ -248,23 +241,23 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attrib consume_each(1); d_flag_preamble = false; - unsigned int required_symbols=GLONASS_GNAV_STRING_SYMBOLS; + unsigned int required_symbols = GLONASS_GNAV_STRING_SYMBOLS; if (d_symbol_history.size()>required_symbols) - { - //******* preamble correlation ******** - for (int i = 0; i < d_symbols_per_preamble; i++) - { - if (d_symbol_history.at(i).Prompt_I < 0) // symbols clipping - { - corr_value -= d_preambles_symbols[i]; - } - else - { - corr_value += d_preambles_symbols[i]; - } - } - } + { + //******* preamble correlation ******** + for (int i = 0; i < d_symbols_per_preamble; i++) + { + if (d_symbol_history.at(i).Prompt_I < 0) // symbols clipping + { + corr_value -= d_preambles_symbols[i]; + } + else + { + corr_value += d_preambles_symbols[i]; + } + } + } //******* frame sync ****************** if (d_stat == 0) //no preamble information @@ -277,7 +270,6 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attrib // Enter into frame pre-detection status d_stat = 1; d_preamble_time_samples = d_symbol_history.at(0).Tracking_sample_counter; // record the preamble sample stamp - } } else if (d_stat == 1) // posible preamble lock @@ -295,8 +287,8 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attrib d_preamble_index = d_sample_counter; //record the preamble sample stamp d_stat = 2; // send asynchronous message to tracking to inform of frame sync and extend correlation time - pmt::pmt_t value = pmt::from_double(static_cast(d_preamble_time_samples) / static_cast(d_symbol_history.at(0).fs) - 0.001); - this->message_port_pub(pmt::mp("preamble_timestamp_s"), value); + pmt::pmt_t value = pmt::from_double(static_cast(d_preamble_time_samples) / static_cast(d_symbol_history.at(0).fs) - 0.001); + this->message_port_pub(pmt::mp("preamble_timestamp_s"), value); } else { @@ -310,7 +302,7 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attrib } else if (d_stat == 2) { - // FIXME: The preamble index marks the first symbol of the string count. Here I just wait for another full string to be received before processing + // FIXME: The preamble index marks the first symbol of the string count. Here I just wait for another full string to be received before processing if (d_sample_counter == d_preamble_index + GLONASS_GNAV_STRING_SYMBOLS) { // NEW GLONASS string received @@ -343,7 +335,7 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attrib { d_flag_frame_sync = true; DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at " - << d_symbol_history.at(0).Tracking_sample_counter << " [samples]"; + << d_symbol_history.at(0).Tracking_sample_counter << " [samples]"; } } else @@ -392,21 +384,21 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attrib current_symbol.PRN = this->d_satellite.get_PRN(); current_symbol.TOW_at_current_symbol_s = d_TOW_at_current_symbol; - current_symbol.TOW_at_current_symbol_s -=delta_t; //Galileo to GPS TOW + current_symbol.TOW_at_current_symbol_s -= delta_t; // Galileo to GPS TOW 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; - d_dump_file.write((char*)&tmp_double, sizeof(double)); - tmp_ulong_int = current_symbol.Tracking_sample_counter; - d_dump_file.write((char*)&tmp_ulong_int, sizeof(unsigned long int)); - tmp_double = 0; - d_dump_file.write((char*)&tmp_double, sizeof(double)); + double tmp_double; + unsigned long int tmp_ulong_int; + tmp_double = d_TOW_at_current_symbol; + d_dump_file.write(reinterpret_cast(&tmp_double), sizeof(double)); + tmp_ulong_int = current_symbol.Tracking_sample_counter; + d_dump_file.write(reinterpret_cast(&tmp_ulong_int), sizeof(unsigned long int)); + tmp_double = 0; + d_dump_file.write(reinterpret_cast(&tmp_double), sizeof(double)); } catch (const std::ifstream::failure & e) { @@ -416,9 +408,9 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attrib // remove used symbols from history if (d_symbol_history.size()>required_symbols) - { - d_symbol_history.pop_front(); - } + { + d_symbol_history.pop_front(); + } //3. Make the output (copy the object contents to the GNURadio reserved memory) *out[0] = current_symbol; @@ -454,7 +446,7 @@ void glonass_l1_ca_telemetry_decoder_cc::set_channel(int channel) } catch (const std::ifstream::failure& e) { - LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e.what(); + LOG(WARNING) << "channel " << d_channel << ": exception opening Glonass TLM dump file. " << e.what(); } } } diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc index 7ccb0c825..003bc8bd1 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc @@ -404,7 +404,7 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attribute_ void gps_l1_ca_telemetry_decoder_cc::set_satellite(const Gnss_Satellite & satellite) { d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); - LOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite; + DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite; d_GPS_FSM.i_satellite_PRN = d_satellite.get_PRN(); DLOG(INFO) << "Navigation Satellite set to " << d_satellite; } diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l2c_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l2c_telemetry_decoder_cc.cc index 693990124..01b4bed0b 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l2c_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l2c_telemetry_decoder_cc.cc @@ -154,7 +154,7 @@ int gps_l2c_telemetry_decoder_cc::general_work (int noutput_items __attribute__( //* The time of the last input symbol can be computed from the message ToW and //* delay by the formulae: //* \code - //* symbolTime_ms = msg->tow * 6000 + *pdelay * 20 + //* symbolTime_ms = msg->tow * 6000 + *pdelay * 20 + (12 * 20); 12 symbols of the encoder's transitory d_TOW_at_current_symbol = static_cast(msg.tow) * 6.0 + static_cast(delay) * GPS_L2_M_PERIOD + 12 * GPS_L2_M_PERIOD; d_TOW_at_current_symbol = floor(d_TOW_at_current_symbol * 1000.0) / 1000.0; d_flag_valid_word = true; @@ -170,12 +170,6 @@ int gps_l2c_telemetry_decoder_cc::general_work (int noutput_items __attribute__( current_synchro_data.TOW_at_current_symbol_s = d_TOW_at_current_symbol; current_synchro_data.Flag_valid_word = d_flag_valid_word; - // if (flag_PLL_180_deg_phase_locked == true) - // { - // //correct the accumulated phase for the Costas loop phase shift, if required - // current_synchro_data.Carrier_phase_rads += GPS_PI; - // } - if(d_dump == true) { // MULTIPLEXED FILE RECORDING - Record results to file @@ -192,7 +186,7 @@ int gps_l2c_telemetry_decoder_cc::general_work (int noutput_items __attribute__( } catch (const std::ifstream::failure & e) { - LOG(WARNING) << "Exception writing observables dump file " << e.what(); + LOG(WARNING) << "Exception writing Telemetry GPS L2 dump file " << e.what(); } } @@ -230,7 +224,7 @@ void gps_l2c_telemetry_decoder_cc::set_channel(int channel) } catch (const std::ifstream::failure &e) { - LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e.what(); + LOG(WARNING) << "channel " << d_channel << " Exception opening Telemetry GPS L2 dump file " << e.what(); } } } diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l5_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l5_telemetry_decoder_cc.cc new file mode 100644 index 000000000..2d604b221 --- /dev/null +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l5_telemetry_decoder_cc.cc @@ -0,0 +1,271 @@ +/*! + * \file gps_l5_telemetry_decoder_cc.cc + * \brief Implementation of a NAV message demodulator block based on + * Kay Borre book MATLAB-based GPS receiver + * \author Antonio Ramos, 2017. antonio.ramos(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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 . + * + * ------------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include +#include "gnss_synchro.h" +#include "gps_l5_telemetry_decoder_cc.h" +#include "gps_cnav_ephemeris.h" +#include "gps_cnav_iono.h" + +using google::LogMessage; + +gps_l5_telemetry_decoder_cc_sptr +gps_l5_make_telemetry_decoder_cc(const Gnss_Satellite & satellite, bool dump) +{ + return gps_l5_telemetry_decoder_cc_sptr(new gps_l5_telemetry_decoder_cc(satellite, dump)); +} + + +gps_l5_telemetry_decoder_cc::gps_l5_telemetry_decoder_cc( + const Gnss_Satellite & satellite, bool dump) : gr::block("gps_l5_telemetry_decoder_cc", + gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)), + gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) +{ + // Telemetry Bit transition synchronization port out + this->message_port_register_out(pmt::mp("preamble_timestamp_s")); + // 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()); + DLOG(INFO) << "GPS L5 TELEMETRY PROCESSING: satellite " << d_satellite; + d_channel = 0; + d_flag_valid_word = false; + d_TOW_at_current_symbol = 0.0; + d_TOW_at_Preamble = 0.0; + //initialize the CNAV frame decoder (libswiftcnav) + cnav_msg_decoder_init(&d_cnav_decoder); + for(int aux = 0; aux < GPS_L5_NH_CODE_LENGTH; aux++) + { + if(GPS_L5_NH_CODE[aux] == 0) + { + bits_NH[aux] = -1.0; + } + else + { + bits_NH[aux] = 1.0; + } + } + sync_NH = false; + new_sym = false; +} + + +gps_l5_telemetry_decoder_cc::~gps_l5_telemetry_decoder_cc() +{ + 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(); + } + } +} + + +int gps_l5_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) +{ + // get pointers on in- and output gnss-synchro objects + Gnss_Synchro *out = reinterpret_cast(output_items[0]); // Get the output buffer pointer + const Gnss_Synchro *in = reinterpret_cast(input_items[0]); // Get the input buffer pointer + + // UPDATE GNSS SYNCHRO DATA + Gnss_Synchro current_synchro_data; //structure to save the synchronization information and send the output object to the next block + //1. Copy the current tracking output + current_synchro_data = in[0]; + consume_each(1); //one by one + sym_hist.push_back(in[0].Prompt_I); + int corr_NH = 0; + int symbol_value = 0; + + //Search correlation with Neuman-Hofman Code (see IS-GPS-705D) + if(sym_hist.size() == GPS_L5_NH_CODE_LENGTH) + { + for(int i = 0; i < GPS_L5_NH_CODE_LENGTH; i++) + { + if((bits_NH[i] * sym_hist.at(i)) > 0.0) {corr_NH += 1;} + else {corr_NH -= 1;} + } + if(abs(corr_NH) == GPS_L5_NH_CODE_LENGTH) + { + sync_NH = true; + if(corr_NH > 0) {symbol_value = 1;} + else {symbol_value = -1;} + new_sym = true; + sym_hist.clear(); + } + else + { + sym_hist.pop_front(); + sync_NH = false; + new_sym = false; + } + } + + bool flag_new_cnav_frame = false; + cnav_msg_t msg; + u32 delay = 0; + + //add the symbol to the decoder + if(new_sym) + { + u8 symbol_clip = static_cast(symbol_value > 0) * 255; + flag_new_cnav_frame = cnav_msg_decoder_add_symbol(&d_cnav_decoder, symbol_clip, &msg, &delay); + new_sym = false; + } + //2. Add the telemetry decoder information + //check if new CNAV frame is available + if (flag_new_cnav_frame == true) + { + std::bitset raw_bits; + //Expand packet bits to bitsets. Notice the reverse order of the bits sequence, required by the CNAV message decoder + for (u32 i = 0; i < GPS_L5_CNAV_DATA_PAGE_BITS ; i++) + { + raw_bits[GPS_L5_CNAV_DATA_PAGE_BITS - 1 - i] = ((msg.raw_msg[i/8] >> (7 - i%8)) & 1u); + } + + d_CNAV_Message.decode_page(raw_bits); + + //Push the new navigation data to the queues + if (d_CNAV_Message.have_new_ephemeris() == true) + { + // get ephemeris object for this SV + std::shared_ptr tmp_obj = std::make_shared(d_CNAV_Message.get_ephemeris()); + std::cout << "New GPS L5 CNAV message received: ephemeris from satellite " << d_satellite << std::endl; + this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj)); + + } + if (d_CNAV_Message.have_new_iono() == true) + { + std::shared_ptr tmp_obj = std::make_shared(d_CNAV_Message.get_iono()); + std::cout << "New GPS L5 CNAV message received: iono model parameters from satellite " << d_satellite << std::endl; + this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj)); + } + + if (d_CNAV_Message.have_new_utc_model() == true) + { + std::shared_ptr tmp_obj = std::make_shared(d_CNAV_Message.get_utc_model()); + std::cout << "New GPS L5 CNAV message received: UTC model parameters from satellite " << d_satellite << std::endl; + this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj)); + } + + //update TOW at the preamble instant + d_TOW_at_Preamble = static_cast(msg.tow) * 6.0; + //* The time of the last input symbol can be computed from the message ToW and + //* delay by the formulae: + //* \code + //* symbolTime_ms = msg->tow * 6000 + *pdelay * 10 + (12 * 10); 12 symbols of the encoder's transitory + d_TOW_at_current_symbol = (static_cast(msg.tow) * 6.0) + (static_cast(delay) + 12.0) * GPS_L5i_SYMBOL_PERIOD; + d_TOW_at_current_symbol = floor(d_TOW_at_current_symbol * 1000.0) / 1000.0; + d_flag_valid_word = true; + } + else + { + d_TOW_at_current_symbol += GPS_L5i_PERIOD; + if (current_synchro_data.Flag_valid_symbol_output == false) + { + d_flag_valid_word = false; + } + } + current_synchro_data.TOW_at_current_symbol_s = d_TOW_at_current_symbol; + current_synchro_data.Flag_valid_word = d_flag_valid_word; + + 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; + d_dump_file.write(reinterpret_cast(&tmp_double), sizeof(double)); + tmp_ulong_int = current_synchro_data.Tracking_sample_counter; + d_dump_file.write(reinterpret_cast(&tmp_ulong_int), sizeof(unsigned long int)); + tmp_double = d_TOW_at_Preamble; + d_dump_file.write(reinterpret_cast(&tmp_double), sizeof(double)); + } + catch (const std::ifstream::failure & e) + { + LOG(WARNING) << "Exception writing Telemetry GPS L5 dump file " << e.what(); + } + } + + //3. Make the output (copy the object contents to the GNURadio reserved memory) + out[0] = current_synchro_data; + return 1; +} + + +void gps_l5_telemetry_decoder_cc::set_satellite(const Gnss_Satellite & satellite) +{ + d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); + LOG(INFO) << "GPS L5 CNAV telemetry decoder in channel " << this->d_channel << " set to satellite " << d_satellite; + d_CNAV_Message.reset(); +} + + +void gps_l5_telemetry_decoder_cc::set_channel(int channel) +{ + d_channel = channel; + d_CNAV_Message.reset(); + LOG(INFO) << "GPS L5 CNAV channel set to " << channel; + // ############# ENABLE DATA FILE LOG ################# + if (d_dump == true) + { + if (d_dump_file.is_open() == false) + { + try + { + d_dump_filename = "telemetry_L5_"; + d_dump_filename.append(boost::lexical_cast(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 Telemetry GPS L5 dump file " << e.what(); + } + } + } +} diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l5_telemetry_decoder_cc.h b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l5_telemetry_decoder_cc.h new file mode 100644 index 000000000..3d60b95ce --- /dev/null +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l5_telemetry_decoder_cc.h @@ -0,0 +1,100 @@ +/*! + * \file gps_l5_telemetry_decoder_cc.h + * \brief Interface of a CNAV message demodulator block based on + * Kay Borre book MATLAB-based GPS receiver + * \author Antonio Ramos, 2017. antonio.ramos(at)cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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 . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_GPS_L5_TELEMETRY_DECODER_CC_H +#define GNSS_SDR_GPS_L5_TELEMETRY_DECODER_CC_H + +#include +#include +#include +#include +#include +#include +#include +#include "gnss_satellite.h" +#include "gps_cnav_navigation_message.h" +#include "concurrent_queue.h" + +extern "C" { + #include "cnav_msg.h" + #include "edc.h" + #include "bits.h" +} + +#include "GPS_L5.h" + +class gps_l5_telemetry_decoder_cc; + +typedef boost::shared_ptr gps_l5_telemetry_decoder_cc_sptr; + +gps_l5_telemetry_decoder_cc_sptr +gps_l5_make_telemetry_decoder_cc(const Gnss_Satellite & satellite, bool dump); + +/*! + * \brief This class implements a GPS L5 Telemetry decoder + * + */ +class gps_l5_telemetry_decoder_cc : public gr::block +{ +public: + ~gps_l5_telemetry_decoder_cc(); + void set_satellite(const Gnss_Satellite & satellite); //!< Set satellite PRN + void set_channel(int channel); //!< Set receiver's channel + 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 gps_l5_telemetry_decoder_cc_sptr + gps_l5_make_telemetry_decoder_cc(const Gnss_Satellite & satellite, bool dump); + gps_l5_telemetry_decoder_cc(const Gnss_Satellite & satellite, bool dump); + + bool d_dump; + Gnss_Satellite d_satellite; + int d_channel; + + std::string d_dump_filename; + std::ofstream d_dump_file; + + cnav_msg_decoder_t d_cnav_decoder; + + double d_TOW_at_current_symbol; + double d_TOW_at_Preamble; + bool d_flag_valid_word; + + Gps_CNAV_Navigation_Message d_CNAV_Message; + double bits_NH[GPS_L5_NH_CODE_LENGTH]; + std::deque sym_hist; + bool sync_NH; + bool new_sym; +}; + + +#endif diff --git a/src/algorithms/telemetry_decoder/libs/libswiftcnav/cnav_msg.c b/src/algorithms/telemetry_decoder/libs/libswiftcnav/cnav_msg.c index bbb9a92f6..e1e62da30 100644 --- a/src/algorithms/telemetry_decoder/libs/libswiftcnav/cnav_msg.c +++ b/src/algorithms/telemetry_decoder/libs/libswiftcnav/cnav_msg.c @@ -49,9 +49,9 @@ */ /** Viterbi decoder reversed polynomial A */ #define GPS_L2C_V27_POLY_A (0x4F) /* 0b01001111 - reversed 0171*/ + /** Viterbi decoder reversed polynomial B */ #define GPS_L2C_V27_POLY_B (0x6D) /* 0b01101101 - reversed 0133 */ - /* * GPS L2C message constants. */ @@ -67,7 +67,7 @@ /** GPS LC2 CNAV CRC length in bits */ #define GPS_CNAV_MSG_CRC_LENGTH (24) /** GPS L2C CNAV message payload length in bits */ -#define GPS_CNAV_MSG_DATA_LENGTH (GPS_CNAV_MSG_LENGTH-GPS_CNAV_MSG_CRC_LENGTH) +#define GPS_CNAV_MSG_DATA_LENGTH (GPS_CNAV_MSG_LENGTH - GPS_CNAV_MSG_CRC_LENGTH) /** GPS L2C CNAV message lock detector threshold */ #define GPS_CNAV_LOCK_MAX_CRC_FAILS (10) @@ -411,7 +411,8 @@ void cnav_msg_decoder_init(cnav_msg_decoder_t *dec) * The time of the last input symbol can be computed from the message ToW and * delay by the formulae: * \code - * symbolTime_ms = msg->tow * 6000 + *pdelay * 20 + * symbolTime_ms = msg->tow * 6000 + *pdelay * 20 (L2) + * symbolTime_ms = msg->tow * 6000 + *pdelay * 10 (L5) * \endcode * * \param[in,out] dec Decoder object. diff --git a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.cc b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.cc index c3a37b548..3289b3ecf 100755 --- a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.cc +++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking.cc @@ -57,19 +57,31 @@ GalileoE1DllPllVemlTracking::GalileoE1DllPllVemlTracking( std::string item_type; std::string default_item_type = "gr_complex"; float pll_bw_hz; + float pll_bw_narrow_hz; float dll_bw_hz; + float dll_bw_narrow_hz; float early_late_space_chips; float very_early_late_space_chips; + float early_late_space_narrow_chips; + float very_early_late_space_narrow_chips; item_type = configuration->property(role + ".item_type", default_item_type); int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); f_if = configuration->property(role + ".if", 0); dump = configuration->property(role + ".dump", false); - pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0); - dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0); + pll_bw_hz = configuration->property(role + ".pll_bw_hz", 5.0); + dll_bw_hz = configuration->property(role + ".dll_bw_hz", 0.5); + pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 2.0); + dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 0.25); + int extend_correlation_symbols; + extend_correlation_symbols = configuration->property(role + ".extend_correlation_symbols", 1); early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.15); very_early_late_space_chips = configuration->property(role + ".very_early_late_space_chips", 0.6); + early_late_space_narrow_chips = configuration->property(role + ".early_late_space_narrow_chips", 0.15); + very_early_late_space_narrow_chips = configuration->property(role + ".very_early_late_space_narrow_chips", 0.6); + + bool track_pilot = configuration->property(role + ".track_pilot", false); std::string default_dump_filename = "./track_ch"; dump_filename = configuration->property(role + ".dump_filename", @@ -88,8 +100,14 @@ GalileoE1DllPllVemlTracking::GalileoE1DllPllVemlTracking( dump_filename, pll_bw_hz, dll_bw_hz, + pll_bw_narrow_hz, + dll_bw_narrow_hz, early_late_space_chips, - very_early_late_space_chips); + very_early_late_space_chips, + early_late_space_narrow_chips, + very_early_late_space_narrow_chips, + extend_correlation_symbols, + track_pilot); } else { @@ -102,14 +120,17 @@ GalileoE1DllPllVemlTracking::GalileoE1DllPllVemlTracking( DLOG(INFO) << "tracking(" << tracking_->unique_id() << ")"; } + GalileoE1DllPllVemlTracking::~GalileoE1DllPllVemlTracking() {} + void GalileoE1DllPllVemlTracking::start_tracking() { tracking_->start_tracking(); } + /* * Set tracking channel unique ID */ @@ -125,23 +146,27 @@ void GalileoE1DllPllVemlTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) tracking_->set_gnss_synchro(p_gnss_synchro); } + void GalileoE1DllPllVemlTracking::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 GalileoE1DllPllVemlTracking::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 GalileoE1DllPllVemlTracking::get_left_block() { return tracking_; } + gr::basic_block_sptr GalileoE1DllPllVemlTracking::get_right_block() { return tracking_; diff --git a/src/algorithms/tracking/adapters/glonass_l1_ca_dll_pll_c_aid_tracking.cc b/src/algorithms/tracking/adapters/glonass_l1_ca_dll_pll_c_aid_tracking.cc index 800d1d4bd..2322626e8 100644 --- a/src/algorithms/tracking/adapters/glonass_l1_ca_dll_pll_c_aid_tracking.cc +++ b/src/algorithms/tracking/adapters/glonass_l1_ca_dll_pll_c_aid_tracking.cc @@ -1,5 +1,5 @@ /*! - * \file glonass_l1_ca_dll_pll_tracking.h + * \file glonass_l1_ca_dll_pll_c_aid_tracking.cc * \brief Interface of an adapter of a DLL+PLL tracking loop block * for Glonass L1 C/A to a TrackingInterface * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com diff --git a/src/algorithms/tracking/adapters/glonass_l1_ca_dll_pll_c_aid_tracking.h b/src/algorithms/tracking/adapters/glonass_l1_ca_dll_pll_c_aid_tracking.h index 4cdd59ce6..b62729a5f 100644 --- a/src/algorithms/tracking/adapters/glonass_l1_ca_dll_pll_c_aid_tracking.h +++ b/src/algorithms/tracking/adapters/glonass_l1_ca_dll_pll_c_aid_tracking.h @@ -1,5 +1,5 @@ /*! - * \file glonass_l1_ca_dll_pll_tracking.h + * \file glonass_l1_ca_dll_pll_c_aid_tracking.h * \brief Interface of an adapter of a DLL+PLL tracking loop block * for Glonass L1 C/A to a TrackingInterface * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com diff --git a/src/algorithms/tracking/adapters/gps_l5i_dll_pll_tracking.cc b/src/algorithms/tracking/adapters/gps_l5i_dll_pll_tracking.cc index e15ff4bb1..be96227d8 100644 --- a/src/algorithms/tracking/adapters/gps_l5i_dll_pll_tracking.cc +++ b/src/algorithms/tracking/adapters/gps_l5i_dll_pll_tracking.cc @@ -1,5 +1,5 @@ /*! - * \file gps_l5idll_pll_tracking.cc + * \file gps_l5i_dll_pll_tracking.cc * \brief Interface of an adapter of a DLL+PLL tracking loop block * for GPS L5i to a TrackingInterface * \author Javier Arribas, 2017. jarribas(at)cttc.es diff --git a/src/algorithms/tracking/adapters/gps_l5i_dll_pll_tracking.h b/src/algorithms/tracking/adapters/gps_l5i_dll_pll_tracking.h index fcc4b3c81..681ddca42 100644 --- a/src/algorithms/tracking/adapters/gps_l5i_dll_pll_tracking.h +++ b/src/algorithms/tracking/adapters/gps_l5i_dll_pll_tracking.h @@ -62,7 +62,7 @@ public: return role_; } - //! Returns "GPS_L2_M_DLL_PLL_Tracking" + //! Returns "GPS_L5i_DLL_PLL_Tracking" inline std::string implementation() override { return "GPS_L5i_DLL_PLL_Tracking"; diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc index 9250de398..ecc7df1be 100755 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc @@ -72,11 +72,30 @@ galileo_e1_dll_pll_veml_make_tracking_cc( std::string dump_filename, float pll_bw_hz, float dll_bw_hz, + float pll_bw_narrow_hz, + float dll_bw_narrow_hz, float early_late_space_chips, - float very_early_late_space_chips) + float very_early_late_space_chips, + float early_late_space_narrow_chips, + float very_early_late_space_narrow_chips, + int extend_correlation_symbols, + bool track_pilot) { return galileo_e1_dll_pll_veml_tracking_cc_sptr(new galileo_e1_dll_pll_veml_tracking_cc(if_freq, - fs_in, vector_length, dump, dump_filename, pll_bw_hz, dll_bw_hz, early_late_space_chips, very_early_late_space_chips)); + fs_in, + vector_length, + dump, + dump_filename, + pll_bw_hz, + dll_bw_hz, + pll_bw_narrow_hz, + dll_bw_narrow_hz, + early_late_space_chips, + very_early_late_space_chips, + early_late_space_narrow_chips, + very_early_late_space_narrow_chips, + extend_correlation_symbols, + track_pilot)); } @@ -98,10 +117,16 @@ galileo_e1_dll_pll_veml_tracking_cc::galileo_e1_dll_pll_veml_tracking_cc( std::string dump_filename, float pll_bw_hz, float dll_bw_hz, + float pll_bw_narrow_hz, + float dll_bw_narrow_hz, float early_late_space_chips, - float very_early_late_space_chips): - gr::block("galileo_e1_dll_pll_veml_tracking_cc", gr::io_signature::make(1, 1, sizeof(gr_complex)), - gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) + float very_early_late_space_chips, + float early_late_space_narrow_chips, + float very_early_late_space_narrow_chips, + int extend_correlation_symbols, + bool track_pilot): + gr::block("galileo_e1_dll_pll_veml_tracking_cc", gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) { // Telemetry bit synchronization message port input this->message_port_register_in(pmt::mp("preamble_timestamp_s")); @@ -121,16 +146,23 @@ galileo_e1_dll_pll_veml_tracking_cc::galileo_e1_dll_pll_veml_tracking_cc( // Initialize tracking ========================================== // Set bandwidth of code and carrier loop filters - d_code_loop_filter.set_DLL_BW(dll_bw_hz); - d_carrier_loop_filter.set_PLL_BW(pll_bw_hz); + d_dll_bw_hz = dll_bw_hz; + d_pll_bw_hz = pll_bw_hz; + d_dll_bw_narrow_hz = dll_bw_narrow_hz; + d_pll_bw_narrow_hz = pll_bw_narrow_hz; + + d_code_loop_filter.set_DLL_BW(d_dll_bw_hz); + d_carrier_loop_filter.set_PLL_BW(d_pll_bw_hz); // Correlator spacing d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips) d_very_early_late_spc_chips = very_early_late_space_chips; // Define very-early-late offset (in chips) + d_early_late_spc_narrow_chips = early_late_space_narrow_chips; // Define narrow early-late offset (in chips) + d_very_early_late_spc_narrow_chips = very_early_late_space_narrow_chips; // Define narrow very-early-late offset (in chips) // Initialization of local code replica // Get space for a vector with the sinboc(1,1) replica sampled 2x/chip - d_ca_code = static_cast(volk_gnsssdr_malloc((2 * Galileo_E1_B_CODE_LENGTH_CHIPS) * sizeof(float), volk_gnsssdr_get_alignment())); + d_tracking_code = static_cast(volk_gnsssdr_malloc((2 * Galileo_E1_B_CODE_LENGTH_CHIPS) * sizeof(float), volk_gnsssdr_get_alignment())); // correlator outputs (scalar) d_n_correlator_taps = 5; // Very-Early, Early, Prompt, Late, Very-Late @@ -155,9 +187,36 @@ galileo_e1_dll_pll_veml_tracking_cc::galileo_e1_dll_pll_veml_tracking_cc( d_local_code_shift_chips[4] = d_very_early_late_spc_chips; d_correlation_length_samples = d_vector_length; - multicorrelator_cpu.init(2 * d_correlation_length_samples, d_n_correlator_taps); + d_extend_correlation_symbols = extend_correlation_symbols; + // Enable Data component prompt correlator (slave to Pilot prompt) if tracking uses Pilot signal + d_track_pilot = track_pilot; + if (d_track_pilot) + { + // extended integration control + if (d_extend_correlation_symbols > 1) + { + d_enable_extended_integration = true; + } + else + { + d_enable_extended_integration = false; + } + // Extra correlator for the data component + d_local_code_data_shift_chips = static_cast(volk_gnsssdr_malloc(sizeof(float), volk_gnsssdr_get_alignment())); + d_local_code_data_shift_chips[0] = 0.0; + correlator_data_cpu.init(2 * d_correlation_length_samples, 1); + d_Prompt_Data = static_cast(volk_gnsssdr_malloc(sizeof(gr_complex), volk_gnsssdr_get_alignment())); + d_Prompt_Data[0] = gr_complex(0,0); + d_data_code = static_cast(volk_gnsssdr_malloc((2 * Galileo_E1_B_CODE_LENGTH_CHIPS) * sizeof(float), volk_gnsssdr_get_alignment())); + } + else + { + // Disable extended integration if data component tracking is selected + d_enable_extended_integration = false; + } + //--- Initializations ------------------------------ // Initial code frequency basis of NCO d_code_freq_chips = static_cast(Galileo_E1_CODE_CHIP_RATE_HZ); @@ -171,9 +230,6 @@ galileo_e1_dll_pll_veml_tracking_cc::galileo_e1_dll_pll_veml_tracking_cc( //d_sample_counter_seconds = 0; d_acq_sample_stamp = 0; - d_enable_tracking = false; - d_pull_in = false; - d_current_prn_length_samples = static_cast(d_vector_length); // CN0 estimation and lock detector buffers @@ -185,11 +241,8 @@ galileo_e1_dll_pll_veml_tracking_cc::galileo_e1_dll_pll_veml_tracking_cc( d_carrier_lock_threshold = CARRIER_LOCK_THRESHOLD; systemName["E"] = std::string("Galileo"); - *d_Very_Early = gr_complex(0,0); - *d_Early = gr_complex(0,0); - *d_Prompt = gr_complex(0,0); - *d_Late = gr_complex(0,0); - *d_Very_Late = gr_complex(0,0); + + clear_tracking_vars(); d_acquisition_gnss_synchro = 0; d_channel = 0; @@ -197,55 +250,124 @@ galileo_e1_dll_pll_veml_tracking_cc::galileo_e1_dll_pll_veml_tracking_cc( d_acq_carrier_doppler_hz = 0.0; d_carrier_doppler_hz = 0.0; d_acc_carrier_phase_rad = 0.0; - d_acc_code_phase_secs = 0.0; + + d_extend_correlation_symbols_count = 0; + d_code_phase_step_chips = 0.0; + d_carrier_phase_step_rad = 0.0; + d_rem_code_phase_chips = 0.0; + d_K_blk_samples = 0.0; + d_code_phase_samples = 0.0; + + d_state = 0; // initial state: standby } void galileo_e1_dll_pll_veml_tracking_cc::start_tracking() { + /* + * correct the code phase according to the delay between acq and trk + */ d_acq_code_phase_samples = d_acquisition_gnss_synchro->Acq_delay_samples; d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz; d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples; + long int acq_trk_diff_samples; + double acq_trk_diff_seconds; + acq_trk_diff_samples = static_cast(d_sample_counter) - static_cast(d_acq_sample_stamp); //-d_vector_length; + DLOG(INFO) << "Number of samples between Acquisition and Tracking = " << acq_trk_diff_samples; + acq_trk_diff_seconds = static_cast(acq_trk_diff_samples) / static_cast(d_fs_in); + // Doppler effect + // Fd=(C/(C+Vr))*F + double radial_velocity = (Galileo_E1_FREQ_HZ + d_acq_carrier_doppler_hz) / Galileo_E1_FREQ_HZ; + // new chip and prn sequence periods based on acq Doppler + double T_chip_mod_seconds; + double T_prn_mod_seconds; + double T_prn_mod_samples; + d_code_freq_chips = radial_velocity * Galileo_E1_CODE_CHIP_RATE_HZ; + d_code_phase_step_chips = static_cast(d_code_freq_chips) / static_cast(d_fs_in); + T_chip_mod_seconds = 1/d_code_freq_chips; + T_prn_mod_seconds = T_chip_mod_seconds * Galileo_E1_B_CODE_LENGTH_CHIPS; + T_prn_mod_samples = T_prn_mod_seconds * static_cast(d_fs_in); + + d_current_prn_length_samples = round(T_prn_mod_samples); + + double T_prn_true_seconds = Galileo_E1_B_CODE_LENGTH_CHIPS / Galileo_E1_CODE_CHIP_RATE_HZ; + double T_prn_true_samples = T_prn_true_seconds * static_cast(d_fs_in); + double T_prn_diff_seconds = T_prn_true_seconds - T_prn_mod_seconds; + double N_prn_diff = acq_trk_diff_seconds / T_prn_true_seconds; + double corrected_acq_phase_samples, delay_correction_samples; + corrected_acq_phase_samples = fmod((d_acq_code_phase_samples + T_prn_diff_seconds * N_prn_diff * static_cast(d_fs_in)), T_prn_true_samples); + if (corrected_acq_phase_samples < 0) + { + corrected_acq_phase_samples = T_prn_mod_samples + corrected_acq_phase_samples; + } + delay_correction_samples = d_acq_code_phase_samples - corrected_acq_phase_samples; + + d_acq_code_phase_samples = corrected_acq_phase_samples; + + d_carrier_doppler_hz = d_acq_carrier_doppler_hz; + d_carrier_phase_step_rad = GALILEO_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); + // DLL/PLL filter initialization d_carrier_loop_filter.initialize(); // initialize the carrier filter d_code_loop_filter.initialize(); // initialize the code filter - // generate local reference ALWAYS starting at chip 1 (2 samples per chip) - galileo_e1_code_gen_float_sampled(d_ca_code, - d_acquisition_gnss_synchro->Signal, - false, - d_acquisition_gnss_synchro->PRN, - 2 * Galileo_E1_CODE_CHIP_RATE_HZ, - 0); + if (d_track_pilot) + { + char pilot_signal[3] = "1C"; + galileo_e1_code_gen_float_sampled(d_tracking_code, + pilot_signal, + false, + d_acquisition_gnss_synchro->PRN, + Galileo_E1_CODE_CHIP_RATE_HZ, + 0); + galileo_e1_code_gen_float_sampled(d_data_code, + d_acquisition_gnss_synchro->Signal, + false, + d_acquisition_gnss_synchro->PRN, + Galileo_E1_CODE_CHIP_RATE_HZ, + 0); + d_Prompt_Data[0] = gr_complex(0,0); // clean data correlator output + correlator_data_cpu.set_local_code_and_taps(static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS), + d_data_code, + d_local_code_shift_chips); + } + else + { + galileo_e1_code_gen_float_sampled(d_tracking_code, + d_acquisition_gnss_synchro->Signal, + false, + d_acquisition_gnss_synchro->PRN, + Galileo_E1_CODE_CHIP_RATE_HZ, + 0); + } - multicorrelator_cpu.set_local_code_and_taps(static_cast(2 * Galileo_E1_B_CODE_LENGTH_CHIPS), d_ca_code, d_local_code_shift_chips); + multicorrelator_cpu.set_local_code_and_taps(static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS), d_tracking_code, d_local_code_shift_chips); for (int n = 0; n < d_n_correlator_taps; n++) { d_correlator_outs[n] = gr_complex(0,0); } d_carrier_lock_fail_counter = 0; - d_rem_code_phase_samples = 0.0; + d_rem_code_phase_samples = 0; d_rem_carr_phase_rad = 0.0; + d_rem_code_phase_chips = 0.0; d_acc_carrier_phase_rad = 0.0; - d_acc_code_phase_secs = 0.0; - d_carrier_doppler_hz = d_acq_carrier_doppler_hz; - d_current_prn_length_samples = d_vector_length; + d_code_phase_samples = d_acq_code_phase_samples; std::string sys_ = &d_acquisition_gnss_synchro->System; - sys = sys_.substr(0, 1); + sys = sys_.substr(0,1); // DEBUG OUTPUT std::cout << "Tracking of Galileo E1 signal started on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl; LOG(INFO) << "Starting tracking of satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << " on channel " << d_channel; - // enable tracking - d_pull_in = true; - d_enable_tracking = true; + // enable tracking pull-in + d_state = 1; LOG(INFO) << "PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz + << " Code Phase correction [samples]=" << delay_correction_samples << " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples; } @@ -279,7 +401,14 @@ galileo_e1_dll_pll_veml_tracking_cc::~galileo_e1_dll_pll_veml_tracking_cc() { volk_gnsssdr_free(d_local_code_shift_chips); volk_gnsssdr_free(d_correlator_outs); - volk_gnsssdr_free(d_ca_code); + volk_gnsssdr_free(d_tracking_code); + if (d_track_pilot) + { + volk_gnsssdr_free(d_Prompt_Data); + volk_gnsssdr_free(d_data_code); + volk_gnsssdr_free(d_local_code_data_shift_chips); + correlator_data_cpu.free(); + } delete[] d_Prompt_buffer; multicorrelator_cpu.free(); } @@ -290,165 +419,167 @@ galileo_e1_dll_pll_veml_tracking_cc::~galileo_e1_dll_pll_veml_tracking_cc() } -int galileo_e1_dll_pll_veml_tracking_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) +bool galileo_e1_dll_pll_veml_tracking_cc::acquire_secondary() { - double carr_error_hz = 0.0; - double carr_error_filt_hz = 0.0; - double code_error_chips = 0.0; - double code_error_filt_chips = 0.0; - - // Block input data and block output stream pointers - const gr_complex* in = reinterpret_cast(input_items[0]); - Gnss_Synchro **out = reinterpret_cast(&output_items[0]); - // GNSS_SYNCHRO OBJECT to interchange data between tracking->telemetry_decoder - Gnss_Synchro current_synchro_data = Gnss_Synchro(); - - if (d_enable_tracking == true) + //******* preamble correlation ******** + int corr_value = 0; + for (unsigned int i = 0; i < Galileo_E1_C_SECONDARY_CODE_LENGTH; i++) { - // Fill the acquisition data - current_synchro_data = *d_acquisition_gnss_synchro; - if (d_pull_in == true) + if (d_Prompt_buffer_deque.at(i).real() < 0) // symbols clipping { - /* - * Signal alignment (skip samples until the incoming signal is aligned with local replica) - */ - int samples_offset; - double acq_trk_shif_correction_samples; - int acq_to_trk_delay_samples; - acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp; - acq_trk_shif_correction_samples = d_current_prn_length_samples - std::fmod(static_cast(acq_to_trk_delay_samples), static_cast(d_current_prn_length_samples)); - samples_offset = round(d_acq_code_phase_samples + acq_trk_shif_correction_samples); - current_synchro_data.Tracking_sample_counter = d_sample_counter + samples_offset; - current_synchro_data.fs = d_fs_in; - *out[0] = current_synchro_data; - d_sample_counter = d_sample_counter + samples_offset; //count for the processed samples - d_pull_in = false; - consume_each(samples_offset); //shift input to perform alignment with local replica - return 1; - } - - // ################# CARRIER WIPEOFF AND CORRELATORS ############################## - // perform carrier wipe-off and compute Early, Prompt and Late correlation - multicorrelator_cpu.set_input_output_vectors(d_correlator_outs,in); - - double carr_phase_step_rad = GALILEO_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); - double code_phase_step_half_chips = (2.0 * d_code_freq_chips) / (static_cast(d_fs_in)); - double rem_code_phase_half_chips = d_rem_code_phase_samples * (2.0*d_code_freq_chips / d_fs_in); - multicorrelator_cpu.Carrier_wipeoff_multicorrelator_resampler( - d_rem_carr_phase_rad, - carr_phase_step_rad, - rem_code_phase_half_chips, - code_phase_step_half_chips, - d_correlation_length_samples); - - // ################## PLL ########################################################## - // PLL discriminator - carr_error_hz = pll_cloop_two_quadrant_atan(*d_Prompt) / GALILEO_TWO_PI; - // Carrier discriminator filter - carr_error_filt_hz = d_carrier_loop_filter.get_carrier_nco(carr_error_hz); - // New carrier Doppler frequency estimation - d_carrier_doppler_hz = d_acq_carrier_doppler_hz + carr_error_filt_hz; - // New code Doppler frequency estimation - d_code_freq_chips = Galileo_E1_CODE_CHIP_RATE_HZ + ((d_carrier_doppler_hz * Galileo_E1_CODE_CHIP_RATE_HZ) / Galileo_E1_FREQ_HZ); - //carrier phase accumulator for (K) Doppler estimation- - d_acc_carrier_phase_rad -= GALILEO_TWO_PI * d_carrier_doppler_hz * static_cast(d_current_prn_length_samples) / static_cast(d_fs_in); - //remnant carrier phase to prevent overflow in the code NCO - d_rem_carr_phase_rad = d_rem_carr_phase_rad + GALILEO_TWO_PI * d_carrier_doppler_hz * static_cast(d_current_prn_length_samples) / static_cast(d_fs_in); - d_rem_carr_phase_rad = std::fmod(d_rem_carr_phase_rad, GALILEO_TWO_PI); - - // ################## DLL ########################################################## - // DLL discriminator - code_error_chips = dll_nc_vemlp_normalized(*d_Very_Early, *d_Early, *d_Late, *d_Very_Late); //[chips/Ti] - // Code discriminator filter - code_error_filt_chips = d_code_loop_filter.get_code_nco(code_error_chips); //[chips/second] - //Code phase accumulator - double code_error_filt_secs; - code_error_filt_secs = (Galileo_E1_CODE_PERIOD * code_error_filt_chips) / Galileo_E1_CODE_CHIP_RATE_HZ; //[seconds] - d_acc_code_phase_secs = d_acc_code_phase_secs + code_error_filt_secs; - - // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### - // keep alignment parameters for the next input buffer - double T_chip_seconds; - double T_prn_seconds; - double T_prn_samples; - double K_blk_samples; - // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation - T_chip_seconds = 1.0 / d_code_freq_chips; - T_prn_seconds = T_chip_seconds * Galileo_E1_B_CODE_LENGTH_CHIPS; - T_prn_samples = T_prn_seconds * static_cast(d_fs_in); - K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs * static_cast(d_fs_in); - d_current_prn_length_samples = round(K_blk_samples); //round to a discrete samples - - // ####### CN0 ESTIMATION AND LOCK DETECTORS ###### - if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES) - { - // fill buffer with prompt correlator output values - d_Prompt_buffer[d_cn0_estimation_counter] = *d_Prompt; - d_cn0_estimation_counter++; - } - else - { - d_cn0_estimation_counter = 0; - - // Code lock indicator - d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, Galileo_E1_B_CODE_LENGTH_CHIPS); - - // Carrier lock indicator - d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); - - // Loss of lock detection - if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < MINIMUM_VALID_CN0) + if (Galileo_E1_C_SECONDARY_CODE.at(i) == '0') { - d_carrier_lock_fail_counter++; + corr_value++; } else { - if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--; - } - if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) - { - std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; - LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; - this->message_port_pub(pmt::mp("events"), pmt::from_long(3));//3 -> loss of lock - d_carrier_lock_fail_counter = 0; - d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine + corr_value--; } } + else + { + if (Galileo_E1_C_SECONDARY_CODE.at(i) == '0') + { + corr_value--; + } + else + { + corr_value++; + } + } + } - // ########### Output the tracking results to Telemetry block ########## - - current_synchro_data.Prompt_I = static_cast((*d_Prompt).real()); - current_synchro_data.Prompt_Q = static_cast((*d_Prompt).imag()); - // Tracking_timestamp_secs is aligned with the CURRENT PRN start sample (Hybridization OK!) - current_synchro_data.Tracking_sample_counter = d_sample_counter; - current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; - //compute remnant code phase samples AFTER the Tracking timestamp - d_rem_code_phase_samples = K_blk_samples - d_current_prn_length_samples; //rounding error < 1 sample - current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; - current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; - current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; - current_synchro_data.Flag_valid_symbol_output = true; - current_synchro_data.correlation_length_ms = Galileo_E1_CODE_PERIOD_MS; - + if (abs(corr_value) == Galileo_E1_C_SECONDARY_CODE_LENGTH) + { + return true; } else - { - *d_Early = gr_complex(0,0); - *d_Prompt = gr_complex(0,0); - *d_Late = gr_complex(0,0); - // GNSS_SYNCHRO OBJECT to interchange data between tracking->telemetry_decoder - current_synchro_data.Tracking_sample_counter = d_sample_counter; - } - //assign the GNURadio block output data - current_synchro_data.System = {'E'}; - std::string str_aux = "1B"; - const char * str = str_aux.c_str(); // get a C style null terminated string - std::memcpy(static_cast(current_synchro_data.Signal), str, 3); + { + return false; + } +} - current_synchro_data.fs = d_fs_in; - *out[0] = current_synchro_data; +bool galileo_e1_dll_pll_veml_tracking_cc::cn0_and_tracking_lock_status() +{ + // ####### CN0 ESTIMATION AND LOCK DETECTORS ###### + if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES) + { + // fill buffer with prompt correlator output values + d_Prompt_buffer[d_cn0_estimation_counter] = d_P_accu; + d_cn0_estimation_counter++; + return true; + } + else + { + d_cn0_estimation_counter = 0; + // Code lock indicator + d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, Galileo_E1_B_CODE_LENGTH_CHIPS); + // Carrier lock indicator + d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); + // Loss of lock detection + if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < MINIMUM_VALID_CN0) + { + d_carrier_lock_fail_counter++; + } + else + { + if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--; + } + if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) + { + std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; + LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; + this->message_port_pub(pmt::mp("events"), pmt::from_long(3)); // 3 -> loss of lock + d_carrier_lock_fail_counter = 0; + return false; + } + else + { + return true; + } + } +} + + +// correlation requires: +// - updated remnant carrier phase in radians (rem_carr_phase_rad) +// - updated remnant code phase in samples (d_rem_code_phase_samples) +// - d_code_freq_chips +// - d_carrier_doppler_hz +void galileo_e1_dll_pll_veml_tracking_cc::do_correlation_step(const gr_complex* input_samples) +{ + // ################# CARRIER WIPEOFF AND CORRELATORS ############################## + // perform carrier wipe-off and compute Early, Prompt and Late correlation + multicorrelator_cpu.set_input_output_vectors(d_correlator_outs,input_samples); + multicorrelator_cpu.Carrier_wipeoff_multicorrelator_resampler( + d_rem_carr_phase_rad, + d_carrier_phase_step_rad, + d_rem_code_phase_chips, + d_code_phase_step_chips, + d_correlation_length_samples); + + // DATA CORRELATOR (if tracking tracks the pilot signal) + if (d_track_pilot) + { + correlator_data_cpu.set_input_output_vectors(d_Prompt_Data,input_samples); + correlator_data_cpu.Carrier_wipeoff_multicorrelator_resampler( + d_rem_carr_phase_rad, + d_carrier_phase_step_rad, + d_rem_code_phase_chips, + d_code_phase_step_chips, + d_correlation_length_samples); + } +} + + +void galileo_e1_dll_pll_veml_tracking_cc::run_dll_pll(bool disable_costas_loop) +{ + // ################## PLL ########################################################## + // PLL discriminator + if (disable_costas_loop == true) + { + // Secondary code acquired. No symbols transition should be present in the signal + d_carr_error_hz = pll_four_quadrant_atan(d_P_accu) / GALILEO_TWO_PI; + } + else + { + // Costas loop discriminator, insensitive to 180 deg phase transitions + d_carr_error_hz = pll_cloop_two_quadrant_atan(d_P_accu) / GALILEO_TWO_PI; + } + + // Carrier discriminator filter + d_carr_error_filt_hz = d_carrier_loop_filter.get_carrier_nco(d_carr_error_hz); + // New carrier Doppler frequency estimation + d_carrier_doppler_hz = d_acq_carrier_doppler_hz + d_carr_error_filt_hz; + // New code Doppler frequency estimation + d_code_freq_chips = Galileo_E1_CODE_CHIP_RATE_HZ + ((d_carrier_doppler_hz * Galileo_E1_CODE_CHIP_RATE_HZ) / Galileo_E1_FREQ_HZ); + + // ################## DLL ########################################################## + // DLL discriminator + d_code_error_chips = dll_nc_vemlp_normalized(d_VE_accu, d_E_accu, d_L_accu, d_VL_accu); // [chips/Ti] + // Code discriminator filter + d_code_error_filt_chips = d_code_loop_filter.get_code_nco(d_code_error_chips); // [chips/second] +} + + +void galileo_e1_dll_pll_veml_tracking_cc::clear_tracking_vars() +{ + *d_Very_Early = gr_complex(0,0); + *d_Early = gr_complex(0,0); + *d_Prompt = gr_complex(0,0); + *d_Late = gr_complex(0,0); + *d_Very_Late= gr_complex(0,0); + d_carr_error_hz = 0.0; + d_carr_error_filt_hz = 0.0; + d_code_error_chips = 0.0; + d_code_error_filt_chips = 0.0; + d_current_symbol = 0; +} + + +void galileo_e1_dll_pll_veml_tracking_cc::log_data() +{ if(d_dump) { // Dump results to file @@ -457,13 +588,15 @@ int galileo_e1_dll_pll_veml_tracking_cc::general_work (int noutput_items __attri float tmp_VE, tmp_E, tmp_P, tmp_L, tmp_VL; float tmp_float; double tmp_double; - prompt_I = (*d_Prompt).real(); - prompt_Q = (*d_Prompt).imag(); - tmp_VE = std::abs(*d_Very_Early); - tmp_E = std::abs(*d_Early); - tmp_P = std::abs(*d_Prompt); - tmp_L = std::abs(*d_Late); - tmp_VL = std::abs(*d_Very_Late); + + prompt_I = static_cast(d_P_accu.real()); + prompt_Q = static_cast(d_P_accu.imag()); + + tmp_VE = std::abs(d_VE_accu); + tmp_E = std::abs(d_E_accu); + tmp_P = std::abs(d_P_accu); + tmp_L = std::abs(d_L_accu); + tmp_VL = std::abs(d_VL_accu); try { @@ -486,15 +619,15 @@ int galileo_e1_dll_pll_veml_tracking_cc::general_work (int noutput_items __attri d_dump_file.write(reinterpret_cast(&tmp_float), sizeof(float)); tmp_float = d_code_freq_chips; d_dump_file.write(reinterpret_cast(&tmp_float), sizeof(float)); - //PLL commands - tmp_float = carr_error_hz; + // PLL commands + tmp_float = d_carr_error_hz; d_dump_file.write(reinterpret_cast(&tmp_float), sizeof(float)); - tmp_float = carr_error_filt_hz; + tmp_float = d_carr_error_filt_hz; d_dump_file.write(reinterpret_cast(&tmp_float), sizeof(float)); - //DLL commands - tmp_float = code_error_chips; + // DLL commands + tmp_float = d_code_error_chips; d_dump_file.write(reinterpret_cast(&tmp_float), sizeof(float)); - tmp_float = code_error_filt_chips; + tmp_float = d_code_error_filt_chips; d_dump_file.write(reinterpret_cast(&tmp_float), sizeof(float)); // CN0 and carrier lock test tmp_float = d_CN0_SNV_dB_Hz; @@ -515,10 +648,345 @@ int galileo_e1_dll_pll_veml_tracking_cc::general_work (int noutput_items __attri LOG(WARNING) << "Exception writing trk dump file " << e.what(); } } - consume_each(d_current_prn_length_samples); // this is required for gr_block derivates - d_sample_counter += d_current_prn_length_samples; //count for the processed samples +} - return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false + +int galileo_e1_dll_pll_veml_tracking_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) +{ + // Block input data and block output stream pointers + const gr_complex* in = reinterpret_cast(input_items[0]); + Gnss_Synchro **out = reinterpret_cast(&output_items[0]); + // GNSS_SYNCHRO OBJECT to interchange data between tracking->telemetry_decoder + Gnss_Synchro current_synchro_data = Gnss_Synchro(); + + switch(d_state) + { + case 0: // standby - bypass + { + current_synchro_data.Tracking_sample_counter = d_sample_counter; + break; + } + case 1: // pull-in + { + /* + * Signal alignment (skip samples until the incoming signal is aligned with local replica) + */ + // Fill the acquisition data + current_synchro_data = *d_acquisition_gnss_synchro; + int samples_offset; + double acq_trk_shif_correction_samples; + int acq_to_trk_delay_samples; + acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp; + acq_trk_shif_correction_samples = d_current_prn_length_samples - std::fmod(static_cast(acq_to_trk_delay_samples), static_cast(d_current_prn_length_samples)); + samples_offset = round(d_acq_code_phase_samples + acq_trk_shif_correction_samples); + current_synchro_data.Tracking_sample_counter = d_sample_counter; + current_synchro_data.fs = d_fs_in; + *out[0] = current_synchro_data; + d_sample_counter = d_sample_counter + samples_offset; // count for the processed samples + consume_each(samples_offset); // shift input to perform alignment with local replica + d_state = 2; // next state is the symbol synchronization + return 0; + } + case 2: // wide tracking and symbol synchronization + { + // Fill the acquisition data + current_synchro_data = *d_acquisition_gnss_synchro; + // Current NCO and code generator parameters + d_carrier_phase_step_rad = GALILEO_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); + d_code_phase_step_chips = d_code_freq_chips / static_cast(d_fs_in); + d_rem_code_phase_chips = d_rem_code_phase_samples * d_code_freq_chips / d_fs_in; + // perform a correlation step + do_correlation_step(in); + // save single correlation step variables + d_VE_accu = *d_Very_Early; + d_E_accu = *d_Early; + d_P_accu = *d_Prompt; + d_L_accu = *d_Late; + d_VL_accu = *d_Very_Late; + // check lock status + if (cn0_and_tracking_lock_status() == false) + { + clear_tracking_vars(); + d_state = 0; // loss-of-lock detected + } + else + { + // perform DLL/PLL tracking loop computations + run_dll_pll(false); + + // ################## PLL COMMANDS ################################################# + // carrier phase accumulator for (K) Doppler estimation- + d_acc_carrier_phase_rad -= GALILEO_TWO_PI * d_carrier_doppler_hz * static_cast(d_current_prn_length_samples) / static_cast(d_fs_in); + // remnant carrier phase to prevent overflow in the code NCO + d_rem_carr_phase_rad = d_rem_carr_phase_rad + GALILEO_TWO_PI * d_carrier_doppler_hz * static_cast(d_current_prn_length_samples) / static_cast(d_fs_in); + d_rem_carr_phase_rad = std::fmod(d_rem_carr_phase_rad, GALILEO_TWO_PI); + + // ################## DLL COMMANDS ################################################# + // Code error from DLL + double code_error_filt_secs; + code_error_filt_secs = (Galileo_E1_CODE_PERIOD * d_code_error_filt_chips) / Galileo_E1_CODE_CHIP_RATE_HZ; // [seconds] + + // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### + // keep alignment parameters for the next input buffer + // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation + double T_chip_seconds = 1.0 / d_code_freq_chips; + double T_prn_seconds = T_chip_seconds * Galileo_E1_B_CODE_LENGTH_CHIPS; + double T_prn_samples = T_prn_seconds * static_cast(d_fs_in); + double K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs * static_cast(d_fs_in); + d_current_prn_length_samples = round(K_blk_samples); // round to a discrete number of samples + + // ########### Output the tracking results to Telemetry block ########## + if (d_track_pilot) + { + current_synchro_data.Prompt_I = static_cast((*d_Prompt_Data).real()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt_Data).imag()); + } + else + { + current_synchro_data.Prompt_I = static_cast((*d_Prompt).real()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt).imag()); + } + current_synchro_data.Tracking_sample_counter = d_sample_counter; + current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; + // compute remnant code phase samples AFTER the Tracking timestamp + d_rem_code_phase_samples = K_blk_samples - d_current_prn_length_samples; // rounding error < 1 sample + current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; + current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; + current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; + current_synchro_data.Flag_valid_symbol_output = true; + current_synchro_data.correlation_length_ms = Galileo_E1_CODE_PERIOD_MS; + + // enable write dump file this cycle (valid DLL/PLL cycle) + log_data(); + + //std::cout<<(d_Prompt->real()>0); + if (d_enable_extended_integration) + { + // ####### SECONDARY CODE LOCK ##### + d_Prompt_buffer_deque.push_back(*d_Prompt); + if (d_Prompt_buffer_deque.size() == Galileo_E1_C_SECONDARY_CODE_LENGTH) + { + if (acquire_secondary() == true) + { + d_extend_correlation_symbols_count = 0; + // reset extended correlator + d_VE_accu = gr_complex(0,0); + d_E_accu = gr_complex(0,0); + d_P_accu = gr_complex(0,0); + d_L_accu = gr_complex(0,0); + d_VL_accu = gr_complex(0,0); + d_Prompt_buffer_deque.clear(); + d_current_symbol = 0; + d_code_loop_filter.set_DLL_BW(d_dll_bw_narrow_hz); + d_carrier_loop_filter.set_PLL_BW(d_pll_bw_narrow_hz); + + // Set TAPs delay values [chips] + d_local_code_shift_chips[0] = - d_very_early_late_spc_narrow_chips; + d_local_code_shift_chips[1] = - d_early_late_spc_narrow_chips; + d_local_code_shift_chips[2] = 0.0; + d_local_code_shift_chips[3] = d_early_late_spc_narrow_chips; + d_local_code_shift_chips[4] = d_very_early_late_spc_narrow_chips; + + LOG(INFO) << "Enabled " << d_extend_correlation_symbols << " [symbols] extended correlator for CH " + << d_channel + << " : Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN); + std::cout << "Enabled " << d_extend_correlation_symbols << " [symbols] extended correlator for CH " + << d_channel + << " : Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl; + //std::cout << " pll_bw = " << d_pll_bw_hz << " [Hz], pll_narrow_bw = " << d_pll_bw_narrow_hz << " [Hz]" << std::endl; + //std::cout << " dll_bw = " << d_dll_bw_hz << " [Hz], dll_narrow_bw = " << d_dll_bw_narrow_hz << " [Hz]" << std::endl; + + // UPDATE INTEGRATION TIME + double new_correlation_time_s = static_cast(d_extend_correlation_symbols) * Galileo_E1_CODE_PERIOD; + d_carrier_loop_filter.set_pdi(new_correlation_time_s); + d_code_loop_filter.set_pdi(new_correlation_time_s); + + d_state = 3; // next state is the extended correlator integrator + } + + d_Prompt_buffer_deque.pop_front(); + } + } + } + break; + } + case 3: // coherent integration (correlation time extension) + { + // Fill the acquisition data + current_synchro_data = *d_acquisition_gnss_synchro; + // Current NCO and code generator parameters + d_carrier_phase_step_rad = GALILEO_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); + d_code_phase_step_chips = d_code_freq_chips / static_cast(d_fs_in); + d_rem_code_phase_chips = d_rem_code_phase_samples * d_code_freq_chips / d_fs_in; + // perform a correlation step + do_correlation_step(in); + // correct the integration sign using the current symbol of the secondary code + if (Galileo_E1_C_SECONDARY_CODE.at(d_current_symbol) == '0') + { + d_VE_accu += *d_Very_Early; + d_E_accu += *d_Early; + d_P_accu += *d_Prompt; + d_L_accu += *d_Late; + d_VL_accu += *d_Very_Late; + } + else + { + d_VE_accu -= *d_Very_Early; + d_E_accu -= *d_Early; + d_P_accu -= *d_Prompt; + d_L_accu -= *d_Late; + d_VL_accu -= *d_Very_Late; + } + d_current_symbol++; + // secondary code roll-up + d_current_symbol = d_current_symbol % Galileo_E1_C_SECONDARY_CODE_LENGTH; + + // PLL/DLL not enabled, we are in the middle of a coherent integration + // keep alignment parameters for the next input buffer + // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation + + // ################## PLL ########################################################## + // carrier phase accumulator for (K) Doppler estimation- + d_acc_carrier_phase_rad -= GALILEO_TWO_PI * d_carrier_doppler_hz * static_cast(d_current_prn_length_samples) / static_cast(d_fs_in); + // remnant carrier phase to prevent overflow in the code NCO + d_rem_carr_phase_rad = d_rem_carr_phase_rad + GALILEO_TWO_PI * d_carrier_doppler_hz * static_cast(d_current_prn_length_samples) / static_cast(d_fs_in); + d_rem_carr_phase_rad = std::fmod(d_rem_carr_phase_rad, GALILEO_TWO_PI); + + // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### + // keep alignment parameters for the next input buffer + // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation + double T_chip_seconds = 1.0 / d_code_freq_chips; + double T_prn_seconds = T_chip_seconds * Galileo_E1_B_CODE_LENGTH_CHIPS; + double T_prn_samples = T_prn_seconds * static_cast(d_fs_in); + double K_blk_samples = T_prn_samples + d_rem_code_phase_samples; + d_current_prn_length_samples = round(K_blk_samples); //round to a discrete samples + + // ########### Output the tracking results to Telemetry block ########## + current_synchro_data.Prompt_I = static_cast((*d_Prompt_Data).real()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt_Data).imag()); + current_synchro_data.Tracking_sample_counter = d_sample_counter; + current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; + // compute remnant code phase samples AFTER the Tracking timestamp + d_rem_code_phase_samples = K_blk_samples - d_current_prn_length_samples; //rounding error < 1 sample + current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; + current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; + current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; + current_synchro_data.Flag_valid_symbol_output = true; + current_synchro_data.correlation_length_ms = Galileo_E1_CODE_PERIOD_MS; + + d_extend_correlation_symbols_count++; + if (d_extend_correlation_symbols_count >= (d_extend_correlation_symbols - 1)) + { + d_extend_correlation_symbols_count = 0; + d_state = 4; + } + break; + } + case 4: // narrow tracking + { + // Fill the acquisition data + current_synchro_data = *d_acquisition_gnss_synchro; + // perform a correlation step + do_correlation_step(in); + + // correct the integration using the current symbol + if (Galileo_E1_C_SECONDARY_CODE.at(d_current_symbol) == '0') + { + d_VE_accu += *d_Very_Early; + d_E_accu += *d_Early; + d_P_accu += *d_Prompt; + d_L_accu += *d_Late; + d_VL_accu += *d_Very_Late; + } + else + { + d_VE_accu -= *d_Very_Early; + d_E_accu -= *d_Early; + d_P_accu -= *d_Prompt; + d_L_accu -= *d_Late; + d_VL_accu -= *d_Very_Late; + } + d_current_symbol++; + // secondary code roll-up + d_current_symbol = d_current_symbol % Galileo_E1_C_SECONDARY_CODE_LENGTH; + + // check lock status + if (cn0_and_tracking_lock_status() == false) + { + clear_tracking_vars(); + d_state = 0; // loss-of-lock detected + } + else + { + run_dll_pll(true); // Costas loop disabled, use four quadrant atan + + // ################## PLL ########################################################## + // carrier phase accumulator for (K) Doppler estimation- + d_acc_carrier_phase_rad -= GALILEO_TWO_PI * d_carrier_doppler_hz * static_cast(d_current_prn_length_samples) / static_cast(d_fs_in); + // remnant carrier phase to prevent overflow in the code NCO + d_rem_carr_phase_rad = d_rem_carr_phase_rad + GALILEO_TWO_PI * d_carrier_doppler_hz * static_cast(d_current_prn_length_samples) / static_cast(d_fs_in); + d_rem_carr_phase_rad = std::fmod(d_rem_carr_phase_rad, GALILEO_TWO_PI); + + // ################## DLL ########################################################## + // Code phase accumulator + double code_error_filt_secs; + code_error_filt_secs = (Galileo_E1_CODE_PERIOD * d_code_error_filt_chips) / Galileo_E1_CODE_CHIP_RATE_HZ; //[seconds] + + // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### + // keep alignment parameters for the next input buffer + // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation + double T_chip_seconds = 1.0 / d_code_freq_chips; + double T_prn_seconds = T_chip_seconds * Galileo_E1_B_CODE_LENGTH_CHIPS; + double T_prn_samples = T_prn_seconds * static_cast(d_fs_in); + double K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs * static_cast(d_fs_in); + d_current_prn_length_samples = round(K_blk_samples); // round to a discrete number of samples + + // ########### Output the tracking results to Telemetry block ########## + current_synchro_data.Prompt_I = static_cast((*d_Prompt_Data).real()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt_Data).imag()); + current_synchro_data.Tracking_sample_counter = d_sample_counter; + current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; + // compute remnant code phase samples AFTER the Tracking timestamp + d_rem_code_phase_samples = K_blk_samples - d_current_prn_length_samples; //rounding error < 1 sample + current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; + current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; + current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; + current_synchro_data.Flag_valid_symbol_output = true; + current_synchro_data.correlation_length_ms = Galileo_E1_CODE_PERIOD_MS; + // enable write dump file this cycle (valid DLL/PLL cycle) + log_data(); + // reset extended correlator + d_VE_accu = gr_complex(0,0); + d_E_accu = gr_complex(0,0); + d_P_accu = gr_complex(0,0); + d_L_accu = gr_complex(0,0); + d_VL_accu = gr_complex(0,0); + d_state = 3; //new coherent integration (correlation time extension) cycle + } + } + } + + //assign the GNURadio block output data + // current_synchro_data.System = {'E'}; + // std::string str_aux = "1B"; + // const char * str = str_aux.c_str(); // get a C style null terminated string + // std::memcpy(static_cast(current_synchro_data.Signal), str, 3); + + current_synchro_data.fs = d_fs_in; + *out[0] = current_synchro_data; + + consume_each(d_current_prn_length_samples); // this is required for gr_block derivates + d_sample_counter += d_current_prn_length_samples; // count for the processed samples + + if (current_synchro_data.Flag_valid_symbol_output) + { + return 1; + } + else + { + return 0; + } } @@ -771,8 +1239,6 @@ void galileo_e1_dll_pll_veml_tracking_cc::set_channel(unsigned int channel) } - - void galileo_e1_dll_pll_veml_tracking_cc::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) { d_acquisition_gnss_synchro = p_gnss_synchro; diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.h b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.h index 2d1aef220..f02c51b8e 100755 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.h +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.h @@ -53,8 +53,14 @@ galileo_e1_dll_pll_veml_make_tracking_cc(long if_freq, std::string dump_filename, float pll_bw_hz, float dll_bw_hz, + float pll_bw_narrow_hz, + float dll_bw_narrow_hz, float early_late_space_chips, - float very_early_late_space_chips); + float very_early_late_space_chips, + float early_late_space_narrow_chips, + float very_early_late_space_narrow_chips, + int extend_correlation_symbols, + bool track_pilot); /*! * \brief This class implements a code DLL + carrier PLL VEML (Very Early @@ -88,8 +94,14 @@ private: std::string dump_filename, float pll_bw_hz, float dll_bw_hz, + float pll_bw_narrow_hz, + float dll_bw_narrow_hz, float early_late_space_chips, - float very_early_late_space_chips); + float very_early_late_space_chips, + float early_late_space_narrow_chips, + float very_early_late_space_narrow_chips, + int extend_correlation_symbols, + bool track_pilot); galileo_e1_dll_pll_veml_tracking_cc(long if_freq, long fs_in, unsigned @@ -98,12 +110,25 @@ private: std::string dump_filename, float pll_bw_hz, float dll_bw_hz, + float pll_bw_narrow_hz, + float dll_bw_narrow_hz, float early_late_space_chips, - float very_early_late_space_chips); + float very_early_late_space_chips, + float early_late_space_narrow_chips, + float very_early_late_space_narrow_chips, + int extend_correlation_symbols, + bool track_pilot); + bool cn0_and_tracking_lock_status(); + void do_correlation_step(const gr_complex* input_samples); + void run_dll_pll(bool disable_costas_loop); void update_local_code(); - void update_local_carrier(); + bool acquire_secondary(); + + void clear_tracking_vars(); + + void log_data(); // tracking configuration vars unsigned int d_vector_length; @@ -114,16 +139,29 @@ private: long d_if_freq; long d_fs_in; + //tracking state machine + int d_state; + //Integration period in samples int d_correlation_length_samples; int d_n_correlator_taps; double d_early_late_spc_chips; double d_very_early_late_spc_chips; - float* d_ca_code; + double d_early_late_spc_narrow_chips; + double d_very_early_late_spc_narrow_chips; + + float* d_tracking_code; + float* d_data_code; float* d_local_code_shift_chips; gr_complex* d_correlator_outs; cpu_multicorrelator_real_codes multicorrelator_cpu; + //todo: currently the multicorrelator does not support adding extra correlator + //with different local code, thus we need extra multicorrelator instance. + //Implement this functionality inside multicorrelator class + //as an enhancement to increase the performance + float* d_local_code_data_shift_chips; + cpu_multicorrelator_real_codes correlator_data_cpu; //for data channel gr_complex *d_Very_Early; gr_complex *d_Early; @@ -131,6 +169,22 @@ private: gr_complex *d_Late; gr_complex *d_Very_Late; + int d_extend_correlation_symbols; + int d_extend_correlation_symbols_count; + bool d_enable_extended_integration; + int d_current_symbol; + + gr_complex d_VE_accu; + gr_complex d_E_accu; + gr_complex d_P_accu; + gr_complex d_L_accu; + gr_complex d_VL_accu; + + bool d_track_pilot; + gr_complex *d_Prompt_Data; + + double d_code_phase_step_chips; + double d_carrier_phase_step_rad; // remaining code phase and carrier phase between tracking loops double d_rem_code_phase_samples; double d_rem_carr_phase_rad; @@ -143,11 +197,24 @@ private: double d_acq_code_phase_samples; double d_acq_carrier_doppler_hz; + // tracking parameters + float d_dll_bw_hz; + float d_pll_bw_hz; + float d_dll_bw_narrow_hz; + float d_pll_bw_narrow_hz; // tracking vars + double d_carr_error_hz; + double d_carr_error_filt_hz; + double d_code_error_chips; + double d_code_error_filt_chips; + + double d_K_blk_samples; + double d_code_freq_chips; double d_carrier_doppler_hz; double d_acc_carrier_phase_rad; - double d_acc_code_phase_secs; + double d_rem_code_phase_chips; + double d_code_phase_samples; //PRN period in samples int d_current_prn_length_samples; @@ -158,16 +225,13 @@ private: // CN0 estimation and lock detector int d_cn0_estimation_counter; + std::deque d_Prompt_buffer_deque; gr_complex* d_Prompt_buffer; double d_carrier_lock_test; double d_CN0_SNV_dB_Hz; double d_carrier_lock_threshold; int d_carrier_lock_fail_counter; - // control vars - bool d_enable_tracking; - bool d_pull_in; - // file dump std::string d_dump_filename; std::ofstream d_dump_file; diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e1_tcp_connector_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_tcp_connector_tracking_cc.cc index 6204215a5..995941285 100644 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e1_tcp_connector_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_tcp_connector_tracking_cc.cc @@ -513,7 +513,12 @@ int Galileo_E1_Tcp_Connector_Tracking_cc::general_work (int noutput_items __attr consume_each(d_current_prn_length_samples); // this is needed in gr::block derivates d_sample_counter += d_current_prn_length_samples; //count for the processed samples - return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false + if (d_enable_tracking) + { + return 1; + }else{ + return 0; + } } diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc index bdc4b7d00..fd4ab4864 100644 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc @@ -642,8 +642,8 @@ int Galileo_E5a_Dll_Pll_Tracking_cc::general_work (int noutput_items __attribute // The first Prompt output not equal to 0 is synchronized with the transition of a navigation data bit. if (d_secondary_lock && d_first_transition) { - current_synchro_data.Prompt_I = static_cast((d_Prompt_data).real()); - current_synchro_data.Prompt_Q = static_cast((d_Prompt_data).imag()); + current_synchro_data.Prompt_I = static_cast(d_Prompt_data.real()); + current_synchro_data.Prompt_Q = static_cast(d_Prompt_data.imag()); current_synchro_data.Tracking_sample_counter = d_sample_counter + d_current_prn_length_samples; current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; @@ -733,7 +733,13 @@ int Galileo_E5a_Dll_Pll_Tracking_cc::general_work (int noutput_items __attribute d_secondary_delay = (d_secondary_delay + 1) % Galileo_E5a_Q_SECONDARY_CODE_LENGTH; d_sample_counter += d_current_prn_length_samples; //count for the processed samples consume_each(d_current_prn_length_samples); // this is necessary in gr::block derivates - return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false + + if (current_synchro_data.Flag_valid_symbol_output) + { + return 1; + }else{ + return 0; + } } diff --git a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_cc.cc index d6569fb81..107334df5 100644 --- a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_cc.cc @@ -1,7 +1,6 @@ /*! - * \file glonass_l1_ca_dll_pll_tracking.h - * \brief Interface of an adapter of a DLL+PLL tracking loop block - * for Glonass L1 C/A to a TrackingInterface + * \file glonass_l1_ca_dll_pll_c_aid_tracking_cc.h + * \brief Implementation of a code DLL + carrier PLL tracking block * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com * \author Luis Esteve, 2017. luis(at)epsilon-formacion.com * \author Damian Miralles, 2017. dmiralles2009(at)gmail.com @@ -218,6 +217,9 @@ glonass_l1_ca_dll_pll_c_aid_tracking_cc::glonass_l1_ca_dll_pll_c_aid_tracking_cc d_preamble_timestamp_s = 0.0; d_carrier_frequency_hz = 0.0; + d_carrier_doppler_old_hz = 0.0; + + d_glonass_freq_ch = 0; //set_min_output_buffer((long int)300); } @@ -270,13 +272,13 @@ void glonass_l1_ca_dll_pll_c_aid_tracking_cc::start_tracking() // d_carrier_doppler_hz = d_acq_carrier_doppler_hz + d_if_freq + (DFRQ1_GLO * GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN)); // d_carrier_doppler_hz = d_acq_carrier_doppler_hz; // d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); - d_carrier_frequency_hz = d_acq_carrier_doppler_hz + d_if_freq + (DFRQ1_GLO * GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN)); + d_carrier_frequency_hz = d_acq_carrier_doppler_hz + d_if_freq + (DFRQ1_GLO * static_cast(GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN))); d_carrier_doppler_hz = d_acq_carrier_doppler_hz; d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_frequency_hz / static_cast(d_fs_in); // DLL/PLL filter initialization - d_carrier_loop_filter.initialize(d_acq_carrier_doppler_hz); // The carrier loop filter implements the Doppler accumulator + d_carrier_loop_filter.initialize(d_carrier_frequency_hz); // The carrier loop filter implements the Doppler accumulator d_code_loop_filter.initialize(); // initialize the code filter // generate local reference ALWAYS starting at chip 1 (1 sample per chip) @@ -709,6 +711,7 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_cc::general_work (int noutput_items __a // ################## PLL ########################################################## // Update PLL discriminator [rads/Ti -> Secs/Ti] d_carr_phase_error_secs_Ti = pll_cloop_two_quadrant_atan(d_correlator_outs[1]) / GLONASS_TWO_PI; // prompt output + d_carrier_doppler_old_hz = d_carrier_doppler_hz; // Carrier discriminator filter // NOTICE: The carrier loop filter includes the Carrier Doppler accumulator, as described in Kaplan // Input [s/Ti] -> output [Hz] @@ -716,7 +719,7 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_cc::general_work (int noutput_items __a // PLL to DLL assistance [Secs/Ti] d_pll_to_dll_assist_secs_Ti = (d_carrier_doppler_hz * CURRENT_INTEGRATION_TIME_S) / d_glonass_freq_ch; // code Doppler frequency update - d_code_freq_chips = GLONASS_L1_CA_CODE_RATE_HZ + ((d_carrier_doppler_hz * GLONASS_L1_CA_CODE_RATE_HZ) / d_glonass_freq_ch); + d_code_freq_chips = GLONASS_L1_CA_CODE_RATE_HZ + (((d_carrier_doppler_hz - d_carrier_doppler_old_hz) * GLONASS_L1_CA_CODE_RATE_HZ) / d_glonass_freq_ch); // ################## DLL ########################################################## // DLL discriminator diff --git a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_cc.h b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_cc.h index 1aa7b72bd..d928beb29 100644 --- a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_cc.h +++ b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_cc.h @@ -1,7 +1,6 @@ /*! * \file glonass_l1_ca_dll_pll_c_aid_tracking_cc.h - * \brief Interface of an adapter of a DLL+PLL tracking loop block - * for Glonass L1 C/A to a TrackingInterface + * \brief Implementation of a code DLL + carrier PLL tracking block * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com * \author Luis Esteve, 2017. luis(at)epsilon-formacion.com * \author Damian Miralles, 2017. dmiralles2009(at)gmail.com @@ -158,6 +157,7 @@ private: double d_code_phase_step_chips; double d_carrier_doppler_hz; double d_carrier_frequency_hz; + double d_carrier_doppler_old_hz; double d_carrier_phase_step_rad; double d_acc_carrier_phase_cycles; double d_code_phase_samples; diff --git a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_sc.cc b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_sc.cc index 197e46379..7cf86026f 100644 --- a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_sc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_sc.cc @@ -1,7 +1,6 @@ /*! - * \file glonass_l1_ca_dll_pll_tracking.h - * \brief Interface of an adapter of a DLL+PLL tracking loop block - * for Glonass L1 C/A to a TrackingInterface + * \file glonass_l1_ca_dll_pll_c_aid_tracking_sc.cc + * \brief Implementation of a code DLL + carrier PLL tracking block * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com * \author Luis Esteve, 2017. luis(at)epsilon-formacion.com * \author Damian Miralles, 2017. dmiralles2009(at)gmail.com @@ -217,6 +216,11 @@ glonass_l1_ca_dll_pll_c_aid_tracking_sc::glonass_l1_ca_dll_pll_c_aid_tracking_sc d_code_error_filt_chips_Ti = 0.0; d_preamble_timestamp_s = 0.0; d_carr_phase_error_secs_Ti = 0.0; + + d_carrier_frequency_hz = 0.0; + d_carrier_doppler_old_hz = 0.0; + + d_glonass_freq_ch = 0; //set_min_output_buffer((long int)300); } @@ -265,13 +269,13 @@ void glonass_l1_ca_dll_pll_c_aid_tracking_sc::start_tracking() d_acq_code_phase_samples = corrected_acq_phase_samples; - d_carrier_doppler_hz = d_acq_carrier_doppler_hz + d_if_freq + (DFRQ1_GLO * GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN)); - // d_carrier_doppler_hz = d_acq_carrier_doppler_hz; + d_carrier_frequency_hz = d_acq_carrier_doppler_hz + d_if_freq + (DFRQ1_GLO * static_cast(GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN)));; + d_carrier_doppler_hz = d_acq_carrier_doppler_hz; - d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); + d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_frequency_hz / static_cast(d_fs_in); // DLL/PLL filter initialization - d_carrier_loop_filter.initialize(d_acq_carrier_doppler_hz); // The carrier loop filter implements the Doppler accumulator + d_carrier_loop_filter.initialize(d_carrier_frequency_hz); // The carrier loop filter implements the Doppler accumulator d_code_loop_filter.initialize(); // initialize the code filter // generate local reference ALWAYS starting at chip 1 (1 sample per chip) @@ -700,7 +704,7 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_sc::general_work (int noutput_items __a // ################## PLL ########################################################## // Update PLL discriminator [rads/Ti -> Secs/Ti] d_carr_phase_error_secs_Ti = pll_cloop_two_quadrant_atan(std::complex(d_correlator_outs_16sc[1].real(),d_correlator_outs_16sc[1].imag())) / GLONASS_TWO_PI; //prompt output - + d_carrier_doppler_old_hz = d_carrier_doppler_hz; // Carrier discriminator filter // NOTICE: The carrier loop filter includes the Carrier Doppler accumulator, as described in Kaplan // Input [s/Ti] -> output [Hz] @@ -708,7 +712,7 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_sc::general_work (int noutput_items __a // PLL to DLL assistance [Secs/Ti] d_pll_to_dll_assist_secs_Ti = (d_carrier_doppler_hz * CURRENT_INTEGRATION_TIME_S) / d_glonass_freq_ch; // code Doppler frequency update - d_code_freq_chips = GLONASS_L1_CA_CODE_RATE_HZ + ((d_carrier_doppler_hz * GLONASS_L1_CA_CODE_RATE_HZ) / d_glonass_freq_ch); + d_code_freq_chips = GLONASS_L1_CA_CODE_RATE_HZ + (((d_carrier_doppler_hz - d_carrier_doppler_old_hz) * GLONASS_L1_CA_CODE_RATE_HZ) / d_glonass_freq_ch); // ################## DLL ########################################################## // DLL discriminator diff --git a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_sc.h b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_sc.h index 6f83bac0d..e9424f9c7 100644 --- a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_sc.h +++ b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_c_aid_tracking_sc.h @@ -1,7 +1,6 @@ /*! - * \file glonass_l1_ca_dll_pll_tracking.h - * \brief Interface of an adapter of a DLL+PLL tracking loop block - * for Glonass L1 C/A to a TrackingInterface + * \file glonass_l1_ca_dll_pll_c_aid_tracking_sc.h + * \brief Implementation of a code DLL + carrier PLL tracking block * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com * \author Luis Esteve, 2017. luis(at)epsilon-formacion.com * \author Damian Miralles, 2017. dmiralles2009(at)gmail.com @@ -160,6 +159,8 @@ private: double d_code_freq_chips; double d_code_phase_step_chips; double d_carrier_doppler_hz; + double d_carrier_frequency_hz; + double d_carrier_doppler_old_hz; double d_carrier_phase_step_rad; double d_acc_carrier_phase_cycles; double d_code_phase_samples; diff --git a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.cc index c7926ac3b..c2b22a832 100644 --- a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.cc @@ -1,7 +1,6 @@ /*! - * \file glonass_l1_ca_dll_pll_tracking.h - * \brief Interface of an adapter of a DLL+PLL tracking loop block - * for Glonass L1 C/A to a TrackingInterface + * \file glonass_l1_ca_dll_pll_tracking_cc.cc + * \brief Implementation of a code DLL + carrier PLL tracking block * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com * \author Luis Esteve, 2017. luis(at)epsilon-formacion.com * \author Damian Miralles, 2017. dmiralles2009(at)gmail.com @@ -580,7 +579,7 @@ int Glonass_L1_Ca_Dll_Pll_Tracking_cc::general_work (int noutput_items __attribu carr_error_filt_hz = d_carrier_loop_filter.get_carrier_nco(carr_error_hz); // New carrier Doppler frequency estimation d_carrier_frequency_hz += carr_error_filt_hz; - d_carrier_doppler_hz = d_acq_carrier_doppler_hz + carr_error_filt_hz; + d_carrier_doppler_hz += carr_error_filt_hz; d_code_freq_chips = GLONASS_L1_CA_CODE_RATE_HZ + ((d_carrier_doppler_hz * GLONASS_L1_CA_CODE_RATE_HZ) / d_glonass_freq_ch); // ################## DLL ########################################################## diff --git a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.h b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.h index 3e7a0cb14..641c6f04e 100644 --- a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.h +++ b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.h @@ -1,7 +1,6 @@ /*! - * \file glonass_l1_ca_dll_pll_tracking.h - * \brief Interface of an adapter of a DLL+PLL tracking loop block - * for Glonass L1 C/A to a TrackingInterface + * \file glonass_l1_ca_dll_pll_tracking_cc.h + * \brief Implementation of a code DLL + carrier PLL tracking block * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com * \author Luis Esteve, 2017. luis(at)epsilon-formacion.com * \author Damian Miralles, 2017. dmiralles2009(at)gmail.com diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.cc index 4bab79242..5264b141a 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.cc @@ -875,7 +875,12 @@ int gps_l1_ca_dll_pll_c_aid_tracking_cc::general_work (int noutput_items __attri consume_each(d_correlation_length_samples); // this is necessary in gr::block derivates d_sample_counter += d_correlation_length_samples; //count for the processed samples - return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false + if (d_enable_tracking) + { + return 1; + }else{ + return 0; + } } diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc index 0b39b1ebe..464ef6493 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc @@ -694,7 +694,12 @@ int gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::general_work( //consume_each(d_correlation_length_samples); // this is necessary in gr::block derivates d_sample_counter += d_correlation_length_samples; //count for the processed samples - return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false + if (d_enable_tracking) + { + return 1; + }else{ + return 0; + } } diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_sc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_sc.cc index 8973bb6a4..2d7aa4102 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_sc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_sc.cc @@ -879,7 +879,12 @@ int gps_l1_ca_dll_pll_c_aid_tracking_sc::general_work (int noutput_items __attri consume_each(d_correlation_length_samples); // this is necessary in gr::block derivates d_sample_counter += d_correlation_length_samples; //count for the processed samples - return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false + if (d_enable_tracking) + { + return 1; + }else{ + return 0; + } } diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_cc.cc index ec5004c56..d3cbb6310 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_cc.cc @@ -185,6 +185,7 @@ Gps_L1_Ca_Dll_Pll_Tracking_cc::Gps_L1_Ca_Dll_Pll_Tracking_cc( void Gps_L1_Ca_Dll_Pll_Tracking_cc::start_tracking() { + gr::thread::scoped_lock lk(d_setlock); /* * correct the code phase according to the delay between acq and trk */ @@ -521,6 +522,7 @@ Gps_L1_Ca_Dll_Pll_Tracking_cc::~Gps_L1_Ca_Dll_Pll_Tracking_cc() int Gps_L1_Ca_Dll_Pll_Tracking_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) { + gr::thread::scoped_lock lk(d_setlock); // process vars double carr_error_hz = 0.0; double carr_error_filt_hz = 0.0; @@ -736,7 +738,13 @@ int Gps_L1_Ca_Dll_Pll_Tracking_cc::general_work (int noutput_items __attribute__ consume_each(d_current_prn_length_samples); // this is necessary in gr::block derivates d_sample_counter += d_current_prn_length_samples; // count for the processed samples - return 1; // output tracking result ALWAYS even in the case of d_enable_tracking==false + + if (d_enable_tracking) + { + return 1; + }else{ + return 0; + } } diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_gpu_cc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_gpu_cc.cc index cbd835b86..b79479d68 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_gpu_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_tracking_gpu_cc.cc @@ -536,7 +536,12 @@ int Gps_L1_Ca_Dll_Pll_Tracking_GPU_cc::general_work (int noutput_items __attribu consume_each(d_correlation_length_samples); // this is necessary in gr::block derivates d_sample_counter += d_correlation_length_samples; //count for the processed samples - return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false + if (d_enable_tracking) + { + return 1; + }else{ + return 0; + } } diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_tcp_connector_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_tcp_connector_tracking_cc.cc index 9bb40eefa..219aaff76 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_tcp_connector_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_tcp_connector_tracking_cc.cc @@ -549,7 +549,12 @@ int Gps_L1_Ca_Tcp_Connector_Tracking_cc::general_work (int noutput_items __attri d_sample_counter_seconds = d_sample_counter_seconds + ( static_cast(d_current_prn_length_samples) / static_cast(d_fs_in) ); d_sample_counter += d_current_prn_length_samples; //count for the processed samples - return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false + if (d_enable_tracking) + { + return 1; + }else{ + return 0; + } } diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l2_m_dll_pll_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l2_m_dll_pll_tracking_cc.cc index dfa1b6990..24224ede0 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l2_m_dll_pll_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l2_m_dll_pll_tracking_cc.cc @@ -729,7 +729,12 @@ int gps_l2_m_dll_pll_tracking_cc::general_work (int noutput_items __attribute__( } consume_each(d_current_prn_length_samples); // this is necessary in gr::block derivates d_sample_counter += d_current_prn_length_samples; // count for the processed samples - return 1; // output tracking result ALWAYS even in the case of d_enable_tracking==false + if (d_enable_tracking) + { + return 1; + }else{ + return 0; + } } diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l5i_dll_pll_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l5i_dll_pll_tracking_cc.cc index a515093a3..ba174dbea 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l5i_dll_pll_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l5i_dll_pll_tracking_cc.cc @@ -257,14 +257,14 @@ void gps_l5i_dll_pll_tracking_cc::start_tracking() sys = sys_.substr(0,1); // DEBUG OUTPUT - std::cout << "Tracking of GPS L2CM signal started on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl; - LOG(INFO) << "Starting GPS L2CM tracking of satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << " on channel " << d_channel; + std::cout << "Tracking of GPS L5i signal started on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl; + LOG(INFO) << "Starting GPS L5i tracking of satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << " on channel " << d_channel; // enable tracking d_pull_in = true; d_enable_tracking = true; - LOG(INFO) << "GPS L2CM PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz + LOG(INFO) << "GPS L5i PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz << " Code Phase correction [samples]=" << delay_correction_samples << " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples; } @@ -729,7 +729,14 @@ int gps_l5i_dll_pll_tracking_cc::general_work (int noutput_items __attribute__(( } consume_each(d_current_prn_length_samples); // this is necessary in gr::block derivates d_sample_counter += d_current_prn_length_samples; // count for the processed samples - return 1; // output tracking result ALWAYS even in the case of d_enable_tracking==false + if (d_enable_tracking) + { + return 1; + } + else + { + return 0; + } } diff --git a/src/core/interfaces/acquisition_interface.h b/src/core/interfaces/acquisition_interface.h index 722b99777..b6d9e4e72 100644 --- a/src/core/interfaces/acquisition_interface.h +++ b/src/core/interfaces/acquisition_interface.h @@ -53,7 +53,6 @@ templateclass concurrent_queue; class AcquisitionInterface: public GNSSBlockInterface { public: - //virtual void set_active(bool active) = 0; virtual void set_gnss_synchro(Gnss_Synchro* gnss_synchro) = 0; virtual void set_channel(unsigned int channel) = 0; virtual void set_threshold(float threshold) = 0; diff --git a/src/core/libs/supl/asn-supl/GeneralizedTime.c b/src/core/libs/supl/asn-supl/GeneralizedTime.c index 9d683efe4..2fd63f262 100644 --- a/src/core/libs/supl/asn-supl/GeneralizedTime.c +++ b/src/core/libs/supl/asn-supl/GeneralizedTime.c @@ -3,7 +3,9 @@ * Redistribution and modifications are permitted subject to BSD license. */ #define _POSIX_PTHREAD_SEMANTICS /* for Sun */ +#ifndef _REENTRANT #define _REENTRANT /* for Sun */ +#endif #include #include #include diff --git a/src/core/receiver/control_message_factory.cc b/src/core/receiver/control_message_factory.cc index 6f7994c29..a7da90ab1 100644 --- a/src/core/receiver/control_message_factory.cc +++ b/src/core/receiver/control_message_factory.cc @@ -44,18 +44,18 @@ ControlMessageFactory::~ControlMessageFactory() {} -boost::shared_ptr ControlMessageFactory::GetQueueMessage(unsigned int who, unsigned int what) +gr::message::sptr ControlMessageFactory::GetQueueMessage(unsigned int who, unsigned int what) { std::shared_ptr control_message = std::make_shared(); control_message->who = who; control_message->what = what; - boost::shared_ptr queue_message = gr::message::make(0, 0, 0, sizeof(ControlMessage)); + gr::message::sptr queue_message = gr::message::make(0, 0, 0, sizeof(ControlMessage)); memcpy(queue_message->msg(), control_message.get(), sizeof(ControlMessage)); return queue_message; } -std::shared_ptr>> ControlMessageFactory::GetControlMessages(boost::shared_ptr queue_message) +std::shared_ptr>> ControlMessageFactory::GetControlMessages(gr::message::sptr queue_message) { std::shared_ptr>> control_messages = std::make_shared>>(); unsigned int control_messages_count = queue_message->length() / sizeof(ControlMessage); diff --git a/src/core/receiver/control_message_factory.h b/src/core/receiver/control_message_factory.h index 2ff294a8c..9bdd49d32 100644 --- a/src/core/receiver/control_message_factory.h +++ b/src/core/receiver/control_message_factory.h @@ -58,7 +58,7 @@ public: //! Virtual destructor virtual ~ControlMessageFactory(); - boost::shared_ptr GetQueueMessage(unsigned int who, unsigned int what); + gr::message::sptr GetQueueMessage(unsigned int who, unsigned int what); std::shared_ptr>> GetControlMessages(gr::message::sptr queue_message); }; diff --git a/src/core/receiver/control_thread.cc b/src/core/receiver/control_thread.cc index 44cdc36d3..73b05651c 100644 --- a/src/core/receiver/control_thread.cc +++ b/src/core/receiver/control_thread.cc @@ -158,7 +158,7 @@ void ControlThread::run() } -void ControlThread::set_control_queue(boost::shared_ptr control_queue) +void ControlThread::set_control_queue(gr::msg_queue::sptr control_queue) { if (flowgraph_->running()) { @@ -445,7 +445,7 @@ void ControlThread::init() void ControlThread::read_control_messages() { DLOG(INFO) << "Reading control messages from queue"; - boost::shared_ptr queue_message = control_queue_->delete_head(); + gr::message::sptr queue_message = control_queue_->delete_head(); if (queue_message != 0) { control_messages_ = control_message_factory_->GetControlMessages(queue_message); diff --git a/src/core/receiver/control_thread.h b/src/core/receiver/control_thread.h index 1580695df..ea0decec8 100644 --- a/src/core/receiver/control_thread.h +++ b/src/core/receiver/control_thread.h @@ -89,7 +89,7 @@ public: * * \param[in] boost::shared_ptr control_queue */ - void set_control_queue(boost::shared_ptr control_queue); + void set_control_queue(gr::msg_queue::sptr control_queue); unsigned int processed_control_messages() @@ -146,7 +146,7 @@ private: void apply_action(unsigned int what); std::shared_ptr flowgraph_; std::shared_ptr configuration_; - boost::shared_ptr control_queue_; + gr::msg_queue::sptr control_queue_; std::shared_ptr control_message_factory_; std::shared_ptr>> control_messages_; bool stop_; diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index dbaa68483..ac72a0549 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -48,10 +48,11 @@ #include "nsr_file_signal_source.h" #include "two_bit_cpx_file_signal_source.h" #include "spir_file_signal_source.h" +#include "spir_gss6450_file_signal_source.h" #include "rtl_tcp_signal_source.h" #include "two_bit_packed_file_signal_source.h" +#include "labsat_signal_source.h" #include "channel.h" - #include "signal_conditioner.h" #include "array_signal_conditioner.h" #include "byte_to_short.h" @@ -93,6 +94,7 @@ #include "gps_l5i_dll_pll_tracking.h" #include "gps_l1_ca_telemetry_decoder.h" #include "gps_l2c_telemetry_decoder.h" +#include "gps_l5_telemetry_decoder.h" #include "galileo_e1b_telemetry_decoder.h" #include "galileo_e5a_telemetry_decoder.h" #include "glonass_l1_ca_telemetry_decoder.h" @@ -154,7 +156,7 @@ GNSSBlockFactory::~GNSSBlockFactory() std::unique_ptr GNSSBlockFactory::GetSignalSource( - std::shared_ptr configuration, boost::shared_ptr queue, int ID) + std::shared_ptr configuration, gr::msg_queue::sptr queue, int ID) { std::string default_implementation = "File_Signal_Source"; std::string role = "SignalSource"; //backwards compatibility for old conf files @@ -233,7 +235,6 @@ std::unique_ptr GNSSBlockFactory::GetSignalConditioner( } - std::unique_ptr GNSSBlockFactory::GetObservables(std::shared_ptr configuration) { std::string default_implementation = "Hybrid_Observables"; @@ -243,12 +244,12 @@ std::unique_ptr GNSSBlockFactory::GetObservables(std::shared Galileo_channels += configuration->property("Channels_5X.count", 0); unsigned int GPS_channels = configuration->property("Channels_1C.count", 0); 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, "Observables", implementation, Galileo_channels + GPS_channels + Glonass_channels, Galileo_channels + GPS_channels + Glonass_channels); } - std::unique_ptr GNSSBlockFactory::GetPVT(std::shared_ptr configuration) { std::string default_implementation = "RTKLIB_PVT"; @@ -258,6 +259,7 @@ std::unique_ptr GNSSBlockFactory::GetPVT(std::shared_ptrproperty("Channels_5X.count", 0); unsigned int GPS_channels = configuration->property("Channels_1C.count", 0); 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); } @@ -267,7 +269,7 @@ std::unique_ptr GNSSBlockFactory::GetPVT(std::shared_ptr GNSSBlockFactory::GetChannel_1C( std::shared_ptr configuration, std::string acq, std::string trk, std::string tlm, int channel, - boost::shared_ptr queue) + gr::msg_queue::sptr queue) { //"appendix" is added to the "role" with the aim of Acquisition, Tracking and Telemetry Decoder adapters //can find their specific configurations when they read the config @@ -331,13 +333,13 @@ std::unique_ptr GNSSBlockFactory::GetChannel_1C( return channel_; } + //********* GPS L2C (M) CHANNEL ***************** std::unique_ptr GNSSBlockFactory::GetChannel_2S( std::shared_ptr configuration, std::string acq, std::string trk, std::string tlm, int channel, - boost::shared_ptr queue) + gr::msg_queue::sptr queue) { - LOG(INFO) << "Instantiating Channel " << channel << " with Acquisition Implementation: " << acq << ", Tracking Implementation: " << trk << ", Telemetry Decoder implementation: " << tlm; std::string aux = configuration->property("Acquisition_2S" + boost::lexical_cast(channel) + ".implementation", std::string("W")); @@ -396,11 +398,12 @@ std::unique_ptr GNSSBlockFactory::GetChannel_2S( return channel_; } + //********* GALILEO E1 B CHANNEL ***************** std::unique_ptr GNSSBlockFactory::GetChannel_1B( std::shared_ptr configuration, std::string acq, std::string trk, std::string tlm, int channel, - boost::shared_ptr queue) + gr::msg_queue::sptr queue) { std::stringstream stream; stream << channel; @@ -463,11 +466,12 @@ std::unique_ptr GNSSBlockFactory::GetChannel_1B( return channel_; } + //********* GALILEO E5a CHANNEL ***************** std::unique_ptr GNSSBlockFactory::GetChannel_5X( std::shared_ptr configuration, std::string acq, std::string trk, std::string tlm, int channel, - boost::shared_ptr queue) + gr::msg_queue::sptr queue) { std::stringstream stream; stream << channel; @@ -530,6 +534,7 @@ std::unique_ptr GNSSBlockFactory::GetChannel_5X( return channel_; } + //********* GLONASS L1 C/A CHANNEL ***************** std::unique_ptr GNSSBlockFactory::GetChannel_1G( std::shared_ptr configuration, @@ -599,8 +604,76 @@ std::unique_ptr GNSSBlockFactory::GetChannel_1G( } +//********* GPS L5 CHANNEL ***************** +std::unique_ptr GNSSBlockFactory::GetChannel_L5( + std::shared_ptr 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_L5" + boost::lexical_cast(channel) + ".implementation", std::string("W")); + std::string appendix1; + if(aux.compare("W") != 0) + { + appendix1 = boost::lexical_cast(channel); + } + else + { + appendix1 = ""; + } + aux = configuration->property("Tracking_L5" + boost::lexical_cast(channel) + ".implementation", std::string("W")); + std::string appendix2; + if(aux.compare("W") != 0) + { + appendix2 = boost::lexical_cast(channel); + } + else + { + appendix2 = ""; + } + aux = configuration->property("TelemetryDecoder_L5" + boost::lexical_cast(channel) + ".implementation", std::string("W")); + std::string appendix3; + if(aux.compare("W") != 0) + { + appendix3 = boost::lexical_cast(channel); + } + else + { + appendix3 = ""; + } + // Automatically detect input data type + std::shared_ptr config; + config = std::make_shared(); + std::string default_item_type = "gr_complex"; + std::string acq_item_type = configuration->property("Acquisition_L5" + appendix1 + ".item_type", default_item_type); + std::string trk_item_type = configuration->property("Tracking_L5" + appendix2 + ".item_type", default_item_type); + if(acq_item_type.compare(trk_item_type)) + { + LOG(ERROR) << "Acquisition and Tracking blocks must have the same input data type!"; + } + config->set_property("Channel.item_type", acq_item_type); + + std::unique_ptr pass_through_ = GetBlock(configuration, "Channel", "Pass_Through", 1, 1, queue); + std::unique_ptr acq_ = GetAcqBlock(configuration, "Acquisition_L5" + appendix1, acq, 1, 0); + std::unique_ptr trk_ = GetTrkBlock(configuration, "Tracking_L5" + appendix2, trk, 1, 1); + std::unique_ptr tlm_ = GetTlmBlock(configuration, "TelemetryDecoder_L5" + appendix3, tlm, 1, 1); + + std::unique_ptr channel_(new Channel(configuration.get(), channel, std::move(pass_through_), + std::move(acq_), + std::move(trk_), + std::move(tlm_), + "Channel", "L5", queue)); + + return channel_; +} + + std::unique_ptr>> GNSSBlockFactory::GetChannels( - std::shared_ptr configuration, boost::shared_ptr queue) + std::shared_ptr configuration, gr::msg_queue::sptr queue) { std::string default_implementation = "Pass_Through"; std::string tracking_implementation; @@ -614,44 +687,45 @@ std::unique_ptr>> GNSSBlockFacto unsigned int Channels_1B_count = configuration->property("Channels_1B.count", 0); unsigned int Channels_5X_count = configuration->property("Channels_5X.count", 0); unsigned int Channels_1G_count = configuration->property("Channels_1G.count", 0); + unsigned int Channels_L5_count = configuration->property("Channels_L5.count", 0); unsigned int total_channels = Channels_1C_count + Channels_2S_count + Channels_1B_count + Channels_5X_count + - Channels_1G_count; + Channels_1G_count + + Channels_L5_count; + std::unique_ptr>> channels(new std::vector>(total_channels)); //**************** GPS L1 C/A CHANNELS ********************** - LOG(INFO) << "Getting " << Channels_1C_count << " GPS L1 C/A channels"; acquisition_implementation = configuration->property("Acquisition_1C.implementation", default_implementation); tracking_implementation = configuration->property("Tracking_1C.implementation", default_implementation); telemetry_decoder_implementation = configuration->property("TelemetryDecoder_1C.implementation", default_implementation); - for (unsigned int i = 0; i < Channels_1C_count; i++) { //(i.e. Acquisition_1C0.implementation=xxxx) std::string acquisition_implementation_specific = configuration->property( - "Acquisition_1C" + boost::lexical_cast(channel_absolute_id) + ".implementation", - acquisition_implementation); + "Acquisition_1C" + boost::lexical_cast(channel_absolute_id) + ".implementation", + acquisition_implementation); //(i.e. Tracking_1C0.implementation=xxxx) std::string tracking_implementation_specific = configuration->property( - "Tracking_1C" + boost::lexical_cast(channel_absolute_id) + ".implementation", - tracking_implementation); + "Tracking_1C" + boost::lexical_cast(channel_absolute_id) + ".implementation", + tracking_implementation); std::string telemetry_decoder_implementation_specific = configuration->property( - "TelemetryDecoder_1C" + boost::lexical_cast(channel_absolute_id) + ".implementation", - telemetry_decoder_implementation); + "TelemetryDecoder_1C" + boost::lexical_cast(channel_absolute_id) + ".implementation", + telemetry_decoder_implementation); // Push back the channel to the vector of channels - channels->at(channel_absolute_id) = std::move(GetChannel_1C(configuration, - acquisition_implementation_specific, - tracking_implementation_specific, - telemetry_decoder_implementation_specific, - channel_absolute_id, - queue)); - channel_absolute_id++; + channels->at(channel_absolute_id) = std::move(GetChannel_1C(configuration, + acquisition_implementation_specific, + tracking_implementation_specific, + telemetry_decoder_implementation_specific, + channel_absolute_id, + queue)); + channel_absolute_id++; } //**************** GPS L2C (M) CHANNELS ********************** @@ -663,86 +737,112 @@ std::unique_ptr>> GNSSBlockFacto { //(i.e. Acquisition_1C0.implementation=xxxx) std::string acquisition_implementation_specific = configuration->property( - "Acquisition_2S" + boost::lexical_cast(channel_absolute_id) + ".implementation", - acquisition_implementation); + "Acquisition_2S" + boost::lexical_cast(channel_absolute_id) + ".implementation", + acquisition_implementation); //(i.e. Tracking_1C0.implementation=xxxx) std::string tracking_implementation_specific = configuration->property( - "Tracking_2S" + boost::lexical_cast(channel_absolute_id) + ".implementation", - tracking_implementation); + "Tracking_2S" + boost::lexical_cast(channel_absolute_id) + ".implementation", + tracking_implementation); std::string telemetry_decoder_implementation_specific = configuration->property( - "TelemetryDecoder_2S" + boost::lexical_cast(channel_absolute_id) + ".implementation", - telemetry_decoder_implementation); + "TelemetryDecoder_2S" + boost::lexical_cast(channel_absolute_id) + ".implementation", + telemetry_decoder_implementation); // Push back the channel to the vector of channels - channels->at(channel_absolute_id) = std::move(GetChannel_2S(configuration, - acquisition_implementation_specific, - tracking_implementation_specific, - telemetry_decoder_implementation_specific, - channel_absolute_id, - queue)); - channel_absolute_id++; + channels->at(channel_absolute_id) = std::move(GetChannel_2S(configuration, + acquisition_implementation_specific, + tracking_implementation_specific, + telemetry_decoder_implementation_specific, + channel_absolute_id, + queue)); + channel_absolute_id++; + } + + //**************** GPS L5 CHANNELS ********************** + LOG(INFO)<< "Getting " << Channels_L5_count << " GPS L5 channels"; + tracking_implementation = configuration->property("Tracking_L5.implementation", default_implementation); + telemetry_decoder_implementation = configuration->property("TelemetryDecoder_L5.implementation", default_implementation); + acquisition_implementation = configuration->property("Acquisition_L5.implementation", default_implementation); + for (unsigned int i = 0; i < Channels_L5_count; i++) + { + //(i.e. Acquisition_1C0.implementation=xxxx) + std::string acquisition_implementation_specific = configuration->property( + "Acquisition_L5" + boost::lexical_cast(channel_absolute_id) + ".implementation", + acquisition_implementation); + //(i.e. Tracking_1C0.implementation=xxxx) + std::string tracking_implementation_specific = configuration->property( + "Tracking_L5" + boost::lexical_cast(channel_absolute_id) + ".implementation", + tracking_implementation); + std::string telemetry_decoder_implementation_specific = configuration->property( + "TelemetryDecoder_L5" + boost::lexical_cast(channel_absolute_id) + ".implementation", + telemetry_decoder_implementation); + + // Push back the channel to the vector of channels + channels->at(channel_absolute_id) = std::move(GetChannel_L5(configuration, + acquisition_implementation_specific, + tracking_implementation_specific, + telemetry_decoder_implementation_specific, + channel_absolute_id, + queue)); + channel_absolute_id++; } //**************** GALILEO E1 B (I/NAV OS) CHANNELS ********************** - LOG(INFO) << "Getting " << Channels_1B_count << " GALILEO E1 B (I/NAV OS) channels"; - tracking_implementation = configuration->property("Tracking_1B.implementation", default_implementation); - telemetry_decoder_implementation = configuration->property("TelemetryDecoder_1B.implementation", default_implementation); - acquisition_implementation = configuration->property("Acquisition_1B.implementation", default_implementation); - for (unsigned int i = 0; i < Channels_1B_count; i++) - { - //(i.e. Acquisition_1C0.implementation=xxxx) - std::string acquisition_implementation_specific = configuration->property( - "Acquisition_1B" + boost::lexical_cast(channel_absolute_id) + ".implementation", - acquisition_implementation); - //(i.e. Tracking_1C0.implementation=xxxx) - std::string tracking_implementation_specific = configuration->property( - "Tracking_1B" + boost::lexical_cast(channel_absolute_id) + ".implementation", - tracking_implementation); - std::string telemetry_decoder_implementation_specific = configuration->property( - "TelemetryDecoder_1B" + boost::lexical_cast(channel_absolute_id) + ".implementation", - telemetry_decoder_implementation); - - // Push back the channel to the vector of channels - channels->at(channel_absolute_id) = std::move(GetChannel_1B(configuration, - acquisition_implementation_specific, - tracking_implementation_specific, - telemetry_decoder_implementation_specific, - channel_absolute_id, - queue)); - channel_absolute_id++; - } + tracking_implementation = configuration->property("Tracking_1B.implementation", default_implementation); + telemetry_decoder_implementation = configuration->property("TelemetryDecoder_1B.implementation", default_implementation); + acquisition_implementation = configuration->property("Acquisition_1B.implementation", default_implementation); + for (unsigned int i = 0; i < Channels_1B_count; i++) + { + //(i.e. Acquisition_1C0.implementation=xxxx) + std::string acquisition_implementation_specific = configuration->property( + "Acquisition_1B" + boost::lexical_cast(channel_absolute_id) + ".implementation", + acquisition_implementation); + //(i.e. Tracking_1C0.implementation=xxxx) + std::string tracking_implementation_specific = configuration->property( + "Tracking_1B" + boost::lexical_cast(channel_absolute_id) + ".implementation", + tracking_implementation); + std::string telemetry_decoder_implementation_specific = configuration->property( + "TelemetryDecoder_1B" + boost::lexical_cast(channel_absolute_id) + ".implementation", + telemetry_decoder_implementation); + // Push back the channel to the vector of channels + channels->at(channel_absolute_id) = std::move(GetChannel_1B(configuration, + acquisition_implementation_specific, + tracking_implementation_specific, + telemetry_decoder_implementation_specific, + channel_absolute_id, + queue)); + channel_absolute_id++; + } //**************** GALILEO E5a I (F/NAV OS) CHANNELS ********************** LOG(INFO) << "Getting " << Channels_5X_count << " GALILEO E5a I (F/NAV OS) channels"; - tracking_implementation = configuration->property("Tracking_5X.implementation", default_implementation); - telemetry_decoder_implementation = configuration->property("TelemetryDecoder_5X.implementation", default_implementation); - acquisition_implementation = configuration->property("Acquisition_5X.implementation", default_implementation); - for (unsigned int i = 0; i < Channels_5X_count; i++) - { - //(i.e. Acquisition_1C0.implementation=xxxx) - std::string acquisition_implementation_specific = configuration->property( - "Acquisition_5X" + boost::lexical_cast(channel_absolute_id) + ".implementation", - acquisition_implementation); - //(i.e. Tracking_1C0.implementation=xxxx) - std::string tracking_implementation_specific = configuration->property( - "Tracking_5X" + boost::lexical_cast(channel_absolute_id) + ".implementation", - tracking_implementation); - std::string telemetry_decoder_implementation_specific = configuration->property( - "TelemetryDecoder_5X" + boost::lexical_cast(channel_absolute_id) + ".implementation", - telemetry_decoder_implementation); - - // Push back the channel to the vector of channels - channels->at(channel_absolute_id) = std::move(GetChannel_5X(configuration, - acquisition_implementation_specific, - tracking_implementation_specific, - telemetry_decoder_implementation_specific, - channel_absolute_id, - queue)); - channel_absolute_id++; - } + tracking_implementation = configuration->property("Tracking_5X.implementation", default_implementation); + telemetry_decoder_implementation = configuration->property("TelemetryDecoder_5X.implementation", default_implementation); + acquisition_implementation = configuration->property("Acquisition_5X.implementation", default_implementation); + for (unsigned int i = 0; i < Channels_5X_count; i++) + { + //(i.e. Acquisition_1C0.implementation=xxxx) + std::string acquisition_implementation_specific = configuration->property( + "Acquisition_5X" + boost::lexical_cast(channel_absolute_id) + ".implementation", + acquisition_implementation); + //(i.e. Tracking_1C0.implementation=xxxx) + std::string tracking_implementation_specific = configuration->property( + "Tracking_5X" + boost::lexical_cast(channel_absolute_id) + ".implementation", + tracking_implementation); + std::string telemetry_decoder_implementation_specific = configuration->property( + "TelemetryDecoder_5X" + boost::lexical_cast(channel_absolute_id) + ".implementation", + telemetry_decoder_implementation); + // Push back the channel to the vector of channels + channels->at(channel_absolute_id) = std::move(GetChannel_5X(configuration, + acquisition_implementation_specific, + tracking_implementation_specific, + telemetry_decoder_implementation_specific, + channel_absolute_id, + queue)); + channel_absolute_id++; + } //**************** GLONASS L1 C/A CHANNELS ********************** LOG(INFO) << "Getting " << Channels_1G_count << " GLONASS L1 C/A channels"; @@ -754,29 +854,30 @@ std::unique_ptr>> GNSSBlockFacto { //(i.e. Acquisition_1G0.implementation=xxxx) std::string acquisition_implementation_specific = configuration->property( - "Acquisition_1G" + boost::lexical_cast(channel_absolute_id) + ".implementation", - acquisition_implementation); + "Acquisition_1G" + boost::lexical_cast(channel_absolute_id) + ".implementation", + acquisition_implementation); //(i.e. Tracking_1G0.implementation=xxxx) std::string tracking_implementation_specific = configuration->property( - "Tracking_1G" + boost::lexical_cast(channel_absolute_id) + ".implementation", - tracking_implementation); + "Tracking_1G" + boost::lexical_cast(channel_absolute_id) + ".implementation", + tracking_implementation); std::string telemetry_decoder_implementation_specific = configuration->property( - "TelemetryDecoder_1G" + boost::lexical_cast(channel_absolute_id) + ".implementation", - telemetry_decoder_implementation); + "TelemetryDecoder_1G" + boost::lexical_cast(channel_absolute_id) + ".implementation", + telemetry_decoder_implementation); // Push back the channel to the vector of channels - channels->at(channel_absolute_id) = std::move(GetChannel_1G(configuration, - acquisition_implementation_specific, - tracking_implementation_specific, - telemetry_decoder_implementation_specific, - channel_absolute_id, - queue)); - channel_absolute_id++; + channels->at(channel_absolute_id) = std::move(GetChannel_1G(configuration, + acquisition_implementation_specific, + tracking_implementation_specific, + telemetry_decoder_implementation_specific, + channel_absolute_id, + queue)); + channel_absolute_id++; } return channels; } + /* * Returns the block with the required configuration and implementation * @@ -790,7 +891,7 @@ std::unique_ptr GNSSBlockFactory::GetBlock( std::shared_ptr configuration, std::string role, std::string implementation, unsigned int in_streams, - unsigned int out_streams, boost::shared_ptr queue) + unsigned int out_streams, gr::msg_queue::sptr queue) { std::unique_ptr block; @@ -871,6 +972,21 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams, queue)); block = std::move(block_); + } + catch (const std::exception &e) + { + std::cout << "GNSS-SDR program ended." << std::endl; + exit(1); + } + } + else if (implementation.compare("Spir_GSS6450_File_Signal_Source") == 0) + { + try + { + std::unique_ptr block_(new SpirGSS6450FileSignalSource(configuration.get(), role, in_streams, + out_streams, queue)); + block = std::move(block_); + } catch (const std::exception &e) { @@ -887,6 +1003,21 @@ std::unique_ptr GNSSBlockFactory::GetBlock( block = std::move(block_); } + catch (const std::exception &e) + { + std::cout << "GNSS-SDR program ended." << std::endl; + exit(1); + } + } + else if (implementation.compare("Labsat_Signal_Source") == 0) + { + try + { + std::unique_ptr block_(new LabsatSignalSource(configuration.get(), role, in_streams, + out_streams, queue)); + block = std::move(block_); + } + catch (const std::exception &e) { std::cout << "GNSS-SDR program ended." << std::endl; @@ -1031,7 +1162,6 @@ std::unique_ptr GNSSBlockFactory::GetBlock( block = std::move(block_); } - // RESAMPLER ------------------------------------------------------------------- else if (implementation.compare("Direct_Resampler") == 0) { @@ -1145,9 +1275,6 @@ std::unique_ptr GNSSBlockFactory::GetBlock( block = std::move(block_); } - - - // TRACKING BLOCKS ------------------------------------------------------------- else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking") == 0) { @@ -1239,6 +1366,12 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } + else if (implementation.compare("GPS_L5_Telemetry_Decoder") == 0) + { + std::unique_ptr block_(new GpsL5TelemetryDecoder(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } else if (implementation.compare("Galileo_E1B_Telemetry_Decoder") == 0) { std::unique_ptr block_(new GalileoE1BTelemetryDecoder(configuration.get(), role, in_streams, @@ -1272,6 +1405,7 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } + // PVT ------------------------------------------------------------------------- else if ((implementation.compare("RTKLIB_PVT") == 0) || (implementation.compare("GPS_L1_CA_PVT") == 0) || (implementation.compare("Galileo_E1_PVT") == 0) || (implementation.compare("Hybrid_PVT") == 0)) { @@ -1555,6 +1689,12 @@ std::unique_ptr GNSSBlockFactory::GetTlmBlock( out_streams)); block = std::move(block_); } + else if (implementation.compare("GPS_L5_Telemetry_Decoder") == 0) + { + std::unique_ptr block_(new GpsL5TelemetryDecoder(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } else { // Log fatal. This causes execution to stop. diff --git a/src/core/receiver/gnss_block_factory.h b/src/core/receiver/gnss_block_factory.h index 6dd6ae11f..4aa852d74 100644 --- a/src/core/receiver/gnss_block_factory.h +++ b/src/core/receiver/gnss_block_factory.h @@ -57,7 +57,7 @@ public: GNSSBlockFactory(); virtual ~GNSSBlockFactory(); std::unique_ptr GetSignalSource(std::shared_ptr configuration, - boost::shared_ptr queue, int ID = -1); + gr::msg_queue::sptr queue, int ID = -1); std::unique_ptr GetSignalConditioner(std::shared_ptr configuration, int ID = -1); @@ -66,7 +66,7 @@ public: std::unique_ptr GetObservables(std::shared_ptr configuration); std::unique_ptr>> GetChannels(std::shared_ptr configuration, - boost::shared_ptr queue); + gr::msg_queue::sptr queue); /* * \brief Returns the block with the required configuration and implementation @@ -74,25 +74,29 @@ public: std::unique_ptr GetBlock(std::shared_ptr configuration, std::string role, std::string implementation, unsigned int in_streams, unsigned int out_streams, - boost::shared_ptr queue = nullptr); + gr::msg_queue::sptr queue = nullptr); private: std::unique_ptr GetChannel_1C(std::shared_ptr configuration, std::string acq, std::string trk, std::string tlm, int channel, - boost::shared_ptr queue); + gr::msg_queue::sptr queue); std::unique_ptr GetChannel_2S(std::shared_ptr configuration, std::string acq, std::string trk, std::string tlm, int channel, - boost::shared_ptr queue); + gr::msg_queue::sptr queue); std::unique_ptr GetChannel_1B(std::shared_ptr configuration, std::string acq, std::string trk, std::string tlm, int channel, - boost::shared_ptr queue); + gr::msg_queue::sptr queue); std::unique_ptr GetChannel_5X(std::shared_ptr configuration, std::string acq, std::string trk, std::string tlm, int channel, - boost::shared_ptr queue); + gr::msg_queue::sptr queue); + + std::unique_ptr GetChannel_L5(std::shared_ptr configuration, + std::string acq, std::string trk, std::string tlm, int channel, + gr::msg_queue::sptr queue); std::unique_ptr GetChannel_1G(std::shared_ptr configuration, std::string acq, std::string trk, std::string tlm, int channel, diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index 388eb5dce..1b4438cea 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -33,7 +33,6 @@ */ #include "gnss_flowgraph.h" -#include #include #include #include @@ -51,8 +50,7 @@ using google::LogMessage; -GNSSFlowgraph::GNSSFlowgraph(std::shared_ptr configuration, - boost::shared_ptr queue) +GNSSFlowgraph::GNSSFlowgraph(std::shared_ptr configuration, gr::msg_queue::sptr queue) { connected_ = false; running_ = false; @@ -91,12 +89,6 @@ void GNSSFlowgraph::start() void GNSSFlowgraph::stop() { - // for (unsigned int i = 0; i < channels_count_; i++) - // { - // channels_.at(i)->stop_channel(); - // LOG(INFO) << "Channel " << i << " in state " << channels_state_[i]; - // } - // LOG(INFO) << "Threads finished. Return to main program."; top_block_->stop(); running_ = false; } @@ -291,18 +283,13 @@ void GNSSFlowgraph::connect() } std::string gnss_signal = channels_.at(i)->get_signal().get_signal_str(); // use channel's implicit signal! - while (gnss_signal.compare(available_GNSS_signals_.front().get_signal_str()) != 0 ) - { - available_GNSS_signals_.push_back(available_GNSS_signals_.front()); - available_GNSS_signals_.pop_front(); - } - channels_.at(i)->set_signal(available_GNSS_signals_.front()); + channels_.at(i)->set_signal(search_next_signal(gnss_signal, false)); if (channels_state_[i] == 1) { channels_.at(i)->start_acquisition(); available_GNSS_signals_.pop_front(); - LOG(INFO) << "Channel " << i << " assigned to " << available_GNSS_signals_.front(); + LOG(INFO) << "Channel " << i << " assigned to " << channels_.at(i)->get_signal(); LOG(INFO) << "Channel " << i << " connected to observables and ready for acquisition"; } else @@ -373,77 +360,59 @@ bool GNSSFlowgraph::send_telemetry_msg(pmt::pmt_t msg) */ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what) { - DLOG(INFO) << "received " << what << " from " << who; - + DLOG(INFO) << "Received " << what << " from " << who << ". Number of applied actions = " << applied_actions_; switch (what) { case 0: - LOG(INFO) << "Channel " << who << " ACQ FAILED satellite " << channels_.at(who)->get_signal().get_satellite() << ", Signal " << channels_.at(who)->get_signal().get_signal_str(); + DLOG(INFO) << "Channel " << who << " ACQ FAILED satellite " << channels_.at(who)->get_signal().get_satellite() << ", Signal " << channels_.at(who)->get_signal().get_signal_str(); available_GNSS_signals_.push_back(channels_.at(who)->get_signal()); - //TODO: Optimize the channel and signal matching! - while ( channels_.at(who)->get_signal().get_signal_str().compare(available_GNSS_signals_.front().get_signal_str()) != 0 ) - { - available_GNSS_signals_.push_back(available_GNSS_signals_.front()); - available_GNSS_signals_.pop_front(); - } - channels_.at(who)->set_signal(available_GNSS_signals_.front()); - available_GNSS_signals_.pop_front(); - usleep(100); - LOG(INFO) << "Channel "<< who << " Starting acquisition " << channels_.at(who)->get_signal().get_satellite() << ", Signal " << channels_.at(who)->get_signal().get_signal_str(); + channels_.at(who)->set_signal(search_next_signal(channels_.at(who)->get_signal().get_signal_str(), true)); + DLOG(INFO) << "Channel "<< who << " Starting acquisition " << channels_.at(who)->get_signal().get_satellite() << ", Signal " << channels_.at(who)->get_signal().get_signal_str(); channels_.at(who)->start_acquisition(); break; + case 1: LOG(INFO) << "Channel " << who << " ACQ SUCCESS satellite " << channels_.at(who)->get_signal().get_satellite(); channels_state_[who] = 2; acq_channels_count_--; - if (!available_GNSS_signals_.empty() && acq_channels_count_ < max_acq_channels_) + for (unsigned int i = 0; i < channels_count_; i++) { - for (unsigned int i = 0; i < channels_count_; i++) + if(!available_GNSS_signals_.empty() && (acq_channels_count_ < max_acq_channels_) && (channels_state_[i] == 0)) { - if (channels_state_[i] == 0) - { - channels_state_[i] = 1; - while (channels_.at(i)->get_signal().get_signal_str().compare(available_GNSS_signals_.front().get_signal_str()) != 0 ) - { - available_GNSS_signals_.push_back(available_GNSS_signals_.front()); - available_GNSS_signals_.pop_front(); - } - channels_.at(i)->set_signal(available_GNSS_signals_.front()); - available_GNSS_signals_.pop_front(); - acq_channels_count_++; - channels_.at(i)->start_acquisition(); - break; - } - DLOG(INFO) << "Channel " << i << " in state " << channels_state_[i]; + channels_state_[i] = 1; + channels_.at(i)->set_signal(search_next_signal(channels_.at(i)->get_signal().get_signal_str(), true)); + acq_channels_count_++; + DLOG(INFO) << "Channel "<< i << " Starting acquisition " << channels_.at(i)->get_signal().get_satellite() << ", Signal " << channels_.at(i)->get_signal().get_signal_str(); + channels_.at(i)->start_acquisition(); } + DLOG(INFO) << "Channel " << i << " in state " << channels_state_[i]; } - break; case 2: LOG(INFO) << "Channel " << who << " TRK FAILED satellite " << channels_.at(who)->get_signal().get_satellite(); + DLOG(INFO) << "Number of channels in acquisition = " << acq_channels_count_; + if (acq_channels_count_ < max_acq_channels_) { channels_state_[who] = 1; acq_channels_count_++; + LOG(INFO) << "Channel "<< who << " Starting acquisition " << channels_.at(who)->get_signal().get_satellite() << ", Signal " << channels_.at(who)->get_signal().get_signal_str(); channels_.at(who)->start_acquisition(); } else { channels_state_[who] = 0; + LOG(INFO) << "Channel "<< who << " Idle state"; available_GNSS_signals_.push_back( channels_.at(who)->get_signal() ); } - - // for (unsigned int i = 0; i < channels_count_; i++) - // { - // LOG(INFO) << "Channel " << i << " in state " << channels_state_[i] << std::endl; - // } break; default: break; } DLOG(INFO) << "Number of available signals: " << available_GNSS_signals_.size(); + applied_actions_++; } @@ -555,7 +524,6 @@ void GNSSFlowgraph::init() set_signals_list(); set_channels_state(); applied_actions_ = 0; - DLOG(INFO) << "Blocks instantiated. " << channels_count_ << " channels."; } @@ -580,7 +548,9 @@ void GNSSFlowgraph::set_signals_list() configuration_->property("Channels_2S.count", 0) + configuration_->property("Channels_1B.count", 0) + configuration_->property("Channels_5X.count", 0) + - configuration_->property("Channels_1G.count", 0); + configuration_->property("Channels_1G.count", 0) + + configuration_->property("Channels_5X.count", 0) + + configuration_->property("Channels_L5.count", 0); /* * Loop to create the list of GNSS Signals @@ -692,6 +662,19 @@ void GNSSFlowgraph::set_signals_list() } } + if (configuration_->property("Channels_L5.count", 0) > 0) + { + /* + * Loop to create GPS L5 signals + */ + for (available_gnss_prn_iter = available_gps_prn.cbegin(); + available_gnss_prn_iter != available_gps_prn.cend(); + available_gnss_prn_iter++) + { + available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("GPS"), + *available_gnss_prn_iter), std::string("L5"))); + } + } if (configuration_->property("Channels_SBAS.count", 0) > 0) { /* @@ -710,7 +693,7 @@ void GNSSFlowgraph::set_signals_list() if (configuration_->property("Channels_1B.count", 0) > 0) { /* - * Loop to create the list of Galileo E1 B signals + * Loop to create the list of Galileo E1B signals */ for (available_gnss_prn_iter = available_galileo_prn.cbegin(); available_gnss_prn_iter != available_galileo_prn.cend(); @@ -724,7 +707,7 @@ void GNSSFlowgraph::set_signals_list() if (configuration_->property("Channels_5X.count", 0) > 0 ) { /* - * Loop to create the list of Galileo E1 B signals + * Loop to create the list of Galileo E5a signals */ for (available_gnss_prn_iter = available_galileo_prn.cbegin(); available_gnss_prn_iter != available_galileo_prn.cend(); @@ -759,7 +742,7 @@ void GNSSFlowgraph::set_signals_list() { std::string gnss_signal = (configuration_->property("Channel" + boost::lexical_cast(i) + ".signal", std::string("1C"))); std::string gnss_system; - if((gnss_signal.compare("1C") == 0) or (gnss_signal.compare("2S") == 0) ) gnss_system = "GPS"; + if((gnss_signal.compare("1C") == 0) or (gnss_signal.compare("2S") == 0) or (gnss_signal.compare("L5") == 0)) gnss_system = "GPS"; if((gnss_signal.compare("1B") == 0) or (gnss_signal.compare("5X") == 0) ) gnss_system = "Galileo"; if((gnss_signal.compare("1G") == 0)/*or (gnss_signal.compare("") == 0)*/) gnss_system = "Glonass"; unsigned int sat = configuration_->property("Channel" + boost::lexical_cast(i) + ".satellite", 0); @@ -775,14 +758,6 @@ void GNSSFlowgraph::set_signals_list() gnss_it = available_GNSS_signals_.insert(gnss_it, signal_value); } } - - // **** FOR DEBUGGING THE LIST OF GNSS SIGNALS **** - // std::list::const_iterator available_gnss_list_iter; - // for (available_gnss_list_iter = available_GNSS_signals_.cbegin(); available_gnss_list_iter - // != available_GNSS_signals_.cend(); available_gnss_list_iter++) - // { - // std::cout << *available_gnss_list_iter << std::endl; - // } } @@ -797,14 +772,22 @@ void GNSSFlowgraph::set_channels_state() channels_state_.reserve(channels_count_); for (unsigned int i = 0; i < channels_count_; i++) { - if (i < max_acq_channels_) - { - channels_state_.push_back(1); - } - else - channels_state_.push_back(0); + if (i < max_acq_channels_) {channels_state_.push_back(1);} + else {channels_state_.push_back(0);} DLOG(INFO) << "Channel " << i << " in state " << channels_state_[i]; } acq_channels_count_ = max_acq_channels_; DLOG(INFO) << acq_channels_count_ << " channels in acquisition state"; } + +Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool pop) +{ + while(searched_signal.compare(available_GNSS_signals_.front().get_signal_str()) != 0) + { + available_GNSS_signals_.push_back(available_GNSS_signals_.front()); + available_GNSS_signals_.pop_front(); + } + Gnss_Signal result = available_GNSS_signals_.front(); + if(pop){available_GNSS_signals_.pop_front();} + return result; +} diff --git a/src/core/receiver/gnss_flowgraph.h b/src/core/receiver/gnss_flowgraph.h index d765d3cf4..abb4a6ef5 100644 --- a/src/core/receiver/gnss_flowgraph.h +++ b/src/core/receiver/gnss_flowgraph.h @@ -63,8 +63,7 @@ public: /*! * \brief Constructor that initializes the receiver flowgraph */ - GNSSFlowgraph(std::shared_ptr configuration, - boost::shared_ptr queue); + GNSSFlowgraph(std::shared_ptr configuration, gr::msg_queue::sptr queue); /*! * \brief Virtual destructor @@ -119,6 +118,7 @@ private: void set_signals_list(); void set_channels_state(); // Initializes the channels state (start acquisition or keep standby) // using the configuration parameters (number of channels and max channels in acquisition) + Gnss_Signal search_next_signal(std::string searched_signal, bool pop); bool connected_; bool running_; int sources_count_; @@ -139,7 +139,7 @@ private: std::vector> channels_; gnss_sdr_sample_counter_sptr ch_out_sample_counter; gr::top_block_sptr top_block_; - boost::shared_ptr queue_; + gr::msg_queue::sptr queue_; std::list available_GNSS_signals_; std::vector channels_state_; }; diff --git a/src/core/system_parameters/GLONASS_L1_CA.h b/src/core/system_parameters/GLONASS_L1_CA.h index 28c634ff3..af0bd0227 100644 --- a/src/core/system_parameters/GLONASS_L1_CA.h +++ b/src/core/system_parameters/GLONASS_L1_CA.h @@ -32,6 +32,7 @@ #ifndef GNSS_SDR_GLONASS_L1_CA_H_ #define GNSS_SDR_GLONASS_L1_CA_H_ +#include #include #include // std::pair #include "MATH_CONSTANTS.h" @@ -50,7 +51,7 @@ const double GLONASS_FLATTENING = 1/29825784; //!< Flatten const double GLONASS_GRAVITY = 97803284; //!< Equatorial acceleration of gravity [mGal] const double GLONASS_GRAVITY_CORRECTION = 0.87; //!< Correction to acceleration of gravity at sea-level due to Atmosphere[мGal] const double GLONASS_J2 = 1082625.75e-9; //!< Second zonal harmonic of the geopotential -const double GLONASS_J4 = -2370.89e-9; //!. + * + * ------------------------------------------------------------------------- + */ + + +#ifndef GNSS_SDR_GPS_CNAV_H_ +#define GNSS_SDR_GPS_CNAV_H_ + +#include +#include +#include // std::pair +#include "MATH_CONSTANTS.h" + +// CNAV GPS NAVIGATION MESSAGE STRUCTURE +// NAVIGATION MESSAGE FIELDS POSITIONS (from IS-GPS-200E Appendix III) + +#define GPS_CNAV_PREAMBLE {1, 0, 0, 0, 1, 0, 1, 1} +#define GPS_CNAV_PREAMBLE_STR "10001011" +#define GPS_CNAV_INV_PREAMBLE_STR "01110100" + +const int GPS_CNAV_DATA_PAGE_BITS = 300; + +// common to all messages +const std::vector > CNAV_PRN( { {9,6} } ); +const std::vector > CNAV_MSG_TYPE( { {15,6} } ); +const std::vector > CNAV_TOW( { {21,17} } ); //GPS Time Of Week in seconds +const double CNAV_TOW_LSB = 6.0; +const std::vector > CNAV_ALERT_FLAG( { {38,1} } ); + +// MESSAGE TYPE 10 (Ephemeris 1) + +const std::vector > CNAV_WN({{39,13}}); +const std::vector > CNAV_HEALTH({{52,3}}); +const std::vector > CNAV_TOP1({{55,11}}); +const double CNAV_TOP1_LSB = 300.0; +const std::vector > CNAV_URA({{66,5}}); + +const std::vector > CNAV_TOE1({{71,11}}); +const double CNAV_TOE1_LSB = 300.0; + +const std::vector > CNAV_DELTA_A({{82,26}}); //Relative to AREF = 26,559,710 meters +const double CNAV_DELTA_A_LSB = TWO_N9; + +const std::vector > CNAV_A_DOT({{108,25}}); +const double CNAV_A_DOT_LSB = TWO_N21; + +const std::vector > CNAV_DELTA_N0({{133,17}}); +const double CNAV_DELTA_N0_LSB = TWO_N44*PI; //semi-circles to radians +const std::vector > CNAV_DELTA_N0_DOT({{150,23}}); +const double CNAV_DELTA_N0_DOT_LSB = TWO_N57*PI;//semi-circles to radians +const std::vector > CNAV_M0({{173,33}}); +const double CNAV_M0_LSB = TWO_N32*PI;//semi-circles to radians +const std::vector > CNAV_E_ECCENTRICITY({{206,33}}); +const double CNAV_E_ECCENTRICITY_LSB = TWO_N34; +const std::vector > CNAV_OMEGA({{239,33}}); +const double CNAV_OMEGA_LSB = TWO_N32*PI;//semi-circles to radians +const std::vector > CNAV_INTEGRITY_FLAG({{272,1}}); +const std::vector > CNAV_L2_PHASING_FLAG({{273,1}}); + +// MESSAGE TYPE 11 (Ephemeris 2) + +const std::vector > CNAV_TOE2({{39,11}}); +const double CNAV_TOE2_LSB = 300.0; +const std::vector > CNAV_OMEGA0({{50,33}}); +const double CNAV_OMEGA0_LSB = TWO_N32*PI;//semi-circles to radians +const std::vector > CNAV_I0({{83,33}}); +const double CNAV_I0_LSB = TWO_N32*PI;//semi-circles to radians +const std::vector > CNAV_DELTA_OMEGA_DOT({{116,17}}); //Relative to REF = -2.6 x 10-9 semi-circles/second. +const double CNAV_DELTA_OMEGA_DOT_LSB = TWO_N44*PI;//semi-circles to radians +const std::vector > CNAV_I0_DOT({{133,15}}); +const double CNAV_I0_DOT_LSB = TWO_N44*PI;//semi-circles to radians +const std::vector > CNAV_CIS({{148,16}}); +const double CNAV_CIS_LSB = TWO_N30; +const std::vector > CNAV_CIC({{164,16}}); +const double CNAV_CIC_LSB = TWO_N30; +const std::vector > CNAV_CRS({{180,24}}); +const double CNAV_CRS_LSB = TWO_N8; +const std::vector > CNAV_CRC({{204,24}}); +const double CNAV_CRC_LSB = TWO_N8; +const std::vector > CNAV_CUS({{228,21}}); +const double CNAV_CUS_LSB = TWO_N30; +const std::vector > CNAV_CUC({{249,21}}); +const double CNAV_CUC_LSB = TWO_N30; + + +// MESSAGE TYPE 30 (CLOCK, IONO, GRUP DELAY) + +const std::vector > CNAV_TOP2({{39,11}}); +const double CNAV_TOP2_LSB = 300.0; +const std::vector > CNAV_URA_NED0({{50,5}}); +const std::vector > CNAV_URA_NED1({{55,3}}); +const std::vector > CNAV_URA_NED2({{58,3}}); +const std::vector > CNAV_TOC({{61,11}}); +const double CNAV_TOC_LSB = 300.0; +const std::vector > CNAV_AF0({{72,26}}); +const double CNAV_AF0_LSB = TWO_N60; +const std::vector > CNAV_AF1({{98,20}}); +const double CNAV_AF1_LSB = TWO_N48; +const std::vector > CNAV_AF2({{118,10}}); +const double CNAV_AF2_LSB = TWO_N35; +const std::vector > CNAV_TGD({{128,13}}); +const double CNAV_TGD_LSB = TWO_N35; +const std::vector > CNAV_ISCL1({{141,13}}); +const double CNAV_ISCL1_LSB = TWO_N35; +const std::vector > CNAV_ISCL2({{154,13}}); +const double CNAV_ISCL2_LSB = TWO_N35; +const std::vector > CNAV_ISCL5I({{167,13}}); +const double CNAV_ISCL5I_LSB = TWO_N35; +const std::vector > CNAV_ISCL5Q({{180,13}}); +const double CNAV_ISCL5Q_LSB = TWO_N35; +//Ionospheric parameters +const std::vector > CNAV_ALPHA0({{193,8}}); +const double CNAV_ALPHA0_LSB = TWO_N30; +const std::vector > CNAV_ALPHA1({{201,8}}); +const double CNAV_ALPHA1_LSB = TWO_N27; +const std::vector > CNAV_ALPHA2({{209,8}}); +const double CNAV_ALPHA2_LSB = TWO_N24; +const std::vector > CNAV_ALPHA3({{217,8}}); +const double CNAV_ALPHA3_LSB = TWO_N24; +const std::vector > CNAV_BETA0({{225,8}}); +const double CNAV_BETA0_LSB = TWO_P11; +const std::vector > CNAV_BETA1({{233,8}}); +const double CNAV_BETA1_LSB = TWO_P14; +const std::vector > CNAV_BETA2({{241,8}}); +const double CNAV_BETA2_LSB = TWO_P16; +const std::vector > CNAV_BETA3({{249,8}}); +const double CNAV_BETA3_LSB = TWO_P16; +const std::vector > CNAV_WNOP({{257,8}}); + + +// MESSAGE TYPE 33 (CLOCK and UTC) + +const std::vector > CNAV_A0({{128,16}}); +const double CNAV_A0_LSB = TWO_N35; +const std::vector > CNAV_A1({{144,13}}); +const double CNAV_A1_LSB = TWO_N51; +const std::vector > CNAV_A2({{157,7}}); +const double CNAV_A2_LSB = TWO_N68; +const std::vector > CNAV_DELTA_TLS({{164,8}}); +const double CNAV_DELTA_TLS_LSB = 1; +const std::vector > CNAV_TOT({{172,16}}); +const double CNAV_TOT_LSB = TWO_P4; +const std::vector > CNAV_WN_OT({{188,13}}); +const double CNAV_WN_OT_LSB = 1; +const std::vector > CNAV_WN_LSF({{201,13}}); +const double CNAV_WN_LSF_LSB = 1; +const std::vector > CNAV_DN({{214,4}}); +const double CNAV_DN_LSB = 1; +const std::vector > CNAV_DELTA_TLSF({{218,8}}); +const double CNAV_DELTA_TLSF_LSB = 1; + + +// TODO: Add more frames (Almanac, etc...) + + + +#endif /* GNSS_SDR_GPS_CNAV_H_ */ diff --git a/src/core/system_parameters/GPS_L2C.h b/src/core/system_parameters/GPS_L2C.h index babbc59ce..70a8e5ff3 100644 --- a/src/core/system_parameters/GPS_L2C.h +++ b/src/core/system_parameters/GPS_L2C.h @@ -37,6 +37,7 @@ #include // std::pair #include "MATH_CONSTANTS.h" #include "gnss_frequencies.h" +#include "GPS_CNAV.h" // Physical constants const double GPS_L2_C_m_s = 299792458.0; //!< The speed of light, [m/s] @@ -92,152 +93,10 @@ const int32_t GPS_L2C_M_INIT_REG[115] = 0706202440, 0705056276, 0020373522, 0746013617, 0132720621, 0434015513, 0566721727, 0140633660}; -// CNAV GPS NAVIGATION MESSAGE STRUCTURE -// NAVIGATION MESSAGE FIELDS POSITIONS (from IS-GPS-200E Appendix III) - -#define GPS_CNAV_PREAMBLE {1, 0, 0, 0, 1, 0, 1, 1} -#define GPS_CNAV_PREAMBLE_STR "10001011" -#define GPS_CNAV_INV_PREAMBLE_STR "01110100" - const int GPS_L2_CNAV_DATA_PAGE_BITS = 300; //!< GPS L2 CNAV page length, including preamble and CRC [bits] const int GPS_L2_SYMBOLS_PER_BIT = 2; const int GPS_L2_SAMPLES_PER_SYMBOL = 1; const int GPS_L2_CNAV_DATA_PAGE_SYMBOLS = 600; const int GPS_L2_CNAV_DATA_PAGE_DURATION_S = 12; -// common to all messages -const std::vector > CNAV_PRN( { {9,6} } ); -const std::vector > CNAV_MSG_TYPE( { {15,6} } ); -const std::vector > CNAV_TOW( { {21,17} } ); //GPS Time Of Week in seconds -const double CNAV_TOW_LSB = 6.0; -const std::vector > CNAV_ALERT_FLAG( { {38,1} } ); - -// MESSAGE TYPE 10 (Ephemeris 1) - -const std::vector > CNAV_WN({{39,13}}); -const std::vector > CNAV_HEALTH({{52,3}}); -const std::vector > CNAV_TOP1({{55,11}}); -const double CNAV_TOP1_LSB = 300.0; -const std::vector > CNAV_URA({{66,5}}); - -const std::vector > CNAV_TOE1({{71,11}}); -const double CNAV_TOE1_LSB = 300.0; - -const std::vector > CNAV_DELTA_A({{82,26}}); //Relative to AREF = 26,559,710 meters -const double CNAV_DELTA_A_LSB = TWO_N9; - -const std::vector > CNAV_A_DOT({{108,25}}); -const double CNAV_A_DOT_LSB = TWO_N21; - -const std::vector > CNAV_DELTA_N0({{133,17}}); -const double CNAV_DELTA_N0_LSB = TWO_N44*GPS_L2_PI; //semi-circles to radians -const std::vector > CNAV_DELTA_N0_DOT({{150,23}}); -const double CNAV_DELTA_N0_DOT_LSB = TWO_N57*GPS_L2_PI;//semi-circles to radians -const std::vector > CNAV_M0({{173,33}}); -const double CNAV_M0_LSB = TWO_N32*GPS_L2_PI;//semi-circles to radians -const std::vector > CNAV_E_ECCENTRICITY({{206,33}}); -const double CNAV_E_ECCENTRICITY_LSB = TWO_N34; -const std::vector > CNAV_OMEGA({{239,33}}); -const double CNAV_OMEGA_LSB = TWO_N32*GPS_L2_PI;//semi-circles to radians -const std::vector > CNAV_INTEGRITY_FLAG({{272,1}}); -const std::vector > CNAV_L2_PHASING_FLAG({{273,1}}); - -// MESSAGE TYPE 11 (Ephemeris 2) - -const std::vector > CNAV_TOE2({{39,11}}); -const double CNAV_TOE2_LSB = 300.0; -const std::vector > CNAV_OMEGA0({{50,33}}); -const double CNAV_OMEGA0_LSB = TWO_N32*GPS_L2_PI;//semi-circles to radians -const std::vector > CNAV_I0({{83,33}}); -const double CNAV_I0_LSB = TWO_N32*GPS_L2_PI;//semi-circles to radians -const std::vector > CNAV_DELTA_OMEGA_DOT({{116,17}}); //Relative to REF = -2.6 x 10-9 semi-circles/second. -const double CNAV_DELTA_OMEGA_DOT_LSB = TWO_N44*GPS_L2_PI;//semi-circles to radians -const std::vector > CNAV_I0_DOT({{133,15}}); -const double CNAV_I0_DOT_LSB = TWO_N44*GPS_L2_PI;//semi-circles to radians -const std::vector > CNAV_CIS({{148,16}}); -const double CNAV_CIS_LSB = TWO_N30; -const std::vector > CNAV_CIC({{164,16}}); -const double CNAV_CIC_LSB = TWO_N30; -const std::vector > CNAV_CRS({{180,24}}); -const double CNAV_CRS_LSB = TWO_N8; -const std::vector > CNAV_CRC({{204,24}}); -const double CNAV_CRC_LSB = TWO_N8; -const std::vector > CNAV_CUS({{228,21}}); -const double CNAV_CUS_LSB = TWO_N30; -const std::vector > CNAV_CUC({{249,21}}); -const double CNAV_CUC_LSB = TWO_N30; - - -// MESSAGE TYPE 30 (CLOCK, IONO, GRUP DELAY) - -const std::vector > CNAV_TOP2({{39,11}}); -const double CNAV_TOP2_LSB = 300.0; - -const std::vector > CNAV_URA_NED0({{50,5}}); -const std::vector > CNAV_URA_NED1({{55,3}}); -const std::vector > CNAV_URA_NED2({{58,3}}); -const std::vector > CNAV_TOC({{61,11}}); -const double CNAV_TOC_LSB = 300.0; -const std::vector > CNAV_AF0({{72,26}}); -const double CNAV_AF0_LSB = TWO_N60; -const std::vector > CNAV_AF1({{98,20}}); -const double CNAV_AF1_LSB = TWO_N48; -const std::vector > CNAV_AF2({{118,10}}); -const double CNAV_AF2_LSB = TWO_N35; -const std::vector > CNAV_TGD({{128,13}}); -const double CNAV_TGD_LSB = TWO_N35; -const std::vector > CNAV_ISCL1({{141,13}}); -const double CNAV_ISCL1_LSB = TWO_N35; -const std::vector > CNAV_ISCL2({{154,13}}); -const double CNAV_ISCL2_LSB = TWO_N35; -const std::vector > CNAV_ISCL5I({{167,13}}); -const double CNAV_ISCL5I_LSB = TWO_N35; -const std::vector > CNAV_ISCL5Q({{180,13}}); -const double CNAV_ISCL5Q_LSB = TWO_N35; -//Ionospheric parameters -const std::vector > CNAV_ALPHA0({{193,8}}); -const double CNAV_ALPHA0_LSB = TWO_N30; -const std::vector > CNAV_ALPHA1({{201,8}}); -const double CNAV_ALPHA1_LSB = TWO_N27; -const std::vector > CNAV_ALPHA2({{209,8}}); -const double CNAV_ALPHA2_LSB = TWO_N24; -const std::vector > CNAV_ALPHA3({{217,8}}); -const double CNAV_ALPHA3_LSB = TWO_N24; -const std::vector > CNAV_BETA0({{225,8}}); -const double CNAV_BETA0_LSB = TWO_P11; -const std::vector > CNAV_BETA1({{233,8}}); -const double CNAV_BETA1_LSB = TWO_P14; -const std::vector > CNAV_BETA2({{241,8}}); -const double CNAV_BETA2_LSB = TWO_P16; -const std::vector > CNAV_BETA3({{249,8}}); -const double CNAV_BETA3_LSB = TWO_P16; -const std::vector > CNAV_WNOP({{257,8}}); - - -// MESSAGE TYPE 33 (CLOCK and UTC) - -const std::vector > CNAV_A0({{128,16}}); -const double CNAV_A0_LSB = TWO_N35; -const std::vector > CNAV_A1({{144,13}}); -const double CNAV_A1_LSB = TWO_N51; -const std::vector > CNAV_A2({{157,7}}); -const double CNAV_A2_LSB = TWO_N68; -const std::vector > CNAV_DELTA_TLS({{164,8}}); -const double CNAV_DELTA_TLS_LSB = 1; -const std::vector > CNAV_TOT({{172,16}}); -const double CNAV_TOT_LSB = TWO_P4; -const std::vector > CNAV_WN_OT({{188,13}}); -const double CNAV_WN_OT_LSB = 1; -const std::vector > CNAV_WN_LSF({{201,13}}); -const double CNAV_WN_LSF_LSB = 1; -const std::vector > CNAV_DN({{214,4}}); -const double CNAV_DN_LSB = 1; -const std::vector > CNAV_DELTA_TLSF({{218,8}}); -const double CNAV_DELTA_TLSF_LSB = 1; - - -// TODO: Add more frames (Almanac, etc...) - - - #endif /* GNSS_SDR_GPS_L2C_H_ */ diff --git a/src/core/system_parameters/GPS_L5.h b/src/core/system_parameters/GPS_L5.h index 23c9fbc73..1c6ceb8ff 100644 --- a/src/core/system_parameters/GPS_L5.h +++ b/src/core/system_parameters/GPS_L5.h @@ -35,6 +35,7 @@ #include #include "MATH_CONSTANTS.h" #include "gnss_frequencies.h" +#include "GPS_CNAV.h" // Physical constants const double GPS_L5_C_m_s = 299792458.0; //!< The speed of light, [m/s] @@ -47,19 +48,21 @@ const double GPS_L5_F = -4.442807633e-10; //!< Constant, [s/(m)^(1 // carrier and code frequencies -const double GPS_L5_FREQ_HZ = FREQ5; //!< L2 [Hz] +const double GPS_L5_FREQ_HZ = FREQ5; //!< L5 [Hz] const double GPS_L5i_CODE_RATE_HZ = 10.23e6; //!< GPS L5i code rate [chips/s] const int GPS_L5i_CODE_LENGTH_CHIPS = 10230; //!< GPS L5i code length [chips] -const double GPS_L5i_PERIOD = 0.001; //!< GPS L2 M code period [seconds] +const double GPS_L5i_PERIOD = 0.001; //!< GPS L5 code period [seconds] +const double GPS_L5i_SYMBOL_PERIOD = 0.01; //!< GPS L5 symbol period [seconds] const double GPS_L5q_CODE_RATE_HZ = 10.23e6; //!< GPS L5i code rate [chips/s] -const int GPS_L5q_CODE_LENGTH_CHIPS = 10230; //!< GPS L5i code length [chips] -const double GPS_L5q_PERIOD = 0.001; //!< GPS L2 M code period [seconds] +const int GPS_L5q_CODE_LENGTH_CHIPS = 10230; //!< GPS L5i code length [chips] +const double GPS_L5q_PERIOD = 0.001; //!< GPS L5 code period [seconds] +const int GPS_L5_HISTORY_DEEP = 5; const int32_t GPS_L5i_INIT_REG[210] = - {266, 365, 804, 1138, + {266, 365, 804, 1138, 1509, 1559, 1756, 2084, 2170, 2303, 2527, 2687, 2930, 3471, 3940, 4132, @@ -172,6 +175,12 @@ const int32_t GPS_L5q_INIT_REG[210] = 2765, 37, 1943, 7977, 2512, 4451, 4071}; - +const int GPS_L5_CNAV_DATA_PAGE_BITS = 300; //!< GPS L5 CNAV page length, including preamble and CRC [bits] +const int GPS_L5_SYMBOLS_PER_BIT = 2; +const int GPS_L5_SAMPLES_PER_SYMBOL = 10; +const int GPS_L5_CNAV_DATA_PAGE_SYMBOLS = 600; +const int GPS_L5_CNAV_DATA_PAGE_DURATION_S = 6; +const int GPS_L5_NH_CODE_LENGTH = 10; +const int GPS_L5_NH_CODE[10] = {0, 0, 0, 0, 1, 1, 0, 1, 0, 1}; #endif /* GNSS_SDR_GPS_L5_H_ */ diff --git a/src/core/system_parameters/Galileo_E1.h b/src/core/system_parameters/Galileo_E1.h index a95afd1ca..be5704a6e 100644 --- a/src/core/system_parameters/Galileo_E1.h +++ b/src/core/system_parameters/Galileo_E1.h @@ -57,7 +57,7 @@ const double Galileo_E1_SUB_CARRIER_A_RATE_HZ = 1.023e6; //!< Galileo E1 sub-car const double Galileo_E1_SUB_CARRIER_B_RATE_HZ = 6.138e6; //!< Galileo E1 sub-carrier 'b' rate [Hz] const double Galileo_E1_B_CODE_LENGTH_CHIPS = 4092.0; //!< Galileo E1-B code length [chips] const double Galileo_E1_B_SYMBOL_RATE_BPS = 250.0; //!< Galileo E1-B symbol rate [bits/second] -const double Galileo_E1_C_SECONDARY_CODE_LENGTH = 25.0; //!< Galileo E1-C secondary code length [chips] +const int Galileo_E1_C_SECONDARY_CODE_LENGTH = 25; //!< Galileo E1-C secondary code length [chips] const int Galileo_E1_NUMBER_OF_CODES = 50; const double GALILEO_STARTOFFSET_ms = 68.802; //[ms] Initial sign. travel time (this cannot go here) diff --git a/src/core/system_parameters/MATH_CONSTANTS.h b/src/core/system_parameters/MATH_CONSTANTS.h index 63db089c7..8c8dfbbe5 100644 --- a/src/core/system_parameters/MATH_CONSTANTS.h +++ b/src/core/system_parameters/MATH_CONSTANTS.h @@ -42,6 +42,7 @@ */ const double PI = 3.1415926535897932; //!< pi +const double PI_2 = 2.0 * PI; //!< 2 * pi const double TWO_P4 = (16); //!< 2^4 const double TWO_P11 = (2048); //!< 2^11 diff --git a/src/core/system_parameters/glonass_gnav_almanac.cc b/src/core/system_parameters/glonass_gnav_almanac.cc index 3b5ca7014..297a1cb59 100644 --- a/src/core/system_parameters/glonass_gnav_almanac.cc +++ b/src/core/system_parameters/glonass_gnav_almanac.cc @@ -29,30 +29,27 @@ * * ------------------------------------------------------------------------- */ + #include "glonass_gnav_almanac.h" -#include -#include "GLONASS_L1_CA.h" -#include "gnss_satellite.h" Glonass_Gnav_Almanac::Glonass_Gnav_Almanac() { - i_satellite_freq_channel = 0; - i_satellite_PRN = 0; - i_satellite_slot_number = 0; - - d_n_A = 0.0; - d_H_n_A = 0.0; - d_lambda_n_A = 0.0; - d_t_lambda_n_A = 0.0; - d_Delta_i_n_A = 0.0; - d_Delta_T_n_A = 0.0; - d_Delta_T_n_A_dot = 0.0; - d_epsilon_n_A = 0.0; - d_omega_n_A = 0.0; - d_M_n_A = 0.0; - d_KP = 0.0; - d_tau_n_A = 0.0; - d_C_n = false; - d_l_n = false; + i_satellite_freq_channel = 0; + i_satellite_PRN = 0; + i_satellite_slot_number = 0; + d_n_A = 0.0; + d_H_n_A = 0.0; + d_lambda_n_A = 0.0; + d_t_lambda_n_A = 0.0; + d_Delta_i_n_A = 0.0; + d_Delta_T_n_A = 0.0; + d_Delta_T_n_A_dot = 0.0; + d_epsilon_n_A = 0.0; + d_omega_n_A = 0.0; + d_M_n_A = 0.0; + d_KP = 0.0; + d_tau_n_A = 0.0; + d_C_n = false; + d_l_n = false; } diff --git a/src/core/system_parameters/glonass_gnav_almanac.h b/src/core/system_parameters/glonass_gnav_almanac.h index 3fc255118..896c5cd62 100644 --- a/src/core/system_parameters/glonass_gnav_almanac.h +++ b/src/core/system_parameters/glonass_gnav_almanac.h @@ -34,9 +34,6 @@ #ifndef GNSS_SDR_GLONASS_ALMANAC_H_ #define GNSS_SDR_GLONASS_ALMANAC_H_ -#include -#include -#include "boost/assign.hpp" #include /*! @@ -59,8 +56,8 @@ public: double d_M_n_A; //!< Type of satellite n_A [dimensionless] double d_KP; //!< Notification on forthcoming leap second correction of UTC [dimensionless] double d_tau_n_A; //!< Coarse value of d_n_A satellite time correction to GLONASS time at instant t_lambdan_A[s] - bool d_C_n; //!< Generalized “unhealthy flag” of n_A satellite at instant of almanac upload [dimensionless] - bool d_l_n; //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] + bool d_C_n; //!< Generalized “unhealthy flag” of n_A satellite at instant of almanac upload [dimensionless] + bool d_l_n; //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] // Satellite Identification Information int i_satellite_freq_channel; //!< SV Frequency Channel Number diff --git a/src/core/system_parameters/glonass_gnav_ephemeris.cc b/src/core/system_parameters/glonass_gnav_ephemeris.cc index 6cd530c59..e899db773 100644 --- a/src/core/system_parameters/glonass_gnav_ephemeris.cc +++ b/src/core/system_parameters/glonass_gnav_ephemeris.cc @@ -32,56 +32,55 @@ #include "glonass_gnav_ephemeris.h" #include -#include - #include "GLONASS_L1_CA.h" #include "gnss_satellite.h" Glonass_Gnav_Ephemeris::Glonass_Gnav_Ephemeris() { - d_m = 0.0; //!< String number within frame [dimensionless] - d_t_k = 0.0; //!< GLONASS Time (UTC(SU) + 3 h) referenced to the beginning of the frame within the current day [s] - d_t_b = 0.0; //!< Reference ephemeris relative time in GLONASS Time (UTC(SU) + 3 h). Index of a time interval within current day according to UTC(SU) + 03 hours 00 min. [s] - d_M = 0.0; //!< Type of satellite transmitting navigation signal [dimensionless] - d_gamma_n = 0.0; //!< Relative deviation of predicted carrier frequency value of n- satellite from nominal value at the instant tb [dimensionless] - d_tau_n = 0.0; //!< Correction to the nth satellite time (tn) relative to GLONASS time (te), - d_Xn = 0.0; //!< Earth-fixed coordinate x of the satellite in PZ-90.02 coordinate system [km]. - d_Yn = 0.0; //!< Earth-fixed coordinate y of the satellite in PZ-90.02 coordinate system [km] - d_Zn = 0.0; //!< Earth-fixed coordinate z of the satellite in PZ-90.02 coordinate system [km] - d_VXn = 0.0; //!< Earth-fixed velocity coordinate x of the satellite in PZ-90.02 coordinate system [km/s] - d_VYn = 0.0; //!< Earth-fixed velocity coordinate y of the satellite in PZ-90.02 coordinate system [km/s] - d_VZn = 0.0; //!< Earth-fixed velocity coordinate z of the satellite in PZ-90.02 coordinate system [km/s] - d_AXn = 0.0; //!< Earth-fixed acceleration coordinate x of the satellite in PZ-90.02 coordinate system [km/s^2] - d_AYn = 0.0; //!< Earth-fixed acceleration coordinate y of the satellite in PZ-90.02 coordinate system [km/s^2] - d_AZn = 0.0; //!< Earth-fixed acceleration coordinate z of the satellite in PZ-90.02 coordinate system [km/s^2] - d_B_n = 0.0; //!< Health flag [dimensionless] - d_P = 0.0; //!< Technological parameter of control segment, indication the satellite operation mode in respect of time parameters [dimensionless] - d_N_T = 0.0; //!< Current date, calendar number of day within four-year interval starting from the 1-st of January in a leap year [days] - d_F_T = 0.0; //!< Parameter that provides the predicted satellite user range accuracy at time tb [dimensionless] - d_n = 0.0; //!< Index of the satellite transmitting given navigation signal. It corresponds to a slot number within GLONASS constellation - d_Delta_tau_n = 0.0; //!< Time difference between navigation RF signal transmitted in L2 sub- band and aviation RF signal transmitted in L1 sub-band by nth satellite. [dimensionless] - d_E_n = 0.0; //!< Characterises "age" of a current information [days] - d_P_1 = 0.0; //!< Flag of the immediate data updating [minutes] - d_P_2 = false; //!< Flag of oddness ("1") or evenness ("0") of the value of (tb) [dimensionless] - d_P_3 = false; //!< Flag indicating a number of satellites for which almanac is transmitted within given frame: "1" corresponds to 5 satellites and "0" corresponds to 4 satellites [dimensionless] - d_P_4 = false; //!< Flag to show that ephemeris parameters are present. "1" indicates that updated ephemeris or frequency/time parameters have been uploaded by the control segment [dimensionless] - d_l3rd_n = false; //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] - d_l5th_n = false; //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] + d_m = 0.0; //!< String number within frame [dimensionless] + d_t_k = 0.0; //!< GLONASS Time (UTC(SU) + 3 h) referenced to the beginning of the frame within the current day [s] + d_t_b = 0.0; //!< Reference ephemeris relative time in GLONASS Time (UTC(SU) + 3 h). Index of a time interval within current day according to UTC(SU) + 03 hours 00 min. [s] + d_M = 0.0; //!< Type of satellite transmitting navigation signal [dimensionless] + d_gamma_n = 0.0; //!< Relative deviation of predicted carrier frequency value of n- satellite from nominal value at the instant tb [dimensionless] + d_tau_n = 0.0; //!< Correction to the nth satellite time (tn) relative to GLONASS time (te), + d_Xn = 0.0; //!< Earth-fixed coordinate x of the satellite in PZ-90.02 coordinate system [km]. + d_Yn = 0.0; //!< Earth-fixed coordinate y of the satellite in PZ-90.02 coordinate system [km] + d_Zn = 0.0; //!< Earth-fixed coordinate z of the satellite in PZ-90.02 coordinate system [km] + d_VXn = 0.0; //!< Earth-fixed velocity coordinate x of the satellite in PZ-90.02 coordinate system [km/s] + d_VYn = 0.0; //!< Earth-fixed velocity coordinate y of the satellite in PZ-90.02 coordinate system [km/s] + d_VZn = 0.0; //!< Earth-fixed velocity coordinate z of the satellite in PZ-90.02 coordinate system [km/s] + d_AXn = 0.0; //!< Earth-fixed acceleration coordinate x of the satellite in PZ-90.02 coordinate system [km/s^2] + d_AYn = 0.0; //!< Earth-fixed acceleration coordinate y of the satellite in PZ-90.02 coordinate system [km/s^2] + d_AZn = 0.0; //!< Earth-fixed acceleration coordinate z of the satellite in PZ-90.02 coordinate system [km/s^2] + d_B_n = 0.0; //!< Health flag [dimensionless] + d_P = 0.0; //!< Technological parameter of control segment, indication the satellite operation mode in respect of time parameters [dimensionless] + d_N_T = 0.0; //!< Current date, calendar number of day within four-year interval starting from the 1-st of January in a leap year [days] + d_F_T = 0.0; //!< Parameter that provides the predicted satellite user range accuracy at time tb [dimensionless] + d_n = 0.0; //!< Index of the satellite transmitting given navigation signal. It corresponds to a slot number within GLONASS constellation + d_Delta_tau_n = 0.0; //!< Time difference between navigation RF signal transmitted in L2 sub- band and aviation RF signal transmitted in L1 sub-band by nth satellite. [dimensionless] + d_E_n = 0.0; //!< Characterises "age" of a current information [days] + d_P_1 = 0.0; //!< Flag of the immediate data updating [minutes] + d_P_2 = false; //!< Flag of oddness ("1") or evenness ("0") of the value of (tb) [dimensionless] + d_P_3 = false; //!< Flag indicating a number of satellites for which almanac is transmitted within given frame: "1" corresponds to 5 satellites and "0" corresponds to 4 satellites [dimensionless] + d_P_4 = false; //!< Flag to show that ephemeris parameters are present. "1" indicates that updated ephemeris or frequency/time parameters have been uploaded by the control segment [dimensionless] + d_l3rd_n = false; //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] + d_l5th_n = false; //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] - // Satellite Identification Information - i_satellite_freq_channel = 0; //!< SV Frequency Channel Number - i_satellite_PRN = 0; //!< SV PRN Number, equivalent to slot number for compatibility with GPS - i_satellite_slot_number = 0; //!< SV Slot Number - d_yr = 1972; //!< Current year, defaults to 1972 (UTC Epoch with leap seconds) - d_satClkDrift = 0.0; //!< GLONASS clock error - d_dtr = 0.0; //!< relativistic clock correction term - d_iode = 0.0; //!< Issue of data, ephemeris (Bit 0-6 of tb) - d_tau_c = 0.0; - d_TOW = 0.0; // tow of the start of frame - d_WN = 0.0; // week number of the start of frame - d_tod = 0.0; + // Satellite Identification Information + i_satellite_freq_channel = 0; //!< SV Frequency Channel Number + i_satellite_PRN = 0; //!< SV PRN Number, equivalent to slot number for compatibility with GPS + i_satellite_slot_number = 0; //!< SV Slot Number + d_yr = 1972; //!< Current year, defaults to 1972 (UTC Epoch with leap seconds) + d_satClkDrift = 0.0; //!< GLONASS clock error + d_dtr = 0.0; //!< relativistic clock correction term + d_iode = 0.0; //!< Issue of data, ephemeris (Bit 0-6 of tb) + d_tau_c = 0.0; + d_TOW = 0.0; // tow of the start of frame + d_WN = 0.0; // week number of the start of frame + d_tod = 0.0; } + boost::posix_time::ptime Glonass_Gnav_Ephemeris::compute_GLONASS_time(const double offset_time) const { boost::posix_time::time_duration t(0, 0, offset_time + d_tau_c + d_tau_n); @@ -92,74 +91,75 @@ boost::posix_time::ptime Glonass_Gnav_Ephemeris::compute_GLONASS_time(const doub return glonass_time; } + boost::posix_time::ptime Glonass_Gnav_Ephemeris::glot_to_utc(const double offset_time, const double glot2utc_corr) const { - double tod = 0.0; - double glot2utc = 3*3600; + double tod = 0.0; + double glot2utc = 3*3600; - tod = offset_time - glot2utc + glot2utc_corr + d_tau_n; - boost::posix_time::time_duration t(0, 0, tod); - boost::gregorian::date d1(d_yr, 1, 1); - boost::gregorian::days d2(d_N_T - 1); - boost::posix_time::ptime utc_time(d1+d2, t); + tod = offset_time - glot2utc + glot2utc_corr + d_tau_n; + boost::posix_time::time_duration t(0, 0, tod); + boost::gregorian::date d1(d_yr, 1, 1); + boost::gregorian::days d2(d_N_T - 1); + boost::posix_time::ptime utc_time(d1 + d2, t); - return utc_time; + return utc_time; } + void Glonass_Gnav_Ephemeris::glot_to_gpst(double tod_offset, double glot2utc_corr, double glot2gpst_corr, double * wn, double * tow) const { - double tod = 0.0; - double glot2utc = 3*3600; - double days = 0.0; - double total_sec = 0.0, sec_of_day = 0.0; - int i = 0; + double tod = 0.0; + double glot2utc = 3*3600; + double days = 0.0; + double total_sec = 0.0, sec_of_day = 0.0; + int i = 0; - boost::gregorian::date gps_epoch { 1980, 1, 6 }; + boost::gregorian::date gps_epoch { 1980, 1, 6 }; - // tk is relative to UTC(SU) + 3.00 hrs, so we need to convert to utc and add corrections - // tk plus 10 sec is the true tod since get_TOW is called when in str5 - tod = tod_offset - glot2utc ; + // tk is relative to UTC(SU) + 3.00 hrs, so we need to convert to utc and add corrections + // tk plus 10 sec is the true tod since get_TOW is called when in str5 + tod = tod_offset - glot2utc ; + boost::posix_time::time_duration t(0, 0, tod); + boost::gregorian::date d1(d_yr, 1, 1); + boost::gregorian::days d2(d_N_T-1); + boost::posix_time::ptime utc_time(d1+d2, t); + boost::gregorian::date utc_date = utc_time.date(); + boost::posix_time::ptime gps_time; - boost::posix_time::time_duration t(0, 0, tod); - boost::gregorian::date d1(d_yr, 1, 1); - boost::gregorian::days d2(d_N_T-1); - boost::posix_time::ptime utc_time(d1+d2, t); - boost::gregorian::date utc_date = utc_time.date(); - boost::posix_time::ptime gps_time; + // Adjust for leap second correction + for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++) + { + boost::posix_time::time_duration t3(GLONASS_LEAP_SECONDS[i][3], GLONASS_LEAP_SECONDS[i][4], GLONASS_LEAP_SECONDS[i][5]); + boost::gregorian::date d3(GLONASS_LEAP_SECONDS[i][0], GLONASS_LEAP_SECONDS[i][1], GLONASS_LEAP_SECONDS[i][2]); + boost::posix_time::ptime ls_time(d3, t3); + if (utc_time >= ls_time) + { + // We add the leap second when going from utc to gpst + gps_time = utc_time + boost::posix_time::time_duration(0,0,fabs(GLONASS_LEAP_SECONDS[i][6])); + break; + } + } - // Adjust for leap second correction - for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++) - { - boost::posix_time::time_duration t3(GLONASS_LEAP_SECONDS[i][3], GLONASS_LEAP_SECONDS[i][4], GLONASS_LEAP_SECONDS[i][5]); - boost::gregorian::date d3(GLONASS_LEAP_SECONDS[i][0], GLONASS_LEAP_SECONDS[i][1], GLONASS_LEAP_SECONDS[i][2]); - boost::posix_time::ptime ls_time(d3, t3); - if (utc_time >= ls_time) - { - // We add the leap second when going from utc to gpst - gps_time = utc_time + boost::posix_time::time_duration(0,0,fabs(GLONASS_LEAP_SECONDS[i][6])); - break; - } - } + // Total number of days + std::string fdat = boost::posix_time::to_simple_string(gps_time); + days = static_cast((utc_date - gps_epoch).days()); - // Total number of days - std::string fdat = boost::posix_time::to_simple_string(gps_time); - days = static_cast((utc_date - gps_epoch).days()); + // Total number of seconds + sec_of_day = static_cast((gps_time.time_of_day()).total_seconds()); + total_sec = days*86400 + sec_of_day; - // Total number of seconds - sec_of_day = static_cast((gps_time.time_of_day()).total_seconds()); - total_sec = days*86400 + sec_of_day; - - // Compute Week number - *wn = floor(total_sec/604800); - - // Compute the arithmetic modules to wrap around range - *tow = total_sec - 604800*floor(total_sec/604800); - // Perform corrections from fractional seconds - *tow += glot2utc_corr + glot2gpst_corr; + // Compute Week number + *wn = floor(total_sec/604800); + // Compute the arithmetic modules to wrap around range + *tow = total_sec - 604800*floor(total_sec/604800); + // Perform corrections from fractional seconds + *tow += glot2utc_corr + glot2gpst_corr; } + double Glonass_Gnav_Ephemeris::check_t(double time) { double corrTime; @@ -176,6 +176,7 @@ double Glonass_Gnav_Ephemeris::check_t(double time) return corrTime; } + // FIXME Fix reference here // 20.3.3.3.3.1 User Algorithm for SV Clock Correction. double Glonass_Gnav_Ephemeris::sv_clock_drift(double transmitTime, double timeCorrUTC) diff --git a/src/core/system_parameters/glonass_gnav_ephemeris.h b/src/core/system_parameters/glonass_gnav_ephemeris.h index 5400e890f..cf43566e2 100644 --- a/src/core/system_parameters/glonass_gnav_ephemeris.h +++ b/src/core/system_parameters/glonass_gnav_ephemeris.h @@ -35,9 +35,6 @@ #define GNSS_SDR_GLONASS_GNAV_EPHEMERIS_H_ -#include -#include -#include "boost/assign.hpp" #include #include @@ -64,7 +61,7 @@ public: double d_m; //!< String number within frame [dimensionless] double d_t_k; //!< GLONASS Time (UTC(SU) + 3 h) referenced to the beginning of the frame within the current day [s] double d_t_b; //!< Reference ephemeris relative time in GLONASS Time (UTC(SU) + 3 h). Index of a time interval within current day according to UTC(SU) + 03 hours 00 min. [s] - double d_M; //!< Type of satellite transmitting navigation signal [dimensionless] + double d_M; //!< Type of satellite transmitting navigation signal [dimensionless] double d_gamma_n; //!< Relative deviation of predicted carrier frequency value of n- satellite from nominal value at the instant tb [dimensionless] double d_tau_n; //!< Correction to the nth satellite time (tn) relative to GLONASS time (te), double d_Xn; //!< Earth-fixed coordinate x of the satellite in PZ-90.02 coordinate system [km]. @@ -84,25 +81,25 @@ public: double d_Delta_tau_n; //!< Time difference between navigation RF signal transmitted in L2 sub- band and aviation RF signal transmitted in L1 sub-band by nth satellite. [dimensionless] double d_E_n; //!< Characterises "age" of a current information [days] double d_P_1; //!< Flag of the immediate data updating [minutes] - bool d_P_2; //!< Flag of oddness ("1") or evenness ("0") of the value of (tb) [dimensionless] - bool d_P_3; //!< Flag indicating a number of satellites for which almanac is transmitted within given frame: "1" corresponds to 5 satellites and "0" corresponds to 4 satellites [dimensionless] - bool d_P_4; //!< Flag to show that ephemeris parameters are present. "1" indicates that updated ephemeris or frequency/time parameters have been uploaded by the control segment [dimensionless] - bool d_l3rd_n; //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] - bool d_l5th_n; //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] + bool d_P_2; //!< Flag of oddness ("1") or evenness ("0") of the value of (tb) [dimensionless] + bool d_P_3; //!< Flag indicating a number of satellites for which almanac is transmitted within given frame: "1" corresponds to 5 satellites and "0" corresponds to 4 satellites [dimensionless] + bool d_P_4; //!< Flag to show that ephemeris parameters are present. "1" indicates that updated ephemeris or frequency/time parameters have been uploaded by the control segment [dimensionless] + bool d_l3rd_n; //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is healthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] + bool d_l5th_n; //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is healthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] // Inmediate deliverables of ephemeris information // Satellite Identification Information - int i_satellite_freq_channel; //!< SV Frequency Channel Number + int i_satellite_freq_channel; //!< SV Frequency Channel Number unsigned int i_satellite_PRN; //!< SV PRN Number, equivalent to slot number for compatibility with GPS unsigned int i_satellite_slot_number; //!< SV Slot Number double d_yr; //!< Current year double d_satClkDrift; //!< GLONASS clock error double d_dtr; //!< relativistic clock correction term double d_iode; //!< Issue of data, ephemeris (Bit 0-6 of tb) - double d_tau_c; //!< GLONASST 2 UTC correction (todo) may be eliminated - double d_TOW; //!< GLONASST IN GPST seconds of week - double d_WN; //!< GLONASST IN GPST week number of the start of frame - double d_tod; //!< Time of Day since ephemeris where decoded + double d_tau_c; //!< GLONASST 2 UTC correction (todo) may be eliminated + double d_TOW; //!< GLONASST IN GPST seconds of week + double d_WN; //!< GLONASST IN GPST week number of the start of frame + double d_tod; //!< Time of Day since ephemeris where decoded template @@ -137,14 +134,14 @@ public: archive & make_nvp("d_N_T", d_N_T); //!< Current date, calendar number of day within four-year interval starting from the 1-st of January in a leap year [days] archive & make_nvp("d_F_T", d_F_T); //!< Parameter that provides the predicted satellite user range accuracy at time tb [dimensionless] archive & make_nvp("d_n", d_n); //!< Index of the satellite transmitting given navigation signal. It corresponds to a slot number within GLONASS constellation - archive & make_nvp("d_Delta_tau_n", d_Delta_tau_n);//!< Time difference between navigation RF signal transmitted in L2 sub- band and aviation RF signal transmitted in L1 sub-band by nth satellite. [dimensionless] + archive & make_nvp("d_Delta_tau_n", d_Delta_tau_n); //!< Time difference between navigation RF signal transmitted in L2 sub- band and aviation RF signal transmitted in L1 sub-band by nth satellite. [dimensionless] archive & make_nvp("d_E_n", d_E_n); //!< Characterises "age" of a current information [days] archive & make_nvp("d_P_1", d_P_1); //!< Flag of the immediate data updating. archive & make_nvp("d_P_2", d_P_2); //!< Flag of oddness ("1") or evenness ("0") of the value of (tb) [dimensionless] archive & make_nvp("d_P_3", d_P_3); //!< Flag indicating a number of satellites for which almanac is transmitted within given frame: "1" corresponds to 5 satellites and "0" corresponds to 4 satellites [dimensionless] archive & make_nvp("d_P_4", d_P_4); //!< Flag to show that ephemeris parameters are present. "1" indicates that updated ephemeris or frequency/time parameters have been uploaded by the control segment [dimensionless] - archive & make_nvp("d_l3rd_n", d_l3rd_n); //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] - archive & make_nvp("d_l5th_n", d_l5th_n); //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] + archive & make_nvp("d_l3rd_n", d_l3rd_n); //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] + archive & make_nvp("d_l5th_n", d_l5th_n); //!< Health flag for nth satellite; ln = 0 indicates the n-th satellite is helthy, ln = 1 indicates malfunction of this nth satellite [dimensionless] } /*! diff --git a/src/core/system_parameters/glonass_gnav_navigation_message.cc b/src/core/system_parameters/glonass_gnav_navigation_message.cc index 102b57dfb..40301ea09 100644 --- a/src/core/system_parameters/glonass_gnav_navigation_message.cc +++ b/src/core/system_parameters/glonass_gnav_navigation_message.cc @@ -31,30 +31,25 @@ */ #include "glonass_gnav_navigation_message.h" -#include -#include -#include -#include -#include #include #include void Glonass_Gnav_Navigation_Message::reset() { - //!< Satellite Identification - i_satellite_PRN = 0; + // Satellite Identification + i_satellite_PRN = 0; i_alm_satellite_slot_number = 0; //!< SV Orbit Slot Number flag_update_slot_number = false; - //!< Ephmeris Flags + // Ephmeris Flags flag_all_ephemeris = false; flag_ephemeris_str_1 = false; flag_ephemeris_str_2 = false; flag_ephemeris_str_3 = false; flag_ephemeris_str_4 = false; - //!< Almanac Flags + // Almanac Flags flag_all_almanac = false; flag_almanac_str_6 = false; flag_almanac_str_7 = false; @@ -67,18 +62,19 @@ void Glonass_Gnav_Navigation_Message::reset() flag_almanac_str_14 = false; flag_almanac_str_15 = false; - //!< UTC and System Clocks Flags + // UTC and System Clocks Flags flag_utc_model_valid = false; //!< If set, it indicates that the UTC model parameters are filled flag_utc_model_str_5 = false; //!< Clock info send in string 5 of navigation data flag_utc_model_str_15 = false; //!< Clock info send in string 15 of frame 5 of navigation data - //broadcast orbit 1 + // broadcast orbit 1 flag_TOW_set = false; flag_TOW_new = false; flag_CRC_test = false; d_frame_ID = 0; d_string_ID = 0; + i_channel_ID = 0; // Clock terms d_satClkCorr = 0.0; @@ -90,7 +86,6 @@ void Glonass_Gnav_Navigation_Message::reset() for(unsigned int i = 0; i < GLONASS_L1_CA_NBR_SATS; i++) d_previous_Na[i] = 0.0; - std::map satelliteBlock; //!< Map that stores to which block the PRN belongs http://www.navcen.uscg.gov/?Do=constellationStatus auto gnss_sat = Gnss_Satellite(); @@ -123,12 +118,11 @@ bool Glonass_Gnav_Navigation_Message::CRC_test(std::bitset string_bits(GLONASS_GNAV_STRING_BITS); - //!< Populate data and hamming code vectors - for(int i = 0; i < static_cast(GLONASS_GNAV_STRING_BITS); i++) - { - string_bits[i] = static_cast(bits[i]); - } - + //!< Populate data and hamming code vectors + for(int i = 0; i < static_cast(GLONASS_GNAV_STRING_BITS); i++) + { + string_bits[i] = static_cast(bits[i]); + } //!< Compute C1 term sum_bits = 0; @@ -211,7 +205,7 @@ bool Glonass_Gnav_Navigation_Message::CRC_test(std::bitset(read_navigation_unsigned(string_bits, STRING_ID)); - switch (d_string_ID) { - case 1: - //--- It is string 1 ----------------------------------------------- - gnav_ephemeris.d_P_1 = (static_cast(read_navigation_unsigned(string_bits, P1)) + 1) * 15; - gnav_ephemeris.d_t_k = static_cast(read_navigation_unsigned(string_bits, T_K_HR)) * 3600 + - static_cast(read_navigation_unsigned(string_bits, T_K_MIN)) * 60 + - static_cast(read_navigation_unsigned(string_bits, T_K_SEC)) * 30; - gnav_ephemeris.d_VXn = static_cast(read_navigation_signed(string_bits, X_N_DOT)) * TWO_N20; - gnav_ephemeris.d_AXn = static_cast(read_navigation_signed(string_bits, X_N_DOT_DOT)) * TWO_N30; - gnav_ephemeris.d_Xn = static_cast(read_navigation_signed(string_bits, X_N)) * TWO_N11; + switch (d_string_ID) + { + case 1: + //--- It is string 1 ----------------------------------------------- + gnav_ephemeris.d_P_1 = (static_cast(read_navigation_unsigned(string_bits, P1)) + 1) * 15; + gnav_ephemeris.d_t_k = static_cast(read_navigation_unsigned(string_bits, T_K_HR)) * 3600 + + static_cast(read_navigation_unsigned(string_bits, T_K_MIN)) * 60 + + static_cast(read_navigation_unsigned(string_bits, T_K_SEC)) * 30; + gnav_ephemeris.d_VXn = static_cast(read_navigation_signed(string_bits, X_N_DOT)) * TWO_N20; + gnav_ephemeris.d_AXn = static_cast(read_navigation_signed(string_bits, X_N_DOT_DOT)) * TWO_N30; + gnav_ephemeris.d_Xn = static_cast(read_navigation_signed(string_bits, X_N)) * TWO_N11; - flag_ephemeris_str_1 = true; + flag_ephemeris_str_1 = true; - break; + break; - case 2: - //--- It is string 2 ----------------------------------------------- - if (flag_ephemeris_str_1 == true) - { - gnav_ephemeris.d_B_n = static_cast(read_navigation_unsigned(string_bits, B_N)); - gnav_ephemeris.d_P_2 = static_cast(read_navigation_bool(string_bits, P2)); - gnav_ephemeris.d_t_b = static_cast(read_navigation_unsigned(string_bits, T_B)) * 15 * 60; - gnav_ephemeris.d_VYn = static_cast(read_navigation_signed(string_bits, Y_N_DOT)) * TWO_N20; - gnav_ephemeris.d_AYn = static_cast(read_navigation_signed(string_bits, Y_N_DOT_DOT)) * TWO_N30; - gnav_ephemeris.d_Yn = static_cast(read_navigation_signed(string_bits, Y_N)) * TWO_N11; + case 2: + //--- It is string 2 ----------------------------------------------- + if (flag_ephemeris_str_1 == true) + { + gnav_ephemeris.d_B_n = static_cast(read_navigation_unsigned(string_bits, B_N)); + gnav_ephemeris.d_P_2 = static_cast(read_navigation_bool(string_bits, P2)); + gnav_ephemeris.d_t_b = static_cast(read_navigation_unsigned(string_bits, T_B)) * 15 * 60; + gnav_ephemeris.d_VYn = static_cast(read_navigation_signed(string_bits, Y_N_DOT)) * TWO_N20; + gnav_ephemeris.d_AYn = static_cast(read_navigation_signed(string_bits, Y_N_DOT_DOT)) * TWO_N30; + gnav_ephemeris.d_Yn = static_cast(read_navigation_signed(string_bits, Y_N)) * TWO_N11; - gnav_ephemeris.d_iode = read_navigation_unsigned(string_bits, T_B); - flag_ephemeris_str_2 = true; - } + gnav_ephemeris.d_iode = read_navigation_unsigned(string_bits, T_B); + flag_ephemeris_str_2 = true; + } - break; + break; - case 3: - // --- It is string 3 ---------------------------------------------- - if (flag_ephemeris_str_2 == true) - { - gnav_ephemeris.d_P_3 = static_cast(read_navigation_bool(string_bits, P3)); - gnav_ephemeris.d_gamma_n = static_cast(read_navigation_signed(string_bits, GAMMA_N)) * TWO_N40; - gnav_ephemeris.d_P = static_cast(read_navigation_unsigned(string_bits, P)); - gnav_ephemeris.d_l3rd_n = static_cast(read_navigation_bool(string_bits, EPH_L_N)); - gnav_ephemeris.d_VZn = static_cast(read_navigation_signed(string_bits, Z_N_DOT)) * TWO_N20; - gnav_ephemeris.d_AZn = static_cast(read_navigation_signed(string_bits, Z_N_DOT_DOT)) * TWO_N30; - gnav_ephemeris.d_Zn = static_cast(read_navigation_signed(string_bits, Z_N)) * TWO_N11; + case 3: + // --- It is string 3 ---------------------------------------------- + if (flag_ephemeris_str_2 == true) + { + gnav_ephemeris.d_P_3 = static_cast(read_navigation_bool(string_bits, P3)); + gnav_ephemeris.d_gamma_n = static_cast(read_navigation_signed(string_bits, GAMMA_N)) * TWO_N40; + gnav_ephemeris.d_P = static_cast(read_navigation_unsigned(string_bits, P)); + gnav_ephemeris.d_l3rd_n = static_cast(read_navigation_bool(string_bits, EPH_L_N)); + gnav_ephemeris.d_VZn = static_cast(read_navigation_signed(string_bits, Z_N_DOT)) * TWO_N20; + gnav_ephemeris.d_AZn = static_cast(read_navigation_signed(string_bits, Z_N_DOT_DOT)) * TWO_N30; + gnav_ephemeris.d_Zn = static_cast(read_navigation_signed(string_bits, Z_N)) * TWO_N11; - flag_ephemeris_str_3 = true; - } + flag_ephemeris_str_3 = true; + } - break; + break; - case 4: - // --- It is string 4 ---------------------------------------------- - if (flag_ephemeris_str_3 == true) - { - gnav_ephemeris.d_tau_n = static_cast(read_navigation_signed(string_bits, TAU_N)) * TWO_N30; - gnav_ephemeris.d_Delta_tau_n = static_cast(read_navigation_signed(string_bits, DELTA_TAU_N)) * TWO_N30; - gnav_ephemeris.d_E_n = static_cast(read_navigation_unsigned(string_bits, E_N)); - gnav_ephemeris.d_P_4 = static_cast(read_navigation_bool(string_bits, P4)); - gnav_ephemeris.d_F_T = static_cast(read_navigation_unsigned(string_bits, F_T)); - gnav_ephemeris.d_N_T = static_cast(read_navigation_unsigned(string_bits, N_T)); - gnav_ephemeris.d_n = static_cast(read_navigation_unsigned(string_bits, N)); - gnav_ephemeris.d_M = static_cast(read_navigation_unsigned(string_bits, M)); + case 4: + // --- It is string 4 ---------------------------------------------- + if (flag_ephemeris_str_3 == true) + { + gnav_ephemeris.d_tau_n = static_cast(read_navigation_signed(string_bits, TAU_N)) * TWO_N30; + gnav_ephemeris.d_Delta_tau_n = static_cast(read_navigation_signed(string_bits, DELTA_TAU_N)) * TWO_N30; + gnav_ephemeris.d_E_n = static_cast(read_navigation_unsigned(string_bits, E_N)); + gnav_ephemeris.d_P_4 = static_cast(read_navigation_bool(string_bits, P4)); + gnav_ephemeris.d_F_T = static_cast(read_navigation_unsigned(string_bits, F_T)); + gnav_ephemeris.d_N_T = static_cast(read_navigation_unsigned(string_bits, N_T)); + gnav_ephemeris.d_n = static_cast(read_navigation_unsigned(string_bits, N)); + gnav_ephemeris.d_M = static_cast(read_navigation_unsigned(string_bits, M)); - // Fill in ephemeris deliverables in the code - flag_update_slot_number = true; - gnav_ephemeris.i_satellite_slot_number = static_cast(gnav_ephemeris.d_n); - gnav_ephemeris.i_satellite_PRN = static_cast(gnav_ephemeris.d_n); + // Fill in ephemeris deliverables in the code + flag_update_slot_number = true; + gnav_ephemeris.i_satellite_slot_number = static_cast(gnav_ephemeris.d_n); + gnav_ephemeris.i_satellite_PRN = static_cast(gnav_ephemeris.d_n); - flag_ephemeris_str_4 = true; - } + flag_ephemeris_str_4 = true; + } - break; + break; - case 5: - // --- It is string 5 ---------------------------------------------- - if (flag_ephemeris_str_4 == true) - { - gnav_utc_model.d_N_A = static_cast(read_navigation_unsigned(string_bits, N_A)); - gnav_utc_model.d_tau_c = static_cast(read_navigation_signed(string_bits, TAU_C)) * TWO_N31; - gnav_utc_model.d_N_4 = static_cast(read_navigation_unsigned(string_bits, N_4)); - gnav_utc_model.d_tau_gps = static_cast(read_navigation_signed(string_bits, TAU_GPS)) * TWO_N30; - gnav_ephemeris.d_l5th_n = static_cast(read_navigation_bool(string_bits, ALM_L_N)); + case 5: + // --- It is string 5 ---------------------------------------------- + if (flag_ephemeris_str_4 == true) + { + gnav_utc_model.d_N_A = static_cast(read_navigation_unsigned(string_bits, N_A)); + gnav_utc_model.d_tau_c = static_cast(read_navigation_signed(string_bits, TAU_C)) * TWO_N31; + gnav_utc_model.d_N_4 = static_cast(read_navigation_unsigned(string_bits, N_4)); + gnav_utc_model.d_tau_gps = static_cast(read_navigation_signed(string_bits, TAU_GPS)) * TWO_N30; + gnav_ephemeris.d_l5th_n = static_cast(read_navigation_bool(string_bits, ALM_L_N)); - flag_utc_model_str_5 = true; + flag_utc_model_str_5 = true; - // Compute Year and DoY based on Algorithm A3.11 of GLONASS ICD - // 1). Current year number J in the four-year interval is calculated - if (gnav_ephemeris.d_N_T >= 1 && gnav_ephemeris.d_N_T <= 366) - { - J = 1; - } - else if (gnav_ephemeris.d_N_T >= 367 && gnav_ephemeris.d_N_T <= 731) - { - J = 2; - } - else if (gnav_ephemeris.d_N_T >= 732 && gnav_ephemeris.d_N_T <= 1096) - { - J = 3; - } - else if (gnav_ephemeris.d_N_T >= 1097 && gnav_ephemeris.d_N_T <= 1461) - { - J = 4; - } - // 2). Current year in common form is calculated by the following formula: - gnav_ephemeris.d_yr = 1996 + 4.0 * (gnav_utc_model.d_N_4 - 1.0) + (J - 1.0); - gnav_ephemeris.d_tau_c = gnav_utc_model.d_tau_c; + // Compute Year and DoY based on Algorithm A3.11 of GLONASS ICD + // 1). Current year number J in the four-year interval is calculated + if (gnav_ephemeris.d_N_T >= 1 && gnav_ephemeris.d_N_T <= 366) + { + J = 1; + } + else if (gnav_ephemeris.d_N_T >= 367 && gnav_ephemeris.d_N_T <= 731) + { + J = 2; + } + else if (gnav_ephemeris.d_N_T >= 732 && gnav_ephemeris.d_N_T <= 1096) + { + J = 3; + } + else if (gnav_ephemeris.d_N_T >= 1097 && gnav_ephemeris.d_N_T <= 1461) + { + J = 4; + } + // 2). Current year in common form is calculated by the following formula: + gnav_ephemeris.d_yr = 1996 + 4.0 * (gnav_utc_model.d_N_4 - 1.0) + (J - 1.0); + gnav_ephemeris.d_tau_c = gnav_utc_model.d_tau_c; - // 3). Set TOW once the year has been defined, it helps with leap second determination - if (flag_ephemeris_str_1 == true) + // 3). Set TOW once the year has been defined, it helps with leap second determination + if (flag_ephemeris_str_1 == true) { gnav_ephemeris.glot_to_gpst(gnav_ephemeris.d_t_k+10, gnav_utc_model.d_tau_c, gnav_utc_model.d_tau_gps, &gnav_ephemeris.d_WN, &gnav_ephemeris.d_TOW); flag_TOW_set = true; flag_TOW_new = true; } - // 4) Set time of day (tod) when ephemeris data is complety decoded - gnav_ephemeris.d_tod = gnav_ephemeris.d_t_k + 2*d_string_ID; + // 4) Set time of day (tod) when ephemeris data is complety decoded + gnav_ephemeris.d_tod = gnav_ephemeris.d_t_k + 2*d_string_ID; + } - } + break; + case 6: + // --- It is string 6 ---------------------------------------------- + i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); + d_frame_ID = get_frame_number(i_alm_satellite_slot_number); + // Make sure a valid frame_ID or satellite slot number is returned + if(d_frame_ID == 0) + return 0; - break; + gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = static_cast(read_navigation_bool(string_bits, C_N)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, n_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18; + gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20; - case 6: - // --- It is string 6 ---------------------------------------------- - i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); - d_frame_ID = get_frame_number(i_alm_satellite_slot_number); - // Make sure a valid frame_ID or satellite slot number is returned - if(d_frame_ID == 0) - return 0; + flag_almanac_str_6 = true; - gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = static_cast(read_navigation_bool(string_bits, C_N)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, n_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18; - gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20; + break; - flag_almanac_str_6 = true; + case 7: + // --- It is string 7 ---------------------------------------------- + if (flag_almanac_str_6 == true) + { + gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14; + gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast(read_navigation_unsigned(string_bits, H_N_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = static_cast(read_navigation_bool(string_bits, ALM_L_N)); - break; + // Set satellite information for redundancy purposes + if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24) + { + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0; + } + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; - case 7: - // --- It is string 7 ---------------------------------------------- - if (flag_almanac_str_6 == true) - { - gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14; - gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast(read_navigation_unsigned(string_bits, H_N_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = static_cast(read_navigation_bool(string_bits, ALM_L_N)); + if (i_alm_satellite_slot_number == gnav_ephemeris.i_satellite_slot_number) + { + gnav_ephemeris.i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel; + } + flag_almanac_str_7 = true; + } - // Set satellite information for redundancy purposes - if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24) - { - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0; - } - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; + break; - if (i_alm_satellite_slot_number == gnav_ephemeris.i_satellite_slot_number) - { - gnav_ephemeris.i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel; - } - flag_almanac_str_7 = true; - } + case 8: + // --- It is string 8 ---------------------------------------------- + i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); + d_frame_ID = get_frame_number(i_alm_satellite_slot_number); + // Make sure a valid frame_ID or satellite slot number is returned + if(d_frame_ID == 0) + return 0; + gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = static_cast(read_navigation_bool(string_bits, C_N)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, n_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18; + gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20; - break; - case 8: - // --- It is string 8 ---------------------------------------------- - i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); - d_frame_ID = get_frame_number(i_alm_satellite_slot_number); - // Make sure a valid frame_ID or satellite slot number is returned - if(d_frame_ID == 0) - return 0; + flag_almanac_str_8 = true; - gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = static_cast(read_navigation_bool(string_bits, C_N)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, n_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18; - gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20; + break; - flag_almanac_str_8 = true; + case 9: + // --- It is string 9 ---------------------------------------------- + if (flag_almanac_str_8 == true) + { + gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14; + gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast(read_navigation_unsigned(string_bits, H_N_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = static_cast(read_navigation_bool(string_bits, ALM_L_N)); - break; - case 9: - // --- It is string 9 ---------------------------------------------- - if (flag_almanac_str_8 == true) - { - gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14; - gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast(read_navigation_unsigned(string_bits, H_N_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = static_cast(read_navigation_bool(string_bits, ALM_L_N)); + // Set satellite information for redundancy purposes + if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24) + { + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0; + } + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; - // Set satellite information for redundancy purposes - if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24) - { - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0; - } - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; + flag_almanac_str_9 = true; + } + break; - flag_almanac_str_9 = true; - } - break; - case 10: - // --- It is string 10 --------------------------------------------- - i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); - d_frame_ID = get_frame_number(i_alm_satellite_slot_number); - // Make sure a valid frame_ID or satellite slot number is returned - if(d_frame_ID == 0) - return 0; + case 10: + // --- It is string 10 --------------------------------------------- + i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); + d_frame_ID = get_frame_number(i_alm_satellite_slot_number); + // Make sure a valid frame_ID or satellite slot number is returned + if(d_frame_ID == 0) + return 0; - gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = static_cast(read_navigation_bool(string_bits, C_N)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, n_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18; - gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20; + gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = static_cast(read_navigation_bool(string_bits, C_N)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, n_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18; + gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20; - flag_almanac_str_10 = true; + flag_almanac_str_10 = true; - break; + break; - case 11: - // --- It is string 11 --------------------------------------------- - if (flag_almanac_str_10 == true) - { - gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14; - gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast(read_navigation_unsigned(string_bits, H_N_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = static_cast(read_navigation_bool(string_bits, ALM_L_N)); + case 11: + // --- It is string 11 --------------------------------------------- + if (flag_almanac_str_10 == true) + { + gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14; + gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast(read_navigation_unsigned(string_bits, H_N_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = static_cast(read_navigation_bool(string_bits, ALM_L_N)); - // Set satellite information for redundancy purposes - if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24) - { - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0; - } - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; + // Set satellite information for redundancy purposes + if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24) + { + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0; + } + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; - flag_almanac_str_11 = true; - } - break; - case 12: - // --- It is string 12 --------------------------------------------- - i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); - d_frame_ID = get_frame_number(i_alm_satellite_slot_number); - // Make sure a valid frame_ID or satellite slot number is returned - if(d_frame_ID == 0) - return 0; - gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = static_cast(read_navigation_bool(string_bits, C_N)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, n_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18; - gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20; + flag_almanac_str_11 = true; + } + break; - flag_almanac_str_12 = true; + case 12: + // --- It is string 12 --------------------------------------------- + i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); + d_frame_ID = get_frame_number(i_alm_satellite_slot_number); + // Make sure a valid frame_ID or satellite slot number is returned + if(d_frame_ID == 0) + return 0; + gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = static_cast(read_navigation_bool(string_bits, C_N)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, n_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18; + gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20; - break; + flag_almanac_str_12 = true; - case 13: - // --- It is string 13 --------------------------------------------- - if (flag_almanac_str_12 == true) - { - gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14; - gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast(read_navigation_unsigned(string_bits, H_N_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = static_cast(read_navigation_bool(string_bits, ALM_L_N)); + break; - // Set satellite information for redundancy purposes - if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24) - { - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0; - } - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; - gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; + case 13: + // --- It is string 13 --------------------------------------------- + if (flag_almanac_str_12 == true) + { + gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14; + gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast(read_navigation_unsigned(string_bits, H_N_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = static_cast(read_navigation_bool(string_bits, ALM_L_N)); - flag_almanac_str_13 = true; - } - break; - case 14: - // --- It is string 14 --------------------------------------------- - if (d_frame_ID == 5) - { - gnav_utc_model.d_B1 = static_cast(read_navigation_unsigned(string_bits, B1)); - gnav_utc_model.d_B2 = static_cast(read_navigation_unsigned(string_bits, B2)); - } - else - { - i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); - d_frame_ID = get_frame_number(i_alm_satellite_slot_number); - // Make sure a valid frame_ID or satellite slot number is returned - if(d_frame_ID == 0) - return 0; - gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = static_cast(read_navigation_bool(string_bits, C_N)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, n_A)); - gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18; - gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GLONASS_PI; - gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20; + // Set satellite information for redundancy purposes + if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24) + { + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0; + } + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; + gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; - flag_almanac_str_14 = true; - } - break; + flag_almanac_str_13 = true; + } + break; - case 15: - // --- It is string 15 ---------------------------------------------- - if (d_frame_ID != 5 and flag_almanac_str_14 == true) { + case 14: + // --- It is string 14 --------------------------------------------- + if (d_frame_ID == 5) + { + gnav_utc_model.d_B1 = static_cast(read_navigation_unsigned(string_bits, B1)); + gnav_utc_model.d_B2 = static_cast(read_navigation_unsigned(string_bits, B2)); + } + else + { + i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); + d_frame_ID = get_frame_number(i_alm_satellite_slot_number); + // Make sure a valid frame_ID or satellite slot number is returned + if(d_frame_ID == 0) + return 0; + gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = static_cast(read_navigation_bool(string_bits, C_N)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast(read_navigation_unsigned(string_bits, M_N_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast(read_navigation_unsigned(string_bits, n_A)); + gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18; + gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GLONASS_PI; + gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20; + + flag_almanac_str_14 = true; + } + break; + + case 15: + // --- It is string 15 ---------------------------------------------- + if (d_frame_ID != 5 and flag_almanac_str_14 == true) { gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GLONASS_PI; gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5; gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9; @@ -672,16 +668,14 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string) gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A; flag_almanac_str_15 = true; - } - break; - default: - LOG(INFO) << "GLONASS GNAV: Invalid String ID of received. Received " << d_string_ID - << ", but acceptable range is from 1-15"; - - - break; - } // switch string ID ... + } + break; + default: + LOG(INFO) << "GLONASS GNAV: Invalid String ID of received. Received " << d_string_ID + << ", but acceptable range is from 1-15"; + break; + } // switch string ID return d_string_ID; } @@ -710,8 +704,8 @@ bool Glonass_Gnav_Navigation_Message::have_new_ephemeris() //Check if we have a bool new_eph = false; // We need to make sure we have received the ephemeris info plus the time info if ((flag_ephemeris_str_1 == true) and (flag_ephemeris_str_2 == true) and - (flag_ephemeris_str_3 == true) and (flag_ephemeris_str_4 == true) and - (flag_utc_model_str_5 == true)) + (flag_ephemeris_str_3 == true) and (flag_ephemeris_str_4 == true) and + (flag_utc_model_str_5 == true)) { if(d_previous_tb != gnav_ephemeris.d_t_b) { @@ -735,7 +729,7 @@ bool Glonass_Gnav_Navigation_Message::have_new_utc_model() // Check if we have a { if (flag_utc_model_str_5 == true) { - flag_utc_model_str_5 = false; // clear the flag + flag_utc_model_str_5 = false; // clear the flag return true; } else @@ -755,7 +749,6 @@ bool Glonass_Gnav_Navigation_Message::have_new_almanac() //Check if we have a ne flag_almanac_str_7 = false; new_alm = true; } - } if ((flag_almanac_str_8 == true) and (flag_almanac_str_9 == true)) { diff --git a/src/core/system_parameters/glonass_gnav_navigation_message.h b/src/core/system_parameters/glonass_gnav_navigation_message.h index 159a212f2..6aef9ad51 100644 --- a/src/core/system_parameters/glonass_gnav_navigation_message.h +++ b/src/core/system_parameters/glonass_gnav_navigation_message.h @@ -36,10 +36,6 @@ #include -#include -#include -#include -#include #include "GLONASS_L1_CA.h" #include "glonass_gnav_ephemeris.h" #include "glonass_gnav_almanac.h" @@ -70,16 +66,16 @@ public: Glonass_Gnav_Ephemeris gnav_ephemeris; //!< Ephemeris information decoded Glonass_Gnav_Utc_Model gnav_utc_model; //!< UTC model information - Glonass_Gnav_Almanac gnav_almanac[GLONASS_L1_CA_NBR_SATS]; //!< Almanac information for all 24 satellites + Glonass_Gnav_Almanac gnav_almanac[GLONASS_L1_CA_NBR_SATS]; //!< Almanac information for all 24 satellites - //!< Ephmeris Flags and control variables + // Ephemeris Flags and control variables bool flag_all_ephemeris; //!< Flag indicating that all strings containing ephemeris have been received bool flag_ephemeris_str_1; //!< Flag indicating that ephemeris 1/4 (string 1) have been received bool flag_ephemeris_str_2; //!< Flag indicating that ephemeris 2/4 (string 2) have been received bool flag_ephemeris_str_3; //!< Flag indicating that ephemeris 3/4 (string 3) have been received bool flag_ephemeris_str_4; //!< Flag indicating that ephemeris 4/4 (string 4) have been received - //!< Almanac Flags + // Almanac Flags bool flag_all_almanac; //!< Flag indicating that all almanac have been received bool flag_almanac_str_6; //!< Flag indicating that almanac of string 6 have been received bool flag_almanac_str_7; //!< Flag indicating that almanac of string 7 have been received @@ -91,23 +87,22 @@ public: bool flag_almanac_str_13; //!< Flag indicating that almanac of string 13 have been received bool flag_almanac_str_14; //!< Flag indicating that almanac of string 14 have been received bool flag_almanac_str_15; //!< Flag indicating that almanac of string 15 have been received - unsigned int i_alm_satellite_slot_number; //!< SV Orbit Slot Number + unsigned int i_alm_satellite_slot_number; //!< SV Orbit Slot Number - //!< UTC and System Clocks Flags - bool flag_utc_model_valid; //!< If set, it indicates that the UTC model parameters are filled - bool flag_utc_model_str_5; //!< Clock info send in string 5 of navigation data - bool flag_utc_model_str_15; //!< Clock info send in string 15 of frame 5 of navigation data + // UTC and System Clocks Flags + bool flag_utc_model_valid; //!< If set, it indicates that the UTC model parameters are filled + bool flag_utc_model_str_5; //!< Clock info send in string 5 of navigation data + bool flag_utc_model_str_15; //!< Clock info send in string 15 of frame 5 of navigation data bool flag_TOW_set; //!< Flag indicating when the TOW has been set bool flag_TOW_new; //!< Flag indicating when a new TOW has been computed - double d_satClkCorr; //!< Satellite clock error - double d_dtr; //!< Relativistic clock correction term - double d_satClkDrift; //!< Satellite clock drift - - double d_previous_tb; //!< Previous iode for the Glonass_Gnav_Ephemeris object. Used to determine when new data arrives - double d_previous_Na[GLONASS_L1_CA_NBR_SATS]; //!< Previous time for almanac of the Glonass_Gnav_Almanac object + double d_satClkCorr; //!< Satellite clock error + double d_dtr; //!< Relativistic clock correction term + double d_satClkDrift; //!< Satellite clock drift + double d_previous_tb; //!< Previous iode for the Glonass_Gnav_Ephemeris object. Used to determine when new data arrives + double d_previous_Na[GLONASS_L1_CA_NBR_SATS]; //!< Previous time for almanac of the Glonass_Gnav_Almanac object /*! * \brief Compute CRC for GLONASS GNAV strings @@ -116,10 +111,10 @@ public: bool CRC_test(std::bitset bits); /*! - * \brief Computes the frame number being decoded given the satellite slot number - * \param satellite_slot_number [in] Satellite slot number identifier - * \returns Frame number being decoded, 0 if operation was not successful. - */ + * \brief Computes the frame number being decoded given the satellite slot number + * \param satellite_slot_number [in] Satellite slot number identifier + * \returns Frame number being decoded, 0 if operation was not successful. + */ unsigned int get_frame_number(unsigned int satellite_slot_number); /*! diff --git a/src/core/system_parameters/gnss_satellite.cc b/src/core/system_parameters/gnss_satellite.cc index 24e08cba0..9970455be 100644 --- a/src/core/system_parameters/gnss_satellite.cc +++ b/src/core/system_parameters/gnss_satellite.cc @@ -279,103 +279,103 @@ std::string Gnss_Satellite::what_block(const std::string& system_, unsigned int { switch ( PRN_ ) { - // info from http://www.navcen.uscg.gov/?Do=constellationStatus + // info from https://www.navcen.uscg.gov/?Do=constellationStatus case 1 : - block_ = std::string("IIF"); //Plane D + block_ = std::string("IIF"); // Plane D break; case 2 : - block_ = std::string("IIR"); //Plane D + block_ = std::string("IIR"); // Plane D break; case 3 : - block_ = std::string("IIF"); //Plane E + block_ = std::string("IIF"); // Plane E break; case 4 : block_ = std::string("Unknown"); break; case 5 : - block_ = std::string("IIR-M"); //Plane E + block_ = std::string("IIR-M"); // Plane E break; case 6 : - block_ = std::string("IIF"); //Plane D + block_ = std::string("IIF"); // Plane D break; case 7 : - block_ = std::string("IIR-M"); //Plane A + block_ = std::string("IIR-M"); // Plane A break; case 8 : - block_ = std::string("IIF"); //Plane C + block_ = std::string("IIF"); // Plane C break; case 9 : - block_ = std::string("IIF"); //Plane F + block_ = std::string("IIF"); // Plane F break; case 10 : - block_ = std::string("IIF"); //Plane E + block_ = std::string("IIF"); // Plane E break; case 11 : - block_ = std::string("IIR"); //Plane D + block_ = std::string("IIR"); // Plane D break; case 12 : - block_ = std::string("IIR-M"); //Plane B + block_ = std::string("IIR-M"); // Plane B break; case 13 : - block_ = std::string("IIR"); //Plane F + block_ = std::string("IIR"); // Plane F break; case 14 : - block_ = std::string("IIR"); //Plane F + block_ = std::string("IIR"); // Plane F break; case 15 : - block_ = std::string("IIR-M"); //Plane F + block_ = std::string("IIR-M"); // Plane F break; case 16 : - block_ = std::string("IIR"); //Plane B + block_ = std::string("IIR"); // Plane B break; case 17 : - block_ = std::string("IIR-M"); //Plane C + block_ = std::string("IIR-M"); // Plane C break; case 18 : - block_ = std::string("IIR"); //Plane E + block_ = std::string("IIR"); // Plane E break; case 19 : - block_ = std::string("IIR"); //Plane D + block_ = std::string("IIR"); // Plane D break; case 20 : - block_ = std::string("IIR"); //Plane B + block_ = std::string("IIR"); // Plane B break; case 21 : - block_ = std::string("IIR"); //Plane D + block_ = std::string("IIR"); // Plane D break; case 22 : - block_ = std::string("IIR"); //Plane E + block_ = std::string("IIR"); // Plane E break; case 23 : - block_ = std::string("IIR"); //Plane F + block_ = std::string("IIR"); // Plane F break; case 24 : - block_ = std::string("IIF"); //Plane A + block_ = std::string("IIF"); // Plane A break; case 25 : - block_ = std::string("IIF"); //Plane B + block_ = std::string("IIF"); // Plane B break; case 26 : - block_ = std::string("IIF"); //Plane B + block_ = std::string("IIF"); // Plane B break; case 27 : - block_ = std::string("IIF"); //Plane C + block_ = std::string("IIF"); // Plane C break; case 28 : - block_ = std::string("IIR"); //Plane B + block_ = std::string("IIR"); // Plane B break; case 29 : - block_ = std::string("IIR-M"); //Plane C + block_ = std::string("IIR-M"); // Plane C break; case 30 : - block_ = std::string("IIF"); //Plane A + block_ = std::string("IIF"); // Plane A break; case 31 : - block_ = std::string("IIR-M"); //Plane A + block_ = std::string("IIR-M"); // Plane A break; case 32 : - block_ = std::string("IIF"); //Plane F + block_ = std::string("IIF"); // Plane F break; default : block_ = std::string("Unknown"); @@ -387,103 +387,103 @@ std::string Gnss_Satellite::what_block(const std::string& system_, unsigned int { switch ( PRN_ ) { - // info from http://www.sdcm.ru/smglo/grupglo?version=eng&site=extern + // Info from http://www.sdcm.ru/smglo/grupglo?version=eng&site=extern // See also http://www.glonass-center.ru/en/GLONASS/ case 1 : - block_ = std::string("1"); //Plane 1 + block_ = std::string("1"); // Plane 1 rf_link = 1; break; case 2 : - block_ = std::string("-4"); //Plane 1 + block_ = std::string("-4"); // Plane 1 rf_link = -4; break; case 3 : - block_ = std::string("5"); //Plane 1 + block_ = std::string("5"); // Plane 1 rf_link = 5; break; case 4 : - block_ = std::string("6"); //Plane 1 + block_ = std::string("6"); // Plane 1 rf_link = 6; break; case 5 : - block_ = std::string("1"); //Plane 1 + block_ = std::string("1"); // Plane 1 rf_link = 1; break; case 6 : - block_ = std::string("-4"); //Plane 1 + block_ = std::string("-4"); // Plane 1 rf_link = -4; break; case 7 : - block_ = std::string("5"); //Plane 1 + block_ = std::string("5"); // Plane 1 rf_link = 5; break; case 8 : - block_ = std::string("6"); //Plane 1 + block_ = std::string("6"); // Plane 1 rf_link = 6; break; case 9 : - block_ = std::string("-2"); //Plane 2 + block_ = std::string("-2"); // Plane 2 rf_link = -2; break; case 10 : - block_ = std::string("-7"); //Plane 2 + block_ = std::string("-7"); // Plane 2 rf_link = -7; break; case 11 : - block_ = std::string("0"); //Plane 2 + block_ = std::string("0"); // Plane 2 rf_link = 0; break; case 12 : - block_ = std::string("-1"); //Plane 2 + block_ = std::string("-1"); // Plane 2 rf_link = -1; break; case 13 : - block_ = std::string("-2"); //Plane 2 + block_ = std::string("-2"); // Plane 2 rf_link = -2; break; case 14 : - block_ = std::string("-7"); //Plane 2 + block_ = std::string("-7"); // Plane 2 rf_link = -7; break; case 15 : - block_ = std::string("0"); //Plane 2 + block_ = std::string("0"); // Plane 2 rf_link = 0; break; case 16 : - block_ = std::string("-1"); //Plane 2 + block_ = std::string("-1"); // Plane 2 rf_link = -1; break; case 17 : - block_ = std::string("4"); //Plane 3 + block_ = std::string("4"); // Plane 3 rf_link = 4; break; case 18 : - block_ = std::string("-3"); //Plane 3 + block_ = std::string("-3"); // Plane 3 rf_link = -3; break; case 19 : - block_ = std::string("3"); //Plane 3 + block_ = std::string("3"); // Plane 3 rf_link = 3; break; case 20 : - block_ = std::string("2"); //Plane 3 + block_ = std::string("2"); // Plane 3 rf_link = 2; break; case 21 : - block_ = std::string("4"); //Plane 3 + block_ = std::string("4"); // Plane 3 rf_link = 4; break; case 22 : - block_ = std::string("-3"); //Plane 3 + block_ = std::string("-3"); // Plane 3 rf_link = -3; break; case 23 : - block_ = std::string("3"); //Plane 3 + block_ = std::string("3"); // Plane 3 rf_link = 3; break; case 24 : - block_ = std::string("2"); //Plane 3 + block_ = std::string("2"); // Plane 3 rf_link = 2; break; default : @@ -515,62 +515,74 @@ std::string Gnss_Satellite::what_block(const std::string& system_, unsigned int } if (system_.compare("Galileo") == 0) { - // Check http://en.wikipedia.org/wiki/List_of_Galileo_satellites + // Check http://en.wikipedia.org/wiki/List_of_Galileo_satellites and https://www.gsc-europa.eu/system-status/Constellation-Information switch ( PRN_ ) { case 1: - block_ = std::string("FOC-FM10"); // Galileo Full Operational Capability (FOC) satellite FM10 / GSAT-0210, launched on May 24, 2016 + block_ = std::string("FOC-FM10"); // Galileo Full Operational Capability (FOC) satellite FM10 / GSAT-0210, launched on May 24, 2016. break; case 2: - block_ = std::string("FOC-FM11"); // Galileo Full Operational Capability (FOC) satellite FM11 / GSAT-0211, launched on May 24, 2016 + block_ = std::string("FOC-FM11"); // Galileo Full Operational Capability (FOC) satellite FM11 / GSAT-0211, launched on May 24, 2016. break; case 3: - block_ = std::string("FOC-FM12"); // Galileo Full Operational Capability (FOC) satellite FM12 / GSAT-0212, launched on November 17, 2016 + block_ = std::string("FOC-FM12"); // Galileo Full Operational Capability (FOC) satellite FM12 / GSAT-0212, launched on November 17, 2016. break; case 4: - block_ = std::string("FOC-FM13"); // Galileo Full Operational Capability (FOC) satellite FM13 / GSAT-0213, launched on November 17, 2016 + block_ = std::string("FOC-FM13"); // Galileo Full Operational Capability (FOC) satellite FM13 / GSAT-0213, launched on November 17, 2016. break; case 5: - block_ = std::string("FOC-FM14"); // Galileo Full Operational Capability (FOC) satellite FM14 / GSAT-0214, launched on November 17, 2016 + block_ = std::string("FOC-FM14"); // Galileo Full Operational Capability (FOC) satellite FM14 / GSAT-0214, launched on November 17, 2016. break; case 7: - block_ = std::string("FOC-FM7"); // Galileo Full Operational Capability (FOC) satellite FM7 / GSAT-0207, launched on November 17, 2016 + block_ = std::string("FOC-FM7"); // Galileo Full Operational Capability (FOC) satellite FM7 / GSAT-0207, launched on November 17, 2016. break; case 8: - block_ = std::string("FOC-FM8"); // Galileo Full Operational Capability (FOC) satellite FM8 / GSAT0208, launched on December 17, 2015 + block_ = std::string("FOC-FM8"); // Galileo Full Operational Capability (FOC) satellite FM8 / GSAT0208, launched on December 17, 2015. break; case 9: - block_ = std::string("FOC-FM9"); // Galileo Full Operational Capability (FOC) satellite FM9 / GSAT0209, launched on December 17, 2015 + block_ = std::string("FOC-FM9"); // Galileo Full Operational Capability (FOC) satellite FM9 / GSAT0209, launched on December 17, 2015. break; case 11 : - block_ = std::string("IOV-PFM"); // PFM, the ProtoFlight Model / GSAT0101, launched from French Guiana at 10:30 GMT on October 21, 2011 + block_ = std::string("IOV-PFM"); // PFM, the ProtoFlight Model / GSAT0101, launched from French Guiana at 10:30 GMT on October 21, 2011. break; case 12 : - block_ = std::string("IOV-FM2**"); // Galileo In-Orbit Validation (IOV) satellite FM2 (Flight Model 2) also known as GSAT0102, from French Guiana at 10:30 GMT on October 21, 2011 + block_ = std::string("IOV-FM2"); // Galileo In-Orbit Validation (IOV) satellite FM2 (Flight Model 2) also known as GSAT0102, from French Guiana at 10:30 GMT on October 21, 2011. break; case 14 : - block_ = std::string("FOC-FM2*"); // Galileo Full Operational Capability (FOC) satellite FM2 / GSAT0202, launched into incorrect orbit on August 22, 2014. Moved to usable orbit in March, 2015. + block_ = std::string("FOC-FM2*"); // Galileo Full Operational Capability (FOC) satellite FM2 / GSAT0202, launched into incorrect orbit on August 22, 2014. Moved to usable orbit in March, 2015. UNDER TESTING. break; case 18 : - block_ = std::string("FOC-FM1*"); // Galileo Full Operational Capability (FOC) satellite FM1 / GSAT0201, launched into incorrect orbit on August 22, 2014. Moved to usable orbit in December, 2014. + block_ = std::string("FOC-FM1*"); // Galileo Full Operational Capability (FOC) satellite FM1 / GSAT0201, launched into incorrect orbit on August 22, 2014. Moved to usable orbit in December, 2014. UNDER TESTING. break; case 19 : - block_ = std::string("IOV-FM3"); // Galileo In-Orbit Validation (IOV) satellite FM3 (Flight Model 3) / GSAT0103, launched on October 12, 2012 + block_ = std::string("IOV-FM3"); // Galileo In-Orbit Validation (IOV) satellite FM3 (Flight Model 3) / GSAT0103, launched on October 12, 2012. break; case 20 : - block_ = std::string("IOV-FM4**"); // Galileo In-Orbit Validation (IOV) satellite FM4 (Flight Model 4) / GSAT0104, launched on October 12, 2012. Partially unavailable: Payload power problem beginning May 27, 2014 led to permanent loss of E5 and E6 transmissions, E1 transmission restored. + block_ = std::string("IOV-FM4**"); // Galileo In-Orbit Validation (IOV) satellite FM4 (Flight Model 4) / GSAT0104, launched on October 12, 2012. Payload power problem beginning May 27, 2014 led to permanent loss of E5 and E6 transmissions, E1 transmission restored. UNAVAILABLE FROM 2014-05-27 UNTIL FURTHER NOTICE + break; + case 21 : + block_ = std::string("FOC-FM15"); // Galileo Full Operational Capability (FOC) satellite FM15 / GSAT0215, launched on Dec. 12, 2017. UNDER COMMISIONING. break; case 22 : - block_ = std::string("FOC-FM4"); // Galileo Full Operational Capability (FOC) satellite FM4 / GSAT0204, launched on March 27, 2015. + block_ = std::string("FOC-FM4**"); // Galileo Full Operational Capability (FOC) satellite FM4 / GSAT0204, launched on March 27, 2015. REMOVED FROM ACTIVE SERVICE ON 2017-12-08 UNTIL FURTHER NOTICE FOR CONSTELLATION MANAGEMENT PURPOSES. break; case 24 : - block_ = std::string("FOC-FM5"); // Galileo Full Operational Capability (FOC) satellite FM5 / GSAT0205, launched on Sept. 11, 2015. + block_ = std::string("FOC-FM5"); // Galileo Full Operational Capability (FOC) satellite FM5 / GSAT0205, launched on Sept. 11, 2015. + break; + case 25 : + block_ = std::string("FOC-FM16"); // Galileo Full Operational Capability (FOC) satellite FM16 / GSAT0216, launched on Dec. 12, 2017. UNDER COMMISIONING. break; case 26 : - block_ = std::string("FOC-FM3"); // Galileo Full Operational Capability (FOC) satellite FM3 / GSAT0203, launched on March 27, 2015. + block_ = std::string("FOC-FM3"); // Galileo Full Operational Capability (FOC) satellite FM3 / GSAT0203, launched on March 27, 2015. + break; + case 27 : + block_ = std::string("FOC-FM17"); // Galileo Full Operational Capability (FOC) satellite FM17 / GSAT0217, launched on Dec. 12, 2017. UNDER COMMISIONING. break; case 30 : - block_ = std::string("FOC-FM6"); // Galileo Full Operational Capability (FOC) satellite FM6 / GSAT0206, launched on Sept. 11, 2015. + block_ = std::string("FOC-FM6"); // Galileo Full Operational Capability (FOC) satellite FM6 / GSAT0206, launched on Sept. 11, 2015. + break; + case 31 : + block_ = std::string("FOC-FM18"); // Galileo Full Operational Capability (FOC) satellite FM18 / GSAT0218, launched on Dec. 12, 2017. UNDER COMMISIONING. break; default: block_ = std::string("Unknown(Simulated)"); diff --git a/src/core/system_parameters/gnss_signal.h b/src/core/system_parameters/gnss_signal.h index 91b6f7162..4645f17e9 100644 --- a/src/core/system_parameters/gnss_signal.h +++ b/src/core/system_parameters/gnss_signal.h @@ -51,7 +51,7 @@ public: Gnss_Signal(const std::string& signal_); Gnss_Signal(const Gnss_Satellite& satellite_, const std::string& signal_); ~Gnss_Signal(); - std::string get_signal_str() const; //!< Get the satellite signal {"1C" for GPS L1 C/A, "2S" for GPS L2C (M), "1G" for GLONASS L1 C/A, "1B" for Galileo E1B, "5X" for Galileo E5a} + std::string get_signal_str() const; //!< Get the satellite signal {"1C" for GPS L1 C/A, "2S" for GPS L2C (M), "L5" for GPS L5, "1G" for GLONASS L1 C/A, "1B" for Galileo E1B, "5X" for Galileo E5a. Gnss_Satellite get_satellite() const; //!< Get the Gnss_Satellite associated to the signal friend bool operator== (const Gnss_Signal &, const Gnss_Signal &); //!< operator== for comparison friend std::ostream& operator<<(std::ostream &, const Gnss_Signal &); //!< operator<< for pretty printing diff --git a/src/core/system_parameters/gps_cnav_ephemeris.cc b/src/core/system_parameters/gps_cnav_ephemeris.cc index 7669fb825..f46cfc310 100644 --- a/src/core/system_parameters/gps_cnav_ephemeris.cc +++ b/src/core/system_parameters/gps_cnav_ephemeris.cc @@ -32,7 +32,6 @@ #include "gps_cnav_ephemeris.h" #include -#include "GPS_L2C.h" #include Gps_CNAV_Ephemeris::Gps_CNAV_Ephemeris() @@ -168,7 +167,7 @@ double Gps_CNAV_Ephemeris::sv_clock_relativistic_term(double transmitTime) { E_old = E; E = M + d_e_eccentricity * sin(E); - dE = fmod(E - E_old, 2.0 * GPS_L2_PI); + dE = fmod(E - E_old, 2.0 * PI); if (fabs(dE) < 1e-12) { //Necessary precision is reached, exit from the loop @@ -239,7 +238,7 @@ double Gps_CNAV_Ephemeris::satellitePosition(double transmitTime) { E_old = E; E = M + d_e_eccentricity * sin(E); - dE = fmod(E - E_old, 2 * GPS_L2_PI); + dE = fmod(E - E_old, 2 * PI); if (fabs(dE) < 1e-12) { //Necessary precision is reached, exit from the loop @@ -268,7 +267,7 @@ double Gps_CNAV_Ephemeris::satellitePosition(double transmitTime) i = d_i_0 + d_IDOT * tk + d_Cic * cos(2*phi) + d_Cis * sin(2*phi); // Compute the angle between the ascending node and the Greenwich meridian - double d_OMEGA_DOT = OMEGA_DOT_REF*GPS_L2_PI + d_DELTA_OMEGA_DOT; + double d_OMEGA_DOT = OMEGA_DOT_REF*PI + d_DELTA_OMEGA_DOT; Omega = d_OMEGA0 + (d_OMEGA_DOT - OMEGA_EARTH_DOT)*tk - OMEGA_EARTH_DOT * d_Toe1; // Reduce to between 0 and 2*pi rad @@ -291,7 +290,7 @@ double Gps_CNAV_Ephemeris::satellitePosition(double transmitTime) double dtr_s = d_A_f0 + d_A_f1 * tk + d_A_f2 * tk * tk; /* relativity correction */ - dtr_s -= 2.0 * sqrt(GM * a) * d_e_eccentricity * sin(E) / (GPS_L2_C_m_s * GPS_L2_C_m_s); + dtr_s -= 2.0 * sqrt(GM * a) * d_e_eccentricity * sin(E) / (SPEED_OF_LIGHT * SPEED_OF_LIGHT); return dtr_s; } diff --git a/src/core/system_parameters/gps_cnav_ephemeris.h b/src/core/system_parameters/gps_cnav_ephemeris.h index 05f2c5029..b8f304951 100644 --- a/src/core/system_parameters/gps_cnav_ephemeris.h +++ b/src/core/system_parameters/gps_cnav_ephemeris.h @@ -32,7 +32,7 @@ #ifndef GNSS_SDR_GPS_CNAV_EPHEMERIS_H_ #define GNSS_SDR_GPS_CNAV_EPHEMERIS_H_ -#include "GPS_L2C.h" +#include "GPS_CNAV.h" #include "boost/assign.hpp" #include diff --git a/src/core/system_parameters/gps_cnav_navigation_message.cc b/src/core/system_parameters/gps_cnav_navigation_message.cc index cf49bba50..a78ade0c7 100644 --- a/src/core/system_parameters/gps_cnav_navigation_message.cc +++ b/src/core/system_parameters/gps_cnav_navigation_message.cc @@ -40,6 +40,7 @@ void Gps_CNAV_Navigation_Message::reset() b_flag_ephemeris_1 = false; b_flag_ephemeris_2 = false; b_flag_iono_valid = false; + b_flag_utc_valid = false; // satellite positions d_satpos_X = 0; @@ -73,11 +74,11 @@ Gps_CNAV_Navigation_Message::Gps_CNAV_Navigation_Message() -bool Gps_CNAV_Navigation_Message::read_navigation_bool(std::bitset bits, const std::vector> parameter) +bool Gps_CNAV_Navigation_Message::read_navigation_bool(std::bitset bits, const std::vector> parameter) { bool value; - if (bits[GPS_L2_CNAV_DATA_PAGE_BITS - parameter[0].first] == 1) + if (bits[GPS_CNAV_DATA_PAGE_BITS - parameter[0].first] == 1) { value = true; } @@ -89,7 +90,7 @@ bool Gps_CNAV_Navigation_Message::read_navigation_bool(std::bitset bits, const std::vector> parameter) +unsigned long int Gps_CNAV_Navigation_Message::read_navigation_unsigned(std::bitset bits, const std::vector> parameter) { unsigned long int value = 0; int num_of_slices = parameter.size(); @@ -98,7 +99,7 @@ unsigned long int Gps_CNAV_Navigation_Message::read_navigation_unsigned(std::bit for (int j = 0; j < parameter[i].second; j++) { value <<= 1; //shift left - if (bits[GPS_L2_CNAV_DATA_PAGE_BITS - parameter[i].first - j] == 1) + if (bits[GPS_CNAV_DATA_PAGE_BITS - parameter[i].first - j] == 1) { value += 1; // insert the bit } @@ -108,7 +109,7 @@ unsigned long int Gps_CNAV_Navigation_Message::read_navigation_unsigned(std::bit } -signed long int Gps_CNAV_Navigation_Message::read_navigation_signed(std::bitset bits, const std::vector> parameter) +signed long int Gps_CNAV_Navigation_Message::read_navigation_signed(std::bitset bits, const std::vector> parameter) { signed long int value = 0; int num_of_slices = parameter.size(); @@ -117,7 +118,7 @@ signed long int Gps_CNAV_Navigation_Message::read_navigation_signed(std::bitset< if (long_int_size_bytes == 8) // if a long int takes 8 bytes, we are in a 64 bits system { // read the MSB and perform the sign extension - if (bits[GPS_L2_CNAV_DATA_PAGE_BITS - parameter[0].first] == 1) + if (bits[GPS_CNAV_DATA_PAGE_BITS - parameter[0].first] == 1) { value ^= 0xFFFFFFFFFFFFFFFF; //64 bits variable } @@ -132,7 +133,7 @@ signed long int Gps_CNAV_Navigation_Message::read_navigation_signed(std::bitset< { value <<= 1; //shift left value &= 0xFFFFFFFFFFFFFFFE; //reset the corresponding bit (for the 64 bits variable) - if (bits[GPS_L2_CNAV_DATA_PAGE_BITS - parameter[i].first - j] == 1) + if (bits[GPS_CNAV_DATA_PAGE_BITS - parameter[i].first - j] == 1) { value += 1; // insert the bit } @@ -142,7 +143,7 @@ signed long int Gps_CNAV_Navigation_Message::read_navigation_signed(std::bitset< else // we assume we are in a 32 bits system { // read the MSB and perform the sign extension - if (bits[GPS_L2_CNAV_DATA_PAGE_BITS - parameter[0].first] == 1) + if (bits[GPS_CNAV_DATA_PAGE_BITS - parameter[0].first] == 1) { value ^= 0xFFFFFFFF; } @@ -157,7 +158,7 @@ signed long int Gps_CNAV_Navigation_Message::read_navigation_signed(std::bitset< { value <<= 1; //shift left value &= 0xFFFFFFFE; //reset the corresponding bit - if (bits[GPS_L2_CNAV_DATA_PAGE_BITS - parameter[i].first - j] == 1) + if (bits[GPS_CNAV_DATA_PAGE_BITS - parameter[i].first - j] == 1) { value += 1; // insert the bit } @@ -168,7 +169,7 @@ signed long int Gps_CNAV_Navigation_Message::read_navigation_signed(std::bitset< } -void Gps_CNAV_Navigation_Message::decode_page(std::bitset data_bits) +void Gps_CNAV_Navigation_Message::decode_page(std::bitset data_bits) { int PRN; int page_type; @@ -188,7 +189,6 @@ void Gps_CNAV_Navigation_Message::decode_page(std::bitset(read_navigation_unsigned(data_bits, CNAV_MSG_TYPE)); - //std::cout << "PRN=" << PRN << " TOW=" << d_TOW << " alert_flag=" << alert_flag << " page_type= " << page_type << std::endl; switch(page_type) { case 10: // Ephemeris 1/2 diff --git a/src/core/system_parameters/gps_cnav_navigation_message.h b/src/core/system_parameters/gps_cnav_navigation_message.h index 9ab370a1a..3fd1fa913 100644 --- a/src/core/system_parameters/gps_cnav_navigation_message.h +++ b/src/core/system_parameters/gps_cnav_navigation_message.h @@ -38,7 +38,7 @@ #include #include #include -#include "GPS_L2C.h" +#include "GPS_CNAV.h" #include "gps_cnav_ephemeris.h" #include "gps_cnav_iono.h" #include "gps_cnav_utc_model.h" @@ -55,9 +55,9 @@ class Gps_CNAV_Navigation_Message { private: - unsigned long int read_navigation_unsigned(std::bitset bits, const std::vector> parameter); - signed long int read_navigation_signed(std::bitset bits, const std::vector> parameter); - bool read_navigation_bool(std::bitset bits, const std::vector> parameter); + unsigned long int read_navigation_unsigned(std::bitset bits, const std::vector> parameter); + signed long int read_navigation_signed(std::bitset bits, const std::vector> parameter); + bool read_navigation_bool(std::bitset bits, const std::vector> parameter); Gps_CNAV_Ephemeris ephemeris_record; Gps_CNAV_Iono iono_record; @@ -89,7 +89,7 @@ public: // public functions void reset(); - void decode_page(std::bitset data_bits); + void decode_page(std::bitset data_bits); /*! * \brief Obtain a GPS SV Ephemeris class filled with current SV data */ diff --git a/src/core/system_parameters/rtcm.cc b/src/core/system_parameters/rtcm.cc index 2c5913674..ee5204b97 100644 --- a/src/core/system_parameters/rtcm.cc +++ b/src/core/system_parameters/rtcm.cc @@ -41,6 +41,7 @@ #include #include #include "Galileo_E1.h" +#include "GPS_L2C.h" using google::LogMessage; diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 0c86b84a5..3394d8a2e 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -260,8 +260,15 @@ if(ENABLE_UNIT_TESTING_EXTRA) SHOW_PROGRESS EXPECTED_HASH MD5=a6fcbefe155137945d3c33c5ef7bd0f9 ) endif(NOT EXISTS ${CMAKE_SOURCE_DIR}/thirdparty/signal_samples/gps_l2c_m_prn7_5msps.dat) + if(NOT EXISTS ${CMAKE_SOURCE_DIR}/thirdparty/signal_samples/Glonass_L1_CA_SIM_Fs_62Msps_4ms.dat) + message(STATUS "Downloading some data files for testing...") + file(DOWNLOAD https://sourceforge.net/projects/gnss-sdr/files/data/Glonass_L1_CA_SIM_Fs_62Msps_4ms.dat ${CMAKE_CURRENT_SOURCE_DIR}/../../thirdparty/signal_samples/Glonass_L1_CA_SIM_Fs_62Msps_4ms.dat + SHOW_PROGRESS + EXPECTED_HASH MD5=ffb72fc63c116be58d5e5ccb1daaed3a ) + endif(NOT EXISTS ${CMAKE_SOURCE_DIR}/thirdparty/signal_samples/Glonass_L1_CA_SIM_Fs_62Msps_4ms.dat) if(ENABLE_INSTALL_TESTS) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../../thirdparty/signal_samples/gps_l2c_m_prn7_5msps.dat DESTINATION share/gnss-sdr/signal_samples) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../../thirdparty/signal_samples/Glonass_L1_CA_SIM_Fs_62Msps_4ms.dat DESTINATION share/gnss-sdr/signal_samples) endif(ENABLE_INSTALL_TESTS) endif(ENABLE_UNIT_TESTING_EXTRA) @@ -269,14 +276,12 @@ if(ENABLE_INSTALL_TESTS) install(FILES ${CMAKE_SOURCE_DIR}/src/tests/signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms.dat DESTINATION share/gnss-sdr/signal_samples) install(FILES ${CMAKE_SOURCE_DIR}/src/tests/signal_samples/Galileo_E1_ID_1_Fs_4Msps_8ms.dat DESTINATION share/gnss-sdr/signal_samples) install(FILES ${CMAKE_SOURCE_DIR}/src/tests/signal_samples/GPS_L1_CA_ID_1_Fs_4Msps_2ms.dat DESTINATION share/gnss-sdr/signal_samples) - install(FILES ${CMAKE_SOURCE_DIR}/src/tests/signal_samples/Glonass_L1_CA_SIM_Fs_62Msps_4ms.dat DESTINATION share/gnss-sdr/signal_samples) install(FILES ${CMAKE_SOURCE_DIR}/src/tests/signal_samples/NT1065_GLONASS_L1_20160831_fs6625e6_if0e3_4ms.bin DESTINATION share/gnss-sdr/signal_samples) add_definitions(-DTEST_PATH="${CMAKE_INSTALL_PREFIX}/share/gnss-sdr/") else(ENABLE_INSTALL_TESTS) file(COPY ${CMAKE_SOURCE_DIR}/src/tests/signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms.dat DESTINATION ${CMAKE_SOURCE_DIR}/thirdparty/signal_samples) file(COPY ${CMAKE_SOURCE_DIR}/src/tests/signal_samples/Galileo_E1_ID_1_Fs_4Msps_8ms.dat DESTINATION ${CMAKE_SOURCE_DIR}/thirdparty/signal_samples) file(COPY ${CMAKE_SOURCE_DIR}/src/tests/signal_samples/GPS_L1_CA_ID_1_Fs_4Msps_2ms.dat DESTINATION ${CMAKE_SOURCE_DIR}/thirdparty/signal_samples) - file(COPY ${CMAKE_SOURCE_DIR}/src/tests/signal_samples/Glonass_L1_CA_SIM_Fs_62Msps_4ms.dat DESTINATION ${CMAKE_SOURCE_DIR}/thirdparty/signal_samples) file(COPY ${CMAKE_SOURCE_DIR}/src/tests/signal_samples/NT1065_GLONASS_L1_20160831_fs6625e6_if0e3_4ms.bin DESTINATION ${CMAKE_SOURCE_DIR}/thirdparty/signal_samples) add_definitions(-DTEST_PATH="${CMAKE_SOURCE_DIR}/thirdparty/") endif(ENABLE_INSTALL_TESTS) diff --git a/src/tests/signal_samples/Glonass_L1_CA_SIM_Fs_62Msps_4ms.dat b/src/tests/signal_samples/Glonass_L1_CA_SIM_Fs_62Msps_4ms.dat deleted file mode 100644 index 8d7b27c25..000000000 Binary files a/src/tests/signal_samples/Glonass_L1_CA_SIM_Fs_62Msps_4ms.dat and /dev/null differ diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index ee86e63da..4f5fb78c1 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -110,7 +110,6 @@ DECLARE_string(log_dir); #include "unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_cccwsr_ambiguous_acquisition_gsoc2013_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_quicksync_ambiguous_acquisition_gsoc2014_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc" -#include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc" #if OPENCL_BLOCKS_TEST @@ -119,6 +118,8 @@ DECLARE_string(log_dir); #include "unit-tests/signal-processing-blocks/tracking/galileo_e1_dll_pll_veml_tracking_test.cc" #include "unit-tests/signal-processing-blocks/tracking/galileo_e5a_tracking_test.cc" +#include "unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_tracking_test.cc" +#include "unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_c_aid_tracking_test.cc" #include "unit-tests/signal-processing-blocks/tracking/tracking_loop_filter_test.cc" #include "unit-tests/signal-processing-blocks/tracking/cpu_multicorrelator_test.cc" #include "unit-tests/signal-processing-blocks/tracking/cpu_multicorrelator_real_codes_test.cc" @@ -139,9 +140,8 @@ DECLARE_string(log_dir); #if EXTRA_TESTS #include "unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc" +#include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc" #include "unit-tests/signal-processing-blocks/tracking/gps_l2_m_dll_pll_tracking_test.cc" -#include "unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_tracking_test.cc" -#include "unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_c_aid_tracking_test.cc" #if MODERN_ARMADILLO #include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc" #include "unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc" diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc index abc2bedb3..47e56df36 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc @@ -1,3 +1,36 @@ +/*! + * \file glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc + * \brief Tests a PCPS acquisition block for Glonass L1 C/A signals + * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com + * \author Luis Esteve, 2017. luis(at)epsilon-formacion.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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 . + * + * ------------------------------------------------------------------------- + */ + + #include #include #include @@ -420,14 +453,14 @@ TEST_F(GlonassL1CaPcpsAcquisitionGSoC2017Test, ConnectAndRun) 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."<< std::endl; + }) << "Failure connecting the blocks of acquisition test."; EXPECT_NO_THROW( { begin = std::chrono::system_clock::now(); top_block->run(); // Start threads and wait end = std::chrono::system_clock::now(); elapsed_seconds = end - begin; - }) << "Failure running the top_block."<< std::endl; + }) << "Failure running the top_block."; std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; @@ -446,28 +479,28 @@ TEST_F(GlonassL1CaPcpsAcquisitionGSoC2017Test, ValidationOfResults) ASSERT_NO_THROW( { acquisition->set_channel(1); - }) << "Failure setting channel."<< std::endl; + }) << "Failure setting channel."; ASSERT_NO_THROW( { acquisition->set_gnss_synchro(&gnss_synchro); - }) << "Failure setting gnss_synchro."<< std::endl; + }) << "Failure setting gnss_synchro."; ASSERT_NO_THROW( { acquisition->set_doppler_max(10000); - }) << "Failure setting doppler_max."<< std::endl; + }) << "Failure setting doppler_max."; ASSERT_NO_THROW( { acquisition->set_doppler_step(500); - }) << "Failure setting doppler_step."<< std::endl; + }) << "Failure setting doppler_step."; ASSERT_NO_THROW( { acquisition->set_threshold(0.5); - }) << "Failure setting threshold."<< std::endl; + }) << "Failure setting threshold."; ASSERT_NO_THROW( { acquisition->connect(top_block); top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); - }) << "Failure connecting acquisition to the top_block."<< std::endl; + }) << "Failure connecting acquisition to the top_block."; acquisition->init(); @@ -478,7 +511,7 @@ TEST_F(GlonassL1CaPcpsAcquisitionGSoC2017Test, ValidationOfResults) signal_source.reset(new GenSignalSource(signal_generator, filter, "SignalSource", queue)); signal_source->connect(top_block); top_block->connect(signal_source->get_right_block(), 0, acquisition->get_left_block(), 0); - }) << "Failure connecting the blocks of acquisition test." << std::endl; + }) << "Failure connecting the blocks of acquisition test."; // i = 0 --> satellite in acquisition is visible // i = 1 --> satellite in acquisition is not visible @@ -501,7 +534,7 @@ TEST_F(GlonassL1CaPcpsAcquisitionGSoC2017Test, ValidationOfResults) EXPECT_NO_THROW( { top_block->run(); // Start threads and wait - }) << "Failure running the top_block."<< std::endl; + }) << "Failure running the top_block."; if (i == 0) { @@ -519,12 +552,12 @@ TEST_F(GlonassL1CaPcpsAcquisitionGSoC2017Test, ValidationOfResults) #ifdef OLD_BOOST ASSERT_NO_THROW( { ch_thread.timed_join(boost::posix_time::seconds(1)); - }) << "Failure while waiting the queue to stop" << std::endl; + }) << "Failure while waiting the queue to stop."; #endif #ifndef OLD_BOOST ASSERT_NO_THROW( { ch_thread.try_join_until(boost::chrono::steady_clock::now() + boost::chrono::milliseconds(50)); - }) << "Failure while waiting the queue to stop" << std::endl; + }) << "Failure while waiting the queue to stop"; #endif } diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc index a49aa3952..7cee76a52 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc @@ -1,3 +1,35 @@ +/*! + * \file glonass_l1_ca_pcps_acquisition_test.cc + * \brief Tests a PCPS acquisition block for Glonass L1 C/A signals + * \author Gabriel Araujo, 2017. gabriel.araujo.5000(at)gmail.com + * \author Luis Esteve, 2017. luis(at)epsilon-formacion.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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 . + * + * ------------------------------------------------------------------------- + */ + #include #include #include @@ -105,24 +137,24 @@ void GlonassL1CaPcpsAcquisitionTest::init() signal.copy(gnss_synchro.Signal, 2, 0); gnss_synchro.PRN = 1; config->set_property("GNSS-SDR.internal_fs_sps", "62314000"); - config->set_property("Acquisition.item_type", "gr_complex"); - config->set_property("Acquisition.if", "9540000"); - config->set_property("Acquisition.coherent_integration_time_ms", "1"); - config->set_property("Acquisition.dump", "true"); - config->set_property("Acquisition.dump_filename", "./acquisition.dat"); - config->set_property("Acquisition.implementation", "Glonass_L1_CA_PCPS_Acquisition"); - config->set_property("Acquisition.threshold", "0.001"); - config->set_property("Acquisition.doppler_max", "5000"); - config->set_property("Acquisition.doppler_step", "500"); - config->set_property("Acquisition.repeat_satellite", "false"); - config->set_property("Acquisition.pfa", "0.0"); + config->set_property("Acquisition_1G.item_type", "gr_complex"); + config->set_property("Acquisition_1G.if", "9540000"); + config->set_property("Acquisition_1G.coherent_integration_time_ms", "1"); + config->set_property("Acquisition_1G.dump", "true"); + config->set_property("Acquisition_1G.dump_filename", "./acquisition.dat"); + config->set_property("Acquisition_1G.implementation", "Glonass_L1_CA_PCPS_Acquisition"); + config->set_property("Acquisition_1G.threshold", "0.001"); + config->set_property("Acquisition_1G.doppler_max", "5000"); + config->set_property("Acquisition_1G.doppler_step", "500"); + config->set_property("Acquisition_1G.repeat_satellite", "false"); + //config->set_property("Acquisition_1G.pfa", "0.0"); } TEST_F(GlonassL1CaPcpsAcquisitionTest, Instantiate) { init(); - boost::shared_ptr acquisition = boost::make_shared(config.get(), "Acquisition", 1, 1); + boost::shared_ptr acquisition = boost::make_shared(config.get(), "Acquisition_1G", 1, 1); } @@ -136,7 +168,7 @@ TEST_F(GlonassL1CaPcpsAcquisitionTest, ConnectAndRun) top_block = gr::make_top_block("Acquisition test"); init(); - boost::shared_ptr acquisition = boost::make_shared(config.get(), "Acquisition", 1, 1); + boost::shared_ptr acquisition = boost::make_shared(config.get(), "Acquisition_1G", 1, 1); boost::shared_ptr msg_rx = GlonassL1CaPcpsAcquisitionTest_msg_rx_make(); ASSERT_NO_THROW( { @@ -146,15 +178,14 @@ TEST_F(GlonassL1CaPcpsAcquisitionTest, ConnectAndRun) 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." << std::endl; + }) << "Failure connecting the blocks of acquisition test."; EXPECT_NO_THROW( { begin = std::chrono::system_clock::now(); top_block->run(); // Start threads and wait end = std::chrono::system_clock::now(); elapsed_seconds = end - begin; - }) << "Failure running the top_block." << std::endl; + }) << "Failure running the top_block."; std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; } @@ -167,35 +198,39 @@ TEST_F(GlonassL1CaPcpsAcquisitionTest, ValidationOfResults) top_block = gr::make_top_block("Acquisition test"); double expected_delay_samples = 31874; - double expected_doppler_hz = -9500; + double expected_doppler_hz = -8000; init(); - std::shared_ptr acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); + std::shared_ptr acquisition = std::make_shared(config.get(), "Acquisition_1G", 1, 1); boost::shared_ptr msg_rx = GlonassL1CaPcpsAcquisitionTest_msg_rx_make(); ASSERT_NO_THROW( { acquisition->set_channel(1); - }) << "Failure setting channel." << std::endl; + }) << "Failure setting channel."; ASSERT_NO_THROW( { acquisition->set_gnss_synchro(&gnss_synchro); - }) << "Failure setting gnss_synchro." << std::endl; + }) << "Failure setting gnss_synchro."; ASSERT_NO_THROW( { - acquisition->set_threshold(0.001); - }) << "Failure setting threshold." << std::endl; + acquisition->set_threshold(0.005); + }) << "Failure setting threshold."; ASSERT_NO_THROW( { acquisition->set_doppler_max(10000); - }) << "Failure setting doppler_max." << std::endl; + }) << "Failure setting doppler_max."; ASSERT_NO_THROW( { - acquisition->set_doppler_step(250); - }) << "Failure setting doppler_step." << std::endl; + acquisition->set_doppler_step(500); + }) << "Failure setting doppler_step."; ASSERT_NO_THROW( { acquisition->connect(top_block); - }) << "Failure connecting acquisition to the top_block." << std::endl; + }) << "Failure connecting acquisition to the top_block."; + + acquisition->set_local_code(); + acquisition->set_state(1); // Ensure that acquisition starts at the first sample + acquisition->init(); ASSERT_NO_THROW( { std::string path = std::string(TEST_PATH); @@ -204,19 +239,14 @@ TEST_F(GlonassL1CaPcpsAcquisitionTest, ValidationOfResults) 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." << std::endl; - - - acquisition->set_state(1); // Ensure that acquisition starts at the first sample - acquisition->init(); + }) << "Failure connecting the blocks of acquisition test."; EXPECT_NO_THROW( { begin = std::chrono::system_clock::now(); top_block->run(); // Start threads and wait end = std::chrono::system_clock::now(); elapsed_seconds = end - begin; - }) << "Failure running the top_block." << std::endl; - + }) << "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; diff --git a/src/tests/unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc b/src/tests/unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc index ceb2d8373..963ab0186 100644 --- a/src/tests/unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc @@ -174,7 +174,7 @@ TEST(RinexPrinterTest, MixedObsHeaderGpsGlo) std::shared_ptr rp1; rp1 = std::make_shared(); - rp1->rinex_obs_header(rp1->obsFile, eph_gps, eph_glo, 0.0, "1C"); + rp1->rinex_obs_header(rp1->obsFile, eph_gps, eph_glo, 0.0, "1G"); rp1->obsFile.seekp(0); int systems_found = 0; @@ -200,7 +200,7 @@ TEST(RinexPrinterTest, MixedObsHeaderGpsGlo) } std::string expected_str("G 4 C1C L1C D1C S1C SYS / # / OBS TYPES "); - std::string expected_str2("R 8 C1C L1C D1C S1C SYS / # / OBS TYPES "); + std::string expected_str2("R 4 C1C L1C D1C S1C SYS / # / OBS TYPES "); EXPECT_EQ(0, expected_str.compare(line_aux)); EXPECT_EQ(0, expected_str2.compare(line_aux2)); if(remove(rp1->obsfilename.c_str()) != 0) LOG(INFO) << "Error deleting temporary file"; @@ -627,7 +627,7 @@ TEST(RinexPrinterTest, MixedObsLogGpsGlo) std::shared_ptr rp; rp = std::make_shared(); - rp->rinex_obs_header(rp->obsFile, eph_gps, eph_glo, 0.0, "1C"); + rp->rinex_obs_header(rp->obsFile, eph_gps, eph_glo, 0.0, "1G"); std::map gnss_pseudoranges_map; @@ -658,7 +658,7 @@ TEST(RinexPrinterTest, MixedObsLogGpsGlo) std::memcpy((void*)gs3.Signal, sig.c_str(), 3); std::memcpy((void*)gs4.Signal, sig.c_str(), 3); - sig = "1C"; + sig = "1G"; std::memcpy((void*)gs5.Signal, sig.c_str(), 3); std::memcpy((void*)gs6.Signal, sig.c_str(), 3); std::memcpy((void*)gs7.Signal, sig.c_str(), 3); @@ -718,7 +718,8 @@ TEST(RinexPrinterTest, MixedObsLogGpsGlo) } } } - std::string expected_str("R16 22000000.000 7 0.127 7 -20.000 7 42.000 22000000.000 6 8.292 6 1534.000 6 41.000"); + + std::string expected_str("R16 22000000.000 6 8.292 6 1534.000 6 41.000 22000000.000 7 0.127 7 -20.000 7 42.000"); EXPECT_EQ(0, expected_str.compare(line_aux)); if(remove(rp->obsfilename.c_str()) != 0) LOG(INFO) << "Error deleting temporary file"; diff --git a/src/tests/unit-tests/signal-processing-blocks/pvt/rtcm_test.cc b/src/tests/unit-tests/signal-processing-blocks/pvt/rtcm_test.cc index 839df16dc..fdc7084a4 100644 --- a/src/tests/unit-tests/signal-processing-blocks/pvt/rtcm_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/pvt/rtcm_test.cc @@ -280,7 +280,6 @@ TEST(RtcmTest, MT1019) TEST(RtcmTest, MT1020) { auto rtcm = std::make_shared(); - bool expected_true = true; // Objects to populate the ephemeris and utc fields Glonass_Gnav_Ephemeris gnav_ephemeris = Glonass_Gnav_Ephemeris(); @@ -357,7 +356,7 @@ TEST(RtcmTest, MSMCell) auto rtcm = std::make_shared(); Gps_Ephemeris gps_eph = Gps_Ephemeris(); Galileo_Ephemeris gal_eph = Galileo_Ephemeris(); - Glonass_Gnav_Ephemeris glo_gnav_eph = Glonass_Gnav_Ephemeris(); + //Glonass_Gnav_Ephemeris glo_gnav_eph = Glonass_Gnav_Ephemeris(); std::map pseudoranges; Gnss_Synchro gnss_synchro; @@ -420,7 +419,7 @@ TEST(RtcmTest, MSMCell) gps_eph.i_satellite_PRN = gnss_synchro2.PRN; gal_eph.i_satellite_PRN = gnss_synchro.PRN; - glo_gnav_eph.i_satellite_PRN = gnss_synchro.PRN; + //glo_gnav_eph.i_satellite_PRN = gnss_synchro.PRN; std::string MSM1 = rtcm->print_MSM_1(gps_eph, {}, @@ -463,7 +462,7 @@ TEST(RtcmTest, MSMCell) divergence_free, more_messages); std::string MSM1_bin_2 = rtcm->binary_data_to_bin(MSM1_2); - EXPECT_EQ(0, MSM1_bin_2.substr(size_header + size_msg_length + 169, Nsat * Nsig).compare("001010101100")); // check cell mask + EXPECT_EQ(0, MSM1_bin_2.substr(size_header + size_msg_length + 169, Nsat * Nsig).compare("001010001100")); // check cell mask Gnss_Synchro gnss_synchro7; gnss_synchro7.PRN = 10; diff --git a/src/tests/unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_c_aid_tracking_test.cc b/src/tests/unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_c_aid_tracking_test.cc index 9876b63f3..e845b0d22 100644 --- a/src/tests/unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_c_aid_tracking_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_c_aid_tracking_test.cc @@ -31,7 +31,7 @@ */ -#include +#include #include #include #include @@ -149,11 +149,11 @@ void GlonassL1CaDllPllCAidTrackingTest::init() config->set_property("Tracking_1G.dll_bw_hz", "0.5"); } + TEST_F(GlonassL1CaDllPllCAidTrackingTest, ValidationOfResults) { - struct timeval tv; - long long int begin = 0; - long long int end = 0; + std::chrono::time_point start, end; + std::chrono::duration elapsed_seconds(0); int fs_in = 6625000; int nsamples = fs_in*4e-3*2; @@ -170,15 +170,15 @@ TEST_F(GlonassL1CaDllPllCAidTrackingTest, ValidationOfResults) ASSERT_NO_THROW( { tracking->set_channel(gnss_synchro.Channel_ID); - }) << "Failure setting channel." << std::endl; + }) << "Failure setting channel."; ASSERT_NO_THROW( { tracking->set_gnss_synchro(&gnss_synchro); - }) << "Failure setting gnss_synchro." << std::endl; + }) << "Failure setting gnss_synchro."; ASSERT_NO_THROW( { tracking->connect(top_block); - }) << "Failure connecting tracking to the top_block." << std::endl; + }) << "Failure connecting tracking to the top_block."; ASSERT_NO_THROW( { gr::analog::sig_source_c::sptr sin_source = gr::analog::sig_source_c::make(fs_in, gr::analog::GR_SIN_WAVE, 1000, 1, gr_complex(0)); @@ -192,18 +192,17 @@ TEST_F(GlonassL1CaDllPllCAidTrackingTest, ValidationOfResults) top_block->connect(valve, 0, tracking->get_left_block(), 0); top_block->connect(tracking->get_right_block(), 0, sink, 0); top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); - }) << "Failure connecting the blocks of tracking test." << std::endl; + }) << "Failure connecting the blocks of tracking test."; tracking->start_tracking(); EXPECT_NO_THROW( { - gettimeofday(&tv, NULL); - begin = tv.tv_sec *1000000 + tv.tv_usec; + start = std::chrono::system_clock::now(); top_block->run(); // Start threads and wait - gettimeofday(&tv, NULL); - end = tv.tv_sec *1000000 + tv.tv_usec; - }) << "Failure running the top_block." << std::endl; + end = std::chrono::system_clock::now(); + elapsed_seconds = end - start; + }) << "Failure running the top_block."; // TODO: Verify tracking results - std::cout << "Tracked " << nsamples << " samples in " << (end - begin) << " microseconds" << std::endl; + std::cout << "Tracked " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; } diff --git a/src/tests/unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_tracking_test.cc b/src/tests/unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_tracking_test.cc index 1158f368c..6625fda4f 100644 --- a/src/tests/unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_tracking_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/tracking/glonass_l1_ca_dll_pll_tracking_test.cc @@ -31,7 +31,7 @@ */ -#include +#include #include #include #include @@ -151,9 +151,8 @@ void GlonassL1CaDllPllTrackingTest::init() TEST_F(GlonassL1CaDllPllTrackingTest, ValidationOfResults) { - struct timeval tv; - long long int begin = 0; - long long int end = 0; + std::chrono::time_point start, end; + std::chrono::duration elapsed_seconds(0); int fs_in = 6625000; int nsamples = fs_in*4e-3*2; @@ -170,15 +169,15 @@ TEST_F(GlonassL1CaDllPllTrackingTest, ValidationOfResults) ASSERT_NO_THROW( { tracking->set_channel(gnss_synchro.Channel_ID); - }) << "Failure setting channel." << std::endl; + }) << "Failure setting channel."; ASSERT_NO_THROW( { tracking->set_gnss_synchro(&gnss_synchro); - }) << "Failure setting gnss_synchro." << std::endl; + }) << "Failure setting gnss_synchro."; ASSERT_NO_THROW( { tracking->connect(top_block); - }) << "Failure connecting tracking to the top_block." << std::endl; + }) << "Failure connecting tracking to the top_block."; ASSERT_NO_THROW( { gr::analog::sig_source_c::sptr sin_source = gr::analog::sig_source_c::make(fs_in, gr::analog::GR_SIN_WAVE, 1000, 1, gr_complex(0)); @@ -192,18 +191,17 @@ TEST_F(GlonassL1CaDllPllTrackingTest, ValidationOfResults) top_block->connect(valve, 0, tracking->get_left_block(), 0); top_block->connect(tracking->get_right_block(), 0, sink, 0); top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); - }) << "Failure connecting the blocks of tracking test." << std::endl; + }) << "Failure connecting the blocks of tracking test."; tracking->start_tracking(); EXPECT_NO_THROW( { - gettimeofday(&tv, NULL); - begin = tv.tv_sec *1000000 + tv.tv_usec; + start = std::chrono::system_clock::now(); top_block->run(); // Start threads and wait - gettimeofday(&tv, NULL); - end = tv.tv_sec *1000000 + tv.tv_usec; - }) << "Failure running the top_block." << std::endl; + end = std::chrono::system_clock::now(); + elapsed_seconds = end - start; + }) << "Failure running the top_block."; // TODO: Verify tracking results - std::cout << "Tracked " << nsamples << " samples in " << (end - begin) << " microseconds" << std::endl; + std::cout << "Tracked " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; } diff --git a/src/tests/unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc b/src/tests/unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc index 7026903e2..10f0cc28d 100644 --- a/src/tests/unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc +++ b/src/tests/unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc @@ -1,5 +1,5 @@ /*! - * \file code_generation_test.cc + * \file glonass_gnav_ephemeris_test.cc.cc * \note Code added as part of GSoC 2017 program * \author Damian Miralles, 2017. dmiralles2009(at)gmail.com * \see GLONASS ICD @@ -7,7 +7,7 @@ * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -31,9 +31,6 @@ */ -#include -#include -#include #include "gnss_signal_processing.h" #include "glonass_gnav_ephemeris.h" @@ -49,21 +46,22 @@ TEST(GlonassGnavEphemerisTest, ComputeGlonassTime) d = d + d2; boost::gregorian::date expected_gdate; - boost::posix_time::time_duration expected_gtime; + boost::posix_time::time_duration expected_gtime; - boost::posix_time::ptime gtime = gnav_eph.compute_GLONASS_time(7560); - expected_gdate = gtime.date(); - expected_gtime = gtime.time_of_day(); + boost::posix_time::ptime gtime = gnav_eph.compute_GLONASS_time(7560); + expected_gdate = gtime.date(); + expected_gtime = gtime.time_of_day(); // Perform assertions of decoded fields - ASSERT_TRUE(expected_gdate.year() - d.year() < FLT_EPSILON ); - ASSERT_TRUE(expected_gdate.month() - d.month() < FLT_EPSILON ); - ASSERT_TRUE(expected_gdate.day() - d.day() < FLT_EPSILON ); - ASSERT_TRUE(expected_gtime.hours() - t.hours() < FLT_EPSILON ); - ASSERT_TRUE(expected_gtime.minutes() - t.minutes() < FLT_EPSILON ); - ASSERT_TRUE(expected_gtime.seconds() - t.seconds() < FLT_EPSILON ); + ASSERT_TRUE(expected_gdate.year() - d.year() < FLT_EPSILON ); + ASSERT_TRUE(expected_gdate.month() - d.month() < FLT_EPSILON ); + ASSERT_TRUE(expected_gdate.day() - d.day() < FLT_EPSILON ); + ASSERT_TRUE(expected_gtime.hours() - t.hours() < FLT_EPSILON ); + ASSERT_TRUE(expected_gtime.minutes() - t.minutes() < FLT_EPSILON ); + ASSERT_TRUE(expected_gtime.seconds() - t.seconds() < FLT_EPSILON ); } + /*! * \brief Testing conversion from GLONASST to GPST * \test Tests scenario for N_T when greater than 365 days. Possible values here from 1 to 365*4 @@ -82,13 +80,14 @@ TEST(GlonassGnavEphemerisTest, ConvertGlonassT2GpsT1) double true_week = 1307; double true_tow = 480600+true_leap_sec; - gnav_eph.glot_to_gpst(tod + glo2utc, 0.0, 0.0, &week, &tow); + gnav_eph.glot_to_gpst(tod + glo2utc, 0.0, 0.0, &week, &tow); // Perform assertions of decoded fields - ASSERT_TRUE(week - true_week < FLT_EPSILON ); - ASSERT_TRUE(tow - true_tow < FLT_EPSILON ); + ASSERT_TRUE(week - true_week < FLT_EPSILON ); + ASSERT_TRUE(tow - true_tow < FLT_EPSILON ); } + /*! * \brief Testing conversion from GLONASST to GPST * \test This version tests the conversion for offsets greater than 30 in a leap year @@ -107,13 +106,14 @@ TEST(GlonassGnavEphemerisTest, ConvertGlonassT2GpsT2) double true_week = 1915; double true_tow = 518400+true_leap_sec+tod; - gnav_eph.glot_to_gpst(tod + glo2utc, 0.0, 0.0, &week, &tow); + gnav_eph.glot_to_gpst(tod + glo2utc, 0.0, 0.0, &week, &tow); // Perform assertions of decoded fields - ASSERT_TRUE(week - true_week < FLT_EPSILON ); - ASSERT_TRUE(tow - true_tow < FLT_EPSILON ); + ASSERT_TRUE(week - true_week < FLT_EPSILON ); + ASSERT_TRUE(tow - true_tow < FLT_EPSILON ); } + /*! * \brief Testing conversion from GLONASST to GPST * \test This version tests the conversion around the vicinity of February 29 days when in leap year @@ -132,9 +132,9 @@ TEST(GlonassGnavEphemerisTest, ConvertGlonassT2GpsT3) double true_week = 1886; double true_tow = 259200+true_leap_sec+tod; - gnav_eph.glot_to_gpst(tod + glo2utc, 0.0, 0.0, &week, &tow); + gnav_eph.glot_to_gpst(tod + glo2utc, 0.0, 0.0, &week, &tow); // Perform assertions of decoded fields - ASSERT_TRUE(week - true_week < FLT_EPSILON ); - ASSERT_TRUE(tow - true_tow < FLT_EPSILON ); + ASSERT_TRUE(week - true_week < FLT_EPSILON ); + ASSERT_TRUE(tow - true_tow < FLT_EPSILON ); } diff --git a/src/tests/unit-tests/system-parameters/glonass_gnav_nav_message_test.cc b/src/tests/unit-tests/system-parameters/glonass_gnav_nav_message_test.cc index 595b1fa2f..e613af58a 100644 --- a/src/tests/unit-tests/system-parameters/glonass_gnav_nav_message_test.cc +++ b/src/tests/unit-tests/system-parameters/glonass_gnav_nav_message_test.cc @@ -31,11 +31,6 @@ * ------------------------------------------------------------------------- */ - -#include -#include -#include -#include #include "gnss_signal_processing.h" #include "glonass_gnav_navigation_message.h" @@ -59,6 +54,7 @@ TEST(GlonassGnavNavigationMessageTest, CRCTestSuccess) ASSERT_TRUE(test_result); } + /*! * \brief Testing CRC computation for GLONASS GNAV data bits of a string * \test The provided string was generated with a version of MATLAB GNSS-SDR that @@ -80,6 +76,7 @@ TEST(GlonassGnavNavigationMessageTest, CRCTestFailure) ASSERT_FALSE(test_result); } + /*! * \brief Testing string decoding for GLONASS GNAV messages * \test The provided string (str1.....str15) was generated with a version of @@ -112,6 +109,7 @@ TEST(GlonassGnavNavigationMessageTest, String1Decoder) ASSERT_TRUE(gnav_ephemeris.d_Xn - gnav_nav_message.gnav_ephemeris.d_Xn < FLT_EPSILON ); } + /*! * \brief Testing string decoding for GLONASS GNAV messages * \test The provided string (str1.....str15) was generated with a version of @@ -148,6 +146,7 @@ TEST(GlonassGnavNavigationMessageTest, String2Decoder) ASSERT_TRUE(gnav_ephemeris.d_Yn - gnav_nav_message.gnav_ephemeris.d_Yn < FLT_EPSILON ); } + /*! * \brief Testing string decoding for GLONASS GNAV messages * \test The provided string (str1.....str15) was generated with a version of @@ -185,6 +184,7 @@ TEST(GlonassGnavNavigationMessageTest, String3Decoder) ASSERT_TRUE(gnav_ephemeris.d_Zn - gnav_nav_message.gnav_ephemeris.d_Zn < FLT_EPSILON ); } + /*! * \brief Testing string decoding for GLONASS GNAV messages * \test The provided string (str1.....str15) was generated with a version of @@ -224,6 +224,7 @@ TEST(GlonassGnavNavigationMessageTest, String4Decoder) ASSERT_TRUE(gnav_ephemeris.d_M - gnav_nav_message.gnav_ephemeris.d_M < FLT_EPSILON ); } + /*! * \brief Testing string decoding for GLONASS GNAV messages * \test The provided string (str1.....str15) was generated with a version of diff --git a/src/utils/front-end-cal/main.cc b/src/utils/front-end-cal/main.cc index cc53987f4..f4c53cd00 100644 --- a/src/utils/front-end-cal/main.cc +++ b/src/utils/front-end-cal/main.cc @@ -422,6 +422,7 @@ int main(int argc, char** argv) gnss_synchro->PRN = PRN; acquisition->set_gnss_synchro(gnss_synchro); acquisition->init(); + acquisition->set_local_code(); acquisition->reset(); stop = false; try diff --git a/src/utils/matlab/libs/read_complex_binary.m b/src/utils/matlab/libs/read_complex_binary.m new file mode 100644 index 000000000..a201b99bb --- /dev/null +++ b/src/utils/matlab/libs/read_complex_binary.m @@ -0,0 +1,57 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio 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, or (at your option) +% any later version. +% +% GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 51 Franklin Street, +% Boston, MA 02110-1301, USA. +% + +function v = read_complex_binary (filename, count, start_sample) + + %% usage: read_complex_binary (filename, [count], [start_sample]) + %% + %% open filename and return the contents as a column vector, + %% treating them as 32 bit complex numbers + %% + + m = nargchk (1,2,nargin); + if (m) + %usage (m); + end + + if (nargin < 2) + count = Inf; + start_sample=0; + end + + if (nargin < 3) + start_sample=0; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + if (start_sample>0) + bytes_per_sample=4; + fseek(f,start_sample*bytes_per_sample,'bof'); + end + t = fread (f, [2, count], 'float'); + fclose (f); + v = t(1,:) + t(2,:)*i; + [r, c] = size (v); + v = reshape (v, c, r); + end diff --git a/src/utils/matlab/libs/read_complex_char_binary.m b/src/utils/matlab/libs/read_complex_char_binary.m new file mode 100644 index 000000000..cafaedcc7 --- /dev/null +++ b/src/utils/matlab/libs/read_complex_char_binary.m @@ -0,0 +1,48 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio 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, or (at your option) +% any later version. +% +% GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 51 Franklin Street, +% Boston, MA 02110-1301, USA. +% + +function v = read_complex_char_binary (filename, count) + + %% usage: read_complex_binary (filename, [count]) + %% + %% open filename and return the contents as a column vector, + %% treating them as 32 bit complex numbers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + t = fread (f, [2, count], 'int8'); + fclose (f); + v = t(1,:) + t(2,:)*i; + [r, c] = size (v); + v = reshape (v, c, r); + end diff --git a/src/utils/matlab/libs/read_complex_short_binary.m b/src/utils/matlab/libs/read_complex_short_binary.m new file mode 100644 index 000000000..55118528b --- /dev/null +++ b/src/utils/matlab/libs/read_complex_short_binary.m @@ -0,0 +1,48 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio 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, or (at your option) +% any later version. +% +% GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 51 Franklin Street, +% Boston, MA 02110-1301, USA. +% + +function v = read_complex_short_binary (filename, count) + + %% usage: read_complex_binary (filename, [count]) + %% + %% open filename and return the contents as a column vector, + %% treating them as 32 bit complex numbers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + t = fread (f, [2, count], 'short'); + fclose (f); + v = t(1,:) + t(2,:)*i; + [r, c] = size (v); + v = reshape (v, c, r); + end