USB GNSS RTK Receiver Setup
Work in Progess
- Initial testing notesWIP
- https://learn.sparkfun.com/tutorials/what-is-gps-rtk/all
- https://www.ardusimple.com/rtk-explained/
- rtkexplorer β Exploring low cost solutions for high precision GPS/GNSS
- https://en.wikipedia.org/wiki/NMEA_0183
- https://incors.in.gov/rtk.aspx
- open mower ntrip
- https://ntrip-list.com/
- http://reach.local
- https://github.com/rtklibexplorer/RTKLIB
- https://packages.ubuntu.com/search?keywords=rtklib
- http://magnav.mit.edu/
- https://youtu.be/lQuVkbphOog
- NTRIP Documenation
- RTKLIB Presentation
Helpful Resources
This setup provides a tutorial on how to use a GNSS RTK Receiver, a Linux Machine, and an RTK Correction Service (or Base Station) to access position data with centimeter-level precision. Many GNSS RTK Receivers will connect to an NTRIP Caster directly utilizing its on-board LoRa,WiFi, Bluetooth, or Cellular Modem. However this tutorial is geared towards using a Linux Machine to connect to an NTRIP Caster to receive the RTK Correction Data and then relay the data to the RTK Receiver via USB. This use case is more relevant to a robotic platform that already has access to the Internet or a Local Network with an NTRIP Caster/Server. Main reason to do it this way is because your Linux Machine may already be using a Cellular Modem or Long Distance Wireless Access Point. This would render the wireless capabilities of the RTK Receiver as redundant or less capable than what the Linux machine is using.
Basic Concepts
GNSS RTK Receiver (Rover)
These devices have recently became available in low-cost forms with comparable performance to higher end products. It is basically a micro-controller with a GNSS antenna and receiver with the capability to run complex calculations that enable it to resolve position data with centimeter precision under the right conditions. The micro-controller may be using a library like RTKLIB to perform the calculations. The most important condition for resolving centimeter-level precision is access to RTK corrections from a nearby (approximately 35 km) Base Station.
Base Station
The Base Station is basically a stationary GNSS RTK Receiver that is configured to stream out RTK correction data using a NTRIP Server (COTS products offer this as a single package). A Base Station and Reference Station are synonymous.
Continuously Operating Reference Stations (CORS) network
A CORS Network is a collection of GNSS Base stations combined in a single network to provide wider coverage of valid RTK correction data. Recall that RTK correction data is only valid within approximately a 35 km radius of the Base Station. A CORS network may provide convenient access to RTK correction data from the nearest base station. There also exist advance techniques to combine correction data from multiple base stations to provide correction data from a Virtual Reference Station (VRS) to further reduce location error. See VRS for details
NTRIP Client
RTKLIB provides a suite of CLIs and GUIs that simplify much of the work. In theory could configure your design to perform the RTK calculations on the Linux Machine. However in this tutorial, the Linux Machine is only used to relay the RTK correction data from the NTRIP Caster to the GNSS RTK Receiver. To do this we use the RTKLIB CLI str2str
which enables us to connect to a NTRIP caster as a data input source and a GNSS RTK Receiver has a data output target. This employs our Linux machine as a NTRIP Client. Alternatively, instead of using the RTKLIB CLI, we can use the ROS package ntrip_client. See OpenMowerβs ntrip_client launch file for further details.
https://software.rtcm-ntrip.org/wiki
GNSS RTK Receiver
Configure RTK device correction input and position out methods
This project is using the Emlid Reach RTK Module and following documentation. Once the device is connected to a local WiFi network device can be accessed via the web app http://reach.local
Emlid Reach
- Raw data receiver: U-blox NEO-M8T β 72 channels, output rate is up to 18Hz, supports GPS L1, GLONASS G1, BeiDou B1, QZSS, SBAS, ready for Galileo E1
- Processing unit: Intel Edison β dual-core 500 MHz
- Connectivity: I2C, UART, GPIO, TimeStamp, OTG USB, Bluetooth, Wi-Fi
- GNSS Antenna: external with MCX connector
Interface
- USB-to-PC
- On Reach Module: Micro-USB
- UART
- On Reach Module: Hirose DF13-6P-1.25H(50) colloquially Β βDF13 Female headersβ
- https://www.lambdrive.com/depot/Robotics/Controller/PixhawkFamily/Connector/index.html
- https://store.emlid.com/us/product/reach-m-cable-for-pixhawk/
- Β Molex PicoBlade- Can be inserted into DF13 Female headers (but not visa versa)
- https://raspberrypi.stackexchange.com/questions/104464/where-are-the-uarts-on-the-raspberry-pi-4
- https://raspberrypi.stackexchange.com/questions/45570/how-do-i-make-serial-work-on-the-raspberry-pi3-pizerow-pi4-or-later-models/107780#107780
The Emlid is configured with the following settings:
[details="Simple system report"] app version: 28.4-r0 enabled: true mode: client correction_input: base_corrections: io_type: serial settings: serial: baud_rate: 115200 device: ttyGS0 (USB-to-PC) send_position_to_base: true position_output: output1: io_type: serial nmea_settings: serial: gga: enabled: true update_rate: 1 gsa: enabled: false update_rate: 1 gst: enabled: false update_rate: 1 gsv: enabled: false update_rate: 1 main_talker_id: gn rmc: enabled: false update_rate: 1 vtg: enabled: false update_rate: 1 zda: enabled: false update_rate: 1 settings: serial: baud_rate: 9600 device: ttyGS0 (USB-to-PC) format: NMEA positioning_settings: elevation_mask_angle: 15 glonass_ar_mode: true gnss_settings: positioning_systems: beidou: false galileo: true glonass: true gps: true qzss: true sbas: true update_rate: 5 gps_ar_mode: fix-and-hold max_horizontal_acceleration: 1 max_vertical_acceleration: 1 positioning_mode: kinematic snr_mask: 35 [/details]
Identifying serial port label
- Open a terminal and enter the following command to capture the serial port device label e.g.
/dev/tty*
More info
- Plugin in the USB RTK module and on the Linux terminal you should see this something like the following:
[604400.525618] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device
^^^^^^^ make note of this label
NOTE
If youβre using a terminal within a docker container you may need to try running the container in privileged mode using the
--privileged
flag. Privileged mode is not a secure solution but the alternative requires you to specify the exact device and grant access to the device group. Thedevcontainer.json
with look something like the following:"runArgs": [ "--device=/dev/ttyUSB0:/dev/ttyUSB0", "--group-add=dialout", ]
Test GPS serial port
- Cancel the process from step 0. In the terminal, enter the following.
or
- You should be able to observe NMEA strings streamed to the terminal. If not, your device may need to be manually configured to do so. One, alternative method is to configure the GNSS receiver to output data via TCP. Enter the either the following commands to observe the data stream.
or
- The
str2str
rtklib CLI application is use to connect to a NTRIP Caster and receive correction data.
$ sudo ./str2str -in ntrip://username:password@hostname:port/mountpoint -out serial://ttyACM0:115200#52001 -b 1
Creating a persistent label for the RTK GNSS USB device
To use the serial device as non-root user, udev rules must be installed.
CAUTION
This serial interface label e.g.
ttyACM0
is liable to change depending on various reasons. The following commands will be used create a persistent label for serial port device and enable use by a non-root user.
- Open a terminal and enter the following follow commands.
- You should see this something like the following:
Bus 003 Device 063: ID 3032:0014 Emlid Reach
^^^^ ^^^^
vendor product
- Identify the the serial port label Identifying serial port label
- Run the udev management tool
udevadmn
to capture additional info.
- Next we need to provide the system instructions on how to treat our GNSS USB device. Here our goal is to create a persistent name for a device node by creating a symbolic link to the default device node.
Explanation
ATTRS{idProduct}=="0014", ATTRS{idVendor}=="3032":
- This helps identify a particular type or brand of device.
MODE:="666"
- β666β corresponds to read (4), write (2), and execute (1) permissions for the owner, group, and others, respectively. In this context, β666β means read and write permissions for everyone.
GROUP="plugdev":
- This specifies the group ownership of the device node. The device will be assigned to the βplugdevβ group. The βplugedevβ group is primarilty associated with serial commuication devices such as UART ports.
SUBSYSTEM=="tty":
- This condition narrows down the rule to devices in the βttyβ (terminal) subsystem. Itβs often used for serial port devices.
SYMLINK+="emlid_rtk":
- This creates a symbolic link named βemlid_rtkβ pointing to the device node. Symbolic links provide an additional name for the device, making it more user-friendly or predictable.
- Next we must reload udev rules and then trigger udev to reevaluate devices based on those updated rules. This enables our recent changes to take effect without requiring a system restart.
Re-plug in USB GNSS receiver and verify NMEA strings streamed to the terminal
Transclude of note.c
RTKLIB str2str
NOTE
Access RTK correction service and RTK correction data
- If your using a RTK correction service then we need a convenient way to store the login credentials securely. This is can be done with Environment Variables
- Alternatively you can set up your own base station (this requires an additional Receiver that can stream out RTK corrections).
- Each method will perform similarly. The limitations of each will be based on the following:
Method | Base Station Coverage | Cost |
---|---|---|
RTK Service | Typically Statewide | Free or Subscription (depending on state) |
RTK Base station | 6 mi (single band) 36 mi (multi-band) | +$300 for additional receiver and antenna |
Installing RTKLIB
- In the terminal install the rtklib
sudo apt install rtklib
- Attempt to receive RTK corrections. Note the placeholders for the required parameters are environment variables. Environment Variables discusses details on how to set these up so you donβt have to remember them.
- Single Site
- Automatic Site
IMPORTANT
Automatic site requires communication with a GNSS RTK Receiver in order to automatically send you correction data from the nearest site (mount point) or if caster is using VRS. Since there is NO target
-out
parameter provided in the example belowstr2str
will timeout as it waits to receive GNSS coordinate data. In this case the-in
-out
semantics might be confusing since the data is being exchanged in both directions between server and client.It is important to understand that if you are using Automatic Cells or VRS (see this) then a target
-out
parameter specifying a GNSS receiver and the-b 1
arguments must be passed withstr2str
or the NTRIP caster will time out.For additional details see [[#explanation-of-str2str-parameters|Explanation of
str2str
parameters]]
str2str
Testing
- Run the
str2str
rtklib CLI application
To receive Single site corrections via NTRIP and relay to USB GNSS receiver via serial
To Receive Automatic cell corrections via NTRIP and relay to USB GNSS receiver via serial
IMPORTANT
For VRS or Automatic Cell sites, just be sure to include
-b 1
with your output stream.
Note
STR2STR also implements βOutput Received Stream to TCP Portβ option like STRSVR 2.4.3 b34 https://github.com/tomojitakasu/RTKLIB/issues/573#issuecomment-760017844
- Alt. to Receive Automatic cell corrections via NTRIP and stream RTCM sentences via serial port. Stream reciever NMEA sentences via serial and TCP port 52001.
- Listen
Explanation of str2str
parameters
- -in ntrip://username:password@host:port/mount#format
- username:
- password:
- host: IP address of
- port:
- mount:
- format:
- -out serial://device_port:bitrate:parity:stopbit:fctr#output_tcp_port
- device_port:
- bitrate:
- parity:
- stopbit:
- fctr:
- output_tcp_port:
- -b 1: The
-b 1
indicates we want to use the 1st of many output streams (if multiple outputs streams are used) as the source to send NMEA GGA messages to the corrections provider (required for VRS or Automatic Cells) background
Environment Variables
There are multiple ways to do this. The most important point is to choose the way that offers the least risk from developers accidentally committing passwords or secrets to your public git repo.
https://www.linode.com/docs/guides/how-to-set-linux-environment-variables/
- Open new terminal, and append the
.bashrc
file with the following template and overwriting the characters with...
WARNING
Note login credentials environment variables have been omitted. Use this snippet as a template. Be careful NOT to upload theses to the internet. This should pasted at the bottom of the .bashrc file of the Linux machine. This will create permanent environment variables to store RTK correction service login credentials. This template has two separate ports and endpoints for connecting to a network that automatically selects a reference station and one for connecting a specific reference station.
Info
If you prefer not to store secrets as environment variables OWSAP recommends using secrets-manager such as:
AWS Secret Manager,Β Azure Key Vault,Β Google Secret Manager), or other third-party facilities (Hashicorp Vault,Β Conjur,Β Keeper,Β Confidant)
Other secret managers are:
- After saving edits, close the terminal then run
source ~/.bahsrc
- Verify environment variables
NOTE
Alternatively, you can save the environment variables to a standalone file such as
.env.dev
and then encrypt the value of the key-value pair with dontenvx. Just donβt commit your.env.keys
πThe main risk is are the following:
- You main accidentally commit
.env.dev
file decrypted.- You may accidentally commit the
.env.keys
file.- Not post-quantum safe.
Extras
- Set trace level with
-t 3
and you can read logs withcat str2str.trace
ROS2 Demo
Initial Testing
- Configure the Emlid Reach device βCorrection inputβ settings to connect to an NTRIP server via the webapp. Note this ideally should be done via
str2str
because such method would used the rpiβs network connection instead of the WiFi module on-board the Reach device itself. The main hurdle with usingstr2str
is that the command typically connects to the serial interface of the GPS device and most ROS2 packages will only connect to a GPS devicesβ serial interface. This is OK because we could provide a second serial interface via the UART interface on-board the Reach device and connect the GPIO/UART pins on to the rpi. However this demo section is simply exploring the several ways of getting RTK correction data to our GPS device and then connecting the NEMA sentences to a ROS2 node that can then publishNavSatFix
messages. - Install the
nmea_serial_driver
ROS2 package
- Echo the ROS2 topic
/fix
which contains thesensor_msgs/msg/NavSatFix
messages
- Observe the
NavSatFix
messages with covariance data.
- Takeaway: This initial test verifies the principles, but one draw back is that the RTCM messages are streamed to the Reach module via itβs onboard WiFi connection from the local network. Ideally I would prefer the RTCM messages were streamed to the Reach Module via the Raspberry Pisβ in a βPC-to-USBβ fashion. The main hurdle with this is we will need to use the UART ports on the the Reach module and Raspberry Pi to receive NMEA sentences. Using a single serial port for transmitting correction data to GNSS receiver and reading the NMEA sentences (using two separate processes) doesnβt seem possible or is error prone at this time so two serial port may be necessary.
My current understanding of possible configurations at this moment are:
- Utilize Reach Modulesβ on-board WiFi and NTRIP client software to receive RTCM and stream the receiver βPosition Outputβ to the Raspberry Pi in a βSerial-To-PCβ fashion and utilize
nmea_navsat_diver
(Initial Testing Config) - Utilize
str2str
andnmea_navsat_driver
and UART as a second channel for receiving NMEA sentences while PC-to-Serial is used for streaming RTCM Messages to the Reach Module. - Utilize
str2str
andnmea_tcp_driver
(Only after nmea_tcp_driver is rewritten for ROS2 support π) Currently started on a emlid_reach_ros2 but Iβm not sure how much work is required. - Utilize
str2str
and gpsd_client
Test 2 - gpsd
Connect emlid device with correction service via str2str and Output Received Stream to TCP Port 52001.
Verify NMEA stream is present on port 52001 with nc.
Launch gpsd with the following options. This program parses the NMEA stream on the TCP port.
-N
: donβt go into background-p
: do not reconfigure the receiver automatically-d
: set debug level, default 0-S
: set port for daemon, default 2947tcp://host[:port]
Run cgps to verify that gpsd
can relay the GPS data.
or
Output from cgps
. Notice we have a fix status.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββSeen 0/Used 0β
β Time: n/a (0) ββGNSS PRN Elev Azim SNR Useβ
β Latitude: <omitted> N ββ β
β Longitude: <omitted> W ββ β
β Alt (HAE, MSL): <omitted>, <omitted> ft ββ β
β Speed: n/a ββ β
β Track (true, var): n/a deg ββ β
β Climb: n/a ββ β
β Status: 3D RTK FIX (161 secs) ββ β
β Long Err (XDOP, EPX): n/a , n/a ββ β
β Lat Err (YDOP, EPY): n/a , n/a ββ β
β Alt Err (VDOP, EPV): n/a , +/- 150 ft ββ β
β 2D Err (HDOP, CEP): n/a , +/- 81.0 ft ββ β
β 3D Err (PDOP, SEP): n/a , +/- 149 ft ββ β
β Time Err (TDOP): n/a ββ β
β Geo Err (GDOP): n/a ββ β
β ECEF X, VX: n/a n/a ββ β
β ECEF Y, VY: n/a n/a ββ
β ECEF Z, VZ: n/a n/a ββ β
β Speed Err (EPS): n/a ββ β
β Track Err (EPD): n/a ββ β
β Time offset: n/a ββ β
β Grid Square: <omitted> ββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Test 2 Results
We demonstrated that a single connection (USB) to the emlid GPS device running the programs str2str
and gpsd
on the rpi prepare us to utilize the ROS2 package gpsd_clientto offer NavSatFix
messages.
Test 2 - gpsd_client
NOTE
These commands quickly become cumbersome to wrangle with. A more practical solution will use a single command that essentially calls the following commands sequentially. These commands are provided as an educational guide and demonstrate principles. Here is a ROS2 python launch file that streamlines the process. gpsd-client-test.py
Connect emlid device with correction service via str2str and Output Received Stream to TCP Port 9123.
Start the gspd server in the foreground (-N
) on port 9234 (-S
) and connect to the previously instantiated TCP stream on port 9123 (tcp://localhost:9123
).
Start the gpsd_client
ROS2 node and connect client to the previously started gpsd
server
IMPORTANT
No nodes (executables) are compiled for
gpsd_client
. Youβll have to load it as a component,gpsd_client::GPSDClientComponent
. And theros2 component standalone
command doesnβt support--ros-args
directly. Instead, you must use theros2 component load
command in conjunction withros2 run
to achieve a similar effect.
Start the component container.
In a new terminal, load the component into the container with the specified parameters.
Print the ROS sensor_msgs/msg/NavSatFix
topic to the terminal.
Observe, GNSS data with a valid fix is available in our ROS topic π₯³
Test 3 - ROS2 reach_ros_node
Pretesting Note: Recently a ROS1 package (reach_ros_node) became available for ROS2 for the Emlid Reach RTK Module. If this works the way I expect it, I would only need to run the str2str
command with the TCP output and the node from this package.
Test 3 Results
I encountered issues with the ros2 branch of reach_ros_node. It seems that it is not fully developed for ROS2 yet.
Testing Summary
The python ros2 launch file examples below, will perform following:
- Use
dotenx
to decryptstr2str
login parameters - Utilize
str2str
to receive correction data- inputs:
- Location Data from GNSS device
- Correction data from CORS Network
- outputs:
- Location data to CORS Network
- Location data to local Network
tcp://localhost:9123
- inputs:
- Utilize a
gpsd
server to republished the data as JSON objects- Inputs:
- Location data from local Network
tcp://localhost:9123
- Location data from local Network
- Outputs:
- JSON formatted location data to local network
tcp://localhost:9234
- JSON formatted location data to local network
- Inputs:
- Utilize
gpsd_client::GPSDClientComponent
to republish data as a ROS topic- input:
- JSON formatted location data from local network
tcp://localhost:9234
- JSON formatted location data from local network
- Outputs:
- Location data as a ROS topic
sensor_msgs/msg/NavSatFix
messages
- Location data as a ROS topic
- input:
Questions
Q1. How do you find the NTRIP Mount point for Automatic Cells or Single Sites?
- The service provider may have a number of resources such as a table specifying the connection details or an interactive map of Sites a part of the CORs Network.
- With a given IP address and Port you can use
str2str -in ntrip://<ip>:<port>
to return a Source Table with the 2nd data field specifying the mount point. For more info see - There are also several tools that enable you browse the available mount points on such as http://monitor.use-snip.com/ or srctblbrows.exe
Nomenclature
Source Table: Represents contents list of provided data by NTRIP servers
- RTK (Real-Time Kinematic): A technique used to improve the precision of GNSS data.
- GNSS (Global Navigation Satellite System): A generic term used for satellite navigation systems including GPS, GLONASS, Galileo, and BeiDou.
- PPP (Precise Point Positioning):
- Base Station: A stationary GNSS receiver used as a reference point for RTK corrections.
- Rover Station: A mobile GNSS receiver that receives corrections from a base station.
- NMEA message/string:todo
- NTRIP (Networked Transport of RTCM via Internet Protocol): A communication protocol to streaming RTCM correction data over the internet.
- RTCM (Radio Technical Commission for Maritime Services): An international standards body that defines standards such as, RTCM SC-104, which specifies a set of binary messages (aka RTCM messages) containing GNSS correction data.
- Observation Data: Raw GNSS measurements collected by a receiver, including pseudoranges and carrier phase information.
- Solution: The final output of the positioning process, providing accurate coordinates for a specific location.
- Float Solution: A position solution with a lower level of accuracy, often used in standard GPS positioning.
- Fix Solution: A high-precision position solution achieved through RTK techniques, providing centimeter-level accuracy.
- DGNSS (Differential GNSS): A technique that improves GNSS accuracy by using correction data from a reference station.
- Cycle Slip:
- ION (Institute of Navigation): A professional organization that focuses on the science and art of navigation.
- Tropospheric Delay: The slowing of GNSS signals as they pass through the Earthβs atmosphere, affecting accuracy.
- Receiver Firmware: . Embedded software of GNSS receievers.
- RINEX (Receiver Independent Exchange Format): A standard format for exchanging GNSS data between different software.
- Solution Status: Information indicating the quality and reliability of the position solution, such as βFIXEDβ or βFLOAT.β
- Ambiguity Resolution: The process of determining the integer values in carrier phase measurements to improve positioning accuracy in RTK.