CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pynmea2

Python library for parsing and generating NMEA 0183 protocol messages used in GPS and marine navigation systems

77

1.11x
Overview
Eval results
Files

gps-positioning.mddocs/

GPS Positioning Sentences

GPS positioning sentences provide location data, satellite information, and positioning quality metrics from GPS and GNSS receivers. These sentences form the core of most NMEA data streams from GPS devices.

GGA - Global Positioning System Fix Data

Essential GPS fix information including position, altitude, and quality indicators.

class GGA(TalkerSentence, ValidGGAFix, LatLonFix):
    """Global Positioning System Fix Data."""
    
    timestamp: datetime.time
    lat: str                    # Latitude in DDMM.MMMM format
    lat_dir: str               # 'N' or 'S'
    lon: str                   # Longitude in DDDMM.MMMM format
    lon_dir: str               # 'E' or 'W'
    gps_qual: str              # GPS quality indicator (0-8)
    num_sats: str              # Number of satellites
    horizontal_dil: str        # Horizontal dilution of precision
    altitude: float            # Altitude above mean sea level
    altitude_units: str        # Units of altitude (usually 'M')
    geo_sep: str               # Geoidal separation
    geo_sep_units: str         # Units of geoidal separation
    age_gps_data: str          # Age of differential GPS data
    ref_station_id: str        # Reference station ID
    
    @property
    def latitude(self) -> float:
        """Latitude in signed decimal degrees."""
    
    @property  
    def longitude(self) -> float:
        """Longitude in signed decimal degrees."""
    
    @property
    def is_valid(self) -> bool:
        """True if GPS quality indicates valid fix (1-5)."""

GPS Quality Indicators

  • 0: Invalid
  • 1: GPS fix (SPS)
  • 2: DGPS fix
  • 3: PPS fix
  • 4: Real Time Kinematic
  • 5: Float RTK
  • 6: Estimated (dead reckoning)
  • 7: Manual input mode
  • 8: Simulation mode

Usage Examples

import pynmea2

# Parse GGA sentence
msg = pynmea2.parse("$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D")

print(f"Time: {msg.timestamp}")              # 18:43:53.070000
print(f"Position: {msg.latitude}, {msg.longitude}")  # -19.4840833333, 24.1751
print(f"Raw coordinates: {msg.lat}{msg.lat_dir}, {msg.lon}{msg.lon_dir}")  # 1929.045S, 02410.506E
print(f"GPS Quality: {msg.gps_qual}")        # 1 (GPS fix)
print(f"Satellites: {msg.num_sats}")         # 04
print(f"HDOP: {msg.horizontal_dil}")         # 2.6
print(f"Altitude: {msg.altitude} {msg.altitude_units}")  # 100.0 M
print(f"Valid fix: {msg.is_valid}")          # True

# Create GGA sentence
gga_data = ['184353.07', '1929.045', 'S', '02410.506', 'E', '1', '04', '2.6', '100.00', 'M', '-33.9', 'M', '', '0000']
new_msg = pynmea2.GGA('GP', 'GGA', gga_data)
print(str(new_msg))  # $GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D

RMC - Recommended Minimum Specific GPS/TRANSIT Data

Minimum recommended navigation information including position, speed, course, and date.

class RMC(TalkerSentence, ValidRMCStatusFix, LatLonFix, DatetimeFix):
    """Recommended Minimum Specific GPS/TRANSIT Data."""
    
    timestamp: datetime.time
    status: str                # 'A' = Active, 'V' = Void
    lat: str                   # Latitude in DDMM.MMMM format
    lat_dir: str              # 'N' or 'S'
    lon: str                  # Longitude in DDDMM.MMMM format
    lon_dir: str              # 'E' or 'W'
    spd_over_grnd: str        # Speed over ground in knots
    true_course: str          # Track angle in degrees
    datestamp: datetime.date  # Date
    mag_variation: str        # Magnetic variation
    mag_var_dir: str          # Direction of magnetic variation
    mode_indicator: str       # Mode indicator (A, D, E, etc.)
    nav_status: str           # Navigational status
    
    @property
    def latitude(self) -> float:
        """Latitude in signed decimal degrees."""
    
    @property
    def longitude(self) -> float:
        """Longitude in signed decimal degrees."""
    
    @property
    def datetime(self) -> datetime.datetime:
        """Combined date and time."""
    
    @property
    def is_valid(self) -> bool:
        """True if status and mode indicators are valid."""

Mode Indicators

  • A: Autonomous mode
  • D: Differential mode
  • E: Estimated (dead reckoning) mode
  • F: Float RTK mode
  • M: Manual input mode
  • P: Precise mode
  • R: Real Time Kinematic mode
  • S: Simulator mode

Usage Examples

import pynmea2

# Parse RMC sentence
msg = pynmea2.parse("$GPRMC,184353.07,A,1929.045,S,02410.506,E,0.13,309.62,120598,A*70")

print(f"Time: {msg.timestamp}")              # 18:43:53.070000
print(f"Date: {msg.datestamp}")              # 1998-05-12
print(f"Combined: {msg.datetime}")           # 1998-05-12 18:43:53.070000
print(f"Status: {msg.status}")               # A (Active)
print(f"Position: {msg.latitude}, {msg.longitude}")  # -19.4840833333, 24.1751
print(f"Speed: {msg.spd_over_grnd} knots")   # 0.13 knots
print(f"Course: {msg.true_course}°")         # 309.62°
print(f"Valid: {msg.is_valid}")              # True

GLL - Geographic Position - Latitude/Longitude

Geographic position information with status and optional FAA mode indicator.

class GLL(TalkerSentence, ValidStatusFix, LatLonFix):
    """Geographic Position - Latitude/Longitude."""
    
    lat: str                   # Latitude in DDMM.MMMM format
    lat_dir: str              # 'N' or 'S'
    lon: str                  # Longitude in DDDMM.MMMM format
    lon_dir: str              # 'E' or 'W'
    timestamp: datetime.time   # UTC time
    status: str               # 'A' = valid, 'V' = invalid
    faa_mode: str             # FAA mode indicator
    
    @property
    def latitude(self) -> float:
        """Latitude in signed decimal degrees."""
    
    @property
    def longitude(self) -> float:
        """Longitude in signed decimal degrees."""
    
    @property
    def is_valid(self) -> bool:
        """True if status is 'A'."""

Usage Examples

import pynmea2

# Parse GLL sentence
msg = pynmea2.parse("$GPGLL,1929.045,S,02410.506,E,184353.07,A,A*4C")

print(f"Position: {msg.latitude}, {msg.longitude}")  # -19.4840833333, 24.1751
print(f"Time: {msg.timestamp}")              # 18:43:53.070000
print(f"Status: {msg.status}")               # A
print(f"FAA Mode: {msg.faa_mode}")           # A
print(f"Valid: {msg.is_valid}")              # True

GNS - GNSS Fix Data

Combined GPS/GLONASS fix data with mode indicators for different satellite systems.

class GNS(TalkerSentence, LatLonFix):
    """GNSS Fix Data."""
    
    timestamp: datetime.time
    lat: str                   # Latitude in DDMM.MMMM format
    lat_dir: str              # 'N' or 'S'
    lon: str                  # Longitude in DDDMM.MMMM format
    lon_dir: str              # 'E' or 'W'
    mode_indicator: str       # Mode indicator for each system
    num_sats: str             # Number of satellites
    hdop: str                 # Horizontal dilution of precision
    altitude: str             # Antenna altitude above geoid
    geo_sep: str              # Geoidal separation
    age_gps_data: str         # Age of differential data
    diferential: str          # Differential reference station ID
    
    @property
    def latitude(self) -> float:
        """Latitude in signed decimal degrees."""
    
    @property
    def longitude(self) -> float:
        """Longitude in signed decimal degrees."""

GSA - GNSS DOP and Active Satellites

Satellite dilution of precision and active satellite information.

class GSA(TalkerSentence, ValidGSAFix):
    """GNSS DOP and Active Satellites."""
    
    mode: str                 # Selection mode (M = Manual, A = Auto)
    mode_fix_type: str        # Fix type (1 = None, 2 = 2D, 3 = 3D)
    sv_id01: str             # Satellite ID channel 1
    sv_id02: str             # Satellite ID channel 2
    sv_id03: str             # Satellite ID channel 3
    sv_id04: str             # Satellite ID channel 4
    sv_id05: str             # Satellite ID channel 5
    sv_id06: str             # Satellite ID channel 6
    sv_id07: str             # Satellite ID channel 7
    sv_id08: str             # Satellite ID channel 8
    sv_id09: str             # Satellite ID channel 9
    sv_id10: str             # Satellite ID channel 10
    sv_id11: str             # Satellite ID channel 11
    sv_id12: str             # Satellite ID channel 12
    pdop: str                # Position dilution of precision
    hdop: str                # Horizontal dilution of precision  
    vdop: str                # Vertical dilution of precision
    
    @property
    def is_valid(self) -> bool:
        """True if fix type is 2D or 3D."""

Usage Examples

import pynmea2

# Parse GSA sentence
msg = pynmea2.parse("$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39")

print(f"Mode: {msg.mode}")                   # A (Auto)
print(f"Fix type: {msg.mode_fix_type}")      # 3 (3D fix)
print(f"Active satellites: {[s for s in [msg.sv_id01, msg.sv_id02, msg.sv_id04, msg.sv_id05, msg.sv_id09, msg.sv_id12, msg.sv_id24] if s]}")
print(f"PDOP: {msg.pdop}")                   # 2.5
print(f"HDOP: {msg.hdop}")                   # 1.3
print(f"VDOP: {msg.vdop}")                   # 2.1
print(f"Valid: {msg.is_valid}")              # True (3D fix)

GSV - GNSS Satellites in View

Information about satellites in view including elevation, azimuth, and signal strength.

class GSV(TalkerSentence):
    """GNSS Satellites in View."""
    
    num_messages: str         # Total number of GSV messages
    msg_num: str             # Current message number
    num_sv_in_view: str      # Total satellites in view
    
    # Satellite 1 information
    sv_prn_num_1: str        # Satellite PRN number
    elevation_deg_1: str     # Elevation in degrees
    azimuth_1: str           # Azimuth in degrees
    snr_1: str               # Signal-to-noise ratio
    
    # Satellite 2 information
    sv_prn_num_2: str
    elevation_deg_2: str
    azimuth_2: str
    snr_2: str
    
    # Satellite 3 information  
    sv_prn_num_3: str
    elevation_deg_3: str
    azimuth_3: str
    snr_3: str
    
    # Satellite 4 information
    sv_prn_num_4: str
    elevation_deg_4: str
    azimuth_4: str
    snr_4: str

Usage Examples

import pynmea2

# Parse GSV sentence
msg = pynmea2.parse("$GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75")

print(f"Message {msg.msg_num} of {msg.num_messages}")  # Message 1 of 2
print(f"Satellites in view: {msg.num_sv_in_view}")     # 8

# Satellite 1 info
print(f"Sat {msg.sv_prn_num_1}: El={msg.elevation_deg_1}° Az={msg.azimuth_1}° SNR={msg.snr_1}")
# Sat 01: El=40° Az=083° SNR=46

# Process all satellites in this message
for i in range(1, 5):  # GSV contains up to 4 satellites per message
    prn = getattr(msg, f'sv_prn_num_{i}')
    if prn:
        elevation = getattr(msg, f'elevation_deg_{i}')
        azimuth = getattr(msg, f'azimuth_{i}')
        snr = getattr(msg, f'snr_{i}')
        print(f"Satellite {prn}: Elevation={elevation}°, Azimuth={azimuth}°, SNR={snr}")

Additional GPS Sentences

GST - GNSS Pseudorange Error Statistics

class GST(TalkerSentence):
    """GNSS Pseudorange Error Statistics."""
    
    timestamp: datetime.time
    rms: str                  # RMS value of standard deviation
    std_dev_major: str        # Standard deviation of semi-major axis
    std_dev_minor: str        # Standard deviation of semi-minor axis
    orientation: str          # Orientation of semi-major axis
    std_dev_latitude: str     # Standard deviation of latitude error
    std_dev_longitude: str    # Standard deviation of longitude error
    std_dev_altitude: str     # Standard deviation of altitude error

GRS - GNSS Range Residuals

class GRS(TalkerSentence):
    """GNSS Range Residuals."""
    
    timestamp: datetime.time
    residuals_mode: str       # Residuals mode (0 = used, 1 = calculated)
    sv_res_01: str           # Satellite 1 residual
    sv_res_02: str           # Satellite 2 residual
    # ... sv_res_03 through sv_res_12
    sv_res_12: str           # Satellite 12 residual

Coordinate Conversion

All GPS positioning sentences that include LatLonFix mixin provide convenient coordinate conversion:

import pynmea2

msg = pynmea2.parse("$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D")

# Decimal degrees (most common)
print(f"Lat: {msg.latitude}")                # -19.4840833333
print(f"Lon: {msg.longitude}")               # 24.1751

# Minutes and seconds components
print(f"Lat minutes: {msg.latitude_minutes}")    # 29.045
print(f"Lon minutes: {msg.longitude_minutes}")   # 4.506
print(f"Lat seconds: {msg.latitude_seconds}")    # 2.7
print(f"Lon seconds: {msg.longitude_seconds}")   # 0.36

# Format coordinates
print(f'{msg.latitude:.6f}°, {msg.longitude:.6f}°')                    # -19.484083°, 24.175100°
print(f'{abs(msg.latitude):.4f}°{msg.lat_dir}, {abs(msg.longitude):.4f}°{msg.lon_dir}')  # 19.4841°S, 24.1751°E

Install with Tessl CLI

npx tessl i tessl/pypi-pynmea2

docs

core-parsing.md

depth-sonar.md

gps-positioning.md

index.md

navigation-course.md

proprietary-sentences.md

stream-processing.md

utilities.md

wind-weather.md

tile.json