speckle_filter.h
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Robot Operating System code by Eurotec B.V.
5  * Copyright (c) 2020, Eurotec B.V.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  *
21  * 3. Neither the name of the copyright holder nor the names of its
22  * contributors may be used to endorse or promote products derived
23  * from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
32  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  * speckle_filter.h
38  */
39 
40 #ifndef SPECKLE_FILTER_H
41 #define SPECKLE_FILTER_H
42 
43 #include <dynamic_reconfigure/server.h>
44 #include <filters/filter_base.hpp>
45 #include <laser_filters/SpeckleFilterConfig.h>
46 #include <sensor_msgs/LaserScan.h>
47 
48 namespace laser_filters
49 {
50 
52 {
53 public:
54  virtual ~WindowValidator() = default;
55  virtual bool checkWindowValid(const sensor_msgs::LaserScan& scan, size_t idx, size_t window, double max_range_difference) = 0;
56 };
57 
59 {
60  virtual bool checkWindowValid(const sensor_msgs::LaserScan& scan, size_t idx, size_t window, double max_range_difference)
61  {
62  const float& range = scan.ranges[idx];
63  if (range != range) {
64  return false;
65  }
66 
67  size_t i = idx + 1;
68  size_t i_max = std::min(idx + window, scan.ranges.size());
69  while (i < i_max) {
70  const float& neighbor_range = scan.ranges[i];
71  if (neighbor_range != neighbor_range || fabs(neighbor_range - range) > max_range_difference) {
72  return false;
73  }
74  ++i;
75  }
76 
77  return true;
78  }
79 };
80 
82 {
83  virtual bool checkWindowValid(const sensor_msgs::LaserScan& scan, size_t idx, size_t window, double max_distance)
84  {
85  int num_neighbors = 0;
86  const float& r1 = scan.ranges[idx];
87  float r2 = 0.;
88 
89  // Look around the current point until either the window is exceeded
90  // or the number of neighbors was found.
91  for (int y = -(int)window; y < (int)window + 1 && num_neighbors < (int)window; y++)
92  {
93  int j = idx + y;
94  r2 = scan.ranges[j];
95 
96  if (j < 0 || j >= static_cast<int>(scan.ranges.size()) || idx == j || std::isnan(r2))
97  { // Out of scan bounds or itself or infinity
98  continue;
99  }
100 
101  // Explanation:
102  //
103  // Distance between two points:
104  // d² = (x2 - x1)² + (y2 - y1)²
105  //
106  // Substitute x with r * cos(phi) and y with r * sin(phi):
107  // d² = (r2 * cos(phi2) - r1 * cos(phi1))² + (r2 * sin(phi2) - r1 * sin(phi1))²
108  //
109  // Apply binomial theorem:
110  // d² = ((r2² * cos(phi2)² + r1² * cos(phi1)² - 2 * r1 * r2 * cos(phi1) * cos(phi2)) +
111  // ((r2² * sin(phi2)² + r1² * sin(phi1)² - 2 * r1 * r2 * sin(phi1) * sin(phi2))
112  //
113  // Merge sums:
114  // d² = r2² * (cos(phi2)² + sin(phi2)²) + r1² * (cos(phi1)² + sin(phi1)² -
115  // 2 * r1 * r2 * (cos(phi1) * cos(phi2) + sin(phi1) * sin(phi2))
116  //
117  // Apply cos² + sin² = 1:
118  // d² = r2² + r1² - 2 * r1 * r2 * (cos(phi1) * cos(phi2) + sin(phi1) * sin(phi2))
119  //
120  // Note the following:
121  // cos(phi1) * cos(phi2) = 1/2 * (cos(phi1 - phi2) + cos(phi1 + phi2))
122  // sin(phi1) * sin(phi2) = 1/2 * (cos(phi1 - phi2) - cos(phi1 + phi2))
123  //
124  // cos(phi1) * cos(phi2) + sin(phi1) * sin(phi2) = cos(phi1 - phi2)
125  //
126  // Finally, phi1 - phi2 is our included_angle.
127 
128  const float d = sqrt(
129  pow(r1,2) + pow(r2,2) -
130  (2 * r1 * r2 * cosf(y * scan.angle_increment)));
131 
132 
133  if (d <= max_distance)
134  {
135  num_neighbors++;
136  }
137  }
138 
139  // consider the window to be the number of neighbors we need
140  if (num_neighbors < window)
141  {
142  return false;
143  }
144  else
145  {
146  return true;
147  }
148  }
149 };
150 
154 class LaserScanSpeckleFilter : public filters::FilterBase<sensor_msgs::LaserScan>
155 {
156 public:
159 
160  bool configure();
161  void configure(SpeckleFilterConfig& config) { reconfigureCB(config, 0); }
162 
163  bool update(const sensor_msgs::LaserScan& input_scan, sensor_msgs::LaserScan& output_scan);
164 
165 private:
166  std::shared_ptr<dynamic_reconfigure::Server<laser_filters::SpeckleFilterConfig>> dyn_server_;
167  void reconfigureCB(laser_filters::SpeckleFilterConfig& config, uint32_t level);
168  boost::recursive_mutex own_mutex_;
169 
170  SpeckleFilterConfig config_ = SpeckleFilterConfig::__getDefault__();
172 
173  // Work area. Vector re-used by update() to avoid repeated dynamic memory allocations
174  std::vector<bool> valid_ranges_work_;
175 };
176 }
177 #endif /* speckle_filter.h */
filters::FilterBase
laser_filters::LaserScanSpeckleFilter::config_
SpeckleFilterConfig config_
Definition: speckle_filter.h:170
laser_filters::WindowValidator::~WindowValidator
virtual ~WindowValidator()=default
laser_filters::WindowValidator::checkWindowValid
virtual bool checkWindowValid(const sensor_msgs::LaserScan &scan, size_t idx, size_t window, double max_range_difference)=0
laser_filters::LaserScanSpeckleFilter::~LaserScanSpeckleFilter
~LaserScanSpeckleFilter()
Definition: speckle_filter.cpp:50
laser_filters::LaserScanSpeckleFilter
This is a filter that removes speckle points in a laser scan based on consecutive ranges.
Definition: speckle_filter.h:154
laser_filters::RadiusOutlierWindowValidator
Definition: speckle_filter.h:81
laser_filters::LaserScanSpeckleFilter::LaserScanSpeckleFilter
LaserScanSpeckleFilter()
Definition: speckle_filter.cpp:45
filter_base.hpp
laser_filters::DistanceWindowValidator
Definition: speckle_filter.h:58
laser_filters::LaserScanSpeckleFilter::validator_
WindowValidator * validator_
Definition: speckle_filter.h:171
laser_filters::LaserScanSpeckleFilter::reconfigureCB
void reconfigureCB(laser_filters::SpeckleFilterConfig &config, uint32_t level)
Definition: speckle_filter.cpp:125
laser_filters::LaserScanSpeckleFilter::update
bool update(const sensor_msgs::LaserScan &input_scan, sensor_msgs::LaserScan &output_scan)
Definition: speckle_filter.cpp:74
d
d
laser_filters::LaserScanSpeckleFilter::dyn_server_
std::shared_ptr< dynamic_reconfigure::Server< laser_filters::SpeckleFilterConfig > > dyn_server_
Definition: speckle_filter.h:166
laser_filters::LaserScanSpeckleFilter::valid_ranges_work_
std::vector< bool > valid_ranges_work_
Definition: speckle_filter.h:174
laser_filters::WindowValidator
Definition: speckle_filter.h:51
laser_filters::RadiusOutlierWindowValidator::checkWindowValid
virtual bool checkWindowValid(const sensor_msgs::LaserScan &scan, size_t idx, size_t window, double max_distance)
Definition: speckle_filter.h:83
laser_filters::LaserScanSpeckleFilter::configure
bool configure()
Definition: speckle_filter.cpp:58
laser_filters::LaserScanSpeckleFilter::configure
void configure(SpeckleFilterConfig &config)
Definition: speckle_filter.h:161
laser_filters
LaserScanMaskFilter removes points on directions defined in a mask from a laser scan.
Definition: angular_bounds_filter.h:43
laser_filters::LaserScanSpeckleFilter::own_mutex_
boost::recursive_mutex own_mutex_
Definition: speckle_filter.h:168
laser_filters::DistanceWindowValidator::checkWindowValid
virtual bool checkWindowValid(const sensor_msgs::LaserScan &scan, size_t idx, size_t window, double max_range_difference)
Definition: speckle_filter.h:60


laser_filters
Author(s): Tully Foote
autogenerated on Mon Apr 3 2023 02:51:57