cob_scan_filter.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 //##################
19 //#### includes ####
20 
21 // standard includes
22 #include <vector>
23 #include <algorithm>
24 
25 // ROS includes
26 #include <ros/ros.h>
27 #include <XmlRpc.h>
28 
29 // ROS message includes
30 #include <sensor_msgs/LaserScan.h>
31 
32 
33 //####################
34 //#### node class ####
35 class NodeClass
36 {
37 public:
38  std::vector<std::vector<double> > scan_intervals;
39 
41  // topics to publish
44 
46  // loading config
47  scan_intervals = loadScanRanges();
48 
49  // implementation of topics to publish
50  topicPub_laser_scan = nh.advertise<sensor_msgs::LaserScan>("scan_out", 1);
51  topicSub_laser_scan_raw = nh.subscribe("scan_in", 1, &NodeClass::scanCallback, this);
52  }
53 
54  void scanCallback(const sensor_msgs::LaserScan::ConstPtr& msg) {
55  //if no filter intervals specified
56  if(scan_intervals.size()==0) {
57  topicPub_laser_scan.publish(*msg);
58  return;
59  }
60 
61 
62  // use hole received message, later only clear some ranges
63  sensor_msgs::LaserScan laser_scan = * msg;
64 
65 
66  int start_scan, stop_scan, num_scans;
67  num_scans = laser_scan.ranges.size();
68 
69  stop_scan = 0;
70  for ( unsigned int i=0; i<scan_intervals.size(); i++) {
71  std::vector<double> * it = & scan_intervals.at(i);
72 
73  if( it->at(1) <= laser_scan.angle_min ) {
74  ROS_WARN("Found an interval that lies below min scan range, skip!");
75  continue;
76  }
77  if( it->at(0) >= laser_scan.angle_max ) {
78  ROS_WARN("Found an interval that lies beyond max scan range, skip!");
79  continue;
80  }
81 
82  if( it->at(0) <= laser_scan.angle_min ) start_scan = 0;
83  else {
84  start_scan = (int)( (it->at(0) - laser_scan.angle_min) / laser_scan.angle_increment);
85  }
86 
87  for(int u = stop_scan; u<start_scan; u++) {
88  laser_scan.ranges.at(u) = 0.0; //laser_scan.range_min;
89  }
90 
91  if( it->at(1) >= laser_scan.angle_max ) stop_scan = num_scans-1;
92  else {
93  stop_scan = (int)( (it->at(1) - laser_scan.angle_min) / laser_scan.angle_increment);
94  }
95 
96  }
97 
98  for(unsigned int u = stop_scan; u<laser_scan.ranges.size(); u++) {
99  laser_scan.ranges.at(u) = 0.0; //laser_scan.range_min;
100  }
101 
102  // publish message
103  topicPub_laser_scan.publish(laser_scan);
104  }
105 
106  std::vector<std::vector<double> > loadScanRanges();
107 };
108 
109 //#######################
110 //#### main programm ####
111 int main(int argc, char** argv)
112 {
113  // initialize ROS, spezify name of node
114  ros::init(argc, argv, "scanner_filter");
115 
116  NodeClass nc;
117 
118  ros::spin();
119  return 0;
120 }
121 
122 bool compareIntervals(std::vector<double> a, std::vector<double> b) {
123  return a.at(0) < b.at(0);
124 }
125 
126 std::vector<std::vector<double> > NodeClass::loadScanRanges() {
127  std::string scan_intervals_param = "scan_intervals";
128  std::vector<std::vector<double> > vd_interval_set;
129  std::vector<double> vd_interval;
130 
131  //grab the range-list from the parameter server if possible
132  XmlRpc::XmlRpcValue intervals_list;
133  if(nh.hasParam(scan_intervals_param)){
134  nh.getParam(scan_intervals_param, intervals_list);
135  //make sure we have a list of lists
136  if(!(intervals_list.getType() == XmlRpc::XmlRpcValue::TypeArray)){
137  ROS_FATAL("The scan intervals must be specified as a list of lists [[x1, y1], [x2, y2], ..., [xn, yn]]");
138  throw std::runtime_error("The scan intervals must be specified as a list of lists [[x1, y1], [x2, y2], ..., [xn, yn]]");
139  }
140 
141  for(int i = 0; i < intervals_list.size(); ++i){
142  vd_interval.clear();
143 
144  //make sure we have a list of lists of size 2
145  XmlRpc::XmlRpcValue interval = intervals_list[i];
146  if(!(interval.getType() == XmlRpc::XmlRpcValue::TypeArray && interval.size() == 2)){
147  ROS_FATAL("The scan intervals must be specified as a list of lists [[x1, y1], [x2, y2], ..., [xn, yn]]");
148  throw std::runtime_error("The scan intervals must be specified as a list of lists [[x1, y1], [x2, y2], ..., [xn, yn]]");
149  }
150 
151  //make sure that the value we're looking at is either a double or an int
152  if(!(interval[0].getType() == XmlRpc::XmlRpcValue::TypeInt || interval[0].getType() == XmlRpc::XmlRpcValue::TypeDouble)){
153  ROS_FATAL("Values in the scan intervals specification must be numbers");
154  throw std::runtime_error("Values in the scan intervals specification must be numbers");
155  }
156  vd_interval.push_back( interval[0].getType() == XmlRpc::XmlRpcValue::TypeInt ? (int)(interval[0]) : (double)(interval[0]) );
157 
158  //make sure that the value we're looking at is either a double or an int
159  if(!(interval[1].getType() == XmlRpc::XmlRpcValue::TypeInt || interval[1].getType() == XmlRpc::XmlRpcValue::TypeDouble)){
160  ROS_FATAL("Values in the scan intervals specification must be numbers");
161  throw std::runtime_error("Values in the scan intervals specification must be numbers");
162  }
163  vd_interval.push_back( interval[1].getType() == XmlRpc::XmlRpcValue::TypeInt ? (int)(interval[1]) : (double)(interval[1]) );
164 
165  //basic checking validity
166  if(vd_interval.at(0)< -M_PI || vd_interval.at(1)< -M_PI) {
167  ROS_WARN("Found a scan interval < -PI, skip!");
168  continue;
169  //throw std::runtime_error("Found a scan interval < -PI!");
170  }
171  //basic checking validity
172  if(vd_interval.at(0)>M_PI || vd_interval.at(1)>M_PI) {
173  ROS_WARN("Found a scan interval > PI, skip!");
174  continue;
175  //throw std::runtime_error("Found a scan interval > PI!");
176  }
177 
178 
179  if(vd_interval.at(0) >= vd_interval.at(1)) {
180  ROS_WARN("Found a scan interval with i1 > i2, switched order!");
181  vd_interval[1] = vd_interval[0];
182  vd_interval[0] = ( interval[1].getType() == XmlRpc::XmlRpcValue::TypeInt ? (int)(interval[1]) : (double)(interval[1]) );
183  }
184 
185  vd_interval_set.push_back(vd_interval);
186  }
187  } else ROS_WARN("Scan filter has not found any scan interval parameters.");
188 
189  //now we want to sort the intervals and check for overlapping
190  sort(vd_interval_set.begin(), vd_interval_set.end(), compareIntervals);
191 
192  for(unsigned int i = 0; i<vd_interval_set.size(); i++) {
193  for(unsigned int u = i+1; u<vd_interval_set.size(); u++) {
194  if( vd_interval_set.at(i).at(1) > vd_interval_set.at(u).at(0)) {
195  ROS_FATAL("The scan intervals you specified are overlapping!");
196  throw std::runtime_error("The scan intervals you specified are overlapping!");
197  }
198  }
199  }
200 
201  /* DEBUG out:
202  for(unsigned int i = 0; i<vd_interval_set.size(); i++) {
203  std::cout << "Interval " << i << " is " << vd_interval_set.at(i).at(0) << " | " << vd_interval_set.at(i).at(1) << std::endl;
204  } */
205 
206  return vd_interval_set;
207 }
208 
ros::NodeHandle nh
#define ROS_FATAL(...)
ros::Publisher topicPub_laser_scan
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
int size() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
std::vector< std::vector< double > > scan_intervals
void scanCallback(const sensor_msgs::LaserScan::ConstPtr &msg)
Type const & getType() const
#define ROS_WARN(...)
ros::Subscriber topicSub_laser_scan_raw
std::vector< std::vector< double > > loadScanRanges()
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ROSCPP_DECL void spin()
int main(int argc, char **argv)
bool getParam(const std::string &key, std::string &s) const
bool hasParam(const std::string &key) const
bool compareIntervals(std::vector< double > a, std::vector< double > b)


cob_sick_s300
Author(s): Florian Weisshardt
autogenerated on Wed Apr 7 2021 02:11:50