Using RTK
Real-Time Kinematic (RTK) positioning is a precision positioning technology, which uses two GNSS receivers: a base station with a precisely known position which provides correction data in the form of RTCM messages, and a rover, which can use this correction data to determine its position with centimeter-level accuracy. The distance between the base and the rover is limited to about 10-20 kilometers.
The requirements for an RTK base station and a precision time server are similar. GNSS receivers that perform well for RTK typically also provide good timing performance, and because RTK is a much larger market, RTK-capable receivers often offer better value for timing applications. Both applications require a stationary antenna with a precisely known position. SatPulse enables a single GNSS receiver to be used simultaneously for both purposes. Running an RTK base and contributing to a public caster such as RTK2go is a good way to make your GNSS receiver as useful as possible. RTK is also useful for determining the precise antenna position needed for GNSS time mode.
This guide shows how to configure SatPulse as an RTK base station, and also how you can use SatPulse as a rover to verify the correct operation of the base station. This works best with u-blox receivers; with other receivers, you will need to use other tools for some of the configuration. I developed this guide with a u-blox ZED-F9T as the base and a u-blox ZED-F9P as the rover.
Base station
Enabling RTCM messages
If you have a u-blox receiver that supports RTCM (e.g. ZED-F9P or ZED-F9T), SatPulse makes it easy to configure your receiver to output RTCM messages. If you have a non u-blox receiver, you will have to use another program to enable the appropriate messages.
Edit the [gps]
table of /etc/satpulse.toml
so it includes the following lines:
[gps]
config=true
rtcmOutput=true
This will configure a sensible set of messages:
- 1005 for the antenna reference position of the base station
- MSM4 messages for every major GNSS constellation that is enabled; if MSM4 is not supported (e.g. on a ZED-F9T with some firmware versions), MSM7 will be enabled instead. The MSM4 and MSM7 messages are, respectively:
- GPS: 1074 and 1077
- GLONASS: 1084 and 1087
- Galileo: 1094 and 1097
- BeiDou: 1124 and 1127
- 1230 (GLONASS code-phase bias) messages if GLONASS is enabled
These are all enabled at 1Hz.
You can alternatively use satpulsetool gps --rtcm-out
for a bit more control. The rtcmOutput=true
configuration in the TOML file is equivalent to satpulsetool gps --rtcm-out auto
.
Other receiver configuration
RTCM messages consume bandwidth, so you should enable a sufficiently high baud rate. Assuming the receiver is also being used for timing, it is important that the RTCM messages do not consume such a high percentage of the bandwidth that timing messages are significantly delayed. I therefore recommend using a high baud rate such as 115200. You can use satpulsetool gps --speed
to configure this.
You should also think about the signals that should be enabled. Generally, more is better for RTK. You can specify the constellations that should be enabled using satpulsetool gps --gnss
. For example, satpulsetool gps --gnss GPS,GAL,BDS,QZSS
would enable GPS, Galileo, BeiDou and QZSS.
Making RTCM messages available over TCP
You also need to configure satpulsed to proxy RTCM packets from the receiver over TCP. This is done by adding a section like this to /etc/satpulse.toml
.
[[proxy.tcp]]
listen = ":2009"
protocol = "RTCM"
This says to make RTCM packets available on port 2009.
Rover
Using satpulsed
You can use satpulsed on the rover side also, for example to determine the fixed position of the antenna using an RTK base station.
First stop the satpulse service. Assuming your receiver is at /dev/ttyACM0
sudo systemctl stop satpulse@ttyACM0
Receiver configuration for u-blox
For this experiment, we will turn off configuration by satpulsed and instead do configuration with satpulsetool.
First edit /etc/satpulse.toml
to disable configuration by satpulsed
For example:
[gps]
config=false
Next use satpulsetool to undo any non-persistent configuration satpulsed did. Assuming your receiver had previously been using 9600 baud do:
satpulsetool gps -d /dev/ttyACM0 -s 9600 --reload
Then set the receiver to use the speed a suitably high speed, e.g. 115200
satpulsetool gps -d /dev/ttyACM0 -s 9600 --speed 115200
I also suggest enabling only RMC and GGA messages.
satpulsetool gps -d /dev/ttyACM0 -s 115200 --nmea-out RMC,GGA
Daemon configuration
Now edit /etc/satpulse.toml
to do the following
- specify the serial speed that you have configured, e.g. 115200
- make NMEA output available on a TCP port, e.g. 2007
- give serial port access via a Unix domain socket
For example:
[serial]
device = "/dev/ttyACM0"
speed = 115200
[[proxy.tcp]]
listen = ":2007"
protocol = "NMEA"
[[proxy.socket]]
path = "/var/run/satpulse.sock"
Verify configuration
Now you restart the satpulse service:
sudo systemctl start satpulse@ttyACM0
Now ensure you have netcat installed
which nc
If not, install openbsd-netcat:
sudo apt install openbsd-netcat
Now if you do
nc localhost 2007
you should see some NMEA sentences (including GGA and RMC).
The 6th comma-separated field of GGA sentences (where $xxGGA counts as field 0) should be 1 or 2 at this point.
Supply RTCM corrections
For this we will need the socat package.
sudo apt install socat
First make sure you have enabled a high baud rate using satpulsetool gps --speed 115200
.
Assuming your base is on the local network as ptp.lan
, you can run the following command to forward the RTCM data from TCP port on the base to the rover:
socat UNIX-CONNECT:/var/run/satpulse.sock TCP:ptp.lan:2009
Here the port 2009 must match what you configured on the base. This command should just run silently until you interrupt it.
Now in another window, do
nc localhost 2007
If everything is working, then the 6th field of the GGA sentences should change to 5, indicating a floating RTK solution. This should take less than 30 seconds assuming reasonably good conditions. After a few minutes, the 6th field should change again to 4, indicating a fixed RTK solution.
Extracting precise position
The GGA line now gives the precise position:
- field 2 is ddmm.mmmmm
- field 3 sign of latitude, N positive, S negative
- field 4 is the longitude ddmm.mmmmm
- field 5 is sign of longitude, E positive, W negative
- field 9 is altitude above mean sea level
- field 11 is geoid separation
To get LLH coordinates, you need to
- convert ddmm.mmmm degress/minutes into decimal degrees dd + mm.mmmmm/60
- add the altitude above mean sea level to geoid separation to get height above ellipsoid
You can then stick this into an online LLH to ECEF converter like ConvertECEF (select HAE in the altitude box).
You could then use this ECEF position as the fixed position for time mode.
Using NTRIP
In the above example, we have used a direct, unsecured TCP connection between the base and rover.
In production, it is more common to use NTRIP. With NTRIP, there are three roles
- a server, which is connected to the receiver on the base
- a client, which is connected to the receiver on the rover
- a caster, which can relay data between multiple servers and clients
We can experiment with NTRIP by installing rtklib on the base and rover.
sudo apt install rtklib
On the base, we can run a simple NTRIP caster using the str2str program from rtklib
str2str -in tcpcli://localhost:2009 -out ntripc://jjc:xyzzy@:2101/bkk
Here
- 2009 is the TCP port on the base over which satpulsed is providing RTCM messages
ntripc://
says to run an NTRIP casterjjc
is the usernamexyzzy
is the password- 2101 is the default port for NTRIP
bkk
is the mount point
To use NTRIP on the rover with satpulsed, you would need a writeable TCP connection
(which is not secure). Add this to /etc/satpulse.toml
[[proxy.tcp]]
listen = ":2006"
On the rover, we can then run a simple NTRIP client using the str2str program:
str2str -in ntrip://jjc:xyzzy@ptp.lan:2101/bkk -out tcpcli://localhost:2006
Here
ntrip://
says to run an NTRIP clientjjc
is the username to give to the casterxyzzy
is the password to give to the caster2101
is the port of the caster to connect toptp.lan
is the hostname of the casterbkk
is the mount point of the caster to connect to- 2006 is the port on localhost to which to send RTCM messages