40 #include <boost/thread.hpp> 41 #include <boost/thread/mutex.hpp> 96 dynamic_recfg_ =
new dynamic_reconfigure::Server<CostmapToLinesDBSRANSACConfig>(nh);
103 std::vector< std::vector<KeyPoint> > clusters;
111 for (
int i = 1; i <clusters.size(); ++i)
117 std::vector<KeyPoint> outliers;
118 std::pair<KeyPoint,KeyPoint> model;
123 geometry_msgs::Polygon line;
124 line.points.resize(2);
125 model.first.toPointMsg(line.points.front());
126 model.second.toPointMsg(line.points.back());
127 polygons->push_back(line);
129 clusters[i] = outliers;
139 geometry_msgs::Polygon polygon;
141 for (
int j=0; j < (int)polygon.points.size(); ++j)
143 polygons->push_back(geometry_msgs::Polygon());
149 for (
int j = 0; j < (int)clusters[i].size(); ++j)
151 polygons->push_back(geometry_msgs::Polygon());
162 if (!clusters.empty())
164 for (
int i=0; i < clusters.front().size(); ++i)
166 polygons->push_back( geometry_msgs::Polygon() );
177 int min_inliers, std::pair<KeyPoint, KeyPoint>& best_model,
178 std::vector<KeyPoint>* inliers, std::vector<KeyPoint>* outliers)
180 if (data.size() < 2 || data.size() < min_inliers)
185 boost::random::uniform_int_distribution<> distribution(0, data.size()-1);
187 std::pair<int, int> best_model_idx;
188 int best_no_inliers = -1;
191 for (
int i=0; i < no_iterations; ++i)
195 int end_idx = start_idx;
196 while (end_idx == start_idx)
202 for (
int j=0; j<(int)data.size(); ++j)
204 if (
isInlier(data[j], data[start_idx], data[end_idx], inlier_distance) )
208 if (no_inliers > best_no_inliers)
210 best_no_inliers = no_inliers;
211 best_model_idx.first = start_idx;
212 best_model_idx.second = end_idx;
216 best_model.first = data[best_model_idx.first];
217 best_model.second = data[best_model_idx.second];
219 if (best_no_inliers < min_inliers)
224 if (inliers || outliers)
232 for (
int i=0; i<(int)data.size(); ++i)
234 if (
isInlier( data[i], best_model.first, best_model.second, inlier_distance ) )
237 inliers->push_back( data[i] );
242 outliers->push_back( data[i] );
251 double* mean_x_out,
double* mean_y_out)
255 ROS_ERROR(
"CostmapToLinesDBSRANSAC: at least 2 data points required for linear regression");
261 for (
int i=0; i<(int)data.size(); ++i)
266 mean_x /= double(data.size());
267 mean_y /= double(data.size());
270 *mean_x_out = mean_x;
273 *mean_y_out = mean_y;
275 double numerator = 0.0;
276 double denominator = 0.0;
278 for(
int i=0; i<(int)data.size(); ++i)
280 double dx = data[i].x - mean_x;
281 numerator += dx * (data[i].y - mean_y);
282 denominator += dx*dx;
285 if (denominator == 0)
287 ROS_ERROR(
"CostmapToLinesDBSRANSAC: linear regression failed, denominator 0");
291 slope = numerator / denominator;
293 intercept = mean_y - slope * mean_x;
std::vector< KeyPoint > occupied_cells_
List of occupied cells in the current map (updated by updateCostmap2D())
int max_pts_
Parameter for DB_Scan: maximum number of points that define a cluster (to avoid large L- and U-shapes...
static void convertPointToPolygon(const Point &point, geometry_msgs::Polygon &polygon)
Convert a generi point type to a geometry_msgs::Polygon.
double max_distance_
Parameter for DB_Scan, maximum distance to neighbors [m].
double min_keypoint_separation_
Clear keypoints of the convex polygon that are close to each other [distance in meters] (0: keep all)...
double ransac_inlier_distance_
Maximum distance to the line segment for inliers.
virtual void initialize(ros::NodeHandle nh)
Initialize the plugin.
bool ransac_convert_outlier_pts_
If true, convert remaining outliers to single points.
PLUGINLIB_EXPORT_CLASS(BAGReader, nodelet::Nodelet)
int ransac_min_inliers_
Minimum numer of inliers required to form a line.
boost::random::mt19937 rnd_generator_
Random number generator for ransac with default seed.
int ransac_no_iterations_
Number of ransac iterations.
int ransac_remainig_outliers_
Repeat ransac until the number of outliers is as specified here.
This class converts the costmap_2d into a set of lines (and points)
dynamic_reconfigure::Server< CostmapToLinesDBSRANSACConfig > * dynamic_recfg_
Dynamic reconfigure server to allow config modifications at runtime.
virtual ~CostmapToLinesDBSRANSAC()
Destructor.
virtual void compute()
This method performs the actual work (conversion of the costmap to polygons)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
This abstract class defines the interface for plugins that convert the costmap into polygon types...
bool lineRansac(const std::vector< KeyPoint > &data, double inlier_distance, int no_iterations, int min_inliers, std::pair< KeyPoint, KeyPoint > &best_model, std::vector< KeyPoint > *inliers=NULL, std::vector< KeyPoint > *outliers=NULL)
Find a straight line segment in a point cloud with RANSAC (without linear regression).
int min_pts_
Parameter for DB_Scan: minimum number of points that define a cluster.
This class converts the costmap_2d into a set of convex polygons (and points)
void reconfigureCB(CostmapToLinesDBSRANSACConfig &config, uint32_t level)
Callback for the dynamic_reconfigure node.
bool linearRegression(const std::vector< KeyPoint > &data, double &slope, double &intercept, double *mean_x_out=NULL, double *mean_y_out=NULL)
Perform a simple linear regression in order to fit a straight line 'y = slope*x + intercept'...
void dbScan(const std::vector< KeyPoint > &occupied_cells, std::vector< std::vector< KeyPoint > > &clusters)
DBSCAN algorithm for clustering.
void convexHull2(std::vector< KeyPoint > &cluster, geometry_msgs::Polygon &polygon)
Compute the convex hull for a single cluster.
static bool isInlier(const Point &point, const LinePoint &line_start, const LinePoint &line_end, double min_distance)
Check if the candidate point is an inlier.
void updatePolygonContainer(PolygonContainerPtr polygons)
Thread-safe update of the internal polygon container (that is shared using getPolygons() from outside...
bool ransac_filter_remaining_outlier_pts_
If true, filter the interior of remaining outliers and keep only keypoints of their convex hull...