scan_shadows_filter.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 Radu Bogdan Rusu <rusu@cs.tum.edu>
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  *
27  * $Id: scan_shadows_filter.cpp,v 1.0 2008/12/04 12:00:00 rusu Exp $
28  *
29  */
30 
31 /*
32  \author Radu Bogdan Rusu <rusu@cs.tum.edu> Tully Foote <tfoote@willowgarage.com>
33 
34 
35 */
36 
37 #ifndef LASER_SCAN_SHADOWS_FILTER_H
38 #define LASER_SCAN_SHADOWS_FILTER_H
39 
40 #include <set>
41 
42 #include "filters/filter_base.h"
44 #include <sensor_msgs/LaserScan.h>
45 #include <angles/angles.h>
46 #include <laser_filters/ScanShadowsFilterConfig.h>
47 #include <dynamic_reconfigure/server.h>
48 #include <ros/ros.h>
49 
50 namespace laser_filters
51 {
55 class ScanShadowsFilter : public filters::FilterBase<sensor_msgs::LaserScan>
56 {
57 public:
58  double laser_max_range_; // Used in laser scan projection
59  double min_angle_, max_angle_; // Filter angle threshold
61  bool remove_shadow_start_point_; // Whether to also remove the start point of the shadow
62 
64 
65  std::shared_ptr<dynamic_reconfigure::Server<laser_filters::ScanShadowsFilterConfig>> dyn_server_;
66  boost::recursive_mutex own_mutex_;
67  ScanShadowsFilterConfig param_config;
68 
71  {
72  }
73 
75  bool configure()
76  {
77  ros::NodeHandle private_nh("~" + getName());
78  dyn_server_.reset(new dynamic_reconfigure::Server<laser_filters::ScanShadowsFilterConfig>(own_mutex_, private_nh));
79  dynamic_reconfigure::Server<laser_filters::ScanShadowsFilterConfig>::CallbackType f;
80  f = boost::bind(&laser_filters::ScanShadowsFilter::reconfigureCB, this, _1, _2);
81  dyn_server_->setCallback(f);
82 
83  if (!filters::FilterBase<sensor_msgs::LaserScan>::getParam(std::string("min_angle"), min_angle_))
84  {
85  ROS_ERROR("Error: ShadowsFilter was not given min_angle.\n");
86  return false;
87  }
88  if (!filters::FilterBase<sensor_msgs::LaserScan>::getParam(std::string("max_angle"), max_angle_))
89  {
90  ROS_ERROR("Error: ShadowsFilter was not given min_angle.\n");
91  return false;
92  }
93  if (!filters::FilterBase<sensor_msgs::LaserScan>::getParam(std::string("window"), window_))
94  {
95  ROS_ERROR("Error: ShadowsFilter was not given window.\n");
96  return false;
97  }
98  neighbors_ = 0; // default value
99  if (!filters::FilterBase<sensor_msgs::LaserScan>::getParam(std::string("neighbors"), neighbors_))
100  {
101  ROS_INFO("Error: ShadowsFilter was not given neighbors.\n");
102  }
103  remove_shadow_start_point_ = false; // default value
104  filters::FilterBase<sensor_msgs::LaserScan>::getParam(std::string("remove_shadow_start_point"), remove_shadow_start_point_);
105  ROS_INFO("Remove shadow start point: %s", remove_shadow_start_point_ ? "true" : "false");
106 
107  if (min_angle_ < 0)
108  {
109  ROS_ERROR("min_angle must be 0 <= min_angle. Forcing min_angle = 0.\n");
110  min_angle_ = 0.0;
111  }
112  if (90 < min_angle_)
113  {
114  ROS_ERROR("min_angle must be min_angle <= 90. Forcing min_angle = 90.\n");
115  min_angle_ = 90.0;
116  }
117  if (max_angle_ < 90)
118  {
119  ROS_ERROR("max_angle must be 90 <= max_angle. Forcing max_angle = 90.\n");
120  max_angle_ = 90.0;
121  }
122  if (180 < min_angle_)
123  {
124  ROS_ERROR("max_angle must be max_angle <= 180. Forcing max_angle = 180.\n");
125  max_angle_ = 180.0;
126  }
127 
128  shadow_detector_.configure(
129  angles::from_degrees(min_angle_),
130  angles::from_degrees(max_angle_));
131 
132  param_config.min_angle = min_angle_;
133  param_config.max_angle = max_angle_;
134  param_config.window = window_;
135  param_config.neighbors = neighbors_;
136  param_config.remove_shadow_start_point = remove_shadow_start_point_;
137  dyn_server_->updateConfig(param_config);
138 
139  return true;
140  }
141 
142  void reconfigureCB(ScanShadowsFilterConfig& config, uint32_t level)
143  {
144  min_angle_ = config.min_angle;
145  max_angle_ = config.max_angle;
146  shadow_detector_.configure(
147  angles::from_degrees(min_angle_),
148  angles::from_degrees(max_angle_));
149  neighbors_ = config.neighbors;
150  window_ = config.window;
151  remove_shadow_start_point_ = config.remove_shadow_start_point;
152  }
153 
156  {
157  }
158 
160 
167  bool update(const sensor_msgs::LaserScan& scan_in, sensor_msgs::LaserScan& scan_out)
168  {
169  boost::recursive_mutex::scoped_lock lock(own_mutex_);
170 
171  // copy across all data first
172  scan_out = scan_in;
173 
174  std::set<int> indices_to_delete;
175  // For each point in the current line scan
176  for (unsigned int i = 0; i < scan_in.ranges.size(); i++)
177  {
178  for (int y = -window_; y < window_ + 1; y++)
179  {
180  int j = i + y;
181  if (j < 0 || j >= (int)scan_in.ranges.size() || (int)i == j)
182  { // Out of scan bounds or itself
183  continue;
184  }
185 
186  if (shadow_detector_.isShadow(
187  scan_in.ranges[i], scan_in.ranges[j], y * scan_in.angle_increment))
188  {
189  for (int index = std::max<int>(i - neighbors_, 0); index <= std::min<int>(i + neighbors_, (int)scan_in.ranges.size() - 1); index++)
190  {
191  if (scan_in.ranges[i] < scan_in.ranges[index])
192  { // delete neighbor if they are farther away (note not self)
193  indices_to_delete.insert(index);
194  }
195  }
196  if (remove_shadow_start_point_)
197  {
198  indices_to_delete.insert(i);
199  }
200  }
201  }
202  }
203 
204  ROS_DEBUG("ScanShadowsFilter removing %d Points from scan with min angle: %.2f, max angle: %.2f, neighbors: %d, and window: %d",
205  (int)indices_to_delete.size(), min_angle_, max_angle_, neighbors_, window_);
206  for (std::set<int>::iterator it = indices_to_delete.begin(); it != indices_to_delete.end(); ++it)
207  {
208  scan_out.ranges[*it] = std::numeric_limits<float>::quiet_NaN(); // Failed test to set the ranges to invalid value
209  }
210  return true;
211  }
212 
214 };
215 }
216 
217 #endif // LASER_SCAN_SHADOWS_FILTER_H
void configure(const float min_angle, const float max_angle)
ScanShadowsFilterConfig param_config
void reconfigureCB(ScanShadowsFilterConfig &config, uint32_t level)
f
LaserScanMaskFilter removes points on directions defined in a mask from a laser scan.
static double from_degrees(double degrees)
#define ROS_INFO(...)
bool update(const sensor_msgs::LaserScan &scan_in, sensor_msgs::LaserScan &scan_out)
Filter shadow points based on 3 global parameters: min_angle, max_angle and window. {min,max}_angle specify the allowed angle interval (in degrees) between the created lines (see getAngleWithViewPoint). Window specifies how many consecutive measurements to take into account for one point.
bool getParam(const std::string &name, std::string &value) const
bool isShadow(const float r1, const float r2, const float included_angle)
std::shared_ptr< dynamic_reconfigure::Server< laser_filters::ScanShadowsFilterConfig > > dyn_server_
#define ROS_ERROR(...)
#define ROS_DEBUG(...)


laser_filters
Author(s): Tully Foote
autogenerated on Mon Feb 28 2022 22:39:24