00001
00002
00003
00004
00005
00006
00007
00008
00009
00019 #include <float.h>
00020 #include <assert.h>
00021 #include <limits>
00022 #include <iostream>
00023
00024 #include <art/epsilon.h>
00025
00026 #include <art_map/coordinates.h>
00027 #include <art_map/euclidean_distance.h>
00028 #include <art_map/PolyOps.h>
00029
00030
00031
00032
00033 PolyOps::PolyOps()
00034 {
00035
00036 }
00037
00038 PolyOps::~PolyOps()
00039 {
00040
00041 }
00042
00043
00044 bool PolyOps::pointInPoly_ratio(float x, float y, const poly& p, float ratio)
00045 {
00046
00047
00048
00049 float diff=(1-ratio)/2;
00050
00051 MapXY p1=p.p1;
00052 MapXY p2=p.p2;
00053 MapXY p3=p.p3;
00054 MapXY p4=p.p4;
00055
00056 poly newpoly;
00057
00058 newpoly.p1.x=p1.x+(p4.x-p1.x)*diff;
00059 newpoly.p4.x=p1.x+(p4.x-p1.x)*(1-diff);
00060 newpoly.p1.y=p1.y+(p4.y-p1.y)*diff;
00061 newpoly.p4.y=p1.y+(p4.y-p1.y)*(1-diff);
00062
00063 newpoly.p2.x=p2.x+(p3.x-p2.x)*diff;
00064 newpoly.p3.x=p2.x+(p3.x-p2.x)*(1-diff);
00065 newpoly.p2.y=p2.y+(p3.y-p2.y)*diff;
00066 newpoly.p3.y=p2.y+(p3.y-p2.y)*(1-diff);
00067
00068 bool value=pointInPoly(x,y,newpoly);
00069
00070 #if 0
00071 if (value) {
00072 ROS_DEBUG("Point in small poly: original poly: [%f,%f; %f,%f;%f,%f;%f,%f]"
00073 " new poly: [%f,%f; %f,%f;%f,%f;%f,%f] point: [%f,%f]",
00074 p.x1,p.y1,p.x2,p.y2,p.x3,p.y3,p.x4,p.y4,
00075 newpoly.x1,newpoly.y1,newpoly.x2,newpoly.y2,
00076 newpoly.x3,newpoly.y3,newpoly.x4,newpoly.y4,x,y);
00077 }
00078 #endif
00079
00080 return value;
00081
00082 }
00083
00084
00085 int PolyOps::getContainingPoly(const std::vector<poly> &polys,
00086 float x, float y)
00087 {
00088
00089 int pindex;
00090 pindex= getClosestPoly(polys, x, y);
00091
00092 if (pindex < 0)
00093 {
00094 ROS_DEBUG("no polygon contains point (%.3f, %.3f)", x, y);
00095 return -1;
00096 }
00097
00098 poly closest=polys.at(pindex);
00099
00100
00101 if (getShortestDistToPoly(x, y, closest) < Epsilon::distance)
00102 {
00103 return pindex;
00104 }
00105
00106 ROS_DEBUG("no polygon contains point (%.3f, %.3f)", x, y);
00107 return -1;
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 float PolyOps::getShortestDistToPoly(float x, float y, const poly& p)
00132 {
00133 float dist = 0;
00134 float d;
00135
00136
00137 if (pointInPoly(x, y, p))
00138 return dist;
00139
00140
00141
00142
00143 dist = shortestDistToLineSegment(x, y, p.p1.x, p.p1.y, p.p2.x, p.p2.y);
00144
00145 if ( (d = shortestDistToLineSegment(x, y, p.p2.x, p.p2.y, p.p3.x, p.p3.y))
00146 < dist)
00147 dist = d;
00148
00149 if ( (d = shortestDistToLineSegment(x, y, p.p3.x, p.p3.y, p.p4.x, p.p4.y))
00150 < dist)
00151 dist = d;
00152
00153 if ( (d = shortestDistToLineSegment(x, y, p.p4.x, p.p4.y, p.p1.x, p.p1.y))
00154 < dist)
00155 dist = d;
00156
00157 return dist;
00158 }
00159
00160
00161
00162
00163 int PolyOps::getClosestPoly(const std::vector<poly>& polys, float x,
00164 float y)
00165 {
00166 poly p;
00167 float d;
00168 int index = -1;
00169
00170 float min_dist = std::numeric_limits<float>::max();
00171
00172 for (int i = 0; (unsigned)i < polys.size(); i++)
00173 {
00174 p = polys.at(i);
00175 d = getShortestDistToPoly(x, y, p);
00176
00177 if (Epsilon::equal(d,0))
00178 {
00179 index = i;
00180 return index;
00181 }
00182
00183 if (i == 0)
00184 {
00185 min_dist = d;
00186 index = 0;
00187 }
00188
00189 if (d < min_dist)
00190 {
00191 min_dist = d;
00192 index = i;
00193 }
00194 }
00195
00196 return index;
00197 }
00198
00199
00200
00201
00202 int PolyOps::getClosestNonTransPoly(const std::vector<poly>& polys, float x,
00203 float y)
00204 {
00205 poly p;
00206 float d;
00207 int index = -1;
00208
00209 float min_dist = std::numeric_limits<float>::max();
00210
00211 for (int i = 0; (unsigned)i < polys.size(); i++)
00212 {
00213 p = polys.at(i);
00214 if (p.is_transition)
00215 continue;
00216 d = getShortestDistToPoly(x, y, p);
00217
00218 if (Epsilon::equal(d,0))
00219 {
00220 index = i;
00221 return index;
00222 }
00223
00224 if (i == 0)
00225 {
00226 min_dist = d;
00227 index = 0;
00228 }
00229
00230 if (d < min_dist)
00231 {
00232 min_dist = d;
00233 index = i;
00234 }
00235 }
00236
00237 return index;
00238 }
00239
00240 #if 0 //TODO
00241
00242 int PolyOps::getClosestPolyEpsilon(const std::vector<poly>& polys,
00243 const player_pose2d_t& pose, const float epsilon)
00244 {
00245 int index = getClosestPoly(polys, pose);
00246 if (index < 0)
00247 return -1;
00248 if (pointNearPoly(pose, polys.at(index), epsilon))
00249 return index;
00250 else
00251 return -1;
00252 }
00253
00254
00255
00256 int PolyOps::getClosestNonTransPolyEpsilon(const std::vector<poly>& polys,
00257 const player_pose2d_t& pose, const float epsilon)
00258 {
00259 int index = getClosestNonTransPoly(polys, pose);
00260 if (index < 0)
00261 return -1;
00262 if (pointNearPoly(pose, polys.at(index), epsilon))
00263 return index;
00264 else
00265 return -1;
00266 }
00267 #endif
00268
00269 MapXY PolyOps::getPolyEdgeMidpoint(const poly& p)
00270 {
00271 MapXY r;
00272 r.x = (p.p2.x + p.p3.x)/2;
00273 r.y = (p.p2.y + p.p3.y)/2;
00274 return r;
00275 }
00276
00277 MapXY PolyOps::centerpoint(const poly& p)
00278 {
00279 return midpoint(midpoint(p.p1, p.p3) , midpoint(p.p2, p.p4));
00280 }
00281
00282 float PolyOps::getLength(const poly& p)
00283 {
00284 MapXY back=midpoint(p.p1, p.p4);
00285 MapXY front=midpoint(p.p2, p.p3);
00286 float d1 = distance(back.x,back.y,p.midpoint.x,p.midpoint.y);
00287 float d2 = distance(front.x,front.y,p.midpoint.x,p.midpoint.y);
00288 return d1+d2;
00289 }
00290
00291 std::vector<poly>
00292 PolyOps::getPolysBetweenPoints(const std::vector<poly>& polys,
00293 float x1, float y1,
00294 float x2, float y2)
00295 {
00296 std::vector<poly> retPolys;
00297 bool foundFirstPoint = false;
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 int i;
00319 for (i = 0; (unsigned)i < polys.size(); i++)
00320 {
00321 if(pointInPoly(x1, y1, polys.at(i)))
00322 {
00323 foundFirstPoint = true;
00324 break;
00325 }
00326 }
00327
00328 if (!foundFirstPoint)
00329 {
00330 poly p;
00331 i= getClosestPoly(polys, x1, y1);
00332 if (i<0)
00333 return retPolys;
00334 p=polys.at(i);
00335 }
00336
00337 for ( ; (unsigned)i < polys.size(); i++)
00338 {
00339 if(pointInPoly(x2, y2, polys.at(i)))
00340 break;
00341
00342 retPolys.push_back(polys.at(i));
00343 }
00344
00345 return retPolys;
00346 }
00347
00348
00349 void PolyOps::getRemainingPolys(const std::vector<poly> &from_polys,
00350 std::vector<poly> &to_polys,
00351 const MapXY &point)
00352 {
00353 bool found_point = false;
00354
00355
00356 unsigned i;
00357 for (i = 0; i < from_polys.size(); i++)
00358 {
00359 if(pointInPoly(point, from_polys.at(i)))
00360 {
00361 found_point = true;
00362 break;
00363 }
00364 }
00365
00366 if (!found_point)
00367 {
00368
00369 poly p;
00370 int closest = getClosestPoly(from_polys, point);
00371 if (closest < 0)
00372 {
00373
00374 to_polys.clear();
00375 return;
00376 }
00377 i = closest;
00378 }
00379
00380 CollectPolys(from_polys, to_polys, i);
00381 }
00382
00383 std::vector<MapXY> PolyOps::getPointsFromPolys(const std::vector<poly>& polys)
00384 {
00385 std::vector<MapXY> retPoints;
00386
00387 for (int i = 0; (unsigned)i < polys.size(); i++)
00388 {
00389 retPoints.push_back(getPolyEdgeMidpoint(polys.at(i)));
00390 }
00391
00392 return retPoints;
00393 }
00394
00395 float PolyOps::distance(float x1, float y1, float x2, float y2)
00396 {
00397 return Euclidean::DistanceTo(x1,y1,x2,y2);
00398 }
00399
00400 float PolyOps::shortestDistToLineSegment(float x, float y,
00401 float line_x1, float line_y1,
00402 float line_x2, float line_y2)
00403 {
00404 float dist1, dist2;
00405 dist1=dist2=0;
00406
00407 Euclidean::DistanceFromLine(x,y,line_x1,line_y1,line_x2,line_y2,dist1,dist2);
00408 return dist1;
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 }
00441
00442 int PolyOps::get_waypoint_index(const std::vector<poly> &polys,
00443 const ElementID& waypoint)
00444 {
00445
00446 for (unsigned i=0; i<polys.size(); i++)
00447 if (polys.at(i).start_way==waypoint &&
00448 polys.at(i).end_way==waypoint)
00449 return i;
00450
00451 return -1;
00452 }
00453
00454 int PolyOps::getPolyWayPt(const std::vector<poly> &polys,
00455 const ElementID& waypoint) {
00456
00457 for (unsigned i=0; i<polys.size(); i++)
00458 if (polys.at(i).start_way==waypoint)
00459 return i;
00460
00461 return -1;
00462 }
00463
00464
00465
00466
00467
00468
00469 void PolyOps::add_polys_for_waypts(const std::vector <poly> &from_polys,
00470 std::vector <poly> &to_polys,
00471 ElementID from_id, ElementID to_id)
00472 {
00473 if (from_id != to_id)
00474 {
00475 for (unsigned i = 0; i < from_polys.size(); ++i)
00476 if (match_waypt_poly(from_polys.at(i), from_id, to_id))
00477 {
00478 to_polys.push_back(from_polys.at(i));
00479 #define EXTREME_DEBUG 1
00480 #ifdef EXTREME_DEBUG
00481 ROS_DEBUG("adding start, end waypoints %s, %s, poly_id = %d",
00482 to_polys.back().start_way.name().str,
00483 to_polys.back().end_way.name().str,
00484 to_polys.back().poly_id);
00485 #endif
00486 }
00487 }
00488
00489 for (unsigned i = 0; i < from_polys.size(); ++i)
00490 if (match_waypt_poly(from_polys.at(i), to_id))
00491 {
00492 to_polys.push_back(from_polys.at(i));
00493 #ifdef EXTREME_DEBUG
00494 ROS_DEBUG("adding start, end waypoints %s, %s, poly_id = %d",
00495 to_polys.back().start_way.name().str,
00496 to_polys.back().end_way.name().str,
00497 to_polys.back().poly_id);
00498 #endif
00499 break;
00500 }
00501 }
00502
00503
00504 void PolyOps::AddTransitionPolys(const std::vector <poly> &from_polys,
00505 std::vector <poly> &to_polys,
00506 WayPointNode way0, WayPointNode way1)
00507 {
00508 for (unsigned i = 0; i < from_polys.size(); ++i)
00509 {
00510 if (MatchTransitionPoly(from_polys.at(i), way0, way1))
00511 {
00512 to_polys.push_back(from_polys.at(i));
00513 }
00514 }
00515 }
00516
00517
00518
00519 void PolyOps::AddLanePolys(const std::vector <poly> &from_polys,
00520 std::vector <poly> &to_polys, ElementID id)
00521 {
00522 for (unsigned i = 0; i < from_polys.size(); ++i)
00523 {
00524 if (LanePoly(from_polys.at(i), id))
00525 {
00526 to_polys.push_back(from_polys.at(i));
00527 }
00528 }
00529 }
00530
00531
00532
00533 void PolyOps::AddLanePolys(const std::vector <poly> &from_polys,
00534 std::vector <poly> &to_polys, WayPointNode waypt)
00535 {
00536 AddLanePolys(from_polys, to_polys, waypt.id);
00537 }
00538
00539
00540
00541 void PolyOps::AddLanePolysEither(const std::vector <poly> &from_polys,
00542 std::vector <poly> &to_polys, WayPointNode waypt,
00543 int direction)
00544 {
00545 if (direction >= 0)
00546 AddLanePolys(from_polys, to_polys, waypt);
00547 else
00548 AddReverseLanePolys(from_polys, to_polys, waypt);
00549 }
00550
00551
00552
00553 void PolyOps::AddReverseLanePolys(const std::vector <poly> &from_polys,
00554 std::vector <poly> &to_polys, ElementID id)
00555 {
00556
00557 int last = from_polys.size() - 1;
00558 ROS_DEBUG("scanning polygons from %d back to 0", last);
00559 for (int i = last; i >= 0; --i)
00560 {
00561
00562 if (LanePoly(from_polys.at(i), id))
00563 {
00564 to_polys.push_back(from_polys.at(i));
00565 }
00566 }
00567 }
00568
00569
00570
00571 void PolyOps::AddReverseLanePolys(const std::vector <poly> &from_polys,
00572 std::vector <poly> &to_polys, WayPointNode waypt)
00573 {
00574 AddReverseLanePolys(from_polys, to_polys, waypt.id);
00575 }
00576
00577
00578 void PolyOps::CollectPolys(const std::vector<poly> &from_polys,
00579 std::vector<poly> &to_polys,
00580 unsigned start, unsigned end)
00581 {
00582 to_polys.clear();
00583 for (unsigned i = start; i < end; ++i)
00584 to_polys.push_back(from_polys.at(i));
00585 }
00586 void PolyOps::CollectPolys(const std::vector<poly> &from_polys,
00587 std::vector<poly> &to_polys,
00588 unsigned start)
00589 {
00590 CollectPolys(from_polys, to_polys, start, from_polys.size());
00591 }
00592
00593
00594 void PolyOps::GetPolys(const art_msgs::ArtLanes &lanes, poly_list_t &polyList)
00595 {
00596 polyList.resize(lanes.polygons.size());
00597 for (unsigned i = 0; i < lanes.polygons.size(); i++) {
00598 polyList[i] = poly(lanes.polygons[i]);
00599 }
00600 }
00601
00602 void PolyOps::GetLanes(poly_list_t &polyList, art_msgs::ArtLanes &lanes)
00603 {
00604 lanes.polygons.resize(polyList.size());
00605 for (unsigned i = 0; i < polyList.size(); i++) {
00606 polyList[i].toMsg(lanes.polygons[i]);
00607 }
00608 }
00609
00610
00611 bool PolyOps::LanePoly(const poly &curPoly, WayPointNode waypt)
00612 {
00613 return LanePoly(curPoly, waypt.id);
00614 }
00615
00616
00617 bool PolyOps::LanePoly(const poly &curPoly, ElementID id)
00618 {
00619 return (curPoly.start_way.seg == id.seg
00620 && curPoly.start_way.lane == id.lane
00621 && curPoly.end_way.seg == id.seg
00622 && curPoly.end_way.lane == id.lane
00623 && !curPoly.is_transition);
00624 }
00625
00626
00627 bool PolyOps::MatchTransitionPoly(const poly& curPoly,
00628 const WayPointNode& way0,
00629 const WayPointNode& way1)
00630 {
00631 return (curPoly.start_way.same_lane(way0.id) &&
00632 curPoly.end_way.same_lane(way1.id) &&
00633 curPoly.is_transition);
00634 }
00635
00636 float PolyOps::PolyHeading(const poly& curPoly)
00637 {
00638 using Coordinates::bearing;
00639 float left_heading = bearing(curPoly.p1,curPoly.p2);
00640 float right_heading = bearing(curPoly.p4, curPoly.p3);
00641 using Coordinates::normalize;
00642 return normalize(right_heading
00643 + normalize(left_heading - right_heading) / 2.0f);
00644 }
00645
00646 int PolyOps::getStartingPoly(const MapPose &pose,
00647 const std::vector<poly>& polygons,
00648 float distance,
00649 float min_heading)
00650 {
00651 using Coordinates::normalize;
00652
00653
00654 int index = getContainingPoly(polygons, pose.map);
00655 if (index >=0
00656 && (fabs(normalize(polygons.at(index).heading - pose.yaw))
00657 < min_heading))
00658 {
00659 return index;
00660 }
00661
00662
00663 index = getClosestPoly(polygons, pose);
00664 if (index < 0)
00665 {
00666 ROS_WARN_STREAM("none of " << polygons.size()
00667 << " polygons near starting pose");
00668 return index;
00669 }
00670 else if (fabs(normalize(polygons.at(index).heading - pose.yaw))
00671 < min_heading)
00672 {
00673 ROS_DEBUG_STREAM("closest polygon[" << index
00674 << "] has suitable heading");
00675 return index;
00676 }
00677
00678
00679 segment_id_t segment = polygons.at(index).start_way.seg;
00680 ROS_INFO_STREAM("closest polygon[" << index
00681 << "] in segment " << segment);
00682
00683
00684 std::vector<lane_id_t> lanes;
00685
00686 for (uint i=0; i<polygons.size(); i++)
00687 if (polygons.at(i).start_way.seg ==
00688 segment) {
00689 bool lane_found=false;
00690 for (uint j=0;j<lanes.size();j++)
00691 if (lanes.at(j)==polygons.at(i).start_way.lane) {
00692 lane_found=true;
00693 break;
00694 }
00695 if (!lane_found)
00696 lanes.push_back(polygons.at(i).start_way.lane);
00697 }
00698
00699
00700
00701
00702 float mindist = FLT_MAX;
00703 poly minpoly = polygons.at(0);
00704 bool foundd = false;
00705 for (uint i=0; i<lanes.size(); i++)
00706 {
00707 ElementID point(segment,lanes.at(i),0);
00708 WayPointNode waypt;
00709 waypt.id=point;
00710
00711 std::vector<poly> lane_polys;
00712 AddLanePolys(polygons, lane_polys, waypt);
00713 int newind = getClosestPoly(lane_polys, pose);
00714 if (newind < 0)
00715 continue;
00716 float tempdist =
00717 fabs(normalize(lane_polys.at(newind).heading - pose.yaw));
00718 if (tempdist < mindist)
00719 {
00720 mindist = tempdist;
00721 minpoly = lane_polys.at(newind);
00722 foundd=true;
00723 }
00724 }
00725
00726 if (!foundd)
00727 {
00728 ROS_WARN_STREAM("no lane within distance " << distance);
00729 return -1;
00730 }
00731
00732
00733 for (uint i=0; i< polygons.size(); i++)
00734 if (minpoly.poly_id == polygons.at(i).poly_id)
00735 return i;
00736
00737 ROS_WARN("no min polygon found");
00738 return -1;
00739 }
00740
00741 #if 0 //TODO
00742 ElementID
00743 PolyOps::updateLaneLocation(const std::vector<poly>& polygons,
00744 const MapPose& pose,
00745 const WayPointNode& waypt1,
00746 const WayPointNode& waypt2)
00747 {
00748
00749 std::vector<poly> lanes_polys;
00750
00751 for (uint i=0; i< polygons.size(); i++)
00752 if ((polygons.at(i).start_way.seg == waypt1.id.seg &&
00753 polygons.at(i).start_way.lane == waypt1.id.lane &&
00754 polygons.at(i).start_way.pt == waypt1.id.pt)
00755 ||
00756 (polygons.at(i).start_way.seg == waypt2.id.seg &&
00757 polygons.at(i).start_way.lane == waypt2.id.lane &&
00758 polygons.at(i).start_way.pt == waypt2.id.pt))
00759 lanes_polys.push_back(polygons.at(i));
00760
00761 int index=getClosestPoly(lanes_polys,pose.px,pose.py);
00762
00763 if (index >= 0)
00764 return lanes_polys.at(index).start_way;
00765
00766 return waypt1.id;
00767
00768 }
00769 #endif
00770
00771 float PolyOps::length_between_polygons(const std::vector<poly>& polygons,
00772 int index1,
00773 int index2)
00774 {
00775 float length = 0;
00776
00777 index1=std::max(0,index1);
00778 index1=std::min(int(polygons.size()),index1);
00779
00780 index2=std::max(0,index2);
00781 index2=std::min(int(polygons.size()),index2);
00782
00783 for(int i = index1+1; i < index2; i++)
00784 length += polygons.at(i).length;
00785 return length;
00786 }
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 float PolyOps::distanceAlongLane(const std::vector<poly>& polygons,
00801 const MapXY& from,
00802 const MapXY& to)
00803 {
00804 return (specialDistanceAlongLane(polygons, from, to)).first;
00805 }
00806
00807
00808
00809
00810 std::pair<float, MapXY>
00811 PolyOps::specialDistanceAlongLane(const std::vector<poly>& polygons,
00812 const MapXY& from,
00813 const MapXY& to)
00814 {
00815
00816 int index1=getClosestPoly(polygons, from);
00817 int index2=getClosestPoly(polygons, to);
00818
00819 if (index1 == -1 || index2 == -1) {
00820 std::pair<float, MapXY> return_value(0, MapXY());
00821 return return_value;
00822 }
00823
00824 poly poly_start = polygons.at(index1);
00825 poly poly_end = polygons.at(index2);
00826
00827 MapXY start_bisect1=midpoint(poly_start.p1, poly_start.p4);
00828 MapXY start_bisect2=midpoint(poly_start.p2, poly_start.p3);
00829
00830 MapXY end_bisect1=midpoint(poly_end.p1, poly_end.p4);
00831 MapXY end_bisect2=midpoint(poly_end.p2, poly_end.p3);
00832
00833 MapXY start_point=GetClosestPointToLine(start_bisect1,start_bisect2,
00834 from, true);
00835
00836 MapXY end_point=GetClosestPointToLine(end_bisect1,end_bisect2,
00837 to, true);
00838
00839 float distance_start, distance_end, polygon_length;
00840 float tmp;
00841 if (index1 < index2)
00842 {
00843 Euclidean::DistanceFromLine(start_point, poly_start.p2, poly_start.p3,
00844 distance_start, tmp);
00845 Euclidean::DistanceFromLine(end_point, poly_end.p1, poly_end.p4,
00846 distance_end, tmp);
00847 polygon_length = length_between_polygons(polygons, index1, index2);
00848 }
00849 else if (index1 > index2)
00850 {
00851 Euclidean::DistanceFromLine(start_point, poly_start.p1, poly_start.p4,
00852 distance_start, tmp);
00853 Euclidean::DistanceFromLine(end_point, poly_end.p2, poly_end.p3,
00854 distance_end, tmp);
00855 polygon_length = length_between_polygons(polygons, index2, index1);
00856 }
00857 else
00858 {
00859 Euclidean::DistanceFromLine(start_point, poly_start.p1, poly_start.p4,
00860 distance_start, tmp);
00861 distance_start = -distance_start;
00862 Euclidean::DistanceFromLine(end_point, poly_end.p1, poly_end.p4,
00863 distance_end, tmp);
00864 polygon_length = 0;
00865 }
00866
00867 float distance_total = distance_start + polygon_length + distance_end;
00868
00869 if (index1 > index2)
00870 distance_total = -distance_total;
00871
00872 #ifdef EXTREME_DEBUG
00873 ROS_DEBUG("distance_total to (%f, %f) %f )", to.x, to.y, distance_total);
00874 ROS_DEBUG("polygon_length to (%f, %f) %f )", to.x, to.y, polygon_length);
00875 #endif
00876
00877 std::pair<float, MapXY> return_value(distance_total, start_point);
00878 return return_value;
00879 }
00880
00881 int PolyOps::index_of_downstream_poly(const std::vector<poly>& polygons,
00882 int start_index,
00883 float distance)
00884 {
00885 if(start_index < 0 || start_index >= (int)polygons.size())
00886 return -1;
00887
00888 if(distance <= 0)
00889 return start_index;
00890
00891 int index = start_index;
00892 float length_so_far = polygons.at(index).length;
00893 while(distance > length_so_far) {
00894 if(index == (int)polygons.size() - 1)
00895 return index;
00896 index++;
00897 length_so_far += polygons.at(index).length;
00898 }
00899 return index;
00900 }
00901
00902 MapXY PolyOps::midpoint(const MapXY& p1, const MapXY& p2)
00903 {
00904 MapXY mid((p1.x+p2.x)/2.0, (p1.y+p2.y)/2.0);
00905 return mid;
00906 }
00907
00908 float PolyOps::avgLengthOfPolySides(const poly& p)
00909 {
00910 float s12 = Euclidean::DistanceTo(p.p1, p.p2);
00911 float s23 = Euclidean::DistanceTo(p.p2, p.p3);
00912 float s34 = Euclidean::DistanceTo(p.p3, p.p4);
00913 float s41 = Euclidean::DistanceTo(p.p4, p.p1);
00914 return (s12 + s23 + s34 + s41) / 4;
00915 }
00916
00917
00918 std::set<ElementID> PolyOps::getPolyLaneIds(const std::vector<poly>& polys)
00919 {
00920 std::set<ElementID> lane_ids;
00921 lane_ids.clear();
00922 for (uint i = 0; i < polys.size(); ++i) {
00923 lane_ids.insert(ElementID(polys.at(i).start_way.seg,
00924 polys.at(i).start_way.lane, 0));
00925 }
00926 return lane_ids;
00927 }
00928
00929 #if 0 //TODO
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943 ElementID PolyOps::getPolyLaneIdDir(const std::vector<poly>& polys,
00944 const int relative,
00945 const int direction,
00946 const player_pose2d_t& pose,
00947 const float poly_epsilon)
00948 {
00949 int cur_poly_index = getClosestPolyEpsilon(polys, pose, poly_epsilon);
00950 if (cur_poly_index == -1) {
00951 ROS_DEBUG("PolyOps::getPolyLaneIdDir: No poly found");
00952 return ElementID(-1,-1,-1);
00953 }
00954
00955 int adj_poly_index[2];
00956 poly my_cur_poly = polys.at(cur_poly_index);
00957
00958 if (direction == 0)
00959 return ElementID(my_cur_poly.start_way.seg, my_cur_poly.start_way.lane, 0);
00960
00961
00962 ElementID adj_lane[2];
00963 adj_lane[0] = polys.at(cur_poly_index).start_way;
00964 adj_lane[1] = polys.at(cur_poly_index).start_way;
00965 adj_lane[0].lane--;
00966 adj_lane[1].lane++;
00967 poly_list_t adj_lane_polys[2];
00968
00969
00970 for (unsigned i = 0; i < 2; ++i) {
00971 adj_lane[i].pt = 0;
00972 adj_lane_polys[i].clear();
00973
00974 if (adj_lane[i].lane > 0) {
00975
00976
00977 AddLanePolys(polys, adj_lane_polys[i], adj_lane[i]);
00978 if (adj_lane_polys[i].size() == 0 )
00979 continue;
00980
00981
00982 adj_poly_index[i] = getClosestPoly(adj_lane_polys[i],
00983 my_cur_poly.midpoint);
00984 if (adj_poly_index[i] == -1)
00985 continue;
00986 poly my_adj_poly = adj_lane_polys[i].at(adj_poly_index[i]);
00987
00988
00989 MapPose poly_pose(my_cur_poly.midpoint, 0.0);
00990 if (relative == 0)
00991 poly_pose.yaw = my_cur_poly.heading;
00992 else if (relative == 1)
00993 poly_pose.yaw = pose.pa;
00994 float theta = Coordinates::bearing(poly_pose, my_adj_poly.midpoint);
00995
00996 if ( (theta > 0 && direction == +1) ||
00997 (theta < 0 && direction == -1) )
00998 return ElementID(my_adj_poly.start_way.seg,
00999 my_adj_poly.start_way.lane, 0);
01000 else;
01001
01002 }
01003 }
01004
01005 ROS_DEBUG("Error: lane must not exist this direction");
01006 return ElementID();
01007 }
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022 ElementID PolyOps::getNonTransPolyLaneIdDir(const poly_list_t& polys,
01023 const int relative,
01024 const int direction,
01025 const player_pose2d_t& pose,
01026 const float poly_epsilon)
01027 {
01028 int cur_poly_index = getClosestNonTransPolyEpsilon(polys, pose, poly_epsilon);
01029 if (cur_poly_index == -1) {
01030 ROS_DEBUG("PolyOps::getNonTransPolyLaneIdDir: No poly found");
01031 return ElementID(-1,-1,-1);
01032 }
01033
01034 int adj_poly_index[2];
01035 poly my_cur_poly = polys.at(cur_poly_index);
01036
01037 if (direction == 0)
01038 return ElementID(my_cur_poly.start_way.seg, my_cur_poly.start_way.lane, 0);
01039
01040
01041 ElementID adj_lane[2];
01042 adj_lane[0] = polys.at(cur_poly_index).start_way;
01043 adj_lane[1] = polys.at(cur_poly_index).start_way;
01044 adj_lane[0].lane--;
01045 adj_lane[1].lane++;
01046 poly_list_t adj_lane_polys[2];
01047
01048
01049 for (unsigned i = 0; i < 2; ++i) {
01050 adj_lane[i].pt = 0;
01051 adj_lane_polys[i].clear();
01052
01053 if (adj_lane[i].lane > 0) {
01054
01055
01056 AddLanePolys(polys, adj_lane_polys[i], adj_lane[i]);
01057 if (adj_lane_polys[i].size() == 0 )
01058 continue;
01059
01060
01061 adj_poly_index[i] = getClosestNonTransPoly(adj_lane_polys[i],
01062 my_cur_poly.midpoint);
01063 if (adj_poly_index[i] == -1)
01064 continue;
01065 poly my_adj_poly = adj_lane_polys[i].at(adj_poly_index[i]);
01066
01067
01068 MapPose poly_pose(my_cur_poly.midpoint, 0.0);
01069 if (relative == 0)
01070 poly_pose.yaw = my_cur_poly.heading;
01071 else if (relative == 1)
01072 poly_pose.yaw = pose.pa;
01073 float theta = Coordinates::bearing(poly_pose, my_adj_poly.midpoint);
01074
01075 if ( (theta > 0 && direction == +1) ||
01076 (theta < 0 && direction == -1) )
01077 return ElementID(my_adj_poly.start_way.seg,
01078 my_adj_poly.start_way.lane, 0);
01079 else;
01080
01081 }
01082 }
01083 ROS_DEBUG("Error: lane must not exist this direction");
01084 return ElementID(-1,-1,-1);
01085
01086 }
01087 #endif
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100 void PolyOps::getLaneDir(const std::vector<poly>& polys,
01101 std::vector<poly>& to_polys,
01102 const int relative,
01103 const int direction,
01104 const MapPose &pose)
01105 {
01106
01107 to_polys.clear();
01108
01109 int cur_poly_index = getClosestPoly(polys, pose);
01110 if (cur_poly_index == -1) {
01111 ROS_DEBUG("PolyOps::getLaneDir: No poly found");
01112 return;
01113 }
01114 int adj_poly_index[2];
01115 poly my_cur_poly = polys.at(cur_poly_index);
01116
01117 if (direction == 0) {
01118 AddLanePolys(polys, to_polys, my_cur_poly.start_way);
01119 return;
01120 }
01121
01122
01123 ElementID adj_lane[2];
01124 adj_lane[0] = polys.at(cur_poly_index).start_way;
01125 adj_lane[1] = polys.at(cur_poly_index).start_way;
01126 adj_lane[0].lane--;
01127 adj_lane[1].lane++;
01128 poly_list_t adj_lane_polys[2];
01129
01130
01131 for (unsigned i = 0; i < 2; ++i) {
01132 adj_lane[i].pt = 0;
01133 adj_lane_polys[i].clear();
01134
01135 if (adj_lane[i].lane > 0) {
01136
01137
01138 AddLanePolys(polys, adj_lane_polys[i], adj_lane[i]);
01139 if (adj_lane_polys[i].size() == 0 )
01140 continue;
01141
01142
01143 adj_poly_index[i] = getClosestPoly(adj_lane_polys[i],
01144 my_cur_poly.midpoint);
01145 if (adj_poly_index[i] == -1)
01146 continue;
01147 poly my_adj_poly = adj_lane_polys[i].at(adj_poly_index[i]);
01148
01149
01150 MapPose poly_pose(my_cur_poly.midpoint, 0.0);
01151 if (relative == 0)
01152 poly_pose.yaw = my_cur_poly.heading;
01153 else if (relative == 1)
01154 poly_pose.yaw = pose.yaw;
01155 float theta = Coordinates::bearing(poly_pose, my_adj_poly.midpoint);
01156
01157 if ( (theta > 0 && direction == +1) ||
01158 (theta < 0 && direction == -1) )
01159 {
01160 CollectPolys(adj_lane_polys[i], to_polys, 0);
01161 return;
01162 }
01163
01164
01165 }
01166 }
01167 ROS_DEBUG("Error: lane must not exist this direction");
01168 }
01169
01170 #if 0 //TODO
01171
01172
01173 void PolyOps::getNumLanesDir(const std::vector<poly>& polys,
01174 std::vector<poly>& to_polys,
01175 const int relative,
01176 const int direction,
01177 const player_pose2d_t &pose,
01178 const unsigned num_lanes)
01179 {
01180 int poly_index;
01181 player_pose2d_t my_pose = pose;
01182 poly_list_t dir_polys;
01183 to_polys.clear();
01184 for (unsigned i = 0; i < num_lanes; i++) {
01185 getLaneDir(polys, dir_polys, relative, direction, my_pose);
01186 poly_index = getClosestPoly(dir_polys, my_pose);
01187 if (poly_index < 0)
01188 return;
01189 AddLanePolys(dir_polys, to_polys, dir_polys.at(poly_index).start_way);
01190 my_pose.px = dir_polys.at(poly_index).midpoint.x;
01191 my_pose.py = dir_polys.at(poly_index).midpoint.y;
01192 }
01193 if (to_polys.size() == 0)
01194 ROS_DEBUG("no lanes in given direction when expected");
01195 }
01196 #endif
01197
01198 ElementID PolyOps::getReverseLane(const std::vector<poly>& polys,
01199 const MapPose &pose)
01200 {
01201 poly_list_t to_polys;
01202
01203 ElementID return_id;
01204
01205 int base_index = getClosestPoly(polys, pose);
01206 if (base_index < 0)
01207 return return_id;
01208
01209 float base_heading=polys.at(base_index).heading;
01210 MapPose my_pose = pose;
01211
01212 while (true)
01213 {
01214 getLaneDir(polys,to_polys,0,+1,my_pose);
01215 int poly_index = getClosestPoly(to_polys, my_pose);
01216 if (poly_index < 0)
01217 break;
01218 float lane_heading=to_polys.at(poly_index).heading;
01219 if (fabs(Coordinates::normalize(lane_heading - base_heading)) > HALFPI)
01220 return to_polys.at(poly_index).end_way;
01221 my_pose.map.x = to_polys.at(poly_index).midpoint.x;
01222 my_pose.map.y = to_polys.at(poly_index).midpoint.y;
01223 }
01224 return return_id;
01225 }
01226
01227
01228 void PolyOps::printPolygons(const poly_list_t& polys)
01229 {
01230 for (uint i = 0; i < polys.size(); ++i) {
01231 poly p = polys.at(i);
01232 ROS_INFO("poly: %d S/T/CW: %d/%d/%d start: %d.%d.%d "
01233 "end: %d.%d.%d mp: %f,%f",
01234 p.poly_id, p.is_stop, p.is_transition, p.contains_way,
01235 p.start_way.seg, p.start_way.lane, p.start_way.pt,
01236 p.end_way.seg, p.end_way.lane, p.end_way.pt,
01237 p.midpoint.x, p.midpoint.y);
01238 }
01239 }
01240
01241
01242 poly_list_t PolyOps::getTransitionPolys(const poly_list_t& polys) {
01243 poly_list_t tran_polys;
01244 for (uint i = 0; i < polys.size(); ++i)
01245 if (polys.at(i).is_transition)
01246 tran_polys.push_back(polys.at(i));
01247 return tran_polys;
01248 }
01249
01250 #if 0 //TODO
01251
01252 poly PolyOps::getClosestPolyInLane(const std::vector<poly>& polys,
01253 const player_pose2d_t& pose,
01254 const ElementID id)
01255 {
01256 std::vector<poly> lane_polys;
01257 AddLanePolys(polys, lane_polys, id);
01258 int poly_index = getClosestPoly(lane_polys, pose);
01259 if (poly_index == -1) {
01260 poly null_poly;
01261 null_poly.poly_id = -1;
01262 return null_poly;
01263 }
01264 else
01265 return lane_polys.at(poly_index);
01266 }
01267 #endif
01268
01269
01270 bool PolyOps::isValidPoly(const poly& p)
01271 {
01272 if (p.poly_id == -1)
01273 return false;
01274 else
01275 return true;
01276 }
01277
01278 #if 0 //TODO
01279
01280 bool PolyOps::travelingCorrectDir(const poly& p, const player_pose2d_t& pose)
01281 {
01282 float theta = Coordinates::normalize(pose.pa - p.heading);
01283 if (fabs(theta) < HALFPI)
01284 return true;
01285 else
01286 return false;
01287 }
01288 #endif
01289
01290 MapXY PolyOps::GetClosestPointToLine(MapXY A, MapXY B,
01291 MapXY P, bool segmentClamp)
01292
01293
01294 {
01295 MapXY AP = P - A;
01296 MapXY AB = B - A;
01297 float ab2 = AB.x*AB.x + AB.y*AB.y;
01298 float ap_ab = AP.x*AB.x + AP.y*AB.y;
01299 float t = ap_ab / ab2;
01300 if (segmentClamp)
01301 {
01302 if (t < 0.0f)
01303 t = 0.0f;
01304 else if (t > 1.0f)
01305 t = 1.0f;
01306 }
01307 AB.x*=t;
01308 AB.y*=t;
01309
01310 MapXY Closest = A + AB;
01311 return Closest;
01312 }
01313
01314
01315 void PolyOps::getPolysBetweenWayPts(const std::vector<poly> &from_polys,
01316 std::vector<poly> &to_polys,
01317 ElementID from_id, ElementID to_id)
01318 {
01319
01320 to_polys.clear();
01321
01322 if (!from_id.valid() or !to_id.valid()) {
01323 ROS_DEBUG("points not valid");
01324 return;
01325 }
01326
01327 if (!from_id.same_lane(to_id)) {
01328 ROS_DEBUG("points not in same lane");
01329 return;
01330 }
01331
01332 int from_index = -1;
01333
01334 for (uint i = 0; i < from_polys.size(); ++i) {
01335 if (from_polys.at(i).start_way.pt == from_id.pt) {
01336 from_index = i;
01337 break;
01338 }
01339 }
01340
01341
01342 if (from_index == -1)
01343 return;
01344
01345
01346 for (uint i = from_index; i < from_polys.size(); ++i) {
01347 if (from_polys.at(i).start_way.pt < to_id.pt)
01348 to_polys.push_back(from_polys.at(i));
01349 }
01350
01351 }
01352
01353
01354
01355
01356 std::vector<MapXY> PolyOps::getRoadPerimeterPoints(
01357 const std::vector<poly>& polys,
01358 const ElementID way0, const ElementID way1)
01359 {
01360
01361 std::vector<poly> all_polys_in_curr_lane;
01362 std::vector<poly> all_polys_in_left_lane;
01363 std::vector<poly> polys_in_curr_lane_forward;
01364 std::vector<poly> polys_in_left_lane_reverse;
01365
01366 std::vector<MapXY> perim_points;
01367 perim_points.clear();
01368
01369
01370 if (!way0.valid() or !way1.valid() or polys.empty() or (way1 < way0))
01371 return perim_points;
01372
01373
01374 int p_idx_way0 = get_waypoint_index(polys, way0);
01375 if (p_idx_way0 < 0)
01376 return perim_points;
01377 poly way0_poly = polys.at(p_idx_way0);
01378
01379 MapPose way0_pose(way0_poly.midpoint, way0_poly.heading);
01380
01381
01382 int p_idx_way1 = get_waypoint_index(polys, way1);
01383 if (p_idx_way1 < 0)
01384 return perim_points;
01385 poly way1_poly = polys.at(p_idx_way1);
01386
01387 MapPose way1_pose(way1_poly.midpoint, way1_poly.heading);
01388
01389
01390 getLaneDir(polys, all_polys_in_curr_lane, 0, 0, way0_pose);
01391
01392 int way0_pi = getPolyIndex(all_polys_in_curr_lane, way0_poly);
01393 int way1_pi = getPolyIndex(all_polys_in_curr_lane, way1_poly);
01394 CollectPolys(all_polys_in_curr_lane, polys_in_curr_lane_forward,
01395 way0_pi, way1_pi);
01396
01397
01398 getLaneDir(polys, all_polys_in_left_lane, 0, +1, way0_pose);
01399 int ll_way0_pi = getClosestPoly(all_polys_in_left_lane, way0_pose);
01400 if (ll_way0_pi < 0) {
01401 ROS_DEBUG("no poly found 0");
01402 return perim_points;
01403 }
01404 int ll_way1_pi = getClosestPoly(all_polys_in_left_lane, way1_pose);
01405 if (ll_way1_pi < 0) {
01406 ROS_DEBUG("no poly found 1");
01407 return perim_points;
01408 }
01409 poly ll_way0_poly = all_polys_in_left_lane.at(ll_way0_pi);
01410 poly ll_way1_poly = all_polys_in_left_lane.at(ll_way1_pi);
01411
01412 ll_way0_pi = getPolyIndex(all_polys_in_left_lane, ll_way0_poly);
01413 ll_way1_pi = getPolyIndex(all_polys_in_left_lane, ll_way1_poly);
01414 CollectPolys(all_polys_in_left_lane, polys_in_left_lane_reverse,
01415 ll_way1_pi, ll_way0_pi);
01416
01417
01418 for (uint i = 0; i < polys_in_curr_lane_forward.size(); ++i) {
01419 perim_points.push_back(polys_in_curr_lane_forward.at(i).p4);
01420 }
01421 if (polys_in_curr_lane_forward.size() > 0)
01422 perim_points.push_back(polys_in_curr_lane_forward.back().p3);
01423
01424
01425 for (uint i = 0; i < polys_in_left_lane_reverse.size(); ++i) {
01426 perim_points.push_back(polys_in_left_lane_reverse.at(i).p2);
01427 }
01428 if (polys_in_left_lane_reverse.size() > 0)
01429 perim_points.push_back(polys_in_left_lane_reverse.back().p1);
01430
01431 return perim_points;
01432
01433 }
01434
01435 std::vector<MapXY> PolyOps::getRoadPerimeterPoints(
01436 const std::vector<poly>& polys,
01437 const ElementID way0)
01438 {
01439
01440 ElementID way1;
01441 std::vector<poly> all_polys_in_curr_lane;
01442 std::vector<poly> all_polys_in_left_lane;
01443 std::vector<poly> polys_in_curr_lane_forward;
01444 std::vector<poly> polys_in_left_lane_reverse;
01445
01446 std::vector<MapXY> perim_points;
01447 perim_points.clear();
01448
01449
01450 if (!way0.valid() or polys.empty())
01451 return perim_points;
01452
01453
01454 int p_idx_way0 = get_waypoint_index(polys, way0);
01455 if (p_idx_way0 < 0)
01456 return perim_points;
01457 poly way0_poly = polys.at(p_idx_way0);
01458
01459 MapPose way0_pose(way0_poly.midpoint, way0_poly.heading);
01460
01461
01462 getLaneDir(polys, all_polys_in_curr_lane, 0, 0, way0_pose);
01463
01464
01465
01466 for (uint i = 0; i < all_polys_in_curr_lane.size(); ++i) {
01467 if (all_polys_in_curr_lane.at(i).is_stop and
01468 all_polys_in_curr_lane.at(i).start_way > way0) {
01469 way1 = all_polys_in_curr_lane.at(i).start_way;
01470 break;
01471 }
01472 if (i == all_polys_in_curr_lane.size()-1)
01473 way1 = all_polys_in_curr_lane.at(i).start_way;
01474 }
01475
01476
01477 if (!way1.valid())
01478 return perim_points;
01479
01480
01481 int p_idx_way1 = get_waypoint_index(polys, way1);
01482 if (p_idx_way1 < 0)
01483 return perim_points;
01484 poly way1_poly = polys.at(p_idx_way1);
01485
01486 MapPose way1_pose(way1_poly.midpoint, way1_poly.heading);
01487
01488
01489 int way0_pi = getPolyIndex(all_polys_in_curr_lane, way0_poly);
01490 int way1_pi = getPolyIndex(all_polys_in_curr_lane, way1_poly);
01491 CollectPolys(all_polys_in_curr_lane, polys_in_curr_lane_forward,
01492 way0_pi, way1_pi);
01493
01494
01495 getLaneDir(polys, all_polys_in_left_lane, 0, +1, way0_pose);
01496 int ll_way0_pi = getClosestPoly(all_polys_in_left_lane, way0_pose);
01497 if (ll_way0_pi < 0) {
01498 ROS_DEBUG("no poly found 0");
01499 return perim_points;
01500 }
01501 int ll_way1_pi = getClosestPoly(all_polys_in_left_lane, way1_pose);
01502 if (ll_way1_pi < 0) {
01503 ROS_DEBUG("no poly found 1");
01504 return perim_points;
01505 }
01506 poly ll_way0_poly = all_polys_in_left_lane.at(ll_way0_pi);
01507 poly ll_way1_poly = all_polys_in_left_lane.at(ll_way1_pi);
01508
01509 ll_way0_pi = getPolyIndex(all_polys_in_left_lane, ll_way0_poly);
01510 ll_way1_pi = getPolyIndex(all_polys_in_left_lane, ll_way1_poly);
01511 CollectPolys(all_polys_in_left_lane, polys_in_left_lane_reverse,
01512 ll_way1_pi, ll_way0_pi);
01513
01514
01515 for (uint i = 0; i < polys_in_curr_lane_forward.size(); ++i) {
01516 perim_points.push_back(polys_in_curr_lane_forward.at(i).p4);
01517 }
01518 if (polys_in_curr_lane_forward.size() > 0)
01519 perim_points.push_back(polys_in_curr_lane_forward.back().p3);
01520
01521
01522 for (uint i = 0; i < polys_in_left_lane_reverse.size(); ++i) {
01523 perim_points.push_back(polys_in_left_lane_reverse.at(i).p2);
01524 }
01525 if (polys_in_left_lane_reverse.size() > 0)
01526 perim_points.push_back(polys_in_left_lane_reverse.back().p1);
01527
01528 return perim_points;
01529
01530 }