costmap_to_polygons_concave.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2016,
6  * TU Dortmund - Institute of Control Theory and Systems Engineering.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of the institute nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * Author: Christoph Rösmann, Otniel Rinaldo
37  *********************************************************************/
38 
40 
42 
44 
45 namespace costmap_converter
46 {
47 
48 CostmapToPolygonsDBSConcaveHull::CostmapToPolygonsDBSConcaveHull() : CostmapToPolygonsDBSMCCH()
49 {
50  dynamic_recfg_ = NULL;
51 }
52 
54 {
55  if (dynamic_recfg_ != NULL)
56  delete dynamic_recfg_;
57 }
58 
60 {
61  nh.param("cluster_max_distance", parameter_.max_distance_, 0.4);
62  nh.param("cluster_min_pts", parameter_.min_pts_, 2);
63  nh.param("cluster_max_pts", parameter_.max_pts_, 30);
64  nh.param("convex_hull_min_pt_separation", parameter_.min_keypoint_separation_, 0.1);
66 
67  nh.param("concave_hull_depth", concave_hull_depth_, 2.0);
68 
69  // setup dynamic reconfigure
70  dynamic_recfg_ = new dynamic_reconfigure::Server<CostmapToPolygonsDBSConcaveHullConfig>(nh);
71  dynamic_reconfigure::Server<CostmapToPolygonsDBSConcaveHullConfig>::CallbackType cb = boost::bind(&CostmapToPolygonsDBSConcaveHull::reconfigureCB, this, _1, _2);
72  dynamic_recfg_->setCallback(cb);
73 }
74 
75 
77 {
78  std::vector< std::vector<KeyPoint> > clusters;
79  dbScan(clusters);
80 
81  // Create new polygon container
82  PolygonContainerPtr polygons(new std::vector<geometry_msgs::Polygon>());
83 
84 
85  // add convex hulls to polygon container
86  for (int i = 1; i <clusters.size(); ++i) // skip first cluster, since it is just noise
87  {
88  polygons->push_back( geometry_msgs::Polygon() );
89  concaveHull(clusters[i], concave_hull_depth_, polygons->back() );
90  }
91 
92  // add our non-cluster points to the polygon container (as single points)
93  if (!clusters.empty())
94  {
95  for (int i=0; i < clusters.front().size(); ++i)
96  {
97  polygons->push_back( geometry_msgs::Polygon() );
98  convertPointToPolygon(clusters.front()[i], polygons->back());
99  }
100  }
101 
102  // replace shared polygon container
103  updatePolygonContainer(polygons);
104 }
105 
106 
107 void CostmapToPolygonsDBSConcaveHull::concaveHull(std::vector<KeyPoint>& cluster, double depth, geometry_msgs::Polygon& polygon)
108 {
109  // start with convex hull
110  convexHull2(cluster, polygon);
111 
112  std::vector<geometry_msgs::Point32>& concave_list = polygon.points;
113 
114  for (int i = 0; i < (int)concave_list.size() - 1; ++i)
115  {
116 
117  // find nearest inner point pk from line (vertex1 -> vertex2)
118  const geometry_msgs::Point32& vertex1 = concave_list[i];
119  const geometry_msgs::Point32& vertex2 = concave_list[i+1];
120 
121  bool found;
122  size_t nearest_idx = findNearestInnerPoint(vertex1, vertex2, cluster, concave_list, &found);
123  if (!found)
124  continue;
125 
126  double line_length = norm2d(vertex1, vertex2);
127 
128  double dst1 = norm2d(cluster[nearest_idx], vertex1);
129  double dst2 = norm2d(cluster[nearest_idx], vertex2);
130  double dd = std::min(dst1, dst2);
131  if (dd<1e-8)
132  continue;
133 
134  if (line_length / dd > depth)
135  {
136  // Check that new candidate edge will not intersect existing edges.
137  bool intersects = checkLineIntersection(concave_list, vertex1, vertex2, vertex1, cluster[nearest_idx]);
138  intersects |= checkLineIntersection(concave_list, vertex1, vertex2, cluster[nearest_idx], vertex2);
139  if (!intersects)
140  {
141  geometry_msgs::Point32 new_point;
142  cluster[nearest_idx].toPointMsg(new_point);
143  concave_list.insert(concave_list.begin() + i + 1, new_point);
144  i--;
145  }
146  }
147  }
148 }
149 
150 
151 void CostmapToPolygonsDBSConcaveHull::concaveHullClusterCut(std::vector<KeyPoint>& cluster, double depth, geometry_msgs::Polygon& polygon)
152 {
153  // start with convex hull
154  convexHull2(cluster, polygon);
155 
156  std::vector<geometry_msgs::Point32>& concave_list = polygon.points;
157 
158  // get line length
159  double mean_length = 0;
160  for (int i = 0; i < (int)concave_list.size() - 1; ++i)
161  {
162  mean_length += norm2d(concave_list[i],concave_list[i+1]);
163  }
164  mean_length /= double(concave_list.size());
165 
166  for (int i = 0; i < (int)concave_list.size() - 1; ++i)
167  {
168 
169  // find nearest inner point pk from line (vertex1 -> vertex2)
170  const geometry_msgs::Point32& vertex1 = concave_list[i];
171  const geometry_msgs::Point32& vertex2 = concave_list[i+1];
172 
173  double line_length = norm2d(vertex1, vertex2);
174 
175  bool found;
176  size_t nearest_idx = findNearestInnerPoint(vertex1, vertex2, cluster, concave_list, &found);
177  if (!found)
178  {
179  continue;
180  }
181 
182 
183  double dst1 = norm2d(cluster[nearest_idx], vertex1);
184  double dst2 = norm2d(cluster[nearest_idx], vertex2);
185  double dd = std::min(dst1, dst2);
186  if (dd<1e-8)
187  continue;
188 
189  if (line_length / dd > depth)
190  {
191  // Check that new candidate edge will not intersect existing edges.
192  bool intersects = checkLineIntersection(concave_list, vertex1, vertex2, vertex1, cluster[nearest_idx]);
193  intersects |= checkLineIntersection(concave_list, vertex1, vertex2, cluster[nearest_idx], vertex2);
194  if (!intersects)
195  {
196  geometry_msgs::Point32 new_point;
197  cluster[nearest_idx].toPointMsg(new_point);
198  concave_list.insert(concave_list.begin() + i + 1, new_point);
199  i--;
200  }
201  }
202  }
203 }
204 
205 
206 
207 
208 void CostmapToPolygonsDBSConcaveHull::reconfigureCB(CostmapToPolygonsDBSConcaveHullConfig& config, uint32_t level)
209 {
210  boost::mutex::scoped_lock lock(parameter_mutex_);
211  parameter_buffered_.max_distance_ = config.cluster_max_distance;
212  parameter_buffered_.min_pts_ = config.cluster_min_pts;
213  parameter_buffered_.max_pts_ = config.cluster_max_pts;
214  parameter_buffered_.min_keypoint_separation_ = config.cluster_min_pts;
215  concave_hull_depth_ = config.concave_hull_depth;
216 }
217 
218 }//end namespace costmap_converter
219 
220 
bool intersects(std::vector< geometry_msgs::Point > &polygon, float testx, float testy)
double min_keypoint_separation_
Clear keypoints of the convex polygon that are close to each other [distance in meters] (0: keep all)...
double norm2d(const Point1 &pt1, const Point2 &pt2)
Calculate the distance between two 2d points.
Definition: misc.h:133
virtual void initialize(ros::NodeHandle nh)
Initialize the plugin.
void concaveHullClusterCut(std::vector< KeyPoint > &cluster, double depth, geometry_msgs::Polygon &polygon)
static void convertPointToPolygon(const Point &point, geometry_msgs::Polygon &polygon)
Convert a generi point type to a geometry_msgs::Polygon.
void dbScan(std::vector< std::vector< KeyPoint > > &clusters)
DBSCAN algorithm for clustering.
int max_pts_
Parameter for DB_Scan: maximum number of points that define a cluster (to avoid large L- and U-shapes...
PLUGINLIB_EXPORT_CLASS(BAGReader, nodelet::Nodelet)
This class converts the costmap_2d into a set of non-convex polygons (and points) ...
bool checkLineIntersection(const Point1 &line1_start, const Point2 &line1_end, const Point3 &line2_start, const Point4 &line2_end)
virtual void compute()
This method performs the actual work (conversion of the costmap to polygons)
void reconfigureCB(CostmapToPolygonsDBSConcaveHullConfig &config, uint32_t level)
Callback for the dynamic_reconfigure node.
dynamic_reconfigure::Server< CostmapToPolygonsDBSConcaveHullConfig > * dynamic_recfg_
Dynamic reconfigure server to allow config modifications at runtime.
int min_pts_
Parameter for DB_Scan: minimum number of points that define a cluster.
boost::mutex parameter_mutex_
Mutex that keeps track about the ownership of the shared polygon instance.
std::size_t findNearestInnerPoint(PointLine line_start, PointLine line_end, const std::vector< PointCluster > &cluster, const std::vector< PointHull > &hull, bool *found)
double max_distance_
Parameter for DB_Scan, maximum distance to neighbors [m].
bool param(const std::string &param_name, T &param_val, const T &default_val) const
This abstract class defines the interface for plugins that convert the costmap into polygon types...
void concaveHull(std::vector< KeyPoint > &cluster, double depth, geometry_msgs::Polygon &polygon)
Compute the concave hull for a single cluster.
This class converts the costmap_2d into a set of convex polygons (and points)
void convexHull2(std::vector< KeyPoint > &cluster, geometry_msgs::Polygon &polygon)
Compute the convex hull for a single cluster.
void updatePolygonContainer(PolygonContainerPtr polygons)
Thread-safe update of the internal polygon container (that is shared using getPolygons() from outside...


costmap_converter
Author(s): Christoph Rösmann , Franz Albers , Otniel Rinaldo
autogenerated on Sat May 16 2020 03:19:18