Apollo 10.0
自动驾驶开放平台
path.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <algorithm>
20#include <limits>
21#include <unordered_map>
22
23#include "absl/strings/str_cat.h"
24#include "absl/strings/str_join.h"
25
26#include "cyber/common/log.h"
31
32namespace apollo {
33namespace hdmap {
34
41using std::placeholders::_1;
42
43namespace {
44
45const double kSampleDistance = 0.25;
46
47bool FindLaneSegment(const MapPathPoint& p1, const MapPathPoint& p2,
48 LaneSegment* const lane_segment) {
49 for (const auto& wp1 : p1.lane_waypoints()) {
50 if (nullptr == wp1.lane) {
51 continue;
52 }
53 for (const auto& wp2 : p2.lane_waypoints()) {
54 if (nullptr == wp2.lane) {
55 continue;
56 }
57 if (wp1.lane->id().id() == wp2.lane->id().id() && wp1.s < wp2.s) {
58 *lane_segment = LaneSegment(wp1.lane, wp1.s, wp2.s);
59 return true;
60 }
61 }
62 }
63 return false;
64}
65
66} // namespace
67
68std::string LaneWaypoint::DebugString() const {
69 if (lane == nullptr) {
70 return "(lane is null)";
71 }
72 return absl::StrCat("id = ", lane->id().id(), " s = ", s);
73}
74
76 if (!waypoint.lane) {
78 }
79 for (const auto& type :
80 waypoint.lane->lane().left_boundary().boundary_type()) {
81 if (type.s() <= waypoint.s) {
82 if (type.types_size() > 0) {
83 return type.types(0);
84 } else {
86 }
87 }
88 }
90}
91
93 if (!waypoint.lane) {
95 }
96 for (const auto& type :
97 waypoint.lane->lane().right_boundary().boundary_type()) {
98 if (type.s() <= waypoint.s) {
99 if (type.types_size() > 0) {
100 return type.types(0);
101 } else {
103 }
104 }
105 }
107}
108
110 LaneWaypoint neighbor;
111 if (!waypoint.lane) {
112 return neighbor;
113 }
114 auto point = waypoint.lane->GetSmoothPoint(waypoint.s);
115 auto map_ptr = HDMapUtil::BaseMapPtr();
116 CHECK_NOTNULL(map_ptr);
117 for (const auto& lane_id :
118 waypoint.lane->lane().left_neighbor_forward_lane_id()) {
119 auto lane = map_ptr->GetLaneById(lane_id);
120 if (!lane) {
121 return neighbor;
122 }
123 double s = 0.0;
124 double l = 0.0;
125 if (!lane->GetProjection({point.x(), point.y()}, &s, &l)) {
126 continue;
127 }
128
129 if (s < -kSampleDistance || s > lane->total_length() + kSampleDistance) {
130 continue;
131 } else {
132 return LaneWaypoint(lane, s);
133 }
134 }
135 return neighbor;
136}
137
138void LaneSegment::Join(std::vector<LaneSegment>* segments) {
139 static constexpr double kSegmentDelta = 0.5;
140 std::size_t k = 0;
141 std::size_t i = 0;
142 while (i < segments->size()) {
143 std::size_t j = i;
144 while (j + 1 < segments->size() &&
145 segments->at(i).lane == segments->at(j + 1).lane) {
146 ++j;
147 }
148 auto& segment_k = segments->at(k);
149 segment_k.lane = segments->at(i).lane;
150 segment_k.start_s = segments->at(i).start_s;
151 segment_k.end_s = segments->at(j).end_s;
152 if (segment_k.start_s < kSegmentDelta) {
153 segment_k.start_s = 0.0;
154 }
155 if (segment_k.end_s + kSegmentDelta >= segment_k.lane->total_length()) {
156 segment_k.end_s = segment_k.lane->total_length();
157 }
158 i = j + 1;
159 ++k;
160 }
161 segments->resize(k);
162 segments->shrink_to_fit(); // release memory
163}
164
166 LaneWaypoint neighbor;
167 if (!waypoint.lane) {
168 return neighbor;
169 }
170 auto point = waypoint.lane->GetSmoothPoint(waypoint.s);
171 auto map_ptr = HDMapUtil::BaseMapPtr();
172 CHECK_NOTNULL(map_ptr);
173 for (const auto& lane_id :
174 waypoint.lane->lane().right_neighbor_forward_lane_id()) {
175 auto lane = map_ptr->GetLaneById(lane_id);
176 if (!lane) {
177 return neighbor;
178 }
179 double s = 0.0;
180 double l = 0.0;
181 if (!lane->GetProjection({point.x(), point.y()}, &s, &l)) {
182 continue;
183 }
184 if (s < -kSampleDistance || s > lane->total_length() + kSampleDistance) {
185 continue;
186 } else {
187 return LaneWaypoint(lane, s);
188 }
189 }
190 return neighbor;
191}
192
193std::string LaneSegment::DebugString() const {
194 if (lane == nullptr) {
195 return "(lane is null)";
196 }
197 return absl::StrCat("id = ", lane->id().id(), " start_s = ", start_s,
198 " end_s = ", end_s);
199}
200
201std::vector<MapPathPoint> MapPathPoint::GetPointsFromSegment(
202 const LaneSegment& segment) {
203 return GetPointsFromLane(segment.lane, segment.start_s, segment.end_s);
204}
205
207 const double start_s,
208 const double end_s) {
209 std::vector<MapPathPoint> points;
210 if (start_s >= end_s) {
211 return points;
212 }
213 double accumulate_s = 0.0;
214 for (size_t i = 0; i < lane->points().size(); ++i) {
215 if (accumulate_s >= start_s && accumulate_s <= end_s) {
216 points.emplace_back(lane->points()[i], lane->headings()[i],
217 LaneWaypoint(lane, accumulate_s));
218 }
219 if (i < lane->segments().size()) {
220 const auto& segment = lane->segments()[i];
221 const double next_accumulate_s = accumulate_s + segment.length();
222 if (start_s > accumulate_s && start_s < next_accumulate_s) {
223 points.emplace_back(segment.start() + segment.unit_direction() *
224 (start_s - accumulate_s),
225 lane->headings()[i], LaneWaypoint(lane, start_s));
226 }
227 if (end_s > accumulate_s && end_s < next_accumulate_s) {
228 points.emplace_back(
229 segment.start() + segment.unit_direction() * (end_s - accumulate_s),
230 lane->headings()[i], LaneWaypoint(lane, end_s));
231 }
232 accumulate_s = next_accumulate_s;
233 }
234 if (accumulate_s > end_s) {
235 break;
236 }
237 }
238 return points;
239}
240
241void MapPathPoint::RemoveDuplicates(std::vector<MapPathPoint>* points) {
242 static constexpr double kDuplicatedPointsEpsilon = 1e-7;
243 static constexpr double limit =
244 kDuplicatedPointsEpsilon * kDuplicatedPointsEpsilon;
245 CHECK_NOTNULL(points);
246 int count = 0;
247 for (size_t i = 0; i < points->size(); ++i) {
248 if (count == 0 ||
249 (*points)[i].DistanceSquareTo((*points)[count - 1]) > limit) {
250 (*points)[count++] = (*points)[i];
251 } else {
252 (*points)[count - 1].add_lane_waypoints((*points)[i].lane_waypoints());
253 }
254 }
255 points->resize(count);
256}
257
258std::string MapPathPoint::DebugString() const {
259 return absl::StrCat(
260 "x = ", x_, " y = ", y_, " heading = ", heading_,
261 " lwp = "
262 "{(",
263 absl::StrJoin(lane_waypoints_, "), (", DebugStringFormatter()), ")}");
264}
265
266std::string Path::DebugString() const {
267 return absl::StrCat(
268 "num_points = ", num_points_,
269 " points = "
270 "{(",
271 absl::StrJoin(path_points_, "), (", DebugStringFormatter()),
272 ")} "
273 "numlane_segments_ = ",
274 lane_segments_.size(),
275 " lane_segments = "
276 "{(",
277 absl::StrJoin(lane_segments_, "), (", DebugStringFormatter()), ")}");
278}
279
280std::string PathOverlap::DebugString() const {
281 return absl::StrCat(object_id, " ", start_s, " ", end_s);
282}
283
284Path::Path(const std::vector<MapPathPoint>& path_points)
285 : path_points_(path_points) {
286 Init();
287}
288
289Path::Path(std::vector<MapPathPoint>&& path_points)
290 : path_points_(std::move(path_points)) {
291 Init();
292}
293
294Path::Path(const std::vector<MapPathPoint>& path_points,
295 const std::vector<LaneSegment>& lane_segments)
296 : path_points_(path_points), lane_segments_(lane_segments) {
297 Init();
298}
299
300Path::Path(std::vector<MapPathPoint>&& path_points,
301 std::vector<LaneSegment>&& lane_segments)
302 : path_points_(std::move(path_points)),
303 lane_segments_(std::move(lane_segments)) {
304 Init();
305}
306
307Path::Path(const std::vector<MapPathPoint>& path_points,
308 const std::vector<LaneSegment>& lane_segments,
309 const double max_approximation_error)
310 : path_points_(path_points), lane_segments_(lane_segments) {
311 Init();
312 if (max_approximation_error > 0.0) {
314 approximation_ = PathApproximation(*this, max_approximation_error);
315 }
316}
317
318Path::Path(const std::vector<LaneSegment>& segments)
319 : lane_segments_(segments) {
320 for (const auto& segment : lane_segments_) {
321 const auto points = MapPathPoint::GetPointsFromLane(
322 segment.lane, segment.start_s, segment.end_s);
323 path_points_.insert(path_points_.end(), points.begin(), points.end());
324 }
326 CHECK_GE(path_points_.size(), 2U);
327 Init();
328}
329
330Path::Path(std::vector<LaneSegment>&& segments)
331 : lane_segments_(std::move(segments)) {
332 for (const auto& segment : lane_segments_) {
333 const auto points = MapPathPoint::GetPointsFromLane(
334 segment.lane, segment.start_s, segment.end_s);
335 path_points_.insert(path_points_.end(), points.begin(), points.end());
336 }
338 CHECK_GE(path_points_.size(), 2U);
339 Init();
340}
341
342Path::Path(std::vector<MapPathPoint>&& path_points,
343 std::vector<LaneSegment>&& lane_segments,
344 const double max_approximation_error)
345 : path_points_(std::move(path_points)),
346 lane_segments_(std::move(lane_segments)) {
347 Init();
348 if (max_approximation_error > 0.0) {
350 approximation_ = PathApproximation(*this, max_approximation_error);
351 }
352}
353
355 InitPoints();
358 InitWidth();
359 InitOverlaps();
360}
361
363 num_points_ = static_cast<int>(path_points_.size());
364 CHECK_GE(num_points_, 2);
365
366 accumulated_s_.clear();
368 segments_.clear();
369 segments_.reserve(num_points_);
370 unit_directions_.clear();
372 double s = 0.0;
373 for (int i = 0; i < num_points_; ++i) {
374 accumulated_s_.push_back(s);
375 Vec2d heading;
376 if (i + 1 >= num_points_) {
377 heading = path_points_[i] - path_points_[i - 1];
378 heading.Normalize();
379 } else {
380 segments_.emplace_back(path_points_[i], path_points_[i + 1]);
381 heading = path_points_[i + 1] - path_points_[i];
382 float heading_length = heading.Length();
383 // TODO(All): use heading.length when all adjacent lanes are guarantee to
384 // be connected.
385 s += heading_length;
386 // Normalize "heading".
387 if (heading_length > 0.0) {
388 heading /= heading_length;
389 }
390 }
391 unit_directions_.push_back(heading);
392 }
393 length_ = s;
394 num_sample_points_ = static_cast<int>(length_ / kSampleDistance) + 1;
396
397 CHECK_EQ(accumulated_s_.size(), static_cast<size_t>(num_points_));
398 CHECK_EQ(unit_directions_.size(), static_cast<size_t>(num_points_));
399 CHECK_EQ(segments_.size(), static_cast<size_t>(num_segments_));
400}
401
403 if (lane_segments_.empty()) {
404 for (int i = 0; i + 1 < num_points_; ++i) {
405 LaneSegment lane_segment;
406 if (FindLaneSegment(path_points_[i], path_points_[i + 1],
407 &lane_segment)) {
408 lane_segments_.push_back(lane_segment);
409 }
410 }
411 }
413 if (lane_segments_.empty()) {
414 return;
415 }
416 lane_accumulated_s_.resize(lane_segments_.size());
417 lane_accumulated_s_[0] = lane_segments_[0].Length();
418 for (std::size_t i = 1; i < lane_segments_.size(); ++i) {
420 lane_accumulated_s_[i - 1] + lane_segments_[i].Length();
421 }
422
425 for (int i = 0; i + 1 < num_points_; ++i) {
426 LaneSegment lane_segment;
427 if (FindLaneSegment(path_points_[i], path_points_[i + 1], &lane_segment)) {
428 lane_segments_to_next_point_.push_back(lane_segment);
429 } else {
431 }
432 }
433 CHECK_EQ(lane_segments_to_next_point_.size(),
434 static_cast<size_t>(num_segments_));
435}
436
438 lane_left_width_.clear();
440 lane_right_width_.clear();
442
443 road_left_width_.clear();
445 road_right_width_.clear();
447
448 double sample_s = 0;
449 double segment_end_s = -1.0;
450 double segment_start_s = -1.0;
451 double waypoint_s = 0.0;
452 double left_width = 0.0;
453 double right_width = 0.0;
454 const LaneWaypoint* cur_waypoint = nullptr;
455 bool is_reach_to_end = false;
456 int path_point_index = 0;
457 for (int i = 0; i < num_sample_points_; ++i) {
458 // Find the segment at the position of "sample_s".
459 while (segment_end_s < sample_s && !is_reach_to_end) {
460 const auto& cur_point = path_points_[path_point_index];
461 cur_waypoint = &(cur_point.lane_waypoints()[0]);
462 CHECK_NOTNULL(cur_waypoint->lane);
463 segment_start_s = accumulated_s_[path_point_index];
464 segment_end_s = segment_start_s + segments_[path_point_index].length();
465 if (++path_point_index >= num_points_) {
466 is_reach_to_end = true;
467 }
468 }
469 // Find the width of the way point at the position of "sample_s".
470 waypoint_s = cur_waypoint->s + sample_s - segment_start_s;
471 cur_waypoint->lane->GetWidth(waypoint_s, &left_width, &right_width);
472 lane_left_width_.push_back(left_width - cur_waypoint->l);
473 lane_right_width_.push_back(right_width + cur_waypoint->l);
474 cur_waypoint->lane->GetRoadWidth(waypoint_s, &left_width, &right_width);
475 road_left_width_.push_back(left_width - cur_waypoint->l);
476 road_right_width_.push_back(right_width + cur_waypoint->l);
477 sample_s += kSampleDistance;
478 }
479 // Check the width array size.
480 auto num_sample_points = static_cast<size_t>(num_sample_points_);
481 CHECK_EQ(lane_left_width_.size(), num_sample_points);
482 CHECK_EQ(lane_right_width_.size(), num_sample_points);
483
484 CHECK_EQ(road_left_width_.size(), num_sample_points);
485 CHECK_EQ(road_right_width_.size(), num_sample_points);
486}
487
489 last_point_index_.clear();
491 double s = 0.0;
492 int last_index = 0;
493 for (int i = 0; i < num_sample_points_; ++i) {
494 while (last_index + 1 < num_points_ &&
495 accumulated_s_[last_index + 1] <= s) {
496 ++last_index;
497 }
498 last_point_index_.push_back(last_index);
499 s += kSampleDistance;
500 }
501 CHECK_EQ(last_point_index_.size(), static_cast<size_t>(num_sample_points_));
502}
503
505 std::vector<PathOverlap>* const overlaps) const {
506 if (overlaps == nullptr) {
507 return;
508 }
509 overlaps->clear();
510 std::unordered_map<std::string, std::vector<std::pair<double, double>>>
511 overlaps_by_id;
512 double s = 0.0;
513 for (const auto& lane_segment : lane_segments_) {
514 if (lane_segment.lane == nullptr) {
515 continue;
516 }
517 for (const auto& overlap : GetOverlaps_from_lane(*(lane_segment.lane))) {
518 const auto& overlap_info =
519 overlap->GetObjectOverlapInfo(lane_segment.lane->id());
520 if (overlap_info == nullptr) {
521 continue;
522 }
523
524 const auto& lane_overlap_info = overlap_info->lane_overlap_info();
525 if (lane_overlap_info.start_s() <= lane_segment.end_s &&
526 lane_overlap_info.end_s() >= lane_segment.start_s) {
527 const double ref_s = s - lane_segment.start_s;
528 const double adjusted_start_s =
529 std::max(lane_overlap_info.start_s(), lane_segment.start_s) + ref_s;
530 const double adjusted_end_s =
531 std::min(lane_overlap_info.end_s(), lane_segment.end_s) + ref_s;
532 for (const auto& object : overlap->overlap().object()) {
533 if (object.id().id() != lane_segment.lane->id().id()) {
534 overlaps_by_id[object.id().id()].emplace_back(adjusted_start_s,
535 adjusted_end_s);
536 }
537 }
538 }
539 }
540 s += lane_segment.end_s - lane_segment.start_s;
541 }
542 for (auto& overlaps_one_object : overlaps_by_id) {
543 const std::string& object_id = overlaps_one_object.first;
544 auto& segments = overlaps_one_object.second;
545 std::sort(segments.begin(), segments.end());
546
547 const double kMinOverlapDistanceGap = 1.5; // in meters.
548 for (const auto& segment : segments) {
549 if (!overlaps->empty() && overlaps->back().object_id == object_id &&
550 segment.first - overlaps->back().end_s <= kMinOverlapDistanceGap) {
551 overlaps->back().end_s =
552 std::max(overlaps->back().end_s, segment.second);
553 } else {
554 overlaps->emplace_back(object_id, segment.first, segment.second);
555 }
556 }
557 }
558 std::sort(overlaps->begin(), overlaps->end(),
559 [](const PathOverlap& overlap1, const PathOverlap& overlap2) {
560 return overlap1.start_s < overlap2.start_s;
561 });
562}
563
564const PathOverlap* Path::NextLaneOverlap(double s) const {
565 auto next = std::upper_bound(
566 lane_overlaps_.begin(), lane_overlaps_.end(), s,
567 [](double s, const PathOverlap& o) { return s < o.start_s; });
568 if (next == lane_overlaps_.end()) {
569 return nullptr;
570 } else {
571 return &(*next);
572 }
573}
574
590
592 CHECK_GE(index.id, 0);
593 CHECK_LT(index.id, num_points_);
594
595 const MapPathPoint& ref_point = path_points_[index.id];
596 if (std::abs(index.offset) > kMathEpsilon) {
597 const Vec2d delta = unit_directions_[index.id] * index.offset;
598 MapPathPoint point({ref_point.x() + delta.x(), ref_point.y() + delta.y()},
599 ref_point.heading());
600 if (index.id < num_segments_ && !ref_point.lane_waypoints().empty()) {
601 const LaneSegment& lane_segment = lane_segments_to_next_point_[index.id];
602 auto ref_lane_waypoint = ref_point.lane_waypoints()[0];
603 if (lane_segment.lane != nullptr) {
604 for (const auto& lane_waypoint : ref_point.lane_waypoints()) {
605 if (lane_waypoint.lane->id().id() == lane_segment.lane->id().id()) {
606 ref_lane_waypoint = lane_waypoint;
607 break;
608 }
609 }
610 point.add_lane_waypoint(
611 LaneWaypoint(lane_segment.lane, lane_segment.start_s + index.offset,
612 ref_lane_waypoint.l));
613 }
614 }
615 if (point.lane_waypoints().empty() && !ref_point.lane_waypoints().empty()) {
616 point.add_lane_waypoint(ref_point.lane_waypoints()[0]);
617 }
618 return point;
619 } else {
620 return ref_point;
621 }
622}
623
625 return GetSmoothPoint(GetIndexFromS(s));
626}
627
628double Path::GetSFromIndex(const InterpolatedIndex& index) const {
629 if (index.id < 0) {
630 return 0.0;
631 }
632 if (index.id >= num_points_) {
633 return length_;
634 }
635 return accumulated_s_[index.id] + index.offset;
636}
637
639 if (s <= 0.0) {
640 return {0, 0.0};
641 }
642 CHECK_GT(num_points_, 0);
643 if (s >= length_) {
644 return {num_points_ - 1, 0.0};
645 }
646 const int sample_id = static_cast<int>(s / kSampleDistance);
647 if (sample_id >= num_sample_points_) {
648 return {num_points_ - 1, 0.0};
649 }
650 const int next_sample_id = sample_id + 1;
651 int low = last_point_index_[sample_id];
652 int high = (next_sample_id < num_sample_points_
653 ? std::min(num_points_, last_point_index_[next_sample_id] + 1)
654 : num_points_);
655 while (low + 1 < high) {
656 const int mid = (low + high) >> 1;
657 if (accumulated_s_[mid] <= s) {
658 low = mid;
659 } else {
660 high = mid;
661 }
662 }
663 return {low, s - accumulated_s_[low]};
664}
665
667 if (s <= 0.0) {
668 return {0, 0.0};
669 }
670 CHECK_GT(lane_segments_.size(), 0U);
671 if (s >= length_) {
672 return {static_cast<int>(lane_segments_.size() - 1),
673 lane_segments_.back().Length()};
674 }
675 auto iter = std::lower_bound(lane_accumulated_s_.begin(),
676 lane_accumulated_s_.end(), s);
677 if (iter == lane_accumulated_s_.end()) {
678 return {static_cast<int>(lane_segments_.size() - 1),
679 lane_segments_.back().Length()};
680 }
681 int index =
682 static_cast<int>(std::distance(lane_accumulated_s_.begin(), iter));
683 if (index == 0) {
684 return {index, s};
685 } else {
686 return {index, s - lane_accumulated_s_[index - 1]};
687 }
688}
689
690std::vector<hdmap::LaneSegment> Path::GetLaneSegments(
691 const double start_s, const double end_s) const {
692 std::vector<hdmap::LaneSegment> lanes;
693 if (start_s + kMathEpsilon > end_s) {
694 return lanes;
695 }
696 auto start_index = GetLaneIndexFromS(start_s);
697 if (start_index.offset + kMathEpsilon >=
698 lane_segments_[start_index.id].Length()) {
699 start_index.id += 1;
700 start_index.offset = 0;
701 }
702 const int num_lanes = static_cast<int>(lane_segments_.size());
703 if (start_index.id >= num_lanes) {
704 return lanes;
705 }
706 lanes.emplace_back(lane_segments_[start_index.id].lane, start_index.offset,
707 lane_segments_[start_index.id].Length());
708 auto end_index = GetLaneIndexFromS(end_s);
709 for (int i = start_index.id; i < end_index.id && i < num_lanes; ++i) {
710 lanes.emplace_back(lane_segments_[i]);
711 }
712 if (end_index.offset >= kMathEpsilon) {
713 lanes.emplace_back(lane_segments_[end_index.id].lane, 0, end_index.offset);
714 }
715 return lanes;
716}
717
718bool Path::GetNearestPoint(const Vec2d& point, double* accumulate_s,
719 double* lateral) const {
720 double distance = 0.0;
721 return GetNearestPoint(point, accumulate_s, lateral, &distance);
722}
723
724bool Path::GetNearestPoint(const Vec2d& point, double* accumulate_s,
725 double* lateral, double* min_distance) const {
726 if (!GetProjection(point, accumulate_s, lateral, min_distance)) {
727 return false;
728 }
729 if (*accumulate_s < 0.0) {
730 *accumulate_s = 0.0;
731 *min_distance = point.DistanceTo(path_points_[0]);
732 } else if (*accumulate_s > length_) {
733 *accumulate_s = length_;
734 *min_distance = point.DistanceTo(path_points_.back());
735 }
736 return true;
737}
738
739bool Path::GetProjection(const common::math::Vec2d& point, double* accumulate_s,
740 double* lateral) const {
741 double distance = 0.0;
742 return GetProjection(point, accumulate_s, lateral, &distance);
743}
744
745bool Path::GetProjection(const double heading, const common::math::Vec2d& point,
746 double* accumulate_s, double* lateral) const {
747 double distance = 0.0;
748 return GetProjection(point, heading, accumulate_s, lateral, &distance);
749}
750
752 double* accumulate_s,
753 double* lateral) const {
754 if (segments_.empty()) {
755 return false;
756 }
757 if (accumulate_s == nullptr || lateral == nullptr) {
758 return false;
759 }
760 if (*accumulate_s < 0.0) {
761 *accumulate_s = 0.0;
762 } else if (*accumulate_s > length()) {
763 *accumulate_s = length();
764 }
765 CHECK_GE(num_points_, 2);
766 double warm_start_s = *accumulate_s;
767 // Find the segment at the position of "accumulate_s".
768 int left_index = 0;
769 int right_index = num_segments_;
770 int mid_index = 0;
771 // Find the segment with projection of the given point on it.
772 while (right_index > left_index + 1) {
773 FindIndex(left_index, right_index, warm_start_s, &mid_index);
774 const auto& segment = segments_[mid_index];
775 const auto& start_point = segment.start();
776 double delta_x = point.x() - start_point.x();
777 double delta_y = point.y() - start_point.y();
778 const auto& unit_direction = segment.unit_direction();
779 double proj = delta_x * unit_direction.x() + delta_y * unit_direction.y();
780 *accumulate_s = accumulated_s_[mid_index] + proj;
781 *lateral = unit_direction.x() * delta_y - unit_direction.y() * delta_x;
782 if (proj > 0.0) {
783 if (proj < segment.length()) {
784 return true;
785 }
786 if (mid_index == right_index) {
787 *accumulate_s = accumulated_s_[mid_index];
788 return true;
789 }
790 left_index = mid_index + 1;
791 } else {
792 if (mid_index == left_index) {
793 *accumulate_s = accumulated_s_[mid_index];
794 return true;
795 }
796 if (std::abs(proj) < segments_[mid_index - 1].length()) {
797 return true;
798 }
799 right_index = mid_index - 1;
800 }
801 warm_start_s = segment.length() + proj;
802 }
803 return true;
804}
805
807 const double hueristic_start_s,
808 const double hueristic_end_s,
809 double* accumulate_s,
810 double* lateral,
811 double* min_distance) const {
812 if (segments_.empty()) {
813 return false;
814 }
815 if (accumulate_s == nullptr || lateral == nullptr ||
816 min_distance == nullptr) {
817 return false;
818 }
819 CHECK_GE(num_points_, 2);
820 *min_distance = std::numeric_limits<double>::infinity();
821
822 int start_interpolation_index = GetIndexFromS(hueristic_start_s).id;
823 int end_interpolation_index = static_cast<int>(
824 std::fmin(num_segments_, GetIndexFromS(hueristic_end_s).id + 1));
825 int min_index = start_interpolation_index;
826 for (int i = start_interpolation_index; i <= end_interpolation_index; ++i) {
827 const double distance = segments_[i].DistanceSquareTo(point);
828 if (distance < *min_distance) {
829 min_index = i;
830 *min_distance = distance;
831 }
832 }
833 *min_distance = std::sqrt(*min_distance);
834 const auto& nearest_seg = segments_[min_index];
835 const auto prod = nearest_seg.ProductOntoUnit(point);
836 const auto proj = nearest_seg.ProjectOntoUnit(point);
837 if (min_index == 0) {
838 *accumulate_s = std::min(proj, nearest_seg.length());
839 if (proj < 0) {
840 *lateral = prod;
841 } else {
842 *lateral = (prod > 0.0 ? 1 : -1) * *min_distance;
843 }
844 } else if (min_index == num_segments_ - 1) {
845 *accumulate_s = accumulated_s_[min_index] + std::max(0.0, proj);
846 if (proj > 0) {
847 *lateral = prod;
848 } else {
849 *lateral = (prod > 0.0 ? 1 : -1) * *min_distance;
850 }
851 } else {
852 *accumulate_s = accumulated_s_[min_index] +
853 std::max(0.0, std::min(proj, nearest_seg.length()));
854 *lateral = (prod > 0.0 ? 1 : -1) * *min_distance;
855 }
856 return true;
857}
858
859bool Path::GetProjection(const Vec2d& point, double* accumulate_s,
860 double* lateral, double* min_distance) const {
861 if (segments_.empty()) {
862 return false;
863 }
864 if (accumulate_s == nullptr || lateral == nullptr ||
865 min_distance == nullptr) {
866 return false;
867 }
869 return approximation_.GetProjection(*this, point, accumulate_s, lateral,
870 min_distance);
871 }
872 CHECK_GE(num_points_, 2);
873 *min_distance = std::numeric_limits<double>::infinity();
874 int min_index = 0;
875 for (int i = 0; i < num_segments_; ++i) {
876 const double distance = segments_[i].DistanceSquareTo(point);
877 if (distance < *min_distance) {
878 min_index = i;
879 *min_distance = distance;
880 }
881 }
882 *min_distance = std::sqrt(*min_distance);
883 const auto& nearest_seg = segments_[min_index];
884 const auto prod = nearest_seg.ProductOntoUnit(point);
885 const auto proj = nearest_seg.ProjectOntoUnit(point);
886 if (min_index == 0) {
887 *accumulate_s = std::min(proj, nearest_seg.length());
888 if (proj < 0) {
889 *lateral = prod;
890 } else {
891 *lateral = (prod > 0.0 ? 1 : -1) * *min_distance;
892 }
893 } else if (min_index == num_segments_ - 1) {
894 *accumulate_s = accumulated_s_[min_index] + std::max(0.0, proj);
895 if (proj > 0) {
896 *lateral = prod;
897 } else {
898 *lateral = (prod > 0.0 ? 1 : -1) * *min_distance;
899 }
900 } else {
901 *accumulate_s = accumulated_s_[min_index] +
902 std::max(0.0, std::min(proj, nearest_seg.length()));
903 *lateral = (prod > 0.0 ? 1 : -1) * *min_distance;
904 }
905 return true;
906}
907
908bool Path::GetProjection(const Vec2d& point, const double heading,
909 double* accumulate_s, double* lateral,
910 double* min_distance) const {
911 if (segments_.empty()) {
912 return false;
913 }
914 if (accumulate_s == nullptr || lateral == nullptr ||
915 min_distance == nullptr) {
916 return false;
917 }
919 return approximation_.GetProjection(*this, point, accumulate_s, lateral,
920 min_distance);
921 }
922 CHECK_GE(num_points_, 2);
923 *min_distance = std::numeric_limits<double>::infinity();
924 int min_index = 0;
925 for (int i = 0; i < num_segments_; ++i) {
926 if (abs(common::math::AngleDiff(segments_[i].heading(), heading)) >= M_PI_2)
927 continue;
928 const double distance = segments_[i].DistanceSquareTo(point);
929 if (distance < *min_distance) {
930 min_index = i;
931 *min_distance = distance;
932 }
933 }
934 *min_distance = std::sqrt(*min_distance);
935 const auto& nearest_seg = segments_[min_index];
936 const auto prod = nearest_seg.ProductOntoUnit(point);
937 const auto proj = nearest_seg.ProjectOntoUnit(point);
938 if (min_index == 0) {
939 *accumulate_s = std::min(proj, nearest_seg.length());
940 if (proj < 0) {
941 *lateral = prod;
942 } else {
943 *lateral = (prod > 0.0 ? 1 : -1) * *min_distance;
944 }
945 } else if (min_index == num_segments_ - 1) {
946 *accumulate_s = accumulated_s_[min_index] + std::max(0.0, proj);
947 if (proj > 0) {
948 *lateral = prod;
949 } else {
950 *lateral = (prod > 0.0 ? 1 : -1) * *min_distance;
951 }
952 } else {
953 *accumulate_s = accumulated_s_[min_index] +
954 std::max(0.0, std::min(proj, nearest_seg.length()));
955 *lateral = (prod > 0.0 ? 1 : -1) * *min_distance;
956 }
957 return true;
958}
959
960bool Path::GetHeadingAlongPath(const Vec2d& point, double* heading) const {
961 if (heading == nullptr) {
962 return false;
963 }
964 double s = 0;
965 double l = 0;
966 if (GetProjection(point, &s, &l)) {
967 *heading = GetSmoothPoint(s).heading();
968 return true;
969 }
970 return false;
971}
972
973double Path::GetLaneLeftWidth(const double s) const {
974 return GetSample(lane_left_width_, s);
975}
976
977double Path::GetLaneRightWidth(const double s) const {
978 return GetSample(lane_right_width_, s);
979}
980
981bool Path::GetLaneWidth(const double s, double* lane_left_width,
982 double* lane_right_width) const {
983 CHECK_NOTNULL(lane_left_width);
984 CHECK_NOTNULL(lane_right_width);
985
986 if (s < 0.0 || s > length_) {
987 return false;
988 }
989 *lane_left_width = GetSample(lane_left_width_, s);
990 *lane_right_width = GetSample(lane_right_width_, s);
991 return true;
992}
993
994double Path::GetRoadLeftWidth(const double s) const {
995 return GetSample(road_left_width_, s);
996}
997
998double Path::GetRoadRightWidth(const double s) const {
999 return GetSample(road_right_width_, s);
1000}
1001
1002bool Path::GetRoadWidth(const double s, double* road_left_width,
1003 double* road_right_width) const {
1004 CHECK_NOTNULL(road_left_width);
1005 CHECK_NOTNULL(road_right_width);
1006
1007 if (s < 0.0 || s > length_) {
1008 return false;
1009 }
1010
1011 *road_left_width = GetSample(road_left_width_, s);
1012 *road_right_width = GetSample(road_right_width_, s);
1013 return true;
1014}
1015
1016double Path::GetSample(const std::vector<double>& samples,
1017 const double s) const {
1018 if (samples.empty()) {
1019 return 0.0;
1020 }
1021 if (s <= 0.0) {
1022 return samples[0];
1023 }
1024 const int idx = static_cast<int>(s / kSampleDistance);
1025 if (idx >= num_sample_points_ - 1) {
1026 return samples.back();
1027 }
1028 const double ratio = (s - idx * kSampleDistance) / kSampleDistance;
1029 return samples[idx] * (1.0 - ratio) + samples[idx + 1] * ratio;
1030}
1031
1032bool Path::IsOnPath(const Vec2d& point) const {
1033 double accumulate_s = 0.0;
1034 double lateral = 0.0;
1035 if (!GetProjection(point, &accumulate_s, &lateral)) {
1036 return false;
1037 }
1038 double lane_left_width = 0.0;
1039 double lane_right_width = 0.0;
1040 if (!GetLaneWidth(accumulate_s, &lane_left_width, &lane_right_width)) {
1041 return false;
1042 }
1043 if (lateral < lane_left_width && lateral > -lane_right_width) {
1044 return true;
1045 }
1046 return false;
1047}
1048
1049bool Path::OverlapWith(const common::math::Box2d& box, double width) const {
1051 return approximation_.OverlapWith(*this, box, width);
1052 }
1053 const Vec2d center = box.center();
1054 const double radius_sqr = Sqr(box.diagonal() / 2.0 + width) + kMathEpsilon;
1055 for (const auto& segment : segments_) {
1056 if (segment.DistanceSquareTo(center) > radius_sqr) {
1057 continue;
1058 }
1059 if (box.DistanceTo(segment) <= width + kMathEpsilon) {
1060 return true;
1061 }
1062 }
1063 return false;
1064}
1065
1066double PathApproximation::compute_max_error(const Path& path, const int s,
1067 const int t) {
1068 if (s + 1 >= t) {
1069 return 0.0;
1070 }
1071 const auto& points = path.path_points();
1072 const LineSegment2d segment(points[s], points[t]);
1073 double max_distance_sqr = 0.0;
1074 for (int i = s + 1; i < t; ++i) {
1075 max_distance_sqr =
1076 std::max(max_distance_sqr, segment.DistanceSquareTo(points[i]));
1077 }
1078 return sqrt(max_distance_sqr);
1079}
1080
1081bool PathApproximation::is_within_max_error(const Path& path, const int s,
1082 const int t) {
1083 if (s + 1 >= t) {
1084 return true;
1085 }
1086 const auto& points = path.path_points();
1087 const LineSegment2d segment(points[s], points[t]);
1088 for (int i = s + 1; i < t; ++i) {
1089 if (segment.DistanceSquareTo(points[i]) > max_sqr_error_) {
1090 return false;
1091 }
1092 }
1093 return true;
1094}
1095
1097 InitDilute(path);
1098 InitProjections(path);
1099}
1100
1102 const int num_original_points = path.num_points();
1103 original_ids_.clear();
1104 int last_idx = 0;
1105 while (last_idx < num_original_points - 1) {
1106 original_ids_.push_back(last_idx);
1107 int next_idx = last_idx + 1;
1108 int delta = 2;
1109 for (; last_idx + delta < num_original_points; delta *= 2) {
1110 if (!is_within_max_error(path, last_idx, last_idx + delta)) {
1111 break;
1112 }
1113 next_idx = last_idx + delta;
1114 }
1115 for (; delta > 0; delta /= 2) {
1116 if (next_idx + delta < num_original_points &&
1117 is_within_max_error(path, last_idx, next_idx + delta)) {
1118 next_idx += delta;
1119 }
1120 }
1121 last_idx = next_idx;
1122 }
1123 original_ids_.push_back(last_idx);
1124 num_points_ = static_cast<int>(original_ids_.size());
1125 if (num_points_ == 0) {
1126 return;
1127 }
1128
1129 segments_.clear();
1130 segments_.reserve(num_points_ - 1);
1131 for (int i = 0; i < num_points_ - 1; ++i) {
1132 segments_.emplace_back(path.path_points()[original_ids_[i]],
1133 path.path_points()[original_ids_[i + 1]]);
1134 }
1135 max_error_per_segment_.clear();
1137 for (int i = 0; i < num_points_ - 1; ++i) {
1138 max_error_per_segment_.push_back(
1140 }
1141}
1142
1144 if (num_points_ == 0) {
1145 return;
1146 }
1147 projections_.clear();
1148 projections_.reserve(segments_.size() + 1);
1149 double s = 0.0;
1150 projections_.push_back(0);
1151 for (const auto& segment : segments_) {
1152 s += segment.length();
1153 projections_.push_back(s);
1154 }
1155 const auto& original_points = path.path_points();
1156 const int num_original_points = static_cast<int>(original_points.size());
1157 original_projections_.clear();
1158 original_projections_.reserve(num_original_points);
1159 for (size_t i = 0; i < projections_.size(); ++i) {
1160 original_projections_.push_back(projections_[i]);
1161 if (i + 1 < projections_.size()) {
1162 const auto& segment = segments_[i];
1163 for (int idx = original_ids_[i] + 1; idx < original_ids_[i + 1]; ++idx) {
1164 const double proj = segment.ProjectOntoUnit(original_points[idx]);
1165 original_projections_.push_back(
1166 projections_[i] + std::max(0.0, std::min(proj, segment.length())));
1167 }
1168 }
1169 }
1170
1171 // max_p_to_left[i] = max(p[0], p[1], ... p[i]).
1172 max_original_projections_to_left_.resize(num_original_points);
1173 double last_projection = -std::numeric_limits<double>::infinity();
1174 for (int i = 0; i < num_original_points; ++i) {
1175 last_projection = std::max(last_projection, original_projections_[i]);
1176 max_original_projections_to_left_[i] = last_projection;
1177 }
1178 for (int i = 0; i + 1 < num_original_points; ++i) {
1180 max_original_projections_to_left_[i + 1] + kMathEpsilon);
1181 }
1182
1183 // min_p_to_right[i] = min(p[i], p[i + 1], ... p[size - 1]).
1185 last_projection = std::numeric_limits<double>::infinity();
1186 for (int i = num_original_points - 1; i >= 0; --i) {
1187 last_projection = std::min(last_projection, original_projections_[i]);
1188 min_original_projections_to_right_[i] = last_projection;
1189 }
1190 for (int i = 0; i + 1 < num_original_points; ++i) {
1192 min_original_projections_to_right_[i + 1] + kMathEpsilon);
1193 }
1194
1195 // Sample max_p_to_left by sample_distance.
1198 static_cast<int>(max_projection_ / kSampleDistance) + 1;
1201 double proj = 0.0;
1202 int last_index = 0;
1203 for (int i = 0; i < num_projection_samples_; ++i) {
1204 while (last_index + 1 < num_original_points &&
1205 max_original_projections_to_left_[last_index + 1] < proj) {
1206 ++last_index;
1207 }
1208 sampled_max_original_projections_to_left_.push_back(last_index);
1209 proj += kSampleDistance;
1210 }
1212 static_cast<size_t>(num_projection_samples_));
1213}
1214
1216 const common::math::Vec2d& point,
1217 double* accumulate_s, double* lateral,
1218 double* min_distance) const {
1219 if (num_points_ == 0) {
1220 return false;
1221 }
1222 if (accumulate_s == nullptr || lateral == nullptr ||
1223 min_distance == nullptr) {
1224 return false;
1225 }
1226 double min_distance_sqr = std::numeric_limits<double>::infinity();
1227 int estimate_nearest_segment_idx = -1;
1228 std::vector<double> distance_sqr_to_segments;
1229 distance_sqr_to_segments.reserve(segments_.size());
1230 for (size_t i = 0; i < segments_.size(); ++i) {
1231 const double distance_sqr = segments_[i].DistanceSquareTo(point);
1232 distance_sqr_to_segments.push_back(distance_sqr);
1233 if (distance_sqr < min_distance_sqr) {
1234 min_distance_sqr = distance_sqr;
1235 estimate_nearest_segment_idx = static_cast<int>(i);
1236 }
1237 }
1238 if (estimate_nearest_segment_idx < 0) {
1239 return false;
1240 }
1241 const auto& original_segments = path.segments();
1242 const int num_original_segments = static_cast<int>(original_segments.size());
1243 const auto& original_accumulated_s = path.accumulated_s();
1244 double min_distance_sqr_with_error =
1245 Sqr(sqrt(min_distance_sqr) +
1246 max_error_per_segment_[estimate_nearest_segment_idx] + max_error_);
1247 *min_distance = std::numeric_limits<double>::infinity();
1248 int nearest_segment_idx = -1;
1249 for (size_t i = 0; i < segments_.size(); ++i) {
1250 if (distance_sqr_to_segments[i] >= min_distance_sqr_with_error) {
1251 continue;
1252 }
1253 int first_segment_idx = original_ids_[i];
1254 int last_segment_idx = original_ids_[i + 1] - 1;
1255 double max_original_projection = std::numeric_limits<double>::infinity();
1256 if (first_segment_idx < last_segment_idx) {
1257 const auto& segment = segments_[i];
1258 const double projection = segment.ProjectOntoUnit(point);
1259 const double prod_sqr = Sqr(segment.ProductOntoUnit(point));
1260 if (prod_sqr >= min_distance_sqr_with_error) {
1261 continue;
1262 }
1263 const double scan_distance = sqrt(min_distance_sqr_with_error - prod_sqr);
1264 const double min_projection = projection - scan_distance;
1265 max_original_projection = projections_[i] + projection + scan_distance;
1266 if (min_projection > 0.0) {
1267 const double limit = projections_[i] + min_projection;
1268 const int sample_index =
1269 std::max(0, static_cast<int>(limit / kSampleDistance));
1270 if (sample_index >= num_projection_samples_) {
1271 first_segment_idx = last_segment_idx;
1272 } else {
1273 first_segment_idx =
1274 std::max(first_segment_idx,
1276 if (first_segment_idx >= last_segment_idx) {
1277 first_segment_idx = last_segment_idx;
1278 } else {
1279 while (first_segment_idx < last_segment_idx &&
1280 max_original_projections_to_left_[first_segment_idx + 1] <
1281 limit) {
1282 ++first_segment_idx;
1283 }
1284 }
1285 }
1286 }
1287 }
1288 bool min_distance_updated = false;
1289 bool is_within_end_point = false;
1290 for (int idx = first_segment_idx; idx <= last_segment_idx; ++idx) {
1291 if (min_original_projections_to_right_[idx] > max_original_projection) {
1292 break;
1293 }
1294 const auto& original_segment = original_segments[idx];
1295 const double x0 = point.x() - original_segment.start().x();
1296 const double y0 = point.y() - original_segment.start().y();
1297 const double ux = original_segment.unit_direction().x();
1298 const double uy = original_segment.unit_direction().y();
1299 double proj = x0 * ux + y0 * uy;
1300 double distance = 0.0;
1301 if (proj < 0.0) {
1302 if (is_within_end_point) {
1303 continue;
1304 }
1305 is_within_end_point = true;
1306 distance = hypot(x0, y0);
1307 } else if (proj <= original_segment.length()) {
1308 is_within_end_point = true;
1309 distance = std::abs(x0 * uy - y0 * ux);
1310 } else {
1311 is_within_end_point = false;
1312 if (idx != last_segment_idx) {
1313 continue;
1314 }
1315 distance = original_segment.end().DistanceTo(point);
1316 }
1317 if (distance < *min_distance) {
1318 min_distance_updated = true;
1319 *min_distance = distance;
1320 nearest_segment_idx = idx;
1321 }
1322 }
1323 if (min_distance_updated) {
1324 min_distance_sqr_with_error = Sqr(*min_distance + max_error_);
1325 }
1326 }
1327 if (nearest_segment_idx >= 0) {
1328 const auto& segment = original_segments[nearest_segment_idx];
1329 double proj = segment.ProjectOntoUnit(point);
1330 const double prod = segment.ProductOntoUnit(point);
1331 if (nearest_segment_idx > 0) {
1332 proj = std::max(0.0, proj);
1333 }
1334 if (nearest_segment_idx + 1 < num_original_segments) {
1335 proj = std::min(segment.length(), proj);
1336 }
1337 *accumulate_s = original_accumulated_s[nearest_segment_idx] + proj;
1338 if ((nearest_segment_idx == 0 && proj < 0.0) ||
1339 (nearest_segment_idx + 1 == num_original_segments &&
1340 proj > segment.length())) {
1341 *lateral = prod;
1342 } else {
1343 *lateral = (prod > 0 ? (*min_distance) : -(*min_distance));
1344 }
1345 return true;
1346 }
1347 return false;
1348}
1349
1350bool PathApproximation::OverlapWith(const Path& path, const Box2d& box,
1351 double width) const {
1352 if (num_points_ == 0) {
1353 return false;
1354 }
1355 const Vec2d center = box.center();
1356 const double radius = box.diagonal() / 2.0 + width;
1357 const double radius_sqr = Sqr(radius);
1358 const auto& original_segments = path.segments();
1359 for (size_t i = 0; i < segments_.size(); ++i) {
1360 const LineSegment2d& segment = segments_[i];
1361 const double max_error = max_error_per_segment_[i];
1362 const double radius_sqr_with_error = Sqr(radius + max_error);
1363 if (segment.DistanceSquareTo(center) > radius_sqr_with_error) {
1364 continue;
1365 }
1366 int first_segment_idx = original_ids_[i];
1367 int last_segment_idx = original_ids_[i + 1] - 1;
1368 double max_original_projection = std::numeric_limits<double>::infinity();
1369 if (first_segment_idx < last_segment_idx) {
1370 const auto& segment = segments_[i];
1371 const double projection = segment.ProjectOntoUnit(center);
1372 const double prod_sqr = Sqr(segment.ProductOntoUnit(center));
1373 if (prod_sqr >= radius_sqr_with_error) {
1374 continue;
1375 }
1376 const double scan_distance = sqrt(radius_sqr_with_error - prod_sqr);
1377 const double min_projection = projection - scan_distance;
1378 max_original_projection = projections_[i] + projection + scan_distance;
1379 if (min_projection > 0.0) {
1380 const double limit = projections_[i] + min_projection;
1381 const int sample_index =
1382 std::max(0, static_cast<int>(limit / kSampleDistance));
1383 if (sample_index >= num_projection_samples_) {
1384 first_segment_idx = last_segment_idx;
1385 } else {
1386 first_segment_idx =
1387 std::max(first_segment_idx,
1389 if (first_segment_idx >= last_segment_idx) {
1390 first_segment_idx = last_segment_idx;
1391 } else {
1392 while (first_segment_idx < last_segment_idx &&
1393 max_original_projections_to_left_[first_segment_idx + 1] <
1394 limit) {
1395 ++first_segment_idx;
1396 }
1397 }
1398 }
1399 }
1400 }
1401 for (int idx = first_segment_idx; idx <= last_segment_idx; ++idx) {
1402 if (min_original_projections_to_right_[idx] > max_original_projection) {
1403 break;
1404 }
1405 const auto& original_segment = original_segments[idx];
1406 if (original_segment.DistanceSquareTo(center) > radius_sqr) {
1407 continue;
1408 }
1409 if (box.DistanceTo(original_segment) <= width) {
1410 return true;
1411 }
1412 }
1413 }
1414 return false;
1415}
1416
1417void Path::FindIndex(int left_index, int right_index, double target_s,
1418 int* mid_index) const {
1419 // Find the segment index with binary search
1420 while (right_index > left_index + 1) {
1421 *mid_index = ((left_index + right_index) >> 1);
1422 if (accumulated_s_[*mid_index] < target_s) {
1423 left_index = *mid_index;
1424 continue;
1425 }
1426 if (accumulated_s_[*mid_index - 1] > target_s) {
1427 right_index = *mid_index - 1;
1428 continue;
1429 }
1430 return;
1431 }
1432}
1433
1434} // namespace hdmap
1435} // namespace apollo
Rectangular (undirected) bounding box in 2-D.
Definition box2d.h:52
double diagonal() const
Getter of the size of the diagonal of the box
Definition box2d.h:172
const Vec2d & center() const
Getter of the center of the box
Definition box2d.h:106
double DistanceTo(const Vec2d &point) const
Determines the distance between the box and a given point
Definition box2d.cc:168
double DistanceSquareTo(const Vec2d &point) const
Compute the square of the shortest distance from a point on the line segment to a point in 2-D.
double ProjectOntoUnit(const Vec2d &point) const
Compute the projection of a vector onto the line segment.
double ProductOntoUnit(const Vec2d &point) const
Compute the cross product of a vector onto the line segment.
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
double DistanceSquareTo(const Vec2d &other) const
Returns the squared distance to the given vector
Definition vec2d.cc:51
double Length() const
Gets the length of the vector
Definition vec2d.cc:33
double y() const
Getter for y component
Definition vec2d.h:57
double DistanceTo(const Vec2d &other) const
Returns the distance to the given vector
Definition vec2d.cc:47
double x() const
Getter for x component
Definition vec2d.h:54
void Normalize()
Returns the unit vector that is co-linear with this vector
Definition vec2d.cc:39
static const HDMap * BaseMapPtr()
const std::vector< OverlapInfoConstPtr > & junctions() const
const std::vector< OverlapInfoConstPtr > & speed_bumps() const
const std::vector< OverlapInfoConstPtr > & stop_signs() const
const std::vector< OverlapInfoConstPtr > & clear_areas() const
const std::vector< OverlapInfoConstPtr > & signals() const
const std::vector< OverlapInfoConstPtr > & parking_spaces() const
const std::vector< OverlapInfoConstPtr > & crosswalks() const
const std::vector< OverlapInfoConstPtr > & pnc_junctions() const
const std::vector< OverlapInfoConstPtr > & yield_signs() const
const std::vector< OverlapInfoConstPtr > & areas() const
const std::vector< OverlapInfoConstPtr > & cross_lanes() const
std::vector< LaneWaypoint > lane_waypoints_
Definition path.h:148
static void RemoveDuplicates(std::vector< MapPathPoint > *points)
Definition path.cc:241
void add_lane_waypoint(LaneWaypoint lane_waypoint)
Definition path.h:125
const std::vector< LaneWaypoint > & lane_waypoints() const
Definition path.h:121
double heading() const
Definition path.h:118
static std::vector< MapPathPoint > GetPointsFromSegment(const LaneSegment &segment)
Definition path.cc:201
static std::vector< MapPathPoint > GetPointsFromLane(LaneInfoConstPtr lane, const double start_s, const double end_s)
Definition path.cc:206
std::string DebugString() const
Definition path.cc:258
bool is_within_max_error(const Path &path, const int s, const int t)
Definition path.cc:1081
std::vector< common::math::LineSegment2d > segments_
Definition path.h:187
void InitProjections(const Path &path)
Definition path.cc:1143
std::vector< double > min_original_projections_to_right_
Definition path.h:203
std::vector< int > sampled_max_original_projections_to_left_
Definition path.h:204
void Init(const Path &path)
Definition path.cc:1096
std::vector< double > max_error_per_segment_
Definition path.h:188
void InitDilute(const Path &path)
Definition path.cc:1101
double compute_max_error(const Path &path, const int s, const int t)
Definition path.cc:1066
std::vector< double > projections_
Definition path.h:193
std::vector< int > original_ids_
Definition path.h:186
bool GetProjection(const Path &path, const common::math::Vec2d &point, double *accumulate_s, double *lateral, double *distance) const
Definition path.cc:1215
std::vector< double > original_projections_
Definition path.h:199
std::vector< double > max_original_projections_to_left_
Definition path.h:202
bool OverlapWith(const Path &path, const common::math::Box2d &box, double width) const
Definition path.cc:1350
const std::vector< common::math::LineSegment2d > & segments() const
Definition path.h:290
void InitLaneSegments()
Definition path.cc:402
std::vector< MapPathPoint > path_points_
Definition path.h:368
InterpolatedIndex GetIndexFromS(double s) const
Definition path.cc:638
bool GetProjectionWithWarmStartS(const common::math::Vec2d &point, double *accumulate_s, double *lateral) const
Definition path.cc:751
double GetSample(const std::vector< double > &samples, const double s) const
Definition path.cc:1016
std::vector< PathOverlap > speed_bump_overlaps_
Definition path.h:397
double length() const
Definition path.h:294
bool GetProjectionWithHueristicParams(const common::math::Vec2d &point, const double hueristic_start_s, const double hueristic_end_s, double *accumulate_s, double *lateral, double *min_distance) const
Definition path.cc:806
void InitPointIndex()
Definition path.cc:488
std::vector< double > lane_accumulated_s_
Definition path.h:370
double GetLaneRightWidth(const double s) const
Definition path.cc:977
bool IsOnPath(const common::math::Vec2d &point) const
Definition path.cc:1032
void InitPoints()
Definition path.cc:362
std::vector< double > accumulated_s_
Definition path.h:374
std::vector< PathOverlap > stop_sign_overlaps_
Definition path.h:390
bool GetLaneWidth(const double s, double *lane_left_width, double *lane_right_width) const
Definition path.cc:981
std::vector< PathOverlap > pnc_junction_overlaps_
Definition path.h:395
std::vector< PathOverlap > parking_space_overlaps_
Definition path.h:392
std::function< const std::vector< OverlapInfoConstPtr > &(const LaneInfo &)> GetOverlapFromLaneFunc
Definition path.h:361
double GetRoadLeftWidth(const double s) const
Definition path.cc:994
std::vector< hdmap::LaneSegment > GetLaneSegments(const double start_s, const double end_s) const
Definition path.cc:690
std::vector< PathOverlap > crosswalk_overlaps_
Definition path.h:391
std::vector< int > last_point_index_
Definition path.h:385
std::vector< double > lane_left_width_
Definition path.h:381
std::vector< PathOverlap > lane_overlaps_
Definition path.h:387
std::vector< PathOverlap > signal_overlaps_
Definition path.h:388
double GetRoadRightWidth(const double s) const
Definition path.cc:998
bool GetHeadingAlongPath(const common::math::Vec2d &point, double *heading) const
Definition path.cc:960
const PathOverlap * NextLaneOverlap(double s) const
Definition path.cc:564
bool GetRoadWidth(const double s, double *road_left_width, double *road_ight_width) const
Definition path.cc:1002
bool GetProjection(const common::math::Vec2d &point, double *accumulate_s, double *lateral) const
Definition path.cc:739
InterpolatedIndex GetLaneIndexFromS(double s) const
Definition path.cc:666
double GetSFromIndex(const InterpolatedIndex &index) const
Definition path.cc:628
std::vector< common::math::Vec2d > unit_directions_
Definition path.h:372
std::vector< PathOverlap > yield_sign_overlaps_
Definition path.h:389
void InitOverlaps()
Definition path.cc:575
std::string DebugString() const
Definition path.cc:266
MapPathPoint GetSmoothPoint(const InterpolatedIndex &index) const
Definition path.cc:591
std::vector< PathOverlap > clear_area_overlaps_
Definition path.h:396
int num_sample_points_
Definition path.h:380
bool GetNearestPoint(const common::math::Vec2d &point, double *accumulate_s, double *lateral) const
Definition path.cc:718
bool OverlapWith(const common::math::Box2d &box, double width) const
Definition path.cc:1049
std::vector< PathOverlap > area_overlaps_
Definition path.h:398
std::vector< double > road_left_width_
Definition path.h:383
int num_points() const
Definition path.h:277
std::vector< double > lane_right_width_
Definition path.h:382
std::vector< common::math::LineSegment2d > segments_
Definition path.h:375
bool use_path_approximation_
Definition path.h:376
std::vector< PathOverlap > junction_overlaps_
Definition path.h:394
std::vector< LaneSegment > lane_segments_to_next_point_
Definition path.h:371
const std::vector< MapPathPoint > & path_points() const
Definition path.h:279
void GetAllOverlaps(GetOverlapFromLaneFunc GetOverlaps_from_lane, std::vector< PathOverlap > *const overlaps) const
Definition path.cc:504
std::vector< LaneSegment > lane_segments_
Definition path.h:369
double GetLaneLeftWidth(const double s) const
Definition path.cc:973
PathApproximation approximation_
Definition path.h:377
const std::vector< double > & accumulated_s() const
Definition path.h:289
std::vector< double > road_right_width_
Definition path.h:384
Define the LineSegment2d class.
Math-related util functions.
double Sqr(const double x)
Definition math_utils.cc:26
constexpr double kMathEpsilon
Definition vec2d.h:35
double AngleDiff(const double from, const double to)
Calculate the difference between angle from and to
Definition math_utils.cc:61
std::shared_ptr< const LaneInfo > LaneInfoConstPtr
LaneBoundaryType::Type LeftBoundaryType(const LaneWaypoint &waypoint)
get left boundary type at a waypoint.
Definition path.cc:75
LaneBoundaryType::Type RightBoundaryType(const LaneWaypoint &waypoint)
get left boundary type at a waypoint.
Definition path.cc:92
LaneWaypoint RightNeighborWaypoint(const LaneWaypoint &waypoint)
get left neighbor lane waypoint.
Definition path.cc:165
LaneWaypoint LeftNeighborWaypoint(const LaneWaypoint &waypoint)
get left neighbor lane waypoint.
Definition path.cc:109
class register implement
Definition arena_queue.h:37
Definition future.h:29
Define the Polygon2d class.
Some string util functions.
static void Join(std::vector< LaneSegment > *segments)
Join neighboring lane segments if they have the same lane id
Definition path.cc:138
LaneInfoConstPtr lane
Definition path.h:77
std::string DebugString() const
Definition path.cc:193
std::string DebugString() const
Definition path.cc:68
LaneInfoConstPtr lane
Definition path.h:44
std::string DebugString() const
Definition path.cc:280
std::string object_id
Definition path.h:95