Sylphase SDGPS
The software-defined GPS(/GNSS) toolkit
SDGPS Tutorial

NOTE: This page is out-of-date. Please refer to Getting started with the Infix-2

We have made two tutorials for those learning our software. The first one is entirely software based using our simulation package if your hardware has not arrived yet (or if you don't feel like gathering the necessary items from around your lab). The second tutorial requires an Infix-1, but we have provided a raw stream of data so that you don't need to obtain an antenna if your developement conditions don't allow for easy line of sight with GNSS satellites.

Let's talk about using SDGPS.

Using SDGPS


After running installing the prerequisites (found in README.md), building SDGPS, and running the set up commands you will be ready to use SDGPS.

The most simple command available to you is just:

sdgps

this will produce the following output (truncated to the first 25 lines of the output for clarity):

Usage: build/main [OPTION]... [PIPELINE]...
Allowed options:
--help produce help message
--print-mallocs
print a message on every malloc
--abort-on-malloc
crash on malloc
--malloc-stats
show malloc stats in status line and at program termination
--timestamp
prefix all printed lines with timestamp
--log FILENAME
log all console output to file
--no-node-monitor
disable tracking of per-thread/per-node CPU usage and sleep time (normally displayable via keybind) to avoid overhead
--version
print version and exit
PIPELINE
To run a pipeline, use this syntax for PIPELINE:
NODETYPE [NODEOPTION]... [! NODETYPE [NODEOPTION]...]...
To run a utility, use this syntax for PIPELINE:
UTILITY [UTILITYOPTION]...
To get options available for a given node or utility, use this syntax for PIPELINE:
NODETYPE/UTILITY --help
To list all available nodes and utilities, provide PIPELINE of "help" or empty PIPELINE.
Available interfaces:
* cooked
* cooked2
* observables
* orientation_trajectory
* raw
* solution
* wrench
Available node types:
* _generate-cooked-test-stream (->cooked)
* _generate-cooked2-test-stream (->cooked2)
* _generate-observables-test-stream (->observables)
* _generate-orientation-trajectory-test-stream (->orientation_trajectory)
* _generate-raw-test-stream (->raw)
* _generate-solution-test-stream (->solution)
* _generate-wrench-test-stream (->wrench)
* abort-signal-tracking (*->*)
* analyze-stream (*->*)
* apply-magnetometer-calibration (*->*)
* background (*->*)
* buffer (*->*)
* buffer-cooked-from (->cooked)
* buffer-cooked2-from (->cooked2)
* buffer-observables-from (->observables)
* buffer-orientation-trajectory-from (->orientation_trajectory)
* buffer-raw-from (->raw)
* buffer-solution-from (->solution)
* buffer-wrench-from (->wrench)
* characterize-channel-rx (raw->[raw])
* characterize-channel-tx (->raw)
* concatenate-cooked-streams (->cooked)
* concatenate-cooked2-streams (->cooked2)
* concatenate-observables-streams (->observables)
* concatenate-orientation-trajectory-streams (->orientation_trajectory)
* concatenate-raw-streams (->raw)
* concatenate-solution-streams (->solution)
* concatenate-wrench-streams (->wrench)
* connect-cooked-tcp (->cooked)
* connect-cooked-unix (->cooked)
* connect-cooked2-tcp (->cooked2)
* connect-cooked2-unix (->cooked2)
* connect-observables-tcp (->observables)
* connect-observables-unix (->observables)
* connect-orientation-trajectory-tcp (->orientation_trajectory)
* connect-orientation-trajectory-unix (->orientation_trajectory)
* connect-raw-tcp (->raw)
* connect-raw-unix (->raw)
* connect-solution-tcp (->solution)
* connect-solution-unix (->solution)
* connect-wrench-tcp (->wrench)
* connect-wrench-unix (->wrench)
* cooked-to-raw (cooked->raw)
* cooked2-to-raw (cooked2->raw)
* decimate-observables (observables->observables)
* decimate-solution (solution->solution)
* decoder (cooked2->observables)
* decrease-bit-depth (*->*)
* dummy-cooked-sink (cooked->cooked)
* export-json (*->*)
* export-json-tcp (*->*)
* export-json-unix (*->*)
* extrapolate-realtime-trajectory (solution->solution)
* fabricate-dropped-packets (*->*)
* fake-gnss-outage (observables->observables)
* fake-packet-loss (*->*)
* filter-cooked2-signals (cooked2->cooked2)
* filter-observables-svs (observables->observables)
* generate-rf-delay-calibration-waveform (->raw)
* generate-simple-trajectory (->solution)
* generate-vcxo-waveform (*->*)
* gpsdo (solution->[solution])
* inertial-kf2 (observables->solution)
* ingest-orientation (observables->observables)
* join-cooked-streams (->cooked)
* join-cooked2-streams (->cooked2)
* join-observables-streams (->observables)
* join-raw-streams (->raw)
* kf2 (observables->solution)
* kill-cooked-spur (cooked->cooked)
* listen-cooked-tcp (cooked->[cooked])
* listen-cooked-unix (cooked->[cooked])
* listen-cooked2-tcp (cooked2->[cooked2])
* listen-cooked2-unix (cooked2->[cooked2])
* listen-observables-tcp (observables->[observables])
* listen-observables-unix (observables->[observables])
* listen-orientation-trajectory-tcp (orientation_trajectory->[orientation_trajectory])
* listen-orientation-trajectory-unix (orientation_trajectory->[orientation_trajectory])
* listen-raw-tcp (raw->[raw])
* listen-raw-unix (raw->[raw])
* listen-solution-tcp (solution->[solution])
* listen-solution-unix (solution->[solution])
* listen-wrench-tcp (wrench->[wrench])
* listen-wrench-unix (wrench->[wrench])
* mock-blocking-node (*->*)
* mock-crashing-node (*->*)
* mock-event-source (*->*)
* mock-invalid-observables (observables->observables)
* mock-leds (*->*)
* mock-pulse-output (*->*)
* mock-vcxo (*->*)
* multiantenna-channel-optimizer (observables->[observables])
* observables-to-cooked2 (observables->cooked2)
* observables-to-raw (observables->raw)
* observables-to-sv-trajectory (observables->solution)
* offset-solution (solution->solution)
* output-pps (solution->[solution])
* output-receiver-pps (*->*)
* pacer (*->*)
* pll-vcxo (*->*)
* plot-cooked (cooked->[cooked])
* plot-cooked2 (cooked2->[cooked2])
* plot-ground-track (solution->[solution])
* plot-holdover-performance (solution->[solution])
* plot-observables (observables->[observables])
* plot-raw (raw->[raw])
* plot-sensors (raw->[raw])
* plot-solution (solution->[solution])
* pps-events-to-time-stream (*->*)
* pretty-print (*->*)
* pretty-print-callbacks (*->*)
* print-dropped-packets (*->*)
* print-time-at-event (*->*)
* read-cooked-file (->cooked)
* read-cooked2-file (->cooked2)
* read-observables-file (->observables)
* read-orientation-trajectory-file (->orientation_trajectory)
* read-raw-file (->raw)
* read-solution-file (->solution)
* read-wrench-file (->wrench)
* recompute-substreams (raw->raw)
* rejitter-packets (*->*)
* remap-streams (*->*)
* renumber-solution (solution->solution)
* replace-config (*->*)
* report-ttff (observables->[observables])
* resample-solution (solution->solution)
* restamp-realtime-wrenches (wrench->wrench)
* run-async-pipeline-deterministically (solution->solution)
* run-subprocess-at-time (*->*)
* send-time-upstream (solution->[solution])
* set-antenna-position (*->*)
* set-leds (*->*)
* shift-gnss-time (solution->solution)
* shift-stream-time (*->*)
* simple-pvt-solver (observables->solution)
* simple-tracking-controller (solution->wrench)
* simulate-cooked (solution->cooked)
* simulate-cooked2 (solution->cooked2)
* simulate-observables (solution->observables)
* simulate-raw (solution->raw)
* simulate-rigid-body-dynamics (->solution)
* simulate-sv-trajectory (->solution)
* simulate-vcxo (*->*)
* solution-to-orientation-trajectory (solution->orientation_trajectory)
* sort-packets (*->*)
* static-kf2 (observables->solution)
* sw-correlator (raw->cooked)
* sylphase-usbgpsimu2 (->cooked)
* sylphase-usbgpsimu2-offline (raw->cooked)
* sylphase-usbgpsimu2-raw (->raw)
* sylphase-usbgpsimu4-raw (->raw)
* synthesize-sensor-measurements (observables->observables)
* tee (*->*)
* tracker (cooked->cooked2)
* tracker-only (cooked->cooked2)
* trim-stream (*->*)
* uhd-rx (->raw)
* uhd-tx (raw->[raw])
* write-cn0-csv (observables->[observables])
* write-cooked-file (cooked->[cooked])
* write-cooked2-file (cooked2->[cooked2])
* write-iq-csv (raw->[raw])
* write-observables-file (observables->[observables])
* write-orientation-trajectory-file (orientation_trajectory->[orientation_trajectory])
* write-raw-file (raw->[raw])
* write-solution-file (solution->[solution])
* write-wrench-file (wrench->[wrench])
Available utilities:
* convert-orientation
* convert-position
* convert-time
* demo-3d-plotting
* do-nothing
* ft60x-tool
* generate-markdown-help
* get-test-source-file
* help-json
* json-rpc-client
* lecroy-oscope
* list-test-tag-patterns
* list-tests
* mini-circuits-switch
* mock-use-after-free
* parse-sdgps-cmdline
* plot-client2
* plot-csv
* plot-gain-pattern
* plot-gnss-cross-correlation
* plot-gnss-info
* plot-ionospheric-model
* plot-lecroy-waveforms
* plot-perlin-noise2
* plot-plot-file
* plot-statlog-file
* plot-tropospheric-model
* pretty-print-json-file
* pretty-print-pipeline
* print-config
* print-cooked-file-info
* print-cooked2-file-info
* print-eop
* print-gnss-info
* print-observables-file-info
* print-orientation-trajectory-file-info
* print-raw-file-info
* print-solution-file-info
* print-wrench-file-info
* query-magnetic-model
* read-from-serial-port
* run-parallel-subprocesses
* run-subprocess
* run-test
* run-uhd-binary
* run-with-SystemLock
* sylphase-usbgpsimu2-eeprom
* sylphase-usbgpsimu2-init
* validate-pipeline
Available config providers:
* custom:see options by running "sdgps print-config custom:'--help'"
* file:FILENAME (can be a text file with JSON or a SDGPS binary file with a JSON header) (also, just "FILENAME" is interpreted as a filename if it doesn't have any colons)
* json:{"gnss_streams": ...} (inline JSON)
* repofile:FILENAME (interpreted relative to SDGPS repository root; useful for configs/ files)
* ugi2:see options by running "sdgps print-config ugi2:'--help'"
Tip: use the "print-config" utility to test config providers.
Available gain pattern providers:
* dipole:<no args>
* isotropic:<no args>
Tip: run "sdgps plot-gain-pattern PROVIDER:--help" to get more detailed help for a specific provider.
Available ionospheric model providers:
* broadcast-gps:<no args>
* static-gps:--filename FILENAME or --json INLINE_JSON
* zero:<no args>
Tip: run "sdgps plot-ionospheric-model MODEL:--help" to get more detailed help for a specific model.
Available tropospheric model providers:
* rtca:<no args>
* simple:<no args>
* zero:<no args>
Tip: run "sdgps plot-tropospheric-model MODEL:--help" to get more detailed help for a specific model.
Available EOP providers:
* dynamic:FILENAME or --json=INLINE_JSON
* random:<no args>
* static:FILENAME or --json=INLINE_JSON
Tip: run "sdgps print-eop PROVIDER:--help" to get more detailed help for a specific provider.
Available UTC providers:
* dynamic:FILENAME or --json=INLINE_JSON
* static:FILENAME or --json=INLINE_JSON
Tip: run "sdgps print-utc PROVIDER:--help" to get more detailed help for a specific provider.
Available GNSS systems:
* GAL_E1B
* GAL_E1C
* GAL_E1Cwide
* GAL_E5b
* GLO_L1
* GLO_L2
* GPS_L1
* GPS_L2C
* GPS_L2CL
GNSS-specific environmental variable overrides are variables that can be overridden for all GNSS signals at once, or for a specific GNSS by appending the GNSS name.
e.g. SDGPS_ACQ_EARLY_MAX_SIGNAL applies to all GNSS, whereas SDGPS_ACQ_EARLY_MAX_SIGNAL_GAL_E1B will only apply to GAL_E1B
Available GNSS-specific environmental variable overrides:
VARIABLE[_GNSS] (TYPE): DESCRIPTION
* SDGPS_ACQ_EARLY_MAX_SIGNAL (int): Don't try acquiring SVs with an SVID > this threshold until after we've attempted to acquire all SVs below this threshold twice
* SDGPS_ACQ_IGNORE_DOPPLER_ACCEL (bool): Don't use the estimated doppler acceleration, instead assume it to be 0
* SDGPS_ACQ_OVERRIDE_FINE_INCOHERENT_REPETITIONS (int): Number of coherent slices of signal to incoherently sum during the refining step
* SDGPS_ACQ_OVERRIDE_INCOHERENT_REPETITIONS (int): Number of coherent slices of signal to incoherently sum
* SDGPS_ACQ_OVERRIDE_N_PRNS (int): Number of PRN sequences used in acquisition's coherent slicing
* SDGPS_CORRELATOR_OVERRIDE_CHANNEL_MULT (int): Controls the time-multiplexing of the hardware correlator channels
Other available environmental variable overrides:
VARIABLE (TYPE): DESCRIPTION [(=DEFAULT)]
* DISPLAY (string): Plot to this display
* PLOT_CLIENT2_FULLSCREEN (bool): Make plot window fullscreen (=0)
* PLOT_CLIENT2_GL_DEBUG_SEVERITY (sdgps::util::plot_client2::main::DebugSeverity): Set the severity threshold for GL errors to report in the console (options: NOTIFICATION, LOW, MEDIUM, HIGH, FATAL) (=FATAL)
* PLOT_CLIENT2_HEIGHT (int): Set plot window height in pixels (does nothing when using PLOT_CLIENT2_FULLSCREEN) (=720)
* PLOT_CLIENT2_WIDTH (int): Set plot window width in pixels (does nothing when using PLOT_CLIENT2_FULLSCREEN) (=1280)
* PLOT_FILE (string): Plot to this file instead of the screen
* PLOT_NO_ACKNOWLEDGE (bool): Don't wait for user to acknowledge the plot when pipeline ends (=1)
* PLOT_PORT (int): Start plot server listening on this TCP port
* SDGPS_ACQ_ANNOUNCE_PERIOD (float): Periodically report acquisition thread CPU usage (only used in non-deterministic mode; period in seconds)
* SDGPS_ACQ_APPLY_CODE_PHASE_BIAS_CHIPS (float): Bias the acquisition code phase by this many chips (=0)
* SDGPS_ACQ_DEBUG (bool): Enable acquisition debug output (=0)
* SDGPS_ACQ_EFFORT_EARLY_DURATION (float): (see SDGPS_ACQ_EFFORT_EARLY_MULTIPLIER) (=10)
* SDGPS_ACQ_EFFORT_EARLY_MULTIPLIER (float): Apply this multiplier to --acq-effort value for the first SDGPS_ACQ_EFFORT_EARLY_DURATION seconds (only has an effect if --deterministic is used) (=1)
* SDGPS_ACQ_MAX_CPU_FRAC (float): Limit each signal's acquisition thread to this percentage of a core when < SDGPS_ACQ_THROTTLE_SVS are being tracked (=0.5)
* SDGPS_ACQ_MIN_CPU_FRAC (float): Limit each signal's acquisition thread to this percentage of a core when >= SDGPS_ACQ_THROTTLE_SVS are being tracked (=0.1)
* SDGPS_ACQ_NO_SVS_CPU_FRAC (float): Limit each signal's acquisition thread to this percentage of a core if zero SVs have been tracked for SDGPS_ACQ_THROTTLE_NO_SVS_TIMEOUT seconds (=0.1)
* SDGPS_ACQ_PLOT (string): Setting this enables acquisition plot output; setting to "all" enables even more plots
* SDGPS_ACQ_PLOT_NO_EXTEND (bool): Don't extend the signal slice used in plotted acquisition results (=0)
* SDGPS_ACQ_PLOT_SLEEP (float): Add a sleep in between acquisition doppler guesses; useful for inspecting the plots before they change (units: seconds)
* SDGPS_ACQ_RADIUS_PPM (float): Acquisition doppler search radius (in PPM) (=13.076637751840977)
* SDGPS_ACQ_SPUR_KILL_DEBUG (bool): Enable debug output on acquisition's spur-killing feature (=0)
* SDGPS_ACQ_SPUR_KILL_DISABLE (bool): Disable acquisition's spur-killing feature (=1)
* SDGPS_ACQ_THREAD_SCHED_FIFO (int): Set acquisition thread's scheduling policy to SCHED_FIFO with this priority
* SDGPS_ACQ_THREAD_SCHED_IDLE (bool): Set acquisition thread's scheduling policy to SCHED_IDLE (=0)
* SDGPS_ACQ_THREAD_VERBOSE (bool): Enable verbose output on acquisition thread (=0)
* SDGPS_ACQ_THROTTLE_NO_SVS_TIMEOUT (float): Limit each signal's acquisition thread to SDGPS_ACQ_NO_SVS_CPU_FRAC of a core if zero SVs have been tracked for this many seconds
* SDGPS_ACQ_THROTTLE_SVS (int): Threshold number of tracked SVs at which to reduce acquisition effort
* SDGPS_ASYNC_WRITER_BUFFER_SIZE (int): Set the size (in bytes) of util::file_buf::AsyncWriter's lockfree circular buffer of pending file writes (=1048576)
* SDGPS_ASYNC_WRITER_CHUNK_SIZE (int): Set the maximum amount of data (in bytes) that util::file_buf::AsyncWriter will provide to a single write() call (=65536)
* SDGPS_ASYNC_WRITER_MAX_DELAY (sdgps::util::Time<sdgps::util::TimeOffset_detail::TimeOffset<sdgps::util::TypeList<>, sdgps::util::TypeList<> > >): Set the maximum amount of time (in seconds) that util::file_buf::AsyncWriter will coalesce writes for (=1.000000000000000000)
* SDGPS_BYPASS_HISTOGRAM_CHECK (bool): Ignore any histogram failure instead of causing program exit (=0)
* SDGPS_BYPASS_KF2_VALIDATE_INITIAL_FIX (bool): Bypass kf2 requirement to confirm the initial fix has a reasonable altitude and velocity before initializing (=0)
* SDGPS_CAPTURE_CHECK_TEST_OUTPUT_DIR (string): Path that individual halves of capture/check-style tests will write/read capture file(s) to/from
* SDGPS_COMMON_ASYNC_CALL_FASTPATH (bool): Skip all checks on CommonChecker::wrap_async_call() and just immediately call the callback (=0)
* SDGPS_COMMON_CHECKER_VERBOSE (bool): Log any detected gaps in packet streams (i.e. dropped packets) (=0)
* SDGPS_CONSTELLATION_GEOMETRY_FALLBACK (bool): Fallback to previous constellation generation with occasional degenerate geometry (=0)
* SDGPS_COROUTINE_DEBUG (bool): Run each coroutine in separate thread for better stack traces in gdb (slower) (=0)
* SDGPS_CORRELATOR_DEBUG (bool): Enable debug messages on hw_correlator (=0)
* SDGPS_CORRELATOR_MAX_SVS_FALLBACK (bool): Fallback to previous behavior of treating --max-svs as a per antenna limit instead of per GNSS system limit (=0)
* SDGPS_DECIMATE_OBSERVABLES_DEBUG (bool): Enable debug output on decimate-observables (=0)
* SDGPS_DISABLE_STATUS_LINE (bool): Disable status line output (=0)
* SDGPS_DISABLE_TERMINATE_HANDLER (bool): Don't install std::terminate() handler (=0)
* SDGPS_EPHEMERIS_EVALUATOR_DIFF (bool): When a new ephemeris is decoded, print the diff between the old and new one; only has an effect if SDGPS_EPHEMERIS_EVALUATOR_VERBOSE is set (=0)
* SDGPS_EPHEMERIS_EVALUATOR_DISABLE_GGTO (bool): Don't apply GGTO correction (=0)
* SDGPS_EPHEMERIS_EVALUATOR_VERBOSE (bool): Enable verbose output on EphemerisEvaluator (=0)
* SDGPS_FX2_PROGRAM_STRESS_TEST (bool): Spam device string control transfers in parallel with FX2 firmware load to test robustness of firmware loading (=0)
* SDGPS_FX2_PROGRAM_VERBOSE (bool): Always output log messages during FX2 programming (=0)
* SDGPS_FX2_RECONNECT_TIMEOUT (float): Wait this many seconds when reconnecting after FX firmware load (=30)
* SDGPS_GPS_L2C_SIMULATE_BLOCK_IIR_SVS (bool): Simulate Block IIR satellites instead of default behavior of all simulated satellites being IIR-M+ (=0)
* SDGPS_HARDWARE_LECROY_OSCOPE_DEBUG (bool): Enable verbose debug logging for LeCroy oscilloscope driver (=0)
* SDGPS_HARDWARE_MINI_CIRCUITS_SWITCH_DEBUG (bool): Enable verbose debug logging for Mini-Circuits RF switch driver (=0)
* SDGPS_HW_CORRELATOR_DISABLE_ACQ_THREAD_MAX_LAUNCH_HINT_AGE (sdgps::util::Time<sdgps::util::TimeOffset_detail::TimeOffset<sdgps::util::TypeList<>, sdgps::util::TypeList<> > >): Maximum LaunchSignalTracking hint age for AcqThread to be suspended (units: seconds) (=5.000000000000000000)
* SDGPS_HW_CORRELATOR_DISABLE_ACQ_THREAD_MIN_SVS_REQUIRED (int): Minimum number of tracked SVs required for AcqThread to be suspended (=6)
* SDGPS_INERTIAL_KF2_ESTIMATE_ANTENNA_DELAYS_JOIN_FRONTENDS (bool): assume that all the frontends of a given secondary antenna have the same delay instead of estimating them independently (=0)
* SDGPS_INERTIAL_KF2_RESET_GYRO_BIAS_MAGNITUDE (float): reset filter if magnitude of gyro_bias estimate exceeds this threshold (units: degrees/second) (=5)
* SDGPS_JSON_RPC_PORT (int): Start JSON-RPC server on this TCP port
* SDGPS_JSON_RPC_WRITE_PORT (string): Write JSON-RPC TCP server port to this file; useful with SDGPS_JSON_RPC_PORT=0, which chooses an arbitrary free port
* SDGPS_KF2_OUTPUT_DURING_SETTLING (bool): Allow kf2 to output a solution stream while the filter is still settling (=0)
* SDGPS_LEAVE_TEMPORARY_FILES (bool): Don't delete file made via TemporaryFile, instead print its path when object is destroyed (=0)
* SDGPS_MAIN_CHECK_MALLOC_BYTES_ABORT (int): Only allow this many bytes allocated via malloc calls at runtime; failure immediately
* SDGPS_MAIN_CHECK_MALLOC_BYTES_MAX (int): Only allow this many bytes allocated via malloc calls at runtime; failure after pipeline exit
* SDGPS_MAIN_CHECK_MALLOC_CALLS_ABORT (int): Only allow this many calls to malloc at runtime; failure immediately
* SDGPS_MAIN_CHECK_MALLOC_CALLS_MAX (int): Only allow this many calls to malloc at runtime; failure after pipeline exit
* SDGPS_MAIN_CHECK_MALLOC_LOG_FIRST (int): Print a stack trace for the first SDGPS_MAIN_CHECK_MALLOC_LOG_FIRST malloc calls and continue
* SDGPS_MAIN_LOG_ROTATE_SIZE_BYTES (int): Rotate --log file such that this many bytes of history are always preserved
* SDGPS_MALLOC_ARENA_STRICT (bool): Die if any allocations are still present when Arena::exit() is called; never use backup pool (mem2) (=0)
* SDGPS_MALLOC_ARENA_TRACE (bool): Display stack traces of all malloc calls (=0)
* SDGPS_NETLIST_ANCHOR_SETUP_DEVICE_NAME (string): only consider device assignment solutions that contain this setup netlist device
* SDGPS_NODE_MONITOR_ENABLE_PER_NODE_STATLOG (bool): Output StatLog data per node in addition to the default of per thread (=1)
* SDGPS_NO_HEADER (bool): Don't print SDGPS header including version and exact command at the start of the pipeline (=0)
* SDGPS_OMIT_INTERFACE_CHECKERS (bool): Don't check to make sure interfaces match between nodes in the pipeline (=0)
* SDGPS_OUTPUT_PPS_EXIT_AFTER_FIRST_PULSE (bool): End pipeline after output-pps emits the first pulse (=0)
* SDGPS_PERLIN_NOISE_DEBUG (bool): Enable debug output for plot-perlin-noise (=0)
* SDGPS_PLOT_CLIENT2_AUTOFIT_IGNORE_X_LESS_THAN (float): Ignore points with an x coordinate less than this when doing autofit
* SDGPS_PLOT_CLIENT2_DPI_SCALE (float): Override DPI scale factor provided by window manager (example: "2" for 200% scaling)
* SDGPS_PLOT_CLIENT2_EXIT_AFTER_REDRAWS (int): Close plotting window after this many redraws
* SDGPS_PLOT_CLIENT2_FAKE_NETWORK_BW_LIMIT (int): Emulate a slow TCP connection for testing purposes (units: bytes/second)
* SDGPS_PLOT_CLIENT2_IMGUI_DEMO (bool): Display demo window to show off ImGui features (=0)
* SDGPS_PLOT_CLIENT2_IMPLOT_DEMO (bool): Display demo window to show off ImPlot features (=0)
* SDGPS_PLOT_CLIENT2_LOG_PROTOCOL (bool): Log plotting protocol packets to the console (=0)
* SDGPS_PLOT_CLIENT2_MIN_PLOT_HEIGHT (int): minimum height of each plot (units: pixels) (=350)
* SDGPS_PLOT_CLIENT2_PLOT2D_SHOW_MARKERS (bool): In addition to the lines connecting them, show circle markers on data points in 2D plots (=0)
* SDGPS_PLOT_CLIENT2_SCREENSHOT_AND_EXIT (string): When the plot comes up, save a screenshot to this filename and immediately exit
* SDGPS_PLOT_LINE_REGEX (sdgps::util::regex): Only show lines with a label matching this regex string (=.*)
* SDGPS_PLOT_TITLE_REGEX (sdgps::util::regex): Only show plots with a title matching this regex string (=.*)
* SDGPS_PLOT_TO_IMAGE_FILE (string): like PLOT_FILE, except plot is rasterized to an image before being written to disk
* SDGPS_PLOT_UNIX_SOCKET (string): Start plot server listening on UNIX socket at this filesystem path
* SDGPS_PLOT_USE_XVFB (bool): Use X virtual framebuffer (=0)
* SDGPS_REACTOR_OVERRIDE_WATCHDOG_ENABLE (bool): Whether the watchdog timer is enabled on realtime threads (=0)
* SDGPS_REALTIME_POLICY_RR (bool): Use SCHED_RR (round robin policy for realtime threads) instead of SCHED_FIFO (=0)
* SDGPS_REALTIME_PRIORITY (int): Set realtime thread's priority to this (99 being highest priority; 1 being lowest) (=99)
* SDGPS_SIMULATE_RAW_BENCHMARK (bool): Enable benchmark mode for simulate-raw (=0)
* SDGPS_SIMULATE_RAW_CHUNK_SIZE (int): Override simulate-raw work chunk size
* SDGPS_SIMULATE_RAW_COMPUTE_PRN_DEBUG_PLOT (bool): Plot simulate-raw compute_prn plot (=0)
* SDGPS_SIMULATE_RAW_REFERENCE (bool): Use reference implementation for innermost loop in simulate-raw (slower) (=0)
* SDGPS_SIMULATE_SCENE_GRANULAR_VISIBILITY (bool): Enable more granular visibility controls for simulated 3d scene (=0)
* SDGPS_SKIP_HISTOGRAM_CHECK (bool): Skip the histogram check on the incoming sample stream from hardware (=0)
* SDGPS_STATIC_KF2_ESTIMATE_ANTENNA_DELAYS_JOIN_FRONTENDS (bool): assume that all the frontends of a given secondary antenna have the same delay instead of estimating them independently (=0)
* SDGPS_STATLOG_FILE_ROTATE_SIZE_BYTES (int): Rotate STATLOG_FILE file such that this many bytes of history are always preserved
* SDGPS_SW_CORRELATOR_DISABLE_ACQ_THREAD_MAX_LAUNCH_HINT_AGE (sdgps::util::Time<sdgps::util::TimeOffset_detail::TimeOffset<sdgps::util::TypeList<>, sdgps::util::TypeList<> > >): Maximum LaunchSignalTracking hint age for AcqThread to be suspended (units: seconds) (=5.000000000000000000)
* SDGPS_SW_CORRELATOR_DISABLE_ACQ_THREAD_MIN_SVS_REQUIRED (int): Minimum number of tracked SVs required for AcqThread to be suspended (=6)
* SDGPS_SYSTEM_STATE_DIR (string): Override the directory SDGPS uses for system state files; e.g. locks, shmids (=/var/lock/sdgps)
* SDGPS_SYSTEM_STATE_DIR_GROUP (string): Override the linux user group that should own the system state directory (=sdgps)
* SDGPS_TEST_PLOT_COMMON_SHOW_PLOTS (bool): Show plot test plots (=0)
* SDGPS_THREAD_COUT_BUFFER_SIZE (int): Sets the size (in bytes) of each thread's lockfree circular buffer of console log messages (=65536)
* SDGPS_UHD_BYPASS_USB_3_CHECK (bool): Bypass USB 3.0 check (=0)
* SDGPS_UHD_RX_DIE_ON_ASYNC_AFTER (sdgps::util::Time<sdgps::interfaces::StreamTimeTag>): Causes uhd-rx to immediately die when an asynchronous event occurs after this many seconds
* SDGPS_UHD_TX_DEBUG (bool): Enable debug logging from uhd-tx node (=0)
* SDGPS_UHD_TX_DIE_ON_ASYNC_AFTER (sdgps::util::DoubleOrInf): Make uhd-tx immediately abort if an asynchronous event (e.g. underflow) occurs after this many seconds of runtime; set to "inf" to never abort (=30)
* SDGPS_UTIL_CSV_IGNORE_ROWS_BEFORE_COLUMN_COUNT_CHANGE (bool): Ignore CSV rows until column count changes, indicating the header is done (useful for parsing statlog files) (=0)
* SDGPS_UTIL_DIE_ABORT (bool): Call abort() instead of exiting if util::die is called or an assertion fails (=0)
* SDGPS_UTIL_DIE_STACK_TRACE (bool): Display a stack trace when program exits via util::die (=0)
* SDGPS_UTIL_DIE_STOP (bool): Call raise(SIGSTOP) to freeze process instead of exiting if util::die is called or an assertion fails (=0)
* SDGPS_UTIL_HTTP_TRACE_ALL (bool): enable verbose logging for all HTTP connections (=0)
* SDGPS_UTIL_MALLOC_WRAPPER_PARANOID (bool): Detect all use-after-frees and most out-of-bounds memory accesses (at the cost of wasting a few pages of RAM per allocation and likely exceeding the default vm.max_map_count limit) (=0)
* SDGPS_UTIL_PARSE_ARGS_DEBUG (bool): Enable debug output for node arg parsing (=0)
* SDGPS_UTIL_PARSE_ARGS_TERMINAL_WIDTH (int): Override autodetected terminal width used for formatting --help text
* SDGPS_UTIL_PERF_BYPASS_OPEN_FAILURE (bool): Make error from perf_event_open() non-fatal; on error, stub implementation of counter that always returns 0 will be used (=0)
* SDGPS_UTIL_PERF_ENABLE (bool): Allow use of hardware performance counters; if disabled, stub implementation of counter that always returns 0 will be used (=1)
* SDGPS_UTIL_PLOT_FILE_USE_BINARY_FORMAT (bool): make PLOT_FILE use binary format (=0)
* SDGPS_UTIL_PUBLISHER_CHUNK_SIZE (int): Set the maximum amount of data (in bytes) that util::Publisher will provide to a single write() call (=65536)
* SDGPS_UTIL_PUBLISHER_DEBUG (bool): Enable debug messages from util::Publisher (=0)
* SDGPS_UTIL_PUBLISHER_MAX_CLIENTS (int): Allow this many simultaneous client connections per util::Publisher instance (=8)
* SDGPS_UTIL_PUBLISHER_MAX_DELAY (sdgps::util::Time<sdgps::util::TimeOffset_detail::TimeOffset<sdgps::util::TypeList<>, sdgps::util::TypeList<> > >): Set the maximum amount of time (in seconds) that util::Publisher will coalesce writes for (=0.100000000000000000)
* SDGPS_UTIL_PUBLISHER_MAX_HEADER_SIZE (int): Set the maximum amount of header data (in bytes) that util::Publisher will be able to handle without dynamically allocating memory when a client connects (=1048576)
* SDGPS_UTIL_STACK_TRACE_DISABLE_COLOR (bool): Do not force ANSI color codes in stack traces (=0)
* SDGPS_UTIL_SUDO_ALLOWED (bool): Allow use of "sudo" command to elevate permissions to access hardware (e.g. /dev/mem) as non-root user (=0)
* SDGPS_UTIL_TCP_CONNECT_DEBUG (bool): Enable verbose logging in util::tcp::connect() for debugging purposes (=0)
* STATLOG_FILE (string): Enable StatLog output to this file
* STATLOG_PLOT (bool): Enable StatLog output to a plot (=0)
* STATLOG_PLOT_POINTS (int): Only keep the most recent N plot points (=1000)
* STATLOG_PORT (int): Enable StatLog output via a TCP server listening on this port
* STATLOG_RATE (sdgps::interfaces::SampleRate): StatLog output rate (units: Hz) (=1)
* STATLOG_REGEX (sdgps::util::regex): Limit the keys that are captured to ones that match this regex (=.*)
* UHD_IMAGES_DIR (string): Directory to search for UHD images (=/tmp/cache_cmd_work.aclbyh9r/w/sdgps_GIT_VERSION/build/hw/uhd/images)
Available plotting backends:
* plot_client_x11: triggered by DISPLAY environment variable being set
* plot_client_xvfb: triggered by SDGPS_PLOT_USE_XVFB environment variable being set
* plot_file: triggered by PLOT_FILE environment variable being set
* plot_server_tcp: triggered by PLOT_PORT environment variable being set
* plot_server_unix: triggered by SDGPS_PLOT_UNIX_SOCKET environment variable being set
version GIT_VERSION-0-gca2ac5e

There are a few things to note here:

Interfaces


  • After each node name is the sink interface followed by the source interface.

The syntax for this is denoted as follows:

node-name (sink_interface->source_interface)

For example:

kf2 (observables->solution)

means that the kf2 node is an observables sink and solution source.

  • Within a node chain, the source and sink interface of adjacent nodes must match.

For example

sdgps sylphase-usbgpsimu2 ! tracker

is a valid node chain because the sylphase-usbgpsimu2 node outputs cooked packets, and the tracker node accepts cooked packets.

  • If you try to use tab complete will only show nodes with matching interfaces.

For example:

sdgps sylphase-usbgpsimu2 ! <TAB>

will not display nodes that are not cooked sinks.

Put simply:

  • Sink interfaces refer to the type of packets that each node can process.
  • Source interfaces refer to the type of packets that node outputs.

For more details about the types of interfaces vist the Interfaces page.

Available Options


  • SDGPS can always be called with any of the Allowed options.

For example:

sdgps help

will produce the same result as:

sdgps
  • Node chains are separated by the ! symbol.
  • Node options can be found by typing:
sdgps node-name --help

For example:

sdgps kf2 --help

produces the following output:

Usage:

kf2 [OPTION]...

Allowed options:

Option Description
--help produce help message
--output-rate arg output solution packets at this rate (units: Hertz) (default: the highest integer divisor of the IMU sample rate that is <= 100 Hz)
--offline don't boost state to realtime. incurs delay of OFFSET seconds
--print-phase-resets print phase resets
--ionospheric-model arg (=zero) use specified ionospheric delay model (default: assume ionospheric delay to always be zero)
--wait-for-ionospheric-model wait for ionospheric model to be initialized to avoid transient behavior
--tropospheric-model arg (=simple) use specified tropospheric delay model
--estimate-ztd-factor estimate ZTD (zenith tropospheric delay) scale factor
--estimate-ionospheric-delay estimate ionospheric delay; with dual-frequency measurements, convergence is immediate, but with single-frequency measurements, convergence takes >= 1 hour
--estimate-antenna-delays estimate differential delay between antennas
--elevation-mask arg do not use observables from SVs with an elevation below this angle relative to the local horizon (units: degrees)
--antenna-elevation-mask arg do not use observables from SVs with an elevation below this angle relative to the plane defined by the antenna's "axis" vector (units: degrees) (multiantenna example: 'ANT0:20,ANT1:0')
--p-ignore arg (=1e-9) p-value threshold for ignoring an SV due to a large pseudorange residual; set to 0 to never ignore
--ignore-duration arg (=1) if --p-ignore is triggered, ignore all of SV's measurements for this many seconds
--abort-signals-ignored-for arg if an SV's measurements are --p-ignored for this many seconds, abort signal tracking via the AbortSignalTracking FunctionalityCallback
--p-log arg (=1e-6) p-value threshold for logging a message about a large measurement residual; set to 0 to never log
--p-reset arg (=0) p-value threshold for triggering a reset due to large pseudorange residual; set to 0 to never reset
--p-phase-reset arg (=1e-6) p-value threshold for resetting carrier phase tracking for a given SV; set to 0 to never reset
--ignore-doppler minimize use of Doppler observable
--ignore-phase don't use phase observable
--clock-wander-rate arg (=1e-17) diffusion constant for local oscillator frequency random walk (units: (s/s)^2/s)
--phase-wander-rate arg (=0.02) diffusion constant for unmodeled SV phase random walk (units: radian^2/s)
--plot-residuals plot measurement residuals
--min-sample-period arg (=0) minimum width between plot points in seconds; plot points closer than this will be averaged
--x-axis-unit arg (=sec) unit of X axis (options: sec, min, hour, day)
--x-axis-absolute plot absolute stream time on X axis instead of relative to now (implied by --wait)
--detrend <no effect>
--wait wait for pipeline to terminate, then plot (default: live plotting)
--live-history arg (=60) duration of live history buffer in seconds
--title-suffix arg append string to plot titles
--sample-time-stream arg name of Time stream to include in "time_streams" key of solution output; will also match a unique prefix of a name; special value of "*" will select all
--include-sisre-in-covariance arg (=0) add given SISRE contribution to position covariance matrix (units: meters rms)
Note: SISRE (rms) = sqrt((--sv-ephemeris-error value)^2 + (--sv-clock-error value)^2)
  • Only nodes with matching interfaces can be chained. Our tab comlete program ensures that only allowable nodes and options will appear when pressing <TAB>, but there are some nuances with files such as cooked2-to-raw and interfaces with the cooked interface as a source.
  • Positional arguments do not need --option-name before the argument. For example:
sdgps read-observables-file foo.obs

and

sdgps read-observables-file --filename foo.obs

are equally valid and produce the same result.

  • You can check if a node has position arguments by checking it's help page:

For example:

sdgps connect-observables-tcp --help

produces:

Usage:

connect-observables-tcp [OPTION]... HOST PORT

Allowed options:

Option Description
--help produce help message
--host HOST make connection to IP address or hostname HOST
--port PORT make connection to TCP port number PORT

Here you can see the HOST and PORT options on the first line are not enclosed by [] which signifies that they are positional arguments in that order.

Simulation Tutorial


Now that the general format of using SDGPS should be fairly clear, let's jump into some examples.

Example:

sdgps generate-simple-trajectory --rate inf --duration 120 --velocity-ecef '[1,0,0]' --angular-velocity-enu '[1, 1, 1]' ! simulate-raw configs/simple ! sw-correlator --deterministic ! tracker ! decoder ! kf2 ! write-solution-file foo.sol

Let's look at the outputs of each of these nodes.

The first node is the generate-simple-trajectory node.

Usage:

generate-simple-trajectory [OPTION]...

Allowed options:

Option Description
--help produce help message
--sample-rate SAMPLE_RATE (=100) sample rate
--rate RATE (=1) generate at RATE times real time (inf works)
--duration DURATION (=inf) stop after DURATION seconds (inf works)
--position-ecef arg (=[740883,-5497747,3136908]) initial platform position as a 3-length JSON array
--velocity-ecef arg (=[0,0,0]) platform velocity as a 3-length JSON array
--acceleration-ecef arg (=[0,0,0]) platform acceleration as a 3-length JSON array (units: m/s^2)
--orientation-enu arg (={"w":1,"x":0,"y":0,"z":0}) initial platform orientation as a JSON object
--angular-velocity-enu arg (=[0,0,0]) platform angular velocity as a 3-length JSON array
--start-time arg (=1298764809.869604401089357952) GNSS time at start of trajectory
--circle arg (={"radius":0,"axis_enu":[0,0,1],"period":1}) circle around the point that would otherwise be output
--bob arg add superimposed bobbing motion of axis_body * sin(2*pi*t/period) (example: '{"axis_body":[0,1,0],"period":5}')

Here we can see that this is node has quite a few options. The options we specified were the:

  • rate, which allows it to generate a solution stream as fast possible.
  • duration, which we limited to 120 seconds.
  • velocity-ecef which is the velocity of the platform in ECEF coordinates. Note that the JSON array is enclosed in single quotes.
  • angular-velocity-enu, we added an angular velocity to allow the kf2 node, which requires motion to initialize.

The next node is the simulate-raw node.

Usage:

simulate-raw [OPTION]... [CONFIG_STR (=repofile:configs/simple)] [ENVIRONMENT_FILENAME]

Allowed options:

Option Description
--help produce help message
--config CONFIG_STR (=repofile:configs/simple) config string (run "sdgps help" for examples)
--satellites SATELLITES_FILENAME read satellite definitions from SATELLITES_FILENAME
--environment ENVIRONMENT_FILENAME read environment definitions from ENVIRONMENT_FILENAME; only simulate-raw supports this option currently
--start-stream-time STREAM_TIME (=10000001234.141592025756835936) first solution packet will correspond to this STREAM_TIME in output
--disable-plot disable plotting of the simulated scenario
--bit-inner-corruption-probability arg (=0) corrupt unprotected GNSS NAV bits this often (used for testing decoder robustness)
--bit-outer-corruption-probability arg (=0) corrupt ECC-protected GNSS NAV bits this often (used for testing decoder robustness)
--gps-broadcast-ionospheric-model GPS_IONOSPHERIC_MODEL JSON with Klobuchar ionospheric model parameters to be broadcast on GPS L1 and L2C signal; This will override the ionospheric model provided via SATELLITES_FILENAME; (e.g. the contents of data/sample_ionospheric_model.iono)
--broadcast-utc UTC_PARAMETERS_FILENAME JSON file with UTC parameters to be broadcast on GPS L2C signal (e.g. data/sample_utc_model.utc)
--broadcast-eop EOP_PROVIDER EOP provider used to generate EOP parameters to be broadcast on GPS L2C signal (e.g. dynamic:data/sample_eop_model.eop)
--broadcast-ggto GGTO_PARAMETERS_FILENAME JSON file with GGTO parameters to be broadcast on GAL_E1B and GAL_E5b signal (e.g. data/sample_ggto_model.ggto)
--broadcast-gps-l1-ura GPS_L1_URA URA value to be broadcast on GPS_L1 signal; default value is 2 meters (e.g. to simulate an invalid URA use '{"error":"invalid"}')
--broadcast-gps-l2c-ura GPS_L2C_URA URA value to be broadcast on GPS_L2C signal; default value is 2 meters (e.g. to simulate 2 meters use '{"result":2}')
--broadcast-galileo-sisa GALILEO_SISA SISA value to be broadcast on GAL_E1B and GAL_E5b signal; default value is 2 meters (uses same format as GPS_L1_URA and GPS_L2C_URA)
--broadcast-glonass-ura GLONASS_URA URA value to be broadcast on GLO_L1 and GLO_L2 signal; default value is 2 meters (uses same format as GPS_L1_URA and GPS_L2C_URA)
--sv-ephemeris-error arg (=0) 1D rms ephemeris error to simulate; each of the 3 spatial axes will have an independent 0-mean random offset with this standard deviation applied (units: meters)
--sv-clock-error arg (=0) rms clock error to simulate; SV clock will have a 0-mean random offset with this standard deviation applied (units: meters)
Note: SISRE (rms) = sqrt((--sv-ephemeris-error value)^2 + (--sv-clock-error value)^2)
--sv-error-relaxation-time RELAXATION_TIME (=3600) autocorrelation decay time constant of SV ephemeris/clock error random walk (units: seconds)
--sv-error-seed SEED (=default) seed for SV ephemeris/clock error random number generator; can be any string
--ztd-variation arg (=0) rms relative zenith tropospheric delay wander to simulate; nominal tropospheric delay will be scaled by a random walk with mean 1 and this standard deviation (unitless)
--ztd-relaxation-time RELAXATION_TIME (=3600) autocorrelation decay time constant of ZTD wander (units: seconds)
--cn0 CN0 fix all signal C/N_0 values to CN0 dB-Hz (default: C/N_0 is calculated based on SV-receiver range) (supports antenna-specific syntax: 'ANT0:45,ANT1:40')
--physical-ionospheric-model arg (=zero) ionospheric model that is used for computing simulated observables
--physical-tropospheric-model arg (=simple) tropospheric model that is used for computing simulated observables
--antenna-elevation-mask arg obscure SVs that have an elevation below this angle (elevation is relative to the horizon defined by the antenna's body-frame "axis" config parameter) (units: degrees) (multiantenna example: 'ANT0:20,ANT1:0')
--gnss-stream-group-delay arg simulate a per-GNSS-stream group delay to model e.g. cable delay or differential antenna SAW filter delay (example: "[1e-9, 2e-9]" to delay stream 0 by 1 ns and stream 1 by 2 ns)
--gain-pattern PROVIDER_NAME[:PROVIDER_ARGS...] (=isotropic) gain pattern provider name and arguments (e.g. "isotropic" or "crossed-dipole:'--radius=0.04527')
--sv-whitelist arg only simulate these SVIDs (e.g. "1,2,3")
--threads-per-gnss-stream THREADS (=4) distribute GNSS stream generation over THREADS threads
--gnss-interpolation-rate FREQUENCY (=100) linearly interpolate SV signals over intervals of 1/FREQUENCY seconds; increased rate adds computational overhead
--spur arg generate spur at this baseband frequency
--spur-cn0 arg (=60) C/N_0 of spurs added by --spur
--outage-start arg start GNSS outage (all SV signals disappear) at this GNSS time
--outage-end arg end GNSS outage (all SV signals reappear) at this GNSS time
--outage-mask arg limit outage to signals which have "STREAM/SUBSTREAM/GNSS/SVID" match this regex (example: '.*/.*/GPS_L2C/.*' will match all GPS_L2C SVs on all (sub)streams
--noise-seed arg (=default) seed for noise floor generation
--antialias (EXPERIMENTAL, SLOW) antialias signal by bandlimiting it to the band defined by the config's "spectrum_info" value
--oversampling-ratio arg (=3) oversampling ratio to reduce artifacts from linear interpolation; = (sampling rate) / (Nyquist rate); only has an effect if --antialias is used
--null arg generate null at this baseband frequency (units: Hertz); only has an effect if --antialias is used
--null-width arg (=1e5) width of nulls added by --null (units: Hertz)
--filter-rolloff arg bandpass filter rolloff (units: dB/MHz) (example: 10 for -10 dB/MHz); only has an effect if --antialias is used

This node, as its name would suggest: simulates raw packets (which consists of unprocessed sensor data) and is a raw source. It also has a required config parameter. There are a few config files in the sdgps/configs directory. They each defines a number of parameters about our sensors (such as covariance for our IMU) and the type of GNSS signals we expect to receive (GPS_L1, GLO_L2, etc). We have several predefined configs with different parameters. For now, we are just going to use the simple config.

The next node is the sw-correlator node.

Usage:

sw-correlator [OPTION]...

Allowed options:

Option Description
--help produce help message
--deterministic run synchronously so that everything is deterministic
--correlators CORRELATORS number of correlator taps (default: minimum required by tracker node)
--correlator-spacing CORRELATOR_SPACING spacing of correlators (units: samples) (default: value preferred by tracker node)
--correlator-config CONFIG_STR get per-substream --correlators and --correlator-spacing values from config string (run "sdgps help" for examples)
--validate test correlator against reference implementation
--benchmark benchmark correlator
--algorithm ALGORITHM (=fast) use ALGORITHM algorithm (choices: fast, simple)
--acq-effort ACQ_EFFORT (=1) scale acquisition effort. only has an effect if --deterministic is used
--output-samples output GNSSSamplePackets into cooked stream
--max-svs COUNT (=100) don't try to track more than this many SVs per GNSS system

Since we want to make this tutorial accessible to those who do not have hardware we used the sw-correlator rather than the hardware correlator we have implemeneted on our Infix-1. We added the --deterministic to guarantee that our results will be the same as your during this tutorial and run it in a single thread.

You can turn this option off you desire.

The next node is the tracker node.

Usage:

tracker [OPTION]...

Description:

The tracker node contains the GNSS signal tracking loops.

A given signal tracking loop generates code phase and Doppler error signals that get fed back to the correlator, which keeps it centered on the peak of the autocorrelation function of the tracked signal.

Allowed options:

Option Description
--help produce help message
--verbose-align output extra debugging information for bit alignment
--plot plot live correlation waveforms
--plot-all plot live correlation waveforms (including from SVs which are not yet aligned)
--plot-first only plot first correlation waveform (useful for debugging acquisition)
--min-sample-period arg (=0) minimum width between plot points in seconds; plot points closer than this will be averaged
--x-axis-unit arg (=sec) unit of X axis (options: sec, min, hour, day)
--x-axis-absolute plot absolute stream time on X axis instead of relative to now (implied by --wait)
--detrend <no effect>
--wait wait for pipeline to terminate, then plot (default: live plotting)
--live-history arg (=60) duration of live history buffer in seconds
--title-suffix arg append string to plot titles
--disable-side-peak-mitigation disable automatic detection and correction of being locked onto side-peak of BOC correlation function
--cn0-drop-threshold arg (=20) drop signals with C/N_0 below this value (units: dB-Hz)
--cn0-drop-grace-period arg (=3) inhibit dropping signals with low C/N_0 for this long after start of tracking (units: seconds)

It is used to run the signal tracking loops and synchronize to the navbits.

The next node is the decoder node.

Usage:

decoder [OPTION]...

Allowed options:

Option Description
--help produce help message
--verbose output extra debugging information from GNSS bit decoders
--read-knowledge FILENAME read knowledge from FILENAME at start
--write-knowledge FILENAME write knowledge to FILENAME periodically
--max-unconfirmed-time TIME (=300) require new ephemerides to be confirmed (by being received twice and matching) after TIME seconds after startup (valid values: any positive number or inf)
--grandfather-time TIME (=300) allow SVs that had unconfirmed ephemerides before --max-unconfirmed-time to be treated as confirmed for TIME seconds afterwards to avoid discontinuity at --max-unconfirmed-time
--confirmed-ephemeris-timeout TIMEOUT (=300) abort tracking of a signal if no confirmed ephemeris has been received for TIMEOUT seconds (if AbortSignalTracking FunctionalityCallback is not available, observables will be dropped) (set to "inf" to disable)
--global-info-period arg (=5) duration between GNSSGlobalInfo packets (units: seconds)

It decodes the satellites' ephemerides.

The next node is the kf2 node. This is the main node used for producing solutions from observables streams using a Kalman filter.

Usage:

kf2 [OPTION]...

Allowed options:

Option Description
--help produce help message
--output-rate arg output solution packets at this rate (units: Hertz) (default: the highest integer divisor of the IMU sample rate that is <= 100 Hz)
--offline don't boost state to realtime. incurs delay of OFFSET seconds
--print-phase-resets print phase resets
--ionospheric-model arg (=zero) use specified ionospheric delay model (default: assume ionospheric delay to always be zero)
--wait-for-ionospheric-model wait for ionospheric model to be initialized to avoid transient behavior
--tropospheric-model arg (=simple) use specified tropospheric delay model
--estimate-ztd-factor estimate ZTD (zenith tropospheric delay) scale factor
--estimate-ionospheric-delay estimate ionospheric delay; with dual-frequency measurements, convergence is immediate, but with single-frequency measurements, convergence takes >= 1 hour
--estimate-antenna-delays estimate differential delay between antennas
--elevation-mask arg do not use observables from SVs with an elevation below this angle relative to the local horizon (units: degrees)
--antenna-elevation-mask arg do not use observables from SVs with an elevation below this angle relative to the plane defined by the antenna's "axis" vector (units: degrees) (multiantenna example: 'ANT0:20,ANT1:0')
--p-ignore arg (=1e-9) p-value threshold for ignoring an SV due to a large pseudorange residual; set to 0 to never ignore
--ignore-duration arg (=1) if --p-ignore is triggered, ignore all of SV's measurements for this many seconds
--abort-signals-ignored-for arg if an SV's measurements are --p-ignored for this many seconds, abort signal tracking via the AbortSignalTracking FunctionalityCallback
--p-log arg (=1e-6) p-value threshold for logging a message about a large measurement residual; set to 0 to never log
--p-reset arg (=0) p-value threshold for triggering a reset due to large pseudorange residual; set to 0 to never reset
--p-phase-reset arg (=1e-6) p-value threshold for resetting carrier phase tracking for a given SV; set to 0 to never reset
--ignore-doppler minimize use of Doppler observable
--ignore-phase don't use phase observable
--clock-wander-rate arg (=1e-17) diffusion constant for local oscillator frequency random walk (units: (s/s)^2/s)
--phase-wander-rate arg (=0.02) diffusion constant for unmodeled SV phase random walk (units: radian^2/s)
--plot-residuals plot measurement residuals
--min-sample-period arg (=0) minimum width between plot points in seconds; plot points closer than this will be averaged
--x-axis-unit arg (=sec) unit of X axis (options: sec, min, hour, day)
--x-axis-absolute plot absolute stream time on X axis instead of relative to now (implied by --wait)
--detrend <no effect>
--wait wait for pipeline to terminate, then plot (default: live plotting)
--live-history arg (=60) duration of live history buffer in seconds
--title-suffix arg append string to plot titles
--sample-time-stream arg name of Time stream to include in "time_streams" key of solution output; will also match a unique prefix of a name; special value of "*" will select all
--include-sisre-in-covariance arg (=0) add given SISRE contribution to position covariance matrix (units: meters rms)
Note: SISRE (rms) = sqrt((--sv-ephemeris-error value)^2 + (--sv-clock-error value)^2)

The last node is the write-solution-file node, its help page looks like this:

Usage:

write-solution-file [OPTION]... FILENAME

Allowed options:

Option Description
--help produce help message
--block force stream source to wait to avoid buffer overrun (default: immediately abort pipeline unless --continue-on-error is used)
--buffer-size BUFFER_SIZE (=128) buffer BUFFER_SIZE MB of data in RAM for smoothing out disk IO latency
--filename FILENAME write to file named FILENAME
--no-metadata don't include metadata (sdgps version, command line) in output
--stream STREAM continually write to file with at least the last STREAM megabytes saved; maximum disk space used is approximately 3 * STREAM megabytes
--allow-overwrite don't exit if file already exists
--continue-on-error on error condition (e.g. overrun, disk full), stop writing to file, print warning every 5 seconds thereafter, and exit with nonzero exit code on pipeline termination (default: immediately abort pipeline)
--async-startup allow pipeline startup to proceed if open() call or write() of stream config header blocks (e.g. if writing to a pipe that does not yet have a reader)

It's used to write files for later consumption, visit its node page for more examples on how to use its brother nodes.

With that we've used SDGPS to generate a solution file. Now lets look at some of our utility scripts to analyze it.

Let's run this:

sdgps read-solution-file foo.sol --rate inf ! plot-solution --live-history 1e9

which will generate the following image:

Here this will generate three plots showing the position over along each ECEF axis. Since we set the velocity to [1,0,0] we can see that the platform is translating at a fixed rate over time.

Just like that! We generated a trajectory, simulated an observables stream, processed it into a solution, saved that file, and then read that file to look at our results!

The simulation tools are powerful and can be used to perform a variety of tests. Visit the rest of the simulation nodes to see examples on how to use the remaining simulation nodes.

Realtime Tutorial


For this part you will need:

Optional:

  • This raw stream from our site in Texas can temporarily serve as a substitute for any part of the Infix-1 / antenna assembly.

If you use the raw stream, anywhere you see:

sylphase-usbgpsimu2

in the tutorial should be replaced with:

read-raw-file foo.raw ! sylphase-usbgpsimu2-offline

if you only have an Infix-1 or

read-raw-file foo.raw ! sw-correlator

(if you have zero hardware available to you)

as you go through the tutorial.

Remember, an Infix-1 and antenna can be substituted with the provided raw file for the purpose of this tutorial, if either item has not arrived yet, you can still start learning the ropes for SDGPS!

sdgps sylphase-usbgpsimu2 --antenna-position '[1,2,3]' ! trim-stream 0 120 ! tracker ! decoder ! kf2 ! write-solution-file foo2.sol

One thing to remember is that kf2 requires motion to initailize properly, reference synthesize-sensor-measurements if you don't feel like rotating your Infix-1 during the recording.

or if you are using the raw file we provided, add synthesize-sensor-measurements to the node chain like so:

sdgps read-raw-file support_files/nov-17-2019.raw --rate inf ! sw-correlator ! tracker ! decoder ! synthesize-sensor-measurements --position-ecef '[-521836,-5521414,3139401]' --gnss-time 1257984000 ! kf2 ! write-solution-file foo2.sol

Here we have only four nodes running this time.

The first is: sylphase-usbgpsimu2:

Usage:

sylphase-usbgpsimu2 [OPTION]...

Allowed options:

Option Description
--help produce help message
--device-id arg use device with this device ID (default: any ID)
--antenna-position arg (=[0,0,0]) antenna position as a 3-length JSON array (example: [0.5,2,3])
--antenna-axis arg (=[0,0,1]) antenna axis as a 3-length JSON array (example: [0,0,1])
--use-ant1 use antenna connected to ANT1 instead of ANT0
--use-r0 use receiver0 instead of receiver1
--list-devices list devices present then exit
--require-device-immediately require device to be captured immediately or exit
--use-pll FREQUENCY lock internal VCTCXO to timing signal connected to GPIO port using PLL; FREQUENCY should be the frequency in Hz of the timing signal
--gpio-stamp-falling stamp falling edges of GPIO input (default: stamp rising edges)
--gpio-stamp-decimation N (=1) only stamp every Nth rising edge (i.e. 0th, Nth, 2*Nth, ...)
--output-samples output GNSSSamplePackets into cooked stream
--max-svs arg (=15) limit number of satellites being tracked e.g. to decrease CPU usage

There are a number of parameters we could be using, but we'll keep it simple and only specify the antenna position relative to our Infix-1. In addition, we've chained a trim-stream node that stops the pipeline after a certain number of seconds have elapsed.

The next nodes are the tracker, decoder, kf2, and write-solution-file nodes which were already explained in the simulation portion of the tutorial.

With that we have a file captured from actual satellites!

Let's run it and see what ours looks like! Your plot may look a little different depending on what you do during the recording, our is generated using an static Infix-1 that was run for 120 seconds

sdgps read-solution-file foo2.sol --rate inf ! plot-solution --live-history 1e9