ros_scanner_node.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019-2020 Pilz GmbH & Co. KG
2 //
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU Lesser General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public License
14 // along with this program. If not, see <https://www.gnu.org/licenses/>.
15 
22 #include <psen_scan/scanner_data.h>
23 
24 namespace psen_scan
25 {
36  const std::string& topic,
37  const std::string& frame_id,
38  const uint16_t& skip,
39  const Degree& x_axis_rotation,
40  std::unique_ptr<vScanner> scanner)
41  : nh_(nh), frame_id_(frame_id), skip_(skip), scanner_(std::move(scanner)), x_axis_rotation_(x_axis_rotation)
42 {
43  if (!scanner_)
44  {
45  throw PSENScanFatalException("Nullpointer isn't a valid argument!");
46  }
48 }
49 
58 double degToRad(const Degree& deg)
59 {
60  return static_cast<double>(deg) * M_PI / 180.0;
61 }
62 
74 {
75  if (laserscan.resolution_ == PSENscanInternalAngle(0))
76  {
77  throw BuildROSMessageException("Resolution cannot be 0!");
78  }
79  if (laserscan.min_scan_angle_ >= laserscan.max_scan_angle_)
80  {
81  throw BuildROSMessageException("Attention: Start angle has to be smaller than end angle!");
82  }
83  uint16_t expected_size =
84  static_cast<int>(laserscan.max_scan_angle_ - laserscan.min_scan_angle_) / static_cast<int>(laserscan.resolution_);
85  if (expected_size != laserscan.measures_.size())
86  {
87  throw BuildROSMessageException("Calculated number of scans doesn't match actual number of scans!");
88  }
89 
90  sensor_msgs::LaserScan ros_message;
91  ros_message.header.stamp = ros::Time::now();
92  ros_message.header.frame_id = frame_id_;
93  ros_message.angle_min = degToRad(Degree(laserscan.min_scan_angle_) - x_axis_rotation_);
94  ros_message.angle_max = degToRad(Degree(laserscan.max_scan_angle_) - x_axis_rotation_);
95  ros_message.angle_increment = degToRad(Degree(laserscan.resolution_));
96  ros_message.time_increment = SCAN_TIME / NUMBER_OF_SAMPLES_FULL_SCAN_MASTER;
97  ros_message.scan_time = SCAN_TIME;
98  ros_message.range_min = 0;
99  ros_message.range_max = 10;
100  ros_message.ranges.insert(ros_message.ranges.end(),
101  laserscan.measures_.rbegin(),
102  laserscan.measures_.rend()); // reverse order
103  std::transform(ros_message.ranges.begin(), ros_message.ranges.end(), ros_message.ranges.begin(), [](float f) {
104  return f * 0.001;
105  });
106 
107  return ros_message;
108 }
114 {
115  uint16_t skip_counter = 0;
116 
117  scanner_->start();
118  while (ros::ok())
119  {
120  try
121  {
122  LaserScan complete_scan = scanner_->getCompleteScan();
123  if (skip_counter == skip_)
124  {
125  pub_.publish(buildRosMessage(complete_scan));
126  }
127  }
128  catch (const CoherentMonitoringFramesException& e)
129  {
130  ROS_WARN_STREAM("Could not build a coherent message: " << e.what() << " Skipping this message.");
131  }
132  catch (const ParseMonitoringFrameException& e)
133  {
134  ROS_FATAL_STREAM("Fatal error occured: " << e.what());
135  }
136  catch (const DiagnosticInformationException& e)
137  {
138  ROS_FATAL_STREAM("Fatal error occured: " << e.what());
139  // throw PSENScanFatalException("");
140  }
141  catch (const BuildROSMessageException& e)
142  {
143  ROS_WARN_STREAM("Could not build ROS message: " << e.what() << " Skipping this message.");
144  }
145 
146  if (++skip_counter > skip_)
147  {
148  skip_counter = 0;
149  }
150  }
151  scanner_->stop();
152 }
153 
154 } // namespace psen_scan
f
Class to model angles in degrees from user&#39;s perspective.
Class to hold the data for one laserscan without depencies to ROS.
Definition: laserscan.h:29
struct psen_scan::LaserScan LaserScan
Class to hold the data for one laserscan without depencies to ROS.
void publish(const boost::shared_ptr< M > &message) const
std::vector< uint16_t > measures_
Definition: laserscan.h:36
#define ROS_FATAL_STREAM(args)
PSENscanInternalAngle const min_scan_angle_
Definition: laserscan.h:38
ROSCPP_DECL bool ok()
double degToRad(const Degree &deg)
Convert angle in deg to rad.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
sensor_msgs::LaserScan buildRosMessage(const LaserScan &laserscan)
Creates a ROS message from an LaserScan, which contains one scanning round.
#define ROS_WARN_STREAM(args)
double const SCAN_TIME
Definition: scanner_data.h:57
PSENscanInternalAngle const max_scan_angle_
Definition: laserscan.h:39
PSENscanInternalAngle resolution_
Definition: laserscan.h:37
ROSScannerNode(ros::NodeHandle &nh, const std::string &topic, const std::string &frame_id, const uint16_t &skip, const Degree &x_axis_rotation, std::unique_ptr< vScanner > scanner)
Construct a new ROSScannerNode::ROSScannerNode object.
static Time now()
Class to model angles in PSENscan internal format (tenth of degrees)
void processingLoop()
endless loop for processing incoming UDP data from the laser scanner
uint16_t const NUMBER_OF_SAMPLES_FULL_SCAN_MASTER
Definition: scanner_data.h:56
std::unique_ptr< vScanner > scanner_


psen_scan
Author(s):
autogenerated on Mon Feb 28 2022 23:16:20