Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PVT solution consistency checks #526

Open
wants to merge 24 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions conf/security_checks_gps_l1_ca.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
; This is a GNSS-SDR configuration file
; The configuration API is described at https://gnss-sdr.org/docs/sp-blocks/
; SPDX-License-Identifier: GPL-3.0-or-later
; SPDX-FileCopyrightText: (C) 2010-2020 (see AUTHORS file for a list of contributors)

; You can define your own receiver and invoke it by doing
; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf


[GNSS-SDR]

;######### GLOBAL OPTIONS ##################
;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [samples per second].
GNSS-SDR.internal_fs_sps=2000000

;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=./data/overpowered_pos_jump_2M.dat
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unless this file is going to be provided, is this config file really something we need to control?

SignalSource.item_type=gr_complex
SignalSource.sampling_frequency=2000000
SignalSource.freq=1575420000
;SignalSource.samples=2000000
SignalSource.repeat=false
SignalSource.enable_throttle_control=false
SignalSource.seconds_to_skip=0


;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Signal_Conditioner
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the sub-components are Pass-Through, why not just make the whole conditioner Pass-Through and elide the sub-sections?


DataTypeAdapter.implementation=Pass_Through
DataTypeAdapter.dump=false
DataTypeAdapter.dump_filename=../data/DataTypeAdapter.dat

InputFilter.implementation=Pass_Through
InputFilter.input_item_type=gr_complex
InputFilter.output_item_type=gr_complex

Resampler.implementation=Pass_Through
Resampler.item_type=gr_complex

;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=5
Channels.in_acquisition=1
Channel.signal=1C

;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=gr_complex
Acquisition_1C.coherent_integration_time_ms=1
Acquisition_1C.pfa=0.01
;Acquisition_1C.pfa=0.01
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete? This commented line appears to duplicate the previous line

Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=250
Acquisition_1C.dump=false
Acquisition_1C.dump_filename=./acq_dump.dat

;######### TRACKING GLOBAL CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.pll_bw_hz=40.0;
Tracking_1C.dll_bw_hz=4.0;
Tracking_1C.order=3;
Tracking_1C.dump=true
Tracking_1C.dump_filename=./trk_dump/epl_tracking_c
Tracking_1C.dump_mat=true

;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't expect any of the blocks to have "dump=true" for production

TelemetryDecoder_1C.security_checks=true
TelemetryDecoder_1C.dump_filename=./tlm_dump/telemetry

;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat

;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=1
PVT.display_rate_ms=1000
PVT.dump_filename=./PVT
PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea;
PVT.flag_nmea_tty_port=false;
PVT.nmea_dump_devname=/dev/pts/4
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=false

PVT.security_checks=true
PVT.print_score=true

;######### Secure PVT ############
SecurePVT.dump_pvt_checks_results=true;

; Position
SecurePVT.position_check=true
SecurePVT.static_pos_check=true ; Disable for dynamic scenarios
SecurePVT.max_jump_distance=100
SecurePVT.geo_fence_radius=5
SecurePVT.static_lat=42
SecurePVT.static_lon=-71
SecurePVT.static_alt=100

SecurePVT.min_altitude=-10
SecurePVT.max_altitude=20000
SecurePVT.min_ground_speed=0
SecurePVT.max_ground_speed=200

; Velocity
SecurePVT.pos_error_threshold=5 ; Receiver will decrease spoofer score if the new location is within 5m of the lkgl, used for velocity consistency check
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newline terminate the final line

106 changes: 106 additions & 0 deletions conf/security_checks_gps_l1_ca_fifo.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
; This is a GNSS-SDR configuration file
; The configuration API is described at https://gnss-sdr.org/docs/sp-blocks/
; SPDX-License-Identifier: GPL-3.0-or-later
; SPDX-FileCopyrightText: (C) 2010-2020 (see AUTHORS file for a list of contributors)

; You can define your own receiver and invoke it by doing
; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf


[GNSS-SDR]

;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=10000000
GNSS-SDR.telecommand_enabled=true
GNSS-SDR.telecommand_tcp_port=3333

;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=Fifo_Signal_Source
SignalSource.filename=/tmp/fifo ; example usage: mkfifo fifo.fifo && cat path_to.bin >> fifo.fifo
SignalSource.sample_type=gr_complex; ; sample representation in fifo stream - will always output gr_complex
SignalSource.dump=false
;SignalSource.dump_filename=dump

;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Pass_Through

;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=8
Channels.in_acquisition=1
Channel.signal=1C


;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=gr_complex
Acquisition_1C.coherent_integration_time_ms=1
Acquisition_1C.pfa=0.01
;Acquisition_1C.pfa=0.01
Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=250
Acquisition_1C.dump=false
Acquisition_1C.dump_filename=./acq_dump.dat


;######### TRACKING GLOBAL CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.dump=true
Tracking_1C.dump_filename=epl_tracking_ch_
Tracking_1C.pll_bw_hz=40.0;
Tracking_1C.dll_bw_hz=4.0;
Tracking_1C.order=3;
Tracking_1C.dump=false
Tracking_1C.dump_filename=../data/epl_tracking_c


;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false


;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat


;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=PPP_Static ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=1
PVT.display_rate_ms=1000
PVT.dump_filename=./PVT
PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea;
PVT.flag_nmea_tty_port=false;
PVT.nmea_dump_devname=/dev/pts/4
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=false

PVT.security_checks=true
PVT.print_score=true

PVT.enable_monitor=true
PVT.monitor_client_addresses=127.0.0.1
PVT.monitor_udp_port=1112
;######### Secure ############

SecurePVT.position_check=true
SecurePVT.static_pos_check=true ; Disable for dynamic scenarios
SecurePVT.max_jump_distance=100
SecurePVT.pos_jump_recovery=10 ; Receiver will decrease spoofer score if the new location is within 10 m of the last known good location
SecurePVT.geo_fence_radius=15
SecurePVT.velocity_difference=15
SecurePVT.static_lat=42.378678035
SecurePVT.static_lon=-70.823051380
SecurePVT.static_alt=100

;######### MONITOR CONFIG ############
Monitor.enable_monitor=true
Monitor.decimation_factor=1
Monitor.client_addresses=127.0.0.1
Monitor.udp_port=1111
40 changes: 35 additions & 5 deletions src/algorithms/PVT/adapters/rtklib_pvt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
#include "gps_ephemeris.h" // for Gps_Ephemeris
#include "pvt_conf.h" // for Pvt_Conf
#include "rtklib_rtkpos.h" // for rtkfree, rtkinit
#include <glog/logging.h> // for LOG
#include <iostream> // for operator<<
#include "spoofing_detector_conf.h"
#include <glog/logging.h> // for LOG
#include <iostream> // for operator<<
#if USE_OLD_BOOST_MATH_COMMON_FACTOR
#include <boost/math/common_factor_rt.hpp>
namespace bc = boost::math;
Expand Down Expand Up @@ -120,7 +121,6 @@ Rtklib_Pvt::Rtklib_Pvt(const ConfigurationInterface* configuration,
pvt_output_parameters.gpx_rate_ms = bc::lcm(configuration->property(role + ".gpx_rate_ms", pvt_output_parameters.gpx_rate_ms), pvt_output_parameters.output_rate_ms);
pvt_output_parameters.geojson_rate_ms = bc::lcm(configuration->property(role + ".geojson_rate_ms", pvt_output_parameters.geojson_rate_ms), pvt_output_parameters.output_rate_ms);
pvt_output_parameters.nmea_rate_ms = bc::lcm(configuration->property(role + ".nmea_rate_ms", pvt_output_parameters.nmea_rate_ms), pvt_output_parameters.output_rate_ms);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't hate on whitespace. It helps readability

// Infer the type of receiver
/*
* TYPE | RECEIVER
Expand Down Expand Up @@ -818,23 +818,53 @@ Rtklib_Pvt::Rtklib_Pvt(const ConfigurationInterface* configuration,
// Set maximum clock offset allowed if pvt_output_parameters.enable_rx_clock_correction = false
pvt_output_parameters.max_obs_block_rx_clock_offset_ms = configuration->property(role + ".max_clock_offset_ms", pvt_output_parameters.max_obs_block_rx_clock_offset_ms);

// Spoofing detection parameters
pvt_output_parameters.security_checks = configuration->property(role + ".security_checks", false);
// ####### Position consistency check configuration

if (pvt_output_parameters.security_checks)
{
pvt_output_parameters.print_score = configuration->property(role + ".print_score", false);

PVTConsistencyChecksConf spoofing_detection_parameters = PVTConsistencyChecksConf();

spoofing_detection_parameters.dump_pvt_checks_results = configuration->property("SecurePVT.dump_pvt_checks_results", false);

spoofing_detection_parameters.position_check = configuration->property("SecurePVT.position_check", false);
spoofing_detection_parameters.max_jump_distance = configuration->property("SecurePVT.max_jump_distance", 100);
spoofing_detection_parameters.geo_fence_radius = configuration->property("SecurePVT.geo_fence_radius", 15);
spoofing_detection_parameters.velocity_difference = configuration->property("SecurePVT.velocity_difference", 15);
spoofing_detection_parameters.pos_error_threshold = configuration->property("SecurePVT.pos_error_threshold", 10);
spoofing_detection_parameters.static_pos_check = configuration->property("SecurePVT.static_pos_check", false);

spoofing_detection_parameters.min_altitude = configuration->property("SecurePVT.min_altitude", -10);
spoofing_detection_parameters.max_altitude = configuration->property("SecurePVT.max_altitude", 20000);
spoofing_detection_parameters.min_ground_speed = configuration->property("SecurePVT.min_ground_speed", 0);
spoofing_detection_parameters.max_ground_speed = configuration->property("SecurePVT.max_ground_speed", 200);

spoofing_detection_parameters.static_lat = configuration->property("SecurePVT.static_lat", 0.0);
spoofing_detection_parameters.static_lon = configuration->property("SecurePVT.static_lon", 0.0);
spoofing_detection_parameters.static_alt = configuration->property("SecurePVT.static_alt", 0.0);
Comment on lines +833 to +847
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the only documentation some people may see is the config file, I strongly encourage you to include units in your attribute names. For example, "SecurePVT.min_altitude_ft" (or did you really mean your upper bound to be 20000m?)

Configuring lat/lon as decimal degrees (presumed) requires an assumption of your origin (East-positive is most common, but not a given). For a config file, a string DDMMSS[.ss]H representation is better. Actually, a single property for location (DDHHMMSSH/DDDHHMMSSH) is better, since latitude is properly inseparable from longitude.

This implementation is constrained to a single instance, which might not be sufficient in the future. Inasmuch as these properties are associated to this PVT instance, it would be better, I think, to tie them to role rather than the hard-coded string "SecurePVT"


pvt_output_parameters.security_parameters = spoofing_detection_parameters;
}

// make PVT object
pvt_ = rtklib_make_pvt_gs(in_streams_, pvt_output_parameters, rtk);

DLOG(INFO) << "pvt(" << pvt_->unique_id() << ")";
if (out_streams_ > 0)
{
LOG(ERROR) << "The PVT block does not have an output stream";
}
}


Rtklib_Pvt::~Rtklib_Pvt()
{
DLOG(INFO) << "PVT adapter destructor called.";
rtkfree(&rtk);
}


bool Rtklib_Pvt::get_latest_PVT(double* longitude_deg,
double* latitude_deg,
double* height_m,
Expand Down
Loading