Javad Taghia
Published © MIT

Centimeter-Level Accuracy - NTRIP Over Internet

Want to get centimetre accuracy tracking for your application. If you have internet and have budget of about USD200-300, you can do it.

AdvancedFull instructions provided16 hours630
Centimeter-Level Accuracy - NTRIP Over Internet

Things used in this project

Hardware components

u-blox ZED-F9P-01B-01
×1
u-blox GNSS Multi-Band Magnetic Mount Antenna - 5m (SMA)
×1

Software apps and online services

u-blox u-cente

Story

Read more

Schematics

Block diagram

Code

Plot GNSS

Python
Python

You need to have the following to run Python codes.
matplotlib
pyproj
pyubx2
pyserial
requests
utm
pyrtcm
pandas
pymongo
geopy
import serial
from pyubx2 import UBXReader, UBXMessage
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np

class UBXHandler:
    """
    Standalone UBXHandler class for handling UBX protocol messages, designed to run on Linux.
    """

    def __init__(self, port='/dev/ttyACM0', baudrate=9600):
        self.serial_port = serial.Serial(port, baudrate, timeout=3)
        self.ubx_reader = UBXReader(self.serial_port, validate=True)
        self.positions = []  # Store (latitude, longitude, height) tuples
        self.hAcc = []       # Store horizontal accuracy
        self.vAcc = []       # Store vertical accuracy

    def read_and_process_data(self):
        """
        Continuously read and process data from the serial.
        """
        try:
            while True:
                raw_data, parsed_data = self.ubx_reader.read()
                if isinstance(parsed_data, UBXMessage):
                    self.process_data(parsed_data)
        except KeyboardInterrupt:
            print("Stopped reading data.")
        except Exception as e:
            print(f"An error occurred: {e}")

    def process_data(self, msg: UBXMessage):
        identity = msg.identity
        if identity in ("NAV-POSLLH", "NAV-HPPOSLLH"):
            self._process_nav_posllh(msg)
        if identity in ("NAV-PVT"):
            self._process_nav_pvt(msg)

    def _process_nav_posllh(self, msg: UBXMessage):
        latitude = msg.lat
        longitude = msg.lon
        height = msg.hMSL / 1000  # Convert to meters
        self.positions.append((latitude, longitude, height))
        print(f"Position: {latitude}, {longitude}, Height: {height}m")

    def _process_nav_pvt(self, msg: UBXMessage):
        hAcc = msg.hAcc / 1000  # Convert to meters
        vAcc = msg.vAcc / 1000  # Convert to meters
        self.hAcc.append(hAcc)
        self.vAcc.append(vAcc)
        print(f"Horizontal Accuracy: {hAcc}m, Vertical Accuracy: {vAcc}m")

    def close(self):
        self.serial_port.close()

    def plot_accuracy(self):
        """
        Live plot for horizontal and vertical accuracy.
        """
        fig, ax = plt.subplots()
        line, = ax.plot([], [], 'ro', label='Horizontal Accuracy')
        line2, = ax.plot([], [], 'bo', label='Vertical Accuracy')
        
        def init():
            ax.set_xlim(0, 100)  # Set limits
            ax.set_ylim(0, max(max(self.hAcc, default=0), max(self.vAcc, default=0)) + 5)
            return line, line2
        
        def update(frame):
            line.set_data(range(len(self.hAcc)), self.hAcc)
            line2.set_data(range(len(self.vAcc)), self.vAcc)
            return line, line2
        
        ani = FuncAnimation(fig, update, frames=np.arange(1, 100), init_func=init, blit=True)
        plt.legend()
        plt.show()

# Example usage:
if __name__ == "__main__":
    handler = UBXHandler()
    try:
        handler.read_and_process_data()
    finally:
        handler.close()
        handler.plot_accuracy()

NTRIP Client

Python
You need to have the following to run Python codes.
matplotlib
pyproj
pyubx2
pyserial
requests
utm
pyrtcm
pandas
pymongo
geopy
import requests
from requests.auth import HTTPBasicAuth
import serial

# NTRIP Server details
url = "https://ntrip.data.gnss.ga.gov.au:443/<YOUR LOCATION>"
username = "GET YOUR USERNAME"
password = "GET YOUR PASSWORD"


# Setup serial port to communicate with GNSS receiver
serial_port = '/dev/ttyACM0'
#'/dev/ttyACM0'  # Adjust this to your GNSS receiver's connected port
baudrate = 9600  # Adjust baud rate as per your device's configuration
ser = serial.Serial(serial_port, baudrate)

def stream_ntrip():
    headers = {
        'Ntrip-Version': 'Ntrip/2.0',
        'User-Agent': 'NTRIP PythonClient/1.0',
        'Connection': 'close'
    }
    try:
        # Connect to NTRIP caster
        response = requests.get(url, headers=headers, stream=True,
                                auth=HTTPBasicAuth(username, password))
        print("Connected to NTRIP Caster.")
        
        # Stream the corrections
        for chunk in response.iter_content(chunk_size=1024):
            # Write the RTCM data directly to the GNSS receiver
            ser.write(chunk)
            print("Sending RTCM data to GNSS receiver..." , chunk)
    except requests.exceptions.RequestException as e:
        print(f"Error connecting to NTRIP caster: {e}")
    finally:
        ser.close()
        print("Serial port closed.")

if __name__ == "__main__":
    stream_ntrip()

Credits

Javad Taghia
2 projects • 0 followers
Embedded systems, control, robotics, DSP, and automation system engineer. FPGAs, microcontrollers, real time and autonomous systems.
Contact

Comments

Please log in or sign up to comment.