From Meters to Centimeters: How RTK Correction Data Sharpens GPS Accuracy

You’ve probably noticed that your GPS can tell you you’re somewhere in the area, but not exactly where you are. That’s fine when you’re ordering pizza, but not when you’re flying a drone or programming a robot to dock itself precisely. A few meters, even centimeters of error might mean a missed landing pad, a wrong turn, or a confused machine. This is exactly where RTK — Real-Time Kinematic positioning — steps in and makes GPS behave like a pro.

In this post, we’ll go beyond the surface. We’ll look at what RTK really is, how it works behind the scenes, what “RTK correction data” means, and how that data is actually received from a base station or server. By the end, you’ll know how RTK transforms an ordinary GPS system into a centimeter-accurate positioning tool — and why it matters.

Why GPS Isn’t Perfect

To understand RTK, we first need to accept that normal GPS isn’t always telling the truth. GPS receivers calculate position using signals from satellites orbiting Earth. These satellites constantly broadcast data containing their positions and the exact time the signal was sent. Your receiver listens to multiple satellites at once, measures how long each signal took to arrive, and calculates where you must be based on those distances.

That’s the theory. In practice, the signals pass through the atmosphere, bounce off surfaces, and are subject to tiny timing errors in both the satellite and receiver clocks. Even though those errors are small — often just nanoseconds — they translate to meters of inaccuracy on the ground.

So, your GPS might tell you that you’re at coordinates (let’s say) 51.5034° N, 0.1276° W, but in reality, you’re standing five meters away. That’s fine for navigation, but unacceptable for tasks that need precision.

What is RTK?

RTK (Real-Time Kinematic) is a technique that improves GPS accuracy by using correction data from a base station — a GPS receiver placed at a known, fixed location. The base station receives the same satellite signals as your GPS device (called the rover). Because the base knows its real coordinates, it can compare the GPS-calculated position with its true position and figure out how wrong the GPS data is. Those small discrepancies are the “corrections.”

rtk

These corrections are then sent from the base station to the rover. The rover applies the same corrections to its own GPS readings, which removes most of the shared errors caused by atmospheric delay, satellite clock drift, and other disturbances. As a result, the rover’s position becomes much more accurate — often within a few centimeters.

You can think of it like this: imagine you and a friend are both using slightly unreliable stopwatches to time the same race. Your friend’s stopwatch is known to be exactly 0.2 seconds slow. If you compare your readings, you can adjust your own and get a far more accurate time. RTK works on the same principle — the base’s known position allows the rover to fix its own measurements in real time.

Receiving the RTK Correction Data: NTRIP, Radio, or Local Base

The corrections that the base station generates are transmitted as structured messages, usually following a standard called RTCM (Radio Technical Commission for Maritime Services). These messages contain detailed information about how much error the base station detected in each satellite signal.

The rover doesn’t need to understand the physics of what caused the error; it just applies the corrections to its own satellite data as they come in. This process happens continuously — every second or even several times per second — so the rover’s position is constantly refined as it moves.

Now, how does this data actually get from the base to the rover? There are a few methods. The simplest setup is a local RTK base station, where the base sends data to the rover directly via a radio link. This works great for smaller, localized setups, like a farm or a construction site, where both devices are within a few kilometers of each other.

However, in most modern applications, correction data travels over the internet using a system called NTRIP, short for Networked Transport of RTCM via Internet Protocol. NTRIP is basically a specialized streaming service for RTK corrections. A central server, called the caster, hosts multiple data streams, each coming from a base station. Each stream is called a mountpoint, and your rover connects to the caster like a client logging into a server. Once connected, it receives a live feed of correction data that matches its region.

This means you don’t need your own physical base station. As long as you have internet access, your rover can connect to a public or commercial NTRIP caster and receive real-time corrections from a nearby base station — possibly one run by your country’s geospatial agency.

Getting RTK correction data using Python

In the following Python code, I am using rtk2go.com which is a free RTK server. I build GGA data using fake coordinates (you may use your real-time data from GNSS receiver) and send it to the server. The server returns the correction data in form of bytes:

import socket
import base64
import time

# NTRIP caster details
NTRIP_HOST = "rtk2go.com"
NTRIP_PORT = 2101
MOUNTPOINT = "KALB"         # your mountpoint
USERNAME = "your_username@gmail.com"
PASSWORD = "none"           # RTK2go uses "none" but still requires the field

def build_gga():
    """
    Create a fake but valid NMEA GGA sentence.
    """
    lat = "your_latitude"
    lat_dir = "N"
    lon = "your_longitude"
    lon_dir = "E"
    fix_quality = "1"
    num_sats = "08"
    hdop = "1.0"
    altitude = "100.0"

    gga = f"GPGGA,000000,{lat},{lat_dir},{lon},{lon_dir},{fix_quality},{num_sats},{hdop},{altitude},M,0.0,M,,"
    checksum = 0

    for c in gga:
        checksum ^= ord(c)

    return f"${gga}*{checksum:02X}\r\n"


def connect_ntrip():
    auth = base64.b64encode(f"{USERNAME}:{PASSWORD}".encode()).decode()

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((NTRIP_HOST, NTRIP_PORT))

    request = (
        f"GET /{MOUNTPOINT} HTTP/1.0\r\n"
        f"User-Agent: NTRIP PythonClient/1.0\r\n"
        f"Authorization: Basic {auth}\r\n"
        f"Ntrip-GGA: {build_gga().strip()}\r\n"  # some casters accept inline GGA
        f"\r\n"
    )

    s.send(request.encode())
    return s


def main():
    print("Connecting to NTRIP caster...")
    sock = connect_ntrip()

    print("Simulating GPS receiver with dummy GGA...")
    gga_timer = time.time()

    while True:
        # send periodic GGA
        if time.time() - gga_timer > 5:
            gga = build_gga()
            print("[SEND] GGA:", gga.strip())
            sock.send(gga.encode())
            gga_timer = time.time()

        # receive RTCM
        data = sock.recv(4096)
        if not data:
            print("Disconnected.")
            break

        print(f"[RTCM] Received {len(data)} bytes")
        print("\n",data)
        print("\n")


if __name__ == "__main__":
    main()

IMPORTANT: This script is intentionally very basic — it’s not meant to give you a working RTK solution, but rather to help you see how the NTRIP process works and what RTCM correction data actually looks like when it arrives at the receiver. You can think of it as a “network-level demo.” It connects to a caster, sends a simple GGA sentence, and prints whatever RTCM packets the server streams back. But the important thing to understand is that you cannot apply these correction messages directly to your coordinates in Python. RTCM is a tightly structured binary protocol designed to be consumed by specialized GNSS hardware, not manually decoded into latitude and longitude.

rtk
Source: https://www.ardusimple.de/product/simplertk2b-basic-starter-kit-ip65/

To actually use the RTK corrections, you need a proper GNSS receiver that supports RTCM input and can perform the internal math required to apply these corrections in real time. Devices like the u-blox ZED-F9P, Trimble, Septentrio, and other industrial-grade receivers are built for this. They take the raw satellite measurements, ingest the RTCM correction stream, and compute a high-precision RTK fix internally. Your Python script (or any external software) never has to “apply” the corrections yourself — the receiver does all the heavy lifting and simply outputs corrected, centimeter-accurate positions.

Summary

RTK might sound complex, but once you grasp the idea of a base station correcting a rover’s GPS data in real time, it becomes simple. The base knows exactly where it is, the rover doesn’t, and the two work together so the rover stops guessing. Whether the correction data travels through a local radio link or via an internet-based NTRIP server, the principle is the same: use one accurate reference point to improve another.

If you already use tools like gpsd to manage GPS data, you’re halfway there. RTK correction data can be piped into gpsd through supporting tools like RTKLIB or direct RTCM streams, giving your GPS subsystem an instant accuracy upgrade.

In short, RTK doesn’t replace GPS — it teaches it some manners. It takes the “roughly here” signal you’re used to and turns it into “exactly here.” Once you see the difference, you won’t look at regular GPS the same way again. If you missed out on how to parse GPS data using Python, head over to my blog Beginner’s Guide to gpsd: A Practical Introduction to GPS Data Handling in Python.

If you do possess one of the ublox GNSS receivers and are willing to try it out, I would recommend this article: How to integrate u-blox ZED-F9P GNSS/RTK receiver into ROS 2. Not only will you receive RTK corrected GNSS data but also will be implementing it in ROS2. This means that the coordinates will be directly available on a ROS2 topic.

Try it out and share your results with me on Instagram @machinelearningsite, or feel free to just ping me. Have fun coding. Peace!

Leave a Reply