35 #include <boost/algorithm/string/split.hpp> 36 #include <boost/algorithm/string/classification.hpp> 60 ulCRC =
static_cast<uint32_t
>(i);
61 for ( j = 8 ; j > 0; j-- )
73 const uint8_t* ucBuffer )
78 while ( ulCount-- != 0 )
80 ulTemp1 =
static_cast<uint32_t
>(( ulCRC >> 8u ) & 0x00FFFFFFL);
81 ulTemp2 =
CRC32Value( ((int32_t) ulCRC ^ *ucBuffer++ ) & 0xffu );
82 ulCRC = ulTemp1 ^ ulTemp2;
90 std::string::const_iterator it = sentence.begin();
91 for (; it != sentence.end(); ++it)
104 const std::string& str,
105 std::vector<std::string>& vectorized_message,
106 const std::string& delimiters)
108 boost::algorithm::split(vectorized_message, str, boost::algorithm::is_any_of(delimiters));
112 const std::string& sentence,
113 std::string& message_id,
114 std::vector<std::string>& header,
115 std::vector<std::string>& body)
121 std::vector<std::string> vectorized_message;
124 if (vectorized_message.size() != 2)
135 message_id = header.front();
152 ROS_DEBUG(
"Binary message was too short to parse.");
165 ROS_ERROR(
"Sync bytes were incorrect; this should never happen and is definitely a bug: %x %x %x",
172 ROS_WARN(
"Binary header length was unexpected: %u (expected %u)",
176 ROS_DEBUG(
"Msg ID: %u Data start / length: %u / %u",
179 if (data_start + data_length + 4 > str.length())
185 ROS_DEBUG(
"Reading binary message data.");
186 msg.
data_.resize(data_length);
187 std::copy(&str[data_start], &str[data_start+data_length], reinterpret_cast<char*>(&msg.
data_[0]));
192 reinterpret_cast<const uint8_t*>(&str[start_idx]));
195 msg.
crc_ =
ParseUInt32(reinterpret_cast<const uint8_t*>(&str[data_start+data_length]));
200 ROS_DEBUG(
"Invalid CRC; Calc: %u In msg: %u", crc, msg.
crc_);
206 ROS_DEBUG(
"Finishing reading binary message.");
211 const std::string& str,
213 std::string& sentence)
218 if (checksum_start == std::string::npos)
223 else if (checksum_start + 8 >= str.size())
231 sentence = str.substr(start_idx + 1, checksum_start - start_idx - 1);
232 std::string checksum_str = str.substr(checksum_start + 1, 8);
233 uint64_t checksum = std::strtoul(checksum_str.c_str(),
nullptr, 16);
235 static_cast<uint32_t>(sentence.size()),
236 reinterpret_cast<const uint8_t*>(sentence.c_str()));
238 if (checksum == ULONG_MAX)
243 else if(static_cast<uint32_t>(checksum) == calculated_checksum)
249 ROS_WARN(
"Expected checksum: [%lx]", calculated_checksum);
257 const std::string& str,
259 std::string& sentence,
265 if (checksum_start == std::string::npos)
270 else if (checksum_start + 2 >= str.size())
278 sentence = str.substr(start_idx + 1, checksum_start - start_idx - 1);
279 std::string checksum_str = str.substr(checksum_start + 1, 2);
280 uint64_t checksum = std::strtoul(checksum_str.c_str(),
nullptr, 16);
282 if (checksum == ULONG_MAX)
287 else if(static_cast<uint32_t>(checksum) == calculated_checksum)
291 sentence.insert(0,
"$");
292 std::string recreated_checksum_str(
"*");
293 recreated_checksum_str += checksum_str;
294 sentence.insert(sentence.end(),
295 recreated_checksum_str.begin(),
296 recreated_checksum_str.end());
302 ROS_WARN(
"Expected: [%lx]", calculated_checksum);
313 size_t& invalid_char_idx)
316 end_idx = std::string::npos;
317 invalid_char_idx = std::string::npos;
319 if (start_idx == std::string::npos)
326 size_t search_stop_idx = std::min(end_idx, sentence.length());
327 for (
size_t i = start_idx; i < search_stop_idx; i++)
329 if (sentence[i] == 9 || sentence[i] == 10 || sentence[i] == 11 || sentence[i] == 13 ||
330 (sentence[i] >= 32 && sentence[i] <= 126))
335 invalid_char_idx = i;
341 const std::string& data,
349 const std::string& sentence,
353 if (!vectorized_message.
body.empty())
355 vectorized_message.
id = vectorized_message.
body.front();
360 const std::string& input,
361 std::vector<NmeaSentence>& nmea_sentences,
362 std::vector<NovatelSentence>& novatel_sentences,
363 std::vector<BinaryMessage>& binary_messages,
364 std::string& remaining,
365 bool keep_nmea_container)
367 bool parse_error =
false;
369 size_t sentence_start = 0;
370 while(sentence_start != std::string::npos && sentence_start < input.size())
372 size_t ascii_start_idx;
373 size_t ascii_end_idx;
374 size_t invalid_ascii_idx;
377 FindAsciiSentence(input, sentence_start, ascii_start_idx, ascii_end_idx, invalid_ascii_idx);
379 ROS_DEBUG(
"Binary start: %lu ASCII start / end / invalid: %lu / %lu / %lu",
380 binary_start_idx, ascii_start_idx, ascii_end_idx, invalid_ascii_idx);
382 if (binary_start_idx == std::string::npos && ascii_start_idx == std::string::npos)
388 if (ascii_start_idx == std::string::npos ||
389 (binary_start_idx != std::string::npos && binary_start_idx < ascii_start_idx))
397 binary_messages.push_back(cur_msg);
398 sentence_start += binary_start_idx + result;
399 ROS_DEBUG(
"Parsed a binary message with %u bytes.", result);
401 else if (result == -1)
404 remaining = input.substr(binary_start_idx);
405 ROS_DEBUG(
"Binary message was incomplete, waiting for more.");
412 ROS_WARN(
"Invalid binary message checksum");
419 size_t ascii_len = ascii_end_idx - ascii_start_idx;
420 if (invalid_ascii_idx != std::string::npos)
425 ROS_WARN(
"Invalid ASCII char: [%s]", input.substr(ascii_start_idx, ascii_len).c_str());
426 ROS_WARN(
" %s^", std::string(invalid_ascii_idx-ascii_start_idx-1,
' ').c_str());
427 sentence_start += invalid_ascii_idx + 1;
429 else if (ascii_end_idx != std::string::npos)
433 ROS_DEBUG(
"ASCII sentence:\n[%s]", input.substr(ascii_start_idx, ascii_len).c_str());
436 std::string cur_sentence;
441 keep_nmea_container);
446 sentence_start = ascii_end_idx;
454 remaining = input.substr(ascii_start_idx);
455 ROS_DEBUG(
"Waiting for more NMEA data.");
460 ROS_WARN(
"Invalid NMEA checksum for: [%s]",
461 input.substr(ascii_start_idx, ascii_len).c_str());
469 std::string cur_sentence;
477 novatel_sentences.pop_back();
481 sentence_start = ascii_end_idx;
490 remaining = input.substr(ascii_start_idx);
491 ROS_DEBUG(
"Waiting for more NovAtel data.");
498 ROS_WARN(
"Invalid NovAtel checksum for: [%s]",
499 input.substr(ascii_start_idx, ascii_len).c_str());
506 ROS_DEBUG(
"Incomplete ASCII sentence, waiting for more.");
507 remaining = input.substr(ascii_start_idx);
518 std::vector<NmeaSentence>::const_reverse_iterator iter;
519 for (iter = sentences.rbegin(); iter != sentences.rend(); iter++)
523 if (iter->body.size() > 1)
525 if (iter->body[1].empty() || iter->body[1] ==
"0")
546 const novatel_gps_msgs::Gprmc& gprmc,
547 const novatel_gps_msgs::Gpgga& gpgga,
548 const gps_common::GPSFixPtr& gps_fix)
550 gps_fix->header.stamp = gpgga.header.stamp;
551 gps_fix->altitude = gpgga.alt;
565 gps_fix->hdop = gpgga.hdop;
566 gps_fix->latitude = gprmc.lat;
567 if (gpgga.lat_dir ==
"S")
569 gps_fix->latitude *= -1;
572 gps_fix->longitude = gprmc.lon;
573 if (gpgga.lon_dir ==
"W")
575 gps_fix->longitude *= -1;
580 gps_fix->speed = gprmc.speed;
582 gps_fix->time = gpgga.utc_seconds;
583 gps_fix->track = gprmc.track;
586 switch (gpgga.gps_qual)
588 case novatel_gps_msgs::Gpgga::GPS_QUAL_INVALID:
589 gps_fix->status.status = gps_common::GPSStatus::STATUS_NO_FIX;
591 case novatel_gps_msgs::Gpgga::GPS_QUAL_WASS:
592 gps_fix->status.status = gps_common::GPSStatus::STATUS_WAAS_FIX;
596 gps_fix->status.status = gps_common::GPSStatus::STATUS_FIX;
599 gps_fix->status.satellites_used =
static_cast<uint16_t
>(gpgga.num_sats);
std::vector< std::string > header
static const std::string MESSAGE_NAME
#define ROS_ERROR_THROTTLE(rate,...)
uint32_t ParseUInt32(const uint8_t *buffer)
Converts a buffer containing 4 bytes into an unsigned 32-bit int.
std::vector< std::string > body
std::vector< std::string > body
static const std::string MESSAGE_NAME
double UtcFloatToSeconds(double utc_float)
std::vector< uint8_t > data_
bool ToDouble(const std::string &string, double &value)