config.cpp
Go to the documentation of this file.
1 /*
2  * @brief config.cpp implements the configuration (yaml, commandline and default parameters) for project sick_scansegment_xd.
3  *
4  * Copyright (C) 2020,2021 Ing.-Buero Dr. Michael Lehning, Hildesheim
5  * Copyright (C) 2020,2021 SICK AG, Waldkirch
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * All rights reserved.
20  *
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions are met:
23  *
24  * * Redistributions of source code must retain the above copyright
25  * notice, this list of conditions and the following disclaimer.
26  * * Redistributions in binary form must reproduce the above copyright
27  * notice, this list of conditions and the following disclaimer in the
28  * documentation and/or other materials provided with the distribution.
29  * * Neither the name of SICK AG nor the names of its
30  * contributors may be used to endorse or promote products derived from
31  * this software without specific prior written permission
32  * * Neither the name of Ing.-Buero Dr. Michael Lehning nor the names of its
33  * contributors may be used to endorse or promote products derived from
34  * this software without specific prior written permission
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
37  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
40  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
41  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46  * POSSIBILITY OF SUCH DAMAGE.
47  *
48  * Authors:
49  * Michael Lehning <michael.lehning@lehning.de>
50  *
51  *
52  */
53 #include <cstring>
58 
59 #define ROS_DECL_GET_PARAMETER(node,name,value) do{rosDeclareParam((node),(name),(value));rosGetParam((node),(name),(value));}while(false)
60 
62 static bool setOptionalArgument(const std::map<std::string, std::string>& key_value_pairs, const std::string& key, std::string& argument)
63 {
64  std::map<std::string, std::string>::const_iterator key_value_pair_iter = key_value_pairs.find(key);
65  if (key_value_pair_iter != key_value_pairs.cend())
66  {
67  argument = key_value_pair_iter->second;
68  ROS_INFO_STREAM(key << "=\"" << argument << "\" set by commandline");
69  return true;
70  }
71  return false;
72 }
73 
75 static bool setOptionalArgument(const std::map<std::string, std::string>& key_value_pairs, const std::string& key, bool& argument)
76 {
77  std::string str_argument;
78  if (setOptionalArgument(key_value_pairs, key, str_argument) && !str_argument.empty())
79  {
80  argument = (str_argument[0] == 'T' || str_argument[0] == 't' || std::stoi(str_argument) > 0);
81  ROS_INFO_STREAM(key << "=" << (argument?"true":"false") << " set by commandline");
82  return true;
83  }
84  return false;
85 }
86 
88 static bool setOptionalArgument(const std::map<std::string, std::string>& key_value_pairs, const std::string& key, int& argument)
89 {
90  std::string str_argument;
91  if (setOptionalArgument(key_value_pairs, key, str_argument) && !str_argument.empty())
92  {
93  argument = std::stoi(str_argument);
94  ROS_INFO_STREAM(key << "=" << argument << " set by commandline");
95  return true;
96  }
97  return false;
98 }
99 
101 static bool setOptionalArgument(const std::map<std::string, std::string>& key_value_pairs, const std::string& key, float& argument)
102 {
103  std::string str_argument;
104  if (setOptionalArgument(key_value_pairs, key, str_argument) && !str_argument.empty())
105  {
106  argument = std::stof(str_argument);
107  ROS_INFO_STREAM(key << "=" << argument << " set by commandline");
108  return true;
109  }
110  return false;
111 }
112 
114 static bool setOptionalArgument(const std::map<std::string, std::string>& key_value_pairs, const std::string& key, double& argument)
115 {
116  std::string str_argument;
117  if (setOptionalArgument(key_value_pairs, key, str_argument) && !str_argument.empty())
118  {
119  argument = std::stod(str_argument);
120  ROS_INFO_STREAM(key << "=" << argument << " set by commandline");
121  return true;
122  }
123  return false;
124 }
125 
128 {
129  // Get endianess of the system (destination target) by comparing MSB and LSB of a int32 number
130  uint32_t u32_one = 1;
131  uint8_t* p_one = (uint8_t*)&u32_one;
132  uint8_t lsb = p_one[0];
133  uint8_t msb = p_one[3];
134  bool dstTargetIsBigEndian = (lsb == 0 && msb != 0);
135  bool dstTargetIsLittleEndian = (lsb != 0 && msb == 0);
136  assert(dstTargetIsBigEndian || dstTargetIsLittleEndian);
137  return dstTargetIsBigEndian;
138 }
139 
140 /*
141  * @brief Default constructor, initializes the configuration with default values
142  */
144 {
145  node = 0; // Created by Config::Init()
146  udp_sender = ""; // Use "" (default) to receive msgpacks from any udp sender, use "127.0.0.1" to restrict to localhost (loopback device), or use the ip-address of a multiScan136 lidar or multiScan136 emulator
147  udp_port = 2115; // default udp port for multiScan136 resp. multiScan136 emulator is 2115
148  publish_frame_id = "world"; // frame id of ros Laserscan messages, default: "world_<layer-id>"
149  publish_laserscan_segment_topic = "scan_segment"; // topic of ros Laserscan segment messages
150  publish_laserscan_fullframe_topic = "scan_fullframe"; //topic of ros Laserscan fullframe messages
151  udp_input_fifolength = 20; // max. udp 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
152  msgpack_output_fifolength = 20; // max. msgpack 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
153  verbose_level = 1; // verbose_level <= 0: quiet mode, verbose_level == 1: print statistics, verbose_level == 2: print details incl. msgpack data, default: 1
154  measure_timing = true; // measure_timing == true: duration and latency of msgpack conversion and export is measured, default: true
155  export_csv = false; // export msgpack data to csv file, default: false
156  export_udp_msg = false; // true : export binary udp and msgpack data to file(*.udp and* .msg), default: false
157  logfolder = ""; // output folder for logfiles, default: "" (no logging)
158  hostname = "192.168.0.1"; // IP address of multiScan136 to post start and stop commands
159  udp_receiver_ip = ""; // UDP destination IP address (host ip used in setIpAddress posted)
160  // port = 2115; // UDP port of multiScan136 to post start and stop commands
161  // send_udp_start = false; // Send udp start string to multiScan136, default: True
162  // send_udp_start_string = "magicalActivate"; // udp string to start multiScan136, default: "magicalActivate"
163  udp_timeout_ms = 10000; // Timeout for udp messages in milliseconds, default: 10*1000
164  udp_timeout_ms_initial = 60000; // Initial timeout for udp messages after start in milliseconds, default: 60*1000
165  scandataformat = 2; // ScanDataFormat: 1 for msgpack or 2 for compact scandata, default: 2
166  performanceprofilenumber = -1; // Set performance profile by sending "sWN PerformanceProfileNumber" if performanceprofilenumber >= 0 (picoScan), default: -1
167  imu_enable = false; // IMU enabled or disabled
168  imu_topic = "imu"; // ROS topic for IMU messages
169  imu_udp_port = 7503; // default udp port for multiScan imu data is 7503
170  imu_latency_microsec = 0; // imu latency in microseconds
171 
172  // SOPAS default settings
173  sopas_tcp_port = "2111"; // TCP port for SOPAS commands, default port: 2111
174  start_sopas_service = true; // True: sopas services for CoLa-commands are started (ROS only), default: true
175  send_sopas_start_stop_cmd = true; // True: multiScan136 start and stop command sequence ("sWN ScanDataEnable 0/1" etc.) are sent after driver start and stop, default: true
176  sopas_cola_binary = false; // False: SOPAS uses CoLa-A (ascii, default, recommended), CoLa-B (true, binary) currently experimental
177  sopas_timeout_ms = 5000; // Timeout for SOPAS response in milliseconds, default: 5000
178  client_authorization_pw = "F4724744"; // Default password for client authorization
179 
180  // MSR100 default filter settings
181  host_read_filtersettings = true; // Read multiScan136 settings for FREchoFilter, LFPangleRangeFilter and LFPlayerFilter at startup, default: true
182  host_FREchoFilter = 1; // Optionally set FREchoFilter with 0 for FIRST_ECHO (EchoCount=1), 1 for ALL_ECHOS (EchoCount=3), or 2 for LAST_ECHO (EchoCount=1)
183  host_set_FREchoFilter = false; // If true, FREchoFilter is set at startup (default: false)
184  host_LFPangleRangeFilter = "0 -180.0 +180.0 -90.0 +90.0 1"; // Optionally set LFPangleRangeFilter to "<enabled> <azimuth_start> <azimuth_stop> <elevation_start> <elevation_stop> <beam_increment>" with azimuth and elevation given in degree
185  host_set_LFPangleRangeFilter = false; // If true, LFPangleRangeFilter is set at startup (default: false)
186  host_LFPlayerFilter = "0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"; // (Multiscan136 only, not for picoscan) Optionally set LFPlayerFilter to "<enabled> <layer0-enabled> <layer1-enabled> <layer2-enabled> ... <layer15-enabled>" with 1 for enabled and 0 for disabled
187  host_set_LFPlayerFilter = false; // If true (Multiscan136 only, always false for picoscan), LFPlayerFilter is set at startup (default: false)
188  host_LFPintervalFilter = "0 1"; // Optionally set LFPintervalFilter to "<enabled> <N>" with 1 for enabled and 0 for disabled and N to reduce output to every N-th scan
189  host_set_LFPintervalFilter = false; // If true, LFPintervalFilter is set at startup (default: false)
190 
191  // msgpack validation default settings
192  msgpack_validator_enabled = false; // true: check msgpack data for out of bounds and missing scan data, false (default): no msgpack validation
193  msgpack_validator_verbose = 0; // 0: print error messages, 1: print error and informational messages, 2: print error and all messages
194  msgpack_validator_discard_msgpacks_out_of_bounds = true; // true: msgpacks are discarded if scan data out of bounds detected, false: error message if a msgpack is not validated
195  msgpack_validator_check_missing_scandata_interval = 12; //
196  msgpack_validator_filter_settings.msgpack_validator_required_echos = { 0 }; // default: 1 echo, for all echos use { 0, 1, 2 }
197  msgpack_validator_filter_settings.msgpack_validator_azimuth_start = (float)(-M_PI); // default for full scan: -M_PI;
198  msgpack_validator_filter_settings.msgpack_validator_azimuth_end = (float)(M_PI); // default for full scan: +M_PI;
199  msgpack_validator_filter_settings.msgpack_validator_elevation_start = (float)(-M_PI/2.0); // default for full scan: -M_PI/2.0;
200  msgpack_validator_filter_settings.msgpack_validator_elevation_end = (float)(M_PI/2.0); // default for full scan: +M_PI/2.0;
201  msgpack_validator_filter_settings.msgpack_validator_layer_filter = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; // default for full scan: 16 layer active, i.e. { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
202  msgpack_validator_valid_segments = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; // default for full scan: 12 segments, i.e. { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }
203 
204  // Configuration of laserscan messages (ROS only):
205  // Parameter "laserscan_layer_filter" sets a mask to create laserscan messages for configured layer (0: no laserscan message, 1: create laserscan messages for this layer)
206  // Use "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" to activate resp. "1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1" to activate laserscan messages for all 16 layers of the Multiscan136
207  // Default is "0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0", i.e. laserscan messages for layer 5, (elevation -0.07 degree, max number of scan points)
208  laserscan_layer_filter = { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
209 
210 }
211 
212 /*
213  * @brief Destructor
214  */
216 {
217 }
218 
219 /*
220  * @brief Prints the commandline arguments.
221  */
223 {
224  ROS_INFO_STREAM("sick_scansegment_xd receives udp packets from multiScan136 or multiScan136 emulator, unpacks, converts and exports the lidar data.");
225  ROS_INFO_STREAM("Commandline options are:");
226  ROS_INFO_STREAM("-udp_sender=<ip> : ip address of udp sender, Use \"\" (default) to receive msgpacks from any udp sender, use \"127.0.0.1\" to restrict to localhost (loopback device), or use the ip-address of a multiScan136 lidar or multiScan136 emulator");
227  ROS_INFO_STREAM("-udp_port=<port> : udp port for multiScan136 resp. multiScan136 emulator, default: " << udp_port);
228  ROS_INFO_STREAM("-udp_input_fifolength=<size> : max. udp 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");
229  ROS_INFO_STREAM("-msgpack_output_fifolength=<size> : max. msgpack 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");
230  ROS_INFO_STREAM("-verbose_level=[0-2] : verbose_level <= 0: quiet mode, verbose_level == 1: print statistics, verbose_level == 2: print details incl. msgpack data, default: " << verbose_level);
231  ROS_INFO_STREAM("-measure_timing=0|1 : measure_timing == true: duration and latency of msgpack conversion and export is measured, default: " << measure_timing);
232  ROS_INFO_STREAM("-export_csv=0|1 : export msgpack data to csv file, default: false");
233  ROS_INFO_STREAM("-export_udp_msg=0|1 : export binary udp and msgpack data to file(*.udp and* .msg), default: false");
234  ROS_INFO_STREAM("-logfolder=<directory> : output folder for logfiles" );
235  ROS_INFO_STREAM("-hostname=<ip-address> : ip address of multiScan136 to post start and stop commands default:" << hostname);
236  ROS_INFO_STREAM("-udp_receiver_ip=<ip-address> : UDP destination IP address (ip address of udp receiver), default:\"" << udp_receiver_ip << "\"");
237  // ROS_INFO_STREAM("-port=<port> : udp port of multiScan136 to post start and stop commands default:" << port);
238  // ROS_INFO_STREAM("-send_udp_start=0|1 : send udp start string to multiScan136, default:" << send_udp_start);
239  // ROS_INFO_STREAM("-send_udp_start_string=<string> : udp string to start multiScan136, default: \"magicalActivate\"" << send_udp_start_string);
240  ROS_INFO_STREAM("-scandataformat=1|2 : set ScanDataFormat, 1 for msgpack or 2 for compact scandata, default: " << scandataformat);
241  ROS_INFO_STREAM("-performanceprofilenumber=[1-9] : set PerformanceProfileNumber or -1 to disable, default: " << performanceprofilenumber);
242  ROS_INFO_STREAM("-imu_enable=0|1 : enable or disable IMU data, default: " << imu_enable);
243  ROS_INFO_STREAM("-imu_topic=<name> : ROS topic of IMU messages, default: " << imu_topic);
244  ROS_INFO_STREAM("-imu_udp_port=<port>: udp port for multiScan imu data, default: " << imu_udp_port);
245  ROS_INFO_STREAM("-imu_latency_microsec=<micro_sec>: imu latency in microseconds, default: " << imu_latency_microsec);
246 }
247 
248 /*
249  * @brief Initializes sick_scansegment_xd configuration
250  * @param[in] node ROS node handle (always 0 on non-ros-targets)
251  */
253 {
254  node = _node;
255 
256  ROS_DECL_GET_PARAMETER(node, "scanner_type", scanner_type);
257  ROS_DECL_GET_PARAMETER(node, "hostname", hostname);
258  ROS_DECL_GET_PARAMETER(node, "udp_sender", udp_sender);
259  ROS_DECL_GET_PARAMETER(node, "udp_port", udp_port);
260  ROS_DECL_GET_PARAMETER(node, "check_udp_receiver_ip", check_udp_receiver_ip);
261  ROS_DECL_GET_PARAMETER(node, "check_udp_receiver_port", check_udp_receiver_port);
262  ROS_DECL_GET_PARAMETER(node, "all_segments_min_deg", all_segments_min_deg);
263  ROS_DECL_GET_PARAMETER(node, "all_segments_max_deg", all_segments_max_deg);
264  ROS_DECL_GET_PARAMETER(node, "publish_frame_id", publish_frame_id);
265  ROS_DECL_GET_PARAMETER(node, "publish_laserscan_segment_topic", publish_laserscan_segment_topic);
266  ROS_DECL_GET_PARAMETER(node, "publish_laserscan_fullframe_topic", publish_laserscan_fullframe_topic);
267  ROS_DECL_GET_PARAMETER(node, "udp_input_fifolength", udp_input_fifolength);
268  ROS_DECL_GET_PARAMETER(node, "msgpack_output_fifolength", msgpack_output_fifolength);
269  ROS_DECL_GET_PARAMETER(node, "verbose_level", verbose_level);
270  ROS_DECL_GET_PARAMETER(node, "measure_timing", measure_timing);
271  ROS_DECL_GET_PARAMETER(node, "export_csv", export_csv);
272  ROS_DECL_GET_PARAMETER(node, "export_udp_msg", export_udp_msg);
273  ROS_DECL_GET_PARAMETER(node, "logfolder", logfolder);
274  ROS_DECL_GET_PARAMETER(node, "udp_receiver_ip", udp_receiver_ip);
275  // ROS_DECL_GET_PARAMETER(node, "send_udp_start_port", port);
276  // ROS_DECL_GET_PARAMETER(node, "send_udp_start", send_udp_start);
277  // ROS_DECL_GET_PARAMETER(node, "send_udp_start_string", send_udp_start_string);
278  ROS_DECL_GET_PARAMETER(node, "udp_timeout_ms", udp_timeout_ms);
279  ROS_DECL_GET_PARAMETER(node, "udp_timeout_ms_initial", udp_timeout_ms_initial);
280  ROS_DECL_GET_PARAMETER(node, "scandataformat", scandataformat);
281  ROS_DECL_GET_PARAMETER(node, "performanceprofilenumber", performanceprofilenumber);
282  ROS_DECL_GET_PARAMETER(node, "imu_enable", imu_enable);
283  ROS_DECL_GET_PARAMETER(node, "imu_topic", imu_topic);
284  ROS_DECL_GET_PARAMETER(node, "imu_udp_port", imu_udp_port);
285  ROS_DECL_GET_PARAMETER(node, "imu_latency_microsec", imu_latency_microsec);
286  ROS_DECL_GET_PARAMETER(node, "sopas_tcp_port", sopas_tcp_port);
287  ROS_DECL_GET_PARAMETER(node, "start_sopas_service", start_sopas_service);
288  ROS_DECL_GET_PARAMETER(node, "send_sopas_start_stop_cmd", send_sopas_start_stop_cmd);
289  ROS_DECL_GET_PARAMETER(node, "sopas_cola_binary", sopas_cola_binary);
290  ROS_DECL_GET_PARAMETER(node, "sopas_timeout_ms", sopas_timeout_ms);
291  ROS_DECL_GET_PARAMETER(node, "client_authorization_pw", client_authorization_pw);
292  // MSR100 filter settings
293  ROS_DECL_GET_PARAMETER(node, "host_read_filtersettings", host_read_filtersettings);
294  ROS_DECL_GET_PARAMETER(node, "host_FREchoFilter", host_FREchoFilter);
295  ROS_DECL_GET_PARAMETER(node, "host_set_FREchoFilter", host_set_FREchoFilter);
296  ROS_DECL_GET_PARAMETER(node, "host_LFPangleRangeFilter", host_LFPangleRangeFilter);
297  ROS_DECL_GET_PARAMETER(node, "host_set_LFPangleRangeFilter", host_set_LFPangleRangeFilter);
298  ROS_DECL_GET_PARAMETER(node, "host_LFPintervalFilter", host_LFPintervalFilter);
299  ROS_DECL_GET_PARAMETER(node, "host_set_LFPintervalFilter", host_set_LFPintervalFilter);
300  if (scanner_type != SICK_SCANNER_PICOSCAN_NAME)
301  {
302  ROS_DECL_GET_PARAMETER(node, "host_LFPlayerFilter", host_LFPlayerFilter);
303  ROS_DECL_GET_PARAMETER(node, "host_set_LFPlayerFilter", host_set_LFPlayerFilter);
304  }
305  else
306  {
307  host_LFPlayerFilter = "";
308  host_set_LFPlayerFilter = false;
309  }
310  // msgpack validation settings
311  std::string str_msgpack_validator_required_echos = "0";
312  std::string str_msgpack_validator_valid_segments = "0 1 2 3 4 5 6 7 8 9 10 11";
313  std::string str_msgpack_validator_layer_filter = "1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1";
314  float msgpack_validator_azimuth_start_deg = msgpack_validator_filter_settings.msgpack_validator_azimuth_start * 180.0 / M_PI;
315  float msgpack_validator_azimuth_end_deg = msgpack_validator_filter_settings.msgpack_validator_azimuth_end * 180.0 / M_PI;
316  float msgpack_validator_elevation_start_deg = msgpack_validator_filter_settings.msgpack_validator_elevation_start * 180.0 / M_PI;
317  float msgpack_validator_elevation_end_deg = msgpack_validator_filter_settings.msgpack_validator_elevation_end * 180.0 / M_PI;
318  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_enabled", msgpack_validator_enabled);
319  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_verbose", msgpack_validator_verbose);
320  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_discard_msgpacks_out_of_bounds", msgpack_validator_discard_msgpacks_out_of_bounds);
321  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_check_missing_scandata_interval", msgpack_validator_check_missing_scandata_interval);
322  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_required_echos", str_msgpack_validator_required_echos);
323  sick_scansegment_xd::util::parseVector(str_msgpack_validator_required_echos, msgpack_validator_filter_settings.msgpack_validator_required_echos);
324  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_azimuth_start", msgpack_validator_azimuth_start_deg);
325  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_azimuth_end", msgpack_validator_azimuth_end_deg);
326  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_elevation_start", msgpack_validator_elevation_start_deg);
327  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_elevation_end", msgpack_validator_elevation_end_deg);
328  msgpack_validator_filter_settings.msgpack_validator_azimuth_start = msgpack_validator_azimuth_start_deg * M_PI / 180;
329  msgpack_validator_filter_settings.msgpack_validator_azimuth_end = msgpack_validator_azimuth_end_deg * M_PI / 180;
330  msgpack_validator_filter_settings.msgpack_validator_elevation_start = msgpack_validator_elevation_start_deg * M_PI / 180;
331  msgpack_validator_filter_settings.msgpack_validator_elevation_end = msgpack_validator_elevation_end_deg * M_PI / 180;
332  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_valid_segments", str_msgpack_validator_valid_segments);
333  ROS_DECL_GET_PARAMETER(node, "msgpack_validator_layer_filter", str_msgpack_validator_layer_filter);
334  sick_scansegment_xd::util::parseVector(str_msgpack_validator_valid_segments, msgpack_validator_valid_segments);
335  sick_scansegment_xd::util::parseVector(str_msgpack_validator_layer_filter, msgpack_validator_filter_settings.msgpack_validator_layer_filter);
336  // Apply an additional transform to the cartesian pointcloud, default: "0,0,0,0,0,0" (i.e. no transform)
337  std::string str_add_transform_xyz_rpy = "0,0,0,0,0,0";
338  ROS_DECL_GET_PARAMETER(node, "add_transform_xyz_rpy", str_add_transform_xyz_rpy);
339  bool add_transform_check_dynamic_updates = false;
340  ROS_DECL_GET_PARAMETER(node, "add_transform_check_dynamic_updates", add_transform_check_dynamic_updates);
341  add_transform_xyz_rpy = sick_scan_xd::SickCloudTransform(node, str_add_transform_xyz_rpy, true, add_transform_check_dynamic_updates);
342 
343  // Configuration of laserscan messages (ROS only), activate/deactivate laserscan messages for each layer
344  std::string str_laserscan_layer_filter = "0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0";
345  ROS_DECL_GET_PARAMETER(node, "laserscan_layer_filter", str_laserscan_layer_filter);
346  sick_scansegment_xd::util::parseVector(str_laserscan_layer_filter, laserscan_layer_filter);
347 
348  if (imu_enable && scandataformat != 2)
349  {
350  ROS_ERROR_STREAM("## ERROR sick_scansegment_xd::Config::Init(): IMU requieres scandataformat 2, IMU deactivated.");
351  imu_enable = false;
352  }
353 
354  return true;
355 }
356 
357 /*
358  * @brief Initializes sick_scansegment_xd configuration by commandline arguments and yaml-file.
359  */
360 bool sick_scansegment_xd::Config::Init(int argc, char** argv)
361 {
362  // Read yaml configuration
363  #if defined __ROS_VERSION && __ROS_VERSION > 1
364  rclcpp::init(argc, argv);
365  rclcpp::NodeOptions node_options;
366  node_options.allow_undeclared_parameters(true);
367  node = rclcpp::Node::make_shared("sick_scansegment_xd", "", node_options);
368  Init(node);
369  #elif defined __ROS_VERSION && __ROS_VERSION > 0
370  ros::init(argc, argv, "sick_scansegment_xd");
371  node = new ros::NodeHandle();
372  Init(node);
373  #endif
374 
375  // Parse commandline arguments
376  std::map<std::string, std::string> cli_parameter_map;
377  for (int n = 1; n < argc; n++)
378  {
379  std::stringstream cli_argument(argv[n]);
380  std::string cli_token;
381  std::vector<std::string> cli_tokens;
382  // split argument "-key=value" into 2 tokens
383  while (getline(cli_argument, cli_token, '='))
384  {
385  cli_tokens.push_back(cli_token);
386  }
387  if (cli_tokens.size() == 2 && !cli_tokens[0].empty() && !cli_tokens[1].empty())
388  {
389  // remove leading '-' for all "-key=value" arguments
390  if (cli_tokens[0][0] == '-')
391  cli_tokens[0] = cli_tokens[0].substr(1);
392  // remove trailing ':' for all "key:=value" arguments
393  if (cli_tokens[0][(cli_tokens[0].length() - 1)] == ':')
394  cli_tokens[0] = cli_tokens[0].substr(0, cli_tokens[0].length() - 1);
395  // append key-value-pair to map
396  cli_parameter_map[cli_tokens[0]] = cli_tokens[1];
397  }
398  }
399  for(std::map<std::string, std::string>::const_iterator iter = cli_parameter_map.cbegin(); iter != cli_parameter_map.cend(); iter++)
400  ROS_INFO_STREAM("commandline argument found: \"" << iter->first << "\"=\"" << iter->second << "\"");
401 
402  // Overwrite with commandline arguments
403  setOptionalArgument(cli_parameter_map, "udp_sender", udp_sender);
404  setOptionalArgument(cli_parameter_map, "udp_port", udp_port);
405  setOptionalArgument(cli_parameter_map, "check_udp_receiver_ip", check_udp_receiver_ip);
406  setOptionalArgument(cli_parameter_map, "check_udp_receiver_port", check_udp_receiver_port);
407  setOptionalArgument(cli_parameter_map, "all_segments_min_deg", all_segments_min_deg);
408  setOptionalArgument(cli_parameter_map, "all_segments_max_deg", all_segments_max_deg);
409  setOptionalArgument(cli_parameter_map, "publish_frame_id", publish_frame_id);
410  setOptionalArgument(cli_parameter_map, "publish_laserscan_segment_topic", publish_laserscan_segment_topic);
411  setOptionalArgument(cli_parameter_map, "publish_laserscan_fullframe_topic", publish_laserscan_fullframe_topic);
412  setOptionalArgument(cli_parameter_map, "udp_input_fifolength", udp_input_fifolength);
413  setOptionalArgument(cli_parameter_map, "msgpack_output_fifolength", msgpack_output_fifolength);
414  setOptionalArgument(cli_parameter_map, "verbose_level", verbose_level);
415  setOptionalArgument(cli_parameter_map, "measure_timing", measure_timing);
416  setOptionalArgument(cli_parameter_map, "export_csv", export_csv);
417  setOptionalArgument(cli_parameter_map, "export_udp_msg", export_udp_msg);
418  setOptionalArgument(cli_parameter_map, "logfolder", logfolder);
419  setOptionalArgument(cli_parameter_map, "hostname", hostname);
420  setOptionalArgument(cli_parameter_map, "udp_receiver_ip", udp_receiver_ip);
421  // setOptionalArgument(cli_parameter_map, "send_udp_start", send_udp_start);;
422  // setOptionalArgument(cli_parameter_map, "send_udp_start_string", send_udp_start_string);
423  setOptionalArgument(cli_parameter_map, "udp_timeout_ms", udp_timeout_ms);
424  setOptionalArgument(cli_parameter_map, "udp_timeout_ms_initial", udp_timeout_ms_initial);
425  setOptionalArgument(cli_parameter_map, "scandataformat", scandataformat);
426  setOptionalArgument(cli_parameter_map, "performanceprofilenumber", performanceprofilenumber);
427  setOptionalArgument(cli_parameter_map, "imu_enable", imu_enable);
428  setOptionalArgument(cli_parameter_map, "imu_topic", imu_topic);
429  setOptionalArgument(cli_parameter_map, "imu_udp_port", imu_udp_port);
430  setOptionalArgument(cli_parameter_map, "imu_latency_microsec", imu_latency_microsec);
431  setOptionalArgument(cli_parameter_map, "sopas_tcp_port", sopas_tcp_port);
432  setOptionalArgument(cli_parameter_map, "start_sopas_service", start_sopas_service);
433  setOptionalArgument(cli_parameter_map, "send_sopas_start_stop_cmd", send_sopas_start_stop_cmd);
434  setOptionalArgument(cli_parameter_map, "sopas_cola_binary", sopas_cola_binary);
435  setOptionalArgument(cli_parameter_map, "sopas_timeout_ms", sopas_timeout_ms);
436  setOptionalArgument(cli_parameter_map, "client_authorization_pw", client_authorization_pw);
437  setOptionalArgument(cli_parameter_map, "host_read_filtersettings", host_read_filtersettings);
438  setOptionalArgument(cli_parameter_map, "host_FREchoFilter", host_FREchoFilter);
439  setOptionalArgument(cli_parameter_map, "host_set_FREchoFilter", host_set_FREchoFilter);
440  setOptionalArgument(cli_parameter_map, "host_LFPangleRangeFilter", host_LFPangleRangeFilter);
441  setOptionalArgument(cli_parameter_map, "host_set_LFPangleRangeFilter", host_set_LFPangleRangeFilter);
442  setOptionalArgument(cli_parameter_map, "host_LFPlayerFilter", host_LFPlayerFilter);
443  setOptionalArgument(cli_parameter_map, "host_set_LFPlayerFilter", host_set_LFPlayerFilter);
444  setOptionalArgument(cli_parameter_map, "host_LFPintervalFilter", host_LFPintervalFilter);
445  setOptionalArgument(cli_parameter_map, "host_set_LFPintervalFilter", host_set_LFPintervalFilter);
446  setOptionalArgument(cli_parameter_map, "msgpack_validator_enabled", msgpack_validator_enabled);
447  setOptionalArgument(cli_parameter_map, "msgpack_validator_verbose", msgpack_validator_verbose);
448  setOptionalArgument(cli_parameter_map, "msgpack_validator_discard_msgpacks_out_of_bounds", msgpack_validator_discard_msgpacks_out_of_bounds);
449  setOptionalArgument(cli_parameter_map, "msgpack_validator_check_missing_scandata_interval", msgpack_validator_check_missing_scandata_interval);
450  std::string cli_msgpack_validator_required_echos, cli_msgpack_validator_valid_segments, cli_msgpack_validator_layer_filter, cli_laserscan_layer_filter;
451  float cli_msgpack_validator_azimuth_start_deg, cli_msgpack_validator_azimuth_end_deg, cli_msgpack_validator_elevation_start_deg, cli_msgpack_validator_elevation_end_deg;
452  if (setOptionalArgument(cli_parameter_map, "msgpack_validator_required_echos", cli_msgpack_validator_required_echos))
453  sick_scansegment_xd::util::parseVector(cli_msgpack_validator_required_echos, msgpack_validator_filter_settings.msgpack_validator_required_echos);
454  if (setOptionalArgument(cli_parameter_map, "msgpack_validator_azimuth_start", cli_msgpack_validator_azimuth_start_deg))
455  msgpack_validator_filter_settings.msgpack_validator_azimuth_start = cli_msgpack_validator_azimuth_start_deg * (float)M_PI / 180.0f;
456  if (setOptionalArgument(cli_parameter_map, "msgpack_validator_azimuth_end", cli_msgpack_validator_azimuth_end_deg))
457  msgpack_validator_filter_settings.msgpack_validator_azimuth_end = cli_msgpack_validator_azimuth_end_deg * (float)M_PI / 180.0f;
458  if (setOptionalArgument(cli_parameter_map, "msgpack_validator_elevation_start", cli_msgpack_validator_elevation_start_deg))
459  msgpack_validator_filter_settings.msgpack_validator_elevation_start = cli_msgpack_validator_elevation_start_deg * (float)M_PI / 180.0f;
460  if (setOptionalArgument(cli_parameter_map, "msgpack_validator_elevation_end", cli_msgpack_validator_elevation_end_deg))
461  msgpack_validator_filter_settings.msgpack_validator_elevation_end = cli_msgpack_validator_elevation_end_deg * (float)M_PI / 180.0f;
462  if (setOptionalArgument(cli_parameter_map, "msgpack_validator_valid_segments", cli_msgpack_validator_valid_segments))
463  sick_scansegment_xd::util::parseVector(cli_msgpack_validator_valid_segments, msgpack_validator_valid_segments);
464  if (setOptionalArgument(cli_parameter_map, "msgpack_validator_layer_filter", cli_msgpack_validator_layer_filter))
465  sick_scansegment_xd::util::parseVector(cli_msgpack_validator_layer_filter, msgpack_validator_filter_settings.msgpack_validator_layer_filter);
466  if (setOptionalArgument(cli_parameter_map, "laserscan_layer_filter", cli_laserscan_layer_filter))
467  sick_scansegment_xd::util::parseVector(cli_laserscan_layer_filter, laserscan_layer_filter);
468 
469  PrintConfig();
470 
471  if (imu_enable && scandataformat != 2)
472  {
473  ROS_ERROR_STREAM("## ERROR sick_scansegment_xd::Config::Init(): IMU requieres scandataformat 2, IMU deactivated.");
474  imu_enable = false;
475  }
476 
477  return true;
478 }
479 
480 /*
481  * @brief Prints the current settings.
482  */
484 {
485  ROS_INFO_STREAM("sick_scansegment_xd configuration:");
486  ROS_INFO_STREAM("scanner_type: " << scanner_type);
487  ROS_INFO_STREAM("udp_sender: " << udp_sender);
488  ROS_INFO_STREAM("udp_port: " << udp_port);
489  ROS_INFO_STREAM("check_udp_receiver_ip: " << check_udp_receiver_ip);
490  ROS_INFO_STREAM("check_udp_receiver_port: " << check_udp_receiver_port);
491  ROS_INFO_STREAM("all_segments_min_deg: " << all_segments_min_deg);
492  ROS_INFO_STREAM("all_segments_max_deg: " << all_segments_max_deg);
493  ROS_INFO_STREAM("publish_frame_id: " << publish_frame_id);
494  ROS_INFO_STREAM("publish_laserscan_segment_topic: " << publish_laserscan_segment_topic);
495  ROS_INFO_STREAM("publish_laserscan_fullframe_topic:" << publish_laserscan_fullframe_topic);
496  ROS_INFO_STREAM("udp_input_fifolength: " << udp_input_fifolength);
497  ROS_INFO_STREAM("msgpack_output_fifolength: " << msgpack_output_fifolength);
498  ROS_INFO_STREAM("verbose_level: " << verbose_level);
499  ROS_INFO_STREAM("measure_timing: " << measure_timing);
500  ROS_INFO_STREAM("export_csv: " << export_csv);
501  ROS_INFO_STREAM("export_udp_msg: " << export_udp_msg);
502  ROS_INFO_STREAM("logfolder: " << logfolder);
503  ROS_INFO_STREAM("hostname: " << hostname);
504  ROS_INFO_STREAM("udp_receiver_ip: " << udp_receiver_ip);
505  //ROS_INFO_STREAM("send_udp_start_port: " << port);
506  //ROS_INFO_STREAM("send_udp_start: " << send_udp_start);
507  //ROS_INFO_STREAM("send_udp_start_string: " << send_udp_start_string);
508  ROS_INFO_STREAM("udp_timeout_ms: " << udp_timeout_ms);
509  ROS_INFO_STREAM("udp_timeout_ms_initial: " << udp_timeout_ms_initial);
510  ROS_INFO_STREAM("scandataformat: " << scandataformat);
511  ROS_INFO_STREAM("performanceprofilenumber: " << performanceprofilenumber);
512  ROS_INFO_STREAM("imu_enable: " << imu_enable);
513  ROS_INFO_STREAM("imu_topic: " << imu_topic);
514  ROS_INFO_STREAM("imu_udp_port: " << imu_udp_port);
515  ROS_INFO_STREAM("imu_latency_microsec: " << imu_latency_microsec);
516  ROS_INFO_STREAM("sopas_tcp_port: " << sopas_tcp_port);
517  ROS_INFO_STREAM("start_sopas_service: " << start_sopas_service);
518  ROS_INFO_STREAM("send_sopas_start_stop_cmd: " << send_sopas_start_stop_cmd);
519  ROS_INFO_STREAM("sopas_cola_binary: " << sopas_cola_binary);
520  ROS_INFO_STREAM("sopas_timeout_ms: " << sopas_timeout_ms);
521  ROS_INFO_STREAM("host_read_filtersettings: " << host_read_filtersettings);
522  ROS_INFO_STREAM("host_FREchoFilter: " << host_FREchoFilter);
523  ROS_INFO_STREAM("host_set_FREchoFilter: " << host_set_FREchoFilter);
524  ROS_INFO_STREAM("host_LFPangleRangeFilter: " << host_LFPangleRangeFilter);
525  ROS_INFO_STREAM("host_set_LFPangleRangeFilter: " << host_set_LFPangleRangeFilter);
526  ROS_INFO_STREAM("host_LFPlayerFilter: " << host_LFPlayerFilter);
527  ROS_INFO_STREAM("host_set_LFPlayerFilter: " << host_set_LFPlayerFilter);
528  ROS_INFO_STREAM("host_LFPintervalFilter: " << host_LFPintervalFilter);
529  ROS_INFO_STREAM("host_set_LFPintervalFilter: " << host_set_LFPintervalFilter);
530  ROS_INFO_STREAM("laserscan_layer_filter: " << sick_scansegment_xd::util::printVector(laserscan_layer_filter));
531  ROS_INFO_STREAM("msgpack_validator_enabled: " << msgpack_validator_enabled);
532  ROS_INFO_STREAM("msgpack_validator_verbose: " << msgpack_validator_verbose);
533  ROS_INFO_STREAM("msgpack_validator_discard_msgpacks_out_of_bounds: " << msgpack_validator_discard_msgpacks_out_of_bounds);
534  ROS_INFO_STREAM("msgpack_validator_check_missing_scandata_interval: " << msgpack_validator_check_missing_scandata_interval);
535  ROS_INFO_STREAM("msgpack_validator_required_echos: " << sick_scansegment_xd::util::printVector(msgpack_validator_filter_settings.msgpack_validator_required_echos));
536  ROS_INFO_STREAM("msgpack_validator_azimuth_start: " << msgpack_validator_filter_settings.msgpack_validator_azimuth_start << " [rad]");
537  ROS_INFO_STREAM("msgpack_validator_azimuth_end: " << msgpack_validator_filter_settings.msgpack_validator_azimuth_end << " [rad]");
538  ROS_INFO_STREAM("msgpack_validator_elevation_start: " << msgpack_validator_filter_settings.msgpack_validator_elevation_start << " [rad]");
539  ROS_INFO_STREAM("msgpack_validator_elevation_end: " << msgpack_validator_filter_settings.msgpack_validator_elevation_end << " [rad]");
540  ROS_INFO_STREAM("msgpack_validator_valid_segments: " << sick_scansegment_xd::util::printVector(msgpack_validator_valid_segments));
541  ROS_INFO_STREAM("msgpack_validator_layer_filter: " << sick_scansegment_xd::util::printVector(msgpack_validator_filter_settings.msgpack_validator_layer_filter));
542 
543 }
sick_scansegment_xd::Config::~Config
~Config()
Definition: config.cpp:215
sick_scansegment_xd::Config::Init
bool Init(int argc, char **argv)
Definition: config.cpp:360
sick_scan_xd::SickCloudTransform
Definition: sick_cloud_transform.h:85
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
alternate ROS initialization function.
ROS_DECL_GET_PARAMETER
#define ROS_DECL_GET_PARAMETER(node, name, value)
Definition: config.cpp:59
sick_scansegment_xd::util::parseVector
void parseVector(const std::string str, std::vector< std::string > &vec, char delim=' ')
Definition: config.h:204
sick_scansegment_xd::util::printVector
std::string printVector(const std::vector< T > &vec, const std::string &delim=" ")
Definition: config.h:236
sick_scansegment_xd::Config::Config
Config()
Definition: config.cpp:143
f
f
sick_ros_wrapper.h
roswrap::param::init
void init(const M_string &remappings)
Definition: param_modi.cpp:809
ROS_INFO_STREAM
#define ROS_INFO_STREAM(...)
Definition: sick_scan_ros2_example.cpp:71
sick_generic_parser.h
polar_to_cartesian_pointcloud_ros1.node
node
Definition: polar_to_cartesian_pointcloud_ros1.py:81
multiscan_pcap_player.udp_port
int udp_port
Definition: multiscan_pcap_player.py:137
sick_scan_common_tcp.h
ros::NodeHandle
sick_scan_xd_api_test.verbose_level
verbose_level
Definition: sick_scan_xd_api_test.py:346
setOptionalArgument
static bool setOptionalArgument(const std::map< std::string, std::string > &key_value_pairs, const std::string &key, std::string &argument)
Definition: config.cpp:62
sick_scansegment_xd::Config::PrintHelp
void PrintHelp(void)
Definition: config.cpp:222
length
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
config.h
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(...)
Definition: sick_scan_ros2_example.cpp:72
sick_scansegment_xd::Config::SystemIsBigEndian
static bool SystemIsBigEndian(void)
Definition: config.cpp:127
sick_scansegment_xd::Config::PrintConfig
void PrintConfig(void)
Definition: config.cpp:483
ros::NodeHandle
SICK_SCANNER_PICOSCAN_NAME
#define SICK_SCANNER_PICOSCAN_NAME
Definition: sick_generic_parser.h:83


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