Merge remote-tracking branch 'upstream/common_solver' into next

This commit Integrates RTKLIB positioning libraries in a universal PVT
block implementation called RTKLIB_PVT. This results in an improved
positioning accuracy and precision with a wide range of options
(including Precise Point Positioning and ionospheric/troposphreic
models).

Not all the RTKLIB features have been ported. Some of them will be
progressively added. The ported options and how to configure them have
been documented in the website, see
http://gnss-sdr.org/docs/sp-blocks/pvt/

This commit also introduces a multi-band, multi system Observables block
implementation.

Relevant architectural changes that reduce latency and makes
multi-system, multi band signal handling easier.

Redundant blocks have been deleted. Old configurations are automatically
redirected to the new blocks for Observables and PVT, so the commit does
not break any existing configuration. The user should just notice a
relevant improvement in positioning performance.

# Conflicts:
#	src/core/receiver/gnss_flowgraph.cc
This commit is contained in:
Carles Fernandez 2017-05-10 22:16:18 +02:00
commit 0253f4ba05
195 changed files with 21368 additions and 10270 deletions

View File

@ -253,8 +253,8 @@ TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -264,14 +264,13 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm:
PVT.implementation=GPS_L1_CA_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=100
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.AR_GPS=PPP-AR ; options: OFF, Continuous, Instantaneous, Fix-and-Hold, PPP-AR
;#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=10
@ -279,6 +278,8 @@ PVT.output_rate_ms=10
;#display_rate_ms: Position console print (std::out) interval [ms]. Notice that output_rate_ms <= display_rate_ms.
PVT.display_rate_ms=500
PVT.positioning_mode=PPP_Static
;# KML, GeoJSON, NMEA and RTCM output configuration
;#dump_filename: Log path and filename without extension. Notice that PVT will add ".dat" to the binary dump, ".kml" and ".geojson" to GIS-friendly formats.
@ -304,5 +305,3 @@ PVT.rtcm_dump_devname=/dev/pts/1
;#dump: Enable or disable the PVT internal binary data file logging [true] or [false]
PVT.dump=false

View File

@ -89,17 +89,17 @@ Tracking_1C.order=3;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=false.
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GPS_L1_CA_PVT
PVT.averaging_depth=100
PVT.flag_averaging=false
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=10
PVT.display_rate_ms=500
PVT.dump_filename=./PVT
@ -110,4 +110,3 @@ PVT.dump=false
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1

View File

@ -266,8 +266,8 @@ TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -278,13 +278,10 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=100
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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=500

View File

@ -291,8 +291,8 @@ TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -302,14 +302,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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

View File

@ -332,8 +332,8 @@ TelemetryDecoder_GPS.dump=false
TelemetryDecoder_GPS.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -343,14 +343,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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

View File

@ -255,8 +255,8 @@ TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -267,13 +267,11 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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;

View File

@ -6,16 +6,16 @@
;######### GLOBAL OPTIONS ##################
;internal_fs_hz: Internal signal sampling frequency after the signal conditioning stage [Hz].
GNSS-SDR.internal_fs_hz=4000000
GNSS-SDR.internal_fs_hz=2600000
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=/datalogger/signals/Agilent/New York/4msps.dat ; <- PUT YOUR FILE HERE
SignalSource.item_type=gr_complex
SignalSource.sampling_frequency=4000000
SignalSource.filename=/home/javier/gnss/gnss-simulator/build/signal_out.bin ; <- PUT YOUR FILE HERE
SignalSource.item_type=byte
SignalSource.sampling_frequency=2600000
SignalSource.freq=1575420000
SignalSource.samples=250000000
SignalSource.samples=0
SignalSource.repeat=false
SignalSource.dump=false
SignalSource.dump_filename=../data/signal_source.dat
@ -23,8 +23,15 @@ SignalSource.enable_throttle_control=false
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Pass_Through
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
DataTypeAdapter.dump=false
;#dump_filename: Log path and filename.
DataTypeAdapter.dump_filename=../data/DataTypeAdapter.dat
;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=8
@ -39,38 +46,38 @@ Acquisition_1C.item_type=gr_complex
Acquisition_1C.if=0
Acquisition_1C.sampled_ms=1
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.threshold=0.005
Acquisition_1C.threshold=0.05
;Acquisition_1C.pfa=0.01
Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=500
Acquisition_1C.doppler_step=250
;######### TRACKING GLOBAL CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_C_Aid_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.if=0
Tracking_1C.dump=false
Tracking_1C.dump_filename=../data/epl_tracking_ch_
Tracking_1C.pll_bw_hz=45.0;
Tracking_1C.dll_bw_hz=2.0;
Tracking_1C.pll_bw_hz=25.0;
Tracking_1C.dll_bw_hz=1.0;
Tracking_1C.order=3;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GPS_L1_CA_PVT
PVT.averaging_depth=100
PVT.flag_averaging=false
PVT.output_rate_ms=10
PVT.display_rate_ms=500
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=1
PVT.display_rate_ms=100
PVT.dump_filename=./PVT
PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea;
PVT.flag_nmea_tty_port=false;
@ -79,4 +86,3 @@ PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=false

View File

@ -57,18 +57,18 @@ Tracking_1C.order=3;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GPS_L1_CA_PVT
PVT.averaging_depth=100
PVT.flag_averaging=false
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=10
PVT.display_rate_ms=500
PVT.dump_filename=./PVT
@ -79,4 +79,3 @@ PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=false

View File

@ -79,16 +79,17 @@ TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GPS_L1_CA_PVT
PVT.averaging_depth=100
PVT.flag_averaging=false
PVT.output_rate_ms=10
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.dump_filename=./PVT
PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea;

View File

@ -28,7 +28,7 @@ GNSS-SDR.SUPL_CI=0x31b0
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=Nsr_File_Signal_Source
SignalSource.filename=/datalogger/signals/ifen/E1L1_FE0_Band0.stream ; <- PUT YOUR FILE HERE
SignalSource.filename=/home/javier/Descargas/RoofTop_FE0_Band1.stream ; <- PUT YOUR FILE HERE
SignalSource.item_type=byte
SignalSource.sampling_frequency=20480000
SignalSource.freq=1575420000
@ -68,7 +68,8 @@ InputFilter.band2_error=1.0
InputFilter.filter_type=bandpass
InputFilter.grid_density=16
InputFilter.sampling_frequency=20480000
InputFilter.IF=5499998.47412109
#InputFilter.IF=5499998.47412109
InputFilter.IF=5679999.2370605494
InputFilter.decimation_factor=8
@ -81,9 +82,10 @@ Resampler.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
;#count: Number of available GPS satellite channels.
Channels_1C.count=8
Channels_1C.count=0
Channels_2S.count=8
Channels.in_acquisition=1
Channel.signal=1C
#Channel.signal=1C
;######### GPS ACQUISITION CONFIG ############
@ -98,6 +100,18 @@ Acquisition_1C.threshold=0.0075
Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=500
Acquisition_2S.dump=false
Acquisition_2S.dump_filename=./acq_dump.dat
Acquisition_2S.item_type=gr_complex
Acquisition_2S.if=0
Acquisition_2S.coherent_integration_time_ms=20
Acquisition_2S.implementation=GPS_L2_M_PCPS_Acquisition
Acquisition_2S.threshold=0.00045
Acquisition_2S.doppler_max=5000
Acquisition_2S.doppler_step=100
Acquisition_2S.bit_transition_flag=false
Acquisition_2S.max_dwells=1
;######### TRACKING GPS CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
@ -109,22 +123,43 @@ Tracking_1C.pll_bw_hz=45.0;
Tracking_1C.dll_bw_hz=2.0;
Tracking_1C.order=3;
;######### GPS L2C GENERIC TRACKING CONFIG ############
Tracking_2S.implementation=GPS_L2_M_DLL_PLL_Tracking
Tracking_2S.item_type=gr_complex
Tracking_2S.if=0
Tracking_2S.dump=true
Tracking_2S.dump_filename=../data/epl_tracking_ch_
Tracking_2S.pll_bw_hz=1.5;
Tracking_2S.dll_bw_hz=0.4;
Tracking_2S.order=2;
Tracking_2S.early_late_space_chips=0.5;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
TelemetryDecoder_2S.implementation=GPS_L2C_Telemetry_Decoder
TelemetryDecoder_2S.dump=false
TelemetryDecoder_2S.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
;#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 ############
PVT.implementation=GPS_L1_CA_PVT
PVT.averaging_depth=100
PVT.flag_averaging=false
PVT.output_rate_ms=10
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.dump_filename=./PVT
PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea;
@ -134,4 +169,3 @@ PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=true

View File

@ -127,18 +127,17 @@ Tracking_1C.order=3;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GPS_L1_CA_PVT
PVT.averaging_depth=100
PVT.flag_averaging=false
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=10
PVT.display_rate_ms=500
PVT.dump_filename=./PVT
@ -149,4 +148,3 @@ PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=true

View File

@ -30,20 +30,20 @@ SignalSource.implementation=File_Signal_Source
;#When left empty, the device discovery routines will search all vailable transports on the system (ethernet, usb...)
SignalSource.device_address=192.168.50.2
;#filename: path to file with the captured GNSS signal samples to be processed
SignalSource.filename=/home/javier/signals/signal_source_int.dat
;#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]
;#sampling_frequency: Original Signal sampling frequency in [Hz]
SignalSource.sampling_frequency=2000000
;#freq: RF front-end center frequency in [Hz]
;#freq: RF front-end center frequency in [Hz]
SignalSource.freq=1575420000
;#gain: Front-end Gain in [dB]
;#gain: Front-end Gain in [dB]
SignalSource.gain=40
;#subdevice: UHD subdevice specification (for USRP1 use A:0 or B:0)
@ -62,12 +62,12 @@ SignalSource.dump_filename=dump.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.
; 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.
;## 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
@ -157,19 +157,18 @@ Tracking_1C.order=3;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
Observables.averaging_depth=1
Observables.implementation=Hybrid_Observables
Observables.dump=true
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GPS_L1_CA_PVT
PVT.averaging_depth=100
PVT.flag_averaging=false
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=1
PVT.display_rate_ms=100
PVT.dump_filename=./PVT
@ -180,4 +179,3 @@ PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=false

View File

@ -243,8 +243,8 @@ TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -254,14 +254,11 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
;#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

View File

@ -120,20 +120,17 @@ TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
;#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
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.dump_filename=./PVT

View File

@ -113,15 +113,16 @@ TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GPS_L1_CA_PVT
PVT.averaging_depth=100
PVT.flag_averaging=false
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=10
PVT.display_rate_ms=500
PVT.dump_filename=./PVT

View File

@ -180,18 +180,17 @@ Tracking_2S.early_late_space_chips=0.5;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_2S.implementation=GPS_L2C_Telemetry_Decoder
TelemetryDecoder_2S.dump=false
TelemetryDecoder_2S.decimation_factor=1;
;######### OBSERVABLES CONFIG ############.
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=Hybrid_PVT
PVT.averaging_depth=10
PVT.flag_averaging=true
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.dump_filename=./PVT

View File

@ -136,18 +136,17 @@ Tracking_2S.early_late_space_chips=0.5;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_2S.implementation=GPS_L2C_Telemetry_Decoder
TelemetryDecoder_2S.dump=true
TelemetryDecoder_2S.decimation_factor=1;
;######### OBSERVABLES CONFIG ############.
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=Hybrid_PVT
PVT.averaging_depth=10
PVT.flag_averaging=true
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.dump_filename=./PVT

View File

@ -62,14 +62,15 @@ TelemetryDecoder_1B.implementation=Galileo_E1B_Telemetry_Decoder
TelemetryDecoder_1B.dump=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=Galileo_E1B_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GALILEO_E1_PVT
PVT.averaging_depth=100
PVT.flag_averaging=false
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100;
PVT.display_rate_ms=500;
PVT.dump=false

View File

@ -237,7 +237,7 @@ TelemetryDecoder_1B.dump=false
;######### OBSERVABLES CONFIG ############
;#implementation:
Observables.implementation=Galileo_E1B_Observables
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -248,13 +248,10 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm:
PVT.implementation=GALILEO_E1_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=100
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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;

View File

@ -239,8 +239,8 @@ TelemetryDecoder_1B.implementation=Galileo_E1B_Telemetry_Decoder
TelemetryDecoder_1B.dump=false
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=Galileo_E1B_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -250,14 +250,11 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GALILEO_E1_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=100
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=false
;#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;

View File

@ -106,15 +106,16 @@ TelemetryDecoder_1B.implementation=Galileo_E1B_Telemetry_Decoder
TelemetryDecoder_1B.dump=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=Galileo_E1B_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=true
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GALILEO_E1_PVT
PVT.averaging_depth=1
PVT.flag_averaging=false
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.dump=true

View File

@ -286,8 +286,7 @@ TelemetryDecoder_5X.dump=false
;######### OBSERVABLES CONFIG ############
;#implementation:
;Use [Galileo_E1B_Observables] for E5a also.
Observables.implementation=Galileo_E1B_Observables
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -298,14 +297,11 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm:
;Use [GALILEO_E1_PVT] for E5a also.
PVT.implementation=GALILEO_E1_PVT
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=100
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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 [ms]
PVT.output_rate_ms=100

View File

@ -134,15 +134,16 @@ TelemetryDecoder_5X.implementation=Galileo_E5a_Telemetry_Decoder
TelemetryDecoder_5X.dump=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=Galileo_E1B_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GALILEO_E1_PVT
PVT.averaging_depth=100
PVT.flag_averaging=true
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=OFF ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=OFF ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
PVT.dump=false
PVT.dump_filename=./PVT
@ -152,4 +153,3 @@ PVT.nmea_dump_devname=/dev/pts/4
PVT.flag_rtcm_server=true
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1

View File

@ -295,10 +295,9 @@ TelemetryDecoder_1C.decimation_factor=4;
;#implementation: Use [Galileo_E1B_Telemetry_Decoder] for Galileo E1B
TelemetryDecoder_1B.implementation=Galileo_E1B_Telemetry_Decoder
TelemetryDecoder_1B.dump=false
TelemetryDecoder_1B.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
@ -309,14 +308,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=Hybrid_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=false
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;

View File

@ -7,7 +7,8 @@
;######### GLOBAL OPTIONS ##################
;internal_fs_hz: Internal signal sampling frequency after the signal conditioning stage [Hz].
GNSS-SDR.internal_fs_hz=4000000
;#GNSS-SDR.internal_fs_hz=2048000
GNSS-SDR.internal_fs_hz=2600000
;######### SIGNAL_SOURCE CONFIG ############
@ -15,7 +16,8 @@ GNSS-SDR.internal_fs_hz=4000000
SignalSource.implementation=File_Signal_Source
;#filename: path to file with the captured GNSS signal samples to be processed
SignalSource.filename=/datalogger/signals/gnss-sim/signal_out.bin ; <- PUT YOUR FILE HERE
;#SignalSource.filename=/home/javier/Descargas/rtlsdr_tcxo_l1/rtlsdr_tcxo_l1.bin ; <- PUT YOUR FILE HERE
SignalSource.filename=/Users/carlesfernandez/git/cttc/build/signal_out.bin ; <- 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=byte
@ -53,7 +55,7 @@ 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_Cshort
DataTypeAdapter.implementation=Ibyte_To_Complex
DataTypeAdapter.dump=false
;#dump_filename: Log path and filename.
DataTypeAdapter.dump_filename=../data/DataTypeAdapter.dat
@ -81,10 +83,10 @@ InputFilter.dump_filename=../data/input_filter.dat
;#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=cshort
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=cshort
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
@ -127,7 +129,7 @@ InputFilter.grid_density=16
;#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.sampling_frequency=4000000
InputFilter.sampling_frequency=2600000
InputFilter.IF=0
@ -135,30 +137,12 @@ InputFilter.IF=0
;######### 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
;#dump: Dump the resamplered data to a file.
Resampler.dump=false
;#dump_filename: Log path and filename.
Resampler.dump_filename=../data/resampler.dat
;#item_type: Type and resolution for each of the signal samples.
Resampler.item_type=cshort
;#sample_freq_in: the sample frequency of the input signal
Resampler.sample_freq_in=4000000
;#sample_freq_out: the desired sample frequency of the output signal
Resampler.sample_freq_out=4000000
Resampler.item_type = gr_complex;
;######### CHANNELS GLOBAL CONFIG ############
;#count: Number of available GPS satellite channels.
Channels_1C.count=12
Channels_1C.count=11
;#count: Number of available Galileo satellite channels.
Channels_1B.count=0
;#in_acquisition: Number of channels simultaneously acquiring for the whole receiver
@ -167,7 +151,7 @@ Channels.in_acquisition=1
;#IMPORTANT: When cshort is used as input type for Acq and Trk, please set the Channel type to cshort here
;#item_type: Type and resolution for each of the signal samples.
Channel.item_type=cshort
Channel.item_type=gr_complex
;#signal:
;#if the option is disabled by default is assigned "1C" GPS L1 C/A
Channel1.signal=1C
@ -194,7 +178,7 @@ 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=cshort
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]
@ -205,7 +189,7 @@ Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
;#notice that this affects the Acquisition threshold range!
Acquisition_1C.use_CFAR_algorithm=false;
;#threshold: Acquisition threshold
Acquisition_1C.threshold=11
Acquisition_1C.threshold=15
;#pfa: Acquisition false alarm probability. This option overrides the threshold option. Only use with implementations: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition]
;Acquisition_1C.pfa=0.01
;#doppler_max: Maximum expected Doppler shift [Hz]
@ -221,7 +205,7 @@ Acquisition_1B.dump=false
;#filename: Log path and filename
Acquisition_1B.dump_filename=./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=cshort
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]
@ -240,9 +224,9 @@ Acquisition_1B.doppler_step=125
;######### 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_C_Aid_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=cshort
Tracking_1C.item_type=gr_complex
;#sampling_frequency: Signal Intermediate Frequency in [Hz]
Tracking_1C.if=0
@ -254,7 +238,7 @@ Tracking_1C.dump=false
Tracking_1C.dump_filename=../data/epl_tracking_ch_
;#pll_bw_hz: PLL loop filter bandwidth [Hz]
Tracking_1C.pll_bw_hz=15.0;
Tracking_1C.pll_bw_hz=20.0;
;#dll_bw_hz: DLL loop filter bandwidth [Hz]
Tracking_1C.dll_bw_hz=1.5;
@ -267,7 +251,7 @@ Tracking_1C.order=3;
;#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=cshort
Tracking_1B.item_type=gr_complex
;#sampling_frequency: Signal Intermediate Frequency in [Hz]
Tracking_1B.if=0
@ -308,8 +292,8 @@ TelemetryDecoder_1B.dump=false
TelemetryDecoder_1B.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -320,13 +304,11 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=false
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;

View File

@ -304,10 +304,9 @@ TelemetryDecoder_1C.decimation_factor=4;
;#implementation: Use [Galileo_E1B_Telemetry_Decoder] for Galileo E1B
TelemetryDecoder_1B.implementation=Galileo_E1B_Telemetry_Decoder
TelemetryDecoder_1B.dump=false
TelemetryDecoder_1B_factor=4;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
@ -318,14 +317,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=Hybrid_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=false
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=10;

View File

@ -311,7 +311,7 @@ TelemetryDecoder_1B.dump=false
TelemetryDecoder_1B.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
@ -322,14 +322,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=Hybrid_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=false
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;

View File

@ -17,7 +17,7 @@ GNSS-SDR.internal_fs_hz=2560000
SignalSource.implementation=Nsr_File_Signal_Source
;#filename: path to file with the captured GNSS signal samples to be processed
SignalSource.filename=/datalogger/signals/ifen/E1L1_FE0_Band0.stream ; <- PUT YOUR FILE HERE
SignalSource.filename=/media/javier/SISTEMA/signals/ifen/E1L1_FE0_Band0.stream ; <- 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=byte
@ -304,7 +304,7 @@ TelemetryDecoder_1B.dump=false
TelemetryDecoder_1B_factor=4;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
@ -315,14 +315,13 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=Hybrid_PVT
;#implementation: Position Velocity and Time (PVT) implementation algorithm.
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
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
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=false
;#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=10;

View File

@ -289,12 +289,10 @@ Tracking_1C.early_late_space_chips=0.5;
;#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=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -304,14 +302,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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

View File

@ -300,8 +300,8 @@ TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -311,14 +311,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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

View File

@ -294,12 +294,10 @@ Tracking_1C.early_late_space_chips=0.5;
;#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=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -309,14 +307,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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

View File

@ -299,8 +299,8 @@ TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -310,14 +310,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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

View File

@ -294,8 +294,8 @@ TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -306,13 +306,11 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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

View File

@ -444,7 +444,7 @@ TelemetryDecoder_2S.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.Mixed_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
@ -455,8 +455,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=Hybrid_PVT
;#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
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10

View File

@ -452,7 +452,7 @@ TelemetryDecoder_1B.decimation_factor=5;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
@ -464,13 +464,11 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=Hybrid_PVT
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=false
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

View File

@ -364,12 +364,10 @@ Tracking_1C.early_late_space_chips=0.5;
;#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=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
Observables.implementation=GPS_L1_CA_Observables
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=false
@ -379,14 +377,12 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=GPS_L1_CA_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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

View File

@ -29,7 +29,7 @@ GNSS-SDR.SUPL_CI=0x31b0
SignalSource.implementation=Flexiband_Signal_Source
SignalSource.flag_read_file=true
SignalSource.signal_file=/datalogger/signals/Fraunhofer/L125_III1b_210s.usb ; <- PUT YOUR FILE HERE
SignalSource.signal_file=/media/javier/SISTEMA/signals/fraunhofer/L125_III1b_210s.usb ; <- 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
@ -74,7 +74,7 @@ DataTypeAdapter0.item_type=gr_complex
InputFilter0.implementation=Freq_Xlating_Fir_Filter
;#dump: Dump the filtered data to a file.
InputFilter0.dump=false
InputFilter0.dump=true
;#dump_filename: Log path and filename.
InputFilter0.dump_filename=../data/input_filter_ch0.dat
@ -267,8 +267,8 @@ Resampler2.implementation=Pass_Through
;######### CHANNELS GLOBAL CONFIG ############
;#count: Number of available GPS satellite channels.
Channels_1C.count=1
Channels_2S.count=8
Channels_1C.count=11
Channels_2S.count=0
;#GPS.prns=7,8
@ -284,14 +284,25 @@ Channels.in_acquisition=1
;# CHANNEL CONNECTION
Channel0.RF_channel_ID=0
Channel1.RF_channel_ID=1
Channel2.RF_channel_ID=1
Channel3.RF_channel_ID=1
Channel4.RF_channel_ID=1
Channel5.RF_channel_ID=1
Channel6.RF_channel_ID=1
Channel7.RF_channel_ID=1
Channel8.RF_channel_ID=1
Channel1.RF_channel_ID=0
Channel2.RF_channel_ID=0
Channel3.RF_channel_ID=0
Channel4.RF_channel_ID=0
Channel5.RF_channel_ID=0
Channel6.RF_channel_ID=0
Channel7.RF_channel_ID=0
Channel8.RF_channel_ID=0
Channel9.RF_channel_ID=0
Channel10.RF_channel_ID=1
Channel11.RF_channel_ID=1
Channel12.RF_channel_ID=1
Channel13.RF_channel_ID=1
Channel14.RF_channel_ID=1
Channel15.RF_channel_ID=1
Channel16.RF_channel_ID=1
Channel17.RF_channel_ID=1
Channel18.RF_channel_ID=1
Channel19.RF_channel_ID=1
;######### ACQUISITION GENERIC CONFIG ######
@ -309,32 +320,19 @@ Acquisition_1C.doppler_step=250
Acquisition_1C.bit_transition_flag=false
Acquisition_1C.max_dwells=1
;# GPS L2C M
Acquisition_2S.dump=false
Acquisition_2S.dump_filename=./acq_dump.dat
Acquisition_2S.item_type=gr_complex
Acquisition_2S.if=0
Acquisition_2S.coherent_integration_time_ms=1
Acquisition_2S.implementation=GPS_L2_M_PCPS_Acquisition
Acquisition_2S.threshold=0.0005
Acquisition_2S.threshold=0.00074
;Acquisition_2S.pfa=0.001
Acquisition_2S.doppler_max=5000
Acquisition_2S.doppler_step=100
Acquisition_2S.bit_transition_flag=false
Acquisition_2S.doppler_min=-5000
Acquisition_2S.doppler_step=60
Acquisition_2S.max_dwells=1
;# channel specific config
Acquisition_2S1.dump=false
Acquisition_2S1.dump_filename=./acq_dump.dat
Acquisition_2S1.item_type=gr_complex
Acquisition_2S1.if=0
Acquisition_2S1.coherent_integration_time_ms=1
Acquisition_2S1.implementation=GPS_L2_M_PCPS_Acquisition
Acquisition_2S1.threshold=0.0005
Acquisition_2S1.doppler_max=5000
Acquisition_2S1.doppler_step=100
Acquisition_2S1.bit_transition_flag=false
Acquisition_2S1.max_dwells=1
;######### TRACKING CONFIG ############
@ -342,7 +340,7 @@ Acquisition_2S1.max_dwells=1
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.if=0
Tracking_1C.dump=true
Tracking_1C.dump=false
Tracking_1C.dump_filename=../data/epl_tracking_ch_
Tracking_1C.pll_bw_hz=40.0;
Tracking_1C.dll_bw_hz=3.0;
@ -354,29 +352,18 @@ Tracking_1C.early_late_space_chips=0.5;
Tracking_2S.implementation=GPS_L2_M_DLL_PLL_Tracking
Tracking_2S.item_type=gr_complex
Tracking_2S.if=0
Tracking_2S.dump=true
Tracking_2S.dump_filename=../data/epl_tracking_ch_
Tracking_2S.dump=false
Tracking_2S.dump_filename=./tracking_ch_
Tracking_2S.pll_bw_hz=2.0;
Tracking_2S.dll_bw_hz=0.5;
Tracking_2S.dll_bw_hz=0.25;
Tracking_2S.order=2;
Tracking_2S.early_late_space_chips=0.5;
;######### GPS L2C SPECIFIC CHANNEL TRACKING CONFIG ############
Tracking_2S1.implementation=GPS_L2_M_DLL_PLL_Tracking
Tracking_2S1.item_type=gr_complex
Tracking_2S1.if=0
Tracking_2S1.dump=true
Tracking_2S1.dump_filename=../data/epl_tracking_ch_
Tracking_2S1.pll_bw_hz=2.0;
Tracking_2S1.dll_bw_hz=0.5;
Tracking_2S1.order=2;
Tracking_2S1.early_late_space_chips=0.5;
;######### TELEMETRY DECODER CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=20;
TelemetryDecoder_1C.decimation_factor=1;
TelemetryDecoder_2S.implementation=GPS_L2C_Telemetry_Decoder
TelemetryDecoder_2S.dump=false
@ -384,31 +371,27 @@ TelemetryDecoder_2S.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
;#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 algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=Hybrid_PVT
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=true
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
PVT.display_rate_ms=100
;# KML, GeoJSON, NMEA and RTCM output configuration

View File

@ -0,0 +1,411 @@
; 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=5000000
;######### SUPL RRLP GPS assistance configuration #####
; Check http://www.mcc-mnc.com/
; On Android: https://play.google.com/store/apps/details?id=net.its_here.cellidinfo&hl=en
GNSS-SDR.SUPL_gps_enabled=false
GNSS-SDR.SUPL_read_gps_assistance_xml=true
GNSS-SDR.SUPL_gps_ephemeris_server=supl.google.com
GNSS-SDR.SUPL_gps_ephemeris_port=7275
GNSS-SDR.SUPL_gps_acquisition_server=supl.google.com
GNSS-SDR.SUPL_gps_acquisition_port=7275
GNSS-SDR.SUPL_MCC=244
GNSS-SDR.SUPL_MNS=5
GNSS-SDR.SUPL_LAC=0x59e2
GNSS-SDR.SUPL_CI=0x31b0
;######### SIGNAL_SOURCE CONFIG ############
;#implementation: Use [File_Signal_Source] or [UHD_Signal_Source] or [GN3S_Signal_Source] (experimental)
SignalSource.implementation=Flexiband_Signal_Source
SignalSource.flag_read_file=true
SignalSource.signal_file=/home/javier/signals/20140923_20-24-17_L125_roof_210s.usb ; <- 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
;# FPGA firmware file
SignalSource.firmware_file=flexiband_III-1b.bit
;#RF_channels: Number of RF channels present in the frontend device, must agree the FPGA firmware file
SignalSource.RF_channels=2
;#frontend channels gain. Not usable yet!
SignalSource.gain1=0
SignalSource.gain2=0
SignalSource.gain3=0
;#frontend channels AGC
SignalSource.AGC=true
;# USB 3.0 packet buffer size (number of SuperSpeed packets)
SignalSource.usb_packet_buffer=128
;######################################################
;######### RF CHANNEL 0 SIGNAL CONDITIONER ############
;######################################################
;######### SIGNAL_CONDITIONER 0 CONFIG ############
;## It holds blocks to change data type, filter and resample input data.
SignalConditioner0.implementation=Signal_Conditioner
;######### DATA_TYPE_ADAPTER 0 CONFIG ############
DataTypeAdapter0.implementation=Pass_Through
DataTypeAdapter0.item_type=gr_complex
;######### INPUT_FILTER 0 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]
;#[Pass_Through] disables this block
;#[Fir_Filter] enables a FIR Filter
;#[Freq_Xlating_Fir_Filter] enables FIR filter and a composite frequency translation that shifts IF down to zero Hz.
InputFilter0.implementation=Freq_Xlating_Fir_Filter
;#dump: Dump the filtered data to a file.
InputFilter0.dump=false
;#dump_filename: Log path and filename.
InputFilter0.dump_filename=../data/input_filter_ch0.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.
InputFilter0.input_item_type=gr_complex
;#outut_item_type: Type and resolution for output filtered signal samples. Use only gr_complex in this version.
InputFilter0.output_item_type=gr_complex
;#taps_item_type: Type and resolution for the taps of the filter. Use only float in this version.
InputFilter0.taps_item_type=float
;#number_of_taps: Number of taps in the filter. Increasing this parameter increases the processing time
InputFilter0.number_of_taps=5
;#number_of _bands: Number of frequency bands in the filter.
InputFilter0.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
InputFilter0.band1_begin=0.0
InputFilter0.band1_end=0.45
InputFilter0.band2_begin=0.55
InputFilter0.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
InputFilter0.ampl1_begin=1.0
InputFilter0.ampl1_end=1.0
InputFilter0.ampl2_begin=0.0
InputFilter0.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
InputFilter0.band1_error=1.0
InputFilter0.band2_error=1.0
;#filter_type: one of "bandpass", "hilbert" or "differentiator"
InputFilter0.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.
InputFilter0.grid_density=16
;#The following options are used only in Freq_Xlating_Fir_Filter implementation.
;#InputFilter0.IF is the intermediate frequency (in Hz) shifted down to zero Hz
;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/
InputFilter0.sampling_frequency=20000000
;# IF deviation due to front-end LO inaccuracies [HZ]
InputFilter0.IF=0
;# Decimation factor after the frequency tranaslating block
InputFilter0.decimation_factor=4
;######### RESAMPLER CONFIG 0 ############
;## Resamples the input data.
Resampler0.implementation=Pass_Through
;######################################################
;######### RF CHANNEL 1 SIGNAL CONDITIONER ############
;######################################################
;######### SIGNAL_CONDITIONER 1 CONFIG ############
;## It holds blocks to change data type, filter and resample input data.
SignalConditioner1.implementation=Signal_Conditioner
;######### DATA_TYPE_ADAPTER 1 CONFIG ############
DataTypeAdapter1.implementation=Pass_Through
DataTypeAdapter1.item_type=gr_complex
;######### INPUT_FILTER 0 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]
;#[Pass_Through] disables this block
;#[Fir_Filter] enables a FIR Filter
;#[Freq_Xlating_Fir_Filter] enables FIR filter and a composite frequency translation that shifts IF down to zero Hz.
InputFilter1.implementation=Freq_Xlating_Fir_Filter
;#dump: Dump the filtered data to a file.
InputFilter1.dump=false
;#dump_filename: Log path and filename.
InputFilter1.dump_filename=../data/input_filter_ch1.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.
InputFilter1.input_item_type=gr_complex
;#outut_item_type: Type and resolution for output filtered signal samples. Use only gr_complex in this version.
InputFilter1.output_item_type=gr_complex
;#taps_item_type: Type and resolution for the taps of the filter. Use only float in this version.
InputFilter1.taps_item_type=float
;#number_of_taps: Number of taps in the filter. Increasing this parameter increases the processing time
InputFilter1.number_of_taps=5
;#number_of _bands: Number of frequency bands in the filter.
InputFilter1.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
InputFilter1.band1_begin=0.0
InputFilter1.band1_end=0.45
InputFilter1.band2_begin=0.55
InputFilter1.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
InputFilter1.ampl1_begin=1.0
InputFilter1.ampl1_end=1.0
InputFilter1.ampl2_begin=0.0
InputFilter1.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
InputFilter1.band1_error=1.0
InputFilter1.band2_error=1.0
;#filter_type: one of "bandpass", "hilbert" or "differentiator"
InputFilter1.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.
InputFilter1.grid_density=16
;#The following options are used only in Freq_Xlating_Fir_Filter implementation.
;#InputFilter0.IF is the intermediate frequency (in Hz) shifted down to zero Hz
;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/
InputFilter1.sampling_frequency=20000000
;# IF deviation due to front-end LO inaccuracies [HZ]
InputFilter1.IF=0
;# Decimation factor after the frequency tranaslating block
InputFilter1.decimation_factor=4
;######### RESAMPLER CONFIG 1 ############
;## Resamples the input data.
Resampler1.implementation=Pass_Through
;######### SIGNAL_CONDITIONER 2 CONFIG ############
;## It holds blocks to change data type, filter and resample input data.
SignalConditioner2.implementation=Pass_Through
;######### DATA_TYPE_ADAPTER 2 CONFIG ############
DataTypeAdapter2.implementation=Pass_Through
DataTypeAdapter2.item_type=gr_complex
;######### INPUT_FILTER 2 CONFIG ############
InputFilter2.implementation=Pass_Through
;#dump: Dump the filtered data to a file.
InputFilter2.dump=false
;#dump_filename: Log path and filename.
InputFilter2.dump_filename=../data/input_filter.dat
;#input_item_type: Type and resolution for input signal samples. Use only gr_complex in this version.
InputFilter2.input_item_type=gr_complex
;#outut_item_type: Type and resolution for output filtered signal samples. Use only gr_complex in this version.
InputFilter2.output_item_type=gr_complex
;######### RESAMPLER CONFIG 2 ############
;## Resamples the input data.
Resampler2.implementation=Pass_Through
;######### CHANNELS GLOBAL CONFIG ############
;#count: Number of available GPS satellite channels.
Channels_1C.count=10
Channels_2S.count=4
;#GPS.prns=7,8
;#in_acquisition: Number of channels simultaneously acquiring for the whole receiver
Channels.in_acquisition=1
;# signal:
;# "1C" GPS L1 C/A
;# "2S" GPS L2 L2C (M)
;# "1B" GALILEO E1 B (I/NAV OS/CS/SoL)
;# "5X" GALILEO E5a I+Q
;# CHANNEL NUMBERING ORDER: GPS L1 C/A, GPS L2 L2C (M), GALILEO E1 B, GALILEO E5a
;# CHANNEL CONNECTION
Channel0.RF_channel_ID=0
Channel1.RF_channel_ID=0
Channel2.RF_channel_ID=0
Channel3.RF_channel_ID=0
Channel4.RF_channel_ID=0
Channel5.RF_channel_ID=0
Channel6.RF_channel_ID=0
Channel7.RF_channel_ID=0
Channel8.RF_channel_ID=0
Channel9.RF_channel_ID=0
Channel10.RF_channel_ID=1
Channel11.RF_channel_ID=1
Channel12.RF_channel_ID=1
Channel13.RF_channel_ID=1
Channel14.RF_channel_ID=1
Channel15.RF_channel_ID=1
Channel16.RF_channel_ID=1
Channel17.RF_channel_ID=1
Channel18.RF_channel_ID=1
Channel19.RF_channel_ID=1
;######### ACQUISITION GENERIC CONFIG ######
;#The following options are specific to each channel and overwrite the generic options
Acquisition_1C.dump=false
Acquisition_1C.dump_filename=./acq_dump.dat
Acquisition_1C.item_type=gr_complex
Acquisition_1C.if=0
Acquisition_1C.coherent_integration_time_ms=1
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.threshold=0.005
Acquisition_1C.doppler_max=5000
Acquisition_1C.doppler_step=250
Acquisition_1C.bit_transition_flag=false
Acquisition_1C.max_dwells=1
;# GPS L2C M
Acquisition_2S.dump=false
Acquisition_2S.dump_filename=./acq_dump.dat
Acquisition_2S.item_type=gr_complex
Acquisition_2S.if=0
Acquisition_2S.implementation=GPS_L2_M_PCPS_Acquisition
Acquisition_2S.threshold=0.00074
;Acquisition_2S.pfa=0.001
Acquisition_2S.doppler_max=5000
Acquisition_2S.doppler_min=-5000
Acquisition_2S.doppler_step=60
Acquisition_2S.max_dwells=1
;######### TRACKING CONFIG ############
;######### GPS L1 C/A GENERIC TRACKING CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.if=0
Tracking_1C.dump=false
Tracking_1C.dump_filename=../data/epl_tracking_ch_
Tracking_1C.pll_bw_hz=40.0;
Tracking_1C.dll_bw_hz=3.0;
Tracking_1C.order=3;
Tracking_1C.early_late_space_chips=0.5;
;######### GPS L2C GENERIC TRACKING CONFIG ############
Tracking_2S.implementation=GPS_L2_M_DLL_PLL_Tracking
Tracking_2S.item_type=gr_complex
Tracking_2S.if=0
Tracking_2S.dump=false
Tracking_2S.dump_filename=./tracking_ch_
Tracking_2S.pll_bw_hz=2.0;
Tracking_2S.dll_bw_hz=0.25;
Tracking_2S.order=2;
Tracking_2S.early_late_space_chips=0.5;
;######### TELEMETRY DECODER CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
TelemetryDecoder_1C.decimation_factor=20;
TelemetryDecoder_2S.implementation=GPS_L2C_Telemetry_Decoder
TelemetryDecoder_2S.dump=false
TelemetryDecoder_2S.decimation_factor=1;
;######### OBSERVABLES CONFIG ############
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
Observables.dump=true
;#dump_filename: Log path and filename.
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#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=100
;# KML, GeoJSON, NMEA and RTCM output configuration
;#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
;#nmea_dump_filename: NMEA log path and filename
PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea;
;#flag_nmea_tty_port: Enable or disable the NMEA log to a serial TTY port (Can be used with real hardware or virtual one)
PVT.flag_nmea_tty_port=false;
;#nmea_dump_devname: serial device descriptor for NMEA logging
PVT.nmea_dump_devname=/dev/pts/4
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
;#dump: Enable or disable the PVT internal binary data file logging [true] or [false]
PVT.dump=false

View File

@ -420,7 +420,7 @@ TelemetryDecoder_Galileo.dump=false
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
@ -431,14 +431,8 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=Hybrid_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=false
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#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;

View File

@ -446,7 +446,7 @@ TelemetryDecoder_1B.decimation_factor=4;
;######### OBSERVABLES CONFIG ############
;#implementation: Use [GPS_L1_CA_Observables] for GPS L1 C/A.
;#implementation:
Observables.implementation=Hybrid_Observables
;#dump: Enable or disable the Observables internal binary data file logging [true] or [false]
@ -457,14 +457,8 @@ Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version.
PVT.implementation=Hybrid_PVT
;#averaging_depth: Number of PVT observations in the moving average algorithm
PVT.averaging_depth=10
;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false]
PVT.flag_averaging=false
;#implementation: Position Velocity and Time (PVT) implementation:
PVT.implementation=RTKLIB_PVT
;#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=10;

View File

@ -16,10 +16,8 @@
# along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
#
set(PVT_ADAPTER_SOURCES
gps_l1_ca_pvt.cc
galileo_e1_pvt.cc
hybrid_pvt.cc
set(PVT_ADAPTER_SOURCES
rtklib_pvt.cc
)
include_directories(
@ -29,6 +27,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/core/receiver
${CMAKE_SOURCE_DIR}/src/algorithms/PVT/gnuradio_blocks
${CMAKE_SOURCE_DIR}/src/algorithms/PVT/libs
${CMAKE_SOURCE_DIR}/src/algorithms/libs/rtklib
${ARMADILLO_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS}

View File

@ -1,141 +0,0 @@
/*!
* \file galileo_e1_pvt.cc
* \brief Implementation of an adapter of a GALILEO E1 PVT solver block to a
* PvtInterface
* \author Javier Arribas, 2011. jarribas(at)cttc.es
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "galileo_e1_pvt.h"
#include <boost/math/common_factor_rt.hpp>
#include <glog/logging.h>
#include "configuration_interface.h"
using google::LogMessage;
GalileoE1Pvt::GalileoE1Pvt(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams) :
role_(role),
in_streams_(in_streams),
out_streams_(out_streams)
{
// dump parameters
std::string default_dump_filename = "./pvt.dat";
std::string default_nmea_dump_filename = "./nmea_pvt.nmea";
std::string default_nmea_dump_devname = "/dev/tty1";
std::string default_rtcm_dump_devname = "/dev/pts/1";
DLOG(INFO) << "role " << role;
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
// moving average depth parameters
int averaging_depth = configuration->property(role + ".averaging_depth", 10);
bool flag_averaging = configuration->property(role + ".flag_averaging", false);
// output rate
int output_rate_ms = configuration->property(role + ".output_rate_ms", 500);
// display rate
int display_rate_ms = configuration->property(role + ".display_rate_ms", 500);
// NMEA Printer settings
bool flag_nmea_tty_port = configuration->property(role + ".flag_nmea_tty_port", false);
std::string nmea_dump_filename = configuration->property(role + ".nmea_dump_filename", default_nmea_dump_filename);
std::string nmea_dump_devname = configuration->property(role + ".nmea_dump_devname", default_nmea_dump_devname);
// RTCM Printer settings
bool flag_rtcm_tty_port = configuration->property(role + ".flag_rtcm_tty_port", false);
std::string rtcm_dump_devname = configuration->property(role + ".rtcm_dump_devname", default_rtcm_dump_devname);
bool flag_rtcm_server = configuration->property(role + ".flag_rtcm_server", false);
unsigned short rtcm_tcp_port = configuration->property(role + ".rtcm_tcp_port", 2101);
unsigned short rtcm_station_id = configuration->property(role + ".rtcm_station_id", 1234);
// RTCM message rates: least common multiple with output_rate_ms
int rtcm_MT1045_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1045_rate_ms", 5000), output_rate_ms);
int rtcm_MSM_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MSM_rate_ms", 1000), output_rate_ms);
std::map<int,int> rtcm_msg_rate_ms;
rtcm_msg_rate_ms[1045] = rtcm_MT1045_rate_ms;
for (int k = 1091; k < 1098; k++) // All Galileo MSM
{
rtcm_msg_rate_ms[k] = rtcm_MSM_rate_ms;
}
// make PVT object
pvt_ = galileo_e1_make_pvt_cc(in_streams_,
dump_,
dump_filename_,
averaging_depth,
flag_averaging,
output_rate_ms,
display_rate_ms,
flag_nmea_tty_port,
nmea_dump_filename,
nmea_dump_devname,
flag_rtcm_server,
flag_rtcm_tty_port,
rtcm_tcp_port,
rtcm_station_id,
rtcm_msg_rate_ms,
rtcm_dump_devname);
DLOG(INFO) << "pvt(" << pvt_->unique_id() << ")";
}
GalileoE1Pvt::~GalileoE1Pvt()
{}
void GalileoE1Pvt::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 GalileoE1Pvt::disconnect(gr::top_block_sptr top_block)
{
if(top_block) { /* top_block is not null */};
// Nothing to disconnect
}
gr::basic_block_sptr GalileoE1Pvt::get_left_block()
{
return pvt_;
}
gr::basic_block_sptr GalileoE1Pvt::get_right_block()
{
return pvt_;
}

View File

@ -1,94 +0,0 @@
/*!
* \file galileo_e1_pvt.h
* \brief Interface of an adapter of a GALILEO E1 PVT solver block to a
* PvtInterface.
* \author Javier Arribas, 2013. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GALILEO_E1_PVT_H_
#define GNSS_SDR_GALILEO_E1_PVT_H_
#include <string>
#include "pvt_interface.h"
#include "galileo_e1_pvt_cc.h"
class ConfigurationInterface;
/*!
* \brief This class implements a PvtInterface for Galileo E1
*/
class GalileoE1Pvt : public PvtInterface
{
public:
GalileoE1Pvt(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~GalileoE1Pvt();
std::string role()
{
return role_;
}
//! Returns "GALILEO_E1_PVT"
std::string implementation()
{
return "GALILEO_E1_PVT";
}
void connect(gr::top_block_sptr top_block);
void disconnect(gr::top_block_sptr top_block);
gr::basic_block_sptr get_left_block();
gr::basic_block_sptr get_right_block();
void reset()
{
return;
}
//! All blocks must have an item_size() function implementation. Returns sizeof(gr_complex)
size_t item_size()
{
return sizeof(gr_complex);
}
private:
galileo_e1_pvt_cc_sptr pvt_;
bool dump_;
//unsigned int fs_in_;
std::string dump_filename_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
};
#endif

View File

@ -1,250 +0,0 @@
/*!
* \file gps_l1_ca_pvt.cc
* \brief Implementation of an adapter of a GPS L1 C/A PVT solver block to a
* PvtInterface
* \author Javier Arribas, 2011. jarribas(at)cttc.es
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "gps_l1_ca_pvt.h"
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/math/common_factor_rt.hpp>
#include <boost/serialization/map.hpp>
#include <glog/logging.h>
#include "configuration_interface.h"
using google::LogMessage;
GpsL1CaPvt::GpsL1CaPvt(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams) :
role_(role),
in_streams_(in_streams),
out_streams_(out_streams)
{
// dump parameters
std::string default_dump_filename = "./pvt.dat";
std::string default_nmea_dump_filename = "./nmea_pvt.nmea";
std::string default_nmea_dump_devname = "/dev/tty1";
std::string default_rtcm_dump_devname = "/dev/pts/1";
DLOG(INFO) << "role " << role;
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
// moving average depth parameters
int averaging_depth = configuration->property(role + ".averaging_depth", 10);
bool flag_averaging = configuration->property(role + ".flag_averaging", false);
// output rate
int output_rate_ms = configuration->property(role + ".output_rate_ms", 500);
// display rate
int display_rate_ms = configuration->property(role + ".display_rate_ms", 500);
// NMEA Printer settings
bool flag_nmea_tty_port = configuration->property(role + ".flag_nmea_tty_port", false);
std::string nmea_dump_filename = configuration->property(role + ".nmea_dump_filename", default_nmea_dump_filename);
std::string nmea_dump_devname = configuration->property(role + ".nmea_dump_devname", default_nmea_dump_devname);
// RTCM Printer settings
bool flag_rtcm_tty_port = configuration->property(role + ".flag_rtcm_tty_port", false);
std::string rtcm_dump_devname = configuration->property(role + ".rtcm_dump_devname", default_rtcm_dump_devname);
bool flag_rtcm_server = configuration->property(role + ".flag_rtcm_server", false);
unsigned short rtcm_tcp_port = configuration->property(role + ".rtcm_tcp_port", 2101);
unsigned short rtcm_station_id = configuration->property(role + ".rtcm_station_id", 1234);
// RTCM message rates: least common multiple with output_rate_ms
int rtcm_MT1019_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1019_rate_ms", 5000), output_rate_ms);
int rtcm_MSM_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MSM_rate_ms", 1000), output_rate_ms);
std::map<int,int> rtcm_msg_rate_ms;
rtcm_msg_rate_ms[1019] = rtcm_MT1019_rate_ms;
for (int k = 1071; k < 1078; k++) // All GPS MSM
{
rtcm_msg_rate_ms[k] = rtcm_MSM_rate_ms;
}
// getting names from the config file, if available
// default filename for assistance data
const std::string eph_default_xml_filename = "./gps_ephemeris.xml";
eph_xml_filename_= configuration->property("GNSS-SDR.SUPL_gps_ephemeris_xml", eph_default_xml_filename);
//const std::string utc_default_xml_filename = "./gps_utc_model.xml";
//const std::string iono_default_xml_filename = "./gps_iono.xml";
//const std::string ref_time_default_xml_filename = "./gps_ref_time.xml";
//const std::string ref_location_default_xml_filename = "./gps_ref_location.xml";
//std::string utc_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_utc_model.xml", utc_default_xml_filename);
//std::string iono_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_iono_xml", iono_default_xml_filename);
//std::string ref_time_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_ref_time_xml", ref_time_default_xml_filename);
//std::string ref_location_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_ref_location_xml", ref_location_default_xml_filename);
// RINEX version
int conf_rinex_version;
conf_rinex_version = configuration->property(role + ".rinex_version", 0);
// make PVT object
pvt_ = gps_l1_ca_make_pvt_cc(in_streams_,
dump_,
dump_filename_,
averaging_depth,
flag_averaging,
output_rate_ms,
display_rate_ms,
flag_nmea_tty_port,
nmea_dump_filename,
nmea_dump_devname,
flag_rtcm_server,
flag_rtcm_tty_port,
rtcm_tcp_port,
rtcm_station_id,
rtcm_msg_rate_ms,
rtcm_dump_devname,
conf_rinex_version );
DLOG(INFO) << "pvt(" << pvt_->unique_id() << ")";
}
bool GpsL1CaPvt::save_assistance_to_XML()
{
// return variable (true == succeeded)
bool ret = false;
LOG(INFO) << "SUPL: Try to save GPS ephemeris to XML file " << eph_xml_filename_;
std::map<int,Gps_Ephemeris> eph_map = pvt_->get_GPS_L1_ephemeris_map();
if (eph_map.size() > 0)
{
try
{
std::ofstream ofs(eph_xml_filename_.c_str(), std::ofstream::trunc | std::ofstream::out);
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_ephemeris_map", eph_map);
ofs.close();
LOG(INFO) << "Saved GPS L1 Ephemeris map data";
}
catch (std::exception& e)
{
LOG(WARNING) << e.what();
return false;
}
return true;
}
else
{
LOG(WARNING) << "Failed to save Ephemeris, map is empty";
return false;
}
// Only try to save {utc, iono, ref time, ref location} if SUPL is enabled
// bool enable_gps_supl_assistance = configuration_->property("GNSS-SDR.SUPL_gps_enabled", false);
// if (enable_gps_supl_assistance == true)
// {
// // try to save utc model xml file
// std::map<int, Gps_Utc_Model> utc_copy = global_gps_utc_model_map.get_map_copy();
// if (supl_client_acquisition_.save_utc_map_xml(utc_xml_filename, utc_copy) == true)
// {
// LOG(INFO) << "SUPL: Successfully saved UTC Model XML file";
// //ret = true;
// }
// else
// {
// LOG(INFO) << "SUPL: Error while trying to save utc XML file";
// //ret = false;
// }
// // try to save iono model xml file
// std::map<int, Gps_Iono> iono_copy = global_gps_iono_map.get_map_copy();
// if (supl_client_acquisition_.save_iono_map_xml(iono_xml_filename, iono_copy) == true)
// {
// LOG(INFO) << "SUPL: Successfully saved IONO Model XML file";
// //ret = true;
// }
// else
// {
// LOG(INFO) << "SUPL: Error while trying to save iono XML file";
// //ret = false;
// }
// // try to save ref time xml file
// std::map<int, Gps_Ref_Time> ref_time_copy = global_gps_ref_time_map.get_map_copy();
// if (supl_client_acquisition_.save_ref_time_map_xml(ref_time_xml_filename, ref_time_copy) == true)
// {
// LOG(INFO) << "SUPL: Successfully saved Ref Time XML file";
// //ret = true;
// }
// else
// {
// LOG(INFO) << "SUPL: Error while trying to save ref time XML file";
// //ref = false;
// }
// // try to save ref location xml file
// std::map<int, Gps_Ref_Location> ref_location_copy = global_gps_ref_location_map.get_map_copy();
// if (supl_client_acquisition_.save_ref_location_map_xml(ref_location_xml_filename, ref_location_copy) == true)
// {
// LOG(INFO) << "SUPL: Successfully saved Ref Location XML file";
// //ref = true;
// }
// else
// {
// LOG(INFO) << "SUPL: Error while trying to save ref location XML file";
// //ret = false;
// }
// }
return ret;
}
GpsL1CaPvt::~GpsL1CaPvt()
{
save_assistance_to_XML();
}
void GpsL1CaPvt::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 GpsL1CaPvt::disconnect(gr::top_block_sptr top_block)
{
if(top_block) { /* top_block is not null */};
// Nothing to disconnect
}
gr::basic_block_sptr GpsL1CaPvt::get_left_block()
{
return pvt_;
}
gr::basic_block_sptr GpsL1CaPvt::get_right_block()
{
return pvt_;
}

View File

@ -1,98 +0,0 @@
/*!
* \file gps_l1_ca_pvt.h
* \brief Interface of an adapter of a GPS L1 C/A PVT solver block to a
* PvtInterface
* Position Velocity and Time
* \author Javier Arribas, 2011. jarribas(at)cttc.es
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GPS_L1_CA_PVT_H_
#define GNSS_SDR_GPS_L1_CA_PVT_H_
#include <string>
#include "pvt_interface.h"
#include "gps_l1_ca_pvt_cc.h"
class ConfigurationInterface;
/*!
* \brief This class implements a PvtInterface for GPS L1 C/A
*/
class GpsL1CaPvt : public PvtInterface
{
public:
GpsL1CaPvt(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~GpsL1CaPvt();
std::string role()
{
return role_;
}
//! Returns "GPS_L1_CA_PVT"
std::string implementation()
{
return "GPS_L1_CA_PVT";
}
void connect(gr::top_block_sptr top_block);
void disconnect(gr::top_block_sptr top_block);
gr::basic_block_sptr get_left_block();
gr::basic_block_sptr get_right_block();
void reset()
{
return;
}
//! All blocks must have an item_size() function implementation. Returns sizeof(gr_complex)
size_t item_size()
{
return sizeof(gr_complex);
}
private:
gps_l1_ca_pvt_cc_sptr pvt_;
bool dump_;
std::string dump_filename_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
std::string eph_xml_filename_;
bool save_assistance_to_XML();
};
#endif

View File

@ -1,237 +0,0 @@
/*!
* \file hybrid_pvt.cc
* \brief Implementation of an adapter of a GALILEO E1 PVT solver block to a
* PvtInterface
* \author Javier Arribas, 2011. jarribas(at)cttc.es
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "hybrid_pvt.h"
#include <glog/logging.h>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/math/common_factor_rt.hpp>
#include <boost/serialization/map.hpp>
#include "configuration_interface.h"
using google::LogMessage;
HybridPvt::HybridPvt(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams) :
role_(role),
in_streams_(in_streams),
out_streams_(out_streams)
{
// dump parameters
std::string default_dump_filename = "./pvt.dat";
std::string default_nmea_dump_filename = "./nmea_pvt.nmea";
std::string default_nmea_dump_devname = "/dev/tty1";
std::string default_rtcm_dump_devname = "/dev/pts/1";
DLOG(INFO) << "role " << role;
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
// moving average depth parameters
int averaging_depth = configuration->property(role + ".averaging_depth", 10);
bool flag_averaging = configuration->property(role + ".flag_averaging", false);
// output rate
int output_rate_ms = configuration->property(role + ".output_rate_ms", 500);
// display rate
int display_rate_ms = configuration->property(role + ".display_rate_ms", 500);
// NMEA Printer settings
bool flag_nmea_tty_port = configuration->property(role + ".flag_nmea_tty_port", false);
std::string nmea_dump_filename = configuration->property(role + ".nmea_dump_filename", default_nmea_dump_filename);
std::string nmea_dump_devname = configuration->property(role + ".nmea_dump_devname", default_nmea_dump_devname);
// RTCM Printer settings
bool flag_rtcm_tty_port = configuration->property(role + ".flag_rtcm_tty_port", false);
std::string rtcm_dump_devname = configuration->property(role + ".rtcm_dump_devname", default_rtcm_dump_devname);
bool flag_rtcm_server = configuration->property(role + ".flag_rtcm_server", false);
unsigned short rtcm_tcp_port = configuration->property(role + ".rtcm_tcp_port", 2101);
unsigned short rtcm_station_id = configuration->property(role + ".rtcm_station_id", 1234);
// RTCM message rates: least common multiple with output_rate_ms
int rtcm_MT1019_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1019_rate_ms", 5000), output_rate_ms);
int rtcm_MT1045_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1045_rate_ms", 5000), output_rate_ms);
int rtcm_MSM_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MSM_rate_ms", 1000), output_rate_ms);
int rtcm_MT1077_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1077_rate_ms", rtcm_MSM_rate_ms), output_rate_ms);
int rtcm_MT1097_rate_ms = boost::math::lcm(configuration->property(role + ".rtcm_MT1097_rate_ms", rtcm_MSM_rate_ms), output_rate_ms);
std::map<int,int> rtcm_msg_rate_ms;
rtcm_msg_rate_ms[1019] = rtcm_MT1019_rate_ms;
rtcm_msg_rate_ms[1045] = rtcm_MT1045_rate_ms;
for (int k = 1071; k < 1078; k++) // All GPS MSM
{
rtcm_msg_rate_ms[k] = rtcm_MT1077_rate_ms;
}
for (int k = 1091; k < 1098; k++) // All Galileo MSM
{
rtcm_msg_rate_ms[k] = rtcm_MT1097_rate_ms;
}
// getting names from the config file, if available
// default filename for assistance data
const std::string eph_default_xml_filename = "./gps_ephemeris.xml";
const std::string utc_default_xml_filename = "./gps_utc_model.xml";
const std::string iono_default_xml_filename = "./gps_iono.xml";
const std::string ref_time_default_xml_filename = "./gps_ref_time.xml";
const std::string ref_location_default_xml_filename = "./gps_ref_location.xml";
eph_xml_filename_ = configuration->property("GNSS-SDR.SUPL_gps_ephemeris_xml", eph_default_xml_filename);
//std::string utc_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_utc_model.xml", utc_default_xml_filename);
//std::string iono_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_iono_xml", iono_default_xml_filename);
//std::string ref_time_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_ref_time_xml", ref_time_default_xml_filename);
//std::string ref_location_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_ref_location_xml", ref_location_default_xml_filename);
// Infer the type of receiver
/*
* TYPE | RECEIVER
* 0 | Unknown
* 1 | GPS L1 C/A
* 2 | GPS L2C
* 3 | GPS L5
* 4 | Galileo E1B
* 5 | Galileo E5a
* 6 | Galileo E5b
* 7 | GPS L1 C/A + GPS L2C
* 8 | GPS L1 C/A + GPS L5
* 9 | GPS L1 C/A + Galileo E1B
* 10 | GPS L1 C/A + Galileo E5a
* 11 | GPS L1 C/A + Galileo E5b
* 12 | Galileo E1B + GPS L2C
* 13 | Galileo E1B + GPS L5
* 14 | Galileo E1B + Galileo E5a
* 15 | Galileo E1B + Galileo E5b
* 16 | GPS L2C + GPS L5
* 17 | GPS L2C + Galileo E5a
* 18 | GPS L2C + Galileo E5b
* 19 | GPS L5 + Galileo E5a
* 20 | GPS L5 + Galileo E5b
* 21 | GPS L1 C/A + Galileo E1B + GPS L2C
* 22 | GPS L1 C/A + Galileo E1B + GPS L5
*/
int gps_1C_count = configuration->property("Channels_1C.count", 0);
int gps_2S_count = configuration->property("Channels_2S.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_E5b_count = configuration->property("Channels_7X.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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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;
// make PVT object
pvt_ = hybrid_make_pvt_cc(in_streams_, dump_, dump_filename_, averaging_depth, flag_averaging, output_rate_ms, display_rate_ms, flag_nmea_tty_port, nmea_dump_filename, nmea_dump_devname, flag_rtcm_server, flag_rtcm_tty_port, rtcm_tcp_port, rtcm_station_id, rtcm_msg_rate_ms, rtcm_dump_devname, type_of_receiver);
DLOG(INFO) << "pvt(" << pvt_->unique_id() << ")";
}
bool HybridPvt::save_assistance_to_XML()
{
LOG(INFO) << "SUPL: Try to save GPS ephemeris to XML file " << eph_xml_filename_;
std::map<int,Gps_Ephemeris> eph_map = pvt_->get_GPS_L1_ephemeris_map();
if (eph_map.size() > 0)
{
try
{
std::ofstream ofs(eph_xml_filename_.c_str(), std::ofstream::trunc | std::ofstream::out);
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_ephemeris_map", eph_map);
ofs.close();
LOG(INFO) << "Saved GPS L1 Ephemeris map data";
}
catch (std::exception& e)
{
LOG(WARNING) << e.what();
return false;
}
return true; // return variable (true == succeeded)
}
else
{
LOG(WARNING) << "Failed to save Ephemeris, map is empty";
return false;
}
}
HybridPvt::~HybridPvt()
{
save_assistance_to_XML();
}
void HybridPvt::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 HybridPvt::disconnect(gr::top_block_sptr top_block)
{
if(top_block) { /* top_block is not null */};
// Nothing to disconnect
}
gr::basic_block_sptr HybridPvt::get_left_block()
{
return pvt_;
}
gr::basic_block_sptr HybridPvt::get_right_block()
{
return pvt_; // this is a sink, nothing downstream
}

View File

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

View File

@ -1,8 +1,7 @@
/*!
* \file hybrid_pvt.h
* \brief Interface of an adapter of a GALILEO E1 PVT solver block to a
* PvtInterface.
* \author Javier Arribas, 2013. jarribas(at)cttc.es
* \file rtklib_pvt.h
* \brief Interface of a Position Velocity and Time computation block
* \author Javier Arribas, 2017. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
@ -31,12 +30,12 @@
#ifndef GNSS_SDR_HYBRID_PVT_H_
#define GNSS_SDR_HYBRID_PVT_H_
#ifndef GNSS_SDR_RTKLIB_PVT_H_
#define GNSS_SDR_RTKLIB_PVT_H_
#include <string>
#include "pvt_interface.h"
#include "hybrid_pvt_cc.h"
#include "rtklib_pvt_cc.h"
class ConfigurationInterface;
@ -44,25 +43,25 @@ class ConfigurationInterface;
/*!
* \brief This class implements a PvtInterface for Galileo E1
*/
class HybridPvt : public PvtInterface
class RtklibPvt : public PvtInterface
{
public:
HybridPvt(ConfigurationInterface* configuration,
RtklibPvt(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~HybridPvt();
virtual ~RtklibPvt();
std::string role()
{
return role_;
}
//! Returns "Hybrid_Pvt"
//! Returns "RTKLIB_Pvt"
std::string implementation()
{
return "Hybrid_PVT";
return "RTKLIB_PVT";
}
void connect(gr::top_block_sptr top_block);
@ -82,13 +81,16 @@ public:
}
private:
hybrid_pvt_cc_sptr pvt_;
rtklib_pvt_cc_sptr pvt_;
rtk_t rtk;
bool dump_;
std::string dump_filename_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
std::string eph_xml_filename_;
bool save_assistance_to_XML();
};

View File

@ -16,10 +16,8 @@
# along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
#
set(PVT_GR_BLOCKS_SOURCES
gps_l1_ca_pvt_cc.cc
galileo_e1_pvt_cc.cc
hybrid_pvt_cc.cc
set(PVT_GR_BLOCKS_SOURCES
rtklib_pvt_cc.cc
)
include_directories(
@ -28,6 +26,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/core/interfaces
${CMAKE_SOURCE_DIR}/src/core/receiver
${CMAKE_SOURCE_DIR}/src/algorithms/PVT/libs
${CMAKE_SOURCE_DIR}/src/algorithms/libs/rtklib
${ARMADILLO_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS}

View File

@ -1,424 +0,0 @@
/*!
* \file galileo_e1_pvt_cc.cc
* \brief Implementation of a Position Velocity and Time computation block for GPS L1 C/A
* \author Javier Arribas, 2013. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "galileo_e1_pvt_cc.h"
#include <algorithm>
#include <iostream>
#include <map>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/math/common_factor_rt.hpp>
#include <gnuradio/gr_complex.h>
#include <gnuradio/io_signature.h>
#include <glog/logging.h>
#include "concurrent_map.h"
using google::LogMessage;
galileo_e1_pvt_cc_sptr galileo_e1_make_pvt_cc(unsigned int nchannels, bool dump, std::string dump_filename, int averaging_depth,
bool flag_averaging, int output_rate_ms, int display_rate_ms, bool flag_nmea_tty_port, std::string nmea_dump_filename,
std::string nmea_dump_devname, bool flag_rtcm_server, bool flag_rtcm_tty_port, unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id, std::map<int,int> rtcm_msg_rate_ms, std::string rtcm_dump_devname)
{
return galileo_e1_pvt_cc_sptr(new galileo_e1_pvt_cc(nchannels, dump, dump_filename, averaging_depth,
flag_averaging, output_rate_ms, display_rate_ms, flag_nmea_tty_port, nmea_dump_filename, nmea_dump_devname,
flag_rtcm_server, flag_rtcm_tty_port, rtcm_tcp_port, rtcm_station_id, rtcm_msg_rate_ms, rtcm_dump_devname));
}
void galileo_e1_pvt_cc::msg_handler_telemetry(pmt::pmt_t msg)
{
try {
if( pmt::any_ref(msg).type() == typeid(std::shared_ptr<Galileo_Ephemeris>) )
{
// ### Galileo EPHEMERIS ###
std::shared_ptr<Galileo_Ephemeris> galileo_eph;
galileo_eph = boost::any_cast<std::shared_ptr<Galileo_Ephemeris>>(pmt::any_ref(msg));
// insert new ephemeris record
DLOG(INFO) << "Galileo New Ephemeris record inserted in global map with TOW =" << galileo_eph->TOW_5
<< ", GALILEO Week Number =" << galileo_eph->WN_5
<< " and Ephemeris IOD = " << galileo_eph->IOD_ephemeris;
// update/insert new ephemeris record to the global ephemeris map
d_ls_pvt->galileo_ephemeris_map[galileo_eph->i_satellite_PRN] = *galileo_eph;
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Galileo_Iono>) )
{
// ### Galileo IONO ###
std::shared_ptr<Galileo_Iono> galileo_iono;
galileo_iono = boost::any_cast<std::shared_ptr<Galileo_Iono>>(pmt::any_ref(msg));
d_ls_pvt->galileo_iono = *galileo_iono;
DLOG(INFO) << "New IONO record has arrived ";
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Galileo_Utc_Model>) )
{
// ### Galileo UTC MODEL ###
std::shared_ptr<Galileo_Utc_Model> galileo_utc_model;
galileo_utc_model = boost::any_cast<std::shared_ptr<Galileo_Utc_Model>>(pmt::any_ref(msg));
d_ls_pvt->galileo_utc_model = *galileo_utc_model;
DLOG(INFO) << "New UTC record has arrived ";
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Galileo_Almanac>) )
{
// ### Galileo Almanac ###
std::shared_ptr<Galileo_Almanac> galileo_almanac;
galileo_almanac = boost::any_cast<std::shared_ptr<Galileo_Almanac>>(pmt::any_ref(msg));
// update/insert new ephemeris record to the global ephemeris map
d_ls_pvt->galileo_almanac = *galileo_almanac;
DLOG(INFO) << "New Galileo Almanac has arrived ";
}
else
{
LOG(WARNING) << "msg_handler_telemetry unknown object type!";
}
}
catch(boost::bad_any_cast& e)
{
LOG(WARNING) << "msg_handler_telemetry Bad any cast!\n";
}
}
galileo_e1_pvt_cc::galileo_e1_pvt_cc(unsigned int nchannels, bool dump, std::string dump_filename, int averaging_depth,
bool flag_averaging, int output_rate_ms, int display_rate_ms, bool flag_nmea_tty_port, std::string nmea_dump_filename, std::string nmea_dump_devname,
bool flag_rtcm_server, bool flag_rtcm_tty_port, unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id, std::map<int,int> rtcm_msg_rate_ms, std::string rtcm_dump_devname) :
gr::block("galileo_e1_pvt_cc", gr::io_signature::make(nchannels, nchannels, sizeof(Gnss_Synchro)), gr::io_signature::make(0, 0, sizeof(gr_complex)))
{
d_output_rate_ms = output_rate_ms;
d_display_rate_ms = display_rate_ms;
d_dump = dump;
d_nchannels = nchannels;
d_dump_filename = dump_filename;
std::string dump_ls_pvt_filename = dump_filename;
// GPS Ephemeris data message port in
this->message_port_register_in(pmt::mp("telemetry"));
this->set_msg_handler(pmt::mp("telemetry"), boost::bind(&galileo_e1_pvt_cc::msg_handler_telemetry, this, _1));
//initialize kml_printer
std::string kml_dump_filename;
kml_dump_filename = d_dump_filename;
d_kml_dump = std::make_shared<Kml_Printer>();
d_kml_dump->set_headers(kml_dump_filename);
//initialize geojson_printer
std::string geojson_dump_filename;
geojson_dump_filename = d_dump_filename;
d_geojson_printer = std::make_shared<GeoJSON_Printer>();
d_geojson_printer->set_headers(geojson_dump_filename);
//initialize nmea_printer
d_nmea_printer = std::make_shared<Nmea_Printer>(nmea_dump_filename, flag_nmea_tty_port, nmea_dump_devname);
//initialize rtcm_printer
std::string rtcm_dump_filename;
rtcm_dump_filename = d_dump_filename;
unsigned short _port = rtcm_tcp_port;
unsigned short _station_id = rtcm_station_id;
d_rtcm_printer = std::make_shared<Rtcm_Printer>(rtcm_dump_filename, flag_rtcm_server, flag_rtcm_tty_port, _port, _station_id, rtcm_dump_devname);
if(rtcm_msg_rate_ms.find(1045) != rtcm_msg_rate_ms.end())
{
d_rtcm_MT1045_rate_ms = rtcm_msg_rate_ms[1045];
}
else
{
d_rtcm_MT1045_rate_ms = boost::math::lcm(5000, d_output_rate_ms); // default value if not set
}
if(rtcm_msg_rate_ms.find(1091) != rtcm_msg_rate_ms.end()) // whatever between 1091 and 1097
{
d_rtcm_MSM_rate_ms = rtcm_msg_rate_ms[1091];
}
else
{
d_rtcm_MSM_rate_ms = boost::math::lcm(1000, d_output_rate_ms); // default value if not set
}
b_rtcm_writing_started = false;
d_dump_filename.append("_raw.dat");
dump_ls_pvt_filename.append("_ls_pvt.dat");
d_averaging_depth = averaging_depth;
d_flag_averaging = flag_averaging;
d_ls_pvt = std::make_shared<galileo_e1_ls_pvt>(nchannels, dump_ls_pvt_filename, d_dump);
d_ls_pvt->set_averaging_depth(d_averaging_depth);
d_sample_counter = 0;
d_last_sample_nav_output = 0;
d_rx_time = 0.0;
b_rinex_header_written = false;
b_rinex_header_updated = false;
rp = std::make_shared<Rinex_Printer>();
d_last_status_print_seg = 0;
// ############# ENABLE DATA FILE LOG #################
if (d_dump == true)
{
if (d_dump_file.is_open() == false)
{
try
{
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) << "PVT dump enabled Log file: " << d_dump_filename.c_str();
}
catch (const std::ifstream::failure& e)
{
LOG(WARNING) << "Exception opening PVT dump file " << e.what();
}
}
}
// Create Sys V message queue
first_fix = true;
sysv_msg_key = 1101;
int msgflg = IPC_CREAT | 0666;
if ((sysv_msqid = msgget(sysv_msg_key, msgflg )) == -1)
{
std::cout << "GNSS-SDR can not create message queues!" << std::endl;
throw new std::exception();
}
}
galileo_e1_pvt_cc::~galileo_e1_pvt_cc()
{
msgctl(sysv_msqid, IPC_RMID, NULL);
}
void galileo_e1_pvt_cc::print_receiver_status(Gnss_Synchro** channels_synchronization_data)
{
// Print the current receiver status using std::cout every second
int current_rx_seg = floor(channels_synchronization_data[0][0].Tracking_timestamp_secs);
if ( current_rx_seg != d_last_status_print_seg)
{
d_last_status_print_seg = current_rx_seg;
std::cout << "Current input signal time = " << current_rx_seg << " [s]" << std::endl << std::flush;
//DLOG(INFO) << "GPS L1 C/A Tracking CH " << d_channel << ": Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN)
// << ", CN0 = " << d_CN0_SNV_dB_Hz << " [dB-Hz]" << std::endl;
}
}
bool galileo_e1_pvt_cc::send_sys_v_ttff_msg(ttff_msgbuf ttff)
{
/* Fill Sys V message structures */
int msgsend_size;
ttff_msgbuf msg;
msg.ttff = ttff.ttff;
msgsend_size = sizeof(msg.ttff);
msg.mtype = 1; /* default message ID */
/* SEND SOLUTION OVER A MESSAGE QUEUE */
/* non-blocking Sys V message send */
msgsnd(sysv_msqid, &msg, msgsend_size, IPC_NOWAIT);
return true;
}
int galileo_e1_pvt_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 __attribute__((unused)))
{
d_sample_counter++;
std::map<int,Gnss_Synchro> gnss_observables_map;
Gnss_Synchro **in = (Gnss_Synchro **) &input_items[0]; //Get the input pointer
print_receiver_status(in);
// ############ 1. READ PSEUDORANGES ####
for (unsigned int i = 0; i < d_nchannels; i++)
{
if (in[i][0].Flag_valid_pseudorange == true)
{
gnss_observables_map.insert(std::pair<int,Gnss_Synchro>(in[i][0].PRN, in[i][0])); // store valid pseudoranges in a map
d_rx_time = in[i][0].d_TOW_at_current_symbol; // all the channels have the same RX timestamp (common RX time pseudoranges)
if(d_ls_pvt->galileo_ephemeris_map.size() > 0)
{
std::map<int,Galileo_Ephemeris>::iterator tmp_eph_iter = d_ls_pvt->galileo_ephemeris_map.find(in[i][0].PRN);
if(tmp_eph_iter != d_ls_pvt->galileo_ephemeris_map.end())
{
d_rtcm_printer->lock_time(d_ls_pvt->galileo_ephemeris_map.find(in[i][0].PRN)->second, d_rx_time, in[i][0]); // keep track of locking time
}
}
}
}
// ############ 2 COMPUTE THE PVT ################################
if (gnss_observables_map.size() > 0 and d_ls_pvt->galileo_ephemeris_map.size() > 0)
{
// compute on the fly PVT solution
if ((d_sample_counter % d_output_rate_ms) == 0)
{
bool pvt_result;
pvt_result = d_ls_pvt->get_PVT(gnss_observables_map, d_rx_time, d_flag_averaging);
if (pvt_result == true)
{
// correct the observable to account for the receiver clock offset
for (std::map<int,Gnss_Synchro>::iterator it = gnss_observables_map.begin(); it != gnss_observables_map.end(); ++it)
{
it->second.Pseudorange_m = it->second.Pseudorange_m - d_ls_pvt->d_rx_dt_s * GPS_C_m_s;
}
if( first_fix == true)
{
std::cout << "First position fix at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
<< " UTC is Lat = " << d_ls_pvt->d_latitude_d << " [deg], Long = " << d_ls_pvt->d_longitude_d
<< " [deg], Height= " << d_ls_pvt->d_height_m << " [m]" << std::endl;
ttff_msgbuf ttff;
ttff.mtype = 1;
ttff.ttff = d_sample_counter;
send_sys_v_ttff_msg(ttff);
first_fix = false;
}
d_kml_dump->print_position(d_ls_pvt, d_flag_averaging);
d_geojson_printer->print_position(d_ls_pvt, d_flag_averaging);
d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging);
if (!b_rinex_header_written)
{
std::map<int,Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.begin();
if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end())
{
rp->rinex_obs_header(rp->obsFile, galileo_ephemeris_iter->second, d_rx_time);
rp->rinex_nav_header(rp->navGalFile, d_ls_pvt->galileo_iono, d_ls_pvt->galileo_utc_model, d_ls_pvt->galileo_almanac);
b_rinex_header_written = true; // do not write header anymore
}
}
if(b_rinex_header_written) // Put here another condition to separate annotations (e.g 30 s)
{
// Limit the RINEX navigation output rate to 1/6 seg
// Notice that d_sample_counter period is 4ms (for Galileo correlators)
if ((d_sample_counter - d_last_sample_nav_output) >= 6000)
{
rp->log_rinex_nav(rp->navGalFile, d_ls_pvt->galileo_ephemeris_map);
d_last_sample_nav_output = d_sample_counter;
}
std::map<int, Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.begin();
if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end())
{
rp->log_rinex_obs(rp->obsFile, galileo_ephemeris_iter->second, d_rx_time, gnss_observables_map);
}
if (!b_rinex_header_updated && (d_ls_pvt->galileo_utc_model.A0_6 != 0))
{
rp->update_nav_header(rp->navGalFile, d_ls_pvt->galileo_iono, d_ls_pvt->galileo_utc_model, d_ls_pvt->galileo_almanac);
rp->update_obs_header(rp->obsFile, d_ls_pvt->galileo_utc_model);
b_rinex_header_updated = true;
}
}
if(b_rtcm_writing_started)
{
if((d_sample_counter % (d_rtcm_MT1045_rate_ms / 4) ) == 0)
{
for(std::map<int,Galileo_Ephemeris>::iterator gal_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.begin(); gal_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end(); gal_ephemeris_iter++ )
{
d_rtcm_printer->Print_Rtcm_MT1045(gal_ephemeris_iter->second);
}
}
if((d_sample_counter % (d_rtcm_MSM_rate_ms / 4) ) == 0)
{
std::map<int,Galileo_Ephemeris>::iterator gal_ephemeris_iter;
gal_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.begin();
if (gal_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end())
{
d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, gal_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
}
}
if(!b_rtcm_writing_started) // the first time
{
for(std::map<int,Galileo_Ephemeris>::iterator gal_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.begin(); gal_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end(); gal_ephemeris_iter++ )
{
d_rtcm_printer->Print_Rtcm_MT1045(gal_ephemeris_iter->second);
}
std::map<int,Galileo_Ephemeris>::iterator gal_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.begin();
if (gal_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end())
{
d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, gal_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
b_rtcm_writing_started = true;
}
}
}
// DEBUG MESSAGE: Display position in console output
if (((d_sample_counter % d_display_rate_ms) == 0) and d_ls_pvt->b_valid_position == true)
{
std::cout << "Galileo Position at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
<< " UTC is Lat = " << d_ls_pvt->d_latitude_d << " [deg], Long = " << d_ls_pvt->d_longitude_d
<< " [deg], Height= " << d_ls_pvt->d_height_m << " [m]" << std::endl;
LOG(INFO) << "Position at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
<< " UTC is Lat = " << d_ls_pvt->d_latitude_d << " [deg], Long = " << d_ls_pvt->d_longitude_d
<< " [deg], Height= " << d_ls_pvt->d_height_m << " [m]";
LOG(INFO) << "Dilution of Precision at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
<< " is HDOP = " << d_ls_pvt->d_HDOP << " VDOP = "
<< d_ls_pvt->d_VDOP <<" TDOP = " << d_ls_pvt->d_TDOP
<< " GDOP = " << d_ls_pvt->d_GDOP;
}
// MULTIPLEXED FILE RECORDING - Record results to file
if(d_dump == true)
{
try
{
double tmp_double;
for (unsigned int i = 0; i < d_nchannels; i++)
{
tmp_double = in[i][0].Pseudorange_m;
d_dump_file.write((char*)&tmp_double, sizeof(double));
tmp_double = 0;
d_dump_file.write((char*)&tmp_double, sizeof(double));
d_dump_file.write((char*)&d_rx_time, sizeof(double));
}
}
catch (const std::ifstream::failure& e)
{
LOG(WARNING) << "Exception writing observables dump file " << e.what();
}
}
}
consume_each(1); //one by one
return 1;
}

View File

@ -1,155 +0,0 @@
/*!
* \file galileo_e1_pvt_cc.h
* \brief Interface of a Position Velocity and Time computation block for Galileo E1
* \author Javier Arribas, 2013. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GALILEO_E1_PVT_CC_H
#define GNSS_SDR_GALILEO_E1_PVT_CC_H
#include <fstream>
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <utility>
#include <gnuradio/block.h>
#include "nmea_printer.h"
#include "kml_printer.h"
#include "rinex_printer.h"
#include "geojson_printer.h"
#include "rtcm_printer.h"
#include "galileo_e1_ls_pvt.h"
class galileo_e1_pvt_cc;
typedef boost::shared_ptr<galileo_e1_pvt_cc> galileo_e1_pvt_cc_sptr;
galileo_e1_pvt_cc_sptr galileo_e1_make_pvt_cc(unsigned int n_channels,
bool dump,
std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname);
/*!
* \brief This class implements a block that computes the PVT solution with Galileo E1 signals
*/
class galileo_e1_pvt_cc : public gr::block
{
private:
friend galileo_e1_pvt_cc_sptr galileo_e1_make_pvt_cc(unsigned int nchannels,
bool dump,
std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname);
galileo_e1_pvt_cc(unsigned int nchannels,
bool dump, std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname);
void msg_handler_telemetry(pmt::pmt_t msg);
bool d_dump;
bool b_rinex_header_written;
bool b_rinex_header_updated;
bool b_rtcm_writing_started;
void print_receiver_status(Gnss_Synchro** channels_synchronization_data);
int d_last_status_print_seg; //for status printer
unsigned int d_nchannels;
std::string d_dump_filename;
std::ofstream d_dump_file;
int d_averaging_depth;
bool d_flag_averaging;
int d_output_rate_ms;
int d_display_rate_ms;
long unsigned int d_sample_counter;
long unsigned int d_last_sample_nav_output;
int d_rtcm_MT1045_rate_ms;
int d_rtcm_MSM_rate_ms;
std::shared_ptr<Rinex_Printer> rp;
std::shared_ptr<Kml_Printer> d_kml_dump;
std::shared_ptr<Nmea_Printer> d_nmea_printer;
std::shared_ptr<GeoJSON_Printer> d_geojson_printer;
std::shared_ptr<Rtcm_Printer> d_rtcm_printer;
double d_rx_time;
std::shared_ptr<galileo_e1_ls_pvt> d_ls_pvt;
bool first_fix;
key_t sysv_msg_key;
int sysv_msqid;
typedef struct {
long mtype;//required by sys v message
double ttff;
} ttff_msgbuf;
bool send_sys_v_ttff_msg(ttff_msgbuf ttff);
public:
~galileo_e1_pvt_cc (); //!< Default destructor
int general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); //!< PVT Signal Processing
};
#endif

View File

@ -1,505 +0,0 @@
/*!
* \file gps_l1_ca_pvt_cc.cc
* \brief Implementation of a Position Velocity and Time computation block for GPS L1 C/A
* \author Javier Arribas, 2011. jarribas(at)cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "gps_l1_ca_pvt_cc.h"
#include <algorithm>
#include <iostream>
#include <map>
#include <utility>
#include <boost/math/common_factor_rt.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <gnuradio/gr_complex.h>
#include <gnuradio/io_signature.h>
#include <glog/logging.h>
#include "concurrent_map.h"
#include "sbas_telemetry_data.h"
#include "sbas_ionospheric_correction.h"
using google::LogMessage;
gps_l1_ca_pvt_cc_sptr
gps_l1_ca_make_pvt_cc(unsigned int nchannels,
bool dump, std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname,
int rinex_version)
{
return gps_l1_ca_pvt_cc_sptr(new gps_l1_ca_pvt_cc(nchannels,
dump,
dump_filename,
averaging_depth,
flag_averaging,
output_rate_ms,
display_rate_ms,
flag_nmea_tty_port,
nmea_dump_filename,
nmea_dump_devname,
flag_rtcm_server,
flag_rtcm_tty_port,
rtcm_tcp_port,
rtcm_station_id,
rtcm_msg_rate_ms,
rtcm_dump_devname,
rinex_version));
}
void gps_l1_ca_pvt_cc::msg_handler_telemetry(pmt::pmt_t msg)
{
try {
if( pmt::any_ref(msg).type() == typeid(std::shared_ptr<Gps_Ephemeris>) )
{
// ### GPS EPHEMERIS ###
std::shared_ptr<Gps_Ephemeris> gps_eph;
gps_eph = boost::any_cast<std::shared_ptr<Gps_Ephemeris>>(pmt::any_ref(msg));
DLOG(INFO) << "Ephemeris record has arrived from SAT ID "
<< gps_eph->i_satellite_PRN << " (Block "
<< gps_eph->satelliteBlock[gps_eph->i_satellite_PRN] << ")"
<< "inserted with Toe="<< gps_eph->d_Toe<<" and GPS Week="
<< gps_eph->i_GPS_week;
// update/insert new ephemeris record to the global ephemeris map
d_ls_pvt->gps_ephemeris_map[gps_eph->i_satellite_PRN] = *gps_eph;
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Gps_Iono>) )
{
// ### GPS IONO ###
std::shared_ptr<Gps_Iono> gps_iono;
gps_iono = boost::any_cast<std::shared_ptr<Gps_Iono>>(pmt::any_ref(msg));
d_ls_pvt->gps_iono = *gps_iono;
DLOG(INFO) << "New IONO record has arrived ";
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Gps_Utc_Model>) )
{
// ### GPS UTC MODEL ###
std::shared_ptr<Gps_Utc_Model> gps_utc_model;
gps_utc_model = boost::any_cast<std::shared_ptr<Gps_Utc_Model>>(pmt::any_ref(msg));
d_ls_pvt->gps_utc_model = *gps_utc_model;
DLOG(INFO) << "New UTC record has arrived ";
}
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Sbas_Ionosphere_Correction>) )
{
// ### SBAS IONO ###
std::shared_ptr<Sbas_Ionosphere_Correction> sbas_iono;
sbas_iono = boost::any_cast<std::shared_ptr<Sbas_Ionosphere_Correction>>(pmt::any_ref(msg));
d_ls_pvt->sbas_iono = *sbas_iono;
DLOG(INFO) << "New SBAS IONO record has arrived ";
}
//TODO: add SBAS correction maps here
//d_ls_pvt->sbas_sat_corr_map = global_sbas_sat_corr_map.get_map_copy();
//d_ls_pvt->sbas_ephemeris_map = global_sbas_ephemeris_map.get_map_copy();
else if (pmt::any_ref(msg).type() == typeid(std::shared_ptr<Sbas_Raw_Msg>) )
{
std::shared_ptr<Sbas_Raw_Msg> sbas_raw_msg_ptr;
sbas_raw_msg_ptr = boost::any_cast<std::shared_ptr<Sbas_Raw_Msg>>(pmt::any_ref(msg));
Sbas_Raw_Msg sbas_raw_msg = *sbas_raw_msg_ptr;
// read SBAS raw messages directly from queue and write them into rinex file
// create the header of not yet done
if(!b_rinex_sbs_header_written)
{
rp->rinex_sbs_header(rp->sbsFile);
b_rinex_sbs_header_written = true;
}
// Define the RX time of the SBAS message by using the GPS time.
// It has only an effect if there has not been yet a SBAS MT12 available
// when the message was received.
if(sbas_raw_msg.get_rx_time_obj().is_related() == false
&& gnss_observables_map.size() > 0
&& d_ls_pvt->gps_ephemeris_map.size() > 0)
{
// doesn't matter which channel/satellite we choose
Gnss_Synchro gs = gnss_observables_map.begin()->second;
Gps_Ephemeris eph = d_ls_pvt->gps_ephemeris_map.begin()->second;
double relative_rx_time = gs.Tracking_timestamp_secs;
int gps_week = eph.i_GPS_week;
double gps_sec = gs.d_TOW_at_current_symbol;
Sbas_Time_Relation time_rel(relative_rx_time, gps_week, gps_sec);
sbas_raw_msg.relate(time_rel);
}
// send the message to the rinex logger if it has a valid GPS time stamp
if(sbas_raw_msg.get_rx_time_obj().is_related())
{
rp->log_rinex_sbs(rp->sbsFile, sbas_raw_msg);
}
}
else
{
LOG(WARNING) << "msg_handler_telemetry unknown object type!";
}
}
catch(boost::bad_any_cast& e)
{
LOG(WARNING) << "msg_handler_telemetry Bad any cast!\n";
}
}
std::map<int,Gps_Ephemeris> gps_l1_ca_pvt_cc::get_GPS_L1_ephemeris_map()
{
return d_ls_pvt->gps_ephemeris_map;
}
bool gps_l1_ca_pvt_cc::send_sys_v_ttff_msg(ttff_msgbuf ttff)
{
/* Fill Sys V message structures */
int msgsend_size;
ttff_msgbuf msg;
msg.ttff = ttff.ttff;
msgsend_size = sizeof(msg.ttff);
msg.mtype = 1; /* default message ID */
/* SEND SOLUTION OVER A MESSAGE QUEUE */
/* non-blocking Sys V message send */
msgsnd(sysv_msqid, &msg, msgsend_size, IPC_NOWAIT);
return true;
}
gps_l1_ca_pvt_cc::gps_l1_ca_pvt_cc(unsigned int nchannels,
bool dump, std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname,
int rinex_version) :
gr::block("gps_l1_ca_pvt_cc", gr::io_signature::make(nchannels, nchannels, sizeof(Gnss_Synchro)),
gr::io_signature::make(0, 0, sizeof(gr_complex)) )
{
d_output_rate_ms = output_rate_ms;
d_display_rate_ms = display_rate_ms;
d_dump = dump;
d_nchannels = nchannels;
d_dump_filename = dump_filename;
std::string dump_ls_pvt_filename = dump_filename;
// GPS Ephemeris data message port in
this->message_port_register_in(pmt::mp("telemetry"));
this->set_msg_handler(pmt::mp("telemetry"),
boost::bind(&gps_l1_ca_pvt_cc::msg_handler_telemetry, this, _1));
// initialize kml_printer
std::string kml_dump_filename;
kml_dump_filename = d_dump_filename;
d_kml_printer = std::make_shared<Kml_Printer>();
d_kml_printer->set_headers(kml_dump_filename);
// initialize geojson_printer
std::string geojson_dump_filename;
geojson_dump_filename = d_dump_filename;
d_geojson_printer = std::make_shared<GeoJSON_Printer>();
d_geojson_printer->set_headers(geojson_dump_filename);
// initialize nmea_printer
d_nmea_printer = std::make_shared<Nmea_Printer>(nmea_dump_filename, flag_nmea_tty_port, nmea_dump_devname);
// initialize rtcm_printer
std::string rtcm_dump_filename;
rtcm_dump_filename = d_dump_filename;
d_rtcm_tcp_port = rtcm_tcp_port;
d_rtcm_station_id = rtcm_station_id;
d_rtcm_printer = std::make_shared<Rtcm_Printer>(rtcm_dump_filename, flag_rtcm_server, flag_rtcm_tty_port, d_rtcm_tcp_port, d_rtcm_station_id, rtcm_dump_devname);
if(rtcm_msg_rate_ms.find(1019) != rtcm_msg_rate_ms.end())
{
d_rtcm_MT1019_rate_ms = rtcm_msg_rate_ms[1019];
}
else
{
d_rtcm_MT1019_rate_ms = boost::math::lcm(5000, d_output_rate_ms); // default value if not set
}
if(rtcm_msg_rate_ms.find(1071) != rtcm_msg_rate_ms.end()) // whatever between 1071 and 1077
{
d_rtcm_MSM_rate_ms = rtcm_msg_rate_ms[1071];
}
else
{
d_rtcm_MSM_rate_ms = boost::math::lcm(1000, d_output_rate_ms); // default value if not set
}
b_rtcm_writing_started = false;
d_dump_filename.append("_raw.dat");
dump_ls_pvt_filename.append("_ls_pvt.dat");
d_averaging_depth = averaging_depth;
d_flag_averaging = flag_averaging;
d_ls_pvt = std::make_shared<gps_l1_ca_ls_pvt>((int)nchannels, dump_ls_pvt_filename, d_dump);
d_ls_pvt->set_averaging_depth(d_averaging_depth);
d_sample_counter = 0;
d_last_sample_nav_output = 0;
d_rx_time = 0.0;
d_last_status_print_seg = 0;
b_rinex_header_written = false;
b_rinex_header_updated = false;
b_rinex_sbs_header_written = false;
rp = std::make_shared<Rinex_Printer>(rinex_version);
// ############# ENABLE DATA FILE LOG #################
if (d_dump == true)
{
if (d_dump_file.is_open() == false)
{
try
{
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) << "PVT dump enabled Log file: " << d_dump_filename.c_str();
}
catch (const std::ifstream::failure & e)
{
LOG(INFO) << "Exception opening PVT dump file " << e.what();
}
}
}
// Create Sys V message queue
first_fix = true;
sysv_msg_key = 1101;
int msgflg = IPC_CREAT | 0666;
if ((sysv_msqid = msgget(sysv_msg_key, msgflg )) == -1)
{
std::cout << "GNSS-SDR can not create message queues!" << std::endl;
throw new std::exception();
}
}
gps_l1_ca_pvt_cc::~gps_l1_ca_pvt_cc()
{
msgctl(sysv_msqid, IPC_RMID, NULL);
}
void gps_l1_ca_pvt_cc::print_receiver_status(Gnss_Synchro** channels_synchronization_data)
{
// Print the current receiver status using std::cout every second
int current_rx_seg = floor(channels_synchronization_data[0][0].Tracking_timestamp_secs);
if ( current_rx_seg!= d_last_status_print_seg)
{
d_last_status_print_seg = current_rx_seg;
std::cout << "Current input signal time = " << current_rx_seg << " [s]" << std::endl << std::flush;
//DLOG(INFO) << "GPS L1 C/A Tracking CH " << d_channel << ": Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN)
// << ", CN0 = " << d_CN0_SNV_dB_Hz << " [dB-Hz]";
}
}
int gps_l1_ca_pvt_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 __attribute__((unused)))
{
gnss_observables_map.clear();
d_sample_counter++;
Gnss_Synchro **in = (Gnss_Synchro **) &input_items[0]; // Get the input pointer
print_receiver_status(in);
// ############ 1. READ PSEUDORANGES ####
for (unsigned int i = 0; i < d_nchannels; i++)
{
if (in[i][0].Flag_valid_pseudorange == true)
{
gnss_observables_map.insert(std::pair<int,Gnss_Synchro>(in[i][0].PRN, in[i][0])); // store valid pseudoranges in a map
d_rx_time = in[i][0].d_TOW_at_current_symbol; // all the channels have the same RX timestamp (common RX time pseudoranges)
if(d_ls_pvt->gps_ephemeris_map.size() > 0)
{
std::map<int,Gps_Ephemeris>::iterator tmp_eph_iter = d_ls_pvt->gps_ephemeris_map.find(in[i][0].PRN);
if(tmp_eph_iter != d_ls_pvt->gps_ephemeris_map.end())
{
d_rtcm_printer->lock_time(d_ls_pvt->gps_ephemeris_map.find(in[i][0].PRN)->second, d_rx_time, in[i][0]); // keep track of locking time
}
}
}
}
// ############ 2 COMPUTE THE PVT ################################
if (gnss_observables_map.size() > 0 and d_ls_pvt->gps_ephemeris_map.size() > 0)
{
// compute on the fly PVT solution
if ((d_sample_counter % d_output_rate_ms) == 0)
{
bool pvt_result;
pvt_result = d_ls_pvt->get_PVT(gnss_observables_map, d_rx_time, d_flag_averaging);
if (pvt_result == true)
{
// correct the observable to account for the receiver clock offset
for (std::map<int,Gnss_Synchro>::iterator it = gnss_observables_map.begin(); it != gnss_observables_map.end(); ++it)
{
it->second.Pseudorange_m = it->second.Pseudorange_m - d_ls_pvt->d_rx_dt_s * GPS_C_m_s;
}
if(first_fix == true)
{
std::cout << "First position fix at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
<< " UTC is Lat = " << d_ls_pvt->d_latitude_d << " [deg], Long = " << d_ls_pvt->d_longitude_d
<< " [deg], Height= " << d_ls_pvt->d_height_m << " [m]" << std::endl;
ttff_msgbuf ttff;
ttff.mtype = 1;
ttff.ttff = d_sample_counter;
send_sys_v_ttff_msg(ttff);
first_fix = false;
}
d_kml_printer->print_position(d_ls_pvt, d_flag_averaging);
d_geojson_printer->print_position(d_ls_pvt, d_flag_averaging);
d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging);
if (!b_rinex_header_written)
{
std::map<int,Gps_Ephemeris>::iterator gps_ephemeris_iter;
gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.begin();
if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.end())
{
rp->rinex_obs_header(rp->obsFile, gps_ephemeris_iter->second, d_rx_time);
rp->rinex_nav_header(rp->navFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model);
b_rinex_header_written = true; // do not write header anymore
}
}
if(b_rinex_header_written)
{
// Limit the RINEX navigation output rate to 1/6 seg
// Notice that d_sample_counter period is 1ms (for GPS correlators)
if ((d_sample_counter - d_last_sample_nav_output) >= 6000)
{
rp->log_rinex_nav(rp->navFile, d_ls_pvt->gps_ephemeris_map);
d_last_sample_nav_output = d_sample_counter;
}
std::map<int,Gps_Ephemeris>::iterator gps_ephemeris_iter;
gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.begin();
if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.end())
{
rp->log_rinex_obs(rp->obsFile, gps_ephemeris_iter->second, d_rx_time, gnss_observables_map);
}
if (!b_rinex_header_updated && (d_ls_pvt->gps_utc_model.d_A0 != 0))
{
rp->update_obs_header(rp->obsFile, d_ls_pvt->gps_utc_model);
rp->update_nav_header(rp->navFile, d_ls_pvt->gps_utc_model, d_ls_pvt->gps_iono);
b_rinex_header_updated = true;
}
}
if(b_rtcm_writing_started)
{
if((d_sample_counter % d_rtcm_MT1019_rate_ms) == 0)
{
for(std::map<int,Gps_Ephemeris>::iterator gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.begin(); gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.end(); gps_ephemeris_iter++ )
{
d_rtcm_printer->Print_Rtcm_MT1019(gps_ephemeris_iter->second);
}
}
if((d_sample_counter % d_rtcm_MSM_rate_ms) == 0)
{
std::map<int,Gps_Ephemeris>::iterator gps_ephemeris_iter;
gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.begin();
if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.end())
{
d_rtcm_printer->Print_Rtcm_MSM(7, gps_ephemeris_iter->second, {}, {}, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
}
}
if(!b_rtcm_writing_started) // the first time
{
for(std::map<int,Gps_Ephemeris>::iterator gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.begin(); gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.end(); gps_ephemeris_iter++ )
{
d_rtcm_printer->Print_Rtcm_MT1019(gps_ephemeris_iter->second);
}
std::map<int,Gps_Ephemeris>::iterator gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.begin();
if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.end())
{
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;
}
}
}
// DEBUG MESSAGE: Display position in console output
if (((d_sample_counter % d_display_rate_ms) == 0) and d_ls_pvt->b_valid_position == true)
{
std::cout << "Position at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
<< " UTC is Lat = " << d_ls_pvt->d_latitude_d << " [deg], Long = " << d_ls_pvt->d_longitude_d
<< " [deg], Height= " << d_ls_pvt->d_height_m << " [m]" << std::endl;
LOG(INFO) << "Position at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
<< " UTC is Lat = " << d_ls_pvt->d_latitude_d << " [deg], Long = " << d_ls_pvt->d_longitude_d
<< " [deg], Height= " << d_ls_pvt->d_height_m << " [m]";
LOG(INFO) << "Dilution of Precision at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
<< " is HDOP = " << d_ls_pvt->d_HDOP << " VDOP = "
<< d_ls_pvt->d_VDOP <<" TDOP = " << d_ls_pvt->d_TDOP << " GDOP = " << d_ls_pvt->d_GDOP;
}
// MULTIPLEXED FILE RECORDING - Record results to file
if(d_dump == true)
{
try
{
double tmp_double;
for (unsigned int i = 0; i < d_nchannels ; i++)
{
tmp_double = in[i][0].Pseudorange_m;
d_dump_file.write((char*)&tmp_double, sizeof(double));
tmp_double = 0;
d_dump_file.write((char*)&tmp_double, sizeof(double));
d_dump_file.write((char*)&d_rx_time, sizeof(double));
}
}
catch (const std::ifstream::failure & e)
{
LOG(WARNING) << "Exception writing observables dump file " << e.what();
}
}
}
consume_each(1); //one by one
return 1;
}

View File

@ -1,170 +0,0 @@
/*!
* \file gps_l1_ca_pvt_cc.h
* \brief Interface of a Position Velocity and Time computation block for GPS L1 C/A
* \author Javier Arribas, 2011. jarribas(at)cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GPS_L1_CA_PVT_CC_H
#define GNSS_SDR_GPS_L1_CA_PVT_CC_H
#include <fstream>
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <gnuradio/block.h>
#include "nmea_printer.h"
#include "kml_printer.h"
#include "rinex_printer.h"
#include "geojson_printer.h"
#include "rtcm_printer.h"
#include "gps_l1_ca_ls_pvt.h"
class gps_l1_ca_pvt_cc;
typedef boost::shared_ptr<gps_l1_ca_pvt_cc> gps_l1_ca_pvt_cc_sptr;
gps_l1_ca_pvt_cc_sptr gps_l1_ca_make_pvt_cc(unsigned int n_channels,
bool dump,
std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname,
int rinex_version
);
/*!
* \brief This class implements a block that computes the PVT solution
*/
class gps_l1_ca_pvt_cc : public gr::block
{
private:
friend gps_l1_ca_pvt_cc_sptr gps_l1_ca_make_pvt_cc(unsigned int nchannels,
bool dump,
std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname,
int rinex_version);
gps_l1_ca_pvt_cc(unsigned int nchannels,
bool dump,
std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname,
int rinex_version);
void msg_handler_telemetry(pmt::pmt_t msg);
bool d_dump;
bool b_rinex_header_written;
bool b_rinex_sbs_header_written;
bool b_rinex_header_updated;
bool b_rtcm_writing_started;
unsigned short d_rtcm_tcp_port;
unsigned short d_rtcm_station_id;
int d_rtcm_MT1019_rate_ms;
int d_rtcm_MSM_rate_ms;
void print_receiver_status(Gnss_Synchro** channels_synchronization_data);
int d_last_status_print_seg; //for status printer
unsigned int d_nchannels;
std::string d_dump_filename;
std::ofstream d_dump_file;
int d_averaging_depth;
bool d_flag_averaging;
int d_output_rate_ms;
int d_display_rate_ms;
long unsigned int d_sample_counter;
long unsigned int d_last_sample_nav_output;
std::shared_ptr<Rinex_Printer> rp;
std::shared_ptr<Kml_Printer> d_kml_printer;
std::shared_ptr<Nmea_Printer> d_nmea_printer;
std::shared_ptr<GeoJSON_Printer> d_geojson_printer;
std::shared_ptr<Rtcm_Printer> d_rtcm_printer;
double d_rx_time;
std::shared_ptr<gps_l1_ca_ls_pvt> d_ls_pvt;
std::map<int,Gnss_Synchro> gnss_observables_map;
bool first_fix;
key_t sysv_msg_key;
int sysv_msqid;
typedef struct {
long mtype;//required by sys v message
double ttff;
} ttff_msgbuf;
bool send_sys_v_ttff_msg(ttff_msgbuf ttff);
public:
/*!
* \brief Get latest set of GPS L1 ephemeris from PVT block
*
* It is used to save the assistance data at the receiver shutdown
*/
std::map<int,Gps_Ephemeris> get_GPS_L1_ephemeris_map();
~gps_l1_ca_pvt_cc (); //!< Default destructor
int general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); //!< PVT Signal Processing
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*!
* \file hybrid_pvt_cc.h
* \brief Interface of a Position Velocity and Time computation block for Galileo E1
* \author Javier Arribas, 2013. jarribas(at)cttc.es
* \file rtklib_pvt_cc.h
* \brief Interface of a Position Velocity and Time computation block
* \author Javier Arribas, 2017. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
@ -28,85 +28,70 @@
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_HYBRID_PVT_CC_H
#define GNSS_SDR_HYBRID_PVT_CC_H
#ifndef GNSS_SDR_RTKLIB_PVT_CC_H
#define GNSS_SDR_RTKLIB_PVT_CC_H
#include <ctime>
#include <fstream>
#include <utility>
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <gnuradio/block.h>
#include <gnuradio/sync_block.h>
#include "nmea_printer.h"
#include "kml_printer.h"
#include "geojson_printer.h"
#include "rinex_printer.h"
#include "rtcm_printer.h"
#include "hybrid_ls_pvt.h"
#include "rtklib_solver.h"
class hybrid_pvt_cc;
class rtklib_pvt_cc;
typedef boost::shared_ptr<hybrid_pvt_cc> hybrid_pvt_cc_sptr;
typedef boost::shared_ptr<rtklib_pvt_cc> rtklib_pvt_cc_sptr;
hybrid_pvt_cc_sptr hybrid_make_pvt_cc(unsigned int n_channels,
rtklib_pvt_cc_sptr rtklib_make_pvt_cc(unsigned int n_channels,
bool dump,
std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
int rinex_version,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname,
const unsigned int type_of_receiver);
const unsigned int type_of_receiver,
rtk_t & rtk);
/*!
* \brief This class implements a block that computes the PVT solution with Galileo E1 signals
*/
class hybrid_pvt_cc : public gr::block
class rtklib_pvt_cc : public gr::sync_block
{
private:
friend hybrid_pvt_cc_sptr hybrid_make_pvt_cc(unsigned int nchannels,
friend rtklib_pvt_cc_sptr rtklib_make_pvt_cc(unsigned int nchannels,
bool dump,
std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
int rinex_version,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname,
const unsigned int type_of_receiver);
hybrid_pvt_cc(unsigned int nchannels,
bool dump, std::string dump_filename,
int averaging_depth,
bool flag_averaging,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname,
const unsigned int type_of_receiver);
const unsigned int type_of_receiver,
rtk_t & rtk);
void msg_handler_telemetry(pmt::pmt_t msg);
@ -120,18 +105,14 @@ private:
int d_rtcm_MT1097_rate_ms;
int d_rtcm_MSM_rate_ms;
void print_receiver_status(Gnss_Synchro** channels_synchronization_data);
int d_last_status_print_seg; //for status printer
unsigned int d_nchannels;
std::string d_dump_filename;
std::ofstream d_dump_file;
int d_averaging_depth;
bool d_flag_averaging;
int d_output_rate_ms;
int d_display_rate_ms;
long unsigned int d_sample_counter;
long unsigned int d_last_sample_nav_output;
std::shared_ptr<Rinex_Printer> rp;
std::shared_ptr<Kml_Printer> d_kml_dump;
@ -139,8 +120,16 @@ private:
std::shared_ptr<GeoJSON_Printer> d_geojson_printer;
std::shared_ptr<Rtcm_Printer> d_rtcm_printer;
double d_rx_time;
double d_TOW_at_curr_symbol_constellation;
std::shared_ptr<hybrid_ls_pvt> d_ls_pvt;
double last_pvt_display_T_rx_s;
double last_RTCM_1019_output_time;
double last_RTCM_1045_output_time;
double last_RTCM_1077_output_time;
double last_RTCM_1097_output_time;
double last_RTCM_MSM_output_time;
double last_RINEX_obs_output_time;
double last_RINEX_nav_output_time;
std::shared_ptr<rtklib_solver> d_ls_pvt;
std::map<int,Gnss_Synchro> gnss_observables_map;
bool observables_pairCompare_min(const std::pair<int,Gnss_Synchro>& a, const std::pair<int,Gnss_Synchro>& b);
@ -154,8 +143,27 @@ private:
double ttff;
} ttff_msgbuf;
bool send_sys_v_ttff_msg(ttff_msgbuf ttff);
struct timeval tv;
long long int begin;
public:
rtklib_pvt_cc(unsigned int nchannels,
bool dump, std::string dump_filename,
int output_rate_ms,
int display_rate_ms,
bool flag_nmea_tty_port,
std::string nmea_dump_filename,
std::string nmea_dump_devname,
int rinex_version,
bool flag_rtcm_server,
bool flag_rtcm_tty_port,
unsigned short rtcm_tcp_port,
unsigned short rtcm_station_id,
std::map<int,int> rtcm_msg_rate_ms,
std::string rtcm_dump_devname,
const unsigned int type_of_receiver,
rtk_t & rtk);
/*!
* \brief Get latest set of GPS L1 ephemeris from PVT block
*
@ -163,10 +171,10 @@ public:
*/
std::map<int,Gps_Ephemeris> get_GPS_L1_ephemeris_map();
~hybrid_pvt_cc (); //!< Default destructor
~rtklib_pvt_cc(); //!< Default destructor
int general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); //!< PVT Signal Processing
int work (int noutput_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items); //!< PVT Signal Processing
};
#endif

View File

@ -21,14 +21,13 @@ add_definitions( -DGNSS_SDR_VERSION="${VERSION}" )
set(PVT_LIB_SOURCES
pvt_solution.cc
ls_pvt.cc
gps_l1_ca_ls_pvt.cc
galileo_e1_ls_pvt.cc
hybrid_ls_pvt.cc
kml_printer.cc
rinex_printer.cc
nmea_printer.cc
rtcm_printer.cc
geojson_printer.cc
rtklib_solver.cc
)
include_directories(
@ -37,6 +36,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/core/interfaces
${CMAKE_SOURCE_DIR}/src/core/receiver
${CMAKE_SOURCE_DIR}/src/algorithms/PVT/adapters
${CMAKE_SOURCE_DIR}/src/algorithms/libs/rtklib
${Boost_INCLUDE_DIRS}
${ARMADILLO_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS}
@ -46,5 +46,17 @@ file(GLOB PVT_LIB_HEADERS "*.h")
list(SORT PVT_LIB_HEADERS)
add_library(pvt_lib ${PVT_LIB_SOURCES} ${PVT_LIB_HEADERS})
source_group(Headers FILES ${PVT_LIB_HEADERS})
add_dependencies(pvt_lib armadillo-${armadillo_RELEASE} glog-${glog_RELEASE})
target_link_libraries(pvt_lib ${Boost_LIBRARIES} ${GFlags_LIBS} ${GLOG_LIBRARIES} ${ARMADILLO_LIBRARIES})
add_dependencies(pvt_lib rtklib_lib armadillo-${armadillo_RELEASE} glog-${glog_RELEASE})
target_link_libraries(
pvt_lib
rtklib_lib
${Boost_LIBRARIES}
${GFlags_LIBS}
${GLOG_LIBRARIES}
${ARMADILLO_LIBRARIES}
${BLAS}
${LAPACK}
)

View File

@ -1,257 +0,0 @@
/*!
* \file galileo_e1_ls_pvt.cc
* \brief Implementation of a Least Squares Position, Velocity, and Time
* (PVT) solver, based on K.Borre's Matlab receiver.
* \author Javier Arribas, 2011. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "galileo_e1_ls_pvt.h"
#include <glog/logging.h>
#include "Galileo_E1.h"
using google::LogMessage;
galileo_e1_ls_pvt::galileo_e1_ls_pvt(int nchannels, std::string dump_filename, bool flag_dump_to_file) : Ls_Pvt()
{
// init empty ephemeris for all the available GNSS channels
d_nchannels = nchannels;
d_ephemeris = new Galileo_Navigation_Message[nchannels];
d_dump_filename = dump_filename;
d_flag_dump_enabled = flag_dump_to_file;
d_galileo_current_time = 0;
d_flag_averaging = false;
// ############# ENABLE DATA FILE LOG #################
if (d_flag_dump_enabled == true)
{
if (d_dump_file.is_open() == false)
{
try
{
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) << "PVT lib dump enabled Log file: " << d_dump_filename.c_str();
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "Exception opening PVT lib dump file " << e.what();
}
}
}
}
galileo_e1_ls_pvt::~galileo_e1_ls_pvt()
{
d_dump_file.close();
delete[] d_ephemeris;
}
bool galileo_e1_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, double galileo_current_time, bool flag_averaging)
{
std::map<int,Gnss_Synchro>::iterator gnss_pseudoranges_iter;
std::map<int,Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
arma::vec W; // channels weight vector
arma::vec obs; // pseudoranges observation vector
arma::mat satpos; // satellite positions matrix
int Galileo_week_number = 0;
double utc = 0.0;
double GST = 0.0;
double TX_time_corrected_s = 0.0;
double SV_clock_bias_s = 0.0;
d_flag_averaging = flag_averaging;
// ********************************************************************************
// ****** PREPARE THE LEAST SQUARES DATA (SV POSITIONS MATRIX AND OBS VECTORS) ****
// ********************************************************************************
int valid_obs = 0; //valid observations counter
for(gnss_pseudoranges_iter = gnss_pseudoranges_map.begin();
gnss_pseudoranges_iter != gnss_pseudoranges_map.end();
gnss_pseudoranges_iter++)
{
// 1- find the ephemeris for the current SV observation. The SV PRN ID is the map key
galileo_ephemeris_iter = galileo_ephemeris_map.find(gnss_pseudoranges_iter->first);
if (galileo_ephemeris_iter != galileo_ephemeris_map.end())
{
/*!
* \todo Place here the satellite CN0 (power level, or weight factor)
*/
W.resize(valid_obs + 1, 1);
W(valid_obs) = 1;
// COMMON RX TIME PVT ALGORITHM
double Rx_time = galileo_current_time;
double Tx_time = Rx_time - gnss_pseudoranges_iter->second.Pseudorange_m / GALILEO_C_m_s;
// 2- compute the clock drift using the clock model (broadcast) for this SV, including relativistic effect
SV_clock_bias_s = galileo_ephemeris_iter->second.sv_clock_drift(Tx_time);
// 3- compute the current ECEF position for this SV using corrected TX time
TX_time_corrected_s = Tx_time - SV_clock_bias_s;
galileo_ephemeris_iter->second.satellitePosition(TX_time_corrected_s);
//store satellite positions in a matrix
satpos.resize(3, valid_obs + 1);
satpos(0, valid_obs) = galileo_ephemeris_iter->second.d_satpos_X;
satpos(1, valid_obs) = galileo_ephemeris_iter->second.d_satpos_Y;
satpos(2, valid_obs) = galileo_ephemeris_iter->second.d_satpos_Z;
// 4- fill the observations vector with the corrected pseudoranges
obs.resize(valid_obs + 1, 1);
obs(valid_obs) = gnss_pseudoranges_iter->second.Pseudorange_m + SV_clock_bias_s * GALILEO_C_m_s - d_rx_dt_s * GALILEO_C_m_s;
d_visible_satellites_IDs[valid_obs] = galileo_ephemeris_iter->second.i_satellite_PRN;
d_visible_satellites_CN0_dB[valid_obs] = gnss_pseudoranges_iter->second.CN0_dB_hz;
Galileo_week_number = galileo_ephemeris_iter->second.WN_5; //for GST
GST = galileo_ephemeris_map.find(gnss_pseudoranges_iter->first)->second.Galileo_System_Time(Galileo_week_number, galileo_current_time);
// SV ECEF DEBUG OUTPUT
DLOG(INFO) << "ECEF satellite SV ID=" << galileo_ephemeris_iter->second.i_satellite_PRN
<< " X=" << galileo_ephemeris_iter->second.d_satpos_X
<< " [m] Y=" << galileo_ephemeris_iter->second.d_satpos_Y
<< " [m] Z=" << galileo_ephemeris_iter->second.d_satpos_Z
<< " [m] PR_obs=" << obs(valid_obs) << " [m]";
valid_obs++;
}
else // the ephemeris are not available for this SV
{
DLOG(INFO) << "No ephemeris data for SV "<< gnss_pseudoranges_iter->first;
}
}
// ********************************************************************************
// ****** SOLVE LEAST SQUARES******************************************************
// ********************************************************************************
d_valid_observations = valid_obs;
LOG(INFO) << "Galileo PVT: valid observations=" << valid_obs;
if (valid_obs >= 4)
{
arma::vec rx_position_and_time;
DLOG(INFO) << "satpos=" << satpos;
DLOG(INFO) << "obs="<< obs;
DLOG(INFO) << "W=" << W;
try
{
// check if this is the initial position computation
if (d_rx_dt_s == 0)
{
// execute Bancroft's algorithm to estimate initial receiver position and time
DLOG(INFO) << " Executing Bancroft algorithm...";
rx_position_and_time = bancroftPos(satpos.t(), obs);
d_rx_pos = rx_position_and_time.rows(0, 2); // save ECEF position for the next iteration
d_rx_dt_s = rx_position_and_time(3) / GALILEO_C_m_s; // save time for the next iteration [meters]->[seconds]
}
// Execute WLS using previous position as the initialization point
rx_position_and_time = leastSquarePos(satpos, obs, W);
d_rx_pos = rx_position_and_time.rows(0, 2); // save ECEF position for the next iteration
d_rx_dt_s += rx_position_and_time(3) / GALILEO_C_m_s; // accumulate the rx time error for the next iteration [meters]->[seconds]
// Compute Gregorian time
utc = galileo_utc_model.GST_to_UTC_time(GST, Galileo_week_number);
// get time string Gregorian calendar
boost::posix_time::time_duration t = boost::posix_time::seconds(utc);
// 22 August 1999 00:00 last Galileo start GST epoch (ICD sec 5.1.2)
boost::posix_time::ptime p_time(boost::gregorian::date(1999, 8, 22), t);
d_position_UTC_time = p_time;
DLOG(INFO) << "Galileo Position at TOW=" << galileo_current_time << " in ECEF (X,Y,Z) = " << rx_position_and_time;
cart2geo(static_cast<double>(rx_position_and_time(0)), static_cast<double>(rx_position_and_time(1)), static_cast<double>(rx_position_and_time(2)), 4);
d_rx_dt_s = rx_position_and_time(3)/GALILEO_C_m_s; // Convert RX time offset from meters to seconds
DLOG(INFO) << "Galileo Position at " << boost::posix_time::to_simple_string(p_time)
<< " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
<< " [deg], Height= " << d_height_m << " [m]" << " RX time offset= " << d_rx_dt_s << " [s]";
// ###### Compute DOPs ########
compute_DOP();
// ######## LOG FILE #########
if(d_flag_dump_enabled == true)
{
// MULTIPLEXED FILE RECORDING - Record results to file
try
{
double tmp_double;
// PVT GPS time
tmp_double = galileo_current_time;
d_dump_file.write((char*)&tmp_double, sizeof(double));
// ECEF User Position East [m]
tmp_double = rx_position_and_time(0);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// ECEF User Position North [m]
tmp_double = rx_position_and_time(1);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// ECEF User Position Up [m]
tmp_double = rx_position_and_time(2);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// User clock offset [s]
tmp_double = rx_position_and_time(3);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// GEO user position Latitude [deg]
tmp_double = d_latitude_d;
d_dump_file.write((char*)&tmp_double, sizeof(double));
// GEO user position Longitude [deg]
tmp_double = d_longitude_d;
d_dump_file.write((char*)&tmp_double, sizeof(double));
// GEO user position Height [m]
tmp_double = d_height_m;
d_dump_file.write((char*)&tmp_double, sizeof(double));
}
catch (const std::ifstream::failure& e)
{
LOG(WARNING) << "Exception writing PVT LS dump file "<< e.what();
}
}
// MOVING AVERAGE PVT
galileo_e1_ls_pvt::pos_averaging(flag_averaging);
}
catch(const std::exception & e)
{
d_rx_dt_s = 0; //reset rx time estimation
LOG(WARNING) << "Problem with the solver, invalid solution!" << e.what();
b_valid_position = false;
}
}
else
{
b_valid_position = false;
}
return b_valid_position;
}

View File

@ -1,74 +0,0 @@
/*!
* \file galileo_e1_ls_pvt.h
* \brief Interface of a Least Squares Position, Velocity, and Time (PVT)
* solver, based on K.Borre's Matlab receiver.
* \author Javier Arribas, 2011. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GALILEO_E1_LS_PVT_H_
#define GNSS_SDR_GALILEO_E1_LS_PVT_H_
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include "ls_pvt.h"
#include "galileo_navigation_message.h"
#include "gnss_synchro.h"
#include "galileo_ephemeris.h"
#include "galileo_utc_model.h"
/*!
* \brief This class implements a simple PVT Least Squares solution
*/
class galileo_e1_ls_pvt : public Ls_Pvt
{
public:
galileo_e1_ls_pvt(int nchannels,std::string dump_filename, bool flag_dump_to_file);
~galileo_e1_ls_pvt();
bool get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, double galileo_current_time, bool flag_averaging);
int d_nchannels; //!< Number of available channels for positioning
Galileo_Navigation_Message* d_ephemeris;
std::map<int,Galileo_Ephemeris> galileo_ephemeris_map; //!< Map storing new Galileo_Ephemeris
Galileo_Utc_Model galileo_utc_model;
Galileo_Iono galileo_iono;
Galileo_Almanac galileo_almanac;
double d_galileo_current_time;
bool d_flag_dump_enabled;
bool d_flag_averaging;
std::string d_dump_filename;
std::ofstream d_dump_file;
};
#endif

View File

@ -1,270 +0,0 @@
/*!
* \file gps_l1_ca_ls_pvt.cc
* \brief Implementation of a Least Squares Position, Velocity, and Time
* (PVT) solver, based on K.Borre's Matlab receiver.
* \author Javier Arribas, 2011. jarribas(at)cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "gps_l1_ca_ls_pvt.h"
#include <gflags/gflags.h>
#include <glog/logging.h>
#include "GPS_L1_CA.h"
#include "GPS_L2C.h"
using google::LogMessage;
gps_l1_ca_ls_pvt::gps_l1_ca_ls_pvt(int nchannels, std::string dump_filename, bool flag_dump_to_file) : Ls_Pvt()
{
// init empty ephemeris for all the available GNSS channels
d_nchannels = nchannels;
d_ephemeris = new Gps_Navigation_Message[nchannels];
d_dump_filename = dump_filename;
d_flag_dump_enabled = flag_dump_to_file;
d_flag_averaging = false;
d_GPS_current_time = 0;
// ############# ENABLE DATA FILE LOG #################
if (d_flag_dump_enabled == true)
{
if (d_dump_file.is_open() == false)
{
try
{
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) << "PVT lib dump enabled Log file: " << d_dump_filename.c_str();
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "Exception opening PVT lib dump file " << e.what();
}
}
}
}
gps_l1_ca_ls_pvt::~gps_l1_ca_ls_pvt()
{
d_dump_file.close();
delete[] d_ephemeris;
}
bool gps_l1_ca_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, double GPS_current_time, bool flag_averaging)
{
std::map<int,Gnss_Synchro>::iterator gnss_pseudoranges_iter;
std::map<int,Gps_Ephemeris>::iterator gps_ephemeris_iter;
arma::vec W; // channels weight vector
arma::vec obs; // pseudoranges observation vector
arma::mat satpos; // satellite positions matrix
int GPS_week = 0;
double utc = 0.0;
double TX_time_corrected_s;
double SV_clock_bias_s = 0.0;
d_flag_averaging = flag_averaging;
// ********************************************************************************
// ****** PREPARE THE LEAST SQUARES DATA (SV POSITIONS MATRIX AND OBS VECTORS) ****
// ********************************************************************************
int valid_obs = 0; //valid observations counter
for(gnss_pseudoranges_iter = gnss_pseudoranges_map.begin();
gnss_pseudoranges_iter != gnss_pseudoranges_map.end();
gnss_pseudoranges_iter++)
{
// 1- find the ephemeris for the current SV observation. The SV PRN ID is the map key
gps_ephemeris_iter = gps_ephemeris_map.find(gnss_pseudoranges_iter->first);
if (gps_ephemeris_iter != gps_ephemeris_map.end())
{
/*!
* \todo Place here the satellite CN0 (power level, or weight factor)
*/
W.resize(valid_obs + 1, 1);
W(valid_obs) = 1;
// COMMON RX TIME PVT ALGORITHM MODIFICATION (Like RINEX files)
// first estimate of transmit time
double Rx_time = GPS_current_time;
double Tx_time = Rx_time - gnss_pseudoranges_iter->second.Pseudorange_m / GPS_C_m_s;
// 2- compute the clock drift using the clock model (broadcast) for this SV, not including relativistic effect
SV_clock_bias_s = gps_ephemeris_iter->second.sv_clock_drift(Tx_time); //- gps_ephemeris_iter->second.d_TGD;
// 3- compute the current ECEF position for this SV using corrected TX time and obtain clock bias including relativistic effect
TX_time_corrected_s = Tx_time - SV_clock_bias_s;
double dtr = gps_ephemeris_iter->second.satellitePosition(TX_time_corrected_s);
//store satellite positions in a matrix
satpos.resize(3, valid_obs + 1);
satpos(0, valid_obs) = gps_ephemeris_iter->second.d_satpos_X;
satpos(1, valid_obs) = gps_ephemeris_iter->second.d_satpos_Y;
satpos(2, valid_obs) = gps_ephemeris_iter->second.d_satpos_Z;
// 4- fill the observations vector with the corrected pseudoranges
// compute code bias: TGD for single frequency
// See IS-GPS-200E section 20.3.3.3.3.2
double sqrt_Gamma=GPS_L1_FREQ_HZ/GPS_L2_FREQ_HZ;
double Gamma=sqrt_Gamma*sqrt_Gamma;
double P1_P2=(1.0-Gamma)*(gps_ephemeris_iter->second.d_TGD* GPS_C_m_s);
double Code_bias_m= P1_P2/(1.0-Gamma);
obs.resize(valid_obs + 1, 1);
obs(valid_obs) = gnss_pseudoranges_iter->second.Pseudorange_m + dtr * GPS_C_m_s-Code_bias_m-d_rx_dt_s * GPS_C_m_s;
d_visible_satellites_IDs[valid_obs] = gps_ephemeris_iter->second.i_satellite_PRN;
d_visible_satellites_CN0_dB[valid_obs] = gnss_pseudoranges_iter->second.CN0_dB_hz;
// SV ECEF DEBUG OUTPUT
DLOG(INFO) << "(new)ECEF satellite SV ID=" << gps_ephemeris_iter->second.i_satellite_PRN
<< " X=" << gps_ephemeris_iter->second.d_satpos_X
<< " [m] Y=" << gps_ephemeris_iter->second.d_satpos_Y
<< " [m] Z=" << gps_ephemeris_iter->second.d_satpos_Z
<< " [m] PR_obs=" << obs(valid_obs) << " [m]";
valid_obs++;
// compute the UTC time for this SV (just to print the associated UTC timestamp)
GPS_week = gps_ephemeris_iter->second.i_GPS_week;
utc = gps_utc_model.utc_time(TX_time_corrected_s, GPS_week);
}
else // the ephemeris are not available for this SV
{
DLOG(INFO) << "No ephemeris data for SV " << gnss_pseudoranges_iter->first;
}
}
// ********************************************************************************
// ****** SOLVE LEAST SQUARES******************************************************
// ********************************************************************************
d_valid_observations = valid_obs;
DLOG(INFO) << "(new)PVT: valid observations=" << valid_obs;
if (valid_obs >= 4)
{
arma::vec rx_position_and_time;
DLOG(INFO) << "satpos=" << satpos;
DLOG(INFO) << "obs=" << obs;
DLOG(INFO) << "W=" << W;
try
{
// check if this is the initial position computation
if (d_rx_dt_s == 0)
{
// execute Bancroft's algorithm to estimate initial receiver position and time
DLOG(INFO) << " Executing Bancroft algorithm...";
rx_position_and_time = bancroftPos(satpos.t(), obs);
d_rx_pos = rx_position_and_time.rows(0, 2); // save ECEF position for the next iteration
d_rx_dt_s = rx_position_and_time(3) / GPS_C_m_s; // save time for the next iteration [meters]->[seconds]
}
// Execute WLS using previous position as the initialization point
rx_position_and_time = leastSquarePos(satpos, obs, W);
d_rx_pos = rx_position_and_time.rows(0, 2); // save ECEF position for the next iteration
d_rx_dt_s += rx_position_and_time(3) / GPS_C_m_s; // accumulate the rx time error for the next iteration [meters]->[seconds]
DLOG(INFO) << "(new)Position at TOW=" << GPS_current_time << " in ECEF (X,Y,Z,t[meters]) = " << rx_position_and_time;
DLOG(INFO) << "Accumulated rx clock error=" << d_rx_dt_s << " clock error for this iteration=" << rx_position_and_time(3) / GPS_C_m_s << " [s]";
cart2geo(static_cast<double>(rx_position_and_time(0)), static_cast<double>(rx_position_and_time(1)), static_cast<double>(rx_position_and_time(2)), 4);
// Compute UTC time and print PVT solution
double secondsperweek = 604800.0; // number of seconds in one week (7*24*60*60)
boost::posix_time::time_duration t = boost::posix_time::seconds(utc + secondsperweek * static_cast<double>(GPS_week));
// 22 August 1999 last GPS time roll over
boost::posix_time::ptime p_time(boost::gregorian::date(1999, 8, 22), t);
d_position_UTC_time = p_time;
DLOG(INFO) << "Position at " << boost::posix_time::to_simple_string(p_time)
<< " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
<< " [deg], Height= " << d_height_m << " [m]" << " RX time offset= " << d_rx_dt_s << " [s]";
// ###### Compute DOPs ########
compute_DOP();
// ######## LOG FILE #########
if(d_flag_dump_enabled == true)
{
// MULTIPLEXED FILE RECORDING - Record results to file
try
{
double tmp_double;
// PVT GPS time
tmp_double = GPS_current_time;
d_dump_file.write((char*)&tmp_double, sizeof(double));
// ECEF User Position East [m]
tmp_double = d_rx_pos(0);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// ECEF User Position North [m]
tmp_double = d_rx_pos(1);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// ECEF User Position Up [m]
tmp_double = d_rx_pos(2);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// User clock offset [s]
tmp_double = d_rx_dt_s;
d_dump_file.write((char*)&tmp_double, sizeof(double));
// GEO user position Latitude [deg]
tmp_double = d_latitude_d;
d_dump_file.write((char*)&tmp_double, sizeof(double));
// GEO user position Longitude [deg]
tmp_double = d_longitude_d;
d_dump_file.write((char*)&tmp_double, sizeof(double));
// GEO user position Height [m]
tmp_double = d_height_m;
d_dump_file.write((char*)&tmp_double, sizeof(double));
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "Exception writing PVT LS dump file " << e.what();
}
}
// MOVING AVERAGE PVT
pos_averaging(flag_averaging);
}
catch(const std::exception & e)
{
d_rx_dt_s = 0; //reset rx time estimation
LOG(WARNING) << "Problem with the solver, invalid solution!" << e.what();
LOG(WARNING) << "satpos=" << satpos;
LOG(WARNING) << "obs=" << obs;
LOG(WARNING) << "W=" << W;
b_valid_position = false;
}
}
else
{
b_valid_position = false;
}
return b_valid_position;
}

View File

@ -1,81 +0,0 @@
/*!
* \file gps_l1_ca_ls_pvt.h
* \brief Interface of a Least Squares Position, Velocity, and Time (PVT)
* solver for GPS L1 C/A, based on K.Borre's Matlab receiver.
* \author Javier Arribas, 2011. jarribas(at)cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GPS_L1_CA_LS_PVT_H_
#define GNSS_SDR_GPS_L1_CA_LS_PVT_H_
#include <fstream>
#include <map>
#include <string>
#include "ls_pvt.h"
#include "GPS_L1_CA.h"
#include "gnss_synchro.h"
#include "gps_ephemeris.h"
#include "gps_navigation_message.h"
#include "gps_utc_model.h"
#include "sbas_telemetry_data.h"
#include "sbas_ionospheric_correction.h"
#include "sbas_satellite_correction.h"
#include "sbas_ephemeris.h"
/*!
* \brief This class implements a simple PVT Least Squares solution for GPS L1 C/A signals
*/
class gps_l1_ca_ls_pvt : public Ls_Pvt
{
public:
gps_l1_ca_ls_pvt(int nchannels, std::string dump_filename, bool flag_dump_to_file);
~gps_l1_ca_ls_pvt();
bool get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, double GPS_current_time, bool flag_averaging);
int d_nchannels; //!< Number of available channels for positioning
Gps_Navigation_Message* d_ephemeris;
// new ephemeris storage
std::map<int,Gps_Ephemeris> gps_ephemeris_map; //!< Map storing new Gps_Ephemeris
Gps_Utc_Model gps_utc_model;
Gps_Iono gps_iono;
Sbas_Ionosphere_Correction sbas_iono;
std::map<int,Sbas_Satellite_Correction> sbas_sat_corr_map;
std::map<int,Sbas_Ephemeris> sbas_ephemeris_map;
double d_GPS_current_time;
bool d_flag_dump_enabled;
bool d_flag_averaging;
std::string d_dump_filename;
std::ofstream d_dump_file;
};
#endif

View File

@ -41,18 +41,20 @@
#include "gps_navigation_message.h"
#include "gps_cnav_navigation_message.h"
#include "gnss_synchro.h"
#include "rtklib_rtkcmn.h"
/*!
* \brief This class implements a simple PVT Least Squares solution
*/
class hybrid_ls_pvt : public Ls_Pvt
{
private:
public:
hybrid_ls_pvt(int nchannels,std::string dump_filename, bool flag_dump_to_file);
~hybrid_ls_pvt();
bool get_PVT(std::map<int,Gnss_Synchro> gnss_observables_map, double hybrid_current_time, bool flag_averaging);
bool get_PVT(std::map<int,Gnss_Synchro> gnss_observables_map, double Rx_time, bool flag_averaging);
int d_nchannels; //!< Number of available channels for positioning
std::map<int,Galileo_Ephemeris> galileo_ephemeris_map; //!< Map storing new Galileo_Ephemeris

View File

@ -187,6 +187,7 @@ Rinex_Printer::Rinex_Printer(int conf_version)
}
numberTypesObservations = 4; // Number of available types of observable in the system
fake_cnav_iode = 1;
}
@ -1897,9 +1898,17 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map<int,Gps_CNAV
// -------- BROADCAST ORBIT - 1
line.clear();
line += std::string(5, ' ');
// If there is no IODE in CNAV, so we set it to zero
double my_zero = 0.0;
line += Rinex_Printer::doub2for(my_zero, 18, 2);
// If there is no IODE in CNAV, so we check if Toe in message Type 10, Toe in Message type 11 and Toc in message types 30-37.
// Whenever these three terms do not match, a data set cutover has occurred and new data must be collected.
// See IS-GPS-200H, p. 155
if ( !((gps_ephemeris_iter->second.d_Toe1 == gps_ephemeris_iter->second.d_Toe2) && (gps_ephemeris_iter->second.d_Toe1 == gps_ephemeris_iter->second.d_Toc)) ) // Toe1: Toe in message type 10, Toe2: Toe in message type 11
{
// Toe1: Toe in message type 10, Toe2: Toe in message type 11,
fake_cnav_iode = fake_cnav_iode + 1;
if(fake_cnav_iode == 240) fake_cnav_iode = 1;
}
line += Rinex_Printer::doub2for(fake_cnav_iode, 18, 2);
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(gps_ephemeris_iter->second.d_Crs, 18, 2);
line += std::string(1, ' ');
@ -1962,6 +1971,7 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map<int,Gps_CNAV
line += Rinex_Printer::doub2for(gps_ephemeris_iter->second.d_IDOT, 18, 2);
line += std::string(1, ' ');
// No data flag for L2 P code
double my_zero = 0.0;
line += Rinex_Printer::doub2for(my_zero, 18, 2);
line += std::string(1, ' ');
double GPS_week_continuous_number = static_cast<double>(gps_ephemeris_iter->second.i_GPS_week + 1024); // valid until April 7, 2019 (check http://www.colorado.edu/geography/gcraft/notes/gps/gpseow.htm)
@ -1981,8 +1991,8 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map<int,Gps_CNAV
line += std::string(1, ' ');
line += Rinex_Printer::doub2for(gps_ephemeris_iter->second.d_TGD, 18, 2);
line += std::string(1, ' ');
// no IODC in CNAV, so we set it to zero
line += Rinex_Printer::doub2for(my_zero, 18, 2);
// no IODC in CNAV, so we fake it (see above)
line += Rinex_Printer::doub2for(fake_cnav_iode, 18, 2);
Rinex_Printer::lengthCheck(line);
out << line << std::endl;
@ -4760,87 +4770,87 @@ void Rinex_Printer::to_date_time(int gps_week, int gps_tow, int &year, int &mont
}
void Rinex_Printer::log_rinex_sbs(std::fstream& out, const Sbas_Raw_Msg& sbs_message)
{
// line 1: PRN / EPOCH / RCVR
std::stringstream line1;
// SBAS PRN
line1 << sbs_message.get_prn();
line1 << " ";
// gps time of reception
int gps_week;
double gps_sec;
if(sbs_message.get_rx_time_obj().get_gps_time(gps_week, gps_sec))
{
int year;
int month;
int day;
int hour;
int minute;
int second;
double gps_sec_one_digit_precicion = round(gps_sec *10)/10; // to prevent rounding towards 60.0sec in the stream output
int gps_tow = trunc(gps_sec_one_digit_precicion);
double sub_sec = gps_sec_one_digit_precicion - double(gps_tow);
to_date_time(gps_week, gps_tow, year, month, day, hour, minute, second);
line1 << asFixWidthString(year, 2, '0') << " " << asFixWidthString(month, 2, '0') << " " << asFixWidthString(day, 2, '0') << " " << asFixWidthString(hour, 2, '0') << " " << asFixWidthString(minute, 2, '0') << " " << rightJustify(asString(double(second)+sub_sec,1),4,' ');
}
else
{
line1 << std::string(19, ' ');
}
line1 << " ";
// band
line1 << "L1";
line1 << " ";
// Length of data message (bytes)
line1 << asFixWidthString(sbs_message.get_msg().size(), 3, ' ');
line1 << " ";
// File-internal receiver index
line1 << " 0";
line1 << " ";
// Transmission System Identifier
line1 << "SBA";
line1 << std::string(35, ' ');
lengthCheck(line1.str());
out << line1.str() << std::endl;
// DATA RECORD - 1
std::stringstream line2;
line2 << " ";
// Message frame identifier
if (sbs_message.get_msg_type() < 10) line2 << " ";
line2 << sbs_message.get_msg_type();
line2 << std::string(4, ' ');
// First 18 bytes of message (hex)
std::vector<unsigned char> msg = sbs_message.get_msg();
for (size_t i = 0; i < 18 && i < msg.size(); ++i)
{
line2 << std::hex << std::setfill('0') << std::setw(2);
line2 << int(msg[i]) << " ";
}
line2 << std::string(19, ' ');
lengthCheck(line2.str());
out << line2.str() << std::endl;
// DATA RECORD - 2
std::stringstream line3;
line3 << std::string(7, ' ');
// Remaining bytes of message (hex)
for (size_t i = 18; i < 36 && i < msg.size(); ++i)
{
line3 << std::hex << std::setfill('0') << std::setw(2);
line3 << int(msg[i]) << " ";
}
line3 << std::string(31, ' ');
lengthCheck(line3.str());
out << line3.str() << std::endl;
}
//void Rinex_Printer::log_rinex_sbs(std::fstream& out, const Sbas_Raw_Msg& sbs_message)
//{
// // line 1: PRN / EPOCH / RCVR
// std::stringstream line1;
//
// // SBAS PRN
// line1 << sbs_message.get_prn();
// line1 << " ";
//
// // gps time of reception
// int gps_week;
// double gps_sec;
// if(sbs_message.get_rx_time_obj().get_gps_time(gps_week, gps_sec))
// {
// int year;
// int month;
// int day;
// int hour;
// int minute;
// int second;
//
// double gps_sec_one_digit_precicion = round(gps_sec *10)/10; // to prevent rounding towards 60.0sec in the stream output
// int gps_tow = trunc(gps_sec_one_digit_precicion);
// double sub_sec = gps_sec_one_digit_precicion - double(gps_tow);
//
// to_date_time(gps_week, gps_tow, year, month, day, hour, minute, second);
// line1 << asFixWidthString(year, 2, '0') << " " << asFixWidthString(month, 2, '0') << " " << asFixWidthString(day, 2, '0') << " " << asFixWidthString(hour, 2, '0') << " " << asFixWidthString(minute, 2, '0') << " " << rightJustify(asString(double(second)+sub_sec,1),4,' ');
// }
// else
// {
// line1 << std::string(19, ' ');
// }
// line1 << " ";
//
// // band
// line1 << "L1";
// line1 << " ";
//
// // Length of data message (bytes)
// line1 << asFixWidthString(sbs_message.get_msg().size(), 3, ' ');
// line1 << " ";
// // File-internal receiver index
// line1 << " 0";
// line1 << " ";
// // Transmission System Identifier
// line1 << "SBA";
// line1 << std::string(35, ' ');
// lengthCheck(line1.str());
// out << line1.str() << std::endl;
//
// // DATA RECORD - 1
// std::stringstream line2;
// line2 << " ";
// // Message frame identifier
// if (sbs_message.get_msg_type() < 10) line2 << " ";
// line2 << sbs_message.get_msg_type();
// line2 << std::string(4, ' ');
// // First 18 bytes of message (hex)
// std::vector<unsigned char> msg = sbs_message.get_msg();
// for (size_t i = 0; i < 18 && i < msg.size(); ++i)
// {
// line2 << std::hex << std::setfill('0') << std::setw(2);
// line2 << int(msg[i]) << " ";
// }
// line2 << std::string(19, ' ');
// lengthCheck(line2.str());
// out << line2.str() << std::endl;
//
// // DATA RECORD - 2
// std::stringstream line3;
// line3 << std::string(7, ' ');
// // Remaining bytes of message (hex)
// for (size_t i = 18; i < 36 && i < msg.size(); ++i)
// {
// line3 << std::hex << std::setfill('0') << std::setw(2);
// line3 << int(msg[i]) << " ";
// }
// line3 << std::string(31, ' ');
// lengthCheck(line3.str());
// out << line3.str() << std::endl;
//}
int Rinex_Printer::signalStrength(const double snr)

View File

@ -61,7 +61,6 @@
#include "gps_navigation_message.h"
#include "gps_cnav_navigation_message.h"
#include "galileo_navigation_message.h"
#include "sbas_telemetry_data.h"
#include "GPS_L1_CA.h"
#include "Galileo_E1.h"
#include "gnss_synchro.h"
@ -214,7 +213,7 @@ public:
/*!
* \brief Writes raw SBAS messages into the RINEX file
*/
void log_rinex_sbs(std::fstream & out, const Sbas_Raw_Msg & sbs_message);
//void log_rinex_sbs(std::fstream & out, const Sbas_Raw_Msg & sbs_message);
void update_nav_header(std::fstream & out, const Gps_Utc_Model & gps_utc, const Gps_Iono & gps_iono);
@ -277,6 +276,8 @@ private:
*/
void lengthCheck(const std::string & line);
double fake_cnav_iode;
/*
* If the string is bigger than length, truncate it from the right.
* otherwise, add pad characters to its right.

View File

@ -0,0 +1,311 @@
/*!
* \file rtklib_solver.cc
* \brief PVT solver based on rtklib library functions adapted to the GNSS-SDR
* data flow and structures
* \authors <ul>
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* <li> 2007-2013, T. Takasu
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* -----------------------------------------------------------------------*/
#include "rtklib_solver.h"
#include <glog/logging.h>
#include "rtklib_conversions.h"
#include "GPS_L1_CA.h"
#include "Galileo_E1.h"
using google::LogMessage;
rtklib_solver::rtklib_solver(int nchannels, std::string dump_filename, bool flag_dump_to_file, rtk_t & rtk)
{
// init empty ephemeris for all the available GNSS channels
d_nchannels = nchannels;
d_dump_filename = dump_filename;
d_flag_dump_enabled = flag_dump_to_file;
count_valid_position = 0;
d_flag_averaging = false;
rtk_ = rtk;
pvt_sol = {{0,0}, {0,0,0,0,0,0}, {0,0,0,0,0,0}, {0,0,0,0,0,0}, '0', '0', '0', 0, 0, 0 };
// ############# ENABLE DATA FILE LOG #################
if (d_flag_dump_enabled == true)
{
if (d_dump_file.is_open() == false)
{
try
{
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) << "PVT lib dump enabled Log file: " << d_dump_filename.c_str();
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "Exception opening PVT lib dump file " << e.what();
}
}
}
}
rtklib_solver::~rtklib_solver()
{
d_dump_file.close();
}
bool rtklib_solver::get_PVT(std::map<int,Gnss_Synchro> gnss_observables_map, double Rx_time, bool flag_averaging)
{
std::map<int,Gnss_Synchro>::iterator gnss_observables_iter;
std::map<int,Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
std::map<int,Gps_Ephemeris>::iterator gps_ephemeris_iter;
std::map<int,Gps_CNAV_Ephemeris>::iterator gps_cnav_ephemeris_iter;
d_flag_averaging = flag_averaging;
// ********************************************************************************
// ****** PREPARE THE DATA (SV EPHEMERIS AND OBSERVATIONS) ************************
// ********************************************************************************
int valid_obs = 0; //valid observations counter
obsd_t obs_data[MAXOBS];
eph_t eph_data[MAXOBS];
for(gnss_observables_iter = gnss_observables_map.begin();
gnss_observables_iter != gnss_observables_map.end();
gnss_observables_iter++)
{
switch(gnss_observables_iter->second.System)
{
case 'E':
{
// 1 Gal - find the ephemeris for the current GALILEO SV observation. The SV PRN ID is the map key
galileo_ephemeris_iter = galileo_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (galileo_ephemeris_iter != galileo_ephemeris_map.end())
{
//convert ephemeris from GNSS-SDR class to RTKLIB structure
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,
gnss_observables_iter->second,
galileo_ephemeris_iter->second.WN_5,
0);
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 'G':
{
// 1 GPS - find the ephemeris for the current GPS SV observation. The SV PRN ID is the map key
std::string sig_(gnss_observables_iter->second.Signal);
if(sig_.compare("1C") == 0)
{
gps_ephemeris_iter = gps_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (gps_ephemeris_iter != gps_ephemeris_map.end())
{
//convert ephemeris from GNSS-SDR class to RTKLIB structure
eph_data[valid_obs] = eph_to_rtklib(gps_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,
gnss_observables_iter->second,
gps_ephemeris_iter->second.i_GPS_week,
0);
valid_obs++;
}
else // the ephemeris are not available for this SV
{
DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->first;
}
}
if(sig_.compare("2S") == 0)
{
gps_cnav_ephemeris_iter = gps_cnav_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (gps_cnav_ephemeris_iter != gps_cnav_ephemeris_map.end())
{
// 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.end())
{
// 2. If found, replace the existing GPS L1 ephemeris with the GPS L2 ephemeris
// (more precise!), and attach the L2 observation to the L1 observation in RTKLIB structure
for (int i = 0; i < valid_obs; i++)
{
if (eph_data[i].sat == static_cast<int>(gnss_observables_iter->second.PRN))
{
eph_data[i] = eph_to_rtklib(gps_cnav_ephemeris_iter->second);
obs_data[valid_obs] = insert_obs_to_rtklib(obs_data[valid_obs],
gnss_observables_iter->second,
gps_cnav_ephemeris_iter->second.i_GPS_week,
1);//Band 2 (L2)
break;
}
}
}
else
{
// 3. If not found, insert the GPS L2 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
obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}};
obs_data[valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second,
gps_cnav_ephemeris_iter->second.i_GPS_week,
1);//Band 2 (L2)
valid_obs++;
}
}
else // the ephemeris are not available for this SV
{
DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN;
}
}
break;
}
default :
DLOG(INFO) << "Hybrid observables: Unknown GNSS";
break;
}
}
// **********************************************************************
// ****** SOLVE PVT******************************************************
// **********************************************************************
b_valid_position = false;
if (valid_obs > 0)
{
int result = 0;
nav_t nav_data;
nav_data.eph = eph_data;
nav_data.n = valid_obs;
for (int i = 0; i < MAXSAT; i++)
{
nav_data.lam[i][0] = SPEED_OF_LIGHT / FREQ1; /* L1/E1 */
nav_data.lam[i][1] = SPEED_OF_LIGHT / FREQ2; /* L2 */
nav_data.lam[i][2] = SPEED_OF_LIGHT / FREQ5; /* L2 */
}
result = rtkpos(&rtk_, obs_data, valid_obs, &nav_data);
if(result == 0)
{
LOG(INFO) << "RTKLIB rtkpos error message: " << rtk_.errbuf;
d_rx_dt_s = 0; //reset rx time estimation
d_valid_observations = 0;
}
else
{
d_valid_observations = rtk_.sol.ns; //record the number of valid satellites used by the PVT solver
pvt_sol = rtk_.sol;
b_valid_position = true;
arma::vec rx_position_and_time(4);
rx_position_and_time(0) = pvt_sol.rr[0];
rx_position_and_time(1) = pvt_sol.rr[1];
rx_position_and_time(2) = pvt_sol.rr[2];
rx_position_and_time(3) = pvt_sol.dtr[0];
d_rx_pos = rx_position_and_time.rows(0, 2); // save ECEF position for the next iteration
d_rx_dt_s += rx_position_and_time(3) / GPS_C_m_s; // accumulate the rx time error for the next iteration [meters]->[seconds]
DLOG(INFO) << "RTKLIB Position at TOW=" << Rx_time << " in ECEF (X,Y,Z,t[meters]) = " << rx_position_and_time;
boost::posix_time::ptime p_time;
gtime_t rtklib_utc_time = gpst2utc(pvt_sol.time);
p_time = boost::posix_time::from_time_t(rtklib_utc_time.time);
p_time+=boost::posix_time::microseconds(round(rtklib_utc_time.sec * 1e6));
d_position_UTC_time = p_time;
cart2geo(static_cast<double>(rx_position_and_time(0)), static_cast<double>(rx_position_and_time(1)), static_cast<double>(rx_position_and_time(2)), 4);
DLOG(INFO) << "RTKLIB Position at " << boost::posix_time::to_simple_string(p_time)
<< " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
<< " [deg], Height= " << d_height_m << " [m]" << " RX time offset= " << d_rx_dt_s << " [s]";
// ######## LOG FILE #########
if(d_flag_dump_enabled == true)
{
// MULTIPLEXED FILE RECORDING - Record results to file
try
{
double tmp_double;
// PVT GPS time
tmp_double = Rx_time;
d_dump_file.write((char*)&tmp_double, sizeof(double));
// ECEF User Position East [m]
tmp_double = rx_position_and_time(0);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// ECEF User Position North [m]
tmp_double = rx_position_and_time(1);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// ECEF User Position Up [m]
tmp_double = rx_position_and_time(2);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// User clock offset [s]
tmp_double = rx_position_and_time(3);
d_dump_file.write((char*)&tmp_double, sizeof(double));
// GEO user position Latitude [deg]
tmp_double = d_latitude_d;
d_dump_file.write((char*)&tmp_double, sizeof(double));
// GEO user position Longitude [deg]
tmp_double = d_longitude_d;
d_dump_file.write((char*)&tmp_double, sizeof(double));
// GEO user position Height [m]
tmp_double = d_height_m;
d_dump_file.write((char*)&tmp_double, sizeof(double));
}
catch (const std::ifstream::failure& e)
{
LOG(WARNING) << "Exception writing PVT LS dump file " << e.what();
}
}
}
}
return b_valid_position;
}

View File

@ -0,0 +1,107 @@
/*!
* \file rtklib_solver.h
* \brief PVT solver based on rtklib library functions adapted to the GNSS-SDR
* data flow and structures
* \authors <ul>
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* <li> 2007-2013, T. Takasu
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* -------------------------------------------------------------------------*/
#ifndef GNSS_SDR_RTKLIB_SOLVER_H_
#define GNSS_SDR_RTKLIB_SOLVER_H_
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include "rtklib_rtkpos.h"
#include "galileo_navigation_message.h"
#include "gps_navigation_message.h"
#include "gps_cnav_navigation_message.h"
#include "gnss_synchro.h"
#include "pvt_solution.h"
/*!
* \brief This class implements a simple PVT Least Squares solution
*/
class rtklib_solver : public Pvt_Solution
{
private:
public:
rtklib_solver(int nchannels,std::string dump_filename, bool flag_dump_to_file, rtk_t & rtk);
~rtklib_solver();
bool get_PVT(std::map<int,Gnss_Synchro> gnss_observables_map, double Rx_time, bool flag_averaging);
int d_nchannels; //!< Number of available channels for positioning
std::map<int,Galileo_Ephemeris> galileo_ephemeris_map; //!< Map storing new Galileo_Ephemeris
std::map<int,Gps_Ephemeris> gps_ephemeris_map; //!< Map storing new GPS_Ephemeris
std::map<int,Gps_CNAV_Ephemeris> gps_cnav_ephemeris_map;
Galileo_Utc_Model galileo_utc_model;
Galileo_Iono galileo_iono;
Galileo_Almanac galileo_almanac;
Gps_Utc_Model gps_utc_model;
Gps_Iono gps_iono;
Gps_CNAV_Iono gps_cnav_iono;
Gps_CNAV_Utc_Model gps_cnav_utc_model;
int count_valid_position;
bool d_flag_dump_enabled;
sol_t pvt_sol;
rtk_t rtk_;
std::string d_dump_filename;
std::ofstream d_dump_file;
};
#endif

View File

@ -275,7 +275,6 @@ void galileo_e5a_noncoherentIQ_acquisition_caf_cc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;

View File

@ -153,7 +153,6 @@ void galileo_pcps_8ms_acquisition_cc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;

View File

@ -162,6 +162,7 @@ void pcps_acquisition_cc::set_local_code(std::complex<float> * code)
// Here we want to create a buffer that looks like this:
// [ 0 0 0 ... 0 c_0 c_1 ... c_L]
// where c_i is the local code and there are L zeros and L chips
gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
if( d_bit_transition_flag )
{
int offset = d_fft_size/2;
@ -193,7 +194,6 @@ void pcps_acquisition_cc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;
@ -217,6 +217,7 @@ void pcps_acquisition_cc::init()
void pcps_acquisition_cc::set_state(int state)
{
gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
d_state = state;
if (d_state == 1)
{
@ -237,6 +238,42 @@ void pcps_acquisition_cc::set_state(int state)
}
void pcps_acquisition_cc::send_positive_acquisition()
{
// 6.1- Declare positive acquisition using a message port
//0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
DLOG(INFO) << "positive acquisition"
<< "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
<< "sample_stamp " << d_sample_counter
<< "test statistics value " << d_test_statistics
<< "test statistics threshold " << d_threshold
<< "code phase " << d_gnss_synchro->Acq_delay_samples
<< "doppler " << d_gnss_synchro->Acq_doppler_hz
<< "magnitude " << d_mag
<< "input signal power " << d_input_power;
this->message_port_pub(pmt::mp("events"), pmt::from_long(1));
}
void pcps_acquisition_cc::send_negative_acquisition()
{
// 6.2- Declare negative acquisition using a message port
//0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
DLOG(INFO) << "negative acquisition"
<< "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
<< "sample_stamp " << d_sample_counter
<< "test statistics value " << d_test_statistics
<< "test statistics threshold " << d_threshold
<< "code phase " << d_gnss_synchro->Acq_delay_samples
<< "doppler " << d_gnss_synchro->Acq_doppler_hz
<< "magnitude " << d_mag
<< "input signal power " << d_input_power;
this->message_port_pub(pmt::mp("events"), pmt::from_long(2));
}
int pcps_acquisition_cc::general_work(int noutput_items,
gr_vector_int &ninput_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items __attribute__((unused)))
@ -252,8 +289,6 @@ int pcps_acquisition_cc::general_work(int noutput_items,
* 6. Declare positive or negative acquisition using a message port
*/
int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
switch (d_state)
{
case 0:
@ -268,15 +303,12 @@ int pcps_acquisition_cc::general_work(int noutput_items,
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]);
//DLOG(INFO) << "Consumed " << ninput_items[0] << " items";
break;
}
@ -294,16 +326,14 @@ int pcps_acquisition_cc::general_work(int noutput_items,
d_input_power = 0.0;
d_mag = 0.0;
d_sample_counter += d_fft_size; // sample counter
d_well_count++;
DLOG(INFO) << "Channel: " << d_channel
DLOG(INFO)<< "Channel: " << d_channel
<< " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
<< " ,sample stamp: " << d_sample_counter << ", threshold: "
<< d_threshold << ", doppler_max: " << d_doppler_max
<< ", doppler_step: " << d_doppler_step;
<< ", doppler_step: " << d_doppler_step<<std::endl;
if (d_use_CFAR_algorithm_flag == true)
{
@ -405,11 +435,15 @@ int pcps_acquisition_cc::general_work(int noutput_items,
{
if (d_test_statistics > d_threshold)
{
d_state = 2; // Positive acquisition
d_state = 0; // Positive acquisition
d_active = false;
send_positive_acquisition();
}
else if (d_well_count == d_max_dwells)
{
d_state = 3; // Negative acquisition
d_state = 0;
d_active = false;
send_negative_acquisition();
}
}
else
@ -418,69 +452,23 @@ int pcps_acquisition_cc::general_work(int noutput_items,
{
if (d_test_statistics > d_threshold)
{
d_state = 2; // Positive acquisition
d_state = 0; // Positive acquisition
d_active = false;
send_positive_acquisition();
}
else
{
d_state = 3; // Negative acquisition
d_state = 0; // Negative acquisition
d_active = false;
send_negative_acquisition();
}
}
}
consume_each(1);
DLOG(INFO) << "Done. Consumed 1 item.";
break;
}
case 2:
{
// 6.1- Declare positive acquisition using a message port
DLOG(INFO) << "positive acquisition";
DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN;
DLOG(INFO) << "sample_stamp " << d_sample_counter;
DLOG(INFO) << "test statistics value " << d_test_statistics;
DLOG(INFO) << "test statistics threshold " << d_threshold;
DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples;
DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz;
DLOG(INFO) << "magnitude " << d_mag;
DLOG(INFO) << "input signal power " << d_input_power;
d_active = false;
d_state = 0;
d_sample_counter += d_fft_size * ninput_items[0]; // sample counter
consume_each(ninput_items[0]);
acquisition_message = 1;
this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message));
break;
}
case 3:
{
// 6.2- Declare negative acquisition using a message port
DLOG(INFO) << "negative acquisition";
DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN;
DLOG(INFO) << "sample_stamp " << d_sample_counter;
DLOG(INFO) << "test statistics value " << d_test_statistics;
DLOG(INFO) << "test statistics threshold " << d_threshold;
DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples;
DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz;
DLOG(INFO) << "magnitude " << d_mag;
DLOG(INFO) << "input signal power " << d_input_power;
d_active = false;
d_state = 0;
d_sample_counter += d_fft_size * ninput_items[0]; // sample counter
consume_each(ninput_items[0]);
acquisition_message = 2;
this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message));
break;
}
}
return noutput_items;

View File

@ -95,6 +95,8 @@ private:
void update_local_carrier(gr_complex* carrier_vector, int correlator_length_samples, float freq);
void send_negative_acquisition();
void send_positive_acquisition();
long d_fs_in;
long d_freq;
int d_samples_per_ms;
@ -143,6 +145,7 @@ public:
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{
gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
d_gnss_synchro = p_gnss_synchro;
}
@ -172,6 +175,7 @@ public:
*/
void set_active(bool active)
{
gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
d_active = active;
}
@ -188,6 +192,7 @@ public:
*/
void set_channel(unsigned int channel)
{
gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
d_channel = channel;
}
@ -198,6 +203,7 @@ public:
*/
void set_threshold(float threshold)
{
gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
d_threshold = threshold;
}
@ -207,6 +213,7 @@ public:
*/
void set_doppler_max(unsigned int doppler_max)
{
gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
d_doppler_max = doppler_max;
}
@ -216,6 +223,7 @@ public:
*/
void set_doppler_step(unsigned int doppler_step)
{
gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
d_doppler_step = doppler_step;
}

View File

@ -165,7 +165,6 @@ void pcps_acquisition_fine_doppler_cc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;

View File

@ -190,7 +190,6 @@ void pcps_acquisition_sc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;

View File

@ -158,7 +158,6 @@ void pcps_assisted_acquisition_cc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;

View File

@ -166,7 +166,6 @@ void pcps_cccwsr_acquisition_cc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;

View File

@ -156,7 +156,6 @@ void pcps_multithread_acquisition_cc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;

View File

@ -293,7 +293,6 @@ void pcps_opencl_acquisition_cc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;

View File

@ -197,7 +197,6 @@ void pcps_quicksync_acquisition_cc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
//DLOG(INFO) << "START init";
d_gnss_synchro->Acq_delay_samples = 0.0;

View File

@ -167,7 +167,6 @@ void pcps_tong_acquisition_cc::init()
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
d_gnss_synchro->Flag_valid_word = false;
d_gnss_synchro->Flag_preamble = false;
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;

View File

@ -16,11 +16,13 @@
# along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
#
add_subdirectory(rtklib)
set(GNSS_SPLIBS_SOURCES
gps_l2c_signal.cc
galileo_e1_signal_processing.cc
gnss_sdr_valve.cc
gnss_sdr_sample_counter.cc
gnss_signal_processing.cc
gps_sdr_signal_processing.cc
pass_through.cc

View File

@ -0,0 +1,71 @@
/*!
* \file gnss_sdr_sample_counter.cc
* \brief Simple block to report the current receiver time based on the output of the tracking or telemetry blocks
* \author Javier Arribas 2017. jarribas(at)cttc.es
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "gnss_sdr_sample_counter.h"
#include "gnss_synchro.h"
#include <gnuradio/io_signature.h>
gnss_sdr_sample_counter::gnss_sdr_sample_counter () : gr::sync_block("sample_counter",
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)),
gr::io_signature::make(0,0,0))
{
this->message_port_register_out(pmt::mp("sample_counter"));
last_T_rx_s=0;
report_interval_s=1;//default reporting 1 second
flag_enable_send_msg=false; //enable it for reporting time with asynchronous message
}
gnss_sdr_sample_counter_sptr gnss_sdr_make_sample_counter ()
{
gnss_sdr_sample_counter_sptr sample_counter_(new gnss_sdr_sample_counter());
return sample_counter_;
}
int gnss_sdr_sample_counter::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const Gnss_Synchro *in = (const Gnss_Synchro *) input_items[0]; // input
double current_T_rx_s=in[noutput_items-1].Tracking_sample_counter/(double)in[noutput_items-1].fs;
if ((current_T_rx_s-last_T_rx_s)>report_interval_s)
{
std::cout<<"Current receiver time: "<<floor(current_T_rx_s)<<" [s]"<<std::endl;
if(flag_enable_send_msg==true)
{
this->message_port_pub(pmt::mp("receiver_time"), pmt::from_double(current_T_rx_s));
}
last_T_rx_s=current_T_rx_s;
}
return noutput_items;
}

View File

@ -0,0 +1,58 @@
/*!
* \file gnss_sdr_sample_counter.h
* \brief Simple block to report the current receiver time based on the output of the tracking or telemetry blocks
* \author Javier Arribas 2017. jarribas(at)cttc.es
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_sample_counter_H_
#define GNSS_SDR_sample_counter_H_
#include <gnuradio/sync_block.h>
#include <boost/shared_ptr.hpp>
class gnss_sdr_sample_counter;
typedef boost::shared_ptr<gnss_sdr_sample_counter> gnss_sdr_sample_counter_sptr;
gnss_sdr_sample_counter_sptr gnss_sdr_make_sample_counter ();
class gnss_sdr_sample_counter : public gr::sync_block
{
friend gnss_sdr_sample_counter_sptr gnss_sdr_make_sample_counter();
gnss_sdr_sample_counter ();
double last_T_rx_s;
double report_interval_s;
bool flag_enable_send_msg;
public:
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
#endif /*GNSS_SDR_sample_counter_H_*/

View File

@ -0,0 +1,58 @@
# Copyright (C) 2012-2017 (see AUTHORS file for a list of contributors)
#
# This file is part of GNSS-SDR.
#
# GNSS-SDR is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GNSS-SDR is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
#
add_definitions( -DGNSS_SDR_VERSION="${VERSION}" )
set(RTKLIB_LIB_SOURCES
rtklib_rtkcmn.cc
rtklib_ephemeris.cc
rtklib_preceph.cc
rtklib_sbas.cc
rtklib_ionex.cc
rtklib_pntpos.cc
rtklib_ppp.cc
rtklib_tides.cc
rtklib_lambda.cc
rtklib_rtkpos.cc
rtklib_conversions.cc
)
include_directories(
$(CMAKE_CURRENT_SOURCE_DIR)
${CMAKE_SOURCE_DIR}/src/core/system_parameters
${CMAKE_SOURCE_DIR}/src/core/interfaces
${CMAKE_SOURCE_DIR}/src/core/receiver
${Boost_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS}
)
file(GLOB RTKLIB_LIB_HEADERS "*.h")
list(SORT RTKLIB_LIB_HEADERS)
add_library(rtklib_lib ${RTKLIB_LIB_SOURCES} ${RTKLIB_LIB_HEADERS})
source_group(Headers FILES ${RTKLIB_LIB_HEADERS})
add_dependencies(rtklib_lib glog-${glog_RELEASE})
target_link_libraries(
rtklib_lib
${Boost_LIBRARIES}
${GFlags_LIBS}
${GLOG_LIBRARIES}
${BLAS}
${LAPACK}
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,214 @@
/*!
* \file rtklib_conversions.cc
* \brief GNSS-SDR to RTKLIB data structures conversion functions
* \author 2017, Javier Arribas
*
* -------------------------------------------------------------------------
*
* 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 <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "rtklib_conversions.h"
#include "rtklib_rtkcmn.h"
obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synchro, int week, int band)
{
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);
double CN0_dB_Hz_est = gnss_synchro.CN0_dB_hz;
if (CN0_dB_Hz_est > 63.75) CN0_dB_Hz_est = 63.75;
if (CN0_dB_Hz_est < 0.0) CN0_dB_Hz_est = 0.0;
unsigned char CN0_dB_Hz = static_cast<unsigned char>(std::round(CN0_dB_Hz_est / 0.25 ));
rtklib_obs.SNR[band] = CN0_dB_Hz;
//Galileo is the third satellite system for RTKLIB, so, add the required offset to discriminate Galileo ephemeris
switch(gnss_synchro.System)
{
case 'G':
rtklib_obs.sat = gnss_synchro.PRN;
break;
case 'E':
rtklib_obs.sat = gnss_synchro.PRN+NSATGPS+NSATGLO;
break;
default:
rtklib_obs.sat = gnss_synchro.PRN;
}
rtklib_obs.time = gpst2time(adjgpsweek(week), gnss_synchro.RX_time);
rtklib_obs.rcv = 1;
//printf("OBS RX TIME [%i]: %s,%f\n\r",rtklib_obs.sat,time_str(rtklib_obs.time,3),rtklib_obs.time.sec);
return rtklib_obs;
}
eph_t eph_to_rtklib(const Galileo_Ephemeris & gal_eph)
{
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 };
//Galileo is the third satellite system for RTKLIB, so, add the required offset to discriminate Galileo ephemeris
rtklib_sat.sat = gal_eph.i_satellite_PRN+NSATGPS+NSATGLO;
rtklib_sat.A = gal_eph.A_1 * gal_eph.A_1;
rtklib_sat.M0 = gal_eph.M0_1;
rtklib_sat.deln = gal_eph.delta_n_3;
rtklib_sat.OMG0 = gal_eph.OMEGA_0_2;
rtklib_sat.OMGd = gal_eph.OMEGA_dot_3;
rtklib_sat.omg = gal_eph.omega_2;
rtklib_sat.i0 = gal_eph.i_0_2;
rtklib_sat.idot = gal_eph.iDot_2;
rtklib_sat.e = gal_eph.e_1;
rtklib_sat.Adot = 0; //only in CNAV;
rtklib_sat.ndot = 0; //only in CNAV;
rtklib_sat.week = adjgpsweek(gal_eph.WN_5); /* week of tow */
rtklib_sat.cic = gal_eph.C_ic_4;
rtklib_sat.cis = gal_eph.C_is_4;
rtklib_sat.cuc = gal_eph.C_uc_3;
rtklib_sat.cus = gal_eph.C_us_3;
rtklib_sat.crc = gal_eph.C_rc_3;
rtklib_sat.crs = gal_eph.C_rs_3;
rtklib_sat.f0 = gal_eph.af0_4;
rtklib_sat.f1 = gal_eph.af1_4;
rtklib_sat.f2 = gal_eph.af2_4;
rtklib_sat.tgd[0] = 0;
rtklib_sat.tgd[1] = 0;
rtklib_sat.tgd[2] = 0;
rtklib_sat.tgd[3] = 0;
rtklib_sat.toes = gal_eph.t0e_1;
rtklib_sat.toc = gpst2time(rtklib_sat.week, gal_eph.t0c_4);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, gal_eph.TOW_5);
/* adjustment for week handover */
double tow, toc;
tow = time2gpst(rtklib_sat.ttr, &rtklib_sat.week);
toc = time2gpst(rtklib_sat.toc, NULL);
if (rtklib_sat.toes < tow - 302400.0) {rtklib_sat.week++; tow -= 604800.0;}
else if (rtklib_sat.toes > tow + 302400.0) {rtklib_sat.week--; tow += 604800.0;}
rtklib_sat.toe = gpst2time(rtklib_sat.week, rtklib_sat.toes);
rtklib_sat.toc = gpst2time(rtklib_sat.week, toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow);
return rtklib_sat;
}
eph_t eph_to_rtklib(const Gps_Ephemeris & gps_eph)
{
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 };
rtklib_sat.sat = gps_eph.i_satellite_PRN;
rtklib_sat.A = gps_eph.d_sqrt_A * gps_eph.d_sqrt_A;
rtklib_sat.M0 = gps_eph.d_M_0;
rtklib_sat.deln = gps_eph.d_Delta_n;
rtklib_sat.OMG0 = gps_eph.d_OMEGA0;
rtklib_sat.OMGd = gps_eph.d_OMEGA_DOT;
rtklib_sat.omg = gps_eph.d_OMEGA;
rtklib_sat.i0 = gps_eph.d_i_0;
rtklib_sat.idot = gps_eph.d_IDOT;
rtklib_sat.e = gps_eph.d_e_eccentricity;
rtklib_sat.Adot = 0; //only in CNAV;
rtklib_sat.ndot = 0; //only in CNAV;
rtklib_sat.week = adjgpsweek(gps_eph.i_GPS_week); /* week of tow */
rtklib_sat.cic = gps_eph.d_Cic;
rtklib_sat.cis = gps_eph.d_Cis;
rtklib_sat.cuc = gps_eph.d_Cuc;
rtklib_sat.cus = gps_eph.d_Cus;
rtklib_sat.crc = gps_eph.d_Crc;
rtklib_sat.crs = gps_eph.d_Crs;
rtklib_sat.f0 = gps_eph.d_A_f0;
rtklib_sat.f1 = gps_eph.d_A_f1;
rtklib_sat.f2 = gps_eph.d_A_f2;
rtklib_sat.tgd[0] = gps_eph.d_TGD;
rtklib_sat.tgd[1] = 0;
rtklib_sat.tgd[2] = 0;
rtklib_sat.tgd[3] = 0;
rtklib_sat.toes = gps_eph.d_Toe;
rtklib_sat.toc = gpst2time(rtklib_sat.week, gps_eph.d_Toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, gps_eph.d_TOW);
/* adjustment for week handover */
double tow, toc;
tow = time2gpst(rtklib_sat.ttr, &rtklib_sat.week);
toc = time2gpst(rtklib_sat.toc, NULL);
if (rtklib_sat.toes < tow - 302400.0) {rtklib_sat.week++; tow -= 604800.0;}
else if (rtklib_sat.toes > tow + 302400.0) {rtklib_sat.week--; tow += 604800.0;}
rtklib_sat.toe = gpst2time(rtklib_sat.week, rtklib_sat.toes);
rtklib_sat.toc = gpst2time(rtklib_sat.week, toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow);
//printf("EPHEMERIS TIME [%i]: %s,%f\n\r",rtklib_sat.sat,time_str(rtklib_sat.toe,3),rtklib_sat.toe.sec);
return rtklib_sat;
}
eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris & gps_cnav_eph)
{
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 };
rtklib_sat.sat = gps_cnav_eph.i_satellite_PRN;
const double A_REF = 26559710.0; // See IS-GPS-200H, pp. 170
rtklib_sat.A = A_REF + gps_cnav_eph.d_DELTA_A;
rtklib_sat.M0 = gps_cnav_eph.d_M_0;
rtklib_sat.deln = gps_cnav_eph.d_Delta_n;
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;
rtklib_sat.OMGd = d_OMEGA_DOT;
rtklib_sat.omg = gps_cnav_eph.d_OMEGA;
rtklib_sat.i0 = gps_cnav_eph.d_i_0;
rtklib_sat.idot = gps_cnav_eph.d_IDOT;
rtklib_sat.e = gps_cnav_eph.d_e_eccentricity;
rtklib_sat.Adot = gps_cnav_eph.d_A_DOT; //only in CNAV;
rtklib_sat.ndot = gps_cnav_eph.d_DELTA_DOT_N; //only in CNAV;
rtklib_sat.week = adjgpsweek(gps_cnav_eph.i_GPS_week); /* week of tow */
rtklib_sat.cic = gps_cnav_eph.d_Cic;
rtklib_sat.cis = gps_cnav_eph.d_Cis;
rtklib_sat.cuc = gps_cnav_eph.d_Cuc;
rtklib_sat.cus = gps_cnav_eph.d_Cus;
rtklib_sat.crc = gps_cnav_eph.d_Crc;
rtklib_sat.crs = gps_cnav_eph.d_Crs;
rtklib_sat.f0 = gps_cnav_eph.d_A_f0;
rtklib_sat.f1 = gps_cnav_eph.d_A_f1;
rtklib_sat.f2 = gps_cnav_eph.d_A_f2;
rtklib_sat.tgd[0] = gps_cnav_eph.d_TGD;
rtklib_sat.tgd[1] = 0;
rtklib_sat.tgd[2] = 0;
rtklib_sat.tgd[3] = 0;
rtklib_sat.toes = gps_cnav_eph.d_Toe1;
rtklib_sat.toc = gpst2time(rtklib_sat.week,gps_cnav_eph.d_Toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week,gps_cnav_eph.d_TOW);
/* adjustment for week handover */
double tow, toc;
tow = time2gpst(rtklib_sat.ttr, &rtklib_sat.week);
toc = time2gpst(rtklib_sat.toc, NULL);
if (rtklib_sat.toes < tow - 302400.0) {rtklib_sat.week++; tow -= 604800.0;}
else if (rtklib_sat.toes > tow + 302400.0) {rtklib_sat.week--; tow += 604800.0;}
rtklib_sat.toe = gpst2time(rtklib_sat.week, rtklib_sat.toes);
rtklib_sat.toc = gpst2time(rtklib_sat.week, toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow);
return rtklib_sat;
}

View File

@ -0,0 +1,46 @@
/*!
* \file rtklib_conversions.h
* \brief GNSS-SDR to RTKLIB data structures conversion functions
* \author 2017, Javier Arribas
*
* -------------------------------------------------------------------------
*
* 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 <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_RTKLIB_CONVERSIONS_H_
#define GNSS_SDR_RTKLIB_CONVERSIONS_H_
#include "rtklib.h"
#include "gnss_synchro.h"
#include "galileo_ephemeris.h"
#include "gps_ephemeris.h"
#include "gps_cnav_ephemeris.h"
eph_t eph_to_rtklib(const Galileo_Ephemeris & gal_eph);
eph_t eph_to_rtklib(const Gps_Ephemeris & gps_eph);
eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris & gps_cnav_eph);
obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synchro, int week, int band);
#endif /* GNSS_SDR_RTKLIB_CONVERSIONS_H_ */

View File

@ -0,0 +1,872 @@
/*!
* \file rtklib_ephemeris.cc
* \brief satellite ephemeris and clock functions
* \authors <ul>
* <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*----------------------------------------------------------------------------*/
#include "rtklib_ephemeris.h"
#include "rtklib_rtkcmn.h"
#include "rtklib_sbas.h"
#include "rtklib_preceph.h"
/* constants ------------------------------------------------------*/
const double RE_GLO = 6378136.0; /* radius of earth (m) ref [2] */
const double MU_GPS = 3.9860050e14; /* gravitational constant ref [1] */
const double MU_GLO = 3.9860044e14; /* gravitational constant ref [2] */
const double MU_GAL = 3.986004418e14; /* earth gravitational constant ref [7] */
const double MU_BDS = 3.986004418e14; /* earth gravitational constant ref [9] */
const double J2_GLO = 1.0826257e-3; /* 2nd zonal harmonic of geopot ref [2] */
const double OMGE_GLO = 7.292115e-5; /* earth angular velocity (rad/s) ref [2] */
const double OMGE_GAL = 7.2921151467e-5; /* earth angular velocity (rad/s) ref [7] */
const double OMGE_BDS = 7.292115e-5; /* earth angular velocity (rad/s) ref [9] */
const double SIN_5 = -0.0871557427476582; /* sin(-5.0 deg) */
const double COS_5 = 0.9961946980917456; /* cos(-5.0 deg) */
const double ERREPH_GLO = 5.0; /* error of glonass ephemeris (m) */
const double TSTEP = 60.0; /* integration step glonass ephemeris (s) */
const double RTOL_KEPLER = 1e-13; /* relative tolerance for Kepler equation */
const double DEFURASSR = 0.15; /* default accurary of ssr corr (m) */
const double MAXECORSSR = 10.0; /* max orbit correction of ssr (m) */
const double MAXCCORSSR = 1e-6 * SPEED_OF_LIGHT; /* max clock correction of ssr (m) */
const double MAXAGESSR = 90.0; /* max age of ssr orbit and clock (s) */
const double MAXAGESSR_HRCLK = 10.0; /* max age of ssr high-rate clock (s) */
const double STD_BRDCCLK = 30.0; /* error of broadcast clock (m) */
const int MAX_ITER_KEPLER = 30; /* max number of iteration of Kelpler */
/* variance by ura ephemeris (ref [1] 20.3.3.3.1.1) --------------------------*/
double var_uraeph(int ura)
{
const double ura_value[] = {
2.4, 3.4, 4.85, 6.85, 9.65, 13.65, 24.0, 48.0, 96.0, 192.0, 384.0, 768.0, 1536.0,
3072.0, 6144.0
};
return ura < 0 || 15 < ura ? std::pow(6144.0, 2.0) : std::pow(ura_value[ura], 2.0);
}
/* variance by ura ssr (ref [4]) ---------------------------------------------*/
double var_urassr(int ura)
{
double std_;
if (ura <= 0) return std::pow(DEFURASSR, 2.0);
if (ura >= 63) return std::pow(5.4665, 2.0);
std_ = (std::pow((ura >> 3) & 7, 2.0) * (1.0 + (ura & 7) / 4.0) - 1.0) * 1e-3;
return std::pow(std_, 2.0);
}
/* almanac to satellite position and clock bias --------------------------------
* compute satellite position and clock bias with almanac (gps, galileo, qzss)
* args : gtime_t time I time (gpst)
* alm_t *alm I almanac
* double *rs O satellite position (ecef) {x,y,z} (m)
* double *dts O satellite clock bias (s)
* return : none
* notes : see ref [1],[7],[8]
*-----------------------------------------------------------------------------*/
void alm2pos(gtime_t time, const alm_t *alm, double *rs, double *dts)
{
double tk, M, E, Ek, sinE, cosE, u, r, i, O, x, y, sinO, cosO, cosi, mu;
int n;
trace(4, "alm2pos : time=%s sat=%2d\n", time_str(time, 3), alm->sat);
tk = timediff(time, alm->toa);
if (alm->A <= 0.0)
{
rs[0] = rs[1] = rs[2] = *dts = 0.0;
return;
}
mu = satsys(alm->sat, NULL) == SYS_GAL ? MU_GAL : MU_GPS;
M = alm->M0 + sqrt(mu / (alm->A * alm->A * alm->A)) * tk;
for (n = 0, E = M, Ek = 0.0; fabs(E - Ek) > RTOL_KEPLER && n < MAX_ITER_KEPLER; n++)
{
Ek = E;
E -= (E - alm->e * sin(E) - M) / (1.0 - alm->e * cos(E));
}
if (n >= MAX_ITER_KEPLER)
{
trace(2, "alm2pos: kepler iteration overflow sat=%2d\n", alm->sat);
return;
}
sinE = sin(E);
cosE = cos(E);
u = atan2(sqrt(1.0 - alm->e * alm->e) * sinE, cosE - alm->e) + alm->omg;
r = alm->A * (1.0 - alm->e*cosE);
i = alm->i0;
O = alm->OMG0 + (alm->OMGd - DEFAULT_OMEGA_EARTH_DOT) * tk - DEFAULT_OMEGA_EARTH_DOT * alm->toas;
x = r * cos(u);
y = r * sin(u);
sinO = sin(O);
cosO = cos(O);
cosi = cos(i);
rs[0] = x * cosO - y * cosi * sinO;
rs[1] = x * sinO + y * cosi * cosO;
rs[2] = y * sin(i);
*dts = alm->f0 + alm->f1 * tk;
}
/* broadcast ephemeris to satellite clock bias ---------------------------------
* compute satellite clock bias with broadcast ephemeris (gps, galileo, qzss)
* args : gtime_t time I time by satellite clock (gpst)
* eph_t *eph I broadcast ephemeris
* return : satellite clock bias (s) without relativeity correction
* notes : see ref [1],[7],[8]
* satellite clock does not include relativity correction and tdg
*-----------------------------------------------------------------------------*/
double eph2clk(gtime_t time, const eph_t *eph)
{
double t;
int i;
trace(4, "eph2clk : time=%s sat=%2d\n", time_str(time, 3), eph->sat);
t = timediff(time, eph->toc);
for (i = 0; i < 2; i++)
{
t -= eph->f0 + eph->f1 * t + eph->f2 * t * t;
}
return eph->f0 + eph->f1 * t + eph->f2 * t *t;
}
/* broadcast ephemeris to satellite position and clock bias --------------------
* compute satellite position and clock bias with broadcast ephemeris (gps,
* galileo, qzss)
* args : gtime_t time I time (gpst)
* eph_t *eph I broadcast ephemeris
* double *rs O satellite position (ecef) {x,y,z} (m)
* double *dts O satellite clock bias (s)
* double *var O satellite position and clock variance (m^2)
* return : none
* notes : see ref [1],[7],[8]
* satellite clock includes relativity correction without code bias
* (tgd or bgd)
*-----------------------------------------------------------------------------*/
void eph2pos(gtime_t time, const eph_t *eph, double *rs, double *dts,
double *var)
{
double tk, M, E, Ek, sinE, cosE, u, r, i, O, sin2u, cos2u, x, y, sinO, cosO, cosi, mu, omge;
double xg, yg, zg, sino, coso;
int n, sys, prn;
trace(4, "eph2pos : time=%s sat=%2d\n", time_str(time, 3), eph->sat);
if (eph->A <= 0.0)
{
rs[0] = rs[1] = rs[2] = *dts = *var = 0.0;
return;
}
tk = timediff(time , eph->toe);
switch ((sys = satsys(eph->sat, &prn)))
{
case SYS_GAL: mu = MU_GAL; omge = OMGE_GAL; break;
case SYS_BDS: mu = MU_BDS; omge = OMGE_BDS; break;
default: mu = MU_GPS; omge = DEFAULT_OMEGA_EARTH_DOT; break;
}
M = eph->M0 + (sqrt(mu / (eph->A * eph->A * eph->A)) + eph->deln) * tk;
for (n = 0, E = M, Ek = 0.0; fabs(E - Ek) > RTOL_KEPLER && n < MAX_ITER_KEPLER; n++)
{
Ek = E;
E -= (E - eph->e * sin(E) - M) / (1.0 - eph->e * cos(E));
}
if (n >= MAX_ITER_KEPLER)
{
trace(2, "eph2pos: kepler iteration overflow sat=%2d\n", eph->sat);
return;
}
sinE = sin(E);
cosE = cos(E);
trace(4, "kepler: sat=%2d e=%8.5f n=%2d del=%10.3e\n", eph->sat, eph->e, n, E - Ek);
u = atan2(sqrt(1.0 - eph->e*eph->e) * sinE, cosE-eph->e) + eph->omg;
r = eph->A * (1.0 - eph->e * cosE);
i = eph->i0 + eph->idot * tk;
sin2u = sin(2.0 * u); cos2u = cos(2.0 * u);
u += eph->cus * sin2u + eph->cuc * cos2u;
r += eph->crs * sin2u + eph->crc * cos2u;
i += eph->cis * sin2u + eph->cic * cos2u;
x = r * cos(u);
y = r * sin(u);
cosi = cos(i);
/* beidou geo satellite (ref [9]) */
if (sys == SYS_BDS && prn <= 5)
{
O = eph->OMG0 + eph->OMGd * tk - omge * eph->toes;
sinO = sin(O);
cosO = cos(O);
xg = x * cosO - y * cosi * sinO;
yg = x * sinO + y * cosi * cosO;
zg = y * sin(i);
sino = sin(omge * tk);
coso = cos(omge * tk);
rs[0] = xg * coso + yg * sino * COS_5 + zg * sino * SIN_5;
rs[1] = -xg * sino + yg * coso * COS_5 + zg * coso * SIN_5;
rs[2] = -yg * SIN_5 + zg * COS_5;
}
else
{
O = eph->OMG0 + (eph->OMGd - omge) * tk - omge * eph->toes;
sinO = sin(O);
cosO = cos(O);
rs[0] = x * cosO - y * cosi * sinO;
rs[1] = x * sinO + y *cosi * cosO;
rs[2] = y * sin(i);
}
tk = timediff(time, eph->toc);
*dts = eph->f0 + eph->f1 * tk + eph->f2 * tk * tk;
/* relativity correction */
*dts -= 2.0 * sqrt(mu * eph->A) * eph-> e* sinE / std::pow(SPEED_OF_LIGHT, 2.0);
/* position and clock error variance */
*var = var_uraeph(eph->sva);
}
/* glonass orbit differential equations --------------------------------------*/
void deq(const double *x, double *xdot, const double *acc)
{
double a, b, c, r2 = dot(x, x, 3), r3 = r2 * sqrt(r2), omg2 = std::pow(OMGE_GLO, 2.0);
if (r2 <= 0.0)
{
xdot[0] = xdot[1] = xdot[2] = xdot[3] = xdot[4] = xdot[5] = 0.0;
return;
}
/* ref [2] A.3.1.2 with bug fix for xdot[4],xdot[5] */
a = 1.5 * J2_GLO * MU_GLO * std::pow(RE_GLO, 2.0) / r2 / r3; /* 3/2*J2*mu*Ae^2/r^5 */
b = 5.0 * x[2] * x[2] / r2; /* 5*z^2/r^2 */
c = -MU_GLO / r3 - a * (1.0 - b); /* -mu/r^3-a(1-b) */
xdot[0] = x[3];
xdot[1] = x[4]; xdot[2] = x[5];
xdot[3] = (c + omg2) * x[0] + 2.0 * OMGE_GLO * x[4] + acc[0];
xdot[4] = (c + omg2) * x[1] - 2.0 * OMGE_GLO * x[3] + acc[1];
xdot[5] = (c - 2.0 * a) * x[2] + acc[2];
}
/* glonass position and velocity by numerical integration --------------------*/
void glorbit(double t, double *x, const double *acc)
{
double k1[6], k2[6], k3[6], k4[6], w[6];
int i;
deq(x, k1, acc); for (i = 0; i< 6; i++) w[i] = x[i] + k1[i] * t / 2.0;
deq(w, k2, acc); for (i = 0; i < 6; i++) w[i] = x[i] + k2[i] * t / 2.0;
deq(w, k3, acc); for (i = 0; i < 6; i++) w[i] = x[i] + k3[i] * t;
deq(w, k4, acc);
for (i = 0; i < 6; i++) x[i] += (k1[i] + 2.0 * k2[i] + 2.0 * k3[i] + k4[i]) * t / 6.0;
}
/* glonass ephemeris to satellite clock bias -----------------------------------
* compute satellite clock bias with glonass ephemeris
* args : gtime_t time I time by satellite clock (gpst)
* geph_t *geph I glonass ephemeris
* return : satellite clock bias (s)
* notes : see ref [2]
*-----------------------------------------------------------------------------*/
double geph2clk(gtime_t time, const geph_t *geph)
{
double t;
int i;
trace(4, "geph2clk: time=%s sat=%2d\n", time_str(time, 3), geph->sat);
t = timediff(time, geph->toe);
for (i = 0; i < 2; i++)
{
t -= -geph->taun + geph->gamn * t;
}
return -geph->taun + geph->gamn * t;
}
/* glonass ephemeris to satellite position and clock bias ----------------------
* compute satellite position and clock bias with glonass ephemeris
* args : gtime_t time I time (gpst)
* geph_t *geph I glonass ephemeris
* double *rs O satellite position {x,y,z} (ecef) (m)
* double *dts O satellite clock bias (s)
* double *var O satellite position and clock variance (m^2)
* return : none
* notes : see ref [2]
*-----------------------------------------------------------------------------*/
void geph2pos(gtime_t time, const geph_t *geph, double *rs, double *dts,
double *var)
{
double t, tt, x[6];
int i;
trace(4, "geph2pos: time=%s sat=%2d\n", time_str(time, 3), geph->sat);
t = timediff(time, geph->toe);
*dts = -geph->taun + geph->gamn * t;
for (i = 0; i < 3; i++)
{
x[i ] = geph->pos[i];
x[i+3] = geph->vel[i];
}
for (tt = t < 0.0 ? - TSTEP : TSTEP; fabs(t) > 1e-9; t -= tt)
{
if (fabs(t) < TSTEP) tt = t;
glorbit(tt, x, geph->acc);
}
for (i = 0; i < 3; i++) rs[i] = x[i];
*var = std::pow(ERREPH_GLO, 2.0);
}
/* sbas ephemeris to satellite clock bias --------------------------------------
* compute satellite clock bias with sbas ephemeris
* args : gtime_t time I time by satellite clock (gpst)
* seph_t *seph I sbas ephemeris
* return : satellite clock bias (s)
* notes : see ref [3]
*-----------------------------------------------------------------------------*/
double seph2clk(gtime_t time, const seph_t *seph)
{
double t;
int i;
trace(4, "seph2clk: time=%s sat=%2d\n", time_str(time, 3), seph->sat);
t = timediff(time, seph->t0);
for (i = 0; i < 2; i++)
{
t-=seph->af0 + seph->af1 * t;
}
return seph->af0 + seph->af1 * t;
}
/* sbas ephemeris to satellite position and clock bias -------------------------
* compute satellite position and clock bias with sbas ephemeris
* args : gtime_t time I time (gpst)
* seph_t *seph I sbas ephemeris
* double *rs O satellite position {x,y,z} (ecef) (m)
* double *dts O satellite clock bias (s)
* double *var O satellite position and clock variance (m^2)
* return : none
* notes : see ref [3]
*-----------------------------------------------------------------------------*/
void seph2pos(gtime_t time, const seph_t *seph, double *rs, double *dts,
double *var)
{
double t;
int i;
trace(4, "seph2pos: time=%s sat=%2d\n", time_str(time, 3), seph->sat);
t = timediff(time, seph->t0);
for (i = 0; i < 3; i++)
{
rs[i] = seph->pos[i] + seph->vel[i] * t + seph->acc[i] * t * t / 2.0;
}
*dts = seph->af0 + seph->af1 * t;
*var = var_uraeph(seph->sva);
}
/* select ephememeris --------------------------------------------------------*/
eph_t *seleph(gtime_t time, int sat, int iode, const nav_t *nav)
{
double t, tmax, tmin;
int i, j = -1;
trace(4, "seleph : time=%s sat=%2d iode=%d\n", time_str(time, 3), sat, iode);
switch (satsys(sat, NULL))
{
case SYS_QZS: tmax = MAXDTOE_QZS + 1.0; break;
case SYS_GAL: tmax = MAXDTOE_GAL + 1.0; break;
case SYS_BDS: tmax = MAXDTOE_BDS + 1.0; break;
default: tmax = MAXDTOE + 1.0; break;
}
tmin = tmax + 1.0;
for (i = 0; i < nav->n; i++)
{
if (nav->eph[i].sat != sat) continue;
if (iode >= 0 && nav->eph[i].iode != iode) continue;
if ((t = fabs(timediff(nav->eph[i].toe, time))) > tmax) continue;
if (iode >= 0) return nav->eph + i;
if (t <= tmin) {j = i; tmin = t;} /* toe closest to time */
}
if (iode >= 0 || j<0)
{
trace(3, "no broadcast ephemeris: %s sat=%2d iode=%3d\n", time_str(time, 0),
sat, iode);
return NULL;
}
return nav->eph + j;
}
/* select glonass ephememeris ------------------------------------------------*/
geph_t *selgeph(gtime_t time, int sat, int iode, const nav_t *nav)
{
double t, tmax = MAXDTOE_GLO, tmin = tmax + 1.0;
int i, j = -1;
trace(4, "selgeph : time=%s sat=%2d iode=%2d\n", time_str(time, 3), sat, iode);
for (i = 0; i < nav->ng; i++)
{
if (nav->geph[i].sat != sat) continue;
if (iode >= 0 && nav->geph[i].iode != iode) continue;
if ((t = fabs(timediff(nav->geph[i].toe, time))) > tmax) continue;
if (iode >= 0) return nav->geph + i;
if (t <= tmin) {j = i; tmin = t;} /* toe closest to time */
}
if (iode >= 0 || j < 0)
{
trace(3, "no glonass ephemeris : %s sat=%2d iode=%2d\n", time_str(time, 0),
sat, iode);
return NULL;
}
return nav->geph + j;
}
/* select sbas ephememeris ---------------------------------------------------*/
seph_t *selseph(gtime_t time, int sat, const nav_t *nav)
{
double t, tmax = MAXDTOE_SBS, tmin = tmax + 1.0;
int i, j = -1;
trace(4, "selseph : time=%s sat=%2d\n", time_str(time, 3), sat);
for (i = 0; i < nav->ns; i++)
{
if (nav->seph[i].sat != sat) continue;
if ((t = fabs(timediff(nav->seph[i].t0, time))) > tmax) continue;
if (t <= tmin) {j = i; tmin = t;} /* toe closest to time */
}
if (j < 0)
{
trace(3, "no sbas ephemeris : %s sat=%2d\n", time_str(time, 0), sat);
return NULL;
}
return nav->seph + j;
}
/* satellite clock with broadcast ephemeris ----------------------------------*/
int ephclk(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
double *dts)
{
eph_t *eph;
geph_t *geph;
seph_t *seph;
int sys;
trace(4, "ephclk : time=%s sat=%2d\n", time_str(time, 3), sat);
sys = satsys(sat, NULL);
if (sys == SYS_GPS || sys == SYS_GAL || sys == SYS_QZS || sys == SYS_BDS)
{
if (!(eph = seleph(teph, sat, -1, nav))) return 0;
*dts = eph2clk(time, eph);
}
else if (sys == SYS_GLO)
{
if (!(geph = selgeph(teph, sat, -1, nav))) return 0;
*dts = geph2clk(time, geph);
}
else if (sys == SYS_SBS)
{
if (!(seph = selseph(teph, sat, nav))) return 0;
*dts = seph2clk(time, seph);
}
else return 0;
return 1;
}
/* satellite position and clock by broadcast ephemeris -----------------------*/
int ephpos(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
int iode, double *rs, double *dts, double *var, int *svh)
{
eph_t *eph;
geph_t *geph;
seph_t *seph;
double rst[3], dtst[1], tt = 1e-3;
int i, sys;
trace(4, "ephpos : time=%s sat=%2d iode=%d\n", time_str(time, 3), sat, iode);
sys = satsys(sat, NULL);
*svh = -1;
if (sys == SYS_GPS || sys == SYS_GAL || sys == SYS_QZS || sys == SYS_BDS)
{
if (!(eph = seleph(teph, sat, iode, nav))) return 0;
eph2pos(time, eph, rs, dts, var);
time = timeadd(time, tt);
eph2pos(time, eph, rst, dtst, var);
*svh = eph->svh;
}
else if (sys == SYS_GLO)
{
if (!(geph = selgeph(teph, sat, iode, nav))) return 0;
geph2pos(time, geph, rs, dts, var);
time = timeadd(time, tt);
geph2pos(time, geph, rst, dtst, var);
*svh = geph->svh;
}
else if (sys == SYS_SBS)
{
if (!(seph = selseph(teph, sat, nav))) return 0;
seph2pos(time, seph, rs, dts, var);
time = timeadd(time, tt);
seph2pos(time, seph, rst, dtst, var);
*svh = seph->svh;
}
else return 0;
/* satellite velocity and clock drift by differential approx */
for (i = 0; i < 3; i++) rs[i + 3] = (rst[i] - rs[i]) / tt;
dts[1] = (dtst[0] - dts[0]) / tt;
return 1;
}
/* satellite position and clock with sbas correction -------------------------*/
int satpos_sbas(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
double *rs, double *dts, double *var, int *svh)
{
const sbssatp_t *sbs;
int i;
trace(4, "satpos_sbas: time=%s sat=%2d\n", time_str(time, 3), sat);
/* search sbas satellite correciton */
for (i = 0; i < nav->sbssat.nsat; i++)
{
sbs = nav->sbssat.sat + i;
if (sbs->sat == sat) break;
}
if (i >= nav->sbssat.nsat)
{
trace(2, "no sbas correction for orbit: %s sat=%2d\n", time_str(time, 0), sat);
ephpos(time, teph, sat, nav, -1, rs, dts, var, svh);
*svh = -1;
return 0;
}
/* satellite postion and clock by broadcast ephemeris */
if (!ephpos(time, teph, sat, nav, sbs->lcorr.iode, rs, dts, var, svh)) return 0;
/* sbas satellite correction (long term and fast) */
if (sbssatcorr(time, sat, nav, rs, dts, var)) return 1;
*svh = -1;
return 0;
}
/* satellite position and clock with ssr correction --------------------------*/
int satpos_ssr(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
int opt, double *rs, double *dts, double *var, int *svh)
{
const ssr_t *ssr;
eph_t *eph;
double t1, t2, t3, er[3], ea[3], ec[3], rc[3], deph[3], dclk, dant[3] = {0}, tk;
int i, sys;
trace(4, "satpos_ssr: time=%s sat=%2d\n", time_str(time, 3), sat);
ssr = nav->ssr + sat - 1;
if (!ssr->t0[0].time)
{
trace(2, "no ssr orbit correction: %s sat=%2d\n", time_str(time, 0), sat);
return 0;
}
if (!ssr->t0[1].time)
{
trace(2, "no ssr clock correction: %s sat=%2d\n", time_str(time, 0), sat);
return 0;
}
/* inconsistency between orbit and clock correction */
if (ssr->iod[0] != ssr->iod[1])
{
trace(2, "inconsist ssr correction: %s sat=%2d iod=%d %d\n",
time_str(time, 0), sat, ssr->iod[0], ssr->iod[1]);
*svh = -1;
return 0;
}
t1 = timediff(time, ssr->t0[0]);
t2 = timediff(time, ssr->t0[1]);
t3 = timediff(time, ssr->t0[2]);
/* ssr orbit and clock correction (ref [4]) */
if (fabs(t1) > MAXAGESSR || fabs(t2) > MAXAGESSR)
{
trace(2, "age of ssr error: %s sat=%2d t=%.0f %.0f\n", time_str(time, 0),
sat, t1, t2);
*svh = -1;
return 0;
}
if (ssr->udi[0] >= 1.0) t1 -= ssr->udi[0] / 2.0;
if (ssr->udi[1] >= 1.0) t2 -= ssr->udi[0] / 2.0;
for (i = 0; i < 3; i++) deph[i] = ssr->deph[i] + ssr->ddeph[i] * t1;
dclk = ssr->dclk[0] + ssr->dclk[1] * t2 + ssr->dclk[2] * t2 * t2;
/* ssr highrate clock correction (ref [4]) */
if (ssr->iod[0] == ssr->iod[2] && ssr->t0[2].time && fabs(t3) < MAXAGESSR_HRCLK)
{
dclk += ssr->hrclk;
}
if (norm_rtk(deph, 3) > MAXECORSSR || fabs(dclk) > MAXCCORSSR)
{
trace(3, "invalid ssr correction: %s deph=%.1f dclk=%.1f\n",
time_str(time, 0), norm_rtk(deph, 3), dclk);
*svh = -1;
return 0;
}
/* satellite postion and clock by broadcast ephemeris */
if (!ephpos(time, teph, sat, nav, ssr->iode, rs, dts, var, svh)) return 0;
/* satellite clock for gps, galileo and qzss */
sys = satsys(sat, NULL);
if (sys == SYS_GPS || sys == SYS_GAL || sys == SYS_QZS || sys == SYS_BDS)
{
if (!(eph = seleph(teph, sat, ssr->iode, nav))) return 0;
/* satellite clock by clock parameters */
tk=timediff(time, eph->toc);
dts[0] = eph->f0 + eph->f1*tk + eph->f2 * tk * tk;
dts[1] = eph->f1 + 2.0*eph->f2 * tk;
/* relativity correction */
dts[0] -= 2.0 * dot(rs, rs + 3, 3) / SPEED_OF_LIGHT / SPEED_OF_LIGHT;
}
/* radial-along-cross directions in ecef */
if (!normv3(rs + 3, ea)) return 0;
cross3(rs, rs + 3, rc);
if (!normv3(rc, ec))
{
*svh = -1;
return 0;
}
cross3(ea, ec, er);
/* satellite antenna offset correction */
if (opt)
{
satantoff(time, rs, sat, nav, dant);
}
for (i = 0; i < 3; i++)
{
rs[i] += -(er[i] * deph[0] + ea[i] * deph[1] + ec[i] * deph[2]) + dant[i];
}
/* t_corr = t_sv - (dts(brdc) + dclk(ssr) / SPEED_OF_LIGHT) (ref [10] eq.3.12-7) */
dts[0] += dclk / SPEED_OF_LIGHT;
/* variance by ssr ura */
*var = var_urassr(ssr->ura);
trace(5, "satpos_ssr: %s sat=%2d deph=%6.3f %6.3f %6.3f er=%6.3f %6.3f %6.3f dclk=%6.3f var=%6.3f\n",
time_str(time, 2), sat, deph[0], deph[1], deph[2], er[0], er[1], er[2], dclk, *var);
return 1;
}
/* satellite position and clock ------------------------------------------------
* compute satellite position, velocity and clock
* args : gtime_t time I time (gpst)
* gtime_t teph I time to select ephemeris (gpst)
* int sat I satellite number
* nav_t *nav I navigation data
* int ephopt I ephemeris option (EPHOPT_???)
* double *rs O sat position and velocity (ecef)
* {x,y,z,vx,vy,vz} (m|m/s)
* double *dts O sat clock {bias,drift} (s|s/s)
* double *var O sat position and clock error variance (m^2)
* int *svh O sat health flag (-1:correction not available)
* return : status (1:ok,0:error)
* notes : satellite position is referenced to antenna phase center
* satellite clock does not include code bias correction (tgd or bgd)
*-----------------------------------------------------------------------------*/
int satpos(gtime_t time, gtime_t teph, int sat, int ephopt,
const nav_t *nav, double *rs, double *dts, double *var,
int *svh)
{
trace(4, "satpos : time=%s sat=%2d ephopt=%d\n", time_str(time, 3), sat, ephopt);
*svh = 0;
switch (ephopt)
{
case EPHOPT_BRDC : return ephpos (time, teph, sat, nav, -1, rs, dts, var, svh);
case EPHOPT_SBAS : return satpos_sbas(time, teph, sat, nav, rs, dts, var, svh);
case EPHOPT_SSRAPC: return satpos_ssr (time, teph, sat, nav, 0, rs, dts, var, svh);
case EPHOPT_SSRCOM: return satpos_ssr (time, teph, sat, nav, 1, rs, dts, var, svh);
case EPHOPT_PREC :
if (!peph2pos(time, sat, nav, 1, rs, dts, var)) break; else return 1;
//TODO: enable lex
//case EPHOPT_LEX :
// if (!lexeph2pos(time, sat, nav, rs, dts, var)) break; else return 1;
}
*svh = -1;
return 0;
}
/* satellite positions and clocks ----------------------------------------------
* compute satellite positions, velocities and clocks
* args : gtime_t teph I time to select ephemeris (gpst)
* obsd_t *obs I observation data
* int n I number of observation data
* nav_t *nav I navigation data
* int ephopt I ephemeris option (EPHOPT_???)
* double *rs O satellite positions and velocities (ecef)
* double *dts O satellite clocks
* double *var O sat position and clock error variances (m^2)
* int *svh O sat health flag (-1:correction not available)
* return : none
* notes : rs [(0:2)+i*6]= obs[i] sat position {x,y,z} (m)
* rs [(3:5)+i*6]= obs[i] sat velocity {vx,vy,vz} (m/s)
* dts[(0:1)+i*2]= obs[i] sat clock {bias,drift} (s|s/s)
* var[i] = obs[i] sat position and clock error variance (m^2)
* svh[i] = obs[i] sat health flag
* if no navigation data, set 0 to rs[], dts[], var[] and svh[]
* satellite position and clock are values at signal transmission time
* satellite position is referenced to antenna phase center
* satellite clock does not include code bias correction (tgd or bgd)
* any pseudorange and broadcast ephemeris are always needed to get
* signal transmission time
*-----------------------------------------------------------------------------*/
void satposs(gtime_t teph, const obsd_t *obs, int n, const nav_t *nav,
int ephopt, double *rs, double *dts, double *var, int *svh)
{
gtime_t time[MAXOBS] = {};
double dt, pr;
int i, j;
trace(3, "satposs : teph=%s n=%d ephopt=%d\n", time_str(teph, 3), n, ephopt);
for (i = 0; i < n && i < MAXOBS; i++)
{
for (j = 0; j < 6; j++) rs [j + i * 6] = 0.0;
for (j = 0; j < 2; j++) dts[j + i * 2] = 0.0;
var[i] = 0.0;
svh[i] = 0;
/* search any pseudorange */
for (j = 0, pr = 0.0; j < NFREQ; j++) if ((pr = obs[i].P[j]) != 0.0) break;
if (j >= NFREQ)
{
trace(2, "no pseudorange %s sat=%2d\n", time_str(obs[i].time, 3), obs[i].sat);
continue;
}
/* transmission time by satellite clock */
time[i] = timeadd(obs[i].time, -pr / SPEED_OF_LIGHT);
/* satellite clock bias by broadcast ephemeris */
if (!ephclk(time[i], teph, obs[i].sat, nav, &dt))
{
trace(3, "no broadcast clock %s sat=%2d\n", time_str(time[i], 3), obs[i].sat);
continue;
}
time[i] = timeadd(time[i], -dt);
/* satellite position and clock at transmission time */
if (!satpos(time[i], teph, obs[i].sat, ephopt, nav, rs + i * 6, dts + i * 2, var + i,
svh + i))
{
trace(3, "no ephemeris %s sat=%2d\n", time_str(time[i], 3), obs[i].sat);
continue;
}
/* if no precise clock available, use broadcast clock instead */
if (dts[i * 2] == 0.0)
{
if (!ephclk(time[i], teph, obs[i].sat, nav, dts + i * 2)) continue;
dts[1 + i * 2] = 0.0;
*var = std::pow(STD_BRDCCLK, 2.0);
}
}
for (i = 0; i < n && i < MAXOBS; i++)
{
trace(4, "%s sat=%2d rs=%13.3f %13.3f %13.3f dts=%12.3f var=%7.3f svh=%02X\n",
time_str(time[i], 6), obs[i].sat, rs[i * 6], rs[1 + i * 6], rs[2 + i * 6],
dts[i * 2] * 1e9, var[i], svh[i]);
}
}

View File

@ -0,0 +1,97 @@
/*!
* \file rtklib_ephemeris.h
* \brief satellite ephemeris and clock functions
* \authors <ul>
* <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*----------------------------------------------------------------------------*/
#ifndef GNSS_SDR_RTKLIB_EPHEMERIS_H_
#define GNSS_SDR_RTKLIB_EPHEMERIS_H_
#include "rtklib.h"
double var_uraeph(int ura);
double var_urassr(int ura);
void alm2pos(gtime_t time, const alm_t *alm, double *rs, double *dts);
double eph2clk(gtime_t time, const eph_t *eph);
void eph2pos(gtime_t time, const eph_t *eph, double *rs, double *dts,
double *var);
void deq(const double *x, double *xdot, const double *acc);
void glorbit(double t, double *x, const double *acc);
double geph2clk(gtime_t time, const geph_t *geph);
void geph2pos(gtime_t time, const geph_t *geph, double *rs, double *dts,
double *var);
double seph2clk(gtime_t time, const seph_t *seph);
void seph2pos(gtime_t time, const seph_t *seph, double *rs, double *dts,
double *var);
eph_t *seleph(gtime_t time, int sat, int iode, const nav_t *nav);
geph_t *selgeph(gtime_t time, int sat, int iode, const nav_t *nav);
seph_t *selseph(gtime_t time, int sat, const nav_t *nav);
int ephclk(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
double *dts);
//satellite position and clock by broadcast ephemeris
int ephpos(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
int iode, double *rs, double *dts, double *var, int *svh);
int satpos_sbas(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
double *rs, double *dts, double *var, int *svh);
int satpos_ssr(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
int opt, double *rs, double *dts, double *var, int *svh);
int satpos(gtime_t time, gtime_t teph, int sat, int ephopt,
const nav_t *nav, double *rs, double *dts, double *var,
int *svh);
void satposs(gtime_t teph, const obsd_t *obs, int n, const nav_t *nav,
int ephopt, double *rs, double *dts, double *var, int *svh);
#endif /* GNSS_SDR_RTKLIB_EPHEMERIS_H_ */

View File

@ -0,0 +1,590 @@
/*!
* \file rtklib_ionex.h
* \brief ionex functions
* \authors <ul>
* <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* References:
* [1] S.Schear, W.Gurtner and J.Feltens, IONEX: The IONosphere Map EXchange
* Format Version 1, February 25, 1998
* [2] S.Schaer, R.Markus, B.Gerhard and A.S.Timon, Daily Global Ionosphere
* Maps based on GPS Carrier Phase Data Routinely producted by CODE
* Analysis Center, Proceeding of the IGS Analysis Center Workshop, 1996
*
*----------------------------------------------------------------------------*/
#include "rtklib_ionex.h"
#include "rtklib_rtkcmn.h"
/* get index -----------------------------------------------------------------*/
int getindex(double value, const double *range)
{
if (range[2] == 0.0) return 0;
if (range[1] > 0.0 && (value < range[0] || range[1]<value)) return -1;
if (range[1] < 0.0 && (value < range[1] || range[0]<value)) return -1;
return (int)floor((value - range[0]) / range[2] + 0.5);
}
/* get number of items -------------------------------------------------------*/
int nitem(const double *range)
{
return getindex(range[1], range) + 1;
}
/* data index (i:lat,j:lon,k:hgt) --------------------------------------------*/
int dataindex(int i, int j, int k, const int *ndata)
{
if (i < 0 || ndata[0] <= i || j < 0 || ndata[1] <= j || k < 0 || ndata[2] <= k) return -1;
return i + ndata[0] * (j + ndata[1] * k);
}
/* add tec data to navigation data -------------------------------------------*/
tec_t *addtec(const double *lats, const double *lons, const double *hgts,
double rb, nav_t *nav)
{
tec_t *p, *nav_tec;
gtime_t time0 = {0, 0};
int i, n, ndata[3];
trace(3, "addtec :\n");
ndata[0] = nitem(lats);
ndata[1] = nitem(lons);
ndata[2] = nitem(hgts);
if (ndata[0] <= 1 || ndata[1] <= 1 || ndata[2] <= 0) return NULL;
if (nav->nt >= nav->ntmax)
{
nav->ntmax+=256;
if (!(nav_tec = (tec_t *)realloc(nav->tec, sizeof(tec_t)*nav->ntmax)))
{
trace(1, "readionex malloc error ntmax=%d\n", nav->ntmax);
free(nav->tec); nav->tec = NULL; nav->nt = nav->ntmax = 0;
return NULL;
}
nav->tec = nav_tec;
}
p = nav->tec+nav->nt;
p->time = time0;
p->rb = rb;
for (i = 0; i < 3; i++)
{
p->ndata[i] = ndata[i];
p->lats[i] = lats[i];
p->lons[i] = lons[i];
p->hgts[i] = hgts[i];
}
n = ndata[0] * ndata[1] * ndata[2];
if (!(p->data = (double *)malloc(sizeof(double) * n)) ||
!(p->rms = (float *)malloc(sizeof(float ) * n)))
{
return NULL;
}
for (i = 0; i < n; i++)
{
p->data[i] = 0.0;
p->rms [i] = 0.0f;
}
nav->nt++;
return p;
}
/* read ionex dcb aux data ----------------------------------------------------*/
void readionexdcb(FILE *fp, double *dcb, double *rms)
{
int i, sat;
char buff[1024], id[32], *label;
trace(3, "readionexdcb:\n");
for (i = 0; i < MAXSAT; i++) dcb[i] = rms[i] = 0.0;
while (fgets(buff, sizeof(buff), fp))
{
if (strlen(buff) < 60) continue;
label = buff + 60;
if (strstr(label, "PRN / BIAS / RMS") == label)
{
strncpy(id, buff+3, 3); id[3] = '\0';
if (!(sat = satid2no(id)))
{
trace(2, "ionex invalid satellite: %s\n", id);
continue;
}
dcb[sat-1] = str2num(buff, 6, 10);
rms[sat-1] = str2num(buff, 16, 10);
}
else if (strstr(label, "END OF AUX DATA") == label) break;
}
}
/* read ionex header ---------------------------------------------------------*/
double readionexh(FILE *fp, double *lats, double *lons, double *hgts,
double *rb, double *nexp, double *dcb, double *rms)
{
double ver = 0.0;
char buff[1024], *label;
trace(3, "readionexh:\n");
while (fgets(buff, sizeof(buff), fp))
{
if (strlen(buff) < 60) continue;
label = buff + 60;
if (strstr(label, "IONEX VERSION / TYPE") == label)
{
if (buff[20] == 'I') ver = str2num(buff, 0, 8);
}
else if (strstr(label, "BASE RADIUS") == label)
{
*rb = str2num(buff, 0, 8);
}
else if (strstr(label, "HGT1 / HGT2 / DHGT") == label)
{
hgts[0] = str2num(buff, 2, 6);
hgts[1] = str2num(buff, 8, 6);
hgts[2] = str2num(buff, 14, 6);
}
else if (strstr(label, "LAT1 / LAT2 / DLAT") == label)
{
lats[0] = str2num(buff, 2, 6);
lats[1] = str2num(buff, 8, 6);
lats[2] = str2num(buff, 14, 6);
}
else if (strstr(label,"LON1 / LON2 / DLON") == label)
{
lons[0] = str2num(buff, 2, 6);
lons[1] = str2num(buff, 8, 6);
lons[2] = str2num(buff, 14, 6);
}
else if (strstr(label, "EXPONENT") == label)
{
*nexp = str2num(buff, 0, 6);
}
else if (strstr(label, "START OF AUX DATA") == label &&
strstr(buff, "DIFFERENTIAL CODE BIASES"))
{
readionexdcb(fp, dcb, rms);
}
else if (strstr(label, "END OF HEADER") == label)
{
return ver;
}
}
return 0.0;
}
/* read ionex body -----------------------------------------------------------*/
int readionexb(FILE *fp, const double *lats, const double *lons,
const double *hgts, double rb, double nexp, nav_t *nav)
{
tec_t *p = NULL;
gtime_t time = {0, 0};
double lat, lon[3], hgt, x;
int i, j, k, n, m, index, type = 0;
char buff[1024], *label = buff + 60;
trace(3, "readionexb:\n");
while (fgets(buff, sizeof(buff), fp))
{
if (strlen(buff) < 60) continue;
if (strstr(label, "START OF TEC MAP") == label)
{
if ((p = addtec(lats, lons, hgts, rb, nav))) type = 1;
}
else if (strstr(label, "END OF TEC MAP") == label)
{
type = 0;
p = NULL;
}
else if (strstr(label, "START OF RMS MAP") == label)
{
type = 2;
p = NULL;
}
else if (strstr(label, "END OF RMS MAP") == label)
{
type = 0;
p = NULL;
}
else if (strstr(label, "EPOCH OF CURRENT MAP") == label)
{
if (str2time(buff, 0, 36, &time))
{
trace(2, "ionex epoch invalid: %-36.36s\n", buff);
continue;
}
if (type == 2)
{
for (i = nav->nt-1; i >= 0; i--)
{
if (fabs(timediff(time, nav->tec[i].time)) >= 1.0) continue;
p = nav->tec + i;
break;
}
}
else if (p) p->time = time;
}
else if (strstr(label, "LAT/LON1/LON2/DLON/H") == label && p)
{
lat = str2num(buff, 2, 6);
lon[0] = str2num(buff, 8, 6);
lon[1] = str2num(buff, 14, 6);
lon[2] = str2num(buff, 20, 6);
hgt = str2num(buff, 26, 6);
i = getindex(lat, p->lats);
k = getindex(hgt, p->hgts);
n = nitem(lon);
for (m = 0; m < n; m++)
{
if (m % 16 == 0 && !fgets(buff, sizeof(buff), fp)) break;
j = getindex(lon[0] + lon[2] * m, p->lons);
if ((index = dataindex(i, j, k, p->ndata)) < 0) continue;
if ((x = str2num(buff, m % 16 * 5, 5)) == 9999.0) continue;
if (type == 1) p->data[index] = x * std::pow(10.0, nexp);
else p->rms[index] = (float)(x * std::pow(10.0, nexp));
}
}
}
return 1;
}
/* combine tec grid data -----------------------------------------------------*/
void combtec(nav_t *nav)
{
tec_t tmp;
int i, j, n = 0;
trace(3, "combtec : nav->nt=%d\n", nav->nt);
for (i = 0; i < nav->nt - 1; i++)
{
for (j = i + 1; j < nav->nt; j++)
{
if (timediff(nav->tec[j].time, nav->tec[i].time) < 0.0)
{
tmp = nav->tec[i];
nav->tec[i] = nav->tec[j];
nav->tec[j] = tmp;
}
}
}
for (i = 0; i < nav->nt; i++)
{
if (i > 0 && timediff(nav->tec[i].time, nav->tec[n - 1].time) == 0.0)
{
free(nav->tec[n - 1].data);
free(nav->tec[n - 1].rms );
nav->tec[n - 1] = nav->tec[i];
continue;
}
nav->tec[n++] = nav->tec[i];
}
nav->nt = n;
trace(4, "combtec : nav->nt=%d\n", nav->nt);
}
/* read ionex tec grid file ----------------------------------------------------
* read ionex ionospheric tec grid file
* args : char *file I ionex tec grid file
* (wind-card * is expanded)
* nav_t *nav IO navigation data
* nav->nt, nav->ntmax and nav->tec are modified
* int opt I read option (1: no clear of tec data,0:clear)
* return : none
* notes : see ref [1]
*-----------------------------------------------------------------------------*/
void readtec(const char *file, nav_t *nav, int opt)
{
FILE *fp;
double lats[3] = {0}, lons[3] = {0}, hgts[3] = {0}, rb = 0.0, nexp = -1.0;
double dcb[MAXSAT] = {0}, rms[MAXSAT] = {0};
int i, n;
char *efiles[MAXEXFILE];
trace(3, "readtec : file=%s\n", file);
/* clear of tec grid data option */
if (!opt)
{
free(nav->tec);
nav->tec = NULL;
nav->nt = nav->ntmax = 0;
}
for (i = 0; i < MAXEXFILE; i++)
{
if (!(efiles[i] = (char *)malloc(1024)))
{
for (i--; i >= 0; i--) free(efiles[i]);
return;
}
}
/* expand wild card in file path */
n = expath(file, efiles, MAXEXFILE);
for (i = 0; i < n; i++)
{
if (!(fp = fopen(efiles[i], "r")))
{
trace(2, "ionex file open error %s\n", efiles[i]);
continue;
}
/* read ionex header */
if (readionexh(fp, lats, lons, hgts, &rb, &nexp, dcb, rms) <= 0.0)
{
trace(2, "ionex file format error %s\n", efiles[i]);
continue;
}
/* read ionex body */
readionexb(fp, lats, lons, hgts, rb, nexp, nav);
fclose(fp);
}
for (i = 0; i < MAXEXFILE; i++) free(efiles[i]);
/* combine tec grid data */
if (nav->nt > 0) combtec(nav);
/* P1-P2 dcb */
for (i = 0; i < MAXSAT; i++)
{
nav->cbias[i][0] = SPEED_OF_LIGHT * dcb[i] * 1e-9; /* ns->m */
}
}
/* interpolate tec grid data -------------------------------------------------*/
int interptec(const tec_t *tec, int k, const double *posp, double *value,
double *rms)
{
double dlat, dlon, a, b, d[4] = {0}, r[4] = {0};
int i, j, n, index;
trace(3, "interptec: k=%d posp=%.2f %.2f\n", k, posp[0] * R2D, posp[1] * R2D);
*value = *rms = 0.0;
if (tec->lats[2] == 0.0 || tec->lons[2] == 0.0) return 0;
dlat = posp[0] * R2D - tec->lats[0];
dlon = posp[1] * R2D - tec->lons[0];
if (tec->lons[2] > 0.0) dlon -= floor( dlon / 360) * 360.0; /* 0 <= dlon<360 */
else dlon += floor(-dlon / 360) * 360.0; /* -360<dlon <= 0 */
a = dlat / tec->lats[2];
b = dlon / tec->lons[2];
i = (int)floor(a);
a -= i;
j = (int)floor(b);
b -= j;
/* get gridded tec data */
for (n = 0; n < 4; n++)
{
if ((index = dataindex(i + (n % 2), j + (n < 2 ? 0 : 1), k, tec->ndata)) < 0) continue;
d[n] = tec->data[index];
r[n] = tec->rms[index];
}
if (d[0] > 0.0 && d[1] > 0.0 && d[2] > 0.0 && d[3] > 0.0)
{
/* bilinear interpolation (inside of grid) */
*value = (1.0 - a) * (1.0 - b) * d[0] + a*(1.0 -b) * d[1] + (1.0 - a) * b * d[2] + a * b * d[3];
*rms = (1.0 - a) * (1.0 - b) * r[0] + a*(1.0 - b) * r[1] + (1.0 - a) * b * r[2] + a * b * r[3];
}
/* nearest-neighbour extrapolation (outside of grid) */
else if (a <= 0.5 && b <= 0.5 && d[0] > 0.0) {*value = d[0]; *rms = r[0];}
else if (a > 0.5 && b <= 0.5 && d[1] > 0.0) {*value = d[1]; *rms = r[1];}
else if (a <= 0.5 && b > 0.5 && d[2] > 0.0) {*value = d[2]; *rms = r[2];}
else if (a > 0.5 && b > 0.5 && d[3] > 0.0) {*value = d[3]; *rms = r[3];}
else
{
i = 0;
for (n = 0; n < 4; n++) if (d[n] > 0.0) {i++; *value += d[n]; *rms += r[n];}
if(i == 0) return 0;
*value /= i;
*rms /= i;
}
return 1;
}
/* ionosphere delay by tec grid data -----------------------------------------*/
int iondelay(gtime_t time, const tec_t *tec, const double *pos,
const double *azel, int opt, double *delay, double *var)
{
const double fact = 40.30E16 / FREQ1 / FREQ1; /* tecu->L1 iono (m) */
double fs, posp[3] = {0}, vtec, rms, hion, rp;
int i;
trace(3, "iondelay: time=%s pos=%.1f %.1f azel=%.1f %.1f\n", time_str(time, 0),
pos[0]*R2D, pos[1]*R2D, azel[0]*R2D, azel[1]*R2D);
*delay = *var = 0.0;
for (i = 0;i < tec->ndata[2]; i++)
{ /* for a layer */
hion = tec->hgts[0] + tec->hgts[2] * i;
/* ionospheric pierce point position */
fs = ionppp(pos, azel, tec->rb, hion, posp);
if (opt&2)
{
/* modified single layer mapping function (M-SLM) ref [2] */
rp = tec->rb / (tec->rb + hion) * sin(0.9782 * (PI / 2.0 - azel[1]));
fs = 1.0 / sqrt(1.0 - rp * rp);
}
if (opt&1)
{
/* earth rotation correction (sun-fixed coordinate) */
posp[1] += 2.0 * PI * timediff(time, tec->time) / 86400.0;
}
/* interpolate tec grid data */
if (!interptec(tec, i, posp, &vtec, &rms)) return 0;
*delay += fact * fs * vtec;
*var += fact * fact * fs * fs * rms * rms;
}
trace(4, "iondelay: delay=%7.2f std=%6.2f\n", *delay, sqrt(*var));
return 1;
}
/* ionosphere model by tec grid data -------------------------------------------
* compute ionospheric delay by tec grid data
* args : gtime_t time I time (gpst)
* nav_t *nav I navigation data
* double *pos I receiver position {lat,lon,h} (rad,m)
* double *azel I azimuth/elevation angle {az,el} (rad)
* int opt I model option
* bit0: 0:earth-fixed,1:sun-fixed
* bit1: 0:single-layer,1:modified single-layer
* double *delay O ionospheric delay (L1) (m)
* double *var O ionospheric dealy (L1) variance (m^2)
* return : status (1:ok,0:error)
* notes : before calling the function, read tec grid data by calling readtec()
* return ok with delay=0 and var=VAR_NOTEC if el<MIN_EL or h<MIN_HGT
*-----------------------------------------------------------------------------*/
int iontec(gtime_t time, const nav_t *nav, const double *pos,
const double *azel, int opt, double *delay, double *var)
{
double dels[2], vars[2], a, tt;
int i, stat[2];
trace(3, "iontec : time=%s pos=%.1f %.1f azel=%.1f %.1f\n", time_str(time, 0),
pos[0] * R2D, pos[1] * R2D, azel[0] * R2D, azel[1] * R2D);
if (azel[1] < MIN_EL || pos[2] < MIN_HGT)
{
*delay = 0.0;
*var = VAR_NOTEC;
return 1;
}
for (i = 0; i < nav->nt; i++)
{
if (timediff(nav->tec[i].time, time) > 0.0) break;
}
if (i == 0 || i >= nav->nt)
{
trace(2, "%s: tec grid out of period\n", time_str(time, 0));
return 0;
}
if ((tt = timediff(nav->tec[i].time, nav->tec[i-1].time)) == 0.0)
{
trace(2, "tec grid time interval error\n");
return 0;
}
/* ionospheric delay by tec grid data */
stat[0] = iondelay(time, nav->tec+i-1, pos, azel, opt, dels , vars );
stat[1] = iondelay(time, nav->tec+i , pos, azel, opt, dels+1, vars+1);
if (!stat[0] && !stat[1])
{
trace(2, "%s: tec grid out of area pos=%6.2f %7.2f azel=%6.1f %5.1f\n",
time_str(time, 0), pos[0] * R2D, pos[1] * R2D, azel[0] * R2D, azel[1] * R2D);
return 0;
}
if (stat[0] && stat[1])
{ /* linear interpolation by time */
a = timediff(time, nav->tec[i-1].time) / tt;
*delay = dels[0] * (1.0 - a) + dels[1] * a;
*var = vars[0] * (1.0 - a) + vars[1] * a;
}
else if (stat[0])
{ /* nearest-neighbour extrapolation by time */
*delay = dels[0];
*var = vars[0];
}
else
{
*delay = dels[1];
*var = vars[1];
}
trace(3, "iontec : delay=%5.2f std=%5.2f\n", *delay, sqrt(*var));
return 1;
}

View File

@ -0,0 +1,90 @@
/*!
* \file rtklib_ionex.h
* \brief ionex functions
* \authors <ul>
* <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* References:
* [1] S.Schear, W.Gurtner and J.Feltens, IONEX: The IONosphere Map EXchange
* Format Version 1, February 25, 1998
* [2] S.Schaer, R.Markus, B.Gerhard and A.S.Timon, Daily Global Ionosphere
* Maps based on GPS Carrier Phase Data Routinely producted by CODE
* Analysis Center, Proceeding of the IGS Analysis Center Workshop, 1996
*
*----------------------------------------------------------------------------*/
#ifndef GNSS_SDR_RTKLIB_IONEX_H_
#define GNSS_SDR_RTKLIB_IONEX_H_
#include "rtklib.h"
const double VAR_NOTEC = 30.0 * 30.0; /* variance of no tec */
const double MIN_EL = 0.0; /* min elevation angle (rad) */
const double MIN_HGT = -1000.0; /* min user height (m) */
int getindex(double value, const double *range);
int nitem(const double *range);
int dataindex(int i, int j, int k, const int *ndata);
tec_t *addtec(const double *lats, const double *lons, const double *hgts,
double rb, nav_t *nav);
void readionexdcb(FILE *fp, double *dcb, double *rms);
double readionexh(FILE *fp, double *lats, double *lons, double *hgts,
double *rb, double *nexp, double *dcb, double *rms);
int readionexb(FILE *fp, const double *lats, const double *lons,
const double *hgts, double rb, double nexp, nav_t *nav);
void combtec(nav_t *nav);
void readtec(const char *file, nav_t *nav, int opt);
int interptec(const tec_t *tec, int k, const double *posp, double *value,
double *rms);
int iondelay(gtime_t time, const tec_t *tec, const double *pos,
const double *azel, int opt, double *delay, double *var);
int iontec(gtime_t time, const nav_t *nav, const double *pos,
const double *azel, int opt, double *delay, double *var);
#endif /* GNSS_SDR_RTKLIB_IONEX_H_ */

View File

@ -0,0 +1,327 @@
/*!
* \file rtklib_lambda.cc
* \brief Integer ambiguity resolution
* \authors <ul>
* <li> 2007-2008, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2008, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*----------------------------------------------------------------------------*/
#include "rtklib_lambda.h"
#include "rtklib_rtkcmn.h"
/* LD factorization (Q=L'*diag(D)*L) -----------------------------------------*/
int LD(int n, const double *Q, double *L, double *D)
{
int i,j,k,info = 0;
double a,*A = mat(n,n);
memcpy(A,Q,sizeof(double)*n*n);
for (i = n-1; i >= 0; i--)
{
if ((D[i] = A[i+i*n])<=0.0) {info = -1; break;}
a = sqrt(D[i]);
for (j = 0; j<=i; j++) L[i+j*n] = A[i+j*n]/a;
for (j = 0; j<=i-1; j++) for (k = 0;k<=j;k++) A[j+k*n] -= L[i+k*n]*L[i+j*n];
for (j = 0; j<=i; j++) L[i+j*n] /= L[i+i*n];
}
free(A);
if (info) fprintf(stderr,"%s : LD factorization error\n",__FILE__);
return info;
}
/* integer gauss transformation ----------------------------------------------*/
void gauss(int n, double *L, double *Z, int i, int j)
{
int k,mu;
if ((mu = (int)ROUND_LAMBDA(L[i+j*n]))!=0)
{
for (k = i; k<n; k++) L[k+n*j] -= (double)mu*L[k+i*n];
for (k = 0; k<n; k++) Z[k+n*j] -= (double)mu*Z[k+i*n];
}
}
/* permutations --------------------------------------------------------------*/
void perm(int n, double *L, double *D, int j, double del, double *Z)
{
int k;
double eta,lam,a0,a1;
eta = D[j]/del;
lam = D[j+1]*L[j+1+j*n]/del;
D[j] = eta*D[j+1]; D[j+1] = del;
for (k = 0; k<=j-1; k++)
{
a0 = L[j+k*n];
a1 = L[j+1+k*n];
L[j+k*n] = -L[j+1+j*n]*a0+a1;
L[j+1+k*n] = eta*a0+lam*a1;
}
L[j+1+j*n] = lam;
for (k = j+2;k<n;k++) SWAP_LAMBDA(L[k+j*n],L[k+(j+1)*n]);
for (k = 0;k<n;k++) SWAP_LAMBDA(Z[k+j*n],Z[k+(j+1)*n]);
}
/* lambda reduction (z=Z'*a, Qz=Z'*Q*Z=L'*diag(D)*L) (ref.[1]) ---------------*/
void reduction(int n, double *L, double *D, double *Z)
{
int i,j,k;
double del;
j = n-2; k = n-2;
while (j >= 0)
{
if (j<=k) for (i = j+1; i<n; i++) gauss(n,L,Z,i,j);
del = D[j]+L[j+1+j*n]*L[j+1+j*n]*D[j+1];
if (del+1E-6<D[j+1])
{ /* compared considering numerical error */
perm(n,L,D,j,del,Z);
k = j; j = n-2;
}
else j--;
}
}
/* modified lambda (mlambda) search (ref. [2]) -------------------------------*/
int search(int n, int m, const double *L, const double *D,
const double *zs, double *zn, double *s)
{
int i,j,k,c,nn = 0,imax = 0;
double newdist,maxdist = 1E99,y;
double *S = zeros(n,n),*dist = mat(n,1),*zb = mat(n,1),*z = mat(n,1),*step = mat(n,1);
k = n-1; dist[k] = 0.0;
zb[k] = zs[k];
z[k] = ROUND_LAMBDA(zb[k]);
y = zb[k]-z[k];
step[k] = SGN_LAMBDA(y);
for (c = 0; c<LOOPMAX; c++)
{
newdist = dist[k]+y*y/D[k];
if (newdist<maxdist)
{
if (k!=0)
{
dist[--k] = newdist;
for (i = 0; i<=k; i++)
S[k+i*n] = S[k+1+i*n]+(z[k+1]-zb[k+1])*L[k+1+i*n];
zb[k] = zs[k]+S[k+k*n];
z[k] = ROUND_LAMBDA(zb[k]); y = zb[k]-z[k]; step[k] = SGN_LAMBDA(y);
}
else
{
if (nn<m)
{
if (nn == 0||newdist>s[imax]) imax = nn;
for (i = 0; i<n; i++) zn[i+nn*n] = z[i];
s[nn++] = newdist;
}
else
{
if (newdist<s[imax])
{
for (i = 0; i<n; i++) zn[i+imax*n] = z[i];
s[imax] = newdist;
for (i = imax = 0; i<m; i++) if (s[imax]<s[i]) imax = i;
}
maxdist = s[imax];
}
z[0] += step[0]; y = zb[0]-z[0]; step[0] = -step[0]-SGN_LAMBDA(step[0]);
}
}
else
{
if (k == n-1) break;
else
{
k++;
z[k] += step[k]; y = zb[k]-z[k]; step[k] = -step[k]-SGN_LAMBDA(step[k]);
}
}
}
for (i = 0; i<m-1; i++)
{ /* sort by s */
for (j = i+1; j<m; j++)
{
if (s[i]<s[j]) continue;
SWAP_LAMBDA(s[i],s[j]);
for (k = 0; k<n; k++) SWAP_LAMBDA(zn[k+i*n],zn[k+j*n]);
}
}
free(S); free(dist); free(zb); free(z); free(step);
if (c >= LOOPMAX)
{
fprintf(stderr,"%s : search loop count overflow\n",__FILE__);
return -1;
}
return 0;
}
/* lambda/mlambda integer least-square estimation ------------------------------
* integer least-square estimation. reduction is performed by lambda (ref.[1]),
* and search by mlambda (ref.[2]).
* args : int n I number of float parameters
* int m I number of fixed solutions
* double *a I float parameters (n x 1)
* double *Q I covariance matrix of float parameters (n x n)
* double *F O fixed solutions (n x m)
* double *s O sum of squared residulas of fixed solutions (1 x m)
* return : status (0:ok,other:error)
* notes : matrix stored by column-major order (fortran convension)
*-----------------------------------------------------------------------------*/
int lambda(int n, int m, const double *a, const double *Q, double *F,
double *s)
{
int info;
double *L,*D,*Z,*z,*E;
if (n<=0||m<=0) return -1;
L = zeros(n,n);
D = mat(n,1);
Z = eye(n);
z = mat(n,1);
E = mat(n,m);
/* LD factorization */
if (!(info = LD(n,Q,L,D)))
{
/* lambda reduction */
reduction(n,L,D,Z);
matmul("TN",n,1,n,1.0,Z,a,0.0,z); /* z=Z'*a */
/* mlambda search */
if (!(info = search(n,m,L,D,z,E,s)))
{
info = solve("T",Z,E,n,m,F); /* F=Z'\E */
}
}
free(L); free(D); free(Z); free(z); free(E);
return info;
}
/* lambda reduction ------------------------------------------------------------
* reduction by lambda (ref [1]) for integer least square
* args : int n I number of float parameters
* double *Q I covariance matrix of float parameters (n x n)
* double *Z O lambda reduction matrix (n x n)
* return : status (0:ok,other:error)
*-----------------------------------------------------------------------------*/
int lambda_reduction(int n, const double *Q, double *Z)
{
double *L,*D;
int i,j,info;
if (n<=0) return -1;
L = zeros(n,n);
D = mat(n,1);
for (i = 0; i<n; i++) for (j = 0; j<n; j++)
{
Z[i+j*n] = i == j ? 1.0 : 0.0;
}
/* LD factorization */
if ((info = LD(n,Q,L,D)))
{
free(L);
free(D);
return info;
}
/* lambda reduction */
reduction(n,L,D,Z);
free(L);
free(D);
return 0;
}
/* mlambda search --------------------------------------------------------------
* search by mlambda (ref [2]) for integer least square
* args : int n I number of float parameters
* int m I number of fixed solutions
* double *a I float parameters (n x 1)
* double *Q I covariance matrix of float parameters (n x n)
* double *F O fixed solutions (n x m)
* double *s O sum of squared residulas of fixed solutions (1 x m)
* return : status (0:ok,other:error)
*-----------------------------------------------------------------------------*/
int lambda_search(int n, int m, const double *a, const double *Q,
double *F, double *s)
{
double *L,*D;
int info;
if (n<=0||m<=0) return -1;
L = zeros(n,n);
D = mat(n,1);
/* LD factorization */
if ((info = LD(n,Q,L,D)))
{
free(L);
free(D);
return info;
}
/* mlambda search */
info = search(n,m,L,D,a,F,s);
free(L);
free(D);
return info;
}

View File

@ -0,0 +1,87 @@
/*!
* \file rtklib_lambda.h
* \brief Integer ambiguity resolution
* \authors <ul>
* <li> 2007-2008, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2008, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* References:
* [1] P.J.G.Teunissen, The least-square ambiguity decorrelation adjustment:
* a method for fast GPS ambiguity estimation, J.Geodesy, Vol.70, 65-82,
* 1995
* [2] X.-W.Chang, X.Yang, T.Zhou, MLAMBDA: A modified LAMBDA method for
* integer least-squares estimation, J.Geodesy, Vol.79, 552-565, 2005
*
*----------------------------------------------------------------------------*/
#ifndef GNSS_SDR_RTKLIB_LAMBDA_H_
#define GNSS_SDR_RTKLIB_LAMBDA_H_
#include "rtklib.h"
/* constants/macros ----------------------------------------------------------*/
const int LOOPMAX = 10000; /* maximum count of search loop */
#define SGN_LAMBDA(x) ((x)<=0.0?-1.0:1.0)
#define ROUND_LAMBDA(x) (floor((x)+0.5))
#define SWAP_LAMBDA(x,y) do {double tmp_; tmp_=x; x=y; y=tmp_;} while (0)
int LD(int n, const double *Q, double *L, double *D);
void gauss(int n, double *L, double *Z, int i, int j);
void perm(int n, double *L, double *D, int j, double del, double *Z);
void reduction(int n, double *L, double *D, double *Z);
int search(int n, int m, const double *L, const double *D,
const double *zs, double *zn, double *s);
int lambda(int n, int m, const double *a, const double *Q, double *F, double *s);
int lambda_reduction(int n, const double *Q, double *Z);
int lambda_search(int n, int m, const double *a, const double *Q,
double *F, double *s);
#endif

View File

@ -0,0 +1,790 @@
/*!
* \file rtklib_pntpos.cc
* \brief standard code-based positioning
* \authors <ul>
* <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*----------------------------------------------------------------------------*/
#include "rtklib_pntpos.h"
#include "rtklib_ephemeris.h"
#include "rtklib_ionex.h"
#include "rtklib_sbas.h"
/* pseudorange measurement error variance ------------------------------------*/
double varerr(const prcopt_t *opt, double el, int sys)
{
double fact, varr;
fact = sys == SYS_GLO ? EFACT_GLO : (sys == SYS_SBS ? EFACT_SBS : EFACT_GPS);
varr = std::pow(opt->err[0], 2.0) * (std::pow(opt->err[1], 2.0) + std::pow(opt->err[2], 2.0) / sin(el));
if (opt->ionoopt == IONOOPT_IFLC) varr *= std::pow(2, 3.0); /* iono-free */
return std::pow(fact, 2.0) * varr;
}
/* get tgd parameter (m) -----------------------------------------------------*/
double gettgd(int sat, const nav_t *nav)
{
int i;
for (i = 0; i < nav->n; i++)
{
if (nav->eph[i].sat != sat) continue;
return SPEED_OF_LIGHT * nav->eph[i].tgd[0];
}
return 0.0;
}
/* psendorange with code bias correction -------------------------------------*/
double prange(const obsd_t *obs, const nav_t *nav, const double *azel,
int iter, const prcopt_t *opt, double *var)
{
const double *lam = nav->lam[obs->sat - 1];
double PC, P1, P2, P1_P2, P1_C1, P2_C2, gamma;
int i = 0, j = 1, sys;
*var = 0.0;
if (!(sys = satsys(obs->sat, NULL)))
{
trace(4, "prange: satsys NULL\n");
return 0.0;
}
/* L1-L2 for GPS/GLO/QZS, L1-L5 for GAL/SBS */
if (NFREQ >= 3 && (sys & (SYS_GAL | SYS_SBS))) j = 2;
if (NFREQ<2 || lam[i] == 0.0 || lam[j] == 0.0)
{
trace(4, "prange: NFREQ<2||lam[i]==0.0||lam[j]==0.0\n");
printf("i: %d j:%d, lam[i]: %f lam[j] %f\n", i, j, lam[i], lam[j]);
return 0.0;
}
/* test snr mask */
if (iter>0)
{
if (testsnr(0, i, azel[1], obs->SNR[i] * 0.25, &opt->snrmask))
{
trace(4, "snr mask: %s sat=%2d el=%.1f snr=%.1f\n",
time_str(obs->time, 0), obs->sat, azel[1] * R2D, obs->SNR[i] * 0.25);
return 0.0;
}
if (opt->ionoopt == IONOOPT_IFLC)
{
if (testsnr(0, j, azel[1], obs->SNR[j] * 0.25, &opt->snrmask))
{
trace(4, "prange: testsnr error\n");
return 0.0;
}
}
}
gamma = std::pow(lam[j], 2.0) / std::pow(lam[i], 2.0); /* f1^2/f2^2 */
P1 = obs->P[i];
P2 = obs->P[j];
P1_P2 = nav->cbias[obs->sat-1][0];
P1_C1 = nav->cbias[obs->sat-1][1];
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)))
{
P1_P2 = (1.0 - gamma) * gettgd(obs->sat, nav);
}
if (opt->ionoopt == IONOOPT_IFLC)
{ /* dual-frequency */
if (P1 == 0.0 || P2 == 0.0) return 0.0;
if (obs->code[i] == CODE_L1C) P1 += P1_C1; /* C1->P1 */
if (obs->code[j] == CODE_L2C) P2 += P2_C2; /* C2->P2 */
/* iono-free combination */
PC = (gamma * P1 - P2) / (gamma - 1.0);
}
else
{ /* single-frequency */
if (P1 == 0.0) return 0.0;
if (obs->code[i] == CODE_L1C) P1 += P1_C1; /* C1->P1 */
PC = P1 - P1_P2 / (1.0 - gamma);
}
if (opt->sateph == EPHOPT_SBAS) PC -= P1_C1; /* sbas clock based C1 */
*var = std::pow(ERR_CBIAS, 2.0);
return PC;
}
/* ionospheric correction ------------------------------------------------------
* compute ionospheric correction
* args : gtime_t time I time
* nav_t *nav I navigation data
* int sat I satellite number
* double *pos I receiver position {lat,lon,h} (rad|m)
* double *azel I azimuth/elevation angle {az,el} (rad)
* int ionoopt I ionospheric correction option (IONOOPT_???)
* double *ion O ionospheric delay (L1) (m)
* double *var O ionospheric delay (L1) variance (m^2)
* return : status(1:ok,0:error)
*-----------------------------------------------------------------------------*/
int ionocorr(gtime_t time, const nav_t *nav, int sat, const double *pos,
const double *azel, int ionoopt, double *ion, double *var)
{
trace(4, "ionocorr: time=%s opt=%d sat=%2d pos=%.3f %.3f azel=%.3f %.3f\n",
time_str(time, 3), ionoopt, sat, pos[0]*R2D, pos[1]*R2D, azel[0]*R2D,
azel[1]*R2D);
/* broadcast model */
if (ionoopt == IONOOPT_BRDC)
{
*ion = ionmodel(time, nav->ion_gps, pos, azel);
*var = std::pow(*ion * ERR_BRDCI, 2.0);
return 1;
}
/* sbas ionosphere model */
if (ionoopt == IONOOPT_SBAS)
{
return sbsioncorr(time, nav, pos, azel, ion, var);
}
/* ionex tec model */
if (ionoopt == IONOOPT_TEC)
{
return iontec(time, nav, pos, azel, 1, ion, var);
}
/* qzss broadcast model */
if (ionoopt == IONOOPT_QZS && norm_rtk(nav->ion_qzs, 8)>0.0)
{
*ion = ionmodel(time, nav->ion_qzs, pos, azel);
*var = std::pow(*ion * ERR_BRDCI, 2.0);
return 1;
}
/* lex ionosphere model */
//if (ionoopt == IONOOPT_LEX) {
// return lexioncorr(time, nav, pos, azel, ion, var);
//}
*ion = 0.0;
*var = ionoopt == IONOOPT_OFF ? std::pow(ERR_ION, 2.0) : 0.0;
return 1;
}
/* tropospheric correction -----------------------------------------------------
* compute tropospheric correction
* args : gtime_t time I time
* nav_t *nav I navigation data
* double *pos I receiver position {lat,lon,h} (rad|m)
* double *azel I azimuth/elevation angle {az,el} (rad)
* int tropopt I tropospheric correction option (TROPOPT_???)
* double *trp O tropospheric delay (m)
* double *var O tropospheric delay variance (m^2)
* return : status(1:ok,0:error)
*-----------------------------------------------------------------------------*/
int tropcorr(gtime_t time, const nav_t *nav __attribute__((unused)), const double *pos,
const double *azel, int tropopt, double *trp, double *var)
{
trace(4, "tropcorr: time=%s opt=%d pos=%.3f %.3f azel=%.3f %.3f\n",
time_str(time, 3), tropopt, pos[0]*R2D, pos[1]*R2D, azel[0]*R2D,
azel[1]*R2D);
/* saastamoinen model */
if (tropopt == TROPOPT_SAAS || tropopt == TROPOPT_EST || tropopt == TROPOPT_ESTG)
{
*trp = tropmodel(time, pos, azel, REL_HUMI);
*var = std::pow(ERR_SAAS / (sin(azel[1]) + 0.1), 2.0);
return 1;
}
/* sbas troposphere model */
if (tropopt == TROPOPT_SBAS)
{
*trp = sbstropcorr(time, pos, azel, var);
return 1;
}
/* no correction */
*trp = 0.0;
*var = tropopt == TROPOPT_OFF ? std::pow(ERR_TROP, 2.0) : 0.0;
return 1;
}
/* pseudorange residuals -----------------------------------------------------*/
int rescode(int iter, const obsd_t *obs, int n, const double *rs,
const double *dts, const double *vare, const int *svh,
const nav_t *nav, const double *x, const prcopt_t *opt,
double *v, double *H, double *var, double *azel, int *vsat,
double *resp, int *ns)
{
double r, dion, dtrp, vmeas, vion, vtrp, rr[3], pos[3], dtr, e[3], P, lam_L1;
int i, j, nv = 0, sys, mask[4] = {0};
trace(3, "resprng : n=%d\n", n);
for (i = 0; i < 3; i++) rr[i] = x[i];
dtr = x[3];
ecef2pos(rr, pos);
for (i = *ns = 0; i < n && i < MAXOBS; i++)
{
vsat[i] = 0;
azel[i*2] = azel[1+i*2] = resp[i] = 0.0;
if (!(sys = satsys(obs[i].sat, NULL))) continue;
/* reject duplicated observation data */
if (i < n - 1 && i < MAXOBS - 1 && obs[i].sat == obs[i+1].sat)
{
trace(2, "duplicated observation data %s sat=%2d\n",
time_str(obs[i].time, 3), obs[i].sat);
i++;
continue;
}
/* geometric distance/azimuth/elevation angle */
if ((r = geodist(rs + i * 6, rr, e)) <= 0.0 || satazel(pos, e, azel + i * 2) < opt->elmin)
{
trace(4, "geodist / satazel error\n");
continue;
}
/* psudorange with code bias correction */
if ((P = prange(obs+i, nav, azel+i*2, iter, opt, &vmeas)) == 0.0)
{
trace(4, "prange error\n");
continue;
}
/* excluded satellite? */
if (satexclude(obs[i].sat, svh[i], opt))
{
trace(4, "satexclude error\n");
continue;
}
/* ionospheric corrections */
if (!ionocorr(obs[i].time, nav, obs[i].sat, pos, azel+i*2,
iter>0 ? opt->ionoopt : IONOOPT_BRDC, &dion, &vion))
{
trace(4, "ionocorr error\n");
continue;
}
/* GPS-L1 -> L1/B1 */
if ((lam_L1 = nav->lam[obs[i].sat - 1][0]) > 0.0)
{
dion *= std::pow(lam_L1 / lam_carr[0], 2.0);
}
/* tropospheric corrections */
if (!tropcorr(obs[i].time, nav, pos, azel + i*2,
iter > 0 ? opt->tropopt : TROPOPT_SAAS, &dtrp, &vtrp))
{
trace(4, "tropocorr error\n");
continue;
}
/* pseudorange residual */
v[nv] = P - (r + dtr - SPEED_OF_LIGHT * dts[i*2] + dion + dtrp);
/* design matrix */
for (j = 0; j < NX; j++) H[j + nv * NX] = j < 3 ? - e[j] : (j == 3 ? 1.0 : 0.0);
/* time system and receiver bias offset correction */
if (sys == SYS_GLO) {v[nv] -= x[4]; H[4+nv*NX] = 1.0; mask[1] = 1;}
else if (sys == SYS_GAL) {v[nv] -= x[5]; H[5+nv*NX] = 1.0; mask[2] = 1;}
else if (sys == SYS_BDS) {v[nv] -= x[6]; H[6+nv*NX] = 1.0; mask[3] = 1;}
else mask[0] = 1;
vsat[i] = 1;
resp[i] = v[nv];
(*ns)++;
/* error variance */
var[nv++] = varerr(opt, azel[1+i*2], sys) + vare[i] + vmeas + vion + vtrp;
trace(4, "sat=%2d azel=%5.1f %4.1f res=%7.3f sig=%5.3f\n", obs[i].sat,
azel[i*2] * R2D, azel[1+i*2] * R2D, resp[i], sqrt(var[nv-1]));
}
/* constraint to avoid rank-deficient */
for (i = 0; i < 4; i++)
{
if (mask[i]) continue;
v[nv] = 0.0;
for (j = 0; j < NX; j++) H[j + nv * NX] = j == i + 3 ? 1.0 : 0.0;
var[nv++] = 0.01;
}
return nv;
}
/* validate solution ---------------------------------------------------------*/
int valsol(const double *azel, const int *vsat, int n,
const prcopt_t *opt, const double *v, int nv, int nx,
char *msg)
{
double azels[MAXOBS*2], dop[4], vv;
int i, ns;
trace(3, "valsol : n=%d nv=%d\n", n, nv);
/* chi-square validation of residuals */
vv = dot(v, v, nv);
if (nv > nx && vv > chisqr[nv-nx-1])
{
sprintf(msg, "chi-square error nv=%d vv=%.1f cs=%.1f", nv, vv, chisqr[nv-nx-1]);
return 0;
}
/* large gdop check */
for (i = ns = 0; i < n; i++)
{
if (!vsat[i]) continue;
azels[ ns*2] = azel[ i*2];
azels[1+ns*2] = azel[1+i*2];
ns++;
}
dops(ns, azels, opt->elmin, dop);
if (dop[0] <= 0.0 || dop[0] > opt->maxgdop)
{
sprintf(msg, "gdop error nv=%d gdop=%.1f", nv, dop[0]);
return 0;
}
return 1;
}
/* estimate receiver position ------------------------------------------------*/
int estpos(const obsd_t *obs, int n, const double *rs, const double *dts,
const double *vare, const int *svh, const nav_t *nav,
const prcopt_t *opt, sol_t *sol, double *azel, int *vsat,
double *resp, char *msg)
{
double x[NX] = {0}, dx[NX], Q[NX*NX], *v, *H, *var, sig;
int i, j, k, info, stat, nv, ns;
trace(3, "estpos : n=%d\n", n);
v = mat(n + 4, 1);
H = mat(NX, n + 4);
var = mat(n + 4, 1);
for (i = 0; i < 3; i++) x[i] = sol->rr[i];
for (i = 0; i < MAXITR; i++)
{
/* pseudorange residuals */
nv = rescode(i, obs, n, rs, dts, vare, svh, nav, x, opt, v, H, var, azel, vsat, resp, &ns);
if (nv < NX)
{
sprintf(msg, "lack of valid sats ns=%d", nv);
break;
}
/* weight by variance */
for (j = 0;j < nv; j++)
{
sig = sqrt(var[j]);
v[j] /= sig;
for (k = 0; k < NX; k++) H[k + j * NX] /= sig;
}
/* least square estimation */
if ((info = lsq(H, v, NX, nv, dx, Q)))
{
sprintf(msg, "lsq error info=%d", info);
break;
}
for (j = 0; j < NX; j++) x[j] += dx[j];
if (norm_rtk(dx, NX) < 1e-4)
{
sol->type = 0;
sol->time = timeadd(obs[0].time, -x[3] / SPEED_OF_LIGHT);
sol->dtr[0] = x[3] / SPEED_OF_LIGHT; /* receiver clock bias (s) */
sol->dtr[1] = x[4] / SPEED_OF_LIGHT; /* glo-gps time offset (s) */
sol->dtr[2] = x[5] / SPEED_OF_LIGHT; /* gal-gps time offset (s) */
sol->dtr[3] = x[6] / SPEED_OF_LIGHT; /* bds-gps time offset (s) */
for (j = 0; j < 6; j++) sol->rr[j] = j < 3 ? x[j] : 0.0;
for (j = 0; j < 3; j++) sol->qr[j] = (float)Q[j + j * NX];
sol->qr[3] = (float)Q[1]; /* cov xy */
sol->qr[4] = (float)Q[2 + NX]; /* cov yz */
sol->qr[5] = (float)Q[2]; /* cov zx */
sol->ns = (unsigned char)ns;
sol->age = sol->ratio = 0.0;
/* validate solution */
if ((stat = valsol(azel, vsat, n, opt, v, nv, NX, msg)))
{
sol->stat = opt->sateph == EPHOPT_SBAS ? SOLQ_SBAS : SOLQ_SINGLE;
}
free(v);
free(H);
free(var);
return stat;
}
}
if (i >= MAXITR) sprintf(msg, "iteration divergent i=%d", i);
free(v);
free(H);
free(var);
return 0;
}
/* raim fde (failure detection and exclution) -------------------------------*/
int raim_fde(const obsd_t *obs, int n, const double *rs,
const double *dts, const double *vare, const int *svh,
const nav_t *nav, const prcopt_t *opt, sol_t *sol,
double *azel, int *vsat, double *resp, char *msg)
{
obsd_t *obs_e;
sol_t sol_e = { {0, 0}, {}, {}, {}, '0', '0', '0', 0.0, 0.0, 0.0};
char tstr[32], name[16], msg_e[128];
double *rs_e, *dts_e, *vare_e, *azel_e, *resp_e, rms_e, rms = 100.0;
int i, j, k, nvsat, stat = 0, *svh_e, *vsat_e, sat = 0;
trace(3, "raim_fde: %s n=%2d\n", time_str(obs[0].time, 0), n);
if (!(obs_e = (obsd_t *)malloc(sizeof(obsd_t) * n))) return 0;
rs_e = mat(6, n);
dts_e = mat(2, n);
vare_e = mat(1, n);
azel_e = zeros(2, n);
svh_e = imat(1, n);
vsat_e = imat(1, n);
resp_e = mat(1, n);
for (i = 0; i < n; i++)
{
/* satellite exclution */
for (j = k = 0; j < n; j++)
{
if (j == i) continue;
obs_e[k] = obs[j];
matcpy(rs_e + 6 * k, rs + 6 * j, 6, 1);
matcpy(dts_e + 2 * k, dts + 2 * j, 2, 1);
vare_e[k] = vare[j];
svh_e[k++] = svh[j];
}
/* estimate receiver position without a satellite */
if (!estpos(obs_e, n-1, rs_e, dts_e, vare_e, svh_e, nav, opt, &sol_e, azel_e,
vsat_e, resp_e, msg_e))
{
trace(3, "raim_fde: exsat=%2d (%s)\n", obs[i].sat, msg);
continue;
}
for (j = nvsat = 0, rms_e = 0.0; j < n - 1; j++)
{
if (!vsat_e[j]) continue;
rms_e += std::pow(resp_e[j], 2.0);
nvsat++;
}
if (nvsat < 5)
{
trace(3, "raim_fde: exsat=%2d lack of satellites nvsat=%2d\n",
obs[i].sat, nvsat);
continue;
}
rms_e = sqrt(rms_e / nvsat);
trace(3, "raim_fde: exsat=%2d rms=%8.3f\n", obs[i].sat, rms_e);
if (rms_e > rms) continue;
/* save result */
for (j = k = 0; j < n; j++)
{
if (j == i) continue;
matcpy(azel + 2 * j, azel_e + 2 * k, 2, 1);
vsat[j] = vsat_e[k];
resp[j] = resp_e[k++];
}
stat = 1;
*sol = sol_e;
sat = obs[i].sat;
rms = rms_e;
vsat[i] = 0;
strcpy(msg, msg_e);
}
if (stat)
{
time2str(obs[0].time, tstr, 2); satno2id(sat, name);
trace(2, "%s: %s excluded by raim\n", tstr + 11, name);
}
free(obs_e);
free(rs_e);
free(dts_e);
free(vare_e);
free(azel_e);
free(svh_e);
free(vsat_e);
free(resp_e);
return stat;
}
/* doppler residuals ---------------------------------------------------------*/
int resdop(const obsd_t *obs, int n, const double *rs, const double *dts,
const nav_t *nav, const double *rr, const double *x,
const double *azel, const int *vsat, double *v, double *H)
{
double lam, rate, pos[3], E[9], a[3], e[3], vs[3], cosel;
int i, j, nv = 0;
trace(3, "resdop : n=%d\n", n);
ecef2pos(rr, pos);
xyz2enu(pos, E);
for (i = 0; i < n && i < MAXOBS; i++)
{
lam = nav->lam[obs[i].sat-1][0];
if (obs[i].D[0] == 0.0 || lam == 0.0 || !vsat[i] || norm_rtk(rs + 3 + i * 6, 3) <= 0.0)
{
continue;
}
/* line-of-sight vector in ecef */
cosel = cos(azel[1+i*2]);
a[0] = sin(azel[i*2]) * cosel;
a[1] = cos(azel[i*2]) * cosel;
a[2] = sin(azel[1+i*2]);
matmul("TN", 3, 1, 3, 1.0, E, a, 0.0, e);
/* satellite velocity relative to receiver in ecef */
for (j = 0; j < 3; j++) vs[j] = rs[j+3+i*6] - x[j];
/* range rate with earth rotation correction */
rate = dot(vs, e, 3) + DEFAULT_OMEGA_EARTH_DOT / SPEED_OF_LIGHT * (rs[4 + i * 6] * rr[0] + rs[1 + i * 6] * x[0]-
rs[3 + i * 6] * rr[1] - rs[i * 6] * x[1]);
/* doppler residual */
v[nv] =- lam * obs[i].D[0] - (rate + x[3] - SPEED_OF_LIGHT * dts[1 + i *2]);
/* design matrix */
for (j = 0; j < 4; j++) H[j + nv * 4] = j < 3 ? - e[j] : 1.0;
nv++;
}
return nv;
}
/* estimate receiver velocity ------------------------------------------------*/
void estvel(const obsd_t *obs, int n, const double *rs, const double *dts,
const nav_t *nav, const prcopt_t *opt __attribute__((unused)), sol_t *sol,
const double *azel, const int *vsat)
{
double x[4] = {0}, dx[4], Q[16], *v, *H;
int i, j, nv;
trace(3, "estvel : n=%d\n", n);
v = mat(n, 1);
H = mat(4, n);
for (i = 0; i < MAXITR; i++)
{
/* doppler residuals */
if ((nv = resdop(obs, n, rs, dts, nav, sol->rr, x, azel, vsat, v, H)) < 4)
{
break;
}
/* least square estimation */
if (lsq(H, v, 4, nv, dx, Q)) break;
for (j = 0; j < 4; j++) x[j] += dx[j];
if (norm_rtk(dx, 4) < 1e-6)
{
for (i = 0; i < 3; i++) sol->rr[i+3] = x[i];
break;
}
}
free(v);
free(H);
}
/* single-point positioning ----------------------------------------------------
* compute receiver position, velocity, clock bias by single-point positioning
* with pseudorange and doppler observables
* args : obsd_t *obs I observation data
* int n I number of observation data
* nav_t *nav I navigation data
* prcopt_t *opt I processing options
* sol_t *sol IO solution
* double *azel IO azimuth/elevation angle (rad) (NULL: no output)
* ssat_t *ssat IO satellite status (NULL: no output)
* char *msg O error message for error exit
* return : status(1:ok,0:error)
* notes : assuming sbas-gps, galileo-gps, qzss-gps, compass-gps time offset and
* receiver bias are negligible (only involving glonass-gps time offset
* and receiver bias)
*-----------------------------------------------------------------------------*/
int pntpos(const obsd_t *obs, int n, const nav_t *nav,
const prcopt_t *opt, sol_t *sol, double *azel, ssat_t *ssat,
char *msg)
{
// int k = 0;
// for (k = 0;k<n;k++)
// {
// printf("OBS[%i]: sat %i, P:%f ,LLI:%s \r\n",k,obs[k].sat,obs[k].P[0], obs[k].LLI);
// }
//
// for (k = 0;k<nav->n;k++)
// {
// printf("NAV[%i]: sat %i, %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f \r\n",
// k,
// nav->eph[k].sat,
// nav->eph[k].A,
// nav->eph[k].Adot,
// nav->eph[k].M0,
// nav->eph[k].OMG0,
// nav->eph[k].OMGd,
// nav->eph[k].cic,
// nav->eph[k].cis,
// nav->eph[k].code,
// nav->eph[k].crc,
// nav->eph[k].crs,
// nav->eph[k].cuc,
// nav->eph[k].cus,
// nav->eph[k].deln,
// nav->eph[k].e,
// nav->eph[k].f0,
// nav->eph[k].f1,
// nav->eph[k].f2,
// nav->eph[k].fit,
// nav->eph[k].flag,
// nav->eph[k].i0,
// nav->eph[k].idot,
// nav->eph[k].iodc,
// nav->eph[k].iode,
// nav->eph[k].ndot,
// nav->eph[k].omg,
// nav->eph[k].sat,
// nav->eph[k].sva,
// nav->eph[k].svh,
// nav->eph[k].tgd[0],
// nav->eph[k].toc.sec,
// nav->eph[k].toe.sec,
// nav->eph[k].toes,
// nav->eph[k].ttr.sec,
// nav->eph[k].week);
// }
prcopt_t opt_ = *opt;
double *rs, *dts, *var, *azel_, *resp;
int i, stat, vsat[MAXOBS] = {0}, svh[MAXOBS];
sol->stat = SOLQ_NONE;
if (n <= 0) {strcpy(msg, "no observation data"); return 0;}
trace(3, "pntpos : tobs=%s n=%d\n", time_str(obs[0].time, 3), n);
sol->time = obs[0].time;
msg[0] = '\0';
rs = mat(6, n);
dts = mat(2, n);
var = mat(1, n);
azel_ = zeros(2, n);
resp = mat(1, n);
if (opt_.mode != PMODE_SINGLE)
{ /* for precise positioning */
#if 0
opt_.sateph = EPHOPT_BRDC;
#endif
opt_.ionoopt = IONOOPT_BRDC;
opt_.tropopt = TROPOPT_SAAS;
}
/* satellite positons, velocities and clocks */
satposs(sol->time, obs, n, nav, opt_.sateph, rs, dts, var, svh);
/* estimate receiver position with pseudorange */
stat = estpos(obs, n, rs, dts, var, svh, nav, &opt_, sol, azel_, vsat, resp, msg);
/* raim fde */
if (!stat && n >= 6 && opt->posopt[4])
{
stat = raim_fde(obs, n, rs, dts, var, svh, nav, &opt_, sol, azel_, vsat, resp, msg);
}
/* estimate receiver velocity with doppler */
if (stat) estvel(obs, n, rs, dts, nav, &opt_, sol, azel_, vsat);
if (azel)
{
for (i = 0; i < n * 2; i++) azel[i] = azel_[i];
}
if (ssat)
{
for (i = 0; i < MAXSAT; i++)
{
ssat[i].vs = 0;
ssat[i].azel[0] = ssat[i].azel[1] = 0.0;
ssat[i].resp[0] = ssat[i].resc[0] = 0.0;
ssat[i].snr[0] = 0;
}
for (i = 0; i < n; i++)
{
ssat[obs[i].sat-1].azel[0] = azel_[ i*2];
ssat[obs[i].sat-1].azel[1] = azel_[1+i*2];
ssat[obs[i].sat-1].snr[0] = obs[i].SNR[0];
if (!vsat[i]) continue;
ssat[obs[i].sat-1].vs = 1;
ssat[obs[i].sat-1].resp[0] = resp[i];
}
}
free(rs);
free(dts);
free(var);
free(azel_);
free(resp);
return stat;
}

View File

@ -0,0 +1,159 @@
/*!
* \file rtklib_pntpos.h
* \brief standard code-based positioning
* \authors <ul>
* <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*----------------------------------------------------------------------------*/
#ifndef GNSS_SDR_RTKLIB_PNTPOS_H_
#define GNSS_SDR_RTKLIB_PNTPOS_H_
#include "rtklib.h"
#include "rtklib_rtkcmn.h"
/* constants -----------------------------------------------------------------*/
const int NX = 4 + 3; //!< # of estimated parameters
const int MAXITR = 10; //!< max number of iteration for point pos
const double ERR_ION = 5.0; //!< ionospheric delay std (m)
const double ERR_TROP = 3.0; //!< tropspheric delay std (m)
/* pseudorange measurement error variance ------------------------------------*/
double varerr(const prcopt_t *opt, double el, int sys);
/* get tgd parameter (m) -----------------------------------------------------*/
double gettgd(int sat, const nav_t *nav);
/* psendorange with code bias correction -------------------------------------*/
double prange(const obsd_t *obs, const nav_t *nav, const double *azel,
int iter, const prcopt_t *opt, double *var);
/* ionospheric correction ------------------------------------------------------
* compute ionospheric correction
* args : gtime_t time I time
* nav_t *nav I navigation data
* int sat I satellite number
* double *pos I receiver position {lat,lon,h} (rad|m)
* double *azel I azimuth/elevation angle {az,el} (rad)
* int ionoopt I ionospheric correction option (IONOOPT_???)
* double *ion O ionospheric delay (L1) (m)
* double *var O ionospheric delay (L1) variance (m^2)
* return : status(1:ok,0:error)
*-----------------------------------------------------------------------------*/
int ionocorr(gtime_t time, const nav_t *nav, int sat, const double *pos,
const double *azel, int ionoopt, double *ion, double *var);
/* tropospheric correction -----------------------------------------------------
* compute tropospheric correction
* args : gtime_t time I time
* nav_t *nav I navigation data
* double *pos I receiver position {lat,lon,h} (rad|m)
* double *azel I azimuth/elevation angle {az,el} (rad)
* int tropopt I tropospheric correction option (TROPOPT_???)
* double *trp O tropospheric delay (m)
* double *var O tropospheric delay variance (m^2)
* return : status(1:ok,0:error)
*-----------------------------------------------------------------------------*/
int tropcorr(gtime_t time, const nav_t *nav, const double *pos,
const double *azel, int tropopt, double *trp, double *var);
/* pseudorange residuals -----------------------------------------------------*/
int rescode(int iter, const obsd_t *obs, int n, const double *rs,
const double *dts, const double *vare, const int *svh,
const nav_t *nav, const double *x, const prcopt_t *opt,
double *v, double *H, double *var, double *azel, int *vsat,
double *resp, int *ns);
/* validate solution ---------------------------------------------------------*/
int valsol(const double *azel, const int *vsat, int n,
const prcopt_t *opt, const double *v, int nv, int nx,
char *msg);
/* estimate receiver position ------------------------------------------------*/
int estpos(const obsd_t *obs, int n, const double *rs, const double *dts,
const double *vare, const int *svh, const nav_t *nav,
const prcopt_t *opt, sol_t *sol, double *azel, int *vsat,
double *resp, char *msg);
/* raim fde (failure detection and exclution) -------------------------------*/
int raim_fde(const obsd_t *obs, int n, const double *rs,
const double *dts, const double *vare, const int *svh,
const nav_t *nav, const prcopt_t *opt, sol_t *sol,
double *azel, int *vsat, double *resp, char *msg);
/* doppler residuals ---------------------------------------------------------*/
int resdop(const obsd_t *obs, int n, const double *rs, const double *dts,
const nav_t *nav, const double *rr, const double *x,
const double *azel, const int *vsat, double *v, double *H);
/* estimate receiver velocity ------------------------------------------------*/
void estvel(const obsd_t *obs, int n, const double *rs, const double *dts,
const nav_t *nav, const prcopt_t *opt, sol_t *sol,
const double *azel, const int *vsat);
/*!
* \brief single-point positioning
* compute receiver position, velocity, clock bias by single-point positioning
* with pseudorange and doppler observables
* args : obsd_t *obs I observation data
* int n I number of observation data
* nav_t *nav I navigation data
* prcopt_t *opt I processing options
* sol_t *sol IO solution
* double *azel IO azimuth/elevation angle (rad) (NULL: no output)
* ssat_t *ssat IO satellite status (NULL: no output)
* char *msg O error message for error exit
* return : status(1:ok,0:error)
* notes : assuming sbas-gps, galileo-gps, qzss-gps, compass-gps time offset and
* receiver bias are negligible (only involving glonass-gps time offset
* and receiver bias)
*/
int pntpos(const obsd_t *obs, int n, const nav_t *nav,
const prcopt_t *opt, sol_t *sol, double *azel, ssat_t *ssat,
char *msg);
#endif /* GNSS_SDR_RTKLIB_PNTPOS_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,186 @@
/*!
* \file rtklib_ppp.h
* \brief Precise Point Positioning
* \authors <ul>
* <li> 2007-2008, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2008, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*----------------------------------------------------------------------------*/
#ifndef GNSS_SDR_RTKLIB_PPP_H_
#define GNSS_SDR_RTKLIB_PPP_H_
#include "rtklib.h"
#define MIN_PPP(x,y) ((x)<=(y)?(x):(y))
#define ROUND_PPP(x) (int)floor((x)+0.5)
#define SWAP_I(x,y) do {int _z=x; x=y; y=_z;} while (0)
#define SWAP_D(x,y) do {double _z=x; x=y; y=_z;} while (0)
const double MIN_ARC_GAP = 300.0; /* min arc gap (s) */
const double CONST_AMB = 0.001; /* constraint to fixed ambiguity */
const double THRES_RES = 0.3; /* threashold of residuals test (m) */
const double LOG_PI = 1.14472988584940017; /* log(pi) */
const double SQRT2 = 1.41421356237309510; /* sqrt(2) */
const double VAR_POS_PPP = std::pow(100.0, 2.0); /* init variance receiver position (m^2) */
const double VAR_CLK = std::pow(100.0, 2.0); /* init variance receiver clock (m^2) */
const double VAR_ZTD = std::pow( 0.3, 2.0); /* init variance ztd (m^2) */
const double VAR_GRA_PPP = std::pow(0.001, 2.0); /* init variance gradient (m^2) */
const double VAR_BIAS = std::pow(100.0, 2.0); /* init variance phase-bias (m^2) */
const double VAR_IONO_OFF = std::pow(10.0, 2.0); /* variance of iono-model-off */
/* functions originally included in RTKLIB/src/ppp_ar.c v2.4.2*/
double lam_LC(int i, int j, int k);
double L_LC(int i, int j, int k, const double *L);
double P_LC(int i, int j, int k, const double *P);
double var_LC(int i, int j, int k, double sig);
double q_gamma(double a, double x, double log_gamma_a);
double p_gamma(double a, double x, double log_gamma_a);
double f_erfc(double x);
double conffunc(int N, double B, double sig);
void average_LC(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav, const double *azel);
int fix_amb_WL(rtk_t *rtk, const nav_t *nav, int sat1, int sat2, int *NW);
int is_depend(int sat1, int sat2, int *flgs, int *max_flg);
int sel_amb(int *sat1, int *sat2, double *N, double *var, int n);
int fix_sol(rtk_t *rtk, const int *sat1, const int *sat2, const double *NC, int n);
int fix_amb_ROUND(rtk_t *rtk, int *sat1, int *sat2, const int *NW, int n);
int fix_amb_ILS(rtk_t *rtk, int *sat1, int *sat2, int *NW, int n);
int pppamb(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav, const double *azel);
/* functions originally included in RTKLIB/src/ppp.c v2.4.2 */
void pppoutsolstat(rtk_t *rtk, int level, FILE *fp);
void tide_pl(const double *eu, const double *rp, double GMp, const double *pos, double *dr);
void tide_solid(const double *rsun, const double *rmoon,
const double *pos, const double *E, double gmst, int opt,
double *dr);
void tide_oload(gtime_t tut, const double *odisp, double *denu);
void iers_mean_pole(gtime_t tut, double *xp_bar, double *yp_bar);
void tide_pole(gtime_t tut, const double *pos, const double *erpv, double *denu);
void tidedisp(gtime_t tutc, const double *rr, int opt, const erp_t *erp,
const double *odisp, double *dr);
void testeclipse(const obsd_t *obs, int n, const nav_t *nav, double *rs);
double varerr(int sat, int sys, double el, int type, const prcopt_t *opt);
void initx(rtk_t *rtk, double xi, double var, int i);
int ifmeas(const obsd_t *obs, const nav_t *nav, const double *azel,
const prcopt_t *opt, const double *dantr, const double *dants,
double phw, double *meas, double *var);
double gettgd_ppp(int sat, const nav_t *nav);
int corr_ion(gtime_t time, const nav_t *nav, int sat, const double *pos,
const double *azel, int ionoopt, double *ion, double *var,
int *brk);
int corrmeas(const obsd_t *obs, const nav_t *nav, const double *pos,
const double *azel, const prcopt_t *opt,
const double *dantr, const double *dants, double phw,
double *meas, double *var, int *brk);
double gfmeas(const obsd_t *obs, const nav_t *nav);
void udpos_ppp(rtk_t *rtk);
void udclk_ppp(rtk_t *rtk);
void udtrop_ppp(rtk_t *rtk);
void detslp_ll(rtk_t *rtk, const obsd_t *obs, int n);
void detslp_gf(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav);
void udbias_ppp(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav);
void udstate_ppp(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav);
void satantpcv(const double *rs, const double *rr, const pcv_t *pcv, double *dant);
double prectrop(gtime_t time, const double *pos, const double *azel,
const prcopt_t *opt, const double *x, double *dtdx,
double *var);
int res_ppp(int iter, const obsd_t *obs, int n, const double *rs,
const double *dts, const double *vare, const int *svh,
const nav_t *nav, const double *x, rtk_t *rtk, double *v,
double *H, double *R, double *azel);
int pppnx(const prcopt_t *opt);
void pppos(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav);
#endif

View File

@ -0,0 +1,873 @@
/*!
* \file rtklib_preceph.cc
* \brief precise ephemeris and clock functions
* \authors <ul>
* <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* References :
* [1] S.Hilla, The Extended Standard Product 3 Orbit Format (SP3-c),
* 12 February, 2007
* [2] J.Ray, W.Gurtner, RINEX Extensions to Handle Clock Information,
* 27 August, 1998
* [3] D.D.McCarthy, IERS Technical Note 21, IERS Conventions 1996, July 1996
* [4] D.A.Vallado, Fundamentals of Astrodynamics and Applications 2nd ed,
* Space Technology Library, 2004
*
*----------------------------------------------------------------------------*/
#include "rtklib_preceph.h"
#include "rtklib_rtkcmn.h"
/* satellite code to satellite system ----------------------------------------*/
int code2sys(char code)
{
if (code == 'G' || code == ' ') return SYS_GPS;
if (code == 'R') return SYS_GLO;
if (code == 'E') return SYS_GAL; /* extension to sp3-c */
if (code == 'J') return SYS_QZS; /* extension to sp3-c */
if (code == 'C') return SYS_BDS; /* extension to sp3-c */
if (code == 'L') return SYS_LEO; /* extension to sp3-c */
return SYS_NONE;
}
/* read sp3 header -----------------------------------------------------------*/
int readsp3h(FILE *fp, gtime_t *time, char *type, int *sats,
double *bfact, char *tsys)
{
int i, j, k = 0, ns = 0, sys, prn;
char buff[1024];
trace(3, "readsp3h:\n");
for (i = 0;i<22;i++)
{
if (!fgets(buff, sizeof(buff), fp)) break;
if (i == 0)
{
*type = buff[2];
if (str2time(buff, 3, 28, time)) return 0;
}
else if (2<=i && i<=6)
{
if (i == 2)
{
ns = (int)str2num(buff, 4, 2);
}
for (j = 0;j<17 && k<ns;j++)
{
sys = code2sys(buff[9+3*j]);
prn = (int)str2num(buff, 10+3*j, 2);
if (k<MAXSAT) sats[k++] = satno(sys, prn);
}
}
else if (i == 12)
{
strncpy(tsys, buff+9, 3); tsys[3] = '\0';
}
else if (i == 14)
{
bfact[0] = str2num(buff, 3, 10);
bfact[1] = str2num(buff, 14, 12);
}
}
return ns;
}
/* add precise ephemeris -----------------------------------------------------*/
int addpeph(nav_t *nav, peph_t *peph)
{
peph_t *nav_peph;
if (nav->ne >= nav->nemax)
{
nav->nemax += 256;
if (!(nav_peph = (peph_t *)realloc(nav->peph, sizeof(peph_t)*nav->nemax)))
{
trace(1, "readsp3b malloc error n=%d\n", nav->nemax);
free(nav->peph);
nav->peph = NULL;
nav->ne = nav->nemax = 0;
return 0;
}
nav->peph = nav_peph;
}
nav->peph[nav->ne++] = *peph;
return 1;
}
/* read sp3 body -------------------------------------------------------------*/
void readsp3b(FILE *fp, char type, int *sats __attribute__((unused)), int ns, double *bfact,
char *tsys, int index, int opt, nav_t *nav)
{
peph_t peph;
gtime_t time;
double val, std, base;
int i, j, sat, sys, prn, n = ns*(type == 'P' ? 1 : 2), pred_o, pred_c, v;
char buff[1024];
trace(3, "readsp3b: type=%c ns=%d index=%d opt=%d\n", type, ns, index, opt);
while (fgets(buff, sizeof(buff), fp))
{
if (!strncmp(buff, "EOF", 3)) break;
if (buff[0] != '*' || str2time(buff, 3, 28, &time))
{
trace(2, "sp3 invalid epoch %31.31s\n", buff);
continue;
}
if (!strcmp(tsys, "UTC")) time = utc2gpst(time); /* utc->gpst */
peph.time = time;
peph.index = index;
for (i = 0; i < MAXSAT; i++)
{
for (j = 0; j < 4; j++)
{
peph.pos[i][j] = 0.0;
peph.std[i][j] = 0.0f;
peph.vel[i][j] = 0.0;
peph.vst[i][j] = 0.0f;
}
for (j = 0; j < 3; j++)
{
peph.cov[i][j] = 0.0f;
peph.vco[i][j] = 0.0f;
}
}
for (i = pred_o = pred_c = v = 0;i<n && fgets(buff, sizeof(buff), fp);i++)
{
if (strlen(buff) < 4 || (buff[0] != 'P' && buff[0] != 'V')) continue;
sys = buff[1] == ' '?SYS_GPS:code2sys(buff[1]);
prn = (int)str2num(buff, 2, 2);
if (sys == SYS_SBS) prn += 100;
else if (sys == SYS_QZS) prn += 192; /* extension to sp3-c */
if (!(sat = satno(sys, prn))) continue;
if (buff[0] == 'P')
{
pred_c = strlen(buff) >= 76 && buff[75] == 'P';
pred_o = strlen(buff) >= 80 && buff[79] == 'P';
}
for (j = 0;j<4;j++)
{
/* read option for predicted value */
if (j< 3 && (opt&1) && pred_o) continue;
if (j< 3 && (opt&2) && !pred_o) continue;
if (j == 3 && (opt&1) && pred_c) continue;
if (j == 3 && (opt&2) && !pred_c) continue;
val = str2num(buff, 4 + j * 14, 14);
std = str2num(buff, 61 + j * 3, j < 3 ? 2 : 3);
if (buff[0] == 'P') { /* position */
if (val != 0.0 && fabs(val - 999999.999999) >= 1e-6)
{
peph.pos[sat-1][j] = val*(j < 3 ? 1000.0 : 1e-6);
v = 1; /* valid epoch */
}
if ((base = bfact[j < 3 ? 0 : 1]) > 0.0 && std > 0.0)
{
peph.std[sat-1][j] = (float)(std::pow(base, std)*(j < 3 ? 1e-3 : 1e-12));
}
}
else if (v) { /* velocity */
if (val != 0.0 && fabs(val - 999999.999999) >= 1e-6)
{
peph.vel[sat-1][j] = val*(j < 3 ? 0.1 : 1e-10);
}
if ((base = bfact[j < 3 ? 0 : 1]) > 0.0 && std > 0.0)
{
peph.vst[sat-1][j] = (float)(std::pow(base, std)*(j < 3 ? 1e-7 : 1e-16));
}
}
}
}
if (v)
{
if (!addpeph(nav, &peph)) return;
}
}
}
/* compare precise ephemeris -------------------------------------------------*/
int cmppeph(const void *p1, const void *p2)
{
peph_t *q1 = (peph_t *)p1, *q2 = (peph_t *)p2;
double tt = timediff(q1->time, q2->time);
return tt < -1e-9 ? -1 : (tt > 1e-9 ? 1 : q1->index - q2->index);
}
/* combine precise ephemeris -------------------------------------------------*/
void combpeph(nav_t *nav, int opt)
{
int i, j, k, m;
trace(3, "combpeph: ne=%d\n", nav->ne);
qsort(nav->peph, nav->ne, sizeof(peph_t), cmppeph);
if (opt&4) return;
for (i = 0, j = 1; j < nav->ne; j++)
{
if (fabs(timediff(nav->peph[i].time, nav->peph[j].time)) < 1e-9)
{
for (k = 0; k < MAXSAT; k++)
{
if (norm_rtk(nav->peph[j].pos[k], 4) <= 0.0) continue;
for (m = 0;m < 4; m++) nav->peph[i].pos[k][m] = nav->peph[j].pos[k][m];
for (m = 0;m < 4; m++) nav->peph[i].std[k][m] = nav->peph[j].std[k][m];
for (m = 0;m < 4; m++) nav->peph[i].vel[k][m] = nav->peph[j].vel[k][m];
for (m = 0;m < 4; m++) nav->peph[i].vst[k][m] = nav->peph[j].vst[k][m];
}
}
else if (++i < j) nav->peph[i] = nav->peph[j];
}
nav->ne = i+1;
trace(4, "combpeph: ne=%d\n", nav->ne);
}
/* read sp3 precise ephemeris file ---------------------------------------------
* read sp3 precise ephemeris/clock files and set them to navigation data
* args : char *file I sp3-c precise ephemeris file
* (wind-card * is expanded)
* nav_t *nav IO navigation data
* int opt I options (1: only observed + 2: only predicted +
* 4: not combined)
* return : none
* notes : see ref [1]
* precise ephemeris is appended and combined
* nav->peph and nav->ne must by properly initialized before calling the
* function
* only files with extensions of .sp3, .SP3, .eph* and .EPH* are read
*-----------------------------------------------------------------------------*/
void readsp3(const char *file, nav_t *nav, int opt)
{
FILE *fp;
gtime_t time = {0, 0};
double bfact[2] = {};
int i, j, n, ns, sats[MAXSAT] = {};
char *efiles[MAXEXFILE], *ext, type = ' ', tsys[4] = "";
trace(3, "readpephs: file=%s\n", file);
for (i = 0; i < MAXEXFILE; i++)
{
if (!(efiles[i] = (char *)malloc(1024)))
{
for (i--; i >= 0; i--) free(efiles[i]);
return;
}
}
/* expand wild card in file path */
n = expath(file, efiles, MAXEXFILE);
for (i = j = 0; i < n; i++)
{
if (!(ext = strrchr(efiles[i], '.'))) continue;
if (!strstr(ext + 1, "sp3") && !strstr(ext + 1, ".SP3") &&
!strstr(ext + 1, "eph") && !strstr(ext + 1, ".EPH")) continue;
if (!(fp = fopen(efiles[i], "r")))
{
trace(2, "sp3 file open error %s\n", efiles[i]);
continue;
}
/* read sp3 header */
ns = readsp3h(fp, &time, &type, sats, bfact, tsys);
/* read sp3 body */
readsp3b(fp, type, sats, ns, bfact, tsys, j++, opt, nav);
fclose(fp);
}
for (i = 0; i < MAXEXFILE; i++) free(efiles[i]);
/* combine precise ephemeris */
if (nav->ne > 0) combpeph(nav, opt);
}
/* read satellite antenna parameters -------------------------------------------
* read satellite antenna parameters
* args : char *file I antenna parameter file
* gtime_t time I time
* nav_t *nav IO navigation data
* return : status (1:ok,0:error)
* notes : only support antex format for the antenna parameter file
*-----------------------------------------------------------------------------*/
int readsap(const char *file, gtime_t time, nav_t *nav)
{
pcv_t aux = { 0, {}, {}, {0,0}, {0,0}, {{},{}}, {{},{}} };
pcvs_t pcvs = {0, 0, &aux };
pcv_t pcv0 = { 0, {}, {}, {0,0}, {0,0}, {{},{}}, {{},{}} }, *pcv;
int i;
trace(3, "readsap : file=%s time=%s\n", file, time_str(time, 0));
if (!readpcv(file, &pcvs)) return 0;
for (i = 0; i < MAXSAT; i++)
{
pcv = searchpcv(i + 1, "", time, &pcvs);
nav->pcvs[i] = pcv ? *pcv : pcv0;
}
free(pcvs.pcv);
return 1;
}
/* read dcb parameters file --------------------------------------------------*/
int readdcbf(const char *file, nav_t *nav, const sta_t *sta)
{
FILE *fp;
double cbias;
char buff[256], str1[32], str2[32] = "";
int i, j, sat, type = 0;
trace(3, "readdcbf: file=%s\n", file);
if (!(fp = fopen(file, "r")))
{
trace(2, "dcb parameters file open error: %s\n", file);
return 0;
}
while (fgets(buff, sizeof(buff), fp))
{
if (strstr(buff, "DIFFERENTIAL (P1-P2) CODE BIASES")) type = 1;
else if (strstr(buff, "DIFFERENTIAL (P1-C1) CODE BIASES")) type = 2;
else if (strstr(buff, "DIFFERENTIAL (P2-C2) CODE BIASES")) type = 3;
if (!type || sscanf(buff, "%s %s", str1, str2) < 1) continue;
if ((cbias = str2num(buff, 26, 9)) == 0.0) continue;
if (sta && (!strcmp(str1, "G") || !strcmp(str1, "R")))
{ /* receiver dcb */
for (i = 0; i < MAXRCV; i++)
{
if (!strcmp(sta[i].name, str2)) break;
}
if (i < MAXRCV)
{
j = !strcmp(str1, "G") ? 0 : 1;
nav->rbias[i][j][type-1] = cbias * 1e-9 * SPEED_OF_LIGHT; /* ns -> m */
}
}
else if ((sat = satid2no(str1)))
{ /* satellite dcb */
nav->cbias[sat-1][type-1] = cbias * 1e-9 * SPEED_OF_LIGHT; /* ns -> m */
}
}
fclose(fp);
return 1;
}
/* read dcb parameters ---------------------------------------------------------
* read differential code bias (dcb) parameters
* args : char *file I dcb parameters file (wild-card * expanded)
* nav_t *nav IO navigation data
* sta_t *sta I station info data to inport receiver dcb
* (NULL: no use)
* return : status (1:ok,0:error)
* notes : currently only p1-c1 bias of code *.dcb file
*-----------------------------------------------------------------------------*/
int readdcb(const char *file, nav_t *nav, const sta_t *sta)
{
int i, j, n;
char *efiles[MAXEXFILE] = {};
trace(3, "readdcb : file=%s\n", file);
for (i = 0;i < MAXSAT; i++) for (j = 0; j < 3; j++)
{
nav->cbias[i][j] = 0.0;
}
for (i = 0; i < MAXEXFILE; i++)
{
if (!(efiles[i] = (char *)malloc(1024)))
{
for (i--; i >= 0; i--) free(efiles[i]);
return 0;
}
}
n = expath(file, efiles, MAXEXFILE);
for (i = 0; i < n; i++)
{
readdcbf(efiles[i], nav, sta);
}
for (i = 0; i < MAXEXFILE;i ++) free(efiles[i]);
return 1;
}
/* add satellite fcb ---------------------------------------------------------*/
int addfcb(nav_t *nav, gtime_t ts, gtime_t te, int sat,
const double *bias, const double *std)
{
fcbd_t *nav_fcb;
int i, j;
if (nav->nf > 0 && fabs(timediff(ts, nav->fcb[nav->nf-1].ts)) <= 1e-3)
{
for (i = 0; i < 3; i++)
{
nav->fcb[nav->nf-1].bias[sat-1][i] = bias[i];
nav->fcb[nav->nf-1].std [sat-1][i] = std [i];
}
return 1;
}
if (nav->nf >= nav->nfmax)
{
nav->nfmax = nav->nfmax <= 0 ? 2048 : nav->nfmax * 2;
if (!(nav_fcb = (fcbd_t *)realloc(nav->fcb, sizeof(fcbd_t)*nav->nfmax)))
{
free(nav->fcb);
nav->nf = nav->nfmax = 0;
return 0;
}
nav->fcb = nav_fcb;
}
for (i = 0; i < MAXSAT; i++) for (j = 0; j < 3; j++)
{
nav->fcb[nav->nf].bias[i][j] = nav->fcb[nav->nf].std[i][j] = 0.0;
}
for (i = 0; i < 3; i++)
{
nav->fcb[nav->nf].bias[sat-1][i] = bias[i];
nav->fcb[nav->nf].std [sat-1][i] = std [i];
}
nav->fcb[nav->nf ].ts = ts;
nav->fcb[nav->nf++].te = te;
return 1;
}
/* read satellite fcb file ---------------------------------------------------*/
int readfcbf(const char *file, nav_t *nav)
{
FILE *fp;
gtime_t ts, te;
double ep1[6], ep2[6], bias[3] = {}, std[3] = {};
char buff[1024], str[32], *p;
int sat;
trace(3, "readfcbf: file=%s\n", file);
if (!(fp = fopen(file, "r")))
{
trace(2, "fcb parameters file open error: %s\n", file);
return 0;
}
while (fgets(buff, sizeof(buff), fp))
{
if ((p = strchr(buff, '#'))) *p = '\0';
if (sscanf(buff, "%lf/%lf/%lf %lf:%lf:%lf %lf/%lf/%lf %lf:%lf:%lf %s"
"%lf %lf %lf %lf %lf %lf", ep1, ep1+1, ep1+2, ep1+3, ep1+4, ep1+5,
ep2, ep2+1, ep2+2, ep2+3, ep2+4, ep2+5, str, bias, std, bias+1, std+1,
bias+2, std+2) < 17) continue;
if (!(sat = satid2no(str))) continue;
ts = epoch2time(ep1);
te = epoch2time(ep2);
if (!addfcb(nav, ts, te, sat, bias, std)) return 0;
}
fclose(fp);
return 1;
}
/* compare satellite fcb -----------------------------------------------------*/
int cmpfcb(const void *p1, const void *p2)
{
fcbd_t *q1 = (fcbd_t *)p1, *q2 = (fcbd_t *)p2;
double tt = timediff(q1->ts, q2->ts);
return tt < -1e-3 ? -1 : (tt > 1e-3 ? 1 : 0);
}
/* read satellite fcb data -----------------------------------------------------
* read satellite fractional cycle bias (dcb) parameters
* args : char *file I fcb parameters file (wild-card * expanded)
* nav_t *nav IO navigation data
* return : status (1:ok,0:error)
* notes : fcb data appended to navigation data
*-----------------------------------------------------------------------------*/
int readfcb(const char *file, nav_t *nav)
{
char *efiles[MAXEXFILE] = {};
int i, n;
trace(3, "readfcb : file=%s\n", file);
for (i = 0; i < MAXEXFILE; i++)
{
if (!(efiles[i] = (char *)malloc(1024)))
{
for (i--; i >= 0; i--) free(efiles[i]);
return 0;
}
}
n = expath(file, efiles, MAXEXFILE);
for (i = 0; i < n; i++)
{
readfcbf(efiles[i], nav);
}
for (i = 0; i < MAXEXFILE; i++) free(efiles[i]);
if (nav->nf > 1)
{
qsort(nav->fcb, nav->nf, sizeof(fcbd_t), cmpfcb);
}
return 1;
}
/* polynomial interpolation by Neville's algorithm ---------------------------*/
double interppol(const double *x, double *y, int n)
{
int i, j;
for (j = 1; j < n; j++)
{
for (i = 0; i < n - j; i++)
{
y[i] = (x[i+j] * y[i] - x[i] * y[i+1]) / (x[i+j] - x[i]);
}
}
return y[0];
}
/* satellite position by precise ephemeris -----------------------------------*/
int pephpos(gtime_t time, int sat, const nav_t *nav, double *rs,
double *dts, double *vare, double *varc)
{
double t[NMAX+1], p[3][NMAX+1], c[2], *pos, std = 0.0, s[3], sinl, cosl;
int i, j, k, index;
trace(4, "pephpos : time=%s sat=%2d\n", time_str(time, 3), sat);
rs[0] = rs[1] = rs[2] = dts[0] = 0.0;
if (nav->ne < NMAX + 1 ||
timediff(time, nav->peph[0].time) < -MAXDTE ||
timediff(time, nav->peph[nav->ne-1].time) > MAXDTE)
{
trace(3, "no prec ephem %s sat=%2d\n", time_str(time, 0), sat);
return 0;
}
/* binary search */
for (i = 0, j = nav->ne - 1; i < j;)
{
k = (i + j) / 2;
if (timediff(nav->peph[k].time, time) < 0.0) i = k + 1; else j = k;
}
index = i <= 0 ? 0 : i-1;
/* polynomial interpolation for orbit */
i = index - (NMAX + 1) / 2;
if (i < 0) i = 0; else if (i + NMAX >= nav->ne) i = nav->ne - NMAX - 1;
for (j = 0; j <= NMAX; j++)
{
t[j] = timediff(nav->peph[i+j].time, time);
if (norm_rtk(nav->peph[i+j].pos[sat-1], 3) <= 0.0)
{
trace(3, "prec ephem outage %s sat=%2d\n", time_str(time, 0), sat);
return 0;
}
}
for (j = 0;j<=NMAX;j++)
{
pos = nav->peph[i+j].pos[sat-1];
#if 0
p[0][j] = pos[0];
p[1][j] = pos[1];
#else
/* correciton for earh rotation ver.2.4.0 */
sinl = sin(DEFAULT_OMEGA_EARTH_DOT * t[j]);
cosl = cos(DEFAULT_OMEGA_EARTH_DOT * t[j]);
p[0][j] = cosl * pos[0] - sinl * pos[1];
p[1][j] = sinl * pos[0] + cosl * pos[1];
#endif
p[2][j] = pos[2];
}
for (i = 0; i < 3; i++)
{
rs[i] = interppol(t, p[i], NMAX + 1);
}
if (vare)
{
for (i = 0; i < 3; i++) s[i] = nav->peph[index].std[sat-1][i];
std = norm_rtk(s, 3);
/* extrapolation error for orbit */
if (t[0 ] > 0.0) std += EXTERR_EPH * std::pow(t[0 ], 2.0) / 2.0;
else if (t[NMAX] < 0.0) std += EXTERR_EPH * std::pow(t[NMAX], 2.0) / 2.0;
*vare = std::pow(std, 2.0);
}
/* linear interpolation for clock */
t[0] = timediff(time, nav->peph[index ].time);
t[1] = timediff(time, nav->peph[index+1].time);
c[0] = nav->peph[index ].pos[sat-1][3];
c[1] = nav->peph[index+1].pos[sat-1][3];
if (t[0] <= 0.0)
{
if ((dts[0] = c[0]) != 0.0)
{
std = nav->peph[index].std[sat-1][3] * SPEED_OF_LIGHT - EXTERR_CLK * t[0];
}
}
else if (t[1] >= 0.0)
{
if ((dts[0] = c[1]) != 0.0)
{
std = nav->peph[index+1].std[sat-1][3] * SPEED_OF_LIGHT + EXTERR_CLK * t[1];
}
}
else if (c[0] != 0.0 && c[1] != 0.0)
{
dts[0] = (c[1] * t[0] - c[0] * t[1]) / (t[0] - t[1]);
i = t[0] < -t[1] ? 0: 1;
std = nav->peph[index+i].std[sat-1][3] + EXTERR_CLK * fabs(t[i]);
}
else
{
dts[0] = 0.0;
}
if (varc) *varc = std::pow(std, 2.0);
return 1;
}
/* satellite clock by precise clock ------------------------------------------*/
int pephclk(gtime_t time, int sat, const nav_t *nav, double *dts,
double *varc)
{
double t[2], c[2], std;
int i, j, k, index;
trace(4, "pephclk : time=%s sat=%2d\n", time_str(time, 3), sat);
if (nav->nc < 2 ||
timediff(time, nav->pclk[0].time) < -MAXDTE ||
timediff(time, nav->pclk[nav->nc-1].time) > MAXDTE)
{
trace(3, "no prec clock %s sat=%2d\n", time_str(time, 0), sat);
return 1;
}
/* binary search */
for (i = 0, j = nav->nc - 1; i < j;)
{
k = (i + j) / 2;
if (timediff(nav->pclk[k].time, time) < 0.0) i = k + 1; else j = k;
}
index = i<=0?0:i-1;
/* linear interpolation for clock */
t[0] = timediff(time, nav->pclk[index ].time);
t[1] = timediff(time, nav->pclk[index+1].time);
c[0] = nav->pclk[index ].clk[sat-1][0];
c[1] = nav->pclk[index+1].clk[sat-1][0];
if (t[0] <= 0.0)
{
if ((dts[0] = c[0]) == 0.0) return 0;
std = nav->pclk[index].std[sat-1][0] * SPEED_OF_LIGHT - EXTERR_CLK * t[0];
}
else if (t[1] >= 0.0)
{
if ((dts[0] = c[1]) == 0.0) return 0;
std = nav->pclk[index+1].std[sat-1][0] * SPEED_OF_LIGHT + EXTERR_CLK * t[1];
}
else if (c[0] != 0.0 && c[1] != 0.0)
{
dts[0] = (c[1]*t[0]-c[0]*t[1]) / (t[0] - t[1]);
i = t[0] < -t[1] ? 0 : 1;
std = nav->pclk[index+i].std[sat-1][0] * SPEED_OF_LIGHT + EXTERR_CLK * fabs(t[i]);
}
else
{
trace(3, "prec clock outage %s sat=%2d\n", time_str(time, 0), sat);
return 0;
}
if (varc) *varc = std::pow(std, 2.0);
return 1;
}
/* satellite antenna phase center offset ---------------------------------------
* compute satellite antenna phase center offset in ecef
* args : gtime_t time I time (gpst)
* double *rs I satellite position and velocity (ecef)
* {x,y,z,vx,vy,vz} (m|m/s)
* int sat I satellite number
* nav_t *nav I navigation data
* double *dant I satellite antenna phase center offset (ecef)
* {dx,dy,dz} (m) (iono-free LC value)
* return : none
*-----------------------------------------------------------------------------*/
void satantoff(gtime_t time, const double *rs, int sat, const nav_t *nav,
double *dant)
{
const double *lam = nav->lam[sat-1];
const pcv_t *pcv = nav->pcvs+sat-1;
double ex[3], ey[3], ez[3], es[3], r[3], rsun[3], gmst, erpv[5] = {};
double gamma, C1, C2, dant1, dant2;
int i, j = 0, k = 1;
trace(4, "satantoff: time=%s sat=%2d\n", time_str(time, 3), sat);
/* sun position in ecef */
sunmoonpos(gpst2utc(time), erpv, rsun, NULL, &gmst);
/* unit vectors of satellite fixed coordinates */
for (i = 0; i < 3; i++) r[i] = -rs[i];
if (!normv3(r, ez)) return;
for (i = 0; i < 3; i++) r[i] = rsun[i]-rs[i];
if (!normv3(r, es)) return;
cross3(ez, es, r);
if (!normv3(r, ey)) return;
cross3(ey, ez, ex);
if (NFREQ >= 3 && (satsys(sat, NULL) & (SYS_GAL | SYS_SBS))) k = 2;
if (NFREQ < 2 || lam[j] == 0.0 || lam[k] == 0.0) return;
gamma = std::pow(lam[k], 2.0) / std::pow(lam[j], 2.0);
C1 = gamma / (gamma - 1.0);
C2 = -1.0 / (gamma - 1.0);
/* iono-free LC */
for (i = 0; i < 3; i++)
{
dant1 = pcv->off[j][0] * ex[i] + pcv->off[j][1] * ey[i] + pcv->off[j][2] * ez[i];
dant2 = pcv->off[k][0] * ex[i] + pcv->off[k][1] * ey[i] + pcv->off[k][2] * ez[i];
dant[i] = C1 * dant1 + C2 * dant2;
}
}
/* satellite position/clock by precise ephemeris/clock -------------------------
* compute satellite position/clock with precise ephemeris/clock
* args : gtime_t time I time (gpst)
* int sat I satellite number
* nav_t *nav I navigation data
* int opt I sat postion option
* (0: center of mass, 1: antenna phase center)
* double *rs O sat position and velocity (ecef)
* {x,y,z,vx,vy,vz} (m|m/s)
* double *dts O sat clock {bias,drift} (s|s/s)
* double *var IO sat position and clock error variance (m)
* (NULL: no output)
* return : status (1:ok,0:error or data outage)
* notes : clock includes relativistic correction but does not contain code bias
* before calling the function, nav->peph, nav->ne, nav->pclk and
* nav->nc must be set by calling readsp3(), readrnx() or readrnxt()
* if precise clocks are not set, clocks in sp3 are used instead
*-----------------------------------------------------------------------------*/
int peph2pos(gtime_t time, int sat, const nav_t *nav, int opt,
double *rs, double *dts, double *var)
{
double rss[3], rst[3], dtss[1], dtst[1], dant[3] = {}, vare = 0.0, varc = 0.0, tt = 1e-3;
int i;
trace(4, "peph2pos: time=%s sat=%2d opt=%d\n", time_str(time, 3), sat, opt);
if (sat <= 0 || MAXSAT < sat) return 0;
/* satellite position and clock bias */
if (!pephpos(time, sat, nav, rss, dtss, &vare, &varc) ||
!pephclk(time, sat, nav, dtss, &varc)) return 0;
time = timeadd(time, tt);
if (!pephpos(time, sat, nav, rst, dtst, NULL, NULL) ||
!pephclk(time, sat, nav, dtst, NULL)) return 0;
/* satellite antenna offset correction */
if (opt)
{
satantoff(time, rss, sat, nav, dant);
}
for (i = 0;i<3;i++)
{
rs[i ] = rss[i] + dant[i];
rs[i+3] = (rst[i] - rss[i]) / tt;
}
/* relativistic effect correction */
if (dtss[0] != 0.0)
{
dts[0] = dtss[0] - 2.0 * dot(rs, rs+3, 3) / SPEED_OF_LIGHT / SPEED_OF_LIGHT;
dts[1] = (dtst[0] - dtss[0]) / tt;
}
else
{ /* no precise clock */
dts[0] = dts[1] = 0.0;
}
if (var) *var = vare + varc;
return 1;
}

View File

@ -0,0 +1,107 @@
/*!
* \file rtklib_preceph.h
* \brief precise ephemeris and clock functions
* \authors <ul>
* <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* References :
* [1] S.Hilla, The Extended Standard Product 3 Orbit Format (SP3-c),
* 12 February, 2007
* [2] J.Ray, W.Gurtner, RINEX Extensions to Handle Clock Information,
* 27 August, 1998
* [3] D.D.McCarthy, IERS Technical Note 21, IERS Conventions 1996, July 1996
* [4] D.A.Vallado, Fundamentals of Astrodynamics and Applications 2nd ed,
* Space Technology Library, 2004
*
*----------------------------------------------------------------------------*/
#ifndef GNSS_SDR_RTKLIB_PRECEPH_H_
#define GNSS_SDR_RTKLIB_PRECEPH_H_
#include "rtklib.h"
const int NMAX = 10; /* order of polynomial interpolation */
const double MAXDTE = 900.0; /* max time difference to ephem time (s) */
const double EXTERR_CLK = 1e-3; /* extrapolation error for clock (m/s) */
const double EXTERR_EPH = 5e-7; /* extrapolation error for ephem (m/s^2) */
int code2sys(char code);
int readsp3h(FILE *fp, gtime_t *time, char *type, int *sats,
double *bfact, char *tsys);
int addpeph(nav_t *nav, peph_t *peph);
void readsp3b(FILE *fp, char type, int *sats, int ns, double *bfact,
char *tsys, int index, int opt, nav_t *nav);
int cmppeph(const void *p1, const void *p2);
void combpeph(nav_t *nav, int opt);
void readsp3(const char *file, nav_t *nav, int opt);
int readsap(const char *file, gtime_t time, nav_t *nav);
int readdcbf(const char *file, nav_t *nav, const sta_t *sta);
int readdcb(const char *file, nav_t *nav, const sta_t *sta);
int addfcb(nav_t *nav, gtime_t ts, gtime_t te, int sat,
const double *bias, const double *std);
int readfcbf(const char *file, nav_t *nav);
int readdcb(const char *file, nav_t *nav, const sta_t *sta);
int addfcb(nav_t *nav, gtime_t ts, gtime_t te, int sat,
const double *bias, const double *std);
int readfcbf(const char *file, nav_t *nav);
int cmpfcb(const void *p1, const void *p2);
int readfcb(const char *file, nav_t *nav);
double interppol(const double *x, double *y, int n);
int pephpos(gtime_t time, int sat, const nav_t *nav, double *rs,
double *dts, double *vare, double *varc);
int pephclk(gtime_t time, int sat, const nav_t *nav, double *dts,
double *varc);
void satantoff(gtime_t time, const double *rs, int sat, const nav_t *nav,
double *dant);
int peph2pos(gtime_t time, int sat, const nav_t *nav, int opt,
double *rs, double *dts, double *var);
#endif // GNSS_SDR_RTKLIB_PRECEPH_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,271 @@
/*!
* \file rtklib_rtkcmn.h
* \brief rtklib common functions
* \authors <ul>
* <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez
* </ul>
*
* This is a derived work from RTKLIB http://www.rtklib.com/
* The original source code at https://github.com/tomojitakasu/RTKLIB is
* released under the BSD 2-clause license with an additional exclusive clause
* that does not apply here. This additional clause is reproduced below:
*
* " The software package includes some companion executive binaries or shared
* libraries necessary to execute APs on Windows. These licenses succeed to the
* original ones of these software. "
*
* Neither the executive binaries nor the shared libraries are required by, used
* or included in GNSS-SDR.
*
* -------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* References :
* [1] IS-GPS-200D, Navstar GPS Space Segment/Navigation User Interfaces,
* 7 March, 2006
* [2] RTCA/DO-229C, Minimum operational performanc standards for global
* positioning system/wide area augmentation system airborne equipment,
* RTCA inc, November 28, 2001
* [3] M.Rothacher, R.Schmid, ANTEX: The Antenna Exchange Format Version 1.4,
* 15 September, 2010
* [4] A.Gelb ed., Applied Optimal Estimation, The M.I.T Press, 1974
* [5] A.E.Niell, Global mapping functions for the atmosphere delay at radio
* wavelengths, Jounal of geophysical research, 1996
* [6] W.Gurtner and L.Estey, RINEX The Receiver Independent Exchange Format
* Version 3.00, November 28, 2007
* [7] J.Kouba, A Guide to using International GNSS Service (IGS) products,
* May 2009
* [8] China Satellite Navigation Office, BeiDou navigation satellite system
* signal in space interface control document, open service signal B1I
* (version 1.0), Dec 2012
* [9] J.Boehm, A.Niell, P.Tregoning and H.Shuh, Global Mapping Function
* (GMF): A new empirical mapping function base on numerical weather
* model data, Geophysical Research Letters, 33, L07304, 2006
* [10] GLONASS/GPS/Galileo/Compass/SBAS NV08C receiver series BINR interface
* protocol specification ver.1.3, August, 2012
*
*----------------------------------------------------------------------------*/
#ifndef GNSS_SDR_RTKLIB_RTKCMN_H_
#define GNSS_SDR_RTKLIB_RTKCMN_H_
#include "rtklib.h"
#include <glog/logging.h>
/* coordinate rotation matrix ------------------------------------------------*/
#define Rx(t,X) do { \
(X)[0]=1.0; (X)[1]=(X)[2]=(X)[3]=(X)[6]=0.0; \
(X)[4]=(X)[8]=cos(t); (X)[7]=sin(t); (X)[5]=-(X)[7]; \
} while (0)
#define Ry(t,X) do { \
(X)[4]=1.0; (X)[1]=(X)[3]=(X)[5]=(X)[7]=0.0; \
(X)[0]=(X)[8]=cos(t); (X)[2]=sin(t); (X)[6]=-(X)[2]; \
} while (0)
#define Rz(t,X) do { \
(X)[8]=1.0; (X)[2]=(X)[5]=(X)[6]=(X)[7]=0.0; \
(X)[0]=(X)[4]=cos(t); (X)[3]=sin(t); (X)[1]=-(X)[3]; \
} while (0)
void fatalerr(const char *format, ...);
int satno(int sys, int prn);
int satsys(int sat, int *prn);
int satid2no(const char *id);
void satno2id(int sat, char *id);
int satexclude(int sat, int svh, const prcopt_t *opt);
int testsnr(int base, int freq, double el, double snr,const snrmask_t *mask);
unsigned char obs2code(const char *obs, int *freq);
char *code2obs(unsigned char code, int *freq);
void setcodepri(int sys, int freq, const char *pri);
int getcodepri(int sys, unsigned char code, const char *opt);
unsigned int getbitu(const unsigned char *buff, int pos, int len);
int getbits(const unsigned char *buff, int pos, int len);
void setbitu(unsigned char *buff, int pos, int len, unsigned int data);
void setbits(unsigned char *buff, int pos, int len, int data);
unsigned int rtk_crc32(const unsigned char *buff, int len);
unsigned int rtk_crc24q(const unsigned char *buff, int len);
unsigned short rtk_crc16(const unsigned char *buff, int len);
int decode_word(unsigned int word, unsigned char *data);
double *mat(int n, int m);
int *imat(int n, int m);
double *zeros(int n, int m);
double *eye(int n);
double dot(const double *a, const double *b, int n);
double norm_rtk(const double *a, int n);
void cross3(const double *a, const double *b, double *c);
int normv3(const double *a, double *b);
void matcpy(double *A, const double *B, int n, int m);
void matmul(const char *tr, int n, int k, int m, double alpha,
const double *A, const double *B, double beta, double *C);
int matinv(double *A, int n);
int solve(const char *tr, const double *A, const double *Y, int n,
int m, double *X);
int lsq(const double *A, const double *y, int n, int m, double *x,
double *Q);
int filter_(const double *x, const double *P, const double *H,
const double *v, const double *R, int n, int m,
double *xp, double *Pp);
int filter(double *x, double *P, const double *H, const double *v,
const double *R, int n, int m);
int smoother(const double *xf, const double *Qf, const double *xb,
const double *Qb, int n, double *xs, double *Qs);
void matfprint(const double A[], int n, int m, int p, int q, FILE *fp);
void matprint(const double A[], int n, int m, int p, int q);
double str2num(const char *s, int i, int n);
int str2time(const char *s, int i, int n, gtime_t *t);
gtime_t epoch2time(const double *ep);
void time2epoch(gtime_t t, double *ep);
gtime_t gpst2time(int week, double sec);
double time2gpst(gtime_t t, int *week);
gtime_t gst2time(int week, double sec);
double time2gst(gtime_t t, int *week);
gtime_t bdt2time(int week, double sec);
double time2bdt(gtime_t t, int *week);
gtime_t timeadd(gtime_t t, double sec);
double timediff(gtime_t t1, gtime_t t2);
gtime_t timeget(void);
//void timeset(gtime_t t);
int read_leaps_text(FILE *fp);
int read_leaps_usno(FILE *fp);
int read_leaps(const char *file);
gtime_t gpst2utc(gtime_t t);
gtime_t utc2gpst(gtime_t t);
gtime_t gpst2bdt(gtime_t t);
gtime_t bdt2gpst(gtime_t t);
double time2sec(gtime_t time, gtime_t *day);
double utc2gmst(gtime_t t, double ut1_utc);
void time2str(gtime_t t, char *s, int n);
char *time_str(gtime_t t, int n);
double time2doy(gtime_t t);
int adjgpsweek(int week);
unsigned int tickget(void);
void sleepms(int ms);
void deg2dms(double deg, double *dms, int ndec);
double dms2deg(const double *dms);
void ecef2pos(const double *r, double *pos);
void pos2ecef(const double *pos, double *r);
void xyz2enu(const double *pos, double *E);
void ecef2enu(const double *pos, const double *r, double *e);
void enu2ecef(const double *pos, const double *e, double *r);
void covenu(const double *pos, const double *P, double *Q);
void covecef(const double *pos, const double *Q, double *P);
void ast_args(double t, double *f);
void nut_iau1980(double t, const double *f, double *dpsi, double *deps);
void eci2ecef(gtime_t tutc, const double *erpv, double *U, double *gmst);
int decodef(char *p, int n, double *v);
void addpcv(const pcv_t *pcv, pcvs_t *pcvs);
int readngspcv(const char *file, pcvs_t *pcvs);
int readantex(const char *file, pcvs_t *pcvs);
int readpcv(const char *file, pcvs_t *pcvs);
pcv_t *searchpcv(int sat, const char *type, gtime_t time,
const pcvs_t *pcvs);
void readpos(const char *file, const char *rcv, double *pos);
int readblqrecord(FILE *fp, double *odisp);
int readblq(const char *file, const char *sta, double *odisp);
int readerp(const char *file, erp_t *erp);
int geterp(const erp_t *erp, gtime_t time, double *erpv);
int cmpeph(const void *p1, const void *p2);
void uniqeph(nav_t *nav);
int cmpgeph(const void *p1, const void *p2);
void uniqgeph(nav_t *nav);
int cmpseph(const void *p1, const void *p2);
void uniqseph(nav_t *nav);
void uniqnav(nav_t *nav);
int cmpobs(const void *p1, const void *p2);
int sortobs(obs_t *obs);
int screent(gtime_t time, gtime_t ts, gtime_t te, double tint);
int readnav(const char *file, nav_t *nav);
int savenav(const char *file, const nav_t *nav);
void freeobs(obs_t *obs);
void freenav(nav_t *nav, int opt);
//void traceopen(const char *file);
//void traceclose(void);
//void tracelevel(int level);
void trace (int level, const char *format, ...);
//void tracet (int level, const char *format, ...);
void tracemat(int level, const double *A, int n, int m, int p, int q);
void traceobs(int level, const obsd_t *obs, int n);
//void tracenav(int level, const nav_t *nav);
//void tracegnav(int level, const nav_t *nav);
//void tracehnav(int level, const nav_t *nav);
//void tracepeph(int level, const nav_t *nav);
//void tracepclk(int level, const nav_t *nav);
//void traceb (int level, const unsigned char *p, int n);
int execcmd(const char *cmd);
void createdir(const char *path);
int repstr(char *str, const char *pat, const char *rep);
int reppath(const char *path, char *rpath, gtime_t time, const char *rov,
const char *base);
int reppaths(const char *path, char *rpath[], int nmax, gtime_t ts,
gtime_t te, const char *rov, const char *base);
double satwavelen(int sat, int frq, const nav_t *nav);
double geodist(const double *rs, const double *rr, double *e);
double satazel(const double *pos, const double *e, double *azel);
//#define SQRT(x) ((x)<0.0?0.0:sqrt(x))
void dops(int ns, const double *azel, double elmin, double *dop);
double ionmodel(gtime_t t, const double *ion, const double *pos,
const double *azel);
double ionmapf(const double *pos, const double *azel);
double ionppp(const double *pos, const double *azel, double re,
double hion, double *posp);
double tropmodel(gtime_t time, const double *pos, const double *azel,
double humi);
double interpc(const double coef[], double lat);
double mapf(double el, double a, double b, double c);
double nmf(gtime_t time, const double pos[], const double azel[],
double *mapfw);
double tropmapf(gtime_t time, const double pos[], const double azel[],
double *mapfw);
double interpvar(double ang, const double *var);
void antmodel(const pcv_t *pcv, const double *del, const double *azel,
int opt, double *dant);
void antmodel_s(const pcv_t *pcv, double nadir, double *dant);
void sunmoonpos_eci(gtime_t tut, double *rsun, double *rmoon);
void sunmoonpos(gtime_t tutc, const double *erpv, double *rsun,
double *rmoon, double *gmst);
void csmooth(obs_t *obs, int ns);
int rtk_uncompress(const char *file, char *uncfile);
int expath(const char *path, char *paths[], int nmax);
void windupcorr(gtime_t time, const double *rs, const double *rr, double *phw);
#endif /* GNSS_SDR_RTKLIB_RTKCMN_H_ */

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More