Fixposition SDK 0.0.0-heads/main-0-g4e80ed3
Collection of c++ libraries and apps for use with Fixposition products on Linux
Loading...
Searching...
No Matches
nmea.hpp
Go to the documentation of this file.
1/**
2 * \verbatim
3 * ___ ___
4 * \ \ / /
5 * \ \/ / Copyright (c) Fixposition AG (www.fixposition.com) and contributors
6 * / /\ \ License: see the LICENSE file
7 * /__/ \__\
8 *
9 * Based on work by flipflip (https://github.com/phkehl)
10 * The information on message structures, IDs, descriptions etc. in this file are from publicly available data, such as:
11 * - NMEA 0183 (https://www.nmea.org/)
12 * - https://en.wikipedia.org/wiki/NMEA_0183
13 * - u-blox ZED-F9P Interface Description (HPG 1.50) (https://www.u-blox.com/en/docs/UBXDOC-963802114-12815),
14 * copyright (c) 2024 u-blox AG
15 * \endverbatim
16 *
17 * @file
18 * @brief Fixposition SDK: Parser NMEA routines and types
19 */
20// clang-format off
21/**
22 * @page FPSDK_COMMON_PARSER_NMEA Parser NMEA routines and types
23 *
24 * **API**: fpsdk_common/parser/nmea.hpp and fpsdk::common::parser::nmea
25 *
26 * @fp_msgspec_begin{NMEA-Protocol}
27 *
28 * The NMEA framing and behaviour is defined by the NMEA 0183 standard (v4.11 and erratas).
29 *
30 * In NMEA speak messages are called *Sentences*. Frames (messages) are in this form:
31 *
32 * <code><b style="color: red;">$</b><b style="color: green;">Talker</b><b style="color: blue;">Formatter</b>,<em>field<sub>1</sub></em>,<em>field<sub>2</sub></em>,…,<em>field<sub>N</sub></em><b style="color: red;">\*CC</b><b style="color: red;">\\r\\n</b></code>
33 *
34 * Where:
35 *
36 * - The NMEA style framing:
37 * - <code><b style="color: red;">\$</b></code>
38 * -- Start character ("$", ASCII 36)
39 * - <code><b style="color: red;">\*CC</b></code>
40 * -- Checksum: "\*" (ASCII 42) and two digit XOR value of all payload
41 * characters in captial hexadecimal notation, for example:
42 * "FPX" = <code>'F' ^ 'P' ^ 'X' = 70 ^ 80 ^ 88 = 78 = 0x4e</code> = checksum <code>4E</code>
43 * - <code><b style="color: red;">\\r\\n</b></code>
44 * -- Sentence termination characters (CR + LF, ASCII 13 + 10)
45 * - A <code><b style="color: green;">Talker</b></code> ID -- Two capital characters:
46 * - `GP` -- Talker ID for GPS, also legacy resp. "compatibility"
47 * - `GL` -- Talker ID for GLONASS
48 * - `GA` -- Talker ID for Galileo
49 * - `GB` -- Talker ID for BeiDou
50 * - `GQ` -- Talker ID for QZSS
51 * - `GI` -- Talker ID for NavIC (IRNSS)
52 * - `GN` -- Talker ID for any combination of GNSS
53 * - A <code><b style="color: blue;">Formatter</b></code> ID -- Three capital characters, for example:
54 * - `RMC` for the message containing recommended minimum specific GNSS data
55 * - See the NMEA 0183 standard document for an extensive list
56 * - Data fields (payload)
57 * - <code><em>field<sub>1</sub></em>,<em>field<sub>2</sub></em>,…,<em>field<sub>N</sub></em></code>
58 * -- The structure of the message data is defined by the <code><b style="color: blue;">Formatter</b></code>.
59 * Each field can contain all printable 7-bit ASCII characters (ASCII 32–126), excluding the
60 * reserved characters `!` (ASCII 33), `$` (ASCII 36), `*` (ASCII 42), `,` (ASCII 44),
61 * `\` (ASCII 92), `~` (ASCII 126).
62 * - Field separators
63 * - All fields (identifier, message type, message version, data fields) are separated by a `,` (comma, ASCII 44)
64 * - Null fields
65 * - Data fields can be _null_, meaning their value is absent to indicate that no data is
66 * available. The data for null fields is the empty string. For example:
67 * - Definition: <code>…,<em>field<sub>i</sub></em>,<em>field<sub>i+1</sub></em>,<em>field<sub>i+2</sub></em>,…</code>
68 * - Values: <code><em>field<sub>i</sub></em></code> = 123, <code><em>field<sub>i+1</sub></em></code> = _null_,
69 * <code><em>field<sub>i+2</sub></em></code> = 456
70 * - Payload string: <code>…,123,,456,…</code>
71 * - Data field types:
72 * - See the NMEA 0183 standard document for specifications
73 *
74 * @fp_msgspec_end
75 *
76 */
77// clang-format on
78#ifndef __FPSDK_COMMON_PARSER_NMEA_HPP__
79#define __FPSDK_COMMON_PARSER_NMEA_HPP__
80
81/* LIBC/STL */
82#include <array>
83#include <cstdint>
84#include <string>
85#include <vector>
86
87/* EXTERNAL */
88
89/* PACKAGE */
90
91namespace fpsdk {
92namespace common {
93namespace parser {
94/**
95 * @brief Parser NMEA routines and types
96 */
97namespace nmea {
98/* ****************************************************************************************************************** */
99
100static constexpr uint8_t NMEA_PREAMBLE = '$'; //!< NMEA framing preamble
101static constexpr std::size_t NMEA_FRAME_SIZE = 6; //!< NMEA frame size ("$*cc\r\n")
102
103//! NMEA message meta data
105{
106 char talker_[3] = { 0 }; //!< Talker ID (for example, "GP", "GN" or "P"), nul-terminated string
107 char formatter_[20] = { 0 }; //!< Formatter (for example, "GGA", "RMC", or "UBX"), nul-terminated string
108 int payload_ix0_ = 0; //!< Index (offset) for start of payload, 0 if no payload available
109 int payload_ix1_ = 0; //!< Index (offset) for end of payload, 0 if no payload available
110};
111
112/**
113 * @brief Get NMEA message meta data
114 *
115 * @param[out] meta The meta data
116 * @param[in] msg Pointer to the NMEA message
117 * @param[in] msg_size Size of the NMEA message (>= 11)
118 *
119 * @note No check on the data provided is done. The caller must ensure that the data is a correct NMEA message.
120 *
121 * @returns true if the meta data was successfully extracted, false otherwise
122 */
123bool NmeaGetMessageMeta(NmeaMessageMeta& meta, const uint8_t* msg, const std::size_t msg_size);
124
125/**
126 * @brief Get NMEA message name
127 *
128 * Generates a name (string) in the form "NMEA-TALKER-FORMATTER" (for example, "NMEA-GP-GGA"). Some proprietary messages
129 * are recognised, for example, "NMEA-PUBX-POSITION".
130 *
131 * @param[out] name String to write the name to
132 * @param[in] size Size of \c name (incl. nul termination)
133 * @param[in] msg Pointer to the NMEA message
134 * @param[in] msg_size Size of the \c msg
135 *
136 * @note No check on the data provided is done. The caller must ensure that the data is a valid NMEA message.
137 *
138 * @returns true if message name was generated, false if \c name buffer was too small
139 */
140bool NmeaGetMessageName(char* name, const std::size_t size, const uint8_t* msg, const std::size_t msg_size);
141
142/**
143 * @brief Get NMEA message info
144 *
145 * This stringifies the content of some NMEA messages, for debugging.
146 *
147 * @param[out] info String to write the info to
148 * @param[in] size Size of \c name (incl. nul termination)
149 * @param[in] msg Pointer to the NMEA message
150 * @param[in] msg_size Size of the \c msg
151 *
152 * @note No check on the data provided is done. The caller must ensure that the data is a valid NMEA message.
153 *
154 * @returns true if message info was generated (even if info is empty), false if \c name buffer was too small
155 */
156bool NmeaGetMessageInfo(char* info, const std::size_t size, const uint8_t* msg, const std::size_t msg_size);
157
158/**
159 * @brief Make a NMEA message
160 *
161 * @param[out] msg The message frame
162 * @param[in] payload The message payload, including the talker ID and formatter
163 * (up to MAX_NMEA_SIZE - NMEA_FRAME_SIZE bytes, can be empty)
164 *
165 * @note Illegal (< 0x20 or > 0x7e) or reserved/special ('$', '\', '!', '~', '^' and '*') characters are replaced
166 * by a '_'.
167 *
168 * @returns true if the message was successfully constructed (\c msg now contains the message),
169 * false if failed contructing the message (payload too large)
170 */
171bool NmeaMakeMessage(std::vector<uint8_t>& msg, const std::string& payload);
172
173/**
174 * @brief Make a NMEA message
175 *
176 * @param[out] msg The message frame
177 * @param[in] payload The message payload, including the talker ID and formatter
178 * (up to MAX_NMEA_SIZE - NMEA_FRAME_SIZE bytes, can be empty)
179 *
180 * @note Illegal (< 0x20 or > 0x7e) or reserved/special ('$', '\', '!', '~', '^' and '*') characters are replaced
181 * by a '_'.
182 *
183 * @returns true if the message was successfully constructed (\c msg now contains the message),
184 * false if failed contructing the message (payload too large)
185 */
186bool NmeaMakeMessage(std::string& msg, const std::string& payload);
187
188/**
189 * @brief NMEA coordinates (integer degrees, float minutes and a sign for N/S resp. E/W)
190 */
192{
193 /**
194 * @brief Constructor
195 *
196 * @param[in] degs Decimal degrees
197 * @param[in] digits Number of digits (0-12), param clamped to range
198 */
199 NmeaCoordinates(const double degs, const int digits = 5);
200
201 int deg_; //!< Integer degrees value, >= 0
202 double min_; //!< Fractional minutes value, >= 0.0
203 bool sign_; //!< false for negative (S or W), true for positive (N or E)
204};
205
206// ---------------------------------------------------------------------------------------------------------------------
207
208/**
209 * @brief NMEA talker IDs
210 */
211enum class NmeaTalkerId : int
212{ // clang-format off
213 UNSPECIFIED = '!', //!< Unspecified
214 PROPRIETARY = 'x', //!< Proprietary
215 GPS_SBAS = 'P', //!< GPS and/or SBAS
216 GLO = 'L', //!< GLONASS
217 GAL = 'A', //!< GALILEO
218 BDS = 'B', //!< BeiDou
219 NAVIC = 'I', //!< NavIC
220 QZSS = 'Q', //!< QZSS
221 GNSS = 'N', //!< GNSS (multi-constellation)
222}; // clang-format on
223
224/**
225 * @brief NMEA-Gx-GGA quality indicator
226 */
227enum class NmeaQualityGga : int
228{ // clang-format off
229 UNSPECIFIED = '!', //!< Unspecified
230 NOFIX = '0', //!< No fix
231 SPP = '1', //!< Autonomous GNSS fix
232 DGNSS = '2', //!< Differential GPS fix (e.g. with SBAS)
233 PPS = '3', //!< PPS mode
234 RTK_FIXED = '4', //!< RTK fixed
235 RTK_FLOAT = '5', //!< RTK float
236 ESTIMATED = '6', //!< Estimated (dead reckoning only)
237 MANUAL = '7', //!< Manual input mode
238 SIM = '8', //!< Simulator
239}; // clang-format on
240
241/**
242 * @brief NMEA-Gx-GLL and NMEA-Gx-RMC status
243 *
244 * @note Do not use <, >, >=, <= operators on this!
245 */
246enum class NmeaStatusGllRmc : int
247{ // clang-format off
248 UNSPECIFIED = '!', //!< Unspecified
249 INVALID = 'V', //!< Data invalid
250 VALID = 'A', //!< Data valid
251 // DIFFERENTIAL = 'D', // @todo another possible value?
252}; // clang-format on
253
254/**
255 * @brief NMEA-Gx-GLL and NMEA-Gx-VTG pos mode
256 *
257 * @note Do not use <, >, >=, <= operators on this!
258 */
259enum class NmeaModeGllVtg : int
260{ // clang-format off
261 UNSPECIFIED = '!', //!< Unspecified
262 INVALID = 'N', //!< Invalid (no fix)
263 AUTONOMOUS = 'A', //!< Autonomous mode (SPP)
264 DGNSS = 'D', //!< Differential GNSS fix
265 ESTIMATED = 'E', //!< Estimated (dead reckoning only)
266 MANUAL = 'M', //!< Manual input mode
267 SIM = 'S', //!< Simulator mode
268}; // clang-format on
269
270/**
271 * @brief NMEA-Gx-RMC and NMEA-Gx-GNS pos mode
272 *
273 * @note Do not use <, >, >=, <= operators on this!
274 */
275enum class NmeaModeRmcGns : int
276{ // clang-format off
277 UNSPECIFIED = '!', //!< Unspecified
278 INVALID = 'N', //!< Invalid (no fix)
279 AUTONOMOUS = 'A', //!< Autonomous mode (SPP)
280 DGNSS = 'D', //!< Differential GNSS fix
281 ESTIMATED = 'E', //!< Estimated (dead reckoning only)
282 RTK_FIXED = 'R', //!< RTK fixed
283 RTK_FLOAT = 'F', //!< RTK float
284 PRECISE = 'P', //!< Precise
285 MANUAL = 'M', //!< Manual input mode
286 SIM = 'S', //!< Simulator mode
287}; // clang-format on
288
289/**
290 * @brief NMEA-Gx-RMC navigational status
291 *
292 * @note Do not use <, >, >=, <= operators on this!
293 */
294enum class NmeaNavStatusRmc : int
295{ // clang-format off
296 UNSPECIFIED = '!', //!< Unspecified
297 SAFE = 'S', //!< Safe
298 CAUTION = 'C', //!< Caution
299 UNSAFE = 'U', //!< Unsafe
300 NA = 'V', //!< Equipment does not provide navigational status
301}; // clang-format on
302
303/**
304 * @brief NMEA-Gx-GNS operation mode
305 *
306 * @note Do not use <, >, >=, <= operators on this!
307 */
308enum class NmeaOpModeGsa : int
309{ // clang-format off
310 UNSPECIFIED = '!', //!< Unspecified
311 MANUAL = 'M', //!< Manual
312 AUTO = 'A', //!< Automatic
313}; // clang-format on
314
315/**
316 * @brief NMEA-Gx-GNS nav mode
317 */
318enum class NmeaNavModeGsa : int
319{ // clang-format off
320 UNSPECIFIED = '!', //!< Unspecified
321 NOFIX = '1', //!< No fix
322 FIX2D = '2', //!< 2D fix
323 FIX3D = '3', //!< 3D fix
324}; // clang-format on
325
326/**
327 * @brief NMEA system IDs
328 *
329 * @note Do not use <, >, >=, <= operators on this!
330 */
331enum class NmeaSystemId : int
332{ // clang-format off
333 UNSPECIFIED = '!', //!< Unspecified
334 GPS_SBAS = '1', //!< GPS and/or SBAS
335 GLO = '2', //!< GLONASS
336 GAL = '3', //!< Galileo
337 BDS = '4', //!< BeiDou
338 QZSS = '5', //!< QZSS
339 NAVIC = '6', //!< NavIC
340}; // clang-format on
341
342/**
343 * @brief NMEA signal IDs
344 *
345 * @note Do not use <, >, >=, <= operators on this!
346 */
347enum class NmeaSignalId : int
348{ // clang-format off
349 UNSPECIFIED = 0x000 + '!', //!< Unspecified
350 NONE = 0x000 + '0', //!< None
351 GPS_L1CA = 0x100 + '1', //!< GPS L1 C/A or SBAS L1 C/A
352 GPS_L2CL = 0x100 + '6', //!< GPS L2 CL
353 GPS_L2CM = 0x100 + '5', //!< GPS L2 CM
354 GPS_L5I = 0x100 + '7', //!< GPS L5 I
355 GPS_L5Q = 0x100 + '8', //!< GPS L5 Q
356 GLO_L1OF = 0x200 + '1', //!< GLONASS L1 OF
357 GLO_L2OF = 0x200 + '3', //!< GLONASS L2 OF
358 GAL_E1 = 0x300 + '7', //!< Galileo E1
359 GAL_E5A = 0x300 + '1', //!< Galileo E5 A
360 GAL_E5B = 0x300 + '2', //!< Galileo E5 B
361 BDS_B1ID = 0x400 + '1', //!< BeiDou B1I D
362 BDS_B2ID = 0x400 + 'B', //!< BeiDou B2I D
363 BDS_B1C = 0x400 + '3', //!< BeiDou B1 C
364 BDS_B2A = 0x400 + '5', //!< BeiDou B2 a
365 QZSS_L1CA = 0x500 + '1', //!< QZSS L1 C/A
366 QZSS_L1S = 0x500 + '4', //!< QZSS L1S
367 QZSS_L2CM = 0x500 + '5', //!< QZSS L2 CM
368 QZSS_L2CL = 0x500 + '6', //!< QZSS L2 CL
369 QZSS_L5I = 0x500 + '7', //!< QZSS L5 I
370 QZSS_L5Q = 0x500 + '8', //!< QZSS L5 Q
371 NAVIC_L5A = 0x600 + '5', //!< NavIC L5 A
372}; // clang-format on
373
374/**
375 * @brief NMEA time (hour, minutes, seconds)
376 */
378{
379 bool valid = false; //!< Data is valid
380 int hours = 0; //!< Hours
381 int mins = 0; //!< Minutes
382 double secs = 0.0; //!< Seconds
383
384 bool operator==(const NmeaTime& rhs) const; //!< Equal
385 bool operator!=(const NmeaTime& rhs) const; //!< Not equal
386};
387
388/**
389 * @brief NMEA date (year, month, day)
390 */
392{
393 bool valid = false; //!< Data is valid
394 int years = 0; //!< Year
395 int months = 0; //!< Month
396 int days = 0.0; //!< Day
397
398 bool operator==(const NmeaDate& rhs) const; //!< Equal
399 bool operator!=(const NmeaDate& rhs) const; //!< Not equal
400};
401
402/**
403 * @brief NMEA geodetic position
404 */
406{
407 bool latlon_valid = false; //!< Latitude/longitude is valid
408 double lat = 0.0; //!< Latitude [deg], >= 0.0 East, < 0.0 West
409 double lon = 0.0; //!< Longitude [deg], >= 0.0 North, < 0.0 South
410 bool height_valid = false; //!< Height is valid
411 double height = 0.0; //!< Ellipsoidal (!) height [m]
412};
413
414/**
415 * @brief NMEA satellite (used, e.g. in GSA)
416 */
418{
419 bool valid = false; //!< Data is valid
421 int svid = 0; //!< Satellite ID (numbering cf. NMEA 0183)
422};
423
424/**
425 * @brief Constants for different versions of NMEA
426 */
428{
429 const int svid_min_gps = -1; //!< Min GPS satellite ID
430 const int svid_max_gps = -1; //!< Max GPS satellite ID
431 const int svid_min_sbas = -1; //!< Min SBAS satellite ID
432 const int svid_max_sbas = -1; //!< Max SBAS satellite ID
433 const int svid_min_gal = -1; //!< Min Galileo satellite ID
434 const int svid_max_gal = -1; //!< Max Galileo satellite ID
435 const int svid_min_bds = -1; //!< Min BeiDou satellite ID
436 const int svid_max_bds = -1; //!< Max BeiDou satellite ID
437 const int svid_min_glo = -1; //!< Min GLONASS satellite ID
438 const int svid_max_glo = -1; //!< Max GLONASS satellite ID
439 const int svid_min_qzss = -1; //!< Min QZSS satellite ID, -1 if not available
440 const int svid_max_qzss = -1; //!< Max QZSS satellite ID, -1 if not available
441 static const NmeaVersion V410; //!< Value for NMEA v4.10
442 static const NmeaVersion V410_UBX_EXT; //!< Value for NMEA v4.10 extended (u-blox flavour)
443 static const NmeaVersion V411; //!< Value for NMEA v4.11
444};
445
446/**
447 * NMEA satellite position (GSA)
448 */
450{
451 bool valid = false; //!< Data is valid
453 int svid = 0; //!< Satellite ID (numbering cf. NMEA 0183)
454 int el = 0; //!< Elevation [deg] (-90..90)
455 int az = 0; //!< Azimuth [deg] (0..360)
456};
457
458/**
459 * NMEA signal levels (GSA)
460 */
462{
463 bool valid = false; //!< Data valid
465 int svid = 0; //!< Satellite ID (numbering cf. NMEA 0183)
467 int cno = 0; //!< Signal level [dBHz]
468};
469
470/**
471 * @brief NMEA integer value
472 */
474{
475 bool valid = false; //!< Data is valid
476 int value = 0; //!< Value
477};
478
479/**
480 * @brief NMEA float value
481 */
483{
484 bool valid = false; //!< Data is valid
485 double value = 0; //!< Value
486};
487
488/**
489 * @brief NMEA payload base class
490 */
492{
494 bool valid_ = false; //!< Payload successfully decoded (true), or not (yet) decoded (false)
495 virtual ~NmeaPayload() = default; //!< Virtual dtor for polymorphism
496};
497
498/**
499 * @brief NMEA-Gx-GGA message payload
500 */
502{
503 NmeaTime time; //!< Time
504 NmeaLlh llh; //!< Position (with height)
506 NmeaInt num_sv; //!< Number of satellites used (may be limited to 12)
507 NmeaFloat hdop; //!< Horizontal dilution of precision (only with valid fix)
508 NmeaFloat diff_age; //!< Differential data age (optional, NMEA 4.11 only)
509 NmeaInt diff_sta; //!< Differential station ID (optional, NMEA 4.11 only)
510
511 /**
512 * @brief Set data from sentence
513 *
514 * @param[in] msg Pointer to the NMEA message
515 * @param[in] msg_size Size of the NMEA message (>= 11)
516 *
517 * @returns true if sentence payload was correct and all data could be extracted (fields are now valid), or false
518 * otherwise (fields are now invalid)
519 */
520 bool SetFromMsg(const uint8_t* msg, const std::size_t msg_size);
521
522 static constexpr const char* FORMATTER = "GGA"; //!< Formatter
523};
524
525/**
526 * @brief NMEA-Gx-GLL message payload
527 */
529{
530 NmeaLlh ll; //!< Position (no height)
531 NmeaTime time; //!< Time
532 NmeaStatusGllRmc status = NmeaStatusGllRmc::UNSPECIFIED; //!< Positioning system status
533 NmeaModeGllVtg mode = NmeaModeGllVtg::UNSPECIFIED; //!< Positioning system mode
534
535 /**
536 * @brief Set data from sentence
537 *
538 * @param[in] msg Pointer to the NMEA message
539 * @param[in] msg_size Size of the NMEA message (>= 11)
540 *
541 * @returns true if sentence payload was correct and all data could be extracted (fields are now valid), or false
542 * otherwise (fields are now invalid)
543 */
544 bool SetFromMsg(const uint8_t* msg, const std::size_t msg_size);
545
546 static constexpr const char* FORMATTER = "GLL"; //!< Formatter
547};
548
549/**
550 * @brief NMEA-Gx-RMC message payload
551 */
553{
554 NmeaTime time; //!< Time
555 NmeaStatusGllRmc status = NmeaStatusGllRmc::UNSPECIFIED; //!< Positioning system status
556 NmeaLlh llh; //!< Position
557 NmeaFloat speed; //!< Speed over ground [knots]
558 NmeaFloat course; //!< Course over ground w.r.t. True North [deg]
559 NmeaDate date; //!< Date
560 NmeaModeRmcGns mode = NmeaModeRmcGns::UNSPECIFIED; //!< Positioning system mode indicator
561 NmeaNavStatusRmc navstatus = NmeaNavStatusRmc::UNSPECIFIED; //!< Navigational status (optional)
562 /**
563 * @brief Set data from sentence
564 *
565 * @param[in] msg Pointer to the NMEA message
566 * @param[in] msg_size Size of the NMEA message (>= 11)
567 *
568 * @returns true if sentence payload was correct and all data could be extracted (fields are now valid), or false
569 * otherwise (fields are now invalid)
570 */
571 bool SetFromMsg(const uint8_t* msg, const std::size_t msg_size);
572
573 static constexpr const char* FORMATTER = "RMC"; //!< Formatter
574};
575
576/**
577 * @brief NMEA-Gx-VTG message payload
578 */
580{
581 NmeaFloat cogt; //!< Course over ground (true) [deg]
582 NmeaFloat cogm; //!< Course over ground (magnetic) [deg], not typically available
583 NmeaFloat sogn; //!< Speed over ground [knots]
584 NmeaFloat sogk; //!< Speed over ground [km/h]
585 NmeaModeGllVtg mode = NmeaModeGllVtg::UNSPECIFIED; //!< Positioning system mode
586
587 /**
588 * @brief Set data from sentence
589 *
590 * @param[in] msg Pointer to the NMEA message
591 * @param[in] msg_size Size of the NMEA message (>= 11)
592 *
593 * @returns true if sentence payload was correct and all data could be extracted (fields are now valid), or false
594 * otherwise (fields are now invalid)
595 */
596 bool SetFromMsg(const uint8_t* msg, const std::size_t msg_size);
597
598 static constexpr const char* FORMATTER = "VTG"; //!< Talker
599};
600
601/**
602 * @brief NMEA-Gx-GST message payload
603 */
605{
606 NmeaTime time; //!< Time
607 NmeaFloat rms_range; //!< RMS value of the standard deviation of the range inputs to the navigation process
608 NmeaFloat std_major; //!< Standard deviation of semi-major axis of error ellipse
609 NmeaFloat std_minor; //!< Standard deviation of semi-minor axis of error ellipse
610 NmeaFloat angle_major; //!< Angle of semi-major axis of error ellipse from true North
611 NmeaFloat std_lat; //!< Standard deviation of latitude error
612 NmeaFloat std_lon; //!< Standard deviation of longitude error
613 NmeaFloat std_alt; //!< Standard deviation of altitude error
614
615 /**
616 * @brief Set data from sentence
617 *
618 * @param[in] msg Pointer to the NMEA message
619 * @param[in] msg_size Size of the NMEA message (>= 11)
620 *
621 * @returns true if sentence payload was correct and all data could be extracted (fields are now valid), or false
622 * otherwise (fields are now invalid)
623 */
624 bool SetFromMsg(const uint8_t* msg, const std::size_t msg_size);
625
626 static constexpr const char* FORMATTER = "GST"; //!< Formatter
627};
628
629/**
630 * @brief NMEA-Gx-HDT message payload
631 */
633{
634 NmeaFloat heading; //!< True heading
635
636 /**
637 * @brief Set data from sentence
638 *
639 * @param[in] msg Pointer to the NMEA message
640 * @param[in] msg_size Size of the NMEA message (>= 11)
641 *
642 * @returns true if sentence payload was correct and all data could be extracted (fields are now valid), or false
643 * otherwise (fields are now invalid)
644 */
645 bool SetFromMsg(const uint8_t* msg, const std::size_t msg_size);
646
647 static constexpr const char* FORMATTER = "HDT"; //!< Formatter
648};
649
650/**
651 * @brief NMEA-Gx-ZDA message payload
652 */
654{
655 NmeaTime time; //!< Time
656 NmeaDate date; //!< Date
657 NmeaInt local_hr; //!< Local zone hours, always 00 (= UTC)
658 NmeaInt local_min; //!< Local zone minutes, always 00 (= UTC)
659
660 /**
661 * @brief Set data from sentence
662 *
663 * @param[in] msg Pointer to the NMEA message
664 * @param[in] msg_size Size of the NMEA message (>= 11)
665 *
666 * @returns true if sentence payload was correct and all data could be extracted (fields are now valid), or false
667 * otherwise (fields are now invalid)
668 */
669 bool SetFromMsg(const uint8_t* msg, const std::size_t msg_size);
670
671 static constexpr const char* FORMATTER = "ZDA"; //!< Formatter
672};
673
674/**
675 * @brief NMEA-Gx-GSA message payload (NMEA 4.11 only!)
676 */
678{
681 std::array<NmeaSat, 12> sats; //!< Satellites, valid ones are 0..(num_sats-1)
682 int num_sats = 0; //!< Number of valid sats (the first n of sats[])
683 NmeaFloat pdop; //!< PDOP
684 NmeaFloat hdop; //!< HDOP
685 NmeaFloat vdop; //!< VDOP
687
688 /**
689 * @brief Set data from sentence
690 *
691 * @param[in] msg Pointer to the NMEA message
692 * @param[in] msg_size Size of the NMEA message (>= 11)
693 *
694 * @returns true if sentence payload was correct and all data could be extracted (fields are now valid), or false
695 * otherwise (fields are now invalid)
696 */
697 bool SetFromMsg(const uint8_t* msg, const std::size_t msg_size);
698
699 static constexpr const char* FORMATTER = "GSA"; //!< Formatter
700};
701
702/**
703 * @brief NMEA-Gx-GSV message payload (NMEA 4.11 only!)
704 */
706{
707 NmeaInt num_msgs; //!< Number of messages in this GSV sequence (for this signal ID)
708 NmeaInt msg_num; //!< Message number in sequence (1...num_msgs)
709 NmeaInt tot_num_sat; //!< Number of sat/sig info in the whole sequence of GSV messages
710 std::array<NmeaAzEl, 4> azels; //!< Satellite positions, valid ones are 0..(num_sats-1)
711 int num_azels = 0; //!< Number of valid satellite positions (the first n of azels[])
712 std::array<NmeaCno, 4> cnos; //!< Signal levels, valid ones are 0..(num_sats-1)
713 int num_cnos = 0; //!< Number of valid signal levels (the first n of azels[])
714 NmeaSystemId system; //!< System ID
715 NmeaSignalId signal; //!< Signal ID
716
717 /**
718 * @brief Set data from sentence
719 *
720 * @param[in] msg Pointer to the NMEA message
721 * @param[in] msg_size Size of the NMEA message (>= 11)
722 *
723 * @returns true if sentence payload was correct and all data could be extracted (fields are now valid), or false
724 * otherwise (fields are now invalid)
725 */
726 bool SetFromMsg(const uint8_t* msg, const std::size_t msg_size);
727
728 static constexpr const char* FORMATTER = "GSV"; //!< Formatter
729};
730
731// ---------------------------------------------------------------------------------------------------------------------
732
733/**
734 * @brief Collector for NMEA-Gx-GSA and NMEA-Gx-GPA
735 */
737{
738 /**
739 * @brief Satellite info
740 */
741 struct Sat
742 {
744 int svid_ = 0; //!< Satellite ID (numbering cf. NMEA 0183)
745 int az_ = 0; //!< Azimuth [deg] (0..360)
746 int el_ = 0; //!< Elevation [deg] (-90..90)
747 };
748
749 /**
750 * Signal info
751 */
752 struct Sig
753 {
755 int svid_ = 0; //!< Satellite ID (numbering cf. NMEA 0183)
757 double cno_ = 0.0; //!< Signal level [dBHz]
758 bool used_ = false; //!< Signal is used in navigation
759 };
760
761 std::vector<Sat> sats_; //!< Collected satellite info
762 std::vector<Sig> sigs_; //!< Collected signal info
763
764 /**
765 * @brief Add NMEA-GN-GSA message to collection
766 *
767 * These must be provided in order and completely, and before the GSV messages.
768 *
769 * @param[in] gsa Decoded message payload
770 *
771 * @returns true if the message was accepted, false otherwise
772 */
773 bool AddGsa(const NmeaGsaPayload& gsa);
774
775 /**
776 * @brief Add NMEA-Gx-GSV message to collection
777 *
778 * These must be provided in order and completely, and after the GSA messages.
779 *
780 * @param[in] gsv Decoded message payload
781 *
782 * @returns true if the message was accepted, false otherwise
783 */
784 bool AddGsv(const NmeaGsvPayload& gsv);
785
786 /**
787 * @brief Complete collection after feeding all GSA and GSV messages
788 */
789 void Complete();
790
791 /**
792 * @brief Add NMEA-GN-GSA and NMEA-Gx-GSV messages to collection
793 *
794 * Does all of AddGsa(), AddGsv() and Complete() in one call.
795 *
796 * @param[in] gsas All decoded message payloads, complete and in order
797 * @param[in] gsvs All decoded message payloads, complete and in order
798 *
799 * @returns true if all messages were collected successfully
800 */
801 bool AddGsaAndGsv(const std::vector<NmeaGsaPayload>& gsas, const std::vector<NmeaGsvPayload>& gsvs);
802
803 private:
804 std::vector<NmeaSat> gsa_sats_; //!< Satellites used
805};
806
807/* ****************************************************************************************************************** */
808} // namespace nmea
809} // namespace parser
810} // namespace common
811} // namespace fpsdk
812#endif // __FPSDK_COMMON_PARSER_NMEA_HPP__
NmeaSystemId
NMEA system IDs.
Definition nmea.hpp:332
NmeaModeRmcGns
NMEA-Gx-RMC and NMEA-Gx-GNS pos mode.
Definition nmea.hpp:276
static constexpr std::size_t NMEA_FRAME_SIZE
NMEA frame size ("$*cc\r\n")
Definition nmea.hpp:101
bool NmeaMakeMessage(std::vector< uint8_t > &msg, const std::string &payload)
Make a NMEA message.
NmeaOpModeGsa
NMEA-Gx-GNS operation mode.
Definition nmea.hpp:309
NmeaNavStatusRmc
NMEA-Gx-RMC navigational status.
Definition nmea.hpp:295
@ NA
Equipment does not provide navigational status.
static constexpr uint8_t NMEA_PREAMBLE
NMEA framing preamble.
Definition nmea.hpp:100
NmeaModeGllVtg
NMEA-Gx-GLL and NMEA-Gx-VTG pos mode.
Definition nmea.hpp:260
NmeaNavModeGsa
NMEA-Gx-GNS nav mode.
Definition nmea.hpp:319
NmeaTalkerId
NMEA talker IDs.
Definition nmea.hpp:212
@ GNSS
GNSS (multi-constellation)
NmeaStatusGllRmc
NMEA-Gx-GLL and NMEA-Gx-RMC status.
Definition nmea.hpp:247
bool NmeaGetMessageInfo(char *info, const std::size_t size, const uint8_t *msg, const std::size_t msg_size)
Get NMEA message info.
bool NmeaGetMessageMeta(NmeaMessageMeta &meta, const uint8_t *msg, const std::size_t msg_size)
Get NMEA message meta data.
NmeaSignalId
NMEA signal IDs.
Definition nmea.hpp:348
@ GPS_L1CA
GPS L1 C/A or SBAS L1 C/A.
bool NmeaGetMessageName(char *name, const std::size_t size, const uint8_t *msg, const std::size_t msg_size)
Get NMEA message name.
NmeaQualityGga
NMEA-Gx-GGA quality indicator.
Definition nmea.hpp:228
@ DGNSS
Differential GPS fix (e.g. with SBAS)
@ ESTIMATED
Estimated (dead reckoning only)
Fixposition SDK.
NmeaSystemId system
System ID.
Definition nmea.hpp:452
int az
Azimuth [deg] (0..360)
Definition nmea.hpp:455
int el
Elevation [deg] (-90..90)
Definition nmea.hpp:454
int svid
Satellite ID (numbering cf. NMEA 0183)
Definition nmea.hpp:453
int cno
Signal level [dBHz].
Definition nmea.hpp:467
NmeaSignalId signal
Signal ID.
Definition nmea.hpp:466
int svid
Satellite ID (numbering cf. NMEA 0183)
Definition nmea.hpp:465
NmeaSystemId system
System ID.
Definition nmea.hpp:464
int svid_
Satellite ID (numbering cf. NMEA 0183)
Definition nmea.hpp:744
int svid_
Satellite ID (numbering cf. NMEA 0183)
Definition nmea.hpp:755
bool used_
Signal is used in navigation.
Definition nmea.hpp:758
Collector for NMEA-Gx-GSA and NMEA-Gx-GPA.
Definition nmea.hpp:737
bool AddGsa(const NmeaGsaPayload &gsa)
Add NMEA-GN-GSA message to collection.
std::vector< Sat > sats_
Collected satellite info.
Definition nmea.hpp:761
bool AddGsv(const NmeaGsvPayload &gsv)
Add NMEA-Gx-GSV message to collection.
std::vector< Sig > sigs_
Collected signal info.
Definition nmea.hpp:762
bool AddGsaAndGsv(const std::vector< NmeaGsaPayload > &gsas, const std::vector< NmeaGsvPayload > &gsvs)
Add NMEA-GN-GSA and NMEA-Gx-GSV messages to collection.
void Complete()
Complete collection after feeding all GSA and GSV messages.
NMEA coordinates (integer degrees, float minutes and a sign for N/S resp. E/W)
Definition nmea.hpp:192
double min_
Fractional minutes value, >= 0.0.
Definition nmea.hpp:202
NmeaCoordinates(const double degs, const int digits=5)
Constructor.
bool sign_
false for negative (S or W), true for positive (N or E)
Definition nmea.hpp:203
int deg_
Integer degrees value, >= 0.
Definition nmea.hpp:201
NMEA date (year, month, day)
Definition nmea.hpp:392
bool operator==(const NmeaDate &rhs) const
Equal.
bool operator!=(const NmeaDate &rhs) const
Not equal.
NMEA-Gx-GGA message payload.
Definition nmea.hpp:502
static constexpr const char * FORMATTER
Formatter.
Definition nmea.hpp:522
NmeaFloat diff_age
Differential data age (optional, NMEA 4.11 only)
Definition nmea.hpp:508
NmeaLlh llh
Position (with height)
Definition nmea.hpp:504
NmeaFloat hdop
Horizontal dilution of precision (only with valid fix)
Definition nmea.hpp:507
NmeaQualityGga quality
Fix quality.
Definition nmea.hpp:505
NmeaInt diff_sta
Differential station ID (optional, NMEA 4.11 only)
Definition nmea.hpp:509
NmeaInt num_sv
Number of satellites used (may be limited to 12)
Definition nmea.hpp:506
bool SetFromMsg(const uint8_t *msg, const std::size_t msg_size)
Set data from sentence.
NMEA-Gx-GLL message payload.
Definition nmea.hpp:529
NmeaLlh ll
Position (no height)
Definition nmea.hpp:530
bool SetFromMsg(const uint8_t *msg, const std::size_t msg_size)
Set data from sentence.
static constexpr const char * FORMATTER
Formatter.
Definition nmea.hpp:546
NmeaStatusGllRmc status
Positioning system status.
Definition nmea.hpp:532
NmeaModeGllVtg mode
Positioning system mode.
Definition nmea.hpp:533
NMEA-Gx-GSA message payload (NMEA 4.11 only!)
Definition nmea.hpp:678
static constexpr const char * FORMATTER
Formatter.
Definition nmea.hpp:699
NmeaOpModeGsa opmode
Operation mode.
Definition nmea.hpp:679
int num_sats
Number of valid sats (the first n of sats[])
Definition nmea.hpp:682
std::array< NmeaSat, 12 > sats
Satellites, valid ones are 0..(num_sats-1)
Definition nmea.hpp:681
bool SetFromMsg(const uint8_t *msg, const std::size_t msg_size)
Set data from sentence.
NMEA-Gx-GST message payload.
Definition nmea.hpp:605
NmeaFloat angle_major
Angle of semi-major axis of error ellipse from true North.
Definition nmea.hpp:610
NmeaFloat std_lat
Standard deviation of latitude error.
Definition nmea.hpp:611
NmeaFloat std_alt
Standard deviation of altitude error.
Definition nmea.hpp:613
static constexpr const char * FORMATTER
Formatter.
Definition nmea.hpp:626
NmeaFloat std_lon
Standard deviation of longitude error.
Definition nmea.hpp:612
NmeaFloat std_major
Standard deviation of semi-major axis of error ellipse.
Definition nmea.hpp:608
NmeaFloat rms_range
RMS value of the standard deviation of the range inputs to the navigation process.
Definition nmea.hpp:607
bool SetFromMsg(const uint8_t *msg, const std::size_t msg_size)
Set data from sentence.
NmeaFloat std_minor
Standard deviation of semi-minor axis of error ellipse.
Definition nmea.hpp:609
NMEA-Gx-GSV message payload (NMEA 4.11 only!)
Definition nmea.hpp:706
int num_azels
Number of valid satellite positions (the first n of azels[])
Definition nmea.hpp:711
NmeaInt tot_num_sat
Number of sat/sig info in the whole sequence of GSV messages.
Definition nmea.hpp:709
NmeaInt num_msgs
Number of messages in this GSV sequence (for this signal ID)
Definition nmea.hpp:707
NmeaInt msg_num
Message number in sequence (1...num_msgs)
Definition nmea.hpp:708
std::array< NmeaAzEl, 4 > azels
Satellite positions, valid ones are 0..(num_sats-1)
Definition nmea.hpp:710
std::array< NmeaCno, 4 > cnos
Signal levels, valid ones are 0..(num_sats-1)
Definition nmea.hpp:712
bool SetFromMsg(const uint8_t *msg, const std::size_t msg_size)
Set data from sentence.
int num_cnos
Number of valid signal levels (the first n of azels[])
Definition nmea.hpp:713
static constexpr const char * FORMATTER
Formatter.
Definition nmea.hpp:728
NMEA-Gx-HDT message payload.
Definition nmea.hpp:633
static constexpr const char * FORMATTER
Formatter.
Definition nmea.hpp:647
bool SetFromMsg(const uint8_t *msg, const std::size_t msg_size)
Set data from sentence.
NMEA geodetic position.
Definition nmea.hpp:406
double height
Ellipsoidal (!) height [m].
Definition nmea.hpp:411
bool latlon_valid
Latitude/longitude is valid.
Definition nmea.hpp:407
double lon
Longitude [deg], >= 0.0 North, < 0.0 South.
Definition nmea.hpp:409
double lat
Latitude [deg], >= 0.0 East, < 0.0 West.
Definition nmea.hpp:408
bool height_valid
Height is valid.
Definition nmea.hpp:410
char talker_[3]
Talker ID (for example, "GP", "GN" or "P"), nul-terminated string.
Definition nmea.hpp:106
char formatter_[20]
Formatter (for example, "GGA", "RMC", or "UBX"), nul-terminated string.
Definition nmea.hpp:107
int payload_ix1_
Index (offset) for end of payload, 0 if no payload available.
Definition nmea.hpp:109
int payload_ix0_
Index (offset) for start of payload, 0 if no payload available.
Definition nmea.hpp:108
NMEA payload base class.
Definition nmea.hpp:492
bool valid_
Payload successfully decoded (true), or not (yet) decoded (false)
Definition nmea.hpp:494
virtual ~NmeaPayload()=default
Virtual dtor for polymorphism.
NMEA-Gx-RMC message payload.
Definition nmea.hpp:553
NmeaStatusGllRmc status
Positioning system status.
Definition nmea.hpp:555
bool SetFromMsg(const uint8_t *msg, const std::size_t msg_size)
Set data from sentence.
NmeaNavStatusRmc navstatus
Navigational status (optional)
Definition nmea.hpp:561
static constexpr const char * FORMATTER
Formatter.
Definition nmea.hpp:573
NmeaModeRmcGns mode
Positioning system mode indicator.
Definition nmea.hpp:560
NmeaFloat speed
Speed over ground [knots].
Definition nmea.hpp:557
NmeaFloat course
Course over ground w.r.t. True North [deg].
Definition nmea.hpp:558
NMEA satellite (used, e.g. in GSA)
Definition nmea.hpp:418
int svid
Satellite ID (numbering cf. NMEA 0183)
Definition nmea.hpp:421
NmeaSystemId system
System ID.
Definition nmea.hpp:420
NMEA time (hour, minutes, seconds)
Definition nmea.hpp:378
bool operator==(const NmeaTime &rhs) const
Equal.
bool operator!=(const NmeaTime &rhs) const
Not equal.
Constants for different versions of NMEA.
Definition nmea.hpp:428
const int svid_max_glo
Max GLONASS satellite ID.
Definition nmea.hpp:438
const int svid_max_gps
Max GPS satellite ID.
Definition nmea.hpp:430
const int svid_min_sbas
Min SBAS satellite ID.
Definition nmea.hpp:431
const int svid_min_bds
Min BeiDou satellite ID.
Definition nmea.hpp:435
static const NmeaVersion V410
Value for NMEA v4.10.
Definition nmea.hpp:441
const int svid_max_qzss
Max QZSS satellite ID, -1 if not available.
Definition nmea.hpp:440
const int svid_min_qzss
Min QZSS satellite ID, -1 if not available.
Definition nmea.hpp:439
const int svid_min_gps
Min GPS satellite ID.
Definition nmea.hpp:429
const int svid_min_gal
Min Galileo satellite ID.
Definition nmea.hpp:433
const int svid_max_gal
Max Galileo satellite ID.
Definition nmea.hpp:434
const int svid_max_sbas
Max SBAS satellite ID.
Definition nmea.hpp:432
static const NmeaVersion V410_UBX_EXT
Value for NMEA v4.10 extended (u-blox flavour)
Definition nmea.hpp:442
const int svid_min_glo
Min GLONASS satellite ID.
Definition nmea.hpp:437
static const NmeaVersion V411
Value for NMEA v4.11.
Definition nmea.hpp:443
const int svid_max_bds
Max BeiDou satellite ID.
Definition nmea.hpp:436
NMEA-Gx-VTG message payload.
Definition nmea.hpp:580
NmeaFloat cogt
Course over ground (true) [deg].
Definition nmea.hpp:581
bool SetFromMsg(const uint8_t *msg, const std::size_t msg_size)
Set data from sentence.
NmeaModeGllVtg mode
Positioning system mode.
Definition nmea.hpp:585
NmeaFloat sogk
Speed over ground [km/h].
Definition nmea.hpp:584
static constexpr const char * FORMATTER
Talker.
Definition nmea.hpp:598
NmeaFloat sogn
Speed over ground [knots].
Definition nmea.hpp:583
NmeaFloat cogm
Course over ground (magnetic) [deg], not typically available.
Definition nmea.hpp:582
NMEA-Gx-ZDA message payload.
Definition nmea.hpp:654
bool SetFromMsg(const uint8_t *msg, const std::size_t msg_size)
Set data from sentence.
NmeaInt local_hr
Local zone hours, always 00 (= UTC)
Definition nmea.hpp:657
static constexpr const char * FORMATTER
Formatter.
Definition nmea.hpp:671
NmeaInt local_min
Local zone minutes, always 00 (= UTC)
Definition nmea.hpp:658