Skip to content

coverclock/com-diag-hazer

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

com-diag-hazer

Parse NMEA strings and other typical output from GNSS devices.

Copyright

Copyright 2017-2023 by the Digital Aggregates Corporation, Colorado, USA.

Except where noted, this software is an original work of its author.

License

Licensed under the terms in LICENSE.txt.

Contact

Chip Overclock
Digital Aggregates Corporation
3440 Youngfield Street, Suite 209
Wheat Ridge CO 80033 USA
http://www.diag.com
mailto:coverclock@diag.com

Disclaimer

I am a software developer. I have been working full time the field since 1976. I have an M.S. (1983) and a B.S. (1980) in computer science from an accredited program at a university. What I am not is a hardware or radio engineer, nor am I an expert in global navigation satellite systems. Behind all the software work I present here is a vast collection of hardware, firmware, and radio frequency expertise contributed by the developers of the GNSS products I use.

If you're wondering why I don't use the excellent open source GPS Daemon (gpsd) and its GPS Monitor (gpsmon), the answer is: I have, in many projects, typically in conjunction with the open source NTPsec Daemon (ntpd). Hazer was developed as an excuse for me to learn in detail more about how GPS works and how NMEA and UBX sentences are formatted (because I only learn by doing), and also to develop an NMEA and UBX parsing library that I can incorporate into the kinds of embedded systems I am frequently called to work upon. Hazer and gpstool have also turned out to be really useful tools for testing and evaluating GPS devices.

Abstract

This file is part of the Digital Aggregates Corporation Hazer project. Hazer is an open source toolkit for interpreting data streams typically generated by GPS and other GNSS receivers and emitted from serial(ish) ports, including USB and Bluetooth. While Hazer is the name of the repository, it incorporates features in support of several different related projects described below:

  • Hazer (NMEA support),
  • Yodel (UBX support including for IMU),
  • Tumbleweed (RTCM support),
  • Wheatstone (LTE-M support),
  • Tesoro (OSM support),
  • Metronome (precision time and frequency support), and
  • Stagecoach (OpenSSL tunnelling).

The Hazer repo includes parsers for three different input formats - NMEA, UBX, and RTCM - and interprets many of the data records represented in those formats into C structures. For purposes of commenting in my C code, I find it useful to refer to NMEA records as "sentences" (terminology consistent with the NMEA standard), UBX records as "packets", and RTCM records as "messages".

NMEA sentences are printable ASCII messages that conform to the National Marine Electronics Association (NMEA) 0183 4.10 specification. NMEA 0183 describes the output produced by most receiving devices of Global Navigation Satellite Systems (GNSS), of which the U.S. Global Positioning System (GPS), formerly known as Navstar, is an example. The NMEA software stack is named Hazer (same as the Git repository).

UBX packets are in a proprietary binary data format generated by devices made by U-Blox, a Swiss designer and manufacturer of GNSS receivers. UBX packets may include not only data generated by the GNSS receiver, but also data generated by an Inertial Measurement Unit (IMU), part of a Inertial Navigation System (INS). UBX is supported by a parallel stack called Yodel.

RTCM messages are in a binary data format used in Differential GNSS (DGNSS) that makes use of Real-Time Kinematics (RTK). This allows communicating GNSS receivers to compare notes and potentially, over time, achieve very high degrees of precision down to centimeters. RTCM was developed by the Radio Technical Commision for Maritime services (RTCM). RTCM is supported by a parallel stack called Tumbleweed.

More broadly: Hazer uses GNSS to do geolocation for applications like moving map displays; Yodel uses GNSS with high precision geolocation and integrated inertial measurement features of specific u-blox devices; and Tumbleweed uses Differental GNSS with specific u-blox devices. All three projects reside in the Hazer repository.

When I use the term "Hazer", I am not very good about distinguishing whether I am talking about the software stack, the project, or the entire repo.

Hazer includes a gpstool application as a kind of Swiss Army knife for dealing with various GNSS devices. gpstool accepts data streams from standard input, from serial-ish devices including serial USB, from files or anything that looks like a file e.g. a FIFO (a.k.a. a named pipe), or from a UDP socket, and can send validated data to a remote UDP socket, write it to a device, and display the interpreted information.

Hazer also includes an rtktool application that is a point-to-multipoint GNSS router that can receive data via a UDP socket from a remote gpstool and forward it to one or more remote gpstools via UDP. This is used along with gpstool to implement a DGNSS system using a stationary base station in survey mode to provide real-time corrections to one or more mobile rovers. This project, called Tumbleweed (same as the RTCM software stack), does not use the Networked Transport of RTCM via Internet Protocol (Ntrip), but instead uses its own trivial data format consisting of raw RTCM messages preceeded by a four-byte sequence number carried over UDP datagrams.

Manual Pages and Reference Manual

These PDFs of manual pages and associated reference manual were built from Hazer's embedded Doxygen comments on 2022-03-01 using tag 50.4.3 .

The unit tests (Hazer/tst), functional tests (Hazer/fun), and command line uilities (Hazer/bin) contain useful and non-trivial examples of how to use the Hazer library.

Dependencies

Diminuto

The Hazer library and its utilities depend on my Diminuto library. Diminuto is a general purpose C-based systems programming library that supports serial port configuration, socket-based communication, and a passle of other useful stuff. gpstool and rtktool are excellent examples of how to leverage Diminuto to get a lot done in not so much C code. I use Diminuto in virtually all of my C-based projects, and sometimes in other languages too that support C-linkage. Portions of Diminuto have also shipped in products from several of my clients. (Details of building Diminuto are shown below.)

Tool Chain

These days most Linux distributions do not include the basic tools to build C and C++ software (despite having themselves been developed using them).

sudo apt-get install gcc
sudo apt-get install g++
sudo apt-get install make

Documentation

If you want to make documentation, doxygen and related tools will need to be installed.

sudo apt-get install doxygen
sudo apt-get install texlive-base
sudo apt-get install texlive-fonts-recommended
sudo apt-get install texlive-fonts-extra
sudo apt-get install texlive-science

Utilities

Some of the Hazer scripts use command line utilities that not all Linux/GNU distros install by default.

sudo apt-get install bc
sudo apt-get install inotify-tools
sudo apt-get install socat
sudo apt-get install expect

Workflow

For my own development workflow, I have also found it useful to install other packages that are often optional in various Linux/GNU distros. Your mileage may vary.

sudo apt-get install openssh-server
sudo apt-get install git
sudo apt-get install vim
sudo apt-get install screen

LFS

The dat directory is where I collect data from tests of Hazer (moving map), Tumblweeed (differential GNSS), and Yodel (integrated intertial measurement). Some of the comma separated value (CSV) files are too large (over a hundred megabytes uncompressed) to be pushed to GitHub in the normal way. These files use GitHub's Large File Storage (LFS).

sudo apt-get install git-lfs

Unless you install GitHub's LFS feature (which manifests as the "git lfs" command), files stored in LFS will appear to have contents that look something like this.

version https://git-lfs.github.com/spec/v1
oid sha256:bcb222ac76e51cad8010086754d4cadeeebd0161b51029d6870a0d806db5f42f
size 137136500

You have to initialize LFS once per machine for every repo it is used in.

git lfs install

You can also safely skip installing LFS, and ignore the large data files, to use this repo.

Secure Socket Layer

The optional (work in progress) scripts that provide an authenticated and encrypted tunnel through which datagrams can be forwarded require OpenSSL.

 sudo apt-get install openssl libssl-dev libssl-doc

geodesic

The geodesic application is based on algorithms described in

Charles F. F. Karney, "Algorithms for geodesics", Journal for Geodesy, 2013-01, 87.1, pp. 43..55

and uses one .c file and one .h file, included in this repository, that were written by Mr. Karney. The original source files can be found at

https://geographiclib.sourceforge.io

and are licensed under the MIT license.

locale

The gpstool, rtktool, and mapstool programs depend on running in a POSIX locale that allows the use of Unicode characters like the degree symbol. Locales like "POSIX" and "C" don't support this, at least not on the systems I have. Locales like "en_US.UTF-8" work okay. Your mileage may vary.

dialout

GNSS modules typically express a serial port - either an actual serial port, a USB serial port emulation ('''ttyUSB'''), or a modem emulation ('''ttyACM'''). The easiest way to get read/write access to such a port as a non-root user is by adding that user to the '''dialout''' group. The user may have to log out and back in again to have this take effect.

sudo adduser pi dialout

Reverse Dependencies

Tesoro

The Tesoro project integrates Hazer with an OpenStreetMaps (OSM) tile server to create a moving map display. Tesoro steers the display by taking location updates, in the form of datagrams containing JSON over UDP, either in real-time or from playback, from Hazer using scripts like csvfollow and csvplayback.

Branching

Hazer is big and complex enough that I sometimes move to a "master" and "develop" dual branch model of development. I make and test major changes in the "develop" branch, and when I think I have a stable release, I merge "develop" into the "master" branch. I still make what I consider to be minor changes in the master branch.

Versioning

I tag major releases with a three-number tuple that is defined in the build Makefile for each project. Release numbers, e.g. 22.2.1, consist of a major number (22), a minor number (2), and a build number (1). The major number changes when I've made a change significant enough that I think applications using the library will likely need to be changed, even though they may compile. The minor number changes when I've added new features or functionality, but existing features and functionality haven't changed. The build number changes when I've fixed a bug so that existing features or functionality works as described (even though this may break workarounds in applications).

The major and minor numbers are incorporated into the name of the shared object (dynamic link library) produced by the build.

The vintage is the date and time of the most recent build in UTC and expressed in ISO8601 format.

The revision is the Git commit number.

The release, revision, vintage, and a bunch of other stuff, are embedded as modules in the Hazer and Diminuto libraries. Those modules can be linked into an application. Each project has a binary executable named vintage that displays this information.

The gpstool and rtktool applications can be run with a -V flag to display the release, vintage, and revision of the Hazer library with which they were built.

Repositories

https://github.com/coverclock/com-diag-hazer

https://github.com/coverclock/com-diag-diminuto

https://github.com/coverclock/com-diag-tesoro

Sentences

Hazer processes the following standard NMEA sentences.

  • GGA - Global Positioning System Fix Data. (NMEA 0183 Version 4.10 p. 68)
  • GLL - Geographic Position - Latitude/Longitude. (NMEA 0183 Version 4.10 p. 87)
  • GSA - GNSS DOP and Active Satellites. (NMEA 0183 Version 4.10 p. 92)
  • GSV - GNSS Satellites In View. (NMEA 0183 Version 4.10 p. 96)
  • RMC - Recommended Minimum Specific GNSS Data. (NMEA 0183 Version 4.10 p. 113)
  • TXT - Text Transmission. (NMEA 0183 Version 4.10 p. 124)
  • VTG - Course Over Ground & Ground Speed. (NMEA 0183 Version 4.10 p. 127)

Hazer processes the following proprietary NMEA sentences.

  • PUBX,00 - emitted by u-blox devices for POSITION. (u-blox 8 31.3 pp. 163-167)
  • PUBX,03 - emitted by u-blox devices for SVSTATUS. (u-blox 8 31.3 pp. 163-167)
  • PUBX,04 - emitted by u-blox devices for TIME. (u-blox 8 31.3 pp. 163-167)

Hazer recognizes the following proprietary NMEA sentences.

  • PMTK - emitted and/or accepted by some GTop/MTK devices.
  • PSRF - emitted and/or accepted by some SiRF devices.
  • PUBX - emitted and/or accepted by some u-blox devices.

Yodel recognizes the following received UBX messages.

  • UBX-ACK-ACK - Acknowledge UBX input and indicate success. (u-blox 9 p. 38)
  • UBX-ACK-NAK - Acknowledge UBX input and indicate failure. (u-blox 9 p. 38)
  • UBX-CFG-VALGET - Get Configuration Value. (u-blox 9 p. 85)
  • UBX-MON-COMMS - Monitor utilization of communication ports. (u-blox 9 p. 131)
  • UBX-MON-HW - Monitor Hardware to detect jamming. (u-blox 8 R15 p. 285)
  • UBX-MON-VER - Monitor hardware and software Version. (u-blox 9 p. 139)
  • UBX-NAV-ATT - Report IMU attitude relative to geodetic. (u-blox 8, p. 317)
  • UBX-NAV-HPPOSLLH - Report high precision lat/lon and height. (u-blox 9 p. 145)
  • UBX-NAV-ODO - Report internal odometer. (u-blox 8 p. 327)
  • UBX-NAV-PVT - Report Position, Velocity, Time solution. (u-blox 8 p. 332)
  • UBX-NAV-STATUS - Report Status to detect spoofing. (u-blox 8 R15 p. 316)
  • UBX-NAV-SVIN - Report Survey-in status on DGNSS Base. (u-blox 9 p. 163)
  • UBX-RXM-RTCM - RXM RTCM input status on DGNSS Rover. (u-blox 9 p. 181)

Tumbleweed recognizes RTCM messages with a valid CRC but does not process their contents. As a special case, an RTCM message with a zero payload length is used by gpstool and rtktool as a keep alive message.

Talkers

Hazer recognizes the following talkers as belonging to the corresponding constellations and systems.

These talkers have been observed in the wild coming from actual GPS receivers.

  • GA - Galileo (as in Galileo Galilei) - EU
  • GB - BeiDou (as in The Big Dipper) a.k.a. COMPASS - China
  • GL - Globalnaya Navigazionnaya Sputnikovaya Sistema (GLONASS) - Russia
  • GN - Global Navigation Satellite System (GNSS) - Generic
  • GP - Global Positioning System (GPS) a.k.a. Navstar GPS - USA

Support for these talkers has been unit tested but the talkers have never been observed in the wild.

  • BD - BeiDou (as in The Big Dipper) - China
  • GQ - Quasi-Zenith Satellite System (QZSS) - Japan
  • QZ - Quasi-Zenith Satellite System (QZSS) - Japan

Identifiers

Receivers that implement the GSA System ID field introduced in NMEA 4.10 may reuse satellite identifiers. For example, I see GPS and Galileo both using identifier 9 on the U-Blox 9 receiver. Despite NMEA and vendor documentation to the contrary, I do not find the satellite identifer convention reliable and only use it as a last resort on older receivers that do not implement the System ID field to identify the constellation. Hazer recognizes the following satellite identifiers in the GSA and GSV messages.

These satellite identifiers have been observed in the wild coming from actual GPS receivers.

  • GPS - 1..32
  • SBAS - 33..64
  • GLONASS - 65..96

Support for these satellite identifiers has been unit tested but has never been exercised using actual GPS receivers.

  • IMES - 173..182
  • QZSS - 193..197
  • BeiDou - 201..235
  • Galileo - 301..336
  • BeiDou 2 - 401..437

Devices

I have successfully tested Hazer with the following GPS chipsets.

  • MediaTek MTK3339
  • Quectel L80-R
  • SiRF Star II
  • SiRF Star III
  • SiRF Star IV
  • U-Blox 6
  • U-Blox 7
  • U-Blox 8
  • U-Blox 9

I have successfully tested Hazer with the following serial-to-USB chipsets.

  • Cygnal Integrated Products
  • FTDI
  • Prolific
  • Silicon Labs CP2104
  • U-Blox (apparently integrated into the GPS chip itself)

I have successfully tested Hazer with the following GPS devices.

  • Adafruit Ultimate GPS (GTop PA6H/MediaTek MTK3339+CP2104, 9600 8N1, v10c4pea60, ttyUSB, 1Hz) 1
  • Ardusimple SimpleRTK2B (U-Blox 9/UBX-ZED-F9P, 230400 8N1, v1516p01a9, ttyACM, 1Hz) 2 3
  • Bad Elf GPS Pro + (STMicroelectronics/MediaTek MTK, 9600 8n1, v0483p5740, ttyACM, 1Hz) 4 5
  • Digi XBIB-C-GPS (U-blox 8/UBX-CAM-M8Q, 9600 8N1, N/A, ttyS, 1Hz) 4
  • Eleduino Gmouse (U-Blox 7, 9600 8N1, v1546p01A7, ttyACM, 1Hz) 6
  • Ettus Research (National Instruments) USRP B210, GNURadio 3.7.11, GNSS-SDR 0.0.10 7
  • Garmin GLO (?MTK?, Bluetooth, N/A, rfcomm, 10Hz) 8 9
  • Garmin GLO 2 (?MTK?, Bluetooth, N/A, rfcomm, 10Hz) 8 9 10
  • Generic Gmouse (U-Blox 7, 9600 8N1, v1546p01A7, ttyACM, 1Hz) 6
  • GlobalSat BU-353S4-5Hz (SiRF Star IV+Prolific, 115200 8N1, v067Bp2303, ttyUSB, 5Hz)
  • GlobalSat BU-353S4 (SiRF Star IV+Prolific, 4800 8N1, v067Bp2303, ttyUSB, 1Hz) 11
  • GlobalSat BU-353W10 (U-Blox 8/UBX-M8030, 9600 8N1, v1546p01a8, ttyACM, 1Hz) 11 6 4 2 12
  • GlobalSat ND-105C (SiRF Star III+Prolific, 4800 8N1, v067Bp2303, ttyUSB, 1Hz)
  • Jackson Labs Technologies CSAC GPSDO (U-Blox 6/UBX-LEA-6T, 115200 8n1, N/A, ttyS, 1Hz)
  • Lynq Technologies Smart Compass (U-Blox 8/UBX-CAM-M8Q, 115200 8n1, v1fc9p0194, ttyACM, 1Hz)
  • MakerFocus USB-Port-GPS (Quectel L80-R+Cygnal, 9600 8N1, v10C4pEA60, ttyUSB, 1Hz) 6 13
  • NaviSys GR-701W (U-Blox 7+Prolific, 9600 8N1, v067Bp2303, ttyUSB, 1Hz) 14 15 2
  • Pharos GPS-360 (SiRF Star II+Prolific, 4800 8N1, v067BpAAA0, ttyUSB, 1Hz) 16
  • Pharos GPS-500 (SiRF Star III+Prolific, 4800 8N1, v067BpAAA0, ttyUSB, 1Hz) 16
  • RaceDayQuads RDQ Micro M8N (U-Blox 8/UBX-NEO-M8N, 9600 8n1, N/A, ttyS, 1Hz) 4 2 17
  • Sourcingbay GM1-86 (U-Blox 7, 9600 8n1, p1546v01A7, ttyACM, 1Hz) 6
  • SparkFun GPS-RTK2 (U-Blox 9/UBX-ZED-F9P, 230400 8N1, v1516p01a9, ttyACM, 1Hz) 2 3
  • SparkFun NEO-M8N (U-Blox 8/UBX-NEO-M8N, 115200 8N1, v1546p01a9, ttyACM, 1Hz) 13 2 3
  • SparkFun NEO-M8U (U-Blox 8/UBX-NEO-M8U, 115200 8N1, v1546p01a8, ttyACM, 1Hz) 4 2 18
  • SparkFun SAM-M8Q (U-Blox 8/UBX-SAM-M8Q, 9600 8n1, N/A, ttyS, 1Hz) 4 13 2 17
  • SparkFun SARA-R5 (U-Blox 8/M8030/UBX-R5, autobaud, v1a86p7523, ttyUSB, 1Hz) 19 20 21
  • SparkFun ZED-F9R (U-Blox 9/UBX-ZED-F9R, 230400 8N1, v1516p01a9, ttyACM, 1Hz) 2 3 18
  • SparkFun ZED-F9T (U-Blox 9/UBX-ZED-F9T, 38400 8N1, v1516p01a9, ttyACM, 1Hz) 2 3 22
  • Stratux Vk-162 Gmouse (U-Blox 7, 9600 8N1, v1546p01A7, ttyACM, 1Hz) 6
  • TOPGNSS GN-803G (U-Blox 8/UBX-M8030-KT, 9600 8N1, v1546p01a8, ttyACM, 1Hz) 6 4 2
  • Uputronics Raspberry Pi GPS Expansion Board v4.1 (U-Blox 8/M8, 9600 8N1, N/A, ttyS, 1Hz) 4

Notes

GlobalSat is also known as GlobalSat Technology, USGlobalSat, US GlobalSat Technology, or GlobalSat Worldcom, but is apparently not the same as the Globalsat mobile satellite service provider.

GlobalTop Technology is also known as GTop, and is part of Sierra Wireless.

SiRF is part of Qualcom.

Platforms

I have tested Hazer and run gpstool on the following platforms, in no particular order. This list is not exhaustive, and just serves as an example of the wide variety of possible computers one may use. Your mileage may vary. Hazer and gpstool are not resource intensive; I routinely run gpstool on an old 32-bit Intel i686 netbook, and run four instances of gpstool simultaneously on a single Raspberry Pi 4B.

Dell OptiPlex 7040
Intel Core i7-6700T x86_64 @ 2.8GHz x 4 x 2
Ubuntu 16.04.2 "Xenial"
Linux 4.4.0
GNU 5.4.0

Intel NUC5i7RYH
Intel Core i7-5557U x86_64 @ 3.10GHz x 2 x 2
Ubuntu 20.04.3 "Focal"
Linux 5.4.0
GNU 9.3.0

Intel NUC7i7BNH
Intel Core i7-7567U x86_64 @ 3.50GHz x 2 x 2
Ubuntu 20.04.3 "Focal""
Linux 5.11.0
GNU 9.3.0

Raspberry Pi 3 Model B+
Broadcom BCM2837B0 Cortex-A53 ARMv7 @ 1.4GHz x 4
Raspbian 9.13 "Stretch"
Linux 4.19.66
GNU 6.3.0

Raspberry Pi 3 Model B+ with a touch-sensitive LCD display
Broadcom BCM2837B0 Cortex-A53 ARMv7 @ 1.4GHz x 4
Raspbian 9.4 "Stretch"
Linux 4.14.30
GNU 6.3.0

Raspberry Pi 4 Model B
Broadcom BCM2711 Cortex-A72 ARMv8 @ 1.5GHz x 4
Raspbian 10 "Buster"
Linux 5.10.17
GNU 8.3.0

VMware Workstation 15 Pro under Windows 10
Intel Core i7-3520M x86_64 @ 2.90GHz x 2
Ubuntu 19.10 "Eoan"
Linux 5.3.0
GNU 9.2.1

HP Mini 110-1100
Intel Atom N270 i686 @ 1.6GHz x 2
Mint 19.3 "Tricia"
Linux 5.0.0
GNU 7.5.0

GPD Micro PC
Intel Celeron N4100 x86_64 @ 1.10GHz x 2 x 2
Ubuntu MATE 19.10 "Eoan"
Linux 5.3.0
GNU 9.2.1

Pi-Top 3 (Raspberry Pi 3 Model B+)
Broadcom BCM2837B0 Cortex-A53 ARMv7 @ 1.4GHz x 4
pi-topOS "Polaris" (Raspbian 9.9 "Stretch")
Linux 4.19.66
GNU 6.3.0

Pi-Top 4 (Raspberry Pi 4 Model B)
Broadcom BCM2711 Cortex-A72 ARMv8 @ 1.5GHz x 4
pi-topOS "Sirius" (Raspbian 10 "Buster")
Linux 5.4.79
GNU 8.3.0

StarFive VisionFive (RISC-V SBC) riscv64 @ 1GHz x 2
Fedora 33 (Rawhide)
Linux 5.15.10
GNU 10.3.1

Diagnostics

Errors

Error messages may be logged by gpstool with the following error numbers (errno) for malformed input data. (Errors reported by system calls and library functions may also cause error messages not related to the input data to be logged.)

  • EINVAL - invalid character in a field e.g. alpha in a numeric field.
  • EIO - error in the end matter e.g. checksum or cyclic redundancy check (CRC).
  • ENODATA - below minimum length or number of fields.
  • ENOMSG - error in the start matter e.g. no discernable identifiers.
  • ERANGE - time, latitude, longitude, etc. value out of range.

Each Hazer library function that parses NMEA sentences (hazer), UBX packets (yodel), or RTCM messages (tumbleweed) returns a value >= 0 if the data were valid and any PNT structures passed to the function were updated. If the function returns a value < 0, the data were rejected, and errno is set to a value. If errno > 0, then the data were invalid and the error number, as indicated in the list above, suggests the reason why. If errno == 0, then the data were valid but indicated that the GNSS device did not have a valid solution, so the PNT structures were not updated.

Synchronization

The following log messages regarding input stream synchronization may be reported by gpstool.

  • Sync Start - one of the state machines has signaled that a valid NMEA, UBX, or RTCM frame has been read with expected beginning and ending matter, including a correct checksum or CRC. The input stream is synchronized where it had not been before.
  • Sync Stop - all three state machines have entered their stop states. This indicates that all have given up trying to synchronize to the input stream. All three state machines will be restarted.
  • Sync Lost - the input stream had been synchronized, but at the beginning of the next frame, none of the expected beginning matter for a NMEA, UBX, or RTCM frame was recognized. All three state machines will be restarted.

Articles

Chip Overclock, "Better Never Than Late", 2017-02, http://coverclock.blogspot.com/2017/02/better-never-than-late.html

Chip Overclock, "Time and Space", 2017-09, https://coverclock.blogspot.com/2017/09/time-space.html

Chip Overclock, "A Menagerie of GPS Devices", 2018-04, https://coverclock.blogspot.com/2018/04/a-menagerie-of-gps-devices-with-usb.html

Chip Overclock, "Practical Geolocation", 2018-08, https://coverclock.blogspot.com/2018/08/practical-geolocation.html

Chip Overclock, "Practical Geolocation II", 2018-08, https://coverclock.blogspot.com/2018/08/practical-geolocation-ii.html

Chip Overclock, "We Have Met the Enemy and He Is Us", 2018-09, https://coverclock.blogspot.com/2018/09/we-have-met-enemy-and-he-is-us.html

Chip Overclock, "GPS Satellite PRN 4", 2018-11, https://coverclock.blogspot.com/2018/11/gps-satellite-prn-4.html

Chip Overclock, "This Is What You Have To Deal With", 2019-06, https://coverclock.blogspot.com/2019/06/this-is-what-you-have-to-deal-with.html

Chip Overclock, "Geolocation While Airborne", 2019-09, https://coverclock.blogspot.com/2019/09/geotagging-while-airborne.html

Chip Overclock, "When Learning By Doing Goes To Eleven", 2020-03, https://coverclock.blogspot.com/2020/03/when-learning-by-doing-goes-to-eleven.html

Chip Overclock, "Improvisational Engineering", 2020-04, https://coverclock.blogspot.com/2020/04/improvisational-engineering.html

Chip Overclock, "Keyhole", 2020-05, https://coverclock.blogspot.com/2020/05/keyhole.html

Chip Overclock, "Pseudorange Multilateration", 2020-05, https://coverclock.blogspot.com/2020/05/pseudorange-multilateration.html

Chip Overclock, "Dilution of Precision", 2020-05, https://coverclock.blogspot.com/2020/05/dilution-of-precision.html

Chip Overclock, "Practical Differential Geolocation", 2020-05, https://coverclock.blogspot.com/2020/05/practical-differential-geolocation.html

Chip Overclock, "Frames of Reference IV", 2020-05, https://coverclock.blogspot.com/2020/05/frames-of-reference-iv.html

Chip Overclock, "Negative Results Are Still Results", 2020-05, https://coverclock.blogspot.com/2020/05/negative-results-are-still-results.html

Chip Overclock, "Location, Location, Location", 2020-06, https://coverclock.blogspot.com/2020/06/location-location-location.html

Chip Overclock, "Headless", 2020-06, https://coverclock.blogspot.com/2020/06/headless.html>

Chip Overclock, "Dead Reckoning", 2020-09, https://coverclock.blogspot.com/2020/09/dead-reckoning.html

Chip Overclock, "A Moving Map Display Using OpenStreetMap", 2021-02, https://coverclock.blogspot.com/2021/02/a-moving-map-display-using.html

Chip Overclock, "The OpenStreetMap Moving Map In Real-Time", 2021-02, https://coverclock.blogspot.com/2021/02/the-openstreetmap-moving-map-in-real.html

Chip Overclock, "The OpenStreetMap Moving Map On Mobile Devices", 2021-03, https://coverclock.blogspot.com/2021/03/the-openstreetmap-moving-map-on-mobile.html

Chip Overclock, "A Static Route Map Display Using OpenStreetMap", 2021-03, https://coverclock.blogspot.com/2021/03/a-static-route-map-display-using.html

Chip Overclock, "Advanced Static Route Maps With OpenStreetMap", 2021-03, https://coverclock.blogspot.com/2021/03/advanced-static-route-maps-with.html

Chip Overclock, "Where the RF Meets the Road", 2021-03, https://coverclock.blogspot.com/2021/03/where-rf-meets-road.html

Chip Overclock, "Solar Power", 2022-03, https://coverclock.blogspot.com/2022/03/solar-power.html

Chip Overclock, "It's About Time", 2022-08, https://coverclock.blogspot.com/2022/08/its-about-time.html

Media

John Sloan, "BU-353W10 Tear Down", album, https://flic.kr/s/aHsmWxTpfs

John Sloan, "Dead Reckoning", album, https://flic.kr/s/aHsmPsGqjA

John Sloan, "Decimal Degrees", album, https://flic.kr/s/aHsmV3GnBe

John Sloan, "GN803G and Hazer 8.0.0", video, https://youtu.be/ZXT_37PvmhE

John Sloan, "GPS Receiver Gallery", album, https://flic.kr/s/aHsmvoXqSH

John Sloan, "Hazer", album, https://flic.kr/s/aHskRMLrx7

John Sloan, "Hazer Test 2017-02-15 15:45 UTC", video, https://youtu.be/UluGfpqpiQw

John Sloan, "NGS AA7126", album, https://flic.kr/s/aHsmEnM8We

John Sloan, "NGS KK1446", album, https://flic.kr/s/aHsmFKdcgF

John Sloan, "NGS KK1770", album, https://flic.kr/s/aHskTG9K1h

John Sloan, "NTP Clock Gallery, album, https://flic.kr/s/aHsmgrizkL

John Sloan, "Tesoro", album, https://flic.kr/s/aHsmTB3tme

John Sloan, "Time and Space", album, https://flic.kr/s/aHsm3ghwxP

John Sloan, "Time and Space", video, https://youtu.be/szoT23ZBcVU

John Sloan, "Tumbleweed", album, https://flic.kr/s/aHsmcdEgq6

John Sloan, "Screen Recording 2021 02 18 at 8 55 20 AM", video, https://youtu.be/GjR7fPQRCZc

John Sloan, "Screen Recording 2021 02 24 at 10 06 20 AM", video, https://youtu.be/-6p3w1SxW1A

John Sloan, "Wheatstone", album, https://flic.kr/s/aHsmVu1wkK

John Sloan, "Yodel", album, https://flic.kr/s/aHsmNDPmDN

References

David Burggraf ed., "OGC KML 2.3", Open Geospatial Consortium, 2015-08-04

Paul E. Ceruzzi, GPS, MIT Press, 2018

David Doyle, "NAD-83 vs WGS-84", NGS, 2000-05-10

David Doyle and Ed McKay, "NGS SURVEY MARKER ACCURACY", NGS, 2000-05-04

M. Dunn at al., "Navstar GPS Space Segment/Navigation User Interfaces", IS-GPS-200H, Global Positioning Systems Directorate / Systems Engineering & Integration, 2013-09-24

Dane E. Ericksen, "NAD 83: What Is It And Why You Should Care", 1994 SBE National Convention and World Media Expo, 1994

Amy Fox, "Precision Matters: The Critical Importance of Decimal Places", blis.com, 2017-07-09

Geocaching.com, "Benchmark Hunting", 2019-09-16

Mohinder S. Gerwal et al., Global Navigation Satellite Systems, Inertial Navigation, and Integration, Wiley, 2013

GIS Geography, "Geodetic Datums: NAD 27, NAD 83 and WGS 84", 2019-03-04

GPS NAVSTAR, "Global Positioning System Standard Positioning Service Signal Specification", 2nd Edition, 1995-06-02

John G. Grimes et al., Global Position System Standard Positioning Service Performance Standard, 4th edition, 2008-09

Grosse-Kunstleve RW, Terwilliger TC, Sauter NK, Adams PD, "Automatic Fortran to C++ conversion with FABLE", Source Code for Biology and Medicine 2012, 7:5

GTop, "PMTK command packet", Revision A11, GlobalTop, 2012

Tony Haddrell, Marino Phocas, Nico Ricquier, "Mobile Phone GPS Antennas - Can They Be Better?", GPS World, 2010-02

IGS et al., "RINEX - The Receiver Independent Exchange Format", Version 3.03, RTCM-SC104, 2015-07-14

ISO, "Standard representation of geographic point location by coordinates", Second edition, ISO 6709:2008(E), 2008-07-15

ISO, "Data elements and interchange formats - Information interchange - Representation of dates and times", First edition, ISO8601:1988(E), 1988-06-15

Elliott D. Kaplan ed., Understanding GPS principles and Applications, Artech House, 1996

Charles F. F. Karney, "Algorithms for geodesics", Journal for Geodesy, 2013-01, 87.1, pp. 43..55

G. Klyne, C. Newman, "Date and Time on the Internet: Timestamps", RFC3339, IETF, July 2002

H. Lyons, "Atomic Clocks", Scientific American, 1957-02

Richard Mason et al., Analyzing a More Resilient National Positioning, Navigation, and Timing Capability, Homeland Security Operational Analysis Center, RAND Corporation, 2021

Greg Milner, Pinpoint: How GPS is Changing Technology, Culture, and Our Minds, W. W. Norton, 2017-05-16

NMEA 0183, "Standard for Interfacing Marine Electronic Devices", Version 4.10, National Marine Electronics Association, 2012

NovAtel, "An Introduction to GNSS", 2nd ed., NovAtel Inc., 2015

RTCM 10403.3, "Differential GNSS (Global Navigation Satellite Systems) Services - Version 3", 141-2016-SC104-STD, 2016-10-07

RTCM 10410.1, "Networked Transport of RTCM via Internet Protocol (NTRIP) - Version 2.0", 111-2009-SC104-STD + 139-2011-SC104-STD, 2011-06-28

SAE 6857, "Requirements for a Terrestrial Based Positioning, Navigation, and Timing (PNT) System to Improve Nagivation Solutions and Ensure Critical Infrastructure Security", SAE6857, 2018-04

u-blox 7, "Receiver Description Including Protocol Specification V14", GPS.G7-SW-12001-B, ublox, 65525, 2013-02-01

u-blox 8, "Receiver Description Including Protocol Specification", v15-20.30.22-23.01, UBX-13003221-R15, ublox, 26415b7, 2018-03-06

u-blox 9, "ZED-F9P Interface Description", UBX-18010854-R05, ublox, 6cc4473, 2018-12-20

u-blox 9, "ZED-F9P Integration Manual", UBX-18010802-R03, ublox, 2018-12-20

u-blox 9, "ZED-F9T series Product Summary", UBX-18011626-R06, ublox, 2022

u-blox 9, "ZED-F9T Data Sheet", UBX-18053713-R07, 2022-01-04

u-blox 9, "u-blox ZED-F9T Interface Description", UBX-18053584-R02, ublox, 2019-06-13

u-blox 9, "ZED-F9T Integration Manual", UBX-19005590-R05, 2020-11-18

Tools

https://www.notams.faa.gov/dinsQueryWeb/

https://pilotweb.nas.faa.gov/PilotWeb/noticesAction.do?queryType=ALLGPS&formatType=ICAO

https://www.navcen.uscg.gov/?pageName=gpsAlmanacs

https://navcen.uscg.gov/?Do=constellationStatus

https://celestrak.com/GPS/NANU/description.php

https://www.gsc-europa.eu/system-status/Constellation-Information

https://www.ngs.noaa.gov/NGSDataExplorer/

https://www.ngs.noaa.gov/NCAT/

https://tagis.dep.wv.gov/convert/

https://www.gpsvisualizer.com/map_input?form=googleearth

https://www.gpsbabel.org

https://github.com/gpsbabel/gpsbabel

https://geodesy.noaa.gov/cgi-bin/HTDP/htdp.prl?f1=4&f2=1

http://www.earthpoint.us/Convert.aspx

Resources

http://www.catb.org/gpsd/NMEA.txt DEPRECATED

http://www.catb.org/gpsd/NMEA.html DEPRECATED

https://gpsd.gitlab.io/gpsd/NMEA.html

https://support.google.com/earth/answer/148095

http://earth.google.com/intl/ar/userguide/v4/index.htm

http://static.googleusercontent.com/media/earth.google.com/en//userguide/v4/google_earth_user_guide.pdf

https://support.google.com/earth/answer/168344

https://dl.google.com/earth/client/GE7/release_7_1_8/googleearth-pro-7.1.8.3036.dmg

https://support.google.com/maps/answer/18539

https://fossies.org/linux/misc/gpsd-3.17.tar.gz/gpsd-3.17/test/daemon/beidou-gb.log

http://ktuukkan.github.io/marine-api/0.9.0/javadoc/net/sf/marineapi/nmea/sentence/TalkerId.html

https://github.com/mvglasow/satstat/wiki/NMEA-IDs

https://www.rapidtables.com/convert/number/degrees-to-degrees-minutes-seconds.html

https://in-the-sky.org/satmap_radar.php Note: when using the "Live Map of Satellite Positions" page, "Satellites above your horizon" tab, the displayed view is as if you are looking upwards into the sky. This means that the azimuth, which starts at 0 degrees at North, increases in the counter clockwise direction. This is probably obvious to the astronomers in the audience, but it wasn't to me.

https://www.gpsworld.com/the-almanac/

https://en.wikipedia.org/wiki/Global_Positioning_System

https://en.wikipedia.org/wiki/List_of_GPS_satellites

https://gssc.esa.int/navipedia/index.php/GPS_Navigation_Message

ftp://ftp.agi.com/pub/Catalog/Almanacs/SEM/GPSAlmanac.al3

https://www.rtca.org/sites/default/files/intentional_gps_interference_approved.pdf

https://github.com/mvglasow/satstat/wiki/NMEA-IDs

https://web.archive.org/web/20130225182002/http://www.colorado.edu/geography/gcraft/notes/gps/gpseow.htm

https://www.novatel.com/support/knowledge-and-learning/published-papers-and-documents/unit-conversions/

http://geostar-navi.com/files/docs/geos5/GeoS_NMEA_protocol_v4_0_eng.pdf

http://ozzmaker.com/wp-content/uploads/2016/08/M10478-M10578-NMEA_Sentence_Output.pdf

https://drotek.gitbook.io/rtk-f9p-positioning-solutions/tutorials/updating-zed-f9p-firmware

https://www.ardusimple.com/simplertk2b-hookup-guide/

https://www.ardusimple.com/simplertk2b-hack-1-unleash-the-usb-power-of-simplertk2b/

https://www.ardusimple.com/simplertk2b-hack-2/

https://www.ardusimple.com/simplertk2b-hack-3/

https://www.ardusimple.com/question/xbee-usage-documentation-for-simplertk/

https://www.ardusimple.com/question/problem-in-configuring-base-in-time-mode-sending-out-rtcm3-messages-from-base/

https://www.ardusimple.com/question/both-units-now-blink-gps-to-xbee-but-no-xbee-to-gps/

https://www.digi.com/resources/documentation/Digidocs/90001456-13/concepts/c_transparent_mode_detailed.htm?tocpath=XBee%20transparent%20mode%7CXBee%20transparent%20mode%20in%20detail%7C_____0

https://github.com/digidotcom/xbee_ansic_library

https://github.com/ukyg9e5r6k7gubiekd6/gpsd/blob/master/crc24q.c

https://youtu.be/T-g27KS0yiY Adam Hart-Davis, "The Clock That Changed the World", A History of the World, BBC, video

https://www.movable-type.co.uk/scripts/latlong.html

https://en.wikipedia.org/wiki/Haversine_formula

https://en.wikipedia.org/wiki/North_American_Plate

https://cs.nyu.edu/visual/home/proj/tiger/gisfaq.html

https://www.solidsignal.com

https://www.tigersupplies.com

https://www.surveying.com

https://www.sparkfun.com/products/15136

https://register.gotowebinar.com/recording/6016509329100006146

https://www.scientificamerican.com/article/gps-is-easy-to-hack-and-the-u-s-has-no-backup/ Paul Tullis, "GPS Is Easy To Hack, And The U.S. Has No Backup", Scientific American, 2019-12-01 (published in the 2019-12 print edition under the title "GPS Down")

https://www.cbsnews.com/news/global-positioning-system-preparing-the-next-generation-of-gps/ CBS Sunday Morning, "Preparing the next generation of GPS", 2019-12-01, video

http://www.aholme.co.uk/GPS/Main.htm

https://time.gov

https://aerospaceamerica.aiaa.org/features/cosmic-gps/ Adam Hadhazy, "Cosmic GPS", Aerospace America, 2020-05

https://www.gps.gov

https://en.wikipedia.org/wiki/Decimal_degrees

https://jsonlines.org

https://www.faa.gov/about/office_org/headquarters_offices/avs/offices/aam/cami/library/online_libraries/aerospace_medicine/tutorial/media/III.4.1.4_Describing_Orbits.pdf

https://www.gpsworldbuyersguide.com

https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797

https://youtu.be/NvpbW7JRu0Q "Philomena Cunk's Moments of Wonder Ep. 1: Time", Charlie Brooker's Weekly Wipe, BBC, video

https://tf.nist.gov/general/pdf/1568.pdf Harold Lyons, "Atomic Clocks", Scientific American, 1957-02 (archived on a NIST website)

http://freenmea.net/docs

https://www.sparkfun.com/datasheets/GPS/NMEA%20Reference%20Manual-Rev2.1-Dec07.pdf

https://www.celestis.com/resources/faq/what-are-the-azimuth-and-elevation-of-a-satellite/

https://ciechanow.ski/gps/

https://learn.sparkfun.com/tutorials/how-to-upgrade-firmware-of-a-u-blox-gnss-receiver/all

https://www.wired.com/story/satellite-time-distribution/ W. Ralston, "When the UK's Timing Systems Fail, This Service Will Save Them", WIRED, 2022-08-26

https://stjarnhimlen.se/comp/time.html Paul Schlyter, "Time Scales"

https://www.gpsrchive.com/Shared/Satellites/GPS%20vs%20GLONASS%20vs%20Galileo.html

Soundtrack

https://www.youtube.com/playlist?list=PLd7Yo1333iA9FMHIG_VmuBCVTQUzB-BZF

Build

Diminuto

Clone and build Diminuto, which is used by gpstool although not by libhazer. (Or follow the directions in the Diminuto README.)

cd ~
mkdir -p src
cd src
git clone https://github.com/coverclock/com-diag-diminuto
cd com-diag-diminuto/Diminuto
make pristine
make depend
make all

Hazer

Clone and build Hazer. (If you don't build Diminuto where the Hazer Makefile expects it, some minor Makefile hacking might be required.)

cd ~
mkdir -p src
cd src
git clone https://github.com/coverclock/com-diag-hazer
cd com-diag-hazer/Hazer
make pristine
make depend
make all

Documentation

You can make HTML, man page, and PDF documentation based on the Doxygen comments embedded in the source code by using the following make targets.

make documentation
make manuals

You can find the resulting documentation in the following directories. The variable TARGET will be replaced by "host" unless you are using some special Makefile configuration (for example, for cross-compilation).

out/${TARGET}/doc/html
out/${TARGET}/doc/man
out/${TARGET}/doc/pdf

(Diminuto has a similer documentation build process.)

Administration

The fs directory contains a file system overlay of files that I've found useful to carefully install in system directories like /etc and /lib. It is not installed automatically, because whether they are helpful, or they reduce your target system to a smoking heap of silicon, depends on your exact circumstances: the target system, the version of Linux it runs, etc. Some of the files under fs are new files in their entirety, some just contain lines that need to be added to the indicated files.

Most Linux distros will require the program accessing the GPS/GNSS device to either have root privileges or be in the "dialout" group. The latter is of course preferred.

sudo usermod -a -G dialout ${USER}

${USER} will need to log out and back in for this to take effect.

It is also possible to edit the udev rules to make the device readable and writeable by the ${USER} (okay) or anyone (nope).

Depending on what features of Hazer you choose to use, you will need to define some services in the /etc/services file. The port numbers are your choices to make. Note that the TCP and UDP port numbers for the same service (e.g. tesoro) can be (and typically are) the same number. Port number values may range from 0 to 65353 and must be unique. Linux also assigns "ephemeral" or temporary port numbers which will not appear in the /etc/services file.

tumbleweed 22222/udp  # Tumbleweed RTK source/sink
tesoro     33333/tcp  # Tesoro JSON source
tesoro     33333/udp  # Tesoro JSON sink
hazer      44444/udp  # Hazer NMEA source/sink

Unit Tests

Set up environment and run tests and utilities. (This establishes the paths for both the Hazer and the Diminuto executables so you don't have to install the libraries and binaries in the system directories.)

cd ~/src/com-diag-hazer/Hazer
. out/host/bin/setup
make sanity

Functional Tests

There are a bunch of scripts that use actual hardware. Some of them require home-built test fixtures and General Purpose Input/Output (GPIO) pins. But there is a small collection of functional tests that do not require any GNSS device at all. Mostly I use these to make sure that gpstool does not throw an assert and core dump.

cd ~/src/com-diag-hazer/Hazer
. out/host/bin/setup
make functional

Directories

  • app - application source files (utilities with more than one source file).
  • bin - utility source files.
  • cfg - configuration makefiles.
  • dat - data captured from Hazer, Yodel, and Tumbleweed tests (some in LFS).
  • fun - functional test source files.
  • inc - public header files.
  • out - build and test artifacts (not under source control).
  • fs - file system overlay that may be useful on the host on which Hazer runs.
  • src - feature implementation and private header source files.
  • tst - unit test source files (does not require a GPS receiver).
  • txt - miscellaneous archived text files.

Artifacts

  • out/$(TARGET)/app - application binary executables.
  • out/$(TARGET)/arc - object file archives for static linking.
  • out/$(TARGET)/bin - utility stripped binary executables and scripts.
  • out/$(TARGET)/dep - make dependencies.
  • out/$(TARGET)/fun - functional test binary executables and scripts.
  • out/$(TARGET)/gen - generated source files.
  • out/$(TARGET)/inc - include (header) files.
  • out/$(TARGET)/lib - shared objects for dynamic linking.
  • out/$(TARGET)/log - log files produced at run-time.
  • out/$(TARGET)/obc - object files.
  • out/$(TARGET)/sym - utility unstripped binary executables.
  • out/$(TARGET)/tmp - temporary files supporting headless operation.
  • out/$(TARGET)/tst - unit test binary executables and scripts.

Bash Sourced Files

  • setup - defines and exports shell variables like PATH and LD_LIBRARY_PATH into the environment.
  • diminuto - defines shell variables like Arch, Release, Revision, and Vintage into the current shell.

Applications

  • dgmtool - multipoint-to-multipoint CSV UDP-to-TCP forwarder.
  • geodesic - computes the geodesic distance in meters between two WGS84 coordinates.
  • gpstool - Hazer's multi-purpose GNSS tool.
  • rtktool - Tumbleweed's point-to-multipoint RTK UDP-to-UDP router.

Utilities

General Purpose

  • bakepi - monitors Raspberry Pi core temperature which throttles at 82C.
  • bucketbrigade - read from a serial port and forward to another serial port.
  • checksum - takes arguments that are unterminated NMEA, UBX, or RTCM packets and adds end matter.
  • compasstool - converts a bearing in decimal degrees to an 8, 16, or 32 compass point.
  • csv2dgm - forwards subset of gpstool CSV fields from stdin to a UDP endpoint, serial port, etc.
  • haversine - computes the great circle distance in meters between two coordinates.
  • hazer - consumes data from a serial port and reports on stdout.
  • iso8601 - converts seconds since the UNIX epoch into an ISO8601 timestamp.
  • mapstool - convert gpstool coordinate strings to formats accepted by Google Maps.
  • monitor - uses gpstool to monitor device without any configuration.
  • pps - uses Diminuto pintool to multiplex on a 1PPS GPIO pin.
  • replay - replay a gpstool catenate (-C) file in non-real-time.

Data Analysis

  • csv2dat - converts gpstool CSV file to a real-time readable output.
  • csv2geo - appends geodesic and altitude differences to gpstool CSV file.
  • csv2iso - converts times in gpstool CSV file into ISO8601-ish timestamps.
  • csv2rmc - converts gpstool CSV file to NMEA RMC sentences.
  • csv2tty - converts gpstool CSV file to a (different) real-time readable output.
  • csvlimits - determines boundary of solutions in a gpstool CSV file.
  • csvparts - splits gpstool CSV file into smaller files in subdirectories.

Google Maps Moving Map (DEPRECATED)

  • client - runs Google Maps API in Firefox browser under MacOS.
  • consumer - consumes datagrams and reports on stdout.
  • producer - consumes data from serial port and forwards as datagrams.
  • provider - consumes datagrams and forwards to serial port.

Google Earth Keyhole Markup Language (KML)

  • csv2kml - converts gpstool CSV file to KML 2.3 XML to visualize a line.
  • csv2kmlchanges - converts gpstool CSV file to KML 2.3 XML to visualize fix changes.
  • csv2kmlpoints - converts gpstool CSV file to KML 2.3 XML to visualize points.
  • out2kmlpoints - converts gpstool OUT files to KML 2.3 XML to visualize points.

Intertial Measurement Unit (Yodel)

  • vehicle - configures and runs a UBX-NEO-M8U with peruse and hups.

Differential GNSS (Tumbleweed)

  • base - configures and runs a UBX-ZED-F9P as a base in survey or fixed mode.
  • benchmark - configures and runs a UBX-ZED-F9P as a corrected rover saving a CSV.
  • control - integrates mobile, peruse, and hups scripts for field testing.
  • field - integrates benchmark, peruse, and hups scripts for field testing.
  • fixed - configures and runs a UBX-ZED-F9P as a base station in fixed mode.
  • mobile - configures and runs a UBX-ZED-F9P as an uncorrected rover.
  • mobilize - like mobile but exit once initialization is complete or fails.
  • proxy - receive UDP packets from the Base and forward to the Rover.
  • router - routes UDP packets received from a base to all rovers.
  • rover - configures and runs a UBX-ZED-F9P as a corrected rover.
  • station - runs a UBX-ZED-F9P with no additional configuration.
  • survey - configures and runs a UBX-ZED-F9P as a base in survey mode.
  • ubxval - converts a number into a UBX-usable form.

OpenStreetMap Moving Map (Tesoro)

  • csvdataset - convert CSV file into a JSON object array for a static map.
  • csvfollow - follow a CSV file in real-time, forward as JSON to a UDP endpoint.
  • csvmeter - meters lines from a gpstool CSV file based on interarrival times.
  • csvplayback - playback a stored CSV file, forward JSON to a UDP endpoint.
  • jsonmeter - meters lines from a JSON file based on interarrival times.
  • tracker - capture CSV with gpstool, forward JSON to an UDP endpoint, with peruse and hups.

UDP over LTE-M (Wheatstone)

  • sarar5 - tracker using a USB-attached U-Blox SARA-R5 LTE-M radio (WIP).
  • xbee3 - tracker using a serial-attached Digi XBEE 3 LTE-M radio.
  • xbee3shutdown - shuts down Digi XBEE 3 LTE-M radio (recommended before powering off).

Precision Time and Frequency Reference (Metronome)

  • reference - configures the ZED-F9T to emit 1PPS (TP1) and 10MHz (TP2).

Output Control

  • checkpoint - move the out/TARGET/tmp directory to a timestamped name.
  • hup - send SIGHUP to all running instances of gpstool.
  • hups - repeatedly send SIGHUP to all running instances of gpstool on demand.
  • peruse - helper script to watch logs and screens from headless scripts.

Functional Tests

  • bu353s4 - exercises the GlobalSat BU-353S4 receiver.
  • bu353w10 - exercises the GlobalSat BU-353W10 receiver.
  • bu353w10C - uses cat to send stored data files to gpstool.
  • bu353w10D - uses socat to send data from GlobalSat BU-353W10 to gpstool over a UDP socket.
  • bu353w10F - exercises the GlobalSat BU-353W10 receiver with slow displays.
  • bu353w10H - exercises the GlobalSat BU-353W10 receiver in headless mode.
  • bu353w10M4 - exercises the GlobalSat BU-353W10 receiver logging PRN 4.
  • bu353w10P - exercises the GlobalSat BU-353W10 receiver configured for U-blox PUBX messages.
  • bu353w10S - uses socat to send data from GlobalSat BU-353W10 to gpstool over named pipe.
  • bu353w10T - exercises the GlobalSat BU-353W10 receiver with no additional configuration.
  • bu353w10V - exercises the GlobalSat BU-353W10 receiver using verbose mode.
  • bu353W10X - exercises the GlobalSat BU-353W10 receiver while testing data expiration.
  • checksums - exercises the checksum utility.
  • collect - collects output of a device into a file.
  • datagramsink - exercises a datagram source.
  • datagramsource - exercises a datagram sink.
  • dgnss - a script used to test other DNSS scripts.
  • gn803g - exercises the TOPGNSS GN-803G receiver.
  • gpsproplusblue - exercises the Bad Elf GPS Pro+ receiver via Bluetooth.
  • gpsproplususb - exercises the Bad Elf GPS Pro+ receiver via USB.
  • gr701w - exercises the NaviSys GR701W receiver.
  • gr701w1pps - exercises the NaviSys GR701W receiver and its 1PPS output.
  • lowresolution - same as bin/base.sh but with much much lower standards.
  • makerfocus - exercises the MakerFocus GPS board.
  • makerfocuspps - exercises the MakerFocus GPS board and its 1PPS output.
  • neom8n - exercises the RDQ Micro M8N board.
  • neom8n1pps - exercises the SparkFun NEO-M8N board and its 1PPS output.
  • neom8u - exercises the SparkFun GPS Deadreckoning board.
  • pmtk - exercises the Adafruit Ultimate GPS board.
  • simplertk2bbase - configures an Ardusimple SimpleRTK2B board as a base.
  • simplertk2b - exercises the Ardusimple SimpleRTK2B board.
  • simplertk2bquery - queries the configuration of an Ardusimple SimpleRTK2B board.
  • simplertk2brover - configures an Ardusimple SimpleRTK2B board as a rover.
  • simplertk2brtcm - collects RTCM messages into a file.
  • simplertk2bsurvey - runs a Ardusimple SimpleRTK2B in survey mode.
  • sink - received UDP packets from the source.
  • sirfstar4 - exercises any SiRF Star 4 device.
  • source - send UDP packets to the sink.
  • streamdump - socat to phex.
  • streamprint - socat to gpstool with a lot of debug output.
  • talkers - processes a file of synthetic input.
  • tesorochoosefile - emit CSV output to an observation file for Tesoro.
  • tesorodraganddrop - emit CSV output to an observation file for Tesoro.
  • tesoroselectchannel - emit CSV output to a UDP endpoint for Tesoro.
  • tumbleweedkeepalives - serves as a Tumbleweed keepalive sink.
  • tumbleweedpi - Another Tumbleweed functional test.
  • tumbleweedremote - serves as a Tumbleweed RTCM sink.
  • tumbleweed - Tumbleweed functional test.
  • ublox7 - exercises any Ublox 7 device.
  • ublox8debug - exercises any Ublox 8 device with gpstool debug enabled.
  • ublox8 - exercises any Ublox 8 device.
  • ublox9 - exercises any Ublox 9 device.
  • ubxcoldstart - sends UBX message to cold start U-blox device.
  • ubxmonitor - sends UBX messages to query U-blox device for internal states.
  • ubxrestoredefaults - sends UBX message to restore defaults to U-blox battery backed RAM (BBRAM).
  • uputronics - exercises the Uputronics GPS board for the Rasperry Pi.
  • zedf9r - exercise UBX-ZED-F9R device.
  • zedf9t - exercise UBX-ZED-F9T device.
  • zedf9t-configure - configure UBX-ZED-F9T RAM for 1PPS (TP1) and 10MHz (TP2).
  • zedf9t-factory - factory reset UBX-ZED-F9T device.
  • zedf9t-flash - configure the UBX-ZED-F9T flash for 1PPS (TP1) and 10MHz (TP2).
  • zedf9t-reset - software reset UBX-ZED-F9T device.

Environmental Variables

export COM_DIAG_HAZER_SAVDIR="${HOME}/save"

Some scripts in the bin and fun directories save stdout, stderr, CSV, or DGNSS parameters in files. Setting this environmental variable changes the directory in which these files are stored. By default, stdout, stderr, and CSV files are stored in the out/${TARGET}/tmp subdirectory of the code base, where TARGET is set to the name of the Makefile configuration file (typically "host"). The DGNSS parameters are saved in ${HOME}/fix, or if ${HOME} is not set, in /var/tmp/fix. All of these defaults are overridden if the environmental variable is set.

export COM_DIAG_DIMINUTO_LOG_MASK=0xff

Sets the default log mask for Diminuto for those applications that set the mask from the environment. The value is an eight-bit number in decimal, hexadecimal, or even octal. In addition, the string ~0 can be used to enable all log levels, equivalent to 255, 0xff, or 0377.

Comma Separated Value (CSV) Output

The -T flag for gpstool will cause the utility to save the current Position, Velocity, Time (PVT) solution once a second to a "trace file" in CSV format as described below. This makes it easy to analyze results using tools like Excel and several tools provided by Hazer itself. The PVT solution is taken from the high precision u-blox UBX-NAV-HPPOSLLH message if it is available, from the ensemble GNSS solution if it exists, or from one of the four Global Satellite Navigation Systems solutions in this order of preference: GPS, GLONASS, Galileo, BeiDou. The attitude (roll, pitch, yaw) is taken from the UBX-NAV-ATT message from the IMU if it is available. Fields which are not available or are not supported by the receiver have values coded as "0." instead of an empty string to simplify parsing in post-processing.

  • 0 - NAM: hostname of computer running gpstool.
  • 1 - NUM: sequence number of observation.
  • 2 - FIX: 0=no fix, 1=dead reckoning, 2=2D, 3=3D, 4=combined, 5=time only.
  • 3 - SYS: 0=ensemble, 1=GPS, 2=GLONASS, 3=GALILEO, 4=BEIDOU.
  • 4 - SAT: number of satellites used in position fix.
  • 5 - CLK: local time in decimal seconds since the POSIX Epoch.
  • 6 - TIM: GPS time in decimal seconds since the POSIX Epoch.
  • 7 - LAT: WGS84 latitude in decimal degrees.
  • 8 - LON: WGS84 longitude in decimal degrees.
  • 9 - HAC: reported horizontal error in decimal meters.
  • 10 - MSL: altitude above Mean Sea Level in decimal meters.
  • 11 - GEO: altitude above WGS84 ellipse in decimal meters.
  • 12 - VAC: reported vertical error in decimal meters.
  • 13 - SOG: speed over ground in decimal knots.
  • 14 - COG: course over ground in decimal degrees.
  • 15 - ROL: roll in decimal degrees from IMU.
  • 16 - PIT: pitch in decimal degrees from IMU.
  • 17 - YAW: yaw in decimal degrees form IMU.
  • 18 - RAC: roll accuracy in decimal degrees.
  • 19 - PAC: pitch accuracy in decimal degrees.
  • 20 - YAC: yaw accuracy in decimal degrees.
  • 21 - OBS: number of survey observations.
  • 22 - MAC: mean accuracy of survey fix.

A snippet of an actual CSV file looks like this.

"neon", 116, 3, 0, 12, 1598455524.895094741, 1598455524.000000000, 39.7943026, -105.1533253, 0., 1708.000, 1686.500, 0., 0.071000, 0., 0.00000, 80.98829, 0.00000, 20.00000, 43.29752, 167.44616, 0, 0.
"neon", 117, 3, 0, 12, 1598455525.895126606, 1598455525.000000000, 39.7943030, -105.1533263, 0., 1708.100, 1686.600, 0., 0.017000, 0., 0.00000, 80.98829, 0.00000, 20.00000, 43.29752, 167.44616, 0, 0.
"neon", 118, 3, 0, 12, 1598455526.895211419, 1598455526.000000000, 39.7943030, -105.1533276, 0., 1708.200, 1686.700, 0., 0.012000, 0., 0.00000, 80.98829, 0.00000, 20.00000, 43.29752, 167.44616, 0, 0.
"neon", 119, 3, 0, 12, 1598455527.895183560, 1598455527.000000000, 39.7943031, -105.1533286, 0., 1708.300, 1686.800, 0., 0.016000, 0., 0.00000, 80.98829, 0.00000, 20.00000, 43.29752, 167.44616, 0, 0.
"neon", 120, 3, 0, 12, 1598455528.901673983, 1598455528.000000000, 39.7943035, -105.1533300, 0., 1708.500, 1687.000, 0., 0.039000, 0., 0.00000, 80.98829, 0.00000, 20.00000, 43.29752, 167.44616, 0, 0.

csv2tty

Piping the CSV snippet into the script csv2tty produces readable output in fixed columns that looks like this.

GN 12 3D | 2020-08-26T15:25:24Z |  39°47'39"N, 105°09'11"W |  1708m |    0kn |   0° N   |   0°,  80°,   0°
GN 12 3D | 2020-08-26T15:25:25Z |  39°47'39"N, 105°09'11"W |  1708m |    0kn |   0° N   |   0°,  80°,   0°
GN 12 3D | 2020-08-26T15:25:26Z |  39°47'39"N, 105°09'11"W |  1708m |    0kn |   0° N   |   0°,  80°,   0°
GN 12 3D | 2020-08-26T15:25:27Z |  39°47'39"N, 105°09'11"W |  1708m |    0kn |   0° N   |   0°,  80°,   0°
GN 12 3D | 2020-08-26T15:25:28Z |  39°47'39"N, 105°09'11"W |  1708m |    0kn |   0° N   |   0°,  80°,   0°

These columns contain the following information.

  • GN - this fix was made using this talker (GN is an ensemble solution).
  • 12 - twelve satellites were used for this fix.
  • 3D - the fix is three-dimensional (NO=none, IN=IMU, 2D, 3D, GI=GNSS+IMU, TM=time, OT=other).
  • 2020-08-26T15:25:24Z - this is the computed date and time in UTC (Zulu).
  • 39°47'39"N, 105°09'11"W - this is the latitude and longitude in the GNSS datum (typically WGS84).
  • 1708m - this is the altitude above mean sea level (MSL).
  • 0kn - this is the ground speed in knots (nautical miles per hour).
  • 0° N - this is the current true bearing and compass direction.
  • 0°, - this is the roll of the vehicle reference frame from the IMU if available.
  • 80°, - this is the pitch of the vehicle reference frame from the IMU if available.
  • 0° - this is the yaw of the vehicle reference frame from the IMU if available.

The following command pipeline is useful.

tail -f out/host/tmp/example.csv | csv2tty

The peruse command supports this directly when used with a CSV file.

peruse example csv

csv2dat

Piping the CSV snippet into the script csv2dat produces a different readable output in fixed columns that looks like this.

GN 12 3D |    116 | 2020-08-26T09:25:24J | 2020-08-26T15:25:24Z |  39°47'39.489360"N, 105°09'11.971080"W |  1708m   5603ft |    0kn    0mph     0kph |   0° N   |   0°,  80°,   0°
GN 12 3D |    117 | 2020-08-26T09:25:25J | 2020-08-26T15:25:25Z |  39°47'39.490799"N, 105°09'11.974680"W |  1708m   5604ft |    0kn    0mph     0kph |   0° N   |   0°,  80°,   0°
GN 12 3D |    118 | 2020-08-26T09:25:26J | 2020-08-26T15:25:26Z |  39°47'39.490799"N, 105°09'11.979359"W |  1708m   5604ft |    0kn    0mph     0kph |   0° N   |   0°,  80°,   0°
GN 12 3D |    119 | 2020-08-26T09:25:27J | 2020-08-26T15:25:27Z |  39°47'39.491160"N, 105°09'11.982959"W |  1708m   5604ft |    0kn    0mph     0kph |   0° N   |   0°,  80°,   0°
GN 12 3D |    120 | 2020-08-26T09:25:28J | 2020-08-26T15:25:28Z |  39°47'39.492599"N, 105°09'11.987999"W |  1708m   5605ft |    0kn    0mph     0kph |   0° N   |   0°,  80°,   0°

These columns contain the following information.

  • GN - this fix was made using this talker (GN is an ensemble solution).
  • 12 - twelve satellites were used for this fix.
  • 3D - the fix is three-dimensional (NO=none, IN=IMU, 2D, 3D, GI=GNSS+IMU, TM=time, OT=other).
  • 116 - this is the monotonically increasing observation number.
  • 2020-08-26T09:25:24J - this is the local system time the observation was made (Juliet).
  • 2020-08-26T15:25:24Z - this is the computed date and time in UTC (Zulu).
  • 39°47'39.489360"N, 105°09'11.971080"W - this is the higher resolution latitude and longitude in the GNSS datum (typically WGS84).
  • 1708m - this is the altitude above mean sea level (MSL) in meters.
  • 5603ft - this is the altitude above mean sea level (MSL) in feet.
  • 0kn - this is the ground speed in knots (nautical miles per hour).
  • 0mph - this is the ground speed in miles per hour.
  • 0kph - this is the ground speed in kilometers mer hour.
  • 0° N - this is the current true bearing and compass direction.
  • 0°, - this is the roll of the vehicle reference frame from the IMU if available.
  • 80°, - this is the pitch of the vehicle reference frame from the IMU if available.
  • 0° - this is the yaw of the vehicle reference frame from the IMU if available.

I find this format more suitable for viewing the data during post-processing.

csv2dgm

Piping the CSV snippet into the script csv2dgm and providing an IP host address and port number like this

csv2dgm -j -U hostname:5555

sends a subset of the CSV line to an endpoint as a UDP datagram in JSON format. Receiving the datagrams using a command like this

socat -u UDP6-RECV:5555 -

produces output that looks like this.

{ "NAM": "neon", "NUM": 116, "TIM": 1598455524, "LAT": 39.7943026, "LON": -105.1533253, "MSL": 1708.000, "LBL": "2020-08-26T15:25:24Z" }
{ "NAM": "neon", "NUM": 117, "TIM": 1598455525, "LAT": 39.7943030, "LON": -105.1533263, "MSL": 1708.100, "LBL": "2020-08-26T15:25:25Z" }
{ "NAM": "neon", "NUM": 118, "TIM": 1598455526, "LAT": 39.7943030, "LON": -105.1533276, "MSL": 1708.200, "LBL": "2020-08-26T15:25:26Z" }
{ "NAM": "neon", "NUM": 119, "TIM": 1598455527, "LAT": 39.7943031, "LON": -105.1533286, "MSL": 1708.300, "LBL": "2020-08-26T15:25:27Z" }
{ "NAM": "neon", "NUM": 120, "TIM": 1598455528, "LAT": 39.7943035, "LON": -105.1533300, "MSL": 1708.500, "LBL": "2020-08-26T15:25:28Z" }

This output can be processed by the fun/channel script in another project, Tesoro, which uses this JSON and some JavaScript code to drive a moving map display using an OpenStreetMap tile server.

The same utility can be used to send the same subset of the CSV output to a serial port. I use this to transmit the CSV data via an Digi XBEE 3 LTE-M radio. If the XBEE is configured correctly, it can send the same datagram to the same endpoint via LTE-M, yielding the same result as above. I use LTE-M SIMs for AT&T's One Rate plan for this.

csv2dgm -j -D /dev/ttyUSB0 -b 9600 -8 -1 -n

csvfollow and csvplayback

The csvfollow script follows (tail -f) a CSV file being output in real-time by gpstool and uses csv2dgm to forward the corresponding JSON datagrams to (for example) a system that is using them to steer a moving map display.

csvfollow 192.168.1.253:tesoro out/host/tmp/vehicle.csv

The csvplayback script uses csvmeter to meter out an existing CSV file at approximately the same rate as it was originally generated by gpstool and uses csv2dgm to forward the corresponding JSON datagrams to (for example) a system that is using them to steer a moving map display.

csvplayback 192.168.1.253:tesoro dat/yodel/20200917/vehicle.csv

See the README in the Tesoro repository for more information.

csvdataset

The csvdataset script is a filter that reads a CSV file and produces a JSON dataset suitable for importation into the Tesoro choosedataset feature to create a static route map. Multiple routes can be rendered on the same map, the the properties of the route line (color, weight, etc.) can be changed either globally or on a per route basis.

csvdataset < dat/yodel/20200917/vehicle.csv > 20200917.json

The entire JSON dataset has to be processed and stored in memory by Tesoro. (This is a requirement of the underlying Leaflet third-party library.) For very large datasets this can be problematic. One way to handle this is to sample the CSV file. An optional value on the command line can cause csvdataset to sample the input file. The first and last data point is always included regardless of the sampling modulo value.

csvdataset 10 < dat/yodel/20200917/vehicle.csv > 20200917.json

See the README in the Tesoro repository for more information.

Help

gpstool

> gpstool -?
usage: gpstool
               [ -d ] [ -v ] [ -u ]
               [ -D DEVICE [ -b BPS ] [ -7 | -8 ] [ -e | -o | -n ] [ -1 | -2 ] [ -l | -m ] [ -h ] [ -s ] | -S FILE ] [ -B BYTES ]
               [ -R | -E | -H HEADLESS | -P ] [ -F SECONDS ] [ -i SECONDS ] [ -t SECONDS ]
               [ -C FILE ]
               [ -O FILE ]
               [ -L FILE ]
               [ -T FILE [ -f SECONDS ] ]
               [ -N FILE ]
               [ -K [ -k MASK ] ]
               [ -A STRING ... ] [ -U STRING ... ] [ -W STRING ... ] [ -Z STRING ... ] [ -w SECONDS ] [ -x ]
               [ -G :PORT | -G IP:PORT [ -g MASK ] ]
               [ -Y :PORT | -Y IP:PORT [ -y SECONDS ] ]
               [ -I PIN | -c ] [ -p PIN ]
               [ -M ] [ -X MASK ] [ -V ]
       -1          Use one stop bit for DEVICE.
       -2          Use two stop bits for DEVICE.
       -7          Use seven data bits for DEVICE.
       -8          Use eight data bits for DEVICE.
       -A STRING   Collapse STRING, append Ubx end matter, write to DEVICE, expect ACK/NAK.
       -A ''       Exit when this empty STRING is processed.
       -B BYTES    Set the input Buffer size to BYTES bytes.
       -C FILE     Catenate input to FILE or named pipe.
       -D DEVICE   Use DEVICE for input or output.
       -E          Like -R but use ANSI Escape sequences.
       -F SECONDS  Set report Frequency to 1/SECONDS, 0 for no delay.
       -G IP:PORT  Use remote IP and PORT as dataGram sink.
       -G :PORT    Use local PORT as dataGram source.
       -H HEADLESS Like -R but writes each iteration to HEADLESS file.
       -I PIN      Take 1PPS from GPIO Input PIN (requires -D) (<0 active low).
       -K          Write input to DEVICE sinK from datagram source.
       -L FILE     Write pretty-printed input to FILE file.
       -M          Run in the background as a daeMon.
       -N FILE     Use fix FILE to save ARP LLH for subsequeNt fixed mode.
       -O FILE     Save process identifier in FILE.
       -P          Process incoming data even if no report is being generated.
       -R          Print a Report on standard output.
       -S FILE     Use source FILE or named pipe for input.
       -T FILE     Save the PVT CSV Trace to FILE.
       -U STRING   Collapse STRING, append Ubx end matter, write to DEVICE.
       -U ''       Exit when this empty STRING is processed.
       -V          Log Version in the form of release, vintage, and revision.
       -W STRING   Collapse STRING, append NMEA end matter, Write to DEVICE.
       -W ''       Exit when this empty STRING is processed.
       -X MASK     Enable special test modes via MASK.
       -Y IP:PORT  Use remote IP and PORT as keepalive sink and surveYor source.
       -Y :PORT    Use local PORT as surveYor source.
       -Z STRING   Collapse STRING, write to DEVICE.
       -Z ''       Exit when this empty STRING is processed.
       -b BPS      Use BPS bits per second for DEVICE.
       -c          Take 1PPS from DCD (requires -D and implies -m).
       -d          Display Debug output on standard error.
       -e          Use Even parity for DEVICE.
       -f SECONDS  Set trace Frequency to 1/SECONDS.
       -g MASK     Set dataGram sink mask (NMEA=1, UBX=2, RTCM=4) default NMEA.
       -h          Use RTS/CTS Hardware flow control for DEVICE.
       -i SECONDS  Bypass input check every SECONDS seconds, 0 for always, -1 for never.
       -k MASK     Set device sinK mask (NMEA=1, UBX=2, RTCM=4) default NMEA.
       -l          Use Local control for DEVICE.
       -m          Use Modem control for DEVICE.
       -n          Use No parity for DEVICE.
       -o          Use Odd parity for DEVICE.
       -p PIN      Assert GPIO outPut PIN with 1PPS (requires -D and -I or -c) (<0 active low).
       -s          Use XON/XOFF (control-Q/control-S) for DEVICE.
       -t SECONDS  Timeout GNSS data after SECONDS seconds.
       -u          Note Unprocessed input on standard error.
       -v          Display Verbose output on standard error.
       -w SECONDS  Write STRING to DEVICE no more than every SECONDS seconds.
       -x          EXit if a NAK is received.
       -y SECONDS  Send surveYor a keep alive every SECONDS seconds.

rtktool

> rtktool -?
usage: rtktool [ -d ] [ -v ] [ -M ] [ -V ] [ -M ] [ -p :PORT ] [ -t SECONDS ]
       -M          Run in the background as a daeMon.
       -V          Log Version in the form of release, vintage, and revision.
       -d          Display Debug output on standard error.
       -p :PORT    Use PORT as the RTCM source and sink port.
       -t SECONDS  Set the client timeout to SECONDS seconds.
       -v          Display Verbose output on standard error.

csv2dgm

> csv2dgm -?
usage: csv2dgm [ -d ] [ -v ] [ -c | -h | -j | | -q | -s | -x | -y ] [ -t ] [ -D DEVICE [ -b BPS ] [ -7 | -8 ] [ -1 | -2 ] [ -e | -o | -n ] [ -m ] [ -r ] ] [ -F FILE ] [ -M MODE ] [ -U HOST:PORT ]
       -1              Set DEVICE to 1 stop bit.
       -2              Set DEVICE to 2 stop bits.
       -7              Set DEVICE to 7 data bits.
       -8              Set DEVICE to 8 data bits.
       -D DEVICE       Write datagram to DEVICE.
       -F FILE         Save latest datagram in observation FILE.
       -M MODE         Set FILE mode to MODE.
       -U HOST:PORT    Forward datagrams to HOST:PORT.
       -b BPS          Set DEVICE to BPS bits per second.
       -c              Emit CSV.
       -d              Enable debug output.
       -e              Set DEVICE to even parity.
       -h              Emit HTML.
       -j              Emit JSON.
       -o              Set DEVICE to odd parity.
       -m              Set DEVICE to use modem control.
       -n              Set DEVICE to no parity.
       -q              Emit URL Query.
       -r              Set DEVICE to use hardware flow control.
       -s              Emit Shell commands.
       -t              Write to standard output.
       -v              Enable verbose output.
       -x              Emit XML.
       -y              Emit YAML.

Memory Leaks

When testing for memory leaks, I strongly recommend using valgrind, specfically with the full leak check option.

valgrind --leak-check=full gpstool ...

I was surprised to find it called out a twelve byte memory leak in the C library's locale handling, which gpstool requires to correctly display Unicode symbols like the degree symbol. Perhaps this will be fixed in a future GNU update (or it's a bug in my code that I can't see).

For More Information

Acknowledgements

Thanks to Charles F. F. Karney for his MIT licensed geographiclib.

Thank you to Kathy Kadnuck of the Valley Water District, who, thanks to her collection of infrastructure survey maps, helped me to determine the location of an old NGS survey marker in my neighborhood which, apparently, had been buried under a sidewalk as part of a development in the past few decades. (Remarkably, it is not illegal to landscape over an NGS survey marker. It's merely illegal to remove or damage them. If a municipality needs to find the marker for official business, be prepared to have your landscaping back-hoe'ed up. And be billed for it.)

A big thank you to Brad Gabbard, a professional surveyor with Flatirons, Inc., a surveying, engineering, and geomatics firm located in Boulder Colorado. Mr. Gabbard generously shared some results off his professional Trimble GPS rover taken at NGS survey marker KK1446 that I have used to test this code.

Thanks to several manufacturers of GNSS devices, or of products that have GNSS devices embedded within them, who, because of design flaws and bugs in their products, led to vast improvements in this code. No, I'm not kidding: almost every time I test a new GNSS-based product I find the opportunity for improvement.

Special thanks to Mrs. Overclock for her assistance in road testing (literally) this software and for her understanding regarding having GPS equipment littered all around the house both inside and outside.

Footnotes

  1. Equipped with a CR1220 3V button cell.

  2. Supports UBX. 2 3 4 5 6 7 8 9 10 11

  3. Receives GPS (U.S.), GLONASS (Russia), Galileo (EU), and COMPASS (China) concurrently. 2 3 4 5

  4. Receives GPS (U.S.) and GLONASS (Russia) constellations concurrently. 2 3 4 5 6 7 8

  5. Bluetooth pairs with Raspberry Pi after update to FW 3.0.0.

  6. Emits all sorts of interesting stuff in unsolicited $GPTXT or $GNTXT sentences. 2 3 4 5 6 7

  7. A software defined radio (SDR).

  8. Uses Bluetooth (see procedure for pairing in https://github.com/coverclock/com-diag-hazer/blob/master/REMARKS.md). 2

  9. Supposed to receive both GPS and GLONASS but my GLO and both of my GLO 2 units just receive GPS. 2

  10. Rumored to differ from the original GLO only by its increased battery life.

  11. A good inexpensive introductory GPS device easily acquired from numerous sources. 2

  12. A tear down of the BU-353W10 reveals it has a button cell for its battery backed RAM.

  13. I have used the 1PPS indication exported via a digital output pin. 2 3

  14. Receives GPS (U.S.) or GLONASS (Russia) constellations via configuration.

  15. I have used the 1PPS indication exported via Data Carrier Detect (DCD).

  16. Install udev rules in overlay to prevent ModemManager from toying with device. 2

  17. Make sure you mount this component side down, patch antenna side up. 2

  18. Has integrated Inertial Measurement Unit (IMU). 2

  19. This SparkFun board requires opening (cutting) and closing (soldering) traces for dual UART operation.

  20. This U-Blox gen 8 receiver is embedded in a U-Blox LTE-M module which required a lot of config via AT commands.

  21. 1PPS (a.k.a. TPS in the docs) only has a pulse width of a few microseconds hence LED inoperative (bug).

  22. Timing and frequency reference claimed +/- 5ns.

About

Parse NMEA sentences and other typical output from GNSS devices.

Resources

License

Stars

Watchers

Forks

Packages

No packages published