0.4.1
Loading...
Searching...
No Matches
UbloxUartSensor.cpp
Go to the documentation of this file.
1// This file is part of INSTINCT, the INS Toolkit for Integrated
2// Navigation Concepts and Training by the Institute of Navigation of
3// the University of Stuttgart, Germany.
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#include "UbloxUartSensor.hpp"
10
11#include "UbloxUtilities.hpp"
12
14
16 : _name(std::move(name)), _buffer(uart::sensors::UartSensor::DefaultReadBufferSize)
17{
19}
20
22{
23 LOG_DATA("{}: Reset tracking", _name);
26
27 _asciiEndChar1Found = false;
30 _binaryMsgIdFound = false;
33
34#if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__clang__)
35 #pragma GCC diagnostic push
36 #pragma GCC diagnostic ignored "-Wstringop-overflow"
37#endif
39 _binaryMsgId = 0;
41#if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__clang__)
42 #pragma GCC diagnostic pop
43#endif
44
45 _buffer.resize(0);
47#if LOG_LEVEL <= LOG_LEVEL_DATA
48 _unrecognizedBytes.clear();
49#endif
50}
51
52std::unique_ptr<uart::protocol::Packet> NAV::vendor::ublox::UbloxUartSensor::findPacket(uint8_t dataByte)
53{
54 if (_buffer.size() == _buffer.capacity())
55 {
56 // Buffer is full
58 LOG_ERROR("{}: Discarding current packet, because buffer is full", _name);
59 }
60
62 {
63#if LOG_LEVEL <= LOG_LEVEL_DATA
64 if (dataByte == BINARY_SYNC_CHAR_1 || dataByte == ASCII_START_CHAR)
65 {
66 if (!_unrecognizedBytes.empty())
67 {
68 LOG_DATA("{}: {} unrecognized bytes since last message: {}", _name, _unrecognizedBytes.size(), joinToString(_unrecognizedBytes, " ", ":x"));
69 }
70 }
71 else
72 {
73 _unrecognizedBytes.push_back(dataByte);
74 }
75#endif
76 // This byte must be the start char
77 if (dataByte == BINARY_SYNC_CHAR_1)
78 {
79 LOG_DATA("{}: 1st sync character found", _name);
82 _buffer.push_back(dataByte);
83 }
84 else if (dataByte == ASCII_START_CHAR)
85 {
86 LOG_DATA("{}: Ascii sync character found", _name);
89 _buffer.push_back(dataByte);
90 }
91 }
93 {
94 _buffer.push_back(dataByte);
95
97 {
98 // This byte must be the second sync char
99 if (dataByte == BINARY_SYNC_CHAR_2)
100 {
102 LOG_DATA("{}: 2nd sync character found", _name);
103 }
104 else
105 {
107 }
108 }
109 else if (!_binaryMsgClassFound)
110 {
111 // This byte must be the message class
113 _binaryMsgClass = dataByte;
114 }
115 else if (!_binaryMsgIdFound)
116 {
117 // This byte must be the message id
118 _binaryMsgIdFound = true;
119 _binaryMsgId = dataByte;
120 }
122 {
124 _binaryPayloadLength = static_cast<uint16_t>(dataByte);
125 }
127 {
129 _binaryPayloadLength |= static_cast<uint16_t>(static_cast<uint16_t>(dataByte) << 8U);
132
133 LOG_DATA("{}: Binary packet: Class={:0x} [{}], Id={:0x} [{}], payload length={}", _name,
136 }
137 else
138 {
139 // We are currently collecting data for our packet.
141
143 {
144 // We have a possible binary packet!
145 auto p = std::make_unique<uart::protocol::Packet>(_buffer, &_sensor);
146
147 if (p->isValid())
148 {
149 // We have a valid binary packet!!!.
151 return p;
152 }
153 // Invalid packet!
154 LOG_DEBUG("{}: Invalid binary packet: Class={:0x}, Id={:0x}, payload length={}", _name, _binaryMsgClass, _binaryMsgId, _binaryPayloadLength);
156 }
157 }
158 }
160 {
161 _buffer.push_back(dataByte);
162
163 if (dataByte == ASCII_ESCAPE_CHAR)
164 {
166 }
167 else if (dataByte == ASCII_END_CHAR_1)
168 {
169 _asciiEndChar1Found = true;
170 }
171 else if (_asciiEndChar1Found)
172 {
173 if (dataByte == ASCII_END_CHAR_2)
174 {
175 // We have a possible data packet
176 auto p = std::make_unique<uart::protocol::Packet>(_buffer, &_sensor);
177
178 if (p->isValid())
179 {
180 // We have a valid ascii packet!!!.
181 LOG_DATA("{}: Valid ascii packet: {}", _name, p->datastr().substr(0, p->getRawDataLength() - 2));
183 return p;
184 }
185 // Invalid packet!
186 LOG_ERROR("{}: Invalid ascii packet: {}", _name, p->datastr());
187 }
188 else
189 {
190 LOG_DATA("{}: 2nd Ascii end character not found", _name);
191 }
193 }
194 }
195
196 return nullptr;
197}
198
199void NAV::vendor::ublox::UbloxUartSensor::packetFinderFunction(const std::vector<uint8_t>& data, const uart::xplat::TimeStamp& timestamp, uart::sensors::UartSensor::ValidPacketFoundHandler dispatchPacket, void* dispatchPacketUserData, void* userData)
200{
201 auto* sensor = static_cast<UbloxUartSensor*>(userData);
202
203 for (size_t i = 0; i < data.size(); i++, sensor->_runningDataIndex++)
204 {
205 auto packetPointer = sensor->findPacket(data.at(i));
206
207 if (packetPointer != nullptr)
208 {
209 uart::protocol::Packet packet = *packetPointer;
210 dispatchPacket(dispatchPacketUserData, packet, sensor->_runningDataIndex, timestamp);
211 }
212 }
213}
214
215uart::protocol::Packet::Type NAV::vendor::ublox::UbloxUartSensor::packetTypeFunction(const uart::protocol::Packet& packet)
216{
217 if (packet.getRawDataLength() < 1)
218 {
219 LOG_CRITICAL("Packet does not contain any data.");
220 }
221
222 if (packet.getRawData().at(0) == '$')
223 {
224 return uart::protocol::Packet::Type::TYPE_ASCII;
225 }
226 if (packet.getRawData().at(0) == BINARY_SYNC_CHAR_1)
227 {
228 if (packet.getRawData().at(1) == BINARY_SYNC_CHAR_2)
229 {
230 return uart::protocol::Packet::Type::TYPE_BINARY;
231 }
232 }
233
234 return uart::protocol::Packet::Type::TYPE_UNKNOWN;
235}
236
237bool NAV::vendor::ublox::UbloxUartSensor::checksumFunction(const uart::protocol::Packet& packet)
238{
239 if (packet.getRawDataLength() <= 8)
240 {
241 return false;
242 }
243
244 if (packet.type() == uart::protocol::Packet::Type::TYPE_ASCII)
245 {
246 // First check if we have a checksum at all
247 if (packet.getRawData().at(packet.getRawDataLength() - 5) != '*')
248 {
249 return false;
250 }
251
252 // Return true, if a wildcard checksum is present
253 if (packet.getRawData().at(packet.getRawDataLength() - 3) == 'X'
254 && packet.getRawData().at(packet.getRawDataLength() - 4) == 'X')
255 {
256 return true;
257 }
258
259 uint8_t checksumHex = ublox::checksumNMEA(packet.getRawData());
260 std::array<uint8_t, 2> checksumRecv = { packet.getRawData().at(packet.getRawDataLength() - 4),
261 packet.getRawData().at(packet.getRawDataLength() - 3) };
262 return uart::to_uint8_from_hexstr(reinterpret_cast<char*>(checksumRecv.data())) == checksumHex;
263 }
264
265 if (packet.type() == uart::protocol::Packet::Type::TYPE_BINARY)
266 {
267 std::pair<uint8_t, uint8_t> checksum = ublox::checksumUBX(packet.getRawData());
268
269 return packet.getRawData().at(packet.getRawDataLength() - 2) == checksum.first
270 && packet.getRawData().at(packet.getRawDataLength() - 1) == checksum.second;
271 }
272
273 LOG_CRITICAL("Can't calculate checksum of packet with unknown type");
274 return false;
275}
276
277bool NAV::vendor::ublox::UbloxUartSensor::isErrorFunction([[maybe_unused]] const uart::protocol::Packet& packet)
278{
279 return false;
280}
281
282bool NAV::vendor::ublox::UbloxUartSensor::isResponseFunction([[maybe_unused]] const uart::protocol::Packet& packet)
283{
284 return false;
285}
#define LOG_CRITICAL(...)
Critical Event, which causes the program to work entirely and throws an exception.
Definition Logger.hpp:75
#define LOG_DEBUG
Debug information. Should not be called on functions which receive observations (spamming)
Definition Logger.hpp:67
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
Definition Logger.hpp:29
#define LOG_ERROR
Error occurred, which stops part of the program to work, but not everything.
Definition Logger.hpp:73
Algorithms concerning the STL containers.
Class to read out Ublox Sensors.
Helper Functions to work with Ublox Sensors.
Abstract Uart Sensor Class.
uint8_t _binaryMsgClass
Message class of the current packet.
static constexpr uint8_t BINARY_SYNC_CHAR_2
b - Second sync character which begins a new binary message
bool _binaryMsgIdFound
Flag if the message id was found.
std::unique_ptr< uart::protocol::Packet > findPacket(uint8_t dataByte)
Collects data bytes and searches for packages inside of them.
static void packetFinderFunction(const std::vector< uint8_t > &data, const uart::xplat::TimeStamp &timestamp, uart::sensors::UartSensor::ValidPacketFoundHandler dispatchPacket, void *dispatchPacketUserData, void *userData)
Function which is called to find packets in the provided data buffer.
static constexpr uint8_t ASCII_END_CHAR_2
Second Ascii End character.
static bool isErrorFunction(const uart::protocol::Packet &packet)
Function which determines, if the packet is an Error Packet.
UbloxUartSensor()=default
Default constructor.
bool _binaryMsgClassFound
Flag if the message class was found.
bool _binaryPayloadLength2Found
Flag if the second byte of the payload length was found.
const std::string _name
Name of the Parent Node.
bool _asciiEndChar1Found
Flag if the first ascii end character was found.
void resetTracking()
Resets the current message tracking.
static constexpr uint8_t ASCII_ESCAPE_CHAR
Ascii Escape charater.
bool _currentlyBuildingAsciiPacket
Flag if currently a ascii packet is built.
static uart::protocol::Packet::Type packetTypeFunction(const uart::protocol::Packet &packet)
Function which is called to determine the packet type (ascii/binary)
uart::sensors::UartSensor _sensor
UartSensor object which handles the UART interface.
static constexpr uint8_t ASCII_END_CHAR_1
First Ascii End character.
bool _currentlyBuildingBinaryPacket
Flag if currently a binary packet is built.
static constexpr uint8_t ASCII_START_CHAR
Ascii character which begins a new ascii message.
static constexpr uart::Endianness ENDIANNESS
Endianess of the sensor.
bool _binaryPayloadLength1Found
Flag if the first byte of the payload length was found.
static constexpr uint8_t BINARY_SYNC_CHAR_1
ยต - First sync character which begins a new binary message
size_t _numOfBytesRemainingForCompletePacket
Amount of bytes remaining for a complete packet.
std::vector< uint8_t > _unrecognizedBytes
Bytes which were not recognized as messages.
UbloxUartSensor(std::string name)
Constructor.
uint16_t _binaryPayloadLength
Payload length of the current packet.
static bool checksumFunction(const uart::protocol::Packet &packet)
Function which is called to verify packet integrity.
static bool isResponseFunction(const uart::protocol::Packet &packet)
Function which determines, if the packet is a Response.
std::vector< uint8_t > _buffer
Buffer to collect messages till they are complete.
uint8_t _binaryMsgId
Message id of the current packet.
bool _binarySyncChar2Found
Flag if the second binary end character was found.
uint8_t checksumNMEA(const std::vector< uint8_t > &data)
Calculates the NMEA checksum for the provided data vector.
std::string getStringFromMsgId(UbxClass msgClass, uint8_t msgId)
Get the a string from a UBX Msg Id.
std::pair< uint8_t, uint8_t > checksumUBX(const std::vector< uint8_t > &data)
Calculates the two UBX checksums for the provided data vector.
UbxClass
The available UBX Class IDs.
std::string getStringFromMsgClass(UbxClass msgClass)
Get the a string from a UBX Msg Class.
std::string joinToString(const T &container, const char *delimiter=", ", const std::string &elementFormat="")
Joins the container to a string.
Definition STL.hpp:30
void move(std::vector< T > &v, size_t sourceIdx, size_t targetIdx)
Moves an element within a vector to a new position.
Definition Vector.hpp:27