UAV Coverage Path Planner
torres_etal_2016.cpp
Go to the documentation of this file.
1 
7 /*
8  * Copyright (c) 2017 Takaki Ueno
9  * Released under the MIT license
10  */
11 
12 // header
13 #include <torres_etal_2016.hpp>
14 
20 std::vector<geometry_msgs::Polygon> generatePolygonVector(const PointVector& polygon)
21 {
22  // convert PointVector (a.k.a. std::vector<geometry_msgs::Point>) to geometry_msgs::Polygon
23  // so that polygon is visualized on the window
24  geometry_msgs::Polygon poly;
25  for (const auto& vertex : polygon)
26  {
27  geometry_msgs::Point32 p;
28  p.x = vertex.x;
29  p.y = vertex.y;
30  poly.points.push_back(p);
31  }
32 
33  std::vector<geometry_msgs::Polygon> polygons = { poly };
34 
35  return polygons;
36 }
37 
43 std::vector<geometry_msgs::Polygon> generatePolygonVector(const std::vector<PointVector>& subPolygons)
44 {
45  std::vector<geometry_msgs::Polygon> subPolygonsRet;
46 
47  // convert PointVector (a.k.a. std::vector<geometry_msgs::Point>) to geometry_msgs::Polygon
48  // so that polygon is visualized on the window
49  for (const auto& subPolygon : subPolygons)
50  {
51  geometry_msgs::Polygon poly;
52  for (const auto& vertex : subPolygon)
53  {
54  geometry_msgs::Point32 pt;
55  pt.x = vertex.x;
56  pt.y = vertex.y;
57  poly.points.push_back(pt);
58  }
59  subPolygonsRet.push_back(poly);
60  }
61 
62  return subPolygonsRet;
63 }
64 
72 bool plan(cpp_uav::Torres16::Request& req, cpp_uav::Torres16::Response& res)
73 {
74  // see torres et al. 2016 for the flow of this algorithm
75 
76  // polygon from request and path for response
77  PointVector polygon, candidatePath;
78  // start point of coverage path
79  geometry_msgs::Point start;
80  // parameters of coverage path
81  std_msgs::Float64 footprintLength, footprintWidth, horizontalOverwrap, verticalOverwrap;
82 
83  polygon = req.polygon;
84  start = req.start;
85 
86  footprintLength = req.footprint_length;
87  footprintWidth = req.footprint_width;
88  horizontalOverwrap = req.horizontal_overwrap;
89  verticalOverwrap = req.vertical_overwrap;
90 
91  // isOptimal is true if computed path does not have intersection with polygon
92  bool isOptimal = computeConvexCoverage(polygon, footprintWidth.data, horizontalOverwrap.data, candidatePath);
93 
94  if (isOptimal == true)
95  {
96  // fill "subpolygon" field of response so that polygon is visualized
97  res.subpolygons = generatePolygonVector(polygon);
98 
99  // set optimal alternative as optimal path
100  // see torres et al. 2016 for Optimal Alternative
101  res.path = identifyOptimalAlternative(polygon, candidatePath, start);
102  }
103  else
104  {
105  std::vector<PointVector> subPolygons = decomposePolygon(polygon);
106 
107  // sum of length of all coverage path
108  double pathLengthSum = 0;
109 
110  int i = 1;
111  // compute length of coverage path of each subpolygon
112  for (const auto& polygon : subPolygons)
113  {
114  PointVector partialPath;
115  computeConvexCoverage(polygon, footprintWidth.data, horizontalOverwrap.data, partialPath);
116  pathLengthSum += calculatePathLength(partialPath);
117  }
118 
119  // existsSecondOptimalPath is true if there is at least one coverage that has no intersection with polygon
120  // second optimal path is the path that has second shortest sweep direction and no intersection with polygon
121  PointVector secondOptimalPath;
122  bool existsSecondOptimalPath =
123  findSecondOptimalPath(polygon, footprintWidth.data, horizontalOverwrap.data, candidatePath);
124 
125  if (existsSecondOptimalPath == true)
126  {
127  // compute optimal alternative for second optimal path
128  secondOptimalPath = identifyOptimalAlternative(polygon, candidatePath, start);
129 
130  // if the length of second optimal path is shorter than the sum of coverage path of subpolygons,
131  // set second optimal path as the path
132  if (pathLengthSum > calculatePathLength(secondOptimalPath))
133  {
134  // fill "subpolygon" field of response so that polygon is visualized
135  res.subpolygons = generatePolygonVector(polygon);
136 
137  res.path = secondOptimalPath;
138 
139  return true;
140 
141  }
142  // returns second optimal path when shortest path is not optimal and polygon cannot be decomposed
143  else if(subPolygons.size() == 1)
144  {
145  res.subpolygons = generatePolygonVector(polygon);
146 
147  res.path = secondOptimalPath;
148 
149  return true;
150  }
151  }
152  else if (subPolygons.size() < 2)
153  {
154  // if number of subpolygon is smaller than 2,
155  // it means no valid path can be computed
156  ROS_ERROR("Unable to generate path.");
157  return true;
158  }
159 
160  // fill "subpolygon" field of response so that polygon is visualized
161  res.subpolygons = generatePolygonVector(subPolygons);
162 
163  // compute coverage path of subpolygons
164  PointVector multipleCoveragePath =
165  computeMultiplePolygonCoverage(subPolygons, footprintWidth.data, horizontalOverwrap.data);
166 
167  res.path = multipleCoveragePath;
168  }
169 
170  return true;
171 }
172 
173 int main(int argc, char** argv)
174 {
175  ros::init(argc, argv, "torres_etal_2016");
176  ros::NodeHandle nh;
177 
178  ros::ServiceServer planner = nh.advertiseService("cpp_torres16", plan);
179  ROS_INFO("Ready to plan.");
180 
181  ros::spin();
182 
183  return 0;
184 }
bool plan(cpp_uav::Torres16::Request &req, cpp_uav::Torres16::Response &res)
Plans coverage path.
Utility for computational geometry.
bool findSecondOptimalPath(const PointVector &polygon, double footprintWidth, double horizontalOverwrap, PointVector &path)
Find second optimal path.
int main(int argc, char **argv)
PointVector identifyOptimalAlternative(const PointVector &polygon, const PointVector &path, const geometry_msgs::Point &start, const geometry_msgs::Point &end)
Identify optimal path from 4 coverage alternatives.
PointVector computeMultiplePolygonCoverage(std::vector< PointVector > subPolygons, double footprintWidth, double horizontalOverwrap, int adjacencyCriteria=1)
Compute coverage path for multiple convex polygons.
std::vector< geometry_msgs::Polygon > generatePolygonVector(const PointVector &polygon)
Generate vector of polygon from PointVector.
std::vector< geometry_msgs::Point > PointVector
Definition: cgutil.hpp:37
bool computeConvexCoverage(const PointVector &polygon, double footprintWidth, double horizontalOverwrap, const Direction &sweepDirection, PointVector &path)
Compute coverage path for convex polygon.
double calculatePathLength(const PointVector &path)
Calculates length of path.
std::vector< PointVector > decomposePolygon(const PointVector &polygon)
Decompose given polygon.
Definition: cgutil.hpp:468