Main MRPT website > C++ reference for MRPT 1.9.9
CGPSInterface_parser_NOVATEL_OEM6.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "hwdrivers-precomp.h" // Precompiled headers
11 
12 #include <mrpt/system/os.h>
13 #include <mrpt/system/filesystem.h>
16 #include <mrpt/utils/crc.h>
17 
18 using namespace mrpt::hwdrivers;
19 using namespace mrpt::obs;
20 using namespace std;
21 
23  size_t& out_minimum_rx_buf_to_decide)
24 {
25  // to be grabbed from the last Message_NV_OEM6_IONUTC msg
26  static uint32_t num_leap_seconds =
27  getenv("MRPT_HWDRIVERS_DEFAULT_LEAP_SECONDS") == nullptr
28  ? 18
29  : atoi(getenv("MRPT_HWDRIVERS_DEFAULT_LEAP_SECONDS"));
30 
31  using namespace mrpt::obs::gnss;
32 
33  out_minimum_rx_buf_to_decide = sizeof(nv_oem6_short_header_t);
34 
35  const size_t nBytesAval = m_rx_buffer.size(); // Available for read
36  if (nBytesAval < out_minimum_rx_buf_to_decide)
37  return true; // no need to skip 1 byte
38 
39  // If the synch bytes do not match, it is not a valid frame:
40  uint8_t peek_buffer[3];
41  m_rx_buffer.peek_many(&peek_buffer[0], 3);
42  // Short header?
43  const bool is_short_hdr =
44  peek_buffer[0] == nv_oem6_short_header_t::SYNCH0 &&
45  peek_buffer[1] == nv_oem6_short_header_t::SYNCH1 &&
46  peek_buffer[2] == nv_oem6_short_header_t::SYNCH2;
47 
48  const bool is_regular_hdr = peek_buffer[0] == nv_oem6_header_t::SYNCH0 &&
49  peek_buffer[1] == nv_oem6_header_t::SYNCH1 &&
50  peek_buffer[2] == nv_oem6_header_t::SYNCH2;
51 
52  if (!is_short_hdr && !is_regular_hdr)
53  return false; // skip 1 byte, we dont recognize this format
54 
55  if (is_short_hdr)
56  {
57  if (nBytesAval < sizeof(nv_oem6_short_header_t))
58  {
59  out_minimum_rx_buf_to_decide = sizeof(nv_oem6_short_header_t);
60  return true; // we must wait for more data in the buffer
61  }
63  m_rx_buffer.peek_many(reinterpret_cast<uint8_t*>(&hdr), sizeof(hdr));
64  const uint32_t expected_total_msg_len =
65  sizeof(hdr) + hdr.msg_len + 4 /*crc*/;
66  if (nBytesAval < expected_total_msg_len)
67  {
68  out_minimum_rx_buf_to_decide = expected_total_msg_len;
69  return true; // we must wait for more data in the buffer
70  }
71 
72  std::vector<uint8_t> buf(expected_total_msg_len);
73  m_rx_buffer.pop_many(reinterpret_cast<uint8_t*>(&buf[0]), sizeof(hdr));
74  m_rx_buffer.pop_many(
75  reinterpret_cast<uint8_t*>(&buf[sizeof(hdr)]),
76  hdr.msg_len + 4 /*crc*/);
77 
78  // Check CRC:
79  const uint32_t crc_computed =
80  mrpt::utils::compute_CRC32(&buf[0], expected_total_msg_len - 4);
81  const uint32_t crc_read = (buf[expected_total_msg_len - 1] << 24) |
82  (buf[expected_total_msg_len - 2] << 16) |
83  (buf[expected_total_msg_len - 3] << 8) |
84  (buf[expected_total_msg_len - 4] << 0);
85  if (crc_read != crc_computed)
86  return false; // skip 1 byte, we dont recognize this format
87 
88  // Deserialize the message:
89  // 1st, test if we have a specific data structure for this msg_id:
90  const bool use_generic_container = !gnss_message::FactoryKnowsMsgType(
92  // ------ Serialization format:
93  // const int32_t msg_id = message_type;
94  // out << msg_id;
95  // this->internal_writeToStream(out); == > out <<
96  // static_cast<uint32_t>(DATA_LEN); out.WriteBuffer(DATA_PTR,DATA_LEN);
97  // }
98  // ------
100  const uint32_t msg_id = use_generic_container
103  tmpStream << (uint32_t)(msg_id);
104  tmpStream << (uint32_t)(
105  expected_total_msg_len); // This len = hdr + hdr.msg_len + 4 (crc);
106  tmpStream.WriteBuffer(&buf[0], buf.size());
107 
108  tmpStream.Seek(0);
109  gnss_message_ptr msg(gnss_message::readAndBuildFromStream(tmpStream));
110  if (!msg.get())
111  {
112  std::cerr << "[CGPSInterface::implement_parser_NOVATEL_OEM6] Error "
113  "parsing binary packet msg_id="
114  << hdr.msg_id << "\n";
115  return true;
116  }
117  m_just_parsed_messages.messages[msg->message_type] = msg;
118  m_just_parsed_messages.originalReceivedTimestamp = mrpt::system::now();
119  if (!CObservationGPS::GPS_time_to_UTC(
120  hdr.week, hdr.ms_in_week * 1e-3, num_leap_seconds,
121  m_just_parsed_messages.timestamp))
122  m_just_parsed_messages.timestamp = mrpt::system::now();
123  else
124  m_just_parsed_messages.has_satellite_timestamp = true;
125 
126  m_just_parsed_messages.sensorLabel = msg->getMessageTypeAsString();
127 
128  flushParsedMessagesNow();
129  return true;
130  } // end short hdr
131 
132  if (is_regular_hdr)
133  {
134  if (nBytesAval < sizeof(nv_oem6_header_t))
135  {
136  out_minimum_rx_buf_to_decide = sizeof(nv_oem6_header_t);
137  return true; // we must wait for more data in the buffer
138  }
139  nv_oem6_header_t hdr;
140  m_rx_buffer.peek_many(reinterpret_cast<uint8_t*>(&hdr), sizeof(hdr));
141  const uint32_t expected_total_msg_len =
142  sizeof(hdr) + hdr.msg_len + 4 /*crc*/;
143  if (nBytesAval < expected_total_msg_len)
144  {
145  out_minimum_rx_buf_to_decide = expected_total_msg_len;
146  return true; // we must wait for more data in the buffer
147  }
148 
149  std::vector<uint8_t> buf(expected_total_msg_len);
150  m_rx_buffer.pop_many(reinterpret_cast<uint8_t*>(&buf[0]), sizeof(hdr));
151  m_rx_buffer.pop_many(
152  reinterpret_cast<uint8_t*>(&buf[sizeof(hdr)]),
153  hdr.msg_len + 4 /*crc*/);
154 
155  // Check CRC:
156  const uint32_t crc_computed =
157  mrpt::utils::compute_CRC32(&buf[0], expected_total_msg_len - 4);
158  const uint32_t crc_read = (buf[expected_total_msg_len - 1] << 24) |
159  (buf[expected_total_msg_len - 2] << 16) |
160  (buf[expected_total_msg_len - 3] << 8) |
161  (buf[expected_total_msg_len - 4] << 0);
162  if (crc_read != crc_computed)
163  return false; // skip 1 byte, we dont recognize this format
164 
165  // Deserialize the message:
166  // 1st, test if we have a specific data structure for this msg_id:
167  const bool use_generic_container = !gnss_message::FactoryKnowsMsgType(
169  // ------ Serialization format:
170  // const int32_t msg_id = message_type;
171  // out << msg_id;
172  // this->internal_writeToStream(out); == > out <<
173  // static_cast<uint32_t>(DATA_LEN); out.WriteBuffer(DATA_PTR,DATA_LEN);
174  // }
175  // ------
176  mrpt::utils::CMemoryStream tmpStream;
177  const int32_t msg_id = use_generic_container
180  tmpStream << msg_id;
181  tmpStream << (uint32_t)(expected_total_msg_len);
182  tmpStream.WriteBuffer(&buf[0], buf.size());
183 
184  tmpStream.Seek(0);
185  gnss_message_ptr msg(gnss_message::readAndBuildFromStream(tmpStream));
186  if (!msg.get())
187  {
188  std::cerr << "[CGPSInterface::implement_parser_NOVATEL_OEM6] Error "
189  "parsing binary packet msg_id="
190  << hdr.msg_id << "\n";
191  return true;
192  }
193  m_just_parsed_messages.messages[msg->message_type] = msg;
194  m_just_parsed_messages.originalReceivedTimestamp = mrpt::system::now();
195  {
196  // Detect NV_OEM6_IONUTC msgs to learn about the current leap
197  // seconds:
198  const gnss::Message_NV_OEM6_IONUTC* ionutc =
199  dynamic_cast<const gnss::Message_NV_OEM6_IONUTC*>(msg.get());
200  if (ionutc) num_leap_seconds = ionutc->fields.deltat_ls;
201  }
202  if (!CObservationGPS::GPS_time_to_UTC(
203  hdr.week, hdr.ms_in_week * 1e-3, num_leap_seconds,
204  m_just_parsed_messages.timestamp))
205  m_just_parsed_messages.timestamp = mrpt::system::now();
206  else
207  m_just_parsed_messages.has_satellite_timestamp = true;
208 
209  m_just_parsed_messages.sensorLabel = msg->getMessageTypeAsString();
210  flushParsedMessagesNow();
211  return true;
212  } // end regular hdr
213 
214  // Shouldnt arrive here, but MSVC complies anyway:
215  return false;
216 }
uint64_t Seek(uint64_t Offset, CStream::TSeekOrigin Origin=sFromBeginning) override
Introduces a pure virtual method for moving to a specified position in the streamed resource...
gnss_message_type_t
List of all known GNSS message types.
void WriteBuffer(const void *Buffer, size_t Count)
Writes a block of bytes to the stream from Buffer.
Definition: CStream.cpp:64
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Definition: datetime.h:76
Contains classes for various device interfaces.
STL namespace.
Novatel OEM6 regular header structure.
unsigned char uint8_t
Definition: rptypes.h:41
This CStream derived class allow using a memory buffer as a CStream.
Definition: CMemoryStream.h:27
This namespace contains representation of robot actions and observations.
bool implement_parser_NOVATEL_OEM6(size_t &out_minimum_rx_buf_to_decide)
gnss_message_type_t message_type
Type of GNSS message.
Novatel OEM6 short header structure.
GNSS (GPS) data structures, mainly for use within mrpt::obs::CObservationGPS.
__int32 int32_t
Definition: rptypes.h:46
uint32_t compute_CRC32(const std::vector< uint8_t > &data, const uint32_t gen_pol=0xEDB88320L)
Computes the CRC32 checksum of a block of data.
Definition: crc.cpp:26
const std::string & getMessageTypeAsString() const
Returns "NMEA_GGA", etc.
unsigned __int32 uint32_t
Definition: rptypes.h:47
A smart pointer to a GNSS message.



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019