nmea_parser.py
Go to the documentation of this file.
1 import math
2 import logging
3 
4 NMEA_DEFAULT_MAX_LENGTH = 82
5 NMEA_DEFAULT_MIN_LENGTH = 3
6 _NMEA_CHECKSUM_SEPERATOR = "*"
7 
8 class NMEAParser:
9 
10  def __init__(self, logerr=logging.error, logwarn=logging.warning, loginfo=logging.info, logdebug=logging.debug):
11  # Bit of a strange pattern here, but save the log functions so we can be agnostic of ROS
12  self._logerr = logerr
13  self._logwarn = logwarn
14  self._loginfo = loginfo
15  self._logdebug = logdebug
16 
17  # Save some other config
18  self.nmea_max_length = NMEA_DEFAULT_MAX_LENGTH
19  self.nmea_min_length = NMEA_DEFAULT_MIN_LENGTH
20 
21  @staticmethod
22  def checksum(sentence_no_checksum):
23  calculated_checksum = 0
24  for char in sentence_no_checksum[1:]:
25  calculated_checksum ^= ord(char)
26  return calculated_checksum
27 
28  @staticmethod
29  def lat_dd_to_dmm(decimal_degrees):
30  decimal_degrees_sub, decimal_degrees_whole = math.modf(abs(decimal_degrees))
31  decimal_minutes_float = decimal_degrees_sub * 60
32  decimal_minutes_sub, decimal_minutes_whole = math.modf(decimal_minutes_float)
33  degrees = int(decimal_degrees_whole)
34  decimal_minutes = int(decimal_minutes_whole)
35  decimal_subminutes = int(decimal_minutes_sub * 1e5)
36  return f"{degrees:02}{decimal_minutes:02}.{decimal_subminutes:02}"
37 
38  @staticmethod
39  def lon_dd_to_dmm(decimal_degrees):
40  decimal_degrees_sub, decimal_degrees_whole = math.modf(abs(decimal_degrees))
41  decimal_minutes_float = decimal_degrees_sub * 60
42  decimal_minutes_sub, decimal_minutes_whole = math.modf(decimal_minutes_float)
43  degrees = int(decimal_degrees_whole)
44  decimal_minutes = int(decimal_minutes_whole)
45  decimal_subminutes = int(decimal_minutes_sub * 1e5)
46  return f"{degrees:03}{decimal_minutes:02}.{decimal_subminutes:02}"
47 
48  def is_valid_sentence(self, sentence):
49  # Simple sanity checks
50  if len(sentence) > self.nmea_max_length:
51  self._logwarn('Received invalid NMEA sentence. Max length is {}, but sentence was {} bytes'.format(self.nmea_max_length, len(sentence)))
52  self._logwarn('Sentence: {}'.format(sentence))
53  return False
54  if len(sentence) < self.nmea_min_length:
55  self._logwarn('Received invalid NMEA sentence. We need at least {} bytes to parse but got {} bytes'.format(self.nmea_min_length, len(sentence)))
56  self._logwarn('Sentence: {}'.format(sentence))
57  return False
58  if sentence[0] != '$' and sentence[0] != '!':
59  self._logwarn('Received invalid NMEA sentence. Sentence should begin with "$" or "!", but instead begins with {}'.format(sentence[0]))
60  self._logwarn('Sentence: {}'.format(sentence))
61  return False
62  if sentence[-2:] != '\r\n':
63  self._logwarn('Received invalid NMEA sentence. Sentence should end with \\r\\n, but instead ends with {}'.format(sentence[-2:]))
64  self._logwarn('Sentence: {}'.format(sentence))
65  return False
66  if _NMEA_CHECKSUM_SEPERATOR not in sentence:
67  self._logwarn('Received invalid NMEA sentence. Sentence should have a "{}" character to seperate the checksum, but we could not find it.'.format(_NMEA_CHECKSUM_SEPERATOR))
68  self._logwarn('Sentence: {}'.format(sentence))
69  return False
70 
71  # Checksum check
72  data, expected_checksum_str = sentence.rsplit(_NMEA_CHECKSUM_SEPERATOR, 1)
73  expected_checksum = int(expected_checksum_str, 16)
74  calculated_checksum = self.checksum(data)
75  if expected_checksum != calculated_checksum:
76  self._logwarn('Received invalid NMEA sentence. Checksum mismatch');
77  self._logwarn('Expected Checksum: 0x{:X}'.format(expected_checksum))
78  self._logwarn('Calculated Checksum: 0x{:X}'.format(calculated_checksum))
79  return False
80 
81  # Passed all checks
82  return True
ntrip_client.nmea_parser.NMEAParser._loginfo
_loginfo
Definition: nmea_parser.py:14
ntrip_client.nmea_parser.NMEAParser.nmea_min_length
nmea_min_length
Definition: nmea_parser.py:19
ntrip_client.nmea_parser.NMEAParser._logwarn
_logwarn
Definition: nmea_parser.py:13
ntrip_client.nmea_parser.NMEAParser.__init__
def __init__(self, logerr=logging.error, logwarn=logging.warning, loginfo=logging.info, logdebug=logging.debug)
Definition: nmea_parser.py:10
ntrip_client.nmea_parser.NMEAParser.nmea_max_length
nmea_max_length
Definition: nmea_parser.py:18
ntrip_client.nmea_parser.NMEAParser.checksum
def checksum(sentence_no_checksum)
Definition: nmea_parser.py:22
ntrip_client.nmea_parser.NMEAParser.lat_dd_to_dmm
def lat_dd_to_dmm(decimal_degrees)
Definition: nmea_parser.py:29
ntrip_client.nmea_parser.NMEAParser.lon_dd_to_dmm
def lon_dd_to_dmm(decimal_degrees)
Definition: nmea_parser.py:39
ntrip_client.nmea_parser.NMEAParser._logerr
_logerr
Definition: nmea_parser.py:12
ntrip_client.nmea_parser.NMEAParser.is_valid_sentence
def is_valid_sentence(self, sentence)
Definition: nmea_parser.py:48
ntrip_client.nmea_parser.NMEAParser._logdebug
_logdebug
Definition: nmea_parser.py:15
ntrip_client.nmea_parser.NMEAParser
Definition: nmea_parser.py:8


ntrip_client
Author(s): Parker Hannifin Corp
autogenerated on Sat Dec 21 2024 03:32:07