sick_ldmrs_driver.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015, DFKI GmbH
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of DFKI GmbH nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * Created on: 20.11.2015
30  *
31  * Authors:
32  * Martin Günther <martin.guenther@dfki.de>
33  * Jochen Sprickerhof <jochen@sprickerhof.de>
34  *
35  * Modified and ported to ROS2: 02.10.2020 by Ing.-Buero Dr. Michael Lehning, Hildesheim
36  */
37 
38 #include <iostream>
39 #include <memory>
40 #include <tf2/LinearMath/Quaternion.h>
41 
44 #include <sick_ldmrs/datatypes/EvalCaseResults.hpp>
45 #include <sick_ldmrs/datatypes/EvalCases.hpp>
46 #include <sick_ldmrs/datatypes/Fields.hpp>
47 #include <sick_ldmrs/datatypes/Measurement.hpp>
48 #include <sick_ldmrs/datatypes/Msg.hpp>
49 #include <sick_ldmrs/datatypes/Scan.hpp>
50 #include <sick_ldmrs/devices/LD_MRS.hpp>
51 #include <sick_ldmrs/tools/errorhandler.hpp>
52 #include <sick_ldmrs/tools/toolbox.hpp>
53 #ifdef ROSSIMU
55 #endif
56 
57 // Convert lmdrs scan to PointCloud2
58 void ldmrsScanToPointCloud2(const datatypes::Scan* scan, sick_scan_xd::SickCloudTransform& add_transform_xyz_rpy, sick_scan_xd::SickRangeFilter& range_filter, bool isRearMirrorSide, const std::string& frame_id, ros_sensor_msgs::PointCloud2& msg, ros_sensor_msgs::PointCloud2& msg_polar);
59 
61 {
62 
63 SickLDMRS::SickLDMRS(rosNodePtr nh, Manager *manager, std::shared_ptr<diagnostic_updater::Updater> diagnostics)
64  : application::BasicApplication()
65  , diagnostics_(diagnostics)
66  , manager_(manager)
67  , expected_frequency_(12.5)
68  , initialized_(false)
69  , nh_(nh)
70  , config_(nh)
71  , pub_()
72  , object_pub_()
73  , diagnosticPub_(0)
74 {
75  std::string nodename;
76  rosDeclareParam(nh, "nodename", nodename);
77  rosGetParam(nh, "nodename", nodename);
78  rosDeclareParam(nh, "cloud_topic", cloud_topic_val);
79  rosGetParam(nh, "cloud_topic", cloud_topic_val);
81 
82  float range_min = 0, range_max = 100;
83  int range_filter_handling = 0;
84  rosDeclareParam(nh, "range_min", range_min);
85  rosGetParam(nh, "range_min", range_min);
86  rosDeclareParam(nh, "range_max", range_max);
87  rosGetParam(nh, "range_max", range_max);
88  rosDeclareParam(nh, "range_filter_handling", range_filter_handling);
89  rosGetParam(nh, "range_filter_handling", range_filter_handling);
91  ROS_INFO_STREAM("Range filter configuration for sick_scansegment_xd: range_min=" << range_min << ", range_max=" << range_max << ", range_filter_handling=" << range_filter_handling);
92 
93  // point cloud publisher
94  pub_ = rosAdvertise<ros_sensor_msgs::PointCloud2>(nh_, cloud_topic_val);
95  object_pub_ = rosAdvertise<sick_scan_msg::SickLdmrsObjectArray>(nh_, nodename + "/objects");
96 
97  #if defined USE_DIAGNOSTIC_UPDATER
98  diagnostics_->setHardwareID("none"); // set from device after connection
99  diagnostics_->add("device info", this, &SickLDMRS::produce_diagnostics);
101  diagnostic_updater::FrequencyStatusParam(&expected_frequency_, &expected_frequency_, 0.1, 10), // frequency should be target +- 10%
102  diagnostic_updater::TimeStampStatusParam(-1, 1.3 * 1.0 / 12.5)); // timestamp delta can be from -1 seconds to 1.3x what it ideally is at the lowest frequency
103  #endif
104 }
105 
107 {
108  delete diagnosticPub_;
109 }
110 
112 {
113  if (isUpsideDown())
114  {
115  ROS_ERROR_STREAM("Error: upside down mode is active, please disable!");
116  }
117  initialized_ = true;
119 
120 #if defined USE_DYNAMIC_RECONFIGURE && __ROS_VERSION == 1
122  // f = boost::bind(&SickLDMRS::update_config_cb, this, _1, _2);
123  f = std::bind(&SickLDMRS::update_config_cb, this, std::placeholders::_1, std::placeholders::_2);
124  dynamic_reconfigure_server_.setCallback(f);
125 #elif defined USE_DYNAMIC_RECONFIGURE && __ROS_VERSION == 2
126  rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr parameter_cb_handle =
127  nh_->add_on_set_parameters_callback(std::bind(&SickLDMRS::update_config_cb, this, std::placeholders::_1));
128 #endif
129 }
130 
132 {
133  devices::LDMRS* ldmrs;
134  ldmrs = dynamic_cast<devices::LDMRS*>(manager_->getFirstDeviceByType(Sourcetype_LDMRS));
135  stat.summary(diagnostic_msgs_DiagnosticStatus_OK, "Device information.");
136 
137  // REP-138 values (http://www.ros.org/reps/rep-0138.html#diagnostic-keys)
138  stat.add("IP Address", ldmrs->getIpAddress());
139  stat.add("IP Port", 12002); // LUX port number
140  stat.add("Vendor Name", "SICK");
141  stat.add("Product Name", "LD-MRS");
142  stat.add("Firmware Version", ldmrs->getFirmwareVersion()); // includes date, e.g. "3.03.5 2015-01-14 13:32"
143  stat.add("FPGA Version", ldmrs->getFPGAVersion()); // FPGA version including date
144  std::string temperature = std::to_string(ldmrs->getTemperature());
145  stat.add("Temperature", temperature);
146  stat.add("Device ID", ldmrs->getSerialNumber());
147 }
148 
149 void SickLDMRS::setData(BasicData &data)
150 {
151  std::string datatypeStr;
152  std::string sourceIdStr;
153 
154  switch (data.getDatatype())
155  {
156  case Datatype_Scan:
157  datatypeStr = "Scan (" + ::toString(((Scan&)data).getNumPoints()) + " points)";
158  {
159  Scan* scan = dynamic_cast<Scan*>(&data);
160  std::vector<ScannerInfo> scannerInfos = scan->getScannerInfos();
161  if (scannerInfos.size() != 1)
162  {
163  ROS_ERROR_STREAM("Expected exactly 1 scannerInfo, got " << scannerInfos.size());
164  return;
165  }
166  const Time& time = scannerInfos[0].getStartTimestamp();
167  ROS_DEBUG_STREAM("setData(): Scan start time: " << time.toString() << " (" << time.toLongString() << ")");
168 
170  ldmrsScanToPointCloud2(scan, m_add_transform_xyz_rpy, m_range_filter, scannerInfos[0].isRearMirrorSide(), config_.frame_id, msg, msg_polar);
171  sick_scan_xd::PointCloud2withEcho sick_cloud_msg(&msg, 1, 0, cloud_topic_val);
172  sick_scan_xd::PointCloud2withEcho sick_cloud_msg_polar(&msg_polar, 1, 0, cloud_topic_val);
173  notifyPolarPointcloudListener(nh_, &sick_cloud_msg_polar);
174  notifyCartesianPointcloudListener(nh_, &sick_cloud_msg);
175  if(diagnosticPub_)
177  else
178  rosPublish(pub_, msg);
179 #ifdef ROSSIMU
180  // plotPointCloud(msg);
181 #endif
182  }
183  break;
184  case Datatype_Objects:
185  datatypeStr = "Objects (" + ::toString(((ObjectList&)data).size()) + " objects)";
186  pubObjects((ObjectList&)data);
187  break;
188  case Datatype_Fields:
189  datatypeStr = "Fields (" + ::toString(((Fields&)data).getFields().size()) + " fields, " +
190  ::toString(((Fields&)data).getNumberOfValidFields()) + " of which are valid)";
191  break;
192  case Datatype_EvalCases:
193  datatypeStr = "EvalCases (" + ::toString(((EvalCases&)data).getEvalCases().size()) + " cases)";
194  break;
196  datatypeStr = "EvalCaseResults (" + ::toString(((EvalCaseResults&)data).size()) + " case results)";
197  break;
198  case Datatype_Msg:
199  datatypeStr = "Msg (" + ((Msg&)data).toString() + ")";
201  diagnostics_->force_update();
202  break;
204  datatypeStr = "MeasurementList (" + ::toString(((MeasurementList&)data).m_list.size()) + " entries)";
205  break;
206  default:
207  datatypeStr = "(unknown)";
208  }
209 
210  sourceIdStr = ::toString(data.getSourceId());
211 
212  ROS_DEBUG_STREAM("setData(): Called with data of type " << datatypeStr << " from ID " << sourceIdStr);
213 }
214 
216 {
217  if (conf.start_angle <= conf.end_angle)
218  {
219  ROS_WARN_STREAM("Start angle must be greater than end angle. Adjusting start_angle.");
220  conf.start_angle = conf.end_angle; // TODO: - 2 * ticks2rad
221  }
222 
223  if (conf.angular_resolution_type != sick_ldmrs_driver::SickLDMRSDriverConfig::angular_res_enum::ConstantRes // SickLDMRSDriver_ConstantRes
224  && conf.scan_frequency != sick_ldmrs_driver::SickLDMRSDriverConfig::scan_freq_enum::ScanFreq1250) // SickLDMRSDriver_ScanFreq1250)
225  {
226  ROS_WARN_STREAM("Focused/flexible resolution only available at 12.5 Hz scan frequency. Adjusting scan frequency.");
227  conf.scan_frequency = sick_ldmrs_driver::SickLDMRSDriverConfig::scan_freq_enum::ScanFreq1250; // SickLDMRSDriver_ScanFreq1250;
228  }
229 
230  if (conf.ignore_near_range && conf.layer_range_reduction != sick_ldmrs_driver::SickLDMRSDriverConfig::range_reduction_enum::RangeLowerReduced) // SickLDMRSDriver_RangeLowerReduced)
231  {
232  ROS_WARN_STREAM("If ignore_near_range is set, layer_range_reduction must be set to 'Lower 4 layers reduced range'. Adjusting layer_range_reduction.");
233  conf.layer_range_reduction = sick_ldmrs_driver::SickLDMRSDriverConfig::range_reduction_enum::RangeLowerReduced; // SickLDMRSDriver_RangeLowerReduced;
234  }
235 
251 }
252 
254 {
255  // Check that res is one of 4/8/16/32. This has to be checked manually here, since
256  // the dynamic parameter is an int with min 4 and max 32, so dynamic reconfigure
257  // doesn't prevent the user from setting an invalid value inside that range.
258  // (Values outside that range will still be clamped automatically.)
259 
260  switch (res)
261  {
262  case sick_ldmrs_driver::SickLDMRSDriverConfig::resolution_enum::Res0125: // SickLDMRSDriver_Res0125:
263  case sick_ldmrs_driver::SickLDMRSDriverConfig::resolution_enum::Res0250: // SickLDMRSDriver_Res0250:
264  case sick_ldmrs_driver::SickLDMRSDriverConfig::resolution_enum::Res0500: // SickLDMRSDriver_Res0500:
265  case sick_ldmrs_driver::SickLDMRSDriverConfig::resolution_enum::Res1000: // SickLDMRSDriver_Res1000:
266  break;
267  default:
268  ROS_WARN_STREAM("Invalid flexres resolution " << res << "! Setting to 32 (= 1 degree).");
269  res = sick_ldmrs_driver::SickLDMRSDriverConfig::resolution_enum::Res1000; // SickLDMRSDriver_Res1000;
270  break;
271  }
272 }
273 
274 void SickLDMRS::validate_flexres_start_angle(double &angle1, double &angle2)
275 {
276  // make sure the angles are monotonically decreasing
277  if (angle2 > angle1)
278  {
279  angle2 = angle1;
280  }
281 }
282 
283 void SickLDMRS::pubObjects(datatypes::ObjectList &objects)
284 {
285  // sick_ldmrs_msgs::msg::ObjectArray oa;
287  oa.header.frame_id = config_.frame_id;
288  // not using time stamp from scanner here, because it is delayed by up to 1.5 seconds
289  oa.header.stamp = rosTimeNow(); // s_rclcpp_clock.now(); // ros::Time::now();
290  oa.objects.resize(objects.size());
291 
292  for (int i = 0; i < objects.size(); i++)
293  {
294  oa.objects[i].id = objects[i].getObjectId();
295 #if __ROS_VERSION == 2 // ROS-2 (Linux or Windows)
296  oa.objects[i].tracking_time = rosTimeNow() - rosDuration(std::chrono::nanoseconds((uint64_t)(1.0e9 * objects[i].getObjectAge() / expected_frequency_)));
297  oa.objects[i].last_seen = rosTimeNow() - rosDuration(std::chrono::nanoseconds((uint64_t)(1.0e9 * objects[i].getHiddenStatusAge() / expected_frequency_)));
298 #else
299  oa.objects[i].tracking_time = rosTimeNow() - rosDuration(objects[i].getObjectAge() / expected_frequency_);
300  oa.objects[i].last_seen = rosTimeNow() - rosDuration(objects[i].getHiddenStatusAge() / expected_frequency_);
301 #endif
302  oa.objects[i].velocity.twist.linear.x = objects[i].getAbsoluteVelocity().getX();
303  oa.objects[i].velocity.twist.linear.y = objects[i].getAbsoluteVelocity().getY();
304  oa.objects[i].velocity.twist.linear.x = objects[i].getAbsoluteVelocity().getX();
305  oa.objects[i].velocity.twist.linear.y = objects[i].getAbsoluteVelocity().getY();
306  oa.objects[i].velocity.covariance[0] = objects[i].getAbsoluteVelocitySigma().getX();
307  oa.objects[i].velocity.covariance[7] = objects[i].getAbsoluteVelocitySigma().getX();
308 
309  oa.objects[i].bounding_box_center.position.x = objects[i].getBoundingBoxCenter().getX();
310  oa.objects[i].bounding_box_center.position.y = objects[i].getBoundingBoxCenter().getY();
311  oa.objects[i].bounding_box_size.x = objects[i].getBoundingBox().getX();
312  oa.objects[i].bounding_box_size.y = objects[i].getBoundingBox().getY();
313 
314  oa.objects[i].object_box_center.pose.position.x = objects[i].getCenterPoint().getX();
315  oa.objects[i].object_box_center.pose.position.y = objects[i].getCenterPoint().getY();
316  // oa.objects[i].object_box_center.pose.orientation = tf::createQuaternionMsgFromYaw(objects[i].getCourseAngle());
317  tf2::Quaternion q;
318  q.setRPY(0, 0, objects[i].getCourseAngle());
319  oa.objects[i].object_box_center.pose.orientation.x = q.x();
320  oa.objects[i].object_box_center.pose.orientation.y = q.y();
321  oa.objects[i].object_box_center.pose.orientation.z = q.z();
322  oa.objects[i].object_box_center.pose.orientation.w = q.w();
323  oa.objects[i].object_box_center.covariance[0] = objects[i].getCenterPointSigma().getX();
324  oa.objects[i].object_box_center.covariance[7] = objects[i].getCenterPointSigma().getY();
325  oa.objects[i].object_box_center.covariance[35] = objects[i].getCourseAngleSigma();
326  oa.objects[i].object_box_size.x = objects[i].getObjectBox().getX();
327  oa.objects[i].object_box_size.y = objects[i].getObjectBox().getY();
328 
329  datatypes::Polygon2D contour = objects[i].getContourPoints();
330  oa.objects[i].contour_points.resize(contour.size());
331  for (int j = 0; j < contour.size(); j++)
332  {
333  oa.objects[i].contour_points[j].x = contour[j].getX();
334  oa.objects[i].contour_points[j].y = contour[j].getY();
335  }
336 
337  //std::cout << objects[i].toString() << std::endl;
338  }
339 
341  rosPublish(object_pub_, oa); // object_pub_->publish(oa); // object_pub_.publish(oa);
342 }
343 
345 {
346  devices::LDMRS* ldmrs;
347  ldmrs = dynamic_cast<devices::LDMRS*>(manager_->getFirstDeviceByType(Sourcetype_LDMRS));
348  if (ldmrs == NULL)
349  {
350  ROS_WARN_STREAM("isUpsideDown: no connection to LDMRS!");
351  return true;
352  }
353 
354  UINT32 code;
355  ldmrs->getParameter(devices::ParaUpsideDownMode, &code);
356  return (code != 0);
357 }
358 
360 {
361  devices::LDMRS* ldmrs;
362  ldmrs = dynamic_cast<devices::LDMRS*>(manager_->getFirstDeviceByType(Sourcetype_LDMRS));
363  if (ldmrs == NULL)
364  {
365  ROS_WARN_STREAM("printFlexResError: no connection to LDMRS!");
366  return;
367  }
368 
369  UINT32 code;
370  ldmrs->getParameter(devices::ParaDetailedError, &code);
371  std::string msg = flexres_err_to_string(code);
372  ROS_ERROR_STREAM("FlexRes detailed error: " << msg);
373 }
374 
375 #if defined USE_DYNAMIC_RECONFIGURE && __ROS_VERSION == 1
376 void SickLDMRS::update_config_cb(sick_scan_xd::SickLDMRSDriverConfig &new_config, uint32_t level)
377 {
379  cfg.frame_id = new_config.frame_id;
380  cfg.start_angle = new_config.start_angle;
381  cfg.end_angle = new_config.end_angle;
382  cfg.scan_frequency = new_config.scan_frequency;
383  cfg.sync_angle_offset = new_config.sync_angle_offset;
384  cfg.angular_resolution_type = new_config.angular_resolution_type;
385  cfg.layer_range_reduction = new_config.layer_range_reduction;
386  cfg.ignore_near_range = new_config.ignore_near_range;
387  cfg.sensitivity_control = new_config.sensitivity_control;
388  cfg.flexres_start_angle1 = new_config.flexres_start_angle1;
389  cfg.flexres_start_angle2 = new_config.flexres_start_angle2;
390  cfg.flexres_start_angle3 = new_config.flexres_start_angle3;
391  cfg.flexres_start_angle4 = new_config.flexres_start_angle4;
392  cfg.flexres_start_angle5 = new_config.flexres_start_angle5;
393  cfg.flexres_start_angle6 = new_config.flexres_start_angle6;
394  cfg.flexres_start_angle7 = new_config.flexres_start_angle7;
395  cfg.flexres_start_angle8 = new_config.flexres_start_angle8;
396  cfg.flexres_resolution1 = new_config.flexres_resolution1;
397  cfg.flexres_resolution2 = new_config.flexres_resolution2;
398  cfg.flexres_resolution3 = new_config.flexres_resolution3;
399  cfg.flexres_resolution4 = new_config.flexres_resolution4;
400  cfg.flexres_resolution5 = new_config.flexres_resolution5;
401  cfg.flexres_resolution6 = new_config.flexres_resolution6;
402  cfg.flexres_resolution7 = new_config.flexres_resolution7;
403  cfg.flexres_resolution8 = new_config.flexres_resolution8;
404  cfg.contour_point_density = new_config.contour_point_density;
405  cfg.min_object_age = new_config.min_object_age;
406  cfg.max_prediction_age = new_config.max_prediction_age;
407  update_config(cfg, level);
408 }
409 #endif
410 
411 #if defined USE_DYNAMIC_RECONFIGURE && __ROS_VERSION == 2
412 rcl_interfaces::msg::SetParametersResult SickLDMRS::update_config_cb(const std::vector<rclcpp::Parameter> &parameters)
413 {
414  rcl_interfaces::msg::SetParametersResult result;
415  result.successful = true;
416  result.reason = "success";
417  if(!parameters.empty())
418  {
419  SickLDMRSDriverConfig new_config = config_;
420  for (const auto &parameter : parameters)
421  {
422  ROS_INFO_STREAM("SickLDMRS::update_config_cb(): parameter " << parameter.get_name() << " (type " << rclcpp::to_string(parameter.get_type()) << ") changed to " << parameter.as_string());
423  bool ok = false;
424  if(parameter.get_type() == rclcpp::ParameterType::PARAMETER_BOOL)
425  ok = new_config.set_parameter(parameter.get_name(), parameter.as_bool());
426  if(parameter.get_type() == rclcpp::ParameterType::PARAMETER_INTEGER)
427  ok = new_config.set_parameter(parameter.get_name(), parameter.as_int());
428  if(parameter.get_type() == rclcpp::ParameterType::PARAMETER_DOUBLE)
429  ok = new_config.set_parameter(parameter.get_name(), parameter.as_double());
430  if(parameter.get_type() == rclcpp::ParameterType::PARAMETER_STRING)
431  ok = new_config.set_parameter(parameter.get_name(), parameter.as_string());
432  if(!ok)
433  {
434  result.successful = false;
435  result.reason = "parameter not supported";
436  }
437  }
438  update_config(new_config);
439  }
440  return result;
441 }
442 #endif
443 
444 void SickLDMRS::update_config(SickLDMRSDriverConfig &new_config, uint32_t level)
445 {
446  validate_config(new_config);
447  config_ = new_config;
448 
449  if (!initialized_)
450  return;
451 
452  ROS_INFO_STREAM("Updating config...");
453 
454  devices::LDMRS* ldmrs;
455  ldmrs = dynamic_cast<devices::LDMRS*>(manager_->getFirstDeviceByType(Sourcetype_LDMRS));
456  if (ldmrs == NULL)
457  {
458  ROS_WARN_STREAM("update_config: no connection to LDMRS!");
459  return;
460  }
461 
462  // TODO: if (new_config.start_angle < config_.end_angle): first update end angle,
463  // then start angle to ensure that always start_angle > end_angle; see comments
464  // in LuxBase::cmd_setScanAngles().
465  if (!ldmrs->setScanAngles(new_config.start_angle, new_config.end_angle))
466  ROS_WARN_STREAM("Sending param not successful: ");
467 
468  switch (config_.scan_frequency)
469  {
470  case sick_ldmrs_driver::SickLDMRSDriverConfig::scan_freq_enum::ScanFreq1250: // SickLDMRSDriver_ScanFreq1250:
471  expected_frequency_ = 12.5;
472  break;
473  case sick_ldmrs_driver::SickLDMRSDriverConfig::scan_freq_enum::ScanFreq2500: // SickLDMRSDriver_ScanFreq2500:
474  expected_frequency_ = 25.0;
475  break;
476  case sick_ldmrs_driver::SickLDMRSDriverConfig::scan_freq_enum::ScanFreq5000: // SickLDMRSDriver_ScanFreq5000:
477  expected_frequency_ = 50.0;
478  break;
479  default:
480  ROS_ERROR_STREAM("Unknown scan frequency: " << config_.scan_frequency);
481  break;
482  }
483 
484  if (!ldmrs->setScanFrequency(expected_frequency_))
485  ROS_WARN_STREAM("Sending param not successful: ScanFrequency");
486  if (!ldmrs->setSyncAngleOffset(config_.sync_angle_offset))
487  ROS_WARN_STREAM("Sending param not successful: SyncAngleOffset");
488  if (!ldmrs->setParameter(devices::ParaContourPointDensity, config_.contour_point_density))
489  ROS_WARN_STREAM("Sending param not successful: ContourPointDensity");
490  if (!ldmrs->setParameter(devices::ParaMinimumObjectAge, config_.min_object_age))
491  ROS_WARN_STREAM("Sending param not successful: MinimumObjectAge");
492  if (!ldmrs->setParameter(devices::ParaMaximumPredictionAge, config_.max_prediction_age))
493  ROS_WARN_STREAM("Sending param not successful: MaximumPredictionAge");
494  if (!ldmrs->setParameter(devices::ParaRangeReduction, config_.layer_range_reduction))
495  ROS_WARN_STREAM("Sending param not successful: RangeReduction");
496  if (!ldmrs->setParameter(devices::ParaIgnoreNearRange, config_.ignore_near_range ? 1 : 0))
497  ROS_WARN_STREAM("Sending param not successful: IgnoreNearRange");
498  if (!ldmrs->setParameter(devices::ParaSensitivityControl, config_.sensitivity_control ? 1 : 0))
499  ROS_WARN_STREAM("Sending param not successful: SensitivityControl");
500 
501  if (config_.angular_resolution_type == sick_ldmrs_driver::SickLDMRSDriverConfig::angular_res_enum::FlexRes) // SickLDMRSDriver_FlexRes)
502  {
503  std::vector<std::pair<int, int> > res_map, res_map_filtered;
504  res_map.push_back(std::pair<int, int>(round(config_.flexres_start_angle1 * rad2deg * 32.0), config_.flexres_resolution1));
505  res_map.push_back(std::pair<int, int>(round(config_.flexres_start_angle2 * rad2deg * 32.0), config_.flexres_resolution2));
506  res_map.push_back(std::pair<int, int>(round(config_.flexres_start_angle3 * rad2deg * 32.0), config_.flexres_resolution3));
507  res_map.push_back(std::pair<int, int>(round(config_.flexres_start_angle4 * rad2deg * 32.0), config_.flexres_resolution4));
508  res_map.push_back(std::pair<int, int>(round(config_.flexres_start_angle5 * rad2deg * 32.0), config_.flexres_resolution5));
509  res_map.push_back(std::pair<int, int>(round(config_.flexres_start_angle6 * rad2deg * 32.0), config_.flexres_resolution6));
510  res_map.push_back(std::pair<int, int>(round(config_.flexres_start_angle7 * rad2deg * 32.0), config_.flexres_resolution7));
511  res_map.push_back(std::pair<int, int>(round(config_.flexres_start_angle8 * rad2deg * 32.0), config_.flexres_resolution8));
512 
513  // --- skip zero-length sectors
514  for (int i = 0; i < res_map.size() - 1; ++i)
515  {
516  if (res_map[i].first > res_map[i + 1].first)
517  {
518  res_map_filtered.push_back(res_map[i]);
519  }
520  }
521  if (res_map[7].first > (-1918)) // -1918 = minimum start angle
522  {
523  res_map_filtered.push_back(res_map[7]);
524  }
525 
526  // --- ensure constraints are met
527  int shots_per_scan = 0;
528  double sum_res0125 = 0;
529  for (int i = 0; i < res_map_filtered.size() - 1; ++i)
530  {
531  // sector angle in degrees
532  double sector_angle = (res_map_filtered[i].first - res_map_filtered[i + 1].first) / 32.0;
533 
534  shots_per_scan += sector_angle * 32.0 / res_map_filtered[i].second;
535  if (res_map_filtered[i].second == sick_ldmrs_driver::SickLDMRSDriverConfig::resolution_enum::Res0125) // SickLDMRSDriver_Res0125)
536  {
537  sum_res0125 += sector_angle;
538  }
539  }
540 
541  if (shots_per_scan > 440)
542  {
543  ROS_WARN_STREAM("FlexRes: The number of shots per scan must be at most 440. Not updating FlexRes config!");
544  return;
545  }
546  if (sum_res0125 > 20.0)
547  {
548  ROS_WARN_STREAM("FlexRes: The sectors with a resolution of 0.125 deg must not sum up to more than 20 deg. Not updating FlexRes config!");
549  return;
550  }
551 
552  // --- switch to constant resolution
553  // when applying FlexRes params, the angular resolution type has to be set
554  // to something other than FlexRes
555  if (!ldmrs->setParameter(devices::ParaAngularResolutionType, sick_ldmrs_driver::SickLDMRSDriverConfig::angular_res_enum::ConstantRes)) // SickLDMRSDriver_ConstantRes))
556  ROS_WARN_STREAM("Sending param not successful: AngularResolutionType");
557 
558  // sleep 10 seconds so that new config is applied by the scanner
559  usleep(10e6);
560 
561  // --- send FlexRes params to scanner
562  if (!ldmrs->setParameter(devices::ParaNumSectors, res_map_filtered.size()))
564 
565  for (int i = 0; i < res_map_filtered.size(); ++i)
566  {
567  // set sector start angle
568  if (!ldmrs->setParameter((devices::MrsParameterId)(0x4001 + i), res_map_filtered[i].first))
570 
571  // set sector resolution
572  if (!ldmrs->setParameter((devices::MrsParameterId)(0x4009 + i), res_map_filtered[i].second))
574  }
575  }
576 
577  // set angular resolution type *after* FlexRes config!
578  if (!ldmrs->setParameter(devices::ParaAngularResolutionType, config_.angular_resolution_type))
579  ROS_WARN_STREAM("Sending param not successful: AngularResolutionType");
580 
581  ROS_INFO_STREAM("... done updating config.");
582 }
583 
584 std::string SickLDMRS::flexres_err_to_string(const UINT32 code) const
585 {
586  switch (code)
587  {
588  case devices::ErrFlexResNumShotsInvalid:
589  return "The number of shots per scan is higher than 440.";
590  case devices::ErrFlexResSizeOneEighthSectorInvalid:
591  return "The sectors with a resolution of 0.125 deg sum up to more than 20 deg.";
592  case devices::ErrFlexResFreqInvalid:
593  return "The scan frequency is not 12.5Hz.";
594  case devices::ErrFlexResSectorsOverlapping:
595  return "The start angles of the sectors decrease not strictly monotone.";
596  case devices::ErrFlexResScannerNotIdle:
597  return "Could not set FlexRes parameter because the sensor is in flex res mode and not idle.";
598  case devices::ErrFlexResResolutionInvalid:
599  return "The resolution of one sector is not 4, 8, 16 or 32 (0.125 deg, 0.25 deg, 0.5 deg, 1 deg).";
600  case devices::ErrFlexResNumSectorsInvalid:
601  return "The number of sectors is larger than 8.";
602  default:
603  std::ostringstream ss;
604  ss << "UNKNOWN ERROR CODE (" << code << ")";
605  return ss.str();
606  }
607 }
608 
609 } // namespace sick_ldmrs_driver
610 
611 // Convert lmdrs scan to PointCloud2
612 void ldmrsScanToPointCloud2(const datatypes::Scan* scan, sick_scan_xd::SickCloudTransform& add_transform_xyz_rpy, sick_scan_xd::SickRangeFilter& range_filter, bool isRearMirrorSide, const std::string& frame_id, ros_sensor_msgs::PointCloud2& msg, ros_sensor_msgs::PointCloud2& msg_polar)
613 {
614  typedef struct SICK_LDMRS_Point
615  {
616  float x;
617  float y;
618  float z;
619  float intensity;
620  uint16_t echowidth; // Pulse width of this ech pulse, in cm
621  uint8_t layer; // Scan layer of this point (0..7); 0 is lowermost layer
622  uint8_t echo; // Echo number of this point (0..2); 0 is first echo
623  uint8_t flags; // Scan point flags; one of enum Flags
624  uint8_t alignment[11];
625  } SICK_LDMRS_Point;
626 
627  msg.header.frame_id = frame_id;
628  msg.header.stamp = rosTimeNow(); // Note: not using time stamp from scanner here, because it is delayed by up to 1.5 seconds
629 
630  msg.height = 1;
631  msg.width = scan->size();
632  msg.is_bigendian = false;
633  msg.is_dense = true;
634  msg.point_step = sizeof(SICK_LDMRS_Point);
635  msg.row_step = msg.point_step * msg.width;
636 
637  msg.fields.resize(7); // 7 channels: x, y, z, echowidth, layer, echo, flags
638  msg.fields[0].name = "x";
639  msg.fields[0].offset = 0;
640  msg.fields[0].count = 1;
641  msg.fields[0].datatype = ros_sensor_msgs::PointField::FLOAT32;
642  msg.fields[1].name = "y";
643  msg.fields[1].offset = msg.fields[0].offset + sizeof(float);
644  msg.fields[1].count = 1;
645  msg.fields[1].datatype = ros_sensor_msgs::PointField::FLOAT32;
646  msg.fields[2].name = "z";
647  msg.fields[2].offset = msg.fields[1].offset + sizeof(float);
648  msg.fields[2].count = 1;
649  msg.fields[2].datatype = ros_sensor_msgs::PointField::FLOAT32;
650  msg.fields[3].name = "echowidth";
651  msg.fields[3].offset = msg.fields[2].offset + 2 * sizeof(float);
652  msg.fields[3].count = 1;
653  msg.fields[3].datatype = ros_sensor_msgs::PointField::UINT16;
654  msg.fields[4].name = "layer";
655  msg.fields[4].offset = msg.fields[3].offset + sizeof(uint16_t);
656  msg.fields[4].count = 1;
657  msg.fields[4].datatype = ros_sensor_msgs::PointField::UINT8;
658  msg.fields[5].name = "echo";
659  msg.fields[5].offset = msg.fields[4].offset + sizeof(uint8_t);
660  msg.fields[5].count = 1;
661  msg.fields[5].datatype = ros_sensor_msgs::PointField::UINT8;
662  msg.fields[6].name = "echo";
663  msg.fields[6].offset = msg.fields[5].offset + sizeof(uint8_t);
664  msg.fields[6].count = 1;
665  msg.fields[6].datatype = ros_sensor_msgs::PointField::UINT8;
666 
667  msg_polar = msg;
668  msg_polar.fields[0].name = "range";
669  msg_polar.fields[1].name = "azimuth";
670  msg_polar.fields[2].name = "elevation";
671 
672  msg.data.resize(msg.row_step * msg.height);
673  std::fill(msg.data.begin(), msg.data.end(), 0);
674  SICK_LDMRS_Point* data_p = (SICK_LDMRS_Point*)(&msg.data[0]);
675 
676  msg_polar.data.resize(msg_polar.row_step * msg_polar.height);
677  std::fill(msg_polar.data.begin(), msg_polar.data.end(), 0);
678  SICK_LDMRS_Point* polar_data_p = (SICK_LDMRS_Point*)(&msg_polar.data[0]);
679 
680  size_t rangeNumPointcloud = 0;
681  for (size_t i = 0; i < scan->size(); i++)
682  {
683  const ScanPoint& p = (*scan)[i];
684  float range = p.getDist();
685  bool range_modified = false;
686  if (range_filter.apply(range, range_modified)) // otherwise point dropped by range filter
687  {
688  float azi = p.getHAngle(), ele = -p.getVAngle();
689  if (range_modified) // range modified, transform polar to cartesian
690  {
691  data_p->x = range * cos(ele) * cos(azi);
692  data_p->y = range * cos(ele) * sin(azi);
693  data_p->z = range * sin(ele);
694  }
695  else
696  {
697  data_p->x = p.getX();
698  data_p->y = p.getY();
699  data_p->z = p.getZ();
700  }
701  add_transform_xyz_rpy.applyTransform(data_p->x, data_p->y, data_p->z);
702  data_p->echowidth = p.getEchoWidth();
703  data_p->layer = p.getLayer() + (isRearMirrorSide ? 4 : 0);
704  data_p->echo = p.getEchoNum();
705  data_p->flags = p.getFlags();
706  *polar_data_p = *data_p;
707  polar_data_p->x = range;
708  polar_data_p->y = azi;
709  polar_data_p->z = ele;
710  rangeNumPointcloud++;
711  data_p++;
712  polar_data_p++;
713  }
714  }
715  if (rangeNumPointcloud < scan->size())
716  {
717  // Points have been dropped, resize point cloud to number of points after applying the range filter
718  range_filter.resizePointCloud(rangeNumPointcloud, msg);
719  range_filter.resizePointCloud(rangeNumPointcloud, msg_polar);
720  }
721 
722 }
UINT16
uint16_t UINT16
Definition: BasicDatatypes.hpp:73
UINT8
uint8_t UINT8
Definition: BasicDatatypes.hpp:75
sick_ldmrs_driver::SickLDMRS::produce_diagnostics
void produce_diagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
Definition: sick_ldmrs_driver.cpp:131
sick_ldmrs_driver::SickLDMRSDriverConfig::scan_frequency
int scan_frequency
Definition: sick_ldmrs_config.hpp:158
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_start_angle8
double flexres_start_angle8
Definition: sick_ldmrs_config.hpp:173
Msg
sick_ldmrs_driver::SickLDMRS::m_add_transform_xyz_rpy
sick_scan_xd::SickCloudTransform m_add_transform_xyz_rpy
Definition: sick_ldmrs_driver.hpp:149
sick_ldmrs_driver::SickLDMRS::printFlexResError
void printFlexResError()
Definition: sick_ldmrs_driver.cpp:359
msg
msg
NULL
#define NULL
sick_ldmrs_driver::SickLDMRS::diagnosticPub_
DiagnosedPublishAdapter< rosPublisher< ros_sensor_msgs::PointCloud2 > > * diagnosticPub_
Definition: sick_ldmrs_driver.hpp:135
sick_ldmrs_driver::SickLDMRSDriverConfig::frame_id
std::string frame_id
Definition: sick_ldmrs_config.hpp:154
sick_ldmrs_driver::SickLDMRS::diagnostics_
std::shared_ptr< diagnostic_updater::Updater > diagnostics_
Definition: sick_ldmrs_driver.hpp:119
diagnostic_updater::TimeStampStatusParam
A structure that holds the constructor parameters for the TimeStampStatus class.
Definition: eloquent/include/diagnostic_updater/update_functions.hpp:218
sick_scan_xd::notifyLdmrsObjectArrayListener
void notifyLdmrsObjectArrayListener(rosNodePtr handle, const sick_scan_msg::SickLdmrsObjectArray *msg)
Definition: sick_generic_callback.cpp:174
Datatype_Scan
@ Datatype_Scan
Definition: BasicDatatypes.hpp:105
sick_ldmrs_driver::DiagnosedPublishAdapter::publish
void publish(const std::shared_ptr< MessageType > &message)
Definition: sick_ldmrs_driver.hpp:87
diagnostic_updater::DiagnosticStatusWrapper::add
void add(const std::string &key, const bool &b)
pointcloud_utils.h
Time::toLongString
std::string toLongString() const
Definition: Time.cpp:74
sick_ldmrs_driver::SickLDMRS::SickLDMRS
SickLDMRS(rosNodePtr nh, Manager *manager, std::shared_ptr< diagnostic_updater::Updater > diagnostics)
Definition: sick_ldmrs_driver.cpp:63
Datatype_EvalCaseResults
@ Datatype_EvalCaseResults
Definition: BasicDatatypes.hpp:110
sick_scan_xd::SickCloudTransform
Definition: sick_cloud_transform.h:85
Time::toString
std::string toString() const
Definition: Time.cpp:63
sick_ldmrs_driver::SickLDMRSDriverConfig::ignore_near_range
bool ignore_near_range
Definition: sick_ldmrs_config.hpp:162
rad2deg
#define rad2deg(x)
Definition: sick_scan_common.cpp:98
sick_ldmrs_driver::SickLDMRS::init
void init()
Definition: sick_ldmrs_driver.cpp:111
sick_ldmrs_driver::SickLDMRS::validate_flexres_resolution
void validate_flexres_resolution(int &res)
Definition: sick_ldmrs_driver.cpp:253
diagnostic_msgs_DiagnosticStatus_WARN
#define diagnostic_msgs_DiagnosticStatus_WARN
Definition: sick_ros_wrapper.h:125
tf2::Quaternion::setRPY
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
sick_ldmrs_driver::SickLDMRSDriverConfig::sensitivity_control
bool sensitivity_control
Definition: sick_ldmrs_config.hpp:163
sensor_msgs::PointCloud2
::sensor_msgs::PointCloud2_< std::allocator< void > > PointCloud2
Definition: PointCloud2.h:90
sick_ldmrs_driver::SickLDMRSDriverConfig::contour_point_density
int contour_point_density
Definition: sick_ldmrs_config.hpp:183
sick_scan_xd::notifyPolarPointcloudListener
void notifyPolarPointcloudListener(rosNodePtr handle, const sick_scan_xd::PointCloud2withEcho *msg)
Definition: sick_generic_callback.cpp:94
sick_ldmrs_driver::SickLDMRSDriverConfig::max_prediction_age
int max_prediction_age
Definition: sick_ldmrs_config.hpp:185
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_start_angle5
double flexres_start_angle5
Definition: sick_ldmrs_config.hpp:170
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_resolution4
int flexres_resolution4
Definition: sick_ldmrs_config.hpp:177
sick_scan_xd::PointCloud2withEcho
Definition: sick_generic_callback.h:76
sick_ldmrs_driver::SickLDMRS::m_range_filter
sick_scan_xd::SickRangeFilter m_range_filter
Definition: sick_ldmrs_driver.hpp:150
sick_generic_callback.h
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_resolution1
int flexres_resolution1
Definition: sick_ldmrs_config.hpp:174
sick_ldmrs_driver::SickLDMRS::pubObjects
void pubObjects(datatypes::ObjectList &objects)
Definition: sick_ldmrs_driver.cpp:283
toString
std::string toString(INT32 value)
Definition: toolbox.cpp:279
data
data
sick_ldmrs_driver::SickLDMRS::manager_
Manager * manager_
Definition: sick_ldmrs_driver.hpp:143
diagnostic_msgs_DiagnosticStatus_OK
#define diagnostic_msgs_DiagnosticStatus_OK
Definition: sick_ros_wrapper.h:124
f
f
sick_ldmrs_driver::SickLDMRS::update_config
void update_config(SickLDMRSDriverConfig &new_config, uint32_t level=0)
Definition: sick_ldmrs_driver.cpp:444
sick_scan_xd::SickLdmrsObjectArray
::sick_scan_xd::SickLdmrsObjectArray_< std::allocator< void > > SickLdmrsObjectArray
Definition: SickLdmrsObjectArray.h:56
diagnostic_updater::DiagnosticStatusWrapper::summary
void summary(const diagnostic_msgs::DiagnosticStatus &src)
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
Definition: sick_scan_logging.h:123
usleep
void usleep(__int64 usec)
Definition: usleep.c:3
ROS_INFO_STREAM
#define ROS_INFO_STREAM(...)
Definition: sick_scan_ros2_example.cpp:71
sick_ldmrs_driver::DiagnosedPublishAdapter
Definition: sick_ldmrs_driver.hpp:76
sick_ldmrs_driver::SickLDMRSDriverConfig::start_angle
double start_angle
Definition: sick_ldmrs_config.hpp:156
sick_ldmrs_driver::SickLDMRS::setData
void setData(BasicData &data)
Definition: sick_ldmrs_driver.cpp:149
Datatype_EvalCases
@ Datatype_EvalCases
Definition: BasicDatatypes.hpp:112
sick_ldmrs_driver::SickLDMRS::object_pub_
rosPublisher< sick_scan_msg::SickLdmrsObjectArray > object_pub_
Definition: sick_ldmrs_driver.hpp:133
range_max
float range_max
Definition: sick_scan_test.cpp:529
sick_ldmrs_driver.hpp
rosPublish
void rosPublish(rosPublisher< T > &publisher, const T &msg)
Definition: sick_ros_wrapper.h:203
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_start_angle7
double flexres_start_angle7
Definition: sick_ldmrs_config.hpp:172
sick_ldmrs_driver::SickLDMRSDriverConfig::end_angle
double end_angle
Definition: sick_ldmrs_config.hpp:157
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_resolution8
int flexres_resolution8
Definition: sick_ldmrs_config.hpp:181
ROS_DEBUG_STREAM
#define ROS_DEBUG_STREAM(args)
Definition: sick_scan_logging.h:113
ros::NodeHandle
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_start_angle1
double flexres_start_angle1
Definition: sick_ldmrs_config.hpp:166
dynamic_reconfigure::Server::CallbackType
std::function< void(ConfigType &, uint32_t level)> CallbackType
Definition: server.h:84
rosGetParam
bool rosGetParam(rosNodePtr nh, const std::string &param_name, T &param_value)
Definition: sick_ros_wrapper.h:167
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_resolution7
int flexres_resolution7
Definition: sick_ldmrs_config.hpp:180
sick_ldmrs_driver::SickLDMRSDriverConfig::sync_angle_offset
double sync_angle_offset
Definition: sick_ldmrs_config.hpp:159
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_start_angle4
double flexres_start_angle4
Definition: sick_ldmrs_config.hpp:169
Datatype_Fields
@ Datatype_Fields
Definition: BasicDatatypes.hpp:115
rosTimeNow
rosTime rosTimeNow(void)
Definition: sick_ros_wrapper.h:173
Datatype_Objects
@ Datatype_Objects
Definition: BasicDatatypes.hpp:106
range_min
float range_min
Definition: sick_scan_test.cpp:528
ldmrsScanToPointCloud2
void ldmrsScanToPointCloud2(const datatypes::Scan *scan, sick_scan_xd::SickCloudTransform &add_transform_xyz_rpy, sick_scan_xd::SickRangeFilter &range_filter, bool isRearMirrorSide, const std::string &frame_id, ros_sensor_msgs::PointCloud2 &msg, ros_sensor_msgs::PointCloud2 &msg_polar)
Definition: sick_ldmrs_driver.cpp:612
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_resolution3
int flexres_resolution3
Definition: sick_ldmrs_config.hpp:176
sick_ldmrs_driver
Definition: sick_ldmrs_driver.cpp:60
sick_ldmrs_driver::SickLDMRS::expected_frequency_
double expected_frequency_
Definition: sick_ldmrs_driver.hpp:146
sick_ldmrs_driver::SickLDMRS::validate_config
void validate_config(SickLDMRSDriverConfig &conf)
Definition: sick_ldmrs_driver.cpp:215
sick_scan_xd::SickRangeFilter::apply
bool apply(float &range, bool &range_modified) const
Definition: sick_range_filter.h:107
Time
Definition: Time.hpp:51
sick_scan_xd::SickRangeFilter::resizePointCloud
void resizePointCloud(size_t rangeNum, ros_sensor_msgs::PointCloud2 &cloud)
Definition: sick_range_filter.h:182
sick_ldmrs_driver::SickLDMRSDriverConfig::layer_range_reduction
int layer_range_reduction
Definition: sick_ldmrs_config.hpp:161
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_start_angle3
double flexres_start_angle3
Definition: sick_ldmrs_config.hpp:168
sick_ldmrs_driver::SickLDMRS::pub_
rosPublisher< ros_sensor_msgs::PointCloud2 > pub_
Definition: sick_ldmrs_driver.hpp:132
Datatype_MeasurementList
@ Datatype_MeasurementList
Definition: BasicDatatypes.hpp:95
sick_ldmrs_driver::SickLDMRSDriverConfig::angular_resolution_type
int angular_resolution_type
Definition: sick_ldmrs_config.hpp:160
tf2::Quaternion
The Quaternion implements quaternion to perform linear algebra rotations in combination with Matrix3x...
Definition: melodic/include/tf2/LinearMath/Quaternion.h:29
diagnostic_updater::DiagnosticStatusWrapper
Wrapper for the diagnostic_msgs::msg::DiagnosticStatus message that makes it easier to update.
Definition: eloquent/include/diagnostic_updater/diagnostic_status_wrapper.hpp:68
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_resolution2
int flexres_resolution2
Definition: sick_ldmrs_config.hpp:175
sick_ldmrs_driver::SickLDMRS::isUpsideDown
bool isUpsideDown()
Definition: sick_ldmrs_driver.cpp:344
sick_ldmrs_driver::SickLDMRS::initialized_
bool initialized_
Definition: sick_ldmrs_driver.hpp:148
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(...)
Definition: sick_scan_ros2_example.cpp:72
rosDuration
ros::Duration rosDuration
Definition: sick_ros_wrapper.h:171
sick_scan_xd::SickCloudTransform::applyTransform
void applyTransform(float_type &x, float_type &y, float_type &z)
Definition: sick_cloud_transform.h:100
UINT32
uint32_t UINT32
Definition: BasicDatatypes.hpp:72
sick_ldmrs_driver::SickLDMRSDriverConfig
Definition: sick_ldmrs_config.hpp:98
sick_ldmrs_driver::SickLDMRSDriverConfig::min_object_age
int min_object_age
Definition: sick_ldmrs_config.hpp:184
sick_scan_xd::notifyCartesianPointcloudListener
void notifyCartesianPointcloudListener(rosNodePtr handle, const sick_scan_xd::PointCloud2withEcho *msg)
Definition: sick_generic_callback.cpp:74
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_start_angle2
double flexres_start_angle2
Definition: sick_ldmrs_config.hpp:167
roswrap::ok
ROSCPP_DECL bool ok()
Check whether it's time to exit.
Definition: rossimu.cpp:273
sick_scan_xd::RangeFilterResultHandling
enum sick_scan_xd::RangeFilterResultHandlingEnum RangeFilterResultHandling
sick_ldmrs_driver::SickLDMRS::cloud_topic_val
std::string cloud_topic_val
Definition: sick_ldmrs_driver.hpp:131
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_resolution6
int flexres_resolution6
Definition: sick_ldmrs_config.hpp:179
sick_ldmrs_driver::SickLDMRS::config_
SickLDMRSDriverConfig config_
Definition: sick_ldmrs_driver.hpp:137
sick_ldmrs_driver::SickLDMRS::flexres_err_to_string
std::string flexres_err_to_string(const UINT32 code) const
Definition: sick_ldmrs_driver.cpp:584
Datatype_Msg
@ Datatype_Msg
Definition: BasicDatatypes.hpp:104
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_start_angle6
double flexres_start_angle6
Definition: sick_ldmrs_config.hpp:171
rosDeclareParam
void rosDeclareParam(rosNodePtr nh, const std::string &param_name, const T &param_value)
Definition: sick_ros_wrapper.h:166
sick_ldmrs_driver::SickLDMRS::validate_flexres_start_angle
void validate_flexres_start_angle(double &angle1, double &angle2)
Definition: sick_ldmrs_driver.cpp:274
sick_ldmrs_driver::SickLDMRSDriverConfig::flexres_resolution5
int flexres_resolution5
Definition: sick_ldmrs_config.hpp:178
sick_ldmrs_driver::SickLDMRS::nh_
rosNodePtr nh_
Definition: sick_ldmrs_driver.hpp:130
Sourcetype_LDMRS
@ Sourcetype_LDMRS
Definition: BasicDatatypes.hpp:127
sick_ldmrs_driver::SickLDMRS::~SickLDMRS
virtual ~SickLDMRS()
Definition: sick_ldmrs_driver.cpp:106
sick_scan_xd::SickRangeFilter
Definition: sick_range_filter.h:85
diagnostic_updater::FrequencyStatusParam
A structure that holds the constructor parameters for the FrequencyStatus class.
Definition: eloquent/include/diagnostic_updater/update_functions.hpp:53


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