fusion_engine_framer.h
Go to the documentation of this file.
1 /**************************************************************************/ /**
2  * @brief FusionEngine message framer.
3  * @file
4  ******************************************************************************/
5 
6 #pragma once
7 
8 #include <cstddef> // For size_t
9 #include <cstdint>
10 #include <functional>
11 #include <memory>
12 
14 
15 namespace point_one {
16 namespace fusion_engine {
17 namespace parsers {
18 
19 /**
20  * @brief Frame and validate incoming FusionEngine messages.
21  *
22  * This class locates and validates FusionEngine messages within a stream of
23  * binary data. Data may be stored in an internally allocated buffer, or in an
24  * external buffer supplied by the user.
25  *
26  * The callback function provided to @ref SetMessageCallback() will be called
27  * each time a complete message is received. Any messages that do not pass the
28  * CRC check, or that are too big to be stored in the data buffer, will be
29  * discarded.
30  *
31  * Example usage:
32  * ```cpp
33  * void MessageReceived(const MessageHeader& header, const void* payload) {
34  * if (header.message_type == MessageType::POSE) {
35  * auto& contents = *static_cast<const PoseMessage*>(payload);
36  * ...
37  * }
38  * }
39  *
40  * FusionEngineFramer framer(1024);
41  * framer.SetMessageCallback(MessageReceived);
42  * framer.OnData(my_data, my_data_size);
43  * ```
44  */
46  public:
47  /**
48  * @brief Construct a framer instance with no buffer allocated.
49  *
50  * @note
51  * You must call @ref SetBuffer() to assign a buffer, otherwise all incoming
52  * data will be discarded.
53  */
54  FusionEngineFramer() = default;
55 
56  /**
57  * @brief Construct a framer instance with an internally allocated buffer.
58  *
59  * @param capacity_bytes The maximum framing buffer capacity (in bytes).
60  */
61  explicit FusionEngineFramer(size_t capacity_bytes)
62  : FusionEngineFramer(nullptr, capacity_bytes) {}
63 
64  /**
65  * @brief Construct a framer instance with a user-specified buffer.
66  *
67  * @post
68  * `buffer` must exist for the lifetime of this instance.
69  *
70  * @param buffer The framing buffer to use. Set to `nullptr` to allocate a
71  * buffer internally.
72  * @param capacity_bytes The maximum framing buffer capacity (in bytes).
73  */
74  FusionEngineFramer(void* buffer, size_t capacity_bytes);
75 
76  /**
77  * @brief Set the buffer to use for message framing.
78  *
79  * @post
80  * `buffer` must exist for the lifetime of this instance.
81  *
82  * @param buffer The framing buffer to use. Set to `nullptr` to allocate a
83  * buffer internally.
84  * @param capacity_bytes The maximum framing buffer capacity (in bytes).
85  */
86  void SetBuffer(void* buffer, size_t capacity_bytes);
87 
88  /**
89  * @brief Enable/disable warnings for CRC and "message too large" failures.
90  *
91  * This is typically used when the incoming stream has multiple types of
92  * binary content (e.g., interleaved FusionEngine and RTCM messages), and the
93  * FusionEngine message preamble is expected to appear in the non-FusionEngine
94  * content occasionally.
95  *
96  * @param enabled If `true`, issue warnings on errors.
97  */
98  void WarnOnError(bool enabled) { warn_on_error_ = enabled; }
99 
100  /**
101  * @brief Specify a function to be called when a message is framed.
102  *
103  * @param callback The function to be called with the message header and a
104  * pointer to the message payload.
105  */
107  std::function<void(const messages::MessageHeader&, const void*)>
108  callback) {
109  callback_ = callback;
110  }
111 
112  /**
113  * @brief Reset the framer and discard all pending data.
114  */
115  void Reset();
116 
117  /**
118  * @brief Process incoming data.
119  *
120  * @param buffer A buffer containing data to be framed.
121  * @param length_bytes The number of bytes to be framed.
122  *
123  * @return The total size of all valid, complete messages, or 0 if no messages
124  * were completed.
125  */
126  size_t OnData(const uint8_t* buffer, size_t length_bytes);
127 
128  private:
129  enum class State {
130  SYNC0 = 0,
131  SYNC1 = 1,
132  HEADER = 2,
133  DATA = 3,
134  };
135 
136  std::function<void(const messages::MessageHeader&, const void*)> callback_;
137 
138  bool warn_on_error_ = true;
139 
140  std::unique_ptr<uint8_t[]> managed_buffer_;
141  uint8_t* buffer_{nullptr};
142  uint32_t capacity_bytes_{0};
143 
145  uint32_t next_byte_index_{0};
147 
148  /**
149  * @brief Process a single byte.
150  *
151  * @pre
152  * The byte must be located at `buffer_[next_byte_index_ - 1]`.
153  *
154  * @param quiet If `true`, suppress failure warning messages.
155  *
156  * @return The total size of all valid, complete messages, 0 if no messages
157  * were completed, or <0 CRC or "message too large" error.
158  */
159  int32_t OnByte(bool quiet);
160 
161  /**
162  * @brief Perform a resynchronization operation starting at `buffer_[1]`.
163  *
164  * @return The total size of all valid, complete messages, or 0 if no messages
165  * were completed.
166  */
167  uint32_t Resync();
168 };
169 
170 } // namespace parsers
171 } // namespace fusion_engine
172 } // namespace point_one
void WarnOnError(bool enabled)
Enable/disable warnings for CRC and "message too large" failures.
The header present at the beginning of every message.
Definition: defs.h:446
FusionEngineFramer(size_t capacity_bytes)
Construct a framer instance with an internally allocated buffer.
uint32_t current_message_size_
uint32_t capacity_bytes_
uint8_t * buffer_
void Reset()
Reset the framer and discard all pending data.
Definition: logging.h:36
uint32_t Resync()
Perform a resynchronization operation starting at buffer_[1].
FusionEngineFramer()=default
Construct a framer instance with no buffer allocated.
State state_
Frame and validate incoming FusionEngine messages.
@ SYNC1
void SetMessageCallback(std::function< void(const messages::MessageHeader &, const void *)> callback)
Specify a function to be called when a message is framed.
@ SYNC0
size_t OnData(const uint8_t *buffer, size_t length_bytes)
Process incoming data.
bool warn_on_error_
void SetBuffer(void *buffer, size_t capacity_bytes)
Set the buffer to use for message framing.
uint32_t next_byte_index_
std::function< void(const messages::MessageHeader &, const void *)> callback_
@ DATA
Point One FusionEngine output message common definitions.
State
int32_t OnByte(bool quiet)
Process a single byte.
std::unique_ptr< uint8_t[]> managed_buffer_
@ HEADER