udp_receiver.cpp
Go to the documentation of this file.
1 /*
2  * @brief udp_receiver receives msgpack raw data by udp.
3  * It implements a udp client, connects to multiScan136 (or any other udp-) sender,
4  * receives and buffers msgpack raw data.
5  *
6  * Copyright (C) 2020,2021 Ing.-Buero Dr. Michael Lehning, Hildesheim
7  * Copyright (C) 2020,2021 SICK AG, Waldkirch
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * All rights reserved.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions are met:
25  *
26  * * Redistributions of source code must retain the above copyright
27  * notice, this list of conditions and the following disclaimer.
28  * * Redistributions in binary form must reproduce the above copyright
29  * notice, this list of conditions and the following disclaimer in the
30  * documentation and/or other materials provided with the distribution.
31  * * Neither the name of SICK AG nor the names of its
32  * contributors may be used to endorse or promote products derived from
33  * this software without specific prior written permission
34  * * Neither the name of Ing.-Buero Dr. Michael Lehning nor the names of its
35  * contributors may be used to endorse or promote products derived from
36  * this software without specific prior written permission
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
39  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
42  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
43  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
44  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48  * POSSIBILITY OF SUCH DAMAGE.
49  *
50  * Authors:
51  * Michael Lehning <michael.lehning@lehning.de>
52  *
53  * Copyright 2020 SICK AG
54  * Copyright 2020 Ing.-Buero Dr. Michael Lehning
55  *
56  */
57 
63 
64 /*
65  * Computes the zlib CRC32 checksum, see https://stackoverflow.com/questions/15030011/same-crc32-for-python-and-c
66  */
67 static uint32_t crc32(uint32_t crc, const uint8_t* buf, size_t len)
68 {
69  crc = ~crc;
70  while (len--)
71  {
72  crc ^= *buf++;
73  for (int k = 0; k < 8; k++)
74  crc = crc & 1 ? (crc >> 1) ^ 0xedb88320 : crc >> 1;
75  }
76  return ~crc;
77 }
78 
79 
80 
81 /*
82  * @brief Default constructor.
83  */
84 sick_scansegment_xd::UdpReceiver::UdpReceiver() : m_verbose(false), m_export_udp_msg(false), m_socket_impl(0), m_fifo_impl(0), m_fifo_impl_created(false), m_receiver_thread(0), m_run_receiver_thread(false),
85  m_udp_recv_buffer_size(0), m_udp_timeout_recv_nonblocking(0), m_udp_sender_timeout(0)
86 {
87 }
88 
89 /*
90  * @brief Default destructor.
91  */
93 {
94  Close();
95 }
96 
97 /*
98  * @brief Initializes an udp socket to a sender.
99  * @param[in] udp_sender ip address of the udp sender, f.e. "127.0.0.1" (localhost, loopback)
100  * @param[in] udp_port ip port, f.e. 2115 (default port for multiScan136 emulator)
101  * @param[in] udp_input_fifolength max. input fifo length (-1: unlimited, default: 20 for buffering 1 second at 20 Hz), elements will be removed from front if number of elements exceeds the fifo_length
102  * @param[in] verbose true: enable debug output, false: quiet mode (default)
103  * @param[in] export_udp_msg: true: export binary udp and msgpack data to file (*.udp and *.msg), default: false
104  * @param[in] scandataformat ScanDataFormat: 1 for msgpack or 2 for compact scandata, default: 1
105  */
106 bool sick_scansegment_xd::UdpReceiver::Init(const std::string& udp_sender, int udp_port, int udp_input_fifolength, bool verbose, bool export_udp_msg, int scandataformat, PayloadFifo* fifo)
107 {
108  if (m_socket_impl || m_fifo_impl || m_receiver_thread)
109  Close();
110  // Receive \x02\x02\x02\x02 | 4Bytes Laenge des Payloads inkl. CRC | Payload | CRC32
111  m_udp_recv_buffer_size = 64 * 1024; // size of buffer to receive udp packages
112  m_udp_msg_start_seq = { 0x02, 0x02, 0x02, 0x02 }; // { 0xDC, 0x00, 0x10, 0x82, 0xA5, 'c', 'l', 'a', 's', 's', 0xA4, 'S', 'c', 'a', 'n' }; // any udp message from multiScan136 starts with 15 byte ".....class.Scan"
113  m_udp_timeout_recv_nonblocking = 1.0; // in normal mode we receive udp datagrams non-blocking with timeout to enable sync with msgpack start
114 #if defined RASPBERRY && RASPBERRY > 0
115  m_udp_timeout_recv_nonblocking = -1.0; // read upd packets in blocking mode on raspberry to prevent timeout in case of high network of system load
116 #endif
117  m_udp_sender_timeout = 2.0; // if no udp packages received within 2 second, we switch to blocking udp receive
118  m_verbose = verbose;
119  m_export_udp_msg = export_udp_msg; // true : export binary udpand msgpack data to file(*.udp and* .msg), default: false
120  m_scandataformat = scandataformat; // ScanDataFormat: 1 for msgpack or 2 for compact scandata, default: 1
121  if (m_scandataformat != SCANDATA_MSGPACK && m_scandataformat != SCANDATA_COMPACT)
122  {
123  ROS_ERROR_STREAM("## ERROR UdpReceiver::Init(): invalid scandataformat configuration, unsupported scandataformat=" << m_scandataformat
124  << ", check configuration and use " << SCANDATA_MSGPACK << " for msgpack or " << SCANDATA_COMPACT << " for compact data");
125  return false;
126  }
127 
128  if (fifo) // Use/share fifo of another udp receiver
129  {
130  m_fifo_impl = fifo;
131  m_fifo_impl_created = false;
132  }
133  else // Create a new fifo for udp payload
134  {
135  m_fifo_impl = new PayloadFifo(udp_input_fifolength);
136  m_fifo_impl_created = true;
137  }
138  m_socket_impl = new UdpReceiverSocketImpl();
139  if (!m_socket_impl->Init(udp_sender, udp_port))
140  {
141  ROS_ERROR_STREAM("## ERROR UdpReceiver::Init(): UdpReceiverSocketImpl::Init(" << udp_sender << "," << udp_port << ") failed.");
142  return false;
143  }
144  return true;
145 }
146 
147 /*
148  * @brief Starts receiving udp packages in a background thread and pops msgpack data packages to the fifo.
149  */
151 {
152  m_run_receiver_thread = true;
153  m_receiver_thread = new std::thread(&sick_scansegment_xd::UdpReceiver::Run, this);
154  return true;
155 }
156 
157 /*
158  * @brief Stops the udp receiver thread
159  */
161 {
162  m_run_receiver_thread = false;
163  if (m_socket_impl)
164  m_socket_impl->running() = false;
165  if (do_join && m_receiver_thread && m_receiver_thread->joinable())
166  m_receiver_thread->join();
167 }
168 
169 /*
170  * @brief Stop to receive data and shutdown the udp socket
171  */
173 {
174  m_run_receiver_thread = false;
175  if (m_socket_impl)
176  m_socket_impl->running() = false;
177  if (m_fifo_impl && m_fifo_impl_created)
178  {
179  m_fifo_impl->Shutdown();
180  }
181  if (m_receiver_thread)
182  {
183  if (m_receiver_thread->joinable())
184  m_receiver_thread->join();
185  delete m_receiver_thread;
186  m_receiver_thread = 0;
187  }
188  if (m_socket_impl)
189  {
190  delete m_socket_impl;
191  m_socket_impl = 0;
192  }
193  if (m_fifo_impl && m_fifo_impl_created)
194  {
195  delete m_fifo_impl;
196  }
197  m_fifo_impl = 0;
198  m_fifo_impl_created = false;
199 }
200 
201 /*
202  * @brief Thread callback, runs the receiver for udp packages and pops msgpack data packages to the fifo.
203  */
205 {
206  if (!m_socket_impl)
207  {
208  ROS_ERROR_STREAM("## ERROR UdpReceiver::Run(): UdpReceiver not initialized, call UdpReceiver::Init() first.");
209  return false;
210  }
211  try
212  {
213  size_t udp_recv_counter = 0;
214  std::vector<uint8_t> udp_payload(m_udp_recv_buffer_size, 0);
215  double udp_recv_timeout = -1; // initial timeout: block until first datagram received
216  chrono_system_time timestamp_last_print = chrono_system_clock::now();
217  chrono_system_time timestamp_last_print_crc_error = chrono_system_clock::now();
218  chrono_system_time timestamp_last_udp_recv = chrono_system_clock::now();
219  while (m_run_receiver_thread)
220  {
221  size_t bytes_received = m_socket_impl->Receive(udp_payload, udp_recv_timeout, m_udp_msg_start_seq);
222  bool do_print = (sick_scansegment_xd::Seconds(timestamp_last_print, chrono_system_clock::now()) > 1.0); // avoid printing with more than 1 Hz
223  bool do_print_crc_error = (sick_scansegment_xd::Seconds(timestamp_last_print_crc_error, chrono_system_clock::now()) > 1.0); // avoid printing crc errors with more than 1 Hz
224  // std::cout << "UdpReceiver::Run(): " << bytes_received << " bytes received" << std::endl;
225  ROS_DEBUG_STREAM("UdpReceiver::Run(): " << bytes_received << " bytes received (port " << m_socket_impl->port() << ", udp_receiver.cpp:" << __LINE__ << ")");
226  if(m_run_receiver_thread && bytes_received > m_udp_msg_start_seq.size() + 8 && std::equal(udp_payload.begin(), udp_payload.begin() + m_udp_msg_start_seq.size(), m_udp_msg_start_seq.begin()))
227  {
228  // Received \x02\x02\x02\x02 | 4Bytes payload length | Payload | CRC32
229  bool crc_error = false, check_crc = true;
230  uint32_t payload_length_bytes = 0;
231  uint32_t bytes_to_receive = 0;
232  uint32_t udp_payload_offset = 0;
233  if (m_scandataformat == SCANDATA_MSGPACK)
234  {
235  // msgpack data (default): UDP message := (4 byte \x02\x02\x02\x02) + (4 byte payload length) + payload + (4 byte CRC)
236  payload_length_bytes = Convert4Byte(udp_payload.data() + m_udp_msg_start_seq.size());
237  bytes_to_receive = (uint32_t)(payload_length_bytes + m_udp_msg_start_seq.size() + 2 * sizeof(uint32_t));
238  udp_payload_offset = m_udp_msg_start_seq.size() + sizeof(uint32_t); // payload starts after (4 byte \x02\x02\x02\x02) + (4 byte payload length)
239  }
240  else if (m_scandataformat == SCANDATA_COMPACT)
241  {
242  bool parse_success = false;
243  uint32_t num_bytes_required = 0;
244  chrono_system_time recv_start_timestamp = chrono_system_clock::now();
245  while (m_run_receiver_thread &&
246  (parse_success = sick_scansegment_xd::CompactDataParser::ParseSegment(udp_payload.data(), bytes_received, 0, payload_length_bytes, num_bytes_required )) == false &&
247  (udp_recv_timeout < 0 || sick_scansegment_xd::Seconds(recv_start_timestamp, chrono_system_clock::now()) < udp_recv_timeout)) // read blocking (udp_recv_timeout < 0) or udp_recv_timeout in seconds
248  {
249  if (num_bytes_required > 1024*1024)
250  {
251  parse_success = false;
252  ROS_ERROR_STREAM("## ERROR UdpReceiver::Run(): " << bytes_received << " bytes received (compact), " << (num_bytes_required + sizeof(uint32_t)) << " bytes or more required, probably incorrect payload");
253  // parse again with debug output after error
254  sick_scansegment_xd::CompactDataParser::ParseSegment(udp_payload.data(), bytes_received, 0, payload_length_bytes, num_bytes_required , 0.0f, 1);
255  break;
256  }
257  ROS_DEBUG_STREAM("UdpReceiver::Run(): " << bytes_received << " bytes received (compact), " << (num_bytes_required + sizeof(uint32_t)) << " bytes or more required");
258  while(m_run_receiver_thread && bytes_received < num_bytes_required + sizeof(uint32_t) && // payload + 4 byte CRC required
259  (udp_recv_timeout < 0 || sick_scansegment_xd::Seconds(recv_start_timestamp, chrono_system_clock::now()) < udp_recv_timeout)) // read blocking (udp_recv_timeout < 0) or udp_recv_timeout in seconds
260  {
261  std::vector<uint8_t> chunk_payload(m_udp_recv_buffer_size, 0);
262  size_t chunk_bytes_received = m_socket_impl->Receive(chunk_payload);
263  if (m_verbose)
264  ROS_INFO_STREAM("UdpReceiver::Run(): chunk of " << chunk_bytes_received << " bytes received (udp_receiver.cpp:" << __LINE__ << ")");
265  udp_payload.insert(udp_payload.begin() + bytes_received, chunk_payload.begin(), chunk_payload.begin() + chunk_bytes_received);
266  bytes_received += chunk_bytes_received;
267  }
268  }
269  if (!parse_success)
270  {
271  ROS_ERROR_STREAM("## ERROR UdpReceiver::Run(): CompactDataParser::ParseSegment failed");
272  continue;
273  }
274  bytes_to_receive = (uint32_t)(payload_length_bytes + sizeof(uint32_t)); // payload + (4 byte CRC)
275  udp_payload_offset = 0; // compact format calculates CRC over complete message (incl. header)
276  ROS_DEBUG_STREAM("UdpReceiver::Run(): payload_length_bytes=" << payload_length_bytes << ", bytes_to_receive= " << bytes_to_receive << ", bytes_received=" << bytes_received << " (udp_receiver.cpp:" << __LINE__ << ")");
277  }
278  else
279  {
280  ROS_ERROR_STREAM("## ERROR UdpReceiver::Run(): invalid scandataformat configuration, unsupported scandataformat=" << m_scandataformat
281  << ", check configuration and use " << SCANDATA_MSGPACK << " for msgpack or " << SCANDATA_COMPACT << " for compact data");
282  m_run_receiver_thread = false;
283  m_socket_impl->running() = false;
284  return false;
285  }
286  if (bytes_received != bytes_to_receive)
287  {
288  if (bytes_received < bytes_to_receive)
289  {
290  ROS_ERROR_STREAM("## ERROR UdpReceiver::Run(): " << bytes_received << " bytes received, " << bytes_to_receive << " bytes expected, payload_length=" << payload_length_bytes << " bytes");
291  timestamp_last_print = chrono_system_clock::now();
292  }
293  else if(m_verbose)
294  {
295  ROS_INFO_STREAM("UdpReceiver::Run(): " << bytes_received << " bytes received, " << bytes_to_receive << " bytes expected, payload_length=" << payload_length_bytes << " bytes");
296  timestamp_last_print = chrono_system_clock::now();
297  }
298  }
299  // std::cout << "UdpReceiver: payload_length_bytes = " << payload_length_bytes << " byte" << std::endl;
300  // CRC check
301  size_t bytes_valid = std::min<size_t>(bytes_received, (size_t)bytes_to_receive);
302  uint32_t u32PayloadCRC = Convert4Byte(udp_payload.data() + bytes_valid - sizeof(uint32_t)); // last 4 bytes are CRC
303  std::vector<uint8_t> msgpack_payload(udp_payload.begin() + udp_payload_offset, udp_payload.begin() + bytes_valid - sizeof(uint32_t));
304  uint32_t u32MsgPackCRC = crc32(0, msgpack_payload.data(), msgpack_payload.size());
305  if (check_crc && u32PayloadCRC != u32MsgPackCRC)
306  {
307  crc_error = true;
308  if (do_print_crc_error)
309  {
310  ROS_ERROR_STREAM("## ERROR UdpReceiver::Run(): CRC 0x" << std::setfill('0') << std::setw(2) << std::hex << u32PayloadCRC
311  << " received from " << std::dec << (bytes_valid - sizeof(uint32_t)) << " udp bytes different to CRC 0x"
312  << std::setfill('0') << std::setw(2) << std::hex << u32MsgPackCRC << " computed from "
313  << std::dec << (msgpack_payload.size()) << " byte payload, message dropped");
314  ROS_ERROR_STREAM("## ERROR UdpReceiver::Run(): decoded payload size: " << payload_length_bytes << " bytes, bytes_to_receive (expected udp message length): "
315  << bytes_to_receive << " byte, bytes_valid (received udp message length): " << bytes_valid << " byte");
316  timestamp_last_print_crc_error = chrono_system_clock::now();
317  }
318  continue;
319  }
320  if (payload_length_bytes != msgpack_payload.size() && do_print)
321  {
322  ROS_ERROR_STREAM("## ERROR UdpReceiver::Run(): payload_length_bytes=" << payload_length_bytes << " different to decoded payload size " << msgpack_payload.size());
323  timestamp_last_print = chrono_system_clock::now();
324  }
325  // Push msgpack_payload to input fifo
326  if (!crc_error)
327  {
328  size_t fifo_length = m_fifo_impl->Push(msgpack_payload, fifo_clock::now(), udp_recv_counter);
329  udp_recv_counter++;
330  if (m_verbose && do_print)
331  {
332  ROS_INFO_STREAM("UdpReceiver::Run(): " << bytes_received << " bytes received: " << ToPrintableString(udp_payload, bytes_received));
333  ROS_INFO_STREAM("UdpReceiver::Run(): " << fifo_length << " messages currently in paylod buffer, totally received " << udp_recv_counter << " udp packages");
334  timestamp_last_print = chrono_system_clock::now();
335  }
336  }
337  if (m_export_udp_msg) // || crc_error
338  {
339  std::ofstream udp_ostream(std::string("udp_received_bin_") + sick_scansegment_xd::FormatNumber(udp_recv_counter, 3, true, false, -1) + ".udp", std::ofstream::binary);
340  std::ofstream msg_ostream(std::string("udp_received_msg_") + sick_scansegment_xd::FormatNumber(udp_recv_counter, 3, true, false, -1) + ".msg", std::ofstream::binary);
341  if (udp_ostream.is_open() && msg_ostream.is_open())
342  {
343  udp_ostream.write((const char*)udp_payload.data(), bytes_received);
344  msg_ostream.write((const char*)msgpack_payload.data(), msgpack_payload.size());
345  }
346  }
347  }
348  else if(bytes_received > 0)
349  {
350  if (do_print)
351  {
352  ROS_ERROR_STREAM("## ERROR UdpReceiver::Run(): Received " << bytes_received << " unexpected bytes");
353  if(m_verbose)
354  ROS_ERROR_STREAM(ToHexString(udp_payload, bytes_received));
355  timestamp_last_print = chrono_system_clock::now();
356  }
357  }
358  if(bytes_received > 0)
359  timestamp_last_udp_recv = chrono_system_clock::now();
360  if (sick_scansegment_xd::Seconds(timestamp_last_udp_recv, chrono_system_clock::now()) > m_udp_sender_timeout) // if no udp packages received within 1-2 seconds, we switch to blocking udp receive
361  udp_recv_timeout = -1; // udp timeout, last datagram more than 1 second ago, resync and block until next datagram received
362  else // in normal mode we receive udp datagrams non-blocking with timeout to enable sync with msgpack start
363  udp_recv_timeout = m_udp_timeout_recv_nonblocking; // receive non-blocking with timeout
364  }
365  m_run_receiver_thread = false;
366  m_socket_impl->running() = false;
367  return true;
368  }
369  catch (std::exception & e)
370  {
371  ROS_ERROR_STREAM("## ERROR UdpReceiver::Run(): " << e.what());
372  }
373  m_run_receiver_thread = false;
374  m_socket_impl->running() = false;
375  return false;
376 }
377 
378 /*
379  * @brief Converts a payload to a hex string
380  * param[in] payload payload buffer
381  * param[in] bytes_received number of received bytes
382  */
383 std::string sick_scansegment_xd::UdpReceiver::ToHexString(const std::vector<uint8_t>& payload, size_t bytes_received)
384 {
385  std::stringstream hexstream;
386  for (size_t n = 0; n < bytes_received; n++)
387  {
388  hexstream << (n > 0 ? " " : "") << std::hex << (int)(payload[n] & 0xFF);
389  }
390  return hexstream.str();
391 }
392 
393 /*
394  * @brief Converts a payload to a printable string (alnum characters or '.' for non-printable bytes)
395  * param[in] payload payload buffer
396  * param[in] bytes_received number of received bytes
397  */
398 std::string sick_scansegment_xd::UdpReceiver::ToPrintableString(const std::vector<uint8_t>& payload, size_t bytes_received)
399 {
400  std::vector<uint8_t> payload_printable(bytes_received + 1);
401  for (size_t n = 0; n < bytes_received; n++)
402  {
403  if (::isprint(payload[n]))
404  payload_printable[n] = payload[n];
405  else
406  payload_printable[n] = '.';
407  }
408  payload_printable[bytes_received] = 0;
409  return std::string((const char*)payload_printable.data());
410 }
sick_scansegment_xd::PayloadFifo
Definition: fifo.h:187
udp_sockets.h
sick_scansegment_xd::UdpReceiver::ToPrintableString
static std::string ToPrintableString(const std::vector< uint8_t > &payload, size_t bytes_received)
Definition: udp_receiver.cpp:398
sick_scansegment_xd::UdpReceiver::ToHexString
static std::string ToHexString(const std::vector< uint8_t > &payload, size_t bytes_received)
Definition: udp_receiver.cpp:383
sick_scansegment_xd::UdpReceiver::Start
bool Start(void)
Definition: udp_receiver.cpp:150
SCANDATA_MSGPACK
#define SCANDATA_MSGPACK
Definition: include/sick_scansegment_xd/common.h:92
fifo.h
sick_scansegment_xd::FormatNumber
static std::string FormatNumber(const T &number, int width=-1, bool setfill=false, bool setfixed=false, int precision=-1)
Definition: include/sick_scansegment_xd/common.h:151
sick_scansegment_xd::UdpReceiver::UdpReceiver
UdpReceiver()
Definition: udp_receiver.cpp:84
udp_receiver.h
sick_scansegment_xd::UdpReceiver::Init
bool Init(const std::string &udp_sender, int udp_port, int udp_input_fifolength=20, bool verbose=false, bool export_udp_msg=false, int scandataformat=1, PayloadFifo *fifo=0)
Definition: udp_receiver.cpp:106
sick_scansegment_xd::UdpReceiver::Close
void Close(void)
Definition: udp_receiver.cpp:172
multiscan_pcap_player.verbose
int verbose
Definition: multiscan_pcap_player.py:142
ROS::now
ROS::Time now(void)
Definition: ros_wrapper.cpp:116
compact_parser.h
chrono_system_time
std::chrono::time_point< std::chrono::system_clock > chrono_system_time
Definition: include/sick_scansegment_xd/common.h:134
pcap_json_converter.payload
string payload
Definition: pcap_json_converter.py:130
ROS_INFO_STREAM
#define ROS_INFO_STREAM(...)
Definition: sick_scan_ros2_example.cpp:71
sick_scansegment_xd::UdpReceiver::~UdpReceiver
~UdpReceiver()
Definition: udp_receiver.cpp:92
multiscan_pcap_player.udp_port
int udp_port
Definition: multiscan_pcap_player.py:137
ROS_DEBUG_STREAM
#define ROS_DEBUG_STREAM(args)
Definition: sick_scan_logging.h:113
sick_scansegment_xd::CompactDataParser::ParseSegment
static bool ParseSegment(const uint8_t *payload, size_t bytes_received, sick_scansegment_xd::CompactSegmentData *segment_data, uint32_t &payload_length_bytes, uint32_t &num_bytes_required, float azimuth_offset=0, int verbose=0)
Definition: compact_parser.cpp:695
sick_scansegment_xd::UdpReceiver::Run
bool Run(void)
Definition: udp_receiver.cpp:204
sick_scansegment_xd::Convert4Byte
static uint32_t Convert4Byte(const uint8_t *p_data)
Definition: udp_sockets.h:98
config.h
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(...)
Definition: sick_scan_ros2_example.cpp:72
crc32
static uint32_t crc32(uint32_t crc, const uint8_t *buf, size_t len)
Definition: udp_receiver.cpp:67
sick_scansegment_xd::Seconds
static double Seconds(const chrono_system_time &timestamp_start, const chrono_system_time &timestamp_end=chrono_system_clock::now())
Definition: include/sick_scansegment_xd/common.h:143
SCANDATA_COMPACT
#define SCANDATA_COMPACT
Definition: include/sick_scansegment_xd/common.h:93
sick_scansegment_xd::UdpReceiverSocketImpl
Definition: udp_sockets.h:106
sick_scansegment_xd::UdpReceiver::Stop
void Stop(bool do_join=true)
Definition: udp_receiver.cpp:160


sick_scan_xd
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Fri Oct 25 2024 02:47:13