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...