msgpack_converter.cpp
Go to the documentation of this file.
1 /*
2  * @brief msgpack_converter runs a background thread to unpack and parses msgpack data for the sick 3D lidar multiScan136.
3  * msgpack_converter pops binary msgpack data from an input fifo, converts the data to scanlines using MsgPackParser::Parse()
4  * and pushes the ScanSegmentParserOutput to an output fifo.
5  *
6  * Usage example:
7  *
8  * sick_scansegment_xd::UdpReceiver udp_receiver;
9  * udp_receiver.Init("127.0.0.1", 2115, -1, true);
10  * sick_scansegment_xd::MsgPackConverter msgpack_converter(udp_receiver.Fifo(), -1, true);
11  * msgpack_converter.Start()
12  * udp_receiver.Start();
13  *
14  * Copyright (C) 2020,2021 Ing.-Buero Dr. Michael Lehning, Hildesheim
15  * Copyright (C) 2020,2021 SICK AG, Waldkirch
16  *
17  * Licensed under the Apache License, Version 2.0 (the "License");
18  * you may not use this file except in compliance with the License.
19  * You may obtain a copy of the License at
20  *
21  * http://www.apache.org/licenses/LICENSE-2.0
22  *
23  * Unless required by applicable law or agreed to in writing, software
24  * distributed under the License is distributed on an "AS IS" BASIS,
25  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26  * See the License for the specific language governing permissions and
27  * limitations under the License.
28  *
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions are met:
33  *
34  * * Redistributions of source code must retain the above copyright
35  * notice, this list of conditions and the following disclaimer.
36  * * Redistributions in binary form must reproduce the above copyright
37  * notice, this list of conditions and the following disclaimer in the
38  * documentation and/or other materials provided with the distribution.
39  * * Neither the name of SICK AG nor the names of its
40  * contributors may be used to endorse or promote products derived from
41  * this software without specific prior written permission
42  * * Neither the name of Ing.-Buero Dr. Michael Lehning nor the names of its
43  * contributors may be used to endorse or promote products derived from
44  * this software without specific prior written permission
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
47  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
50  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56  * POSSIBILITY OF SUCH DAMAGE.
57  *
58  * Authors:
59  * Michael Lehning <michael.lehning@lehning.de>
60  *
61  * Copyright 2020 SICK AG
62  * Copyright 2020 Ing.-Buero Dr. Michael Lehning
63  *
64  */
69 
70 /*
71  * @brief Default constructor.
72  */
73 sick_scansegment_xd::MsgPackConverter::MsgPackConverter() : m_verbose(false), m_input_fifo(0), m_scandataformat(1), m_output_fifo(0), m_converter_thread(0), m_run_converter_thread(false)
74 
75 {
76 }
77 
78 /*
79  * @brief Initializing constructor
80  * @param[in] parser_config configuration and settings for multiScan and picoScan parser
81  * @param[in] add_transform_xyz_rpy Apply an additional transform to the cartesian pointcloud, default: "0,0,0,0,0,0" (i.e. no transform)
82  * @param[in] input_fifo input fifo buffering udp packages
83  * @param[in] scandataformat ScanDataFormat: 1 for msgpack or 2 for compact scandata, default: 1
84  * @param[in] msgpack_output_fifolength max. output 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
85  * @param[in] verbose true: enable debug output, false: quiet mode (default)
86  */
87 sick_scansegment_xd::MsgPackConverter::MsgPackConverter(const ScanSegmentParserConfig& parser_config, const sick_scan_xd::SickCloudTransform& add_transform_xyz_rpy, sick_scansegment_xd::PayloadFifo* input_fifo, int scandataformat, int msgpack_output_fifolength, bool verbose)
88  : m_parser_config(parser_config), m_verbose(verbose), m_input_fifo(input_fifo), m_scandataformat(scandataformat), m_converter_thread(0), m_run_converter_thread(false), m_msgpack_validator_enabled(false), m_discard_msgpacks_not_validated(false)
89 {
91  m_add_transform_xyz_rpy = add_transform_xyz_rpy;
92 }
93 
94 /*
95  * @brief Default destructor.
96  */
98 {
99  Close();
100 }
101 
102 /*
103  * @brief Starts a background thread, pops msgpack data packages from input fifo, converts them
104  * and pushes ScanSegmentParserOutput data to the output fifo.
105  */
107 {
108  m_run_converter_thread = true;
109  m_converter_thread = new std::thread(&sick_scansegment_xd::MsgPackConverter::Run, this);
110  return true;
111 }
112 
113 /*
114  * @brief Stops the converter thread
115  */
117 {
118  m_run_converter_thread = false;
119  if (m_output_fifo)
120  {
121  m_output_fifo->Shutdown();
122  }
123  if (m_converter_thread)
124  {
125  if (m_converter_thread->joinable())
126  m_converter_thread->join();
127  delete m_converter_thread;
128  m_converter_thread = 0;
129  }
130  if (m_output_fifo)
131  {
132  delete m_output_fifo;
133  m_output_fifo = 0;
134  }
135 }
136 
137 /*
138  * @brief Configures msgpack validation, see MsgPackValidator for details
139  * @param[in] msgpack_validator the msgpack validator
140  * @param[in] msgpack_validator_enabled true: check msgpack data for out of bounds and missing scan data, false: no msgpack validation
141  * @param[in] discard_msgpacks_not_validated true: msgpacks are discarded if scan data out of bounds detected, false: error message if a msgpack is not validated
142  * @param[in] msgpack_validator_check_missing_scandata_interval check msgpack for missing scandata after collecting N msgpacks, default: N = 12 segments. Increase this value to tolerate udp packet drops. Use 12 to check each full scan.
143  */
144 void sick_scansegment_xd::MsgPackConverter::SetValidator(sick_scansegment_xd::MsgPackValidator& msgpack_validator, bool msgpack_validator_enabled, bool discard_msgpacks_not_validated, int msgpack_validator_check_missing_scandata_interval)
145 {
146  m_msgpack_validator = msgpack_validator;
147  m_msgpack_validator_enabled = msgpack_validator_enabled;
148  m_discard_msgpacks_not_validated = discard_msgpacks_not_validated;
149  m_msgpack_validator_check_missing_scandata_interval = msgpack_validator_check_missing_scandata_interval;
150 }
151 
152 
153 /*
154  * @brief Thread callback, runs the converter. Pops msgpack data from the input fifo, converts them und pushes ScanSegmentParserOutput data to the output fifo.
155  */
157 {
158  if (!m_input_fifo || !m_output_fifo)
159  {
160  ROS_ERROR_STREAM("## ERROR MsgPackConverter::Run(): MsgPackConverter not initialized.");
161  return false;
162  }
163  try
164  {
165  sick_scansegment_xd::MsgPackValidatorData msgpack_validator_data_collector;
166  for (size_t msgpack_cnt = 1; m_run_converter_thread; msgpack_cnt++)
167  {
168  std::vector<uint8_t> input_payload;
169  fifo_timestamp input_timestamp;
170  size_t input_counter = 0;
171  if (m_input_fifo->Pop(input_payload, input_timestamp, input_counter))
172  {
173  try
174  {
176  bool parse_success = false;
177  if (m_scandataformat == SCANDATA_MSGPACK)
178  {
179  parse_success = sick_scansegment_xd::MsgPackParser::Parse(input_payload, input_timestamp, m_add_transform_xyz_rpy, msgpack_output, msgpack_validator_data_collector,
180  m_msgpack_validator, m_msgpack_validator_enabled, m_discard_msgpacks_not_validated, true, m_verbose);
181  }
182  else if (m_scandataformat == SCANDATA_COMPACT)
183  {
184  parse_success = sick_scansegment_xd::CompactDataParser::Parse(m_parser_config, input_payload, input_timestamp, m_add_transform_xyz_rpy, msgpack_output);
185  }
186  else
187  {
188  ROS_ERROR_STREAM("## ERROR MsgPackConverter::Run(): invalid scandataformat configuration, unsupported scandataformat=" << m_scandataformat
189  << ", check configuration and use " << SCANDATA_MSGPACK << " for msgpack or " << SCANDATA_COMPACT << " for compact data");
190  }
191  if (parse_success)
192  {
193  size_t fifo_length = m_output_fifo->Push(msgpack_output, input_timestamp, input_counter);
194  if (m_verbose)
195  {
196  ROS_INFO_STREAM("MsgPackConverter::Run(): " << m_input_fifo->Size() << " messages in input fifo, " << fifo_length << " messages in output fifo.");
197  }
198  }
199  else
200  {
201  ROS_ERROR_STREAM("## ERROR MsgPackConverter::Run(): msgpack parse error");
202  if (m_verbose)
203  {
204  ROS_ERROR_STREAM("## ERROR MsgPackConverter::Run(): MsgPackParser::Parse() failed on " << input_payload.size() << " byte input data: " << sick_scansegment_xd::UdpReceiver::ToPrintableString(input_payload, input_payload.size()));
205  }
206  }
207  if (m_msgpack_validator_enabled) // validate msgpack data
208  {
209  if (m_msgpack_validator.validateNotOutOfBound(msgpack_validator_data_collector) == false)
210  ROS_ERROR_STREAM("## ERROR MsgPackConverter::Run(): msgpack out of bounds validation failed");
211  else if (m_verbose)
212  ROS_INFO_STREAM("MsgPackConverter::Run(): msgpack validation passed (no scandata out of bounds)");
213  if(msgpack_cnt >= m_msgpack_validator_check_missing_scandata_interval)
214  {
215  if (m_msgpack_validator.validateNoMissingScandata(msgpack_validator_data_collector) == false)
216  ROS_ERROR_STREAM("## ERROR MsgPackConverter::Run(): msgpack validation failed (scandata missing)");
217  else if (m_verbose)
218  ROS_INFO_STREAM("MsgPackConverter::Run(): msgpack validation passed (no scandata missing)");
219  msgpack_cnt = 0; // reset counter for next interval
220  msgpack_validator_data_collector = sick_scansegment_xd::MsgPackValidatorData(); // reset collected msgpack data
221  }
222  }
223  }
224  catch (std::exception & e)
225  {
226  ROS_ERROR_STREAM("## ERROR MsgPackConverter::Run(): parse error " << e.what());
227  }
228  }
229  }
230  m_run_converter_thread = false;
231  return true;
232  }
233  catch (std::exception & e)
234  {
235  ROS_ERROR_STREAM("## ERROR MsgPackConverter::Run(): " << e.what());
236  }
237  m_run_converter_thread = false;
238  return false;
239 }
sick_scansegment_xd::PayloadFifo
Definition: fifo.h:187
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_scan_xd::SickCloudTransform
Definition: sick_cloud_transform.h:85
sick_scansegment_xd::MsgPackValidatorData
Definition: msgpack_validator.h:86
SCANDATA_MSGPACK
#define SCANDATA_MSGPACK
Definition: include/sick_scansegment_xd/common.h:92
sick_scansegment_xd::MsgPackConverter::SetValidator
void SetValidator(sick_scansegment_xd::MsgPackValidator &msgpack_validator, bool msgpack_validator_enabled, bool discard_msgpacks_not_validated, int msgpack_validator_check_missing_scandata_interval)
Definition: msgpack_converter.cpp:144
sick_scansegment_xd::MsgPackConverter::~MsgPackConverter
~MsgPackConverter()
Definition: msgpack_converter.cpp:97
sick_scansegment_xd::MsgPackConverter::m_output_fifo
sick_scansegment_xd::Fifo< ScanSegmentParserOutput > * m_output_fifo
Definition: msgpack_converter.h:152
udp_receiver.h
multiscan_pcap_player.verbose
int verbose
Definition: multiscan_pcap_player.py:142
compact_parser.h
ROS_INFO_STREAM
#define ROS_INFO_STREAM(...)
Definition: sick_scan_ros2_example.cpp:71
sick_scansegment_xd::ScanSegmentParserOutput
Definition: scansegment_parser_output.h:118
sick_scansegment_xd::MsgPackConverter::m_add_transform_xyz_rpy
sick_scan_xd::SickCloudTransform m_add_transform_xyz_rpy
Definition: msgpack_converter.h:159
sick_scansegment_xd::Fifo
Definition: fifo.h:75
sick_scansegment_xd::MsgPackParser::Parse
static bool Parse(const std::vector< uint8_t > &msgpack_data, fifo_timestamp msgpack_timestamp, sick_scan_xd::SickCloudTransform &add_transform_xyz_rpy, ScanSegmentParserOutput &result, sick_scansegment_xd::MsgPackValidatorData &msgpack_validator_data_collector, const sick_scansegment_xd::MsgPackValidator &msgpack_validator=sick_scansegment_xd::MsgPackValidator(), bool msgpack_validator_enabled=false, bool discard_msgpacks_not_validated=false, bool use_software_pll=true, bool verbose=false)
Definition: msgpack_parser.cpp:481
sick_scansegment_xd::MsgPackConverter::MsgPackConverter
MsgPackConverter()
Definition: msgpack_converter.cpp:73
sick_scansegment_xd::CompactDataParser::Parse
static bool Parse(const ScanSegmentParserConfig &parser_config, const std::vector< uint8_t > &payload, fifo_timestamp system_timestamp, sick_scan_xd::SickCloudTransform &add_transform_xyz_rpy, ScanSegmentParserOutput &result, bool use_software_pll=true, bool verbose=false)
Definition: compact_parser.cpp:864
fifo_timestamp
std::chrono::time_point< std::chrono::system_clock > fifo_timestamp
Definition: fifo.h:68
msgpack_converter.h
sick_scansegment_xd::MsgPackConverter::Run
bool Run(void)
Definition: msgpack_converter.cpp:156
sick_scansegment_xd::MsgPackConverter::Start
bool Start(void)
Definition: msgpack_converter.cpp:106
config.h
sick_scansegment_xd::MsgPackValidator
Definition: msgpack_validator.h:201
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(...)
Definition: sick_scan_ros2_example.cpp:72
sick_scansegment_xd::ScanSegmentParserConfig
Definition: scansegment_parser_output.h:91
SCANDATA_COMPACT
#define SCANDATA_COMPACT
Definition: include/sick_scansegment_xd/common.h:93
sick_scansegment_xd::MsgPackConverter::Close
void Close(void)
Definition: msgpack_converter.cpp:116


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