How to achieve centimeter-level GNSS localization for commercial applications, when cost is a factor.
The Basics: Why Isn’t GNSS Infinitely Precise?
- Satellite inaccuracies: Satellite orbits are not known to infinite precision, for example due to varying atmospheric drag. Their atomic clocks also have nanosecond jitter and the signal path is subject to varying delay for example due to thermal cycling.
- Environmental influences: Space weather, and Earth-bound weather distort the signal as it travels to the receiver. Additionally the ground under the receiver moves ever so slightly, for example due to gravitational pull from the moon, tidal loading, especially in coastal regions. The movement of the receiver and the antenna placement also has an influence on signal propagation.
The Three Main Correction Methods
1. RTK (Real-Time Kinematic)
- How it works: The reference station’s measurement is “subtracted” from the receiver’s measurement, removing all forms of inaccuracies in one go. But the further the receiver is from the reference station, the more the environmental factors differ, so the precision gets worse.
- Accuracy: Best in class (~1-2 cm).
- Constraint: You must be within ~30 km of a reference station. The closer the better.
- Peculiarities: It’s quite easy to operate your own base station.
2. PPP (Precise Point Positioning)
- How it works: The PPP algorithm solves a system of equations involving the measurements of the signal and phase, the correction data (orbit, clock, bias), and the influence of the receiver hardware, while recursively estimating the influence of the troposphere and the signals’ cycle ambiguity.
- Accuracy: Good (~10 cm).
- Constraint: Convergence time of a few minutes (~15-30 min) to reach that accuracy.
3. PPP-RTK
- How it works: PPP-RTK follows the same approach as PPP, but combines that with data from a regional network of reference stations transmitting model parameters for ionosphere and troposphere. As a bonus, not having to estimate influences from ionosphere and troposphere eliminates the major contributors to the high convergence time of PPP.
- Accuracy: Better than standard PPP, but generally not as good as pure RTK (~3-5 cm).
- Constraint: PPP-RTK is the “newest” evolution of precise positioning. It can be harder to find (or more costly to use) correction data services and GNSS modules supporting it. There also exist several competing correction data formats (RTCM-SSR, SPARTN, SSRZ) which results in incompatibilities between service providers and modules.
The Data Dilemma: Sourcing Corrections in Germany
RTK: The SAPOS Maze
- Cost: 10 €/month per device.
- Cost: Most states provide this for free under Open Data regulations.
- Drawback: Not all states are free. Rhineland-Palatinate charges ~120 €/year per device (the same as ZSS-SAPOS), Bavaria charges ~20 €/year per registration, and Mecklenburg-Vorpommern has a 100 € one-time fee per registration.
PPP: The Global Player
- Cost: Free.
- Benefit: It comes with comparatively low convergence time (~5 min) and is delivered via satellite.
- Drawback: With officially <20 cm, though often better in practice, it’s not as precise as other PPP solutions. It currently “delivers Service Level 1 only with a reduced performance” with “Full Service Declaration targeted in Q1-Q2 of 2027”. It needs a compatible module.
PPP-RTK: The GEPOS Alternative (Internet or DAB+)
- Cost: Free.
- Accessibility: No registration required.
- Benefit: GEPOS is not only available via internet, it’s also broadcast via DAB+, which has good coverage in Germany even in rural areas.
- Drawback: This service uses the niche SSRZ format which is not compatible with any available GNSS module. Instead a closed source converter tool is provided, though only for Android and Windows.
Use-Cases:
Which Path Should You Choose?
Scenario A:
You need the absolute best precision (1–2 cm)
- Small Area: If you operate in a small area, consider using federal SAPOS or operate your own reference station.
- Large Area + Small Fleet: If you have very few devices, save yourself the engineering headache and buy the ZSS-SAPOS service (10 €/month/device).
- Large Area + Large Fleet: If you have many devices and you are willing to skip coverage in Rhineland-Palatinate, use the federal SAPOS instances. For this to work you will need to write some logic to switch instances based on location, because the federal VRSs will only work with their respective reference stations. (Note: We did not go this path and there are potential unknowns in the federal SAPOS instances and their administration, so test and evaluate properly before going this route.)
Scenario B:
You don’t need the highest precision (~20 cm)
Scenario C:
You operate in rural areas with poor internet
- RTK with your own reference station, sending corrections via radio.
- PPP-RTK via DAB+, if you can work around its format conversion issues by using Android or Windows.
- PPP with GALILEO HAS via satellite.
The Verdict
Bonus: Example RTK setup
using federal SAPOS (Berlin) and NEO-F9P module
- Registering on a federal instance: On sapos.de you can find a list of all federal instances. The registration process differs and in some states it’s not even needed. We registered for federal SAPOS in Berlin via the [online form]. It took one business day to receive our login data and another day for the login to be activated.
- Setup the hardware: For testing we used a Holybro H-RTK NEO-F9P Rover. We connected the antenna via a USB-UART-adapter to a development machine running Linux Mint.
- Start the GPS client: We want to use
gpsd, so we checked its man page. Usually it suffices to pass the NTRIP caster URLsapos-be-ntrip, port2101, and VRS mount pointVRS_3_4G_BE; together with login information (USERNAMEandPASSWORD) togpsd, like so:ntrip://USERNAME:PASSWORD@sapos-be-ntrip.de:2101/VRS_3_4G_BE; The full command looks like this:
$ sudo gpsd -n -N -D 4 -F /var/run/gpsd.sock /dev/serial/by-id/USB-UART-adapter ntrip://USERNAME:PASSWORD@sapos-be-ntrip.de:2101/VRS_3_4G_BE 2>&1 | tee gpsd.log
This failed on the first try, becausegpsddoesn’t support the RTCM 3.4 format yet, which this SAPOS instance uses. Luckily RTCM is backward compatible andgpsd; already supports RTCM 3.3, so it was a simple fix that we submitted upstream. Now runninggpsdand checking withgpspipewe got:$ gpspipe -w | grep –line-buffered TPV | jq –unbuffered -c '{status, lat, lon, alt, ecefpAcc, ecefvAcc}'
{"status":2,"lat":52.520843100,"lon":13.409317600,"alt":240.8120,"ecefpAcc":4.5000,"ecefvAcc":0.3100}
{"status":2,"lat":52.520843100,"lon":13.409317500,"alt":240.8080,"ecefpAcc":4.5400,"ecefvAcc":0.3000}
{"status":2,"lat":52.520843100,"lon":13.409317500,"alt":240.8080,"ecefpAcc":4.5400,"ecefvAcc":0.3000}
{"status":2,"lat":52.520843100,"lon":13.409317500,"alt":240.8400,"ecefpAcc":4.5800,"ecefvAcc":0.3100}
{"status":4,"lat":52.520817200,"lon":13.409312700,"alt":239.6610,"ecefpAcc":1.1900,"ecefvAcc":0.3100}
{"status":4,"lat":52.520795700,"lon":13.409304900,"alt":236.4270,"ecefpAcc":0.7700,"ecefvAcc":0.3100}
{"status":4,"lat":52.520788400,"lon":13.409300300,"alt":235.1760,"ecefpAcc":0.6900,"ecefvAcc":0.3000}
{"status":4,"lat":52.520788400,"lon":13.409300300,"alt":235.1760,"ecefpAcc":0.6900,"ecefvAcc":0.3000}
{"status":4,"lat":52.520784300,"lon":13.409298700,"alt":234.6180,"ecefpAcc":0.6600,"ecefvAcc":0.3200}
{"status":4,"lat":52.520783700,"lon":13.409298200,"alt":234.3460,"ecefpAcc":0.6600,"ecefvAcc":0.2600}
{"status":4,"lat":52.520784100,"lon":13.409296900,"alt":234.2430,"ecefpAcc":0.6200,"ecefvAcc":0.1100}
{"status":4,"lat":52.520785200,"lon":13.409297100,"alt":234.1680,"ecefpAcc":0.5500,"ecefvAcc":0.1600}
{"status":4,"lat":52.520785200,"lon":13.409297100,"alt":234.1680,"ecefpAcc":0.5500,"ecefvAcc":0.1600}
{"status":3,"lat":52.520826800,"lon":13.409302700,"alt":239.4330,"ecefpAcc":0.0200,"ecefvAcc":0.1000}
{"status":3,"lat":52.520826700,"lon":13.409302800,"alt":239.4290,"ecefpAcc":0.0200,"ecefvAcc":0.1900}
{"status":3,"lat":52.520826600,"lon":13.409302800,"alt":239.4250,"ecefpAcc":0.0200,"ecefvAcc":0.1900}
{"status":3,"lat":52.520826700,"lon":13.409303000,"alt":239.4270,"ecefpAcc":0.0200,"ecefvAcc":0.1300}
{"status":3,"lat":52.520826700,"lon":13.409303000,"alt":239.4270,"ecefpAcc":0.0200,"ecefvAcc":0.1300}
Interpretation:status(codes aregpsdspecific): 2 = DGNSS, 4 = RTK float, 3 = RTK fix;lat/lon/alt: latitude, longitude, altitude;ecefpAcc: position accuracy estimate in meter;ecefvAcc: speed accuracy estimate in meters per second.4. Verify positioning accuracy: We didn’t do this, but if you really want to know the real accuracy of your solution, you will have to find a public reference station with known coordinates that are more precise than what your solution can provide. In Germany there are public reference points, so called “Geodätische Referenzpunkte” or “Geodätische Grundnetzpunkte“. The location of these is known to the centimeter and they can be used to measure the RTK positioning accuracy. [Wikipedia has a list of all public reference points.][/vc_column_text][/vc_column][/vc_row]







