26 out_minimum_rx_buf_to_decide = 3;
28 if (m_rx_buffer.size() < 3)
return true;
30 const size_t nBytesAval = m_rx_buffer.size();
34 m_rx_buffer.peek_many(&buf[0], 3);
38 static const std::array<const char*, 12> known_prefixes = {
39 "BD",
"CD",
"EC",
"GA",
"GB",
"GL",
"GN",
"GP",
"II",
"IN",
"LC",
"QZ"};
41 bool recognized =
false;
44 for (
const char* prefix : known_prefixes)
46 if (buf[1] == prefix[0] && buf[2] == prefix[1])
54 if (!recognized)
return false;
58 bool line_is_ended =
false;
61 const char val =
static_cast<char>(m_rx_buffer.peek(i));
62 if (
val ==
'\r' ||
val ==
'\n')
72 for (
size_t i = 0; i < line.size(); i++) m_rx_buffer.pop();
75 const bool did_have_gga = m_just_parsed_messages.has_GGA_datum();
77 line, m_just_parsed_messages,
false ))
80 m_just_parsed_messages.sensorLabel =
"NMEA";
83 const bool now_has_gga = m_just_parsed_messages.has_GGA_datum();
84 if (now_has_gga && !did_have_gga)
92 std::cerr <<
"[CGPSInterface::implement_parser_NMEA] Line " 93 "of unknown format ignored: `" 101 out_minimum_rx_buf_to_decide = nBytesAval + 1;
118 if (
verbose) cout <<
"[CGPSInterface] GPS raw string: " << s << endl;
121 if (s.size() < 7)
return false;
122 if (s[0] !=
'$')
return false;
124 std::vector<std::string> lstTokens;
126 s,
"*,\t\r\n", lstTokens,
false );
127 if (lstTokens.size() < 3)
return false;
129 for (
auto& lstToken : lstTokens)
132 bool parsed_ok =
false;
135 if (lstTokens[0].
size() > 3) lstTokens[0] = lstTokens[0].substr(3);
138 if (lstTokens[0] ==
"GGA" && lstTokens.size() >= 13)
143 bool all_fields_ok =
true;
150 token = lstTokens[1];
151 if (token.size() >= 6)
158 all_fields_ok =
false;
161 token = lstTokens[2];
162 if (token.size() >= 4)
164 double lat = 10 * (token[0] -
'0') + token[1] -
'0';
165 lat += atof(&(token.c_str()[2])) / 60.0;
169 all_fields_ok =
false;
172 token = lstTokens[3];
174 all_fields_ok =
false;
175 else if (token[0] ==
'S')
179 token = lstTokens[4];
180 if (token.size() >= 5)
183 100 * (token[0] -
'0') + 10 * (token[1] -
'0') + token[2] -
'0';
184 lat += atof(&(token.c_str()[3])) / 60.0;
188 all_fields_ok =
false;
191 token = lstTokens[5];
193 all_fields_ok =
false;
194 else if (token[0] ==
'W')
198 token = lstTokens[6];
203 token = lstTokens[7];
208 token = lstTokens[8];
216 token = lstTokens[9];
218 all_fields_ok =
false;
227 token = lstTokens[11];
248 parsed_ok = all_fields_ok;
250 else if (lstTokens[0] ==
"RMC" && lstTokens.size() >= 13)
255 bool all_fields_ok =
true;
262 token = lstTokens[1];
263 if (token.size() >= 6)
270 all_fields_ok =
false;
273 token = lstTokens[2];
275 all_fields_ok =
false;
280 token = lstTokens[3];
281 if (token.size() >= 4)
283 double lat = 10 * (token[0] -
'0') + token[1] -
'0';
284 lat += atof(&(token.c_str()[2])) / 60.0;
288 all_fields_ok =
false;
291 token = lstTokens[4];
293 all_fields_ok =
false;
294 else if (token[0] ==
'S')
298 token = lstTokens[5];
299 if (token.size() >= 5)
302 100 * (token[0] -
'0') + 10 * (token[1] -
'0') + token[2] -
'0';
303 lat += atof(&(token.c_str()[3])) / 60.0;
307 all_fields_ok =
false;
310 token = lstTokens[6];
312 all_fields_ok =
false;
313 else if (token[0] ==
'W')
317 token = lstTokens[7];
321 token = lstTokens[8];
325 token = lstTokens[9];
326 if (token.size() >= 6)
333 all_fields_ok =
false;
336 token = lstTokens[10];
337 if (token.size() >= 2)
341 token = lstTokens[11];
343 all_fields_ok =
false;
344 else if (token[0] ==
'W')
349 if (lstTokens.size() >= 14)
352 token = lstTokens[12];
354 all_fields_ok =
false;
371 parsed_ok = all_fields_ok;
373 else if (lstTokens[0] ==
"GLL" && lstTokens.size() >= 5)
378 bool all_fields_ok =
true;
384 token = lstTokens[1];
385 if (token.size() >= 4)
387 double lat = 10 * (token[0] -
'0') + token[1] -
'0';
388 lat += atof(&(token.c_str()[2])) / 60.0;
392 all_fields_ok =
false;
395 token = lstTokens[2];
397 all_fields_ok =
false;
398 else if (token[0] ==
'S')
402 token = lstTokens[3];
403 if (token.size() >= 5)
406 100 * (token[0] -
'0') + 10 * (token[1] -
'0') + token[2] -
'0';
407 lat += atof(&(token.c_str()[3])) / 60.0;
411 all_fields_ok =
false;
414 token = lstTokens[4];
416 all_fields_ok =
false;
417 else if (token[0] ==
'W')
420 if (lstTokens.size() >= 7)
423 token = lstTokens[5];
424 if (token.size() >= 6)
427 10 * (token[0] -
'0') + token[1] -
'0';
429 10 * (token[2] -
'0') + token[3] -
'0';
433 all_fields_ok =
false;
436 token = lstTokens[6];
438 all_fields_ok =
false;
452 parsed_ok = all_fields_ok;
454 else if (lstTokens[0] ==
"VTG" && lstTokens.size() >= 9)
459 bool all_fields_ok =
true;
470 if (lstTokens[2] !=
"T" || lstTokens[4] !=
"M" || lstTokens[6] !=
"N" ||
472 all_fields_ok =
false;
481 parsed_ok = all_fields_ok;
483 else if (lstTokens[0] ==
"ZDA" && lstTokens.size() >= 5)
488 bool all_fields_ok =
true;
502 token = lstTokens[1];
503 if (token.size() >= 6)
510 all_fields_ok =
false;
513 token = lstTokens[2];
516 token = lstTokens[3];
519 token = lstTokens[4];
539 parsed_ok = all_fields_ok;
541 else if (lstTokens[0] ==
"GSA" && lstTokens.size() >= 18)
546 bool all_fields_ok =
true;
563 token = lstTokens[1];
567 all_fields_ok =
false;
569 token = lstTokens[2];
573 all_fields_ok =
false;
575 for (
int i = 0; i < 12; i++)
577 token = lstTokens[3 + i];
578 if (token.size() > 0) gsa.
fields.
PRNs[i][0] = token[0];
579 if (token.size() > 1) gsa.
fields.
PRNs[i][1] = token[1];
591 parsed_ok = all_fields_ok;
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
uint8_t fix_quality
NMEA standard values: 0 = invalid, 1 = GPS fix (SPS), 2 = DGPS fix, 3 = PPS fix, 4 = Real Time Kinema...
content_t fields
Message content, accesible by individual fields.
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
mrpt::system::TTimeStamp getAsTimestamp(const mrpt::system::TTimeStamp &date) const
Build an MRPT timestamp with the hour/minute/sec of this structure and the date from the given timest...
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
size_t size(const MATRIXLIKE &m, const int dim)
mrpt::system::TTimeStamp originalReceivedTimestamp
The local computer-based timestamp based on the reception of the message in the computer.
content_t fields
Message content, accesible by individual fields.
content_t fields
Message content, accesible by individual fields.
uint32_t satellitesUsed
The number of satelites used to compute this estimation.
char fix_2D_3D
1: no fix, 2: 2D fix, 3: 3D fix
const size_t MAX_NMEA_LINE_LENGTH
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Contains classes for various device interfaces.
content_t fields
Message content, accesible by individual fields.
UTC_time UTCTime
The GPS sensor measured timestamp (in UTC time)
int8_t validity_char
This will be: 'A'=OK or 'V'=void.
UTC_time UTCTime
The GPS sensor measured timestamp (in UTC time)
void tokenize(const std::string &inString, const std::string &inDelimiters, OUT_CONTAINER &outTokens, bool skipBlankTokens=true) noexcept
Tokenizes a string according to a set of delimiting characters.
double orthometric_altitude
The measured orthometric altitude, in meters (A)+(B).
mrpt::Clock::time_point TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1...
double altitude_meters
The measured altitude, in meters (A).
bool thereis_HDOP
This states whether to take into account the value in the HDOP field.
UTC_time UTCTime
The GPS sensor measured timestamp (in UTC time)
double corrected_orthometric_altitude
The corrected (only for TopCon mmGPS) orthometric altitude, in meters mmGPS(A+B). ...
mrpt::system::TTimeStamp getDateAsTimestamp() const
Build an MRPT timestamp with the year/month/day of this observation.
bool implement_parser_NMEA(size_t &out_minimum_rx_buf_to_decide)
char PRNs[12][2]
Satellite IDs used.
uint8_t date_day
Date: day (1-31), month (1-12), two-digits year (00-99)
content_t fields
Message content, accesible by individual fields.
float HDOP
The HDOP (Horizontal Dilution of Precision) as returned by the sensor.
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
This namespace contains representation of robot actions and observations.
double lat
[deg], [deg], hgt over sea level[m]
bool has_satellite_timestamp
If true, CObservation::timestamp has been generated from accurate satellite clock.
static bool parse_NMEA(const std::string &cmd_line, mrpt::obs::CObservationGPS &out_obs, const bool verbose=false)
Parses one line of NMEA data from a GPS receiver, and writes the recognized fields (if any) into an o...
double geoidal_distance
Undulation: Difference between the measured altitude and the geoid, in meters (B).
double magnetic_dir
Magnetic variation direction (East:+, West:-)
mrpt::system::TTimeStamp getDateAsTimestamp() const
Build an MRPT timestamp with the year/month/day of this observation.
mrpt::system::TTimeStamp getDateTimeAsTimestamp() const
Build an MRPT UTC timestamp with the year/month/day + hour/minute/sec of this observation.
void setMsg(const MSG_CLASS &msg)
Stores a message in the list messages, making a copy of the passed object.
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
double speed_knots
Measured speed (in knots)
double direction_degrees
Measured speed direction (in degrees)
char positioning_mode
'A': Autonomous, 'D': Differential, 'N': Not valid, 'E': Estimated, 'M': Manual
content_t fields
Message content, accesible by individual fields.
std::string trim(const std::string &str)
Removes leading and trailing spaces.
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
int8_t validity_char
This will be: 'A'=OK or 'V'=void.
double ground_speed_knots
This class stores messages from GNSS or GNSS+IMU devices, from consumer-grade inexpensive GPS receive...
uint16_t date_year
2000-...
double true_track
Degrees.
UTC_time UTCTime
The GPS sensor measured timestamp (in UTC time)
for(unsigned int i=0;i< NUM_IMGS;i++)
static struct FontData data