37 #include "ompl/extensions/triangle/TriangularDecomposition.h"
38 #include "ompl/base/State.h"
39 #include "ompl/base/StateSampler.h"
40 #include "ompl/base/spaces/RealVectorBounds.h"
41 #include "ompl/control/planners/syclop/Decomposition.h"
42 #include "ompl/control/planners/syclop/GridDecomposition.h"
43 #include "ompl/util/RandomNumbers.h"
44 #include "ompl/util/Hash.h"
49 #include <unordered_map>
56 #define ANSI_DECLARATORS
63 struct hash<ompl::control::TriangularDecomposition::Vertex>
67 std::size_t hash = std::hash<double>()(v.x);
68 ompl::hash_combine(hash, v.y);
75 const std::vector<Polygon> &holes,
const std::vector<Polygon> &intRegs) :
86 ompl::control::TriangularDecomposition::~TriangularDecomposition(
void)
90 void ompl::control::TriangularDecomposition::setup(
void)
92 int numTriangles = createTriangles();
97 void ompl::control::TriangularDecomposition::addHole(
const Polygon& hole)
99 holes_.push_back(hole);
102 void ompl::control::TriangularDecomposition::addRegionOfInterest(
const Polygon& region)
104 intRegs_.push_back(region);
107 int ompl::control::TriangularDecomposition::getNumHoles(
void)
const
109 return holes_.size();
112 int ompl::control::TriangularDecomposition::getNumRegionsOfInterest(
void)
const
114 return intRegs_.size();
117 const std::vector<ompl::control::TriangularDecomposition::Polygon>&
118 ompl::control::TriangularDecomposition::getHoles(
void)
const
123 const std::vector<ompl::control::TriangularDecomposition::Polygon>&
124 ompl::control::TriangularDecomposition::getAreasOfInterest(
void)
const
131 return intRegInfo_[triID];
142 (tri.pts[0].x-tri.pts[2].x)*(tri.pts[1].y-tri.pts[0].y)
143 - (tri.pts[0].x-tri.pts[1].x)*(tri.pts[2].y-tri.pts[0].y)
151 neighbors = triangles_[triID].neighbors;
156 std::vector<double> coord(2);
158 const std::vector<int>& gridTriangles = locator.locateTriangles(s);
160 for (std::vector<int>::const_iterator i = gridTriangles.begin(); i != gridTriangles.end(); ++i)
163 if (triContains(triangles_[triID], coord))
166 OMPL_WARN(
"Decomposition space coordinate (%f,%f) is somehow contained by multiple triangles. \
167 This can happen if the coordinate is located exactly on a triangle segment.\n",
179 const Triangle& tri = triangles_[triID];
183 coord[0] = (1-r1)*tri.pts[0].x + r1*(1-r2)*tri.pts[1].x + r1*r2*tri.pts[2].x;
184 coord[1] = (1-r1)*tri.pts[0].y + r1*(1-r2)*tri.pts[1].y + r1*r2*tri.pts[2].y;
187 void ompl::control::TriangularDecomposition::print(std::ostream& out)
const
194 for (
unsigned int i = 0; i < triangles_.size(); ++i)
197 const Triangle& tri = triangles_[i];
198 for (
int v = 0; v < 3; ++v)
199 out << tri.pts[v].x <<
" " << tri.pts[v].y <<
" ";
200 if (intRegInfo_[i] > -1) out << intRegInfo_[i] <<
" ";
201 out <<
"-1" << std::endl;
205 ompl::control::TriangularDecomposition::Vertex::Vertex(
double vx,
double vy) : x(vx), y(vy)
209 bool ompl::control::TriangularDecomposition::Vertex::operator==(
const Vertex &v)
const
211 return x == v.x && y == v.y;
220 const double maxTriangleArea = bounds.
getVolume() * triAreaPct_;
221 std::string triswitches =
"pDznQA -a" + std::to_string(maxTriangleArea);
222 struct triangulateio in;
230 std::unordered_map<Vertex, int> pointIndex;
241 in.numberofpoints = 4;
242 in.numberofsegments = 4;
244 typedef std::vector<Polygon>::const_iterator PolyIter;
245 typedef std::vector<Vertex>::const_iterator VertexIter;
248 for (PolyIter p = holes_.begin(); p != holes_.end(); ++p)
250 for (VertexIter v = p->pts.begin(); v != p->pts.end(); ++v)
252 ++in.numberofsegments;
255 if (pointIndex.find(*v) == pointIndex.end())
256 pointIndex[*v] = in.numberofpoints++;
262 for (PolyIter p = intRegs_.begin(); p != intRegs_.end(); ++p)
264 for (VertexIter v = p->pts.begin(); v != p->pts.end(); ++v)
266 ++in.numberofsegments;
267 if (pointIndex.find(*v) == pointIndex.end())
268 pointIndex[*v] = in.numberofpoints++;
273 in.pointlist = (REAL*) malloc(2*in.numberofpoints*
sizeof(REAL));
276 typedef std::unordered_map<Vertex, int>::const_iterator IndexIter;
277 for (IndexIter i = pointIndex.begin(); i != pointIndex.end(); ++i)
279 const Vertex& v = i->first;
280 int index = i->second;
281 in.pointlist[2*index] = v.x;
282 in.pointlist[2*index+1] = v.y;
287 in.segmentlist = (
int*) malloc(2*in.numberofsegments*
sizeof(
int));
290 for (
int i = 0; i < 4; ++i)
292 in.segmentlist[2*i] = i;
293 in.segmentlist[2*i+1] = (i+1) % 4;
302 for (PolyIter p = holes_.begin(); p != holes_.end(); ++p)
304 for (
unsigned int j = 0; j < p->pts.size(); ++j)
306 in.segmentlist[2*segIndex] = pointIndex[p->pts[j]];
307 in.segmentlist[2*segIndex+1] = pointIndex[p->pts[(j+1)%p->pts.size()]];
314 for (PolyIter p = intRegs_.begin(); p != intRegs_.end(); ++p)
316 for (
unsigned int j = 0; j < p->pts.size(); ++j)
318 in.segmentlist[2*segIndex] = pointIndex[p->pts[j]];
319 in.segmentlist[2*segIndex+1] = pointIndex[p->pts[(j+1)%p->pts.size()]];
327 in.numberofholes = holes_.size();
328 in.holelist =
nullptr;
329 if (in.numberofholes > 0)
333 in.holelist = (REAL*) malloc(2*in.numberofholes*
sizeof(REAL));
334 for (
int i = 0; i < in.numberofholes; ++i)
336 Vertex v = getPointInPoly(holes_[i]);
337 in.holelist[2*i] = v.x;
338 in.holelist[2*i+1] = v.y;
345 in.numberofregions = intRegs_.size();
346 in.regionlist =
nullptr;
347 if (in.numberofregions > 0)
353 in.regionlist = (REAL*) malloc(4*in.numberofregions*
sizeof(REAL));
354 for (
unsigned int i = 0; i < intRegs_.size(); ++i)
356 Vertex v = getPointInPoly(intRegs_[i]);
357 in.regionlist[4*i] = v.x;
358 in.regionlist[4*i+1] = v.y;
361 in.regionlist[4*i+2] = (REAL) (i+1);
362 in.regionlist[4*i+3] = -1.;
367 in.segmentmarkerlist = (
int*)
nullptr;
368 in.numberofpointattributes = 0;
369 in.pointattributelist =
nullptr;
370 in.pointmarkerlist =
nullptr;
373 struct triangulateio out;
374 out.pointlist = (REAL*)
nullptr;
375 out.pointattributelist = (REAL*)
nullptr;
376 out.pointmarkerlist = (
int*)
nullptr;
377 out.trianglelist = (
int*)
nullptr;
378 out.triangleattributelist = (REAL*)
nullptr;
379 out.neighborlist = (
int*)
nullptr;
380 out.segmentlist = (
int*)
nullptr;
381 out.segmentmarkerlist = (
int*)
nullptr;
382 out.edgelist = (
int*)
nullptr;
383 out.edgemarkerlist = (
int*)
nullptr;
384 out.pointlist = (REAL*)
nullptr;
385 out.pointattributelist = (REAL*)
nullptr;
386 out.trianglelist = (
int*)
nullptr;
387 out.triangleattributelist = (REAL*)
nullptr;
390 triangulate(const_cast<char*>(triswitches.c_str()), &in, &out,
nullptr);
392 triangles_.resize(out.numberoftriangles);
393 intRegInfo_.resize(out.numberoftriangles);
394 for (
int i = 0; i < out.numberoftriangles; ++i)
397 for (
int j = 0; j < 3; ++j)
399 t.pts[j].x = out.pointlist[2*out.trianglelist[3*i+j]];
400 t.pts[j].y = out.pointlist[2*out.trianglelist[3*i+j]+1];
401 if (out.neighborlist[3*i+j] >= 0)
402 t.neighbors.push_back(out.neighborlist[3*i+j]);
406 if (in.numberofregions > 0)
408 int attribute = (int) out.triangleattributelist[i];
410 intRegInfo_[i] = (attribute > 0 ? attribute-1 : -1);
414 trifree(in.pointlist);
415 trifree(in.segmentlist);
416 if (in.numberofholes > 0)
417 trifree(in.holelist);
418 if (in.numberofregions > 0)
419 trifree(in.regionlist);
420 trifree(out.pointlist);
421 trifree(out.pointattributelist);
422 trifree(out.pointmarkerlist);
423 trifree(out.trianglelist);
424 trifree(out.triangleattributelist);
425 trifree(out.neighborlist);
426 trifree(out.edgelist);
427 trifree(out.edgemarkerlist);
428 trifree(out.segmentlist);
429 trifree(out.segmentmarkerlist);
431 return out.numberoftriangles;
434 void ompl::control::TriangularDecomposition::LocatorGrid::buildTriangleMap(
const std::vector<Triangle>& triangles)
436 regToTriangles_.resize(getNumRegions());
437 std::vector<double> bboxLow(2);
438 std::vector<double> bboxHigh(2);
439 std::vector<int> gridCoord[2];
440 for (
unsigned int i = 0; i < triangles.size(); ++i)
444 const Triangle& tri = triangles[i];
445 bboxLow[0] = tri.pts[0].x;
446 bboxLow[1] = tri.pts[0].y;
447 bboxHigh[0] = bboxLow[0];
448 bboxHigh[1] = bboxLow[1];
450 for (
int j = 1; j < 3; ++j)
452 if (tri.pts[j].x < bboxLow[0])
453 bboxLow[0] = tri.pts[j].x;
454 else if (tri.pts[j].x > bboxHigh[0])
455 bboxHigh[0] = tri.pts[j].x;
456 if (tri.pts[j].y < bboxLow[1])
457 bboxLow[1] = tri.pts[j].y;
458 else if (tri.pts[j].y > bboxHigh[1])
459 bboxHigh[1] = tri.pts[j].y;
464 coordToGridCoord(bboxLow, gridCoord[0]);
465 coordToGridCoord(bboxHigh, gridCoord[1]);
469 std::vector<int> c(2);
470 for (
int x = gridCoord[0][0]; x <= gridCoord[1][0]; ++x)
472 for (
int y = gridCoord[0][1]; y <= gridCoord[1][1]; ++y)
476 int cellID = gridCoordToRegion(c);
477 regToTriangles_[cellID].push_back(i);
483 void ompl::control::TriangularDecomposition::buildLocatorGrid()
485 locator.buildTriangleMap(triangles_);
488 bool ompl::control::TriangularDecomposition::triContains(
const Triangle& tri,
const std::vector<double>& coord)
490 for (
int i = 0; i < 3; ++i)
494 const double ax = tri.pts[i].x;
495 const double ay = tri.pts[i].y;
496 const double bx = tri.pts[(i+1)%3].x;
497 const double by = tri.pts[(i+1)%3].y;
500 if ((coord[0]-ax)*(by-ay) - (bx-ax)*(coord[1]-ay) > 0.)
511 for (std::vector<Vertex>::const_iterator i = poly.pts.begin(); i != poly.pts.end(); ++i)
516 p.x /= poly.pts.size();
517 p.y /= poly.pts.size();
double getVolume() const
Compute the volume of the space enclosed by the bounds.
std::vector< double > low
Lower bound.
virtual int locateRegion(const base::State *s) const
Returns the index of the region containing a given State. Most often, this is obtained by first calli...
virtual double getRegionVolume(int triID)
Returns the volume of a given region in this Decomposition.
virtual int createTriangles()
Helper method to triangulate the space and return the number of triangles.
virtual void getNeighbors(int triID, std::vector< int > &neighbors) const
Stores a given region's neighbors into a given vector.
A Decomposition is a partition of a bounded Euclidean space into a fixed number of regions which are ...
double uniform01()
Generate a random real between 0 and 1.
virtual void sampleFromRegion(int triID, RNG &rng, std::vector< double > &coord) const
Samples a projected coordinate from a given region.
int getRegionOfInterestAt(int triID) const
Returns the region of interest that contains the given triangle ID. Returns -1 if the triangle ID is ...
Random number generation. An instance of this class cannot be used by multiple threads at once (membe...
std::vector< double > high
Upper bound.
Definition of an abstract state.
#define OMPL_WARN(fmt,...)
Log a formatted warning string.
The lower and upper bounds for an Rn space.
TriangularDecomposition(const base::RealVectorBounds &bounds, const std::vector< Polygon > &holes=std::vector< Polygon >(), const std::vector< Polygon > &intRegs=std::vector< Polygon >())
Creates a TriangularDecomposition over the given bounds, which must be 2-dimensional. The underlying mesh will be a conforming Delaunay triangulation. The triangulation will ignore any obstacles, given as a list of polygons. The triangulation will respect the boundaries of any regions of interest, given as a list of polygons. No two obstacles may overlap, and no two regions of interest may overlap.
#define OMPL_INFORM(fmt,...)
Log a formatted information string.