Skip to content

Commit 7ee3c7e

Browse files
author
svn
committed
Moved outlier filter to separate files and removed parameter lookup in callback
1 parent eaf12d9 commit 7ee3c7e

File tree

5 files changed

+188
-5
lines changed

5 files changed

+188
-5
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ target_link_libraries(pointcloud_to_laserscan ${catkin_LIBRARIES})
2929
add_executable(pointcloud_to_laserscan_node src/pointcloud_to_laserscan_node.cpp)
3030
target_link_libraries(pointcloud_to_laserscan_node pointcloud_to_laserscan ${catkin_LIBRARIES})
3131

32-
add_library(ipa_pointcloud_to_laserscan src/ipa_pointcloud_to_laserscan_nodelet.cpp)
32+
add_library(ipa_pointcloud_to_laserscan src/ipa_pointcloud_to_laserscan_nodelet.cpp src/scan_outlier_removal_filter.cpp)
3333
target_link_libraries(ipa_pointcloud_to_laserscan ${catkin_LIBRARIES})
3434

35-
add_executable(ipa_pointcloud_to_laserscan_node src/ipa_pointcloud_to_laserscan_node.cpp)
35+
add_executable(ipa_pointcloud_to_laserscan_node src/ipa_pointcloud_to_laserscan_node.cpp src/scan_outlier_removal_filter.cpp)
3636
target_link_libraries(ipa_pointcloud_to_laserscan_node ipa_pointcloud_to_laserscan ${catkin_LIBRARIES})
3737

3838
install(TARGETS pointcloud_to_laserscan pointcloud_to_laserscan_node ipa_pointcloud_to_laserscan ipa_pointcloud_to_laserscan_node

include/pointcloud_to_laserscan/ipa_pointcloud_to_laserscan_nodelet.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "tf2_ros/message_filter.h"
5252
#include "message_filters/subscriber.h"
5353
#include "sensor_msgs/PointCloud2.h"
54+
#include <pointcloud_to_laserscan/scan_outlier_removal_filter.h>
5455

5556

5657
namespace pointcloud_to_laserscan
@@ -65,6 +66,7 @@ namespace pointcloud_to_laserscan
6566

6667
public:
6768
IpaPointCloudToLaserScanNodelet();
69+
void configure_filter();
6870

6971
private:
7072
virtual void onInit();
@@ -86,12 +88,14 @@ namespace pointcloud_to_laserscan
8688
message_filters::Subscriber<sensor_msgs::PointCloud2> sub_;
8789
boost::shared_ptr<MessageFilter> message_filter_;
8890

91+
scan_outlier_filter::ScanOutlierRemovalFilter outlier_filter_;
8992
// ROS Parameters
9093
unsigned int input_queue_size_;
9194
std::string target_frame_;
9295
double tolerance_;
9396
double min_height_, max_height_, angle_min_, angle_max_, angle_increment_, scan_time_, range_min_, range_max_;
9497
bool use_inf_;
98+
bool use_outlier_filter_;
9599
};
96100

97101
} // pointcloud_to_laserscan
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
2+
/*
3+
* Software License Agreement (BSD License)
4+
*
5+
* Copyright (c) 2010-2012, Fraunhofer IPA
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+
* * Redistributions of source code must retain the above copyright
13+
* notice, this list of conditions and the following disclaimer.
14+
* * Redistributions in binary form must reproduce the above
15+
* copyright notice, this list of conditions and the following
16+
* disclaimer in the documentation and/or other materials provided
17+
* with the distribution.
18+
* * Neither the name of Willow Garage, Inc. nor the names of its
19+
* contributors may be used to endorse or promote products derived
20+
* from this software without specific prior written permission.
21+
*
22+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33+
* POSSIBILITY OF SUCH DAMAGE.
34+
*
35+
*
36+
*/
37+
38+
/*
39+
* Author: Sofie Nilsson
40+
*/
41+
42+
#ifndef IPA_POINTCLOUD_TO_LASERSCAN_SCAN_OUTLIER_REMOVAL_FILTER
43+
#define IPA_POINTCLOUD_TO_LASERSCAN_SCAN_OUTLIER_REMOVAL_FILTER
44+
45+
#include <sensor_msgs/LaserScan.h>
46+
47+
namespace scan_outlier_filter
48+
{
49+
class ScanOutlierRemovalFilter
50+
{
51+
private:
52+
bool filter_configured_;
53+
double cluster_break_distance_;
54+
int max_noise_cluster_size_;
55+
double max_noise_cluster_distance_;
56+
57+
public:
58+
ScanOutlierRemovalFilter():
59+
filter_configured_(false),
60+
cluster_break_distance_(0.0),
61+
max_noise_cluster_size_(0),
62+
max_noise_cluster_distance_(0.0)
63+
{};
64+
void configure(double cluster_break_distance, int max_noise_cluster_size, double max_noise_cluster_distance);
65+
66+
void remove_outliers(sensor_msgs::LaserScan &scan);
67+
};
68+
}
69+
#endif //IPA_POINTCLOUD_TO_LASERSCAN_SCAN_OUTLIER_REMOVAL_FILTER

src/ipa_pointcloud_to_laserscan_nodelet.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
namespace pointcloud_to_laserscan
5353
{
54-
void scan_outlier_removal_filter(sensor_msgs::LaserScan &scan, double cluster_break_distance, int max_noise_cluster_size, double max_noise_cluster_distance);
54+
//void scan_outlier_removal_filter(sensor_msgs::LaserScan &scan, double cluster_break_distance, int max_noise_cluster_size, double max_noise_cluster_distance);
5555

5656
IpaPointCloudToLaserScanNodelet::IpaPointCloudToLaserScanNodelet() {}
5757

@@ -76,6 +76,8 @@ namespace pointcloud_to_laserscan
7676
private_nh_.param<int>("concurrency_level", concurrency_level, 1);
7777
private_nh_.param<bool>("use_inf", use_inf_, true);
7878

79+
configure_filter();
80+
7981
//Check if explicitly single threaded, otherwise, let nodelet manager dictate thread pool size
8082
if (concurrency_level == 1)
8183
{
@@ -115,6 +117,23 @@ namespace pointcloud_to_laserscan
115117
boost::bind(&IpaPointCloudToLaserScanNodelet::disconnectCb, this));
116118
}
117119

120+
void IpaPointCloudToLaserScanNodelet::configure_filter()
121+
{
122+
NODELET_DEBUG_STREAM("configuring filter");
123+
// Get filter related parameters
124+
125+
private_nh_.param<bool>("use_outlier_filter", use_outlier_filter_, false);
126+
127+
double max_noise_cluster_distance;
128+
double cluster_break_distance;
129+
int max_noise_cluster_size;
130+
private_nh_.param<double>("max_noise_cluster_distance", max_noise_cluster_distance, 2.0);
131+
private_nh_.param<double>("cluster_break_distance", cluster_break_distance, 0.3);
132+
private_nh_.param<int>("max_noise_cluster_size", max_noise_cluster_size, 5);
133+
134+
outlier_filter_.configure(cluster_break_distance, max_noise_cluster_size, max_noise_cluster_distance);
135+
}
136+
118137
void IpaPointCloudToLaserScanNodelet::connectCb()
119138
{
120139
boost::mutex::scoped_lock lock(connect_mutex_);
@@ -148,6 +167,7 @@ namespace pointcloud_to_laserscan
148167
NODELET_INFO_STREAM("PC with timestamp " << cloud_msg->header.stamp << " recevied at time " << start_time);
149168
// TODO move to config and add dynamic reconfiguring
150169
// Get filter related parameters
170+
/*
151171
bool use_outlier_filter;
152172
double max_noise_cluster_distance;
153173
double cluster_break_distance;
@@ -156,6 +176,7 @@ namespace pointcloud_to_laserscan
156176
private_nh_.param<double>("max_noise_cluster_distance", max_noise_cluster_distance, 2.0);
157177
private_nh_.param<double>("cluster_break_distance", cluster_break_distance, 0.3);
158178
private_nh_.param<int>("max_noise_cluster_size", max_noise_cluster_size, 5);
179+
*/
159180

160181
// convert const ptr to ptr to support downsampling
161182
sensor_msgs::PointCloud2Ptr cloud(boost::const_pointer_cast<sensor_msgs::PointCloud2>(cloud_msg));
@@ -310,9 +331,10 @@ namespace pointcloud_to_laserscan
310331

311332
}
312333

313-
if(use_outlier_filter)
334+
if(use_outlier_filter_)
314335
{
315-
scan_outlier_removal_filter(output, cluster_break_distance, max_noise_cluster_size, max_noise_cluster_distance);
336+
//scan_outlier_removal_filter(output, cluster_break_distance, max_noise_cluster_size, max_noise_cluster_distance);
337+
outlier_filter_.remove_outliers(output);
316338
}
317339

318340
ros::Time end_time = ros::Time::now();
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
2+
#include <pointcloud_to_laserscan/scan_outlier_removal_filter.h>
3+
4+
using namespace scan_outlier_filter;
5+
6+
void ScanOutlierRemovalFilter::configure(double cluster_break_distance, int max_noise_cluster_size, double max_noise_cluster_distance)
7+
{
8+
filter_configured_ = true;
9+
cluster_break_distance_ = cluster_break_distance;
10+
max_noise_cluster_size_ = max_noise_cluster_size;
11+
max_noise_cluster_distance_ = max_noise_cluster_distance;
12+
}
13+
14+
void ScanOutlierRemovalFilter::remove_outliers(sensor_msgs::LaserScan &scan)
15+
{
16+
if (!filter_configured_)
17+
return;
18+
19+
// help function initialization
20+
int ranges_size = scan.ranges.size();
21+
int i_current_cluster = 0;
22+
bool cluster_further_away = false;
23+
std::vector<int> cluster_indecies;
24+
double diffs[ranges_size-1];
25+
26+
// calculate diffs
27+
for (int i = 1; i< ranges_size; i++)
28+
{
29+
diffs[i-1] = scan.ranges[i] - scan.ranges[i-1];
30+
}
31+
32+
// find and remove outliers
33+
for (int i = 0; i< ranges_size-1; i++)
34+
{
35+
// add point to cluster
36+
cluster_indecies.push_back(i);
37+
i_current_cluster ++;
38+
39+
// check if last point in cluster; find diff larger than border -> cluster separation
40+
if (diffs[i] > cluster_break_distance_ || diffs[i] < -cluster_break_distance_)
41+
{
42+
bool new_cluster_further_away = (diffs[i] > 0);
43+
44+
// Only remove cluster if it is closer than surrounding clusters
45+
if ((i_current_cluster < max_noise_cluster_size_) && (new_cluster_further_away != cluster_further_away))
46+
{
47+
// check if all cluster points are closer than the max noise distance
48+
bool is_noise_cluster = true;
49+
for (int k = 0; k < i_current_cluster; k++)
50+
{
51+
if (scan.ranges[cluster_indecies[k]] > max_noise_cluster_distance_)
52+
{
53+
is_noise_cluster = false;
54+
break;
55+
}
56+
}
57+
58+
// Only remove cluster points if all points are closer than the max noise distance
59+
if(is_noise_cluster)
60+
{
61+
for (int k = 0; k < i_current_cluster; k++)
62+
{
63+
if (scan.ranges[cluster_indecies[k]] < max_noise_cluster_distance_)
64+
scan.ranges[cluster_indecies[k]] = scan.range_max;
65+
}
66+
}
67+
}
68+
69+
// initialize new cluster
70+
cluster_further_away = new_cluster_further_away;
71+
cluster_indecies.clear();
72+
i_current_cluster = 0;
73+
}
74+
}
75+
76+
77+
// remove last cluster if small enough
78+
if ((i_current_cluster < cluster_break_distance_) && !cluster_further_away)
79+
{
80+
for (int k = 0; k < i_current_cluster; k++)
81+
{
82+
scan.ranges[cluster_indecies[k]] = scan.range_max;
83+
}
84+
// remove last point as well
85+
scan.ranges[ranges_size-1] = scan.range_max;
86+
}
87+
88+
}

0 commit comments

Comments
 (0)