00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00019 #ifndef __POLYOPS_H__
00020 #define __POLYOPS_H__
00021
00022
00023 #include <utility>
00024 #include <math.h>
00025 #include <vector>
00026 #include <set>
00027 #include <map>
00028
00029 #include <art_msgs/ArtLanes.h>
00030 #include <art_map/coordinates.h>
00031 #include <art_map/types.h>
00032
00038 class poly
00039 {
00040 public:
00041
00042
00043
00044 MapXY p1;
00045 MapXY p2;
00046 MapXY p3;
00047 MapXY p4;
00048
00049
00050 float heading;
00051
00052
00053 MapXY midpoint;
00054
00055
00056 float length;
00057
00058 poly_id_t poly_id;
00059
00060 bool is_stop;
00061 bool is_transition;
00062
00063
00064 bool contains_way;
00065
00066 ElementID start_way;
00067 ElementID end_way;
00068
00069 Lane_marking left_boundary;
00070 Lane_marking right_boundary;
00071
00073 poly() {};
00074
00076 poly(const art_msgs::ArtQuadrilateral &msg)
00077 {
00078 p1 = MapXY(msg.poly.points[art_msgs::ArtQuadrilateral::bottom_left]);
00079 p2 = MapXY(msg.poly.points[art_msgs::ArtQuadrilateral::top_left]);
00080 p3 = MapXY(msg.poly.points[art_msgs::ArtQuadrilateral::top_right]);
00081 p4 = MapXY(msg.poly.points[art_msgs::ArtQuadrilateral::bottom_right]);
00082 midpoint = MapXY(msg.midpoint);
00083
00084 heading = msg.heading;
00085 length = msg.length;
00086 poly_id = msg.poly_id;
00087
00088 is_stop = msg.is_stop;
00089 is_transition = msg.is_transition;
00090 contains_way = msg.contains_way;
00091
00092 start_way = ElementID(msg.start_way);
00093 end_way = ElementID(msg.end_way);
00094
00095 left_boundary = Lane_marking(msg.left_boundary.lane_marking);
00096 right_boundary = Lane_marking(msg.right_boundary.lane_marking);
00097 };
00098
00099 void toMsg(art_msgs::ArtQuadrilateral &msg) {
00100 msg.poly.points.resize(art_msgs::ArtQuadrilateral::quad_size);
00101 p1.toMsg(msg.poly.points[art_msgs::ArtQuadrilateral::bottom_left]);
00102 p2.toMsg(msg.poly.points[art_msgs::ArtQuadrilateral::top_left]);
00103 p3.toMsg(msg.poly.points[art_msgs::ArtQuadrilateral::top_right]);
00104 p4.toMsg(msg.poly.points[art_msgs::ArtQuadrilateral::bottom_right]);
00105 midpoint.toMsg(msg.midpoint);
00106
00107 msg.heading = heading;
00108 msg.length = length;
00109 msg.poly_id = poly_id;
00110
00111 msg.is_stop = is_stop;
00112 msg.is_transition = is_transition;
00113 msg.contains_way = contains_way;
00114
00115 msg.start_way = start_way.toMapID();
00116 msg.end_way = end_way.toMapID();
00117
00118 msg.left_boundary.lane_marking = left_boundary;
00119 msg.right_boundary.lane_marking = right_boundary;
00120 }
00121 };
00122
00123 typedef std::vector<poly> poly_list_t;
00124
00125
00126 typedef struct polyUpdate
00127 {
00128 poly_id_t poly_id;
00129 int point_id;
00130 float distance;
00131 float bearing;
00132 float confidence;
00133 } lanes_poly_vision_t;
00134
00135
00141 class PolyOps
00142 {
00143 public:
00144 PolyOps();
00145 ~PolyOps();
00146
00147 int get_waypoint_index(const std::vector<poly> &polys,
00148 const ElementID& waypoint);
00149
00150 int getPolyWayPt(const std::vector<poly> &polys,
00151 const ElementID& waypoint);
00152
00153
00154 void add_polys_for_waypts(const std::vector <poly> &from_polys,
00155 std::vector <poly> &to_polys,
00156 ElementID from_id, ElementID to_id);
00157
00158
00159 void AddTransitionPolys(const std::vector <poly> &from_polys,
00160 std::vector <poly> &to_polys,
00161 WayPointNode way0, WayPointNode way1);
00162
00163
00164
00165 void AddLanePolys(const std::vector <poly> &from_polys,
00166 std::vector <poly> &to_polys, ElementID id);
00167
00168 void AddLanePolys(const std::vector <poly> &from_polys,
00169 std::vector <poly> &to_polys, WayPointNode waypt);
00170
00171
00172
00173 void AddLanePolysEither(const std::vector <poly> &from_polys,
00174 std::vector <poly> &to_polys, WayPointNode waypt,
00175 int direction);
00176
00177
00178
00179 void AddReverseLanePolys(const std::vector <poly> &from_polys,
00180 std::vector <poly> &to_polys, ElementID id);
00181
00182 void AddReverseLanePolys(const std::vector <poly> &from_polys,
00183 std::vector <poly> &to_polys, WayPointNode waypt);
00184
00185
00186 void CollectPolys(const std::vector<poly> &from_polys,
00187 std::vector<poly> &to_polys,
00188 unsigned start, unsigned end);
00189
00190 void CollectPolys(const std::vector<poly> &from_polys,
00191 std::vector<poly> &to_polys,
00192 unsigned start);
00193
00194 void GetPolys(const art_msgs::ArtLanes &lanes, poly_list_t &polyList);
00195
00196 void GetLanes(poly_list_t &polyList, art_msgs::ArtLanes &lanes);
00197
00198
00199
00200
00201 bool LanePoly(const poly &curPoly, ElementID id);
00202
00203 bool LanePoly(const poly &curPoly, WayPointNode waypt);
00204
00205
00206 bool match_waypt_poly(const poly& curPoly, ElementID way0, ElementID way1)
00207 {
00208 return (ElementID(curPoly.start_way) == way0
00209 && ElementID(curPoly.end_way) == way1);
00210 }
00211
00212
00213 bool match_waypt_poly(const poly& curPoly, ElementID way)
00214 {
00215 return (ElementID(curPoly.start_way) == way
00216 && ElementID(curPoly.end_way) == way);
00217 }
00218
00219
00220 bool MatchTransitionPoly(const poly& curPoly,
00221 const WayPointNode& way0,
00222 const WayPointNode& way1);
00223
00224 float PolyHeading(const poly& curPoly);
00225
00226
00227
00228 bool pointInHull(float x, float y, const poly& p)
00229 {
00230 float minx=p.p1.x;
00231 float maxx=p.p1.x;
00232 float miny=p.p1.y;
00233 float maxy=p.p1.y;
00234
00235 minx=fminf(fminf(fminf(minx,p.p2.x),p.p3.x),p.p4.x);
00236 miny=fminf(fminf(fminf(miny,p.p2.y),p.p3.y),p.p4.y);
00237 maxx=fmaxf(fmaxf(fmaxf(maxx,p.p2.x),p.p3.x),p.p4.x);
00238 maxy=fmaxf(fmaxf(fmaxf(maxy,p.p2.y),p.p3.y),p.p4.y);
00239
00240 return (Epsilon::gte(x,minx) && Epsilon::lte(x,maxx) &&
00241 Epsilon::gte(y,miny) && Epsilon::lte(y,maxy));
00242 }
00243
00244 bool pointOnSegment(float x, float y, MapXY p1, MapXY p2)
00245 {
00246 float minx=fminf(p1.x,p2.x);
00247 float miny=fminf(p1.y,p2.y);
00248 float maxx=fmaxf(p1.x,p2.x);
00249 float maxy=fmaxf(p1.y,p2.y);
00250
00251 if (Epsilon::gte(x,minx) && Epsilon::lte(x,maxx) &&
00252 Epsilon::gte(y,miny) && Epsilon::lte(y,maxy))
00253 {
00254 float diffy=p2.y-p1.y;
00255 float diffx=p2.x-p1.x;
00256
00257 float diff2y=y-p1.y;
00258 float diff2x=x-p1.x;
00259
00260 if (Epsilon::equal(diffx,0.0))
00261 return (Epsilon::equal(diff2x,0.0) &&
00262 ((diff2y<0) == (diffy<0)));
00263
00264 if (Epsilon::equal(diff2x,0.0))
00265 return false;
00266
00267 return (Epsilon::equal(diffy/diffx,diff2y/diff2x));
00268 }
00269 return false;
00270
00271 }
00272
00273 bool pointOnEdges(float x, float y, const poly& p)
00274 {
00275 return (pointOnSegment(x, y, MapXY(p.p1), MapXY(p.p2)) ||
00276 pointOnSegment(x, y, MapXY(p.p3), MapXY(p.p2)) ||
00277 pointOnSegment(x, y, MapXY(p.p4), MapXY(p.p3)) ||
00278 pointOnSegment(x, y, MapXY(p.p1), MapXY(p.p4)));
00279 }
00280
00281 bool pointInPoly(float x, float y, const poly& p)
00282 {
00283 if (!pointInHull(x,y,p))
00284 return false;
00285
00286 bool odd = false;
00287
00288
00289
00290 if ((p.p1.y < y && p.p2.y >= y) || (p.p2.y < y && p.p1.y >= y))
00291 if (p.p1.x + (y-p.p1.y)/(p.p2.y-p.p1.y)*(p.p2.x-p.p1.x) < x)
00292 odd = !odd;
00293
00294 if ((p.p2.y < y && p.p3.y >= y) || (p.p3.y < y && p.p2.y >= y))
00295 if (p.p2.x + (y-p.p2.y)/(p.p3.y-p.p2.y)*(p.p3.x-p.p2.x) < x)
00296 odd = !odd;
00297
00298 if ((p.p3.y < y && p.p4.y >= y) || (p.p4.y < y && p.p3.y >= y))
00299 if (p.p3.x + (y-p.p3.y)/(p.p4.y-p.p3.y)*(p.p4.x-p.p3.x) < x)
00300 odd = !odd;
00301
00302 if ((p.p4.y < y && p.p1.y >= y) || (p.p1.y < y && p.p4.y >= y))
00303 if (p.p4.x + (y-p.p4.y)/(p.p1.y-p.p4.y)*(p.p1.x-p.p4.x) < x)
00304 odd = !odd;
00305
00306 if (odd)
00307 return true;
00308
00309 return pointOnEdges(x, y, p);
00310
00311 }
00312
00313 bool pointInPoly(const MapXY& pt, const poly& p)
00314 {
00315 return pointInPoly(pt.x, pt.y, p);
00316 };
00317
00318 bool pointInPoly(const Polar& polar, const MapPose &origin,
00319 const poly &p)
00320 {
00321 return pointInPoly(Coordinates::Polar_to_MapXY(polar, origin), p);
00322 };
00323
00324
00325
00326
00327
00328 bool pointInPoly_ratio(float x, float y, const poly& p, float ratio);
00329 bool pointInPoly_ratio(const MapXY& pt, const poly& p, float ratio)
00330 {
00331 return pointInPoly_ratio(pt.x, pt.y, p, ratio);
00332 };
00333
00334
00335
00336
00337
00338
00339
00340 bool pointNearPoly(double x, double y, const poly& poly, double epsilon)
00341 {
00342 return (getShortestDistToPoly(x, y, poly) < epsilon);
00343 }
00344 bool pointNearPoly(const MapXY& pt, const poly& poly, double epsilon)
00345 {
00346 return (getShortestDistToPoly(pt.x, pt.y, poly) < epsilon);
00347 }
00348
00349
00350
00351
00352
00353
00361 int getContainingPoly(const std::vector<poly> &polys, float x, float y);
00362 int getContainingPoly(const std::vector<poly>& polys, const MapXY& pt)
00363 {
00364 return getContainingPoly(polys, pt.x, pt.y);
00365 };
00366
00367 int getContainingPoly(const std::vector<poly>& polys,
00368 const MapPose &pose)
00369 {
00370 return getContainingPoly(polys, pose.map.x, pose.map.y);
00371 };
00372
00373
00374 poly_id_t getContainingPolyID(const std::vector<poly> &polys,
00375 float x, float y)
00376 {
00377 int index = getContainingPoly(polys, x, y);
00378 if (index < 0)
00379 return -1;
00380 else
00381 return polys[index].poly_id;
00382 };
00383 poly_id_t getContainingPolyID(const std::vector<poly>& polys,
00384 const MapXY& pt)
00385 {
00386 int index = getContainingPoly(polys, pt);
00387 if (index < 0)
00388 return -1;
00389 else
00390 return polys[index].poly_id;
00391 };
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 int getPolyIndex(const std::vector<poly>& polys, const poly& curPoly)
00404 {
00405 int i;
00406 for (i = 0; i < (int) polys.size(); ++i)
00407 {
00408 if (polys.at(i).poly_id == curPoly.poly_id)
00409 return i;
00410 }
00411 return -1;
00412 }
00413
00414
00415 void getRemainingPolys(const std::vector<poly> &from_polys,
00416 std::vector<poly> &to_polys,
00417 const MapXY &point);
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 float getShortestDistToPoly(float x, float y, const poly& p);
00429 float getShortestDistToPoly(MapXY pt, const poly& p)
00430 {
00431 return getShortestDistToPoly(pt.x, pt.y, p);
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441 int getClosestPoly(const std::vector<poly>& polys, float x, float y);
00442 int getClosestPoly(const std::vector<poly>& polys, MapXY pt)
00443 {
00444 return getClosestPoly(polys, pt.x, pt.y);
00445 }
00446 int getClosestPoly(const std::vector<poly>& polys,
00447 const MapPose &pose)
00448 {
00449 return getClosestPoly(polys, pose.map.x, pose.map.y);
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 int getClosestNonTransPoly(const std::vector<poly>& polys, float x, float y);
00466 int getClosestNonTransPoly(const std::vector<poly>& polys, MapXY pt)
00467 {
00468 return getClosestNonTransPoly(polys, pt.x, pt.y);
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 MapXY getPolyEdgeMidpoint(const poly& p);
00491
00492
00493 MapXY centerpoint(const poly& p);
00494
00495
00496 float getLength(const poly& p);
00497
00498
00499
00500
00501
00502
00503
00504 std::vector<poly> getPolysBetweenPoints(const std::vector<poly>& polys,
00505 float x1, float y1,
00506 float x2, float y2);
00507
00508
00509
00510 std::vector<MapXY> getPointsFromPolys(const std::vector<poly>& polys);
00511
00524 int getStartingPoly(const MapPose &pose,
00525 const std::vector<poly>& polygons,
00526 float distance,
00527 float min_heading);
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 float distanceAlongLane(const std::vector<poly>& polygons,
00538 const MapXY& from,
00539 const MapXY& to);
00540
00541 std::pair<float, MapXY>
00542 specialDistanceAlongLane(const std::vector<poly>& polygons,
00543 const MapXY& from,
00544 const MapXY& to);
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 int index_of_downstream_poly(const std::vector<poly>& polygons,
00555 int start_index,
00556 float distance);
00557
00558
00559
00560 float shortestDistToLineSegment(float x, float y, float line_x1,
00561 float line_y1, float line_x2,
00562 float line_y2);
00563
00564
00565 float avgLengthOfPolySides(const poly& p);
00566
00567
00568 std::set<ElementID> getPolyLaneIds(const std::vector<poly>& polys);
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 void getLaneDir(const std::vector<poly>& polys,
00621 std::vector<poly>& to_polys,
00622 const int relative,
00623 const int direction,
00624 const MapPose &pose);
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 void printPolygons(const poly_list_t& polys);
00637
00638
00639 poly_list_t getTransitionPolys(const poly_list_t& polys);
00640
00641
00642
00643
00644
00645
00646
00647 bool isValidPoly(const poly& p);
00648
00649
00650
00651
00652 MapXY GetClosestPointToLine(MapXY A, MapXY B,
00653 MapXY P, bool segmentClamp);
00654
00655 MapXY midpoint(const MapXY& p1, const MapXY& p2);
00656
00657 ElementID getReverseLane(const std::vector<poly>& polys,
00658 const MapPose &pose);
00659
00660
00661 bool left_of_poly(const poly &this_poly, const poly &cur_poly)
00662 {
00663
00664 MapPose cur_pose(cur_poly.midpoint, cur_poly.heading);
00665
00666
00667 float theta = Coordinates::bearing(cur_pose, this_poly.midpoint);
00668 return (theta > 0.0);
00669 }
00670
00671
00672 bool same_direction(const poly &p1, const poly &p2, float angle)
00673 {
00674 return (fabs(Coordinates::normalize(p1.heading - p2.heading)) < angle);
00675 }
00676
00677
00678 void getPolysBetweenWayPts(
00679 const std::vector<poly> &from_polys,
00680 std::vector<poly> &to_polys,
00681 ElementID from_id, ElementID to_id);
00682
00683
00684
00685
00686 std::vector<MapXY> getRoadPerimeterPoints(const std::vector<poly>& polys,
00687 const ElementID way0,
00688 const ElementID way1);
00689
00690 std::vector<MapXY> getRoadPerimeterPoints(const std::vector<poly>& polys,
00691 const ElementID way0);
00692
00693
00694 private:
00695
00696
00697
00698 float distance(float x1, float y1, float x2, float y2);
00699
00700
00701 float length_between_polygons(const std::vector<poly>& polygons,
00702 int index1=-1,
00703 int index2=-1);
00704
00705
00706 };
00707
00708 #endif