Differential GPS (GNSS RTK)
Accurate navigation for outdoor rover using rtklib.

Wikipedia.org: Differential Global Positioning System (DGPS) is an enhancement to Global Positioning System that provides improved location accuracy, from the 15-meter nominal GPS accuracy to about 10 cm in case of the best implementations.
Wikipedia.org: Real Time Kinematic (RTK) satellite navigation is a technique used to enhance the precision of position data derived from satellite-based positioning systems (global navigation satellite systems, GNSS). The nominal accuracy for these systems is 1 centimetre ± 2 parts-per-million (ppm) horizontally and 2 centimetres ± 2 ppm vertically.

Differential GPS

A base station GPS at a fixed and known location is used in conjunction with the GPS on the rover.

At the risk of over-simplifying, the base station GPS and the rover GPS suffer the same atmospheric distortions, but the exact position of the base station is known. Therefore the error on the base station (due to the atmospheric distortions) is known. Hence this error can be applied to the rover GPS reading, and a very accurate reading obtained.

A far better explanation than this is at RTK Explorer.


CSG NEO-M8T U-Blox GNSS (GPS)Raw-mode capable of GNSS, supported by RTKLIB. Two of these will required for DIY RTKLIB / Kinematics. Note that these were the first ones used, but they were later replaced with the (more expensive and L1/L2 capable) M8P-based ones.
BoxA box for the mast head on the rover. Get one with a non-clear lid.
150mm PVC capBase of roof-top enclosure for GPS base station antenna.
150mm PVC pipeSides of roof-top enclosure for GPS base station antenna. Ironically only about 6m is needed, and 150mm is quite expensive in standard lengths. Get an off-cut from the plumbing store.
150mm PVC threaded CapTo attach lid of roof-top enclosure for GPS base station antenna..
150mm PVC threaded endTo make lid of roof-top enclosure for GPS base station antenna..
Raspberry PisOne for the base station, and one for the rover. These can multitask with other things (security lighting etc).

Base station

The GPS base antenna is mounted in a 150mm plumbing pipe and fittings - the bottom is a glued cap, and the top is a screw cap. This actually makes a pretty expensive box, but it will be water-proof and last pretty much forever. (Again this was later replaced with the M8P version).

Water tight .. within reason. A USB cable goes out the bottom, and through the shed roof. It is protected from the sun by a length of irrigation tube. It's tempting to make the enclosure water-tight / air-tight, but the reality is that even changing air pressure (think hot day, cold night), will eventually result in moisture-ingress. A small hole at the bottom (or even a tiny gap around the antenna cable) will allow it to breathe.

The USB cable through the roof goes to the Raspberry Pi in the garden shed (which also performs a number of other tasks, including controlling the irrigation, intruder alarm, automatic light switch, solar charge monitor etc).

Mast head for the rover

The GNSS (GPS) is placed in an elevated plastic box on a mast made from PVC plumbing pipe and appropriate joiners, using as little metal as possible.

An LSM8DS0 IMU is also mounted in the mast head to distance the magnetometer from the metal of the rover body.

As little metal as possible has been used in the mast head box to avoid magnetic or RF interference. The bolts to hold the GNSS and IMU in place in this design are plastic. The PVC pipe and components use plumbing glue.

The elevated mast is a trade-off: The LidarLiteSweeper should be both as low as possible (to detect low obstacles), but be the highest point of the rover to get a 360° view. The mast will get in the way of the scanning, and will probably require software programming to remove it from view. This will create a blind-spot. If the mast is behind the LidarLiteSweeper, at least the blind spot will be behind the rover and not in front. However it does force a directionality into the rover, which in principle could be orientation-agnostic.

Consider, for instance a rover pushing a reel-mower (one of those old ones which powers the blades from being pushed by the operator). It would run forwards to mow grass, but backwards when moving to position, returning to be recharged etc. Orientation-agnosticism would be important there.

The lid in this image is clear, but after debugging and testing, the lid should be replaced with a opaque one to avoid the greenhouse effect - particularly as the GPS antenna is black.

Software libraries

RTKLIB - for the GNSS handling (specifically the str2str and the rtkrcv programs).
RTKLIB files on Raspberry Pi

GNSS (GPS) L1 only

RTKLIB requires a GNSS ground station receiver, as well as a GNSS on the rover.

It requires a quality GNSS which can receive phase information and transmit raw data.

This project initially used two "NEO-M8T U-BLOX" from CSG Shop (with built-in antenna). These are not high enough quality for high precision, but they are affordable, and pretty good for racing rovers around the farm.

Conclusion: The NEO-M8Ts are only a single frequency (L1). They are not actually up to the task of precision location. They will do reasonably well in most cases (probably well enough for a large mower in a paddock), but not for a small mower with a 20 inch blade, or for controlling a tractor to do precision rows. These tasks require a higher cost GNSS receiver.


This little gem is an M8P-based version which does L1 and L2.

They are around twice the price of the initial M8T version, but give a higher accuracy.


Recommendation / Experiences with CSG Shop
All four of the GPS antennas for this project were purchased from CSG Shop. It's always a bit of a worry sending significant sums of money to an eastern-European country, but there aren't that many places that sell these. My experience is that
  • They are a bit slow (but mail in that part of the world probably is a bit slow).
  • They don't give the proper tracking number immediately.
  • They will give the tracking number later if you ask for it.
  • The gear has always showed up eventually.
In summary - these are the good guys. I would buy from them again if I needed equipment.


RTKLIB is tricky to get going, and could have a whole web-site itself. Actually it does, and it's still confusing.

Get started by doing this

Buy a suitable GNSS which is supported by RTKLIB.
Download RTKLIB_bin from github https://github.com/tomojitakasu/RTKLIB_bin (branch rtklib_2.4.3). This will get you started on Windows.
Copy this this on a Windows box and run it. Get it working with the GNSS device in SINGLE mode. Play with the pretty displays etc.
If you get lucky and get a corrective feed (eg Auscors) locally, you might be finished.
If you decide you need your own base station, buy another suitable GNSS (the same type as the first is recommended by others, but probably not essential).
Install this GNSS and RTKLIB on another Windows box, and network them, one as rover, one as base station etc.
When you graduate to a real operating system (Linux) download http://github.com/tomojitakasu/RTKLIB (branch rtklib_2.4.3) and compile and install str2str and rtkrcv.
Then install them onto Linux and use the command-line options to get str2str and rtkrcv going. Play around.
Study and understand the network diagram above.
The best way to set up the configuration file on Linux is to set it up on Windows (using the GUI), and copy it to Linux.
Get inspiration from this configuration file (noting that some hardwired coordinates have been removed).
Get further inspiration from these configuration files.
Useful files are here, including the AAAREADME.txt file.

Walk around the yard (M8T)

The light green dots are the readings obtained from walking around the yard carrying the mast (attached to Raspberry Pi and a battery, obviously), superimposed over a map of the house paddock (ignore the solid blue line, it's a route for another experiment).

The GPS did pretty well in this test.

The missing dots on the east side of the garden shed (the eastern black square) are due to the WiFi signal being lost (the shed blocked the WiFi antenna, which is on the top of the homestead) as I walked past - okay for me, but a serious problem for a rover.

There are at least three other short (1s) drop-outs on the south and south-east of the walk. A better WiFi antenna on the rover largely solved this problem, though there are still times when rtklib can't find a solution.

First successful house circumnavigation (M8T)

This is a geo-log of the first time the rover followed a pre-programmed route around the house without being rescued along the way.

At the time it was only using GPS (U.S.) satellites not the Glonass (Russian) satellites, so the readings are a bit rough.

The thin blue path is the programmed course (starting at the north, going around the house clockwise), and the thicker light-green path (actually series of dots) is path the rover 'thinks' it took (according to the GPS logs).

The red blob north of the house is the final position of the rover (stopped after completing the course), and the tail at the start of the course is the path the rover took (autonomously) moving to the initial position to start the course.


There are some interesting features here.

1. This is the path the rover thinks it took - not where it actually went. In particular, there are some 'spurs' visible in the path up the western driveway, which did not actually occur in the path it took. The GPS reading jumped to the side, and rover 'corrected'.

2. The rover consistently overshoots when the course has a sharp corner. This is partly the crude path-following program (it doesn't change direction until it reaches the end of a line segment), and also due to the rtklib solution only arriving once per second - and often some time after the actual measurements if the rtkrcv output is to be believed. Hence the rtklib solution data could be up to two seconds out of date. so the rover frequently passes the turning point before it knows to start turning. Clearly the overshoots will be worse for a faster rover.

RTK results (M8T)

In this experiment, the rover was left stationary for one hour, and the solution results mapped (units are metres). The first five minutes of results were removed (to let things warm-up first). The drift is around 60mm. Not bad!

More RTK results (M8T)

Here we have been running (stationary rover) for several hours, and almost all solutions are within 8cm. Not bad.

We can pick up the Glonass (Russian) satellites. The NEO-M8T will apparently pick up the Galileo satellites, but needs a newer firmware version and (disappointingly) U-BLOX don't seem keen to make this upgrade available to their user base.

More RTK results (M8P)

Accuracy test with rover and base both M8P based antennas. Note that even with the more accurate antennas, we will get the occasional glitch (where the location jumps off the bottom of the screen).
In fairness, though, it (almost) always knows when it has goofed. The outliers are (almost) always tan instead of green - indicating 'FLOAT' not 'FIX'. That is, RTKLIB knew it was a poorer measure.
A sample over some hours.

Software for rover

A truckload of software to make this do anything sensible.

With regards navigation in particular, there are multiple inputs coming in from different sources which give clues about location, velocity, orientation and spin. Don't expect consistency between these. Don't even expect consistency between different GNSS streams (eg the velocity/heading is based on Doppler measurements, but the location is computed from timing information. Location may jump around madly even when velocity stays correct). This is a very interesting and challenging problem which might best be classified as 'open ended'.

Useful rtklib tricks

The robot program connects directly to the rover str2str on port 2832 to get the raw (NMEA) feed from the GNSS. This raw feed is used for getting speed/tracking/climb information and also the date and time. Of course the binary UBLOX packets are mixed with it, so it requires filtering to get the NMEA only information.
telnet roverhostname 2833 will let the operator see the feed from the RTK system. Good for debugging.


Currently the RTK position quality goes to FLOAT, but hardly ever goes to FIX, however the accuracy still seems to be pretty good - at least good enough for some agricultural purposes, though possibly not good enough for a domestic lawn-mower. 'Agricultural GPS' is normally expected to be around 100mm. A serious domestic mower will need to be better than 30mm to avoid the wife's flower beds.

Using an NTRIP caster

There are a number of publicly accessible NTRIP casters on the interweb which broadcast base-station data which can be used instead of installing your own base station. With permission of Geoscience Australia, I tried using AUSCORS NTRIP broadcaster and read data from a server around 30km away.

The results, in one word: disappointing, with 2m drift common. The results are so disappointing, I have not even graphed them here [update: I think the problem was a misconfiguration with the Russian satellites, but I have not revisited this]. Maybe there is a source of error here, but overall I suggest using your own base station if you are serious about robot navigation.

The future

    Retry a non-local base station (like the Geoservices Australia one based on the internet), with proper Glonass settings.
    There are GNSS base stations on the interweb which transmit RTCM3. These can be used if they are nearby, and if good internet is available. This feed can be used instead of installing a local RTKLIB base station.
    Try out the new (experimental) SBAS feed in Australia. I am a bit far out of town to really take advantage of this, but if you in town or lucky enough to be close to a station ..


None really, except ..

The system goes to FLOAT solution quite quickly, but only seldom goes to FIX. This is not a problem in itself, but others seem to be able to get the system to FIX, and have pretty much stay there. I have not achieved this with these GNSS units. Those who have enjoyed greater success also seem to be blessed with deeper pockets than yours truly - they have purchased more expensive GNSS units.

The M8T units will get a good solution for the price, but not get truly high-precision RTK positioning - you simply need more expensive (multi frequency) GNSS receivers such as the M8P.

Cool links

Leave a comment

Something I'm doing wrong? Solved my problems? Got a better idea? Got a similar problem?
Think I might have solved your problem? Ninety-nine problems, but your robot ain't one? Say so ..