Apollo 10.0
自动驾驶开放平台
reference_line.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
22
23#include <algorithm>
24#include <limits>
25#include <unordered_set>
26
27#include "absl/strings/str_cat.h"
28#include "absl/strings/str_join.h"
29#include "boost/math/tools/minima.hpp"
30
31#include "cyber/common/log.h"
40
41namespace apollo {
42namespace planning {
43
50
52 const std::vector<ReferencePoint>& reference_points)
53 : reference_points_(reference_points),
54 map_path_(std::move(std::vector<hdmap::MapPathPoint>(
55 reference_points.begin(), reference_points.end()))) {
56 CHECK_EQ(static_cast<size_t>(map_path_.num_points()),
57 reference_points_.size());
58}
59
61 : map_path_(hdmap_path) {
62 for (const auto& point : hdmap_path.path_points()) {
63 DCHECK(!point.lane_waypoints().empty());
64 const auto& lane_waypoint = point.lane_waypoints()[0];
65 reference_points_.emplace_back(
66 hdmap::MapPathPoint(point, point.heading(), lane_waypoint), 0.0, 0.0);
67 }
68 CHECK_EQ(static_cast<size_t>(map_path_.num_points()),
69 reference_points_.size());
70}
71
73 if (other.reference_points().empty()) {
74 AWARN << "The other reference line is empty.";
75 return true;
76 }
77 auto first_point = reference_points_.front();
78 common::SLPoint first_sl;
79 if (!other.XYToSL(first_point, &first_sl)) {
80 AWARN << "Failed to project the first point to the other reference line.";
81 return false;
82 }
83 bool first_join = first_sl.s() > 0 && first_sl.s() < other.Length();
84
85 auto last_point = reference_points_.back();
86 common::SLPoint last_sl;
87 if (!other.XYToSL(last_point, &last_sl)) {
88 AWARN << "Failed to project the last point to the other reference line.";
89 return false;
90 }
91 bool last_join = last_sl.s() > 0 && last_sl.s() < other.Length();
92
93 if (!first_join && !last_join) {
94 AERROR << "These reference lines are not connected.";
95 return false;
96 }
97
98 const auto& accumulated_s = other.map_path().accumulated_s();
99 const auto& other_points = other.reference_points();
100 auto lower = accumulated_s.begin();
101 static constexpr double kStitchingError = 1e-1;
102 if (first_join) {
103 if (first_sl.l() > kStitchingError) {
104 AERROR << "lateral stitching error on first join of reference line too "
105 "big, stitching fails";
106 return false;
107 }
108 lower = std::lower_bound(accumulated_s.begin(), accumulated_s.end(),
109 first_sl.s());
110 size_t start_i = std::distance(accumulated_s.begin(), lower);
111 reference_points_.insert(reference_points_.begin(), other_points.begin(),
112 other_points.begin() + start_i);
113 }
114 if (last_join) {
115 if (last_sl.l() > kStitchingError) {
116 AERROR << "lateral stitching error on first join of reference line too "
117 "big, stitching fails";
118 return false;
119 }
120 auto upper = std::upper_bound(lower, accumulated_s.end(), last_sl.s());
121 auto end_i = std::distance(accumulated_s.begin(), upper);
122 reference_points_.insert(reference_points_.end(),
123 other_points.begin() + end_i, other_points.end());
124 }
125 map_path_ = MapPath(std::move(std::vector<hdmap::MapPathPoint>(
126 reference_points_.begin(), reference_points_.end())));
127 return true;
128}
129
131 const common::math::Vec2d& xy) const {
132 double min_dist = std::numeric_limits<double>::max();
133 size_t min_index = 0;
134 for (size_t i = 0; i < reference_points_.size(); ++i) {
135 const double distance = DistanceXY(xy, reference_points_[i]);
136 if (distance < min_dist) {
137 min_dist = distance;
138 min_index = i;
139 }
140 }
141 return reference_points_[min_index];
142}
143
145 const double look_backward,
146 const double look_forward) {
148 if (!XYToSL(point, &sl)) {
149 AERROR << "Failed to project point: " << point.DebugString();
150 return false;
151 }
152 return Segment(sl.s(), look_backward, look_forward);
153}
154
155bool ReferenceLine::Segment(const double s, const double look_backward,
156 const double look_forward) {
157 const auto& accumulated_s = map_path_.accumulated_s();
158
159 // inclusive
160 auto start_index =
161 std::distance(accumulated_s.begin(),
162 std::lower_bound(accumulated_s.begin(), accumulated_s.end(),
163 s - look_backward));
164
165 // exclusive
166 auto end_index =
167 std::distance(accumulated_s.begin(),
168 std::upper_bound(accumulated_s.begin(), accumulated_s.end(),
169 s + look_forward));
170
171 if (end_index - start_index < 2) {
172 AERROR << "Too few reference points after shrinking.";
173 return false;
174 }
175
176 reference_points_ =
177 std::vector<ReferencePoint>(reference_points_.begin() + start_index,
178 reference_points_.begin() + end_index);
179
180 map_path_ = MapPath(std::vector<hdmap::MapPathPoint>(
181 reference_points_.begin(), reference_points_.end()));
182 return true;
183}
184
186 const common::PathPoint& path_point) const {
187 if (reference_points_.empty()) {
189 }
190
191 common::SLPoint sl_point;
192 XYToSL(path_point, &sl_point);
193 common::FrenetFramePoint frenet_frame_point;
194 frenet_frame_point.set_s(sl_point.s());
195 frenet_frame_point.set_l(sl_point.l());
196
197 const double theta = path_point.theta();
198 const double kappa = path_point.kappa();
199 const double l = frenet_frame_point.l();
200
201 ReferencePoint ref_point = GetReferencePoint(frenet_frame_point.s());
202
203 const double theta_ref = ref_point.heading();
204 const double kappa_ref = ref_point.kappa();
205 const double dkappa_ref = ref_point.dkappa();
206
208 theta_ref, theta, l, kappa_ref);
209 const double ddl =
211 theta_ref, theta, kappa_ref, kappa, dkappa_ref, l);
212 frenet_frame_point.set_dl(dl);
213 frenet_frame_point.set_ddl(ddl);
214 return frenet_frame_point;
215}
216
217std::pair<std::array<double, 3>, std::array<double, 3>>
219 ACHECK(!reference_points_.empty());
220
221 common::SLPoint sl_point;
222 XYToSL(traj_point.path_point().theta(),
223 {traj_point.path_point().x(), traj_point.path_point().y()}, &sl_point);
224
225 std::array<double, 3> s_condition;
226 std::array<double, 3> l_condition;
227 ReferencePoint ref_point = GetReferencePoint(sl_point.s());
229 sl_point.s(), ref_point.x(), ref_point.y(), ref_point.heading(),
230 ref_point.kappa(), ref_point.dkappa(), traj_point.path_point().x(),
231 traj_point.path_point().y(), traj_point.v(), traj_point.a(),
232 traj_point.path_point().theta(), traj_point.path_point().kappa(),
233 &s_condition, &l_condition);
234 AINFO << "planning_start_point x,y,the,k: " << std::fixed
235 << traj_point.path_point().x() << ", y: " << traj_point.path_point().y()
236 << "," << traj_point.path_point().theta() << ","
237 << traj_point.path_point().kappa() << "," << traj_point.v() << ","
238 << traj_point.a();
239 AINFO << "ref point x y the ka dka" << std::fixed << ref_point.x() << ","
240 << ref_point.y() << "," << ref_point.heading() << ","
241 << ref_point.kappa() << "," << ref_point.dkappa();
242 return std::make_pair(s_condition, l_condition);
243}
244
246 const auto& accumulated_s = map_path_.accumulated_s();
247 if (s < accumulated_s.front() - 1e-2) {
248 AWARN << "The requested s: " << s << " < 0.";
249 return reference_points_.front();
250 }
251 if (s > accumulated_s.back() + 1e-2) {
252 AWARN << "The requested s: " << s
253 << " > reference line length: " << accumulated_s.back();
254 return reference_points_.back();
255 }
256 auto it_lower =
257 std::lower_bound(accumulated_s.begin(), accumulated_s.end(), s);
258 if (it_lower == accumulated_s.begin()) {
259 return reference_points_.front();
260 }
261 auto index = std::distance(accumulated_s.begin(), it_lower);
262 if (std::fabs(accumulated_s[index - 1] - s) <
263 std::fabs(accumulated_s[index] - s)) {
264 return reference_points_[index - 1];
265 }
266 return reference_points_[index];
267}
268
269size_t ReferenceLine::GetNearestReferenceIndex(const double s) const {
270 const auto& accumulated_s = map_path_.accumulated_s();
271 if (s < accumulated_s.front() - 1e-2) {
272 AWARN << "The requested s: " << s << " < 0.";
273 return 0;
274 }
275 if (s > accumulated_s.back() + 1e-2) {
276 AWARN << "The requested s: " << s << " > reference line length "
277 << accumulated_s.back();
278 return reference_points_.size() - 1;
279 }
280 auto it_lower =
281 std::lower_bound(accumulated_s.begin(), accumulated_s.end(), s);
282 return std::distance(accumulated_s.begin(), it_lower);
283}
284
285std::vector<ReferencePoint> ReferenceLine::GetReferencePoints(
286 double start_s, double end_s) const {
287 if (start_s < 0.0) {
288 start_s = 0.0;
289 }
290 if (end_s > Length()) {
291 end_s = Length();
292 }
293 std::vector<ReferencePoint> ref_points;
294 auto start_index = GetNearestReferenceIndex(start_s);
295 auto end_index = GetNearestReferenceIndex(end_s);
296 if (start_index < end_index) {
297 ref_points.assign(reference_points_.begin() + start_index,
298 reference_points_.begin() + end_index);
299 }
300 return ref_points;
301}
302
304 const auto& accumulated_s = map_path_.accumulated_s();
305 if (s < accumulated_s.front() - 1e-2) {
306 AWARN << "The requested s: " << s << " < 0.";
307 return reference_points_.front();
308 }
309 if (s > accumulated_s.back() + 1e-2) {
310 AWARN << "The requested s: " << s
311 << " > reference line length: " << accumulated_s.back();
312 return reference_points_.back();
313 }
314
315 auto interpolate_index = map_path_.GetIndexFromS(s);
316
317 size_t index = interpolate_index.id;
318 size_t next_index = index + 1;
319 if (next_index >= reference_points_.size()) {
320 next_index = reference_points_.size() - 1;
321 }
322
323 const auto& p0 = reference_points_[index];
324 const auto& p1 = reference_points_[next_index];
325
326 const double s0 = accumulated_s[index];
327 const double s1 = accumulated_s[next_index];
328 return InterpolateWithMatchedIndex(p0, s0, p1, s1, interpolate_index);
329}
330
331double ReferenceLine::FindMinDistancePoint(const ReferencePoint& p0,
332 const double s0,
333 const ReferencePoint& p1,
334 const double s1, const double x,
335 const double y) {
336 auto func_dist_square = [&p0, &p1, &s0, &s1, &x, &y](const double s) {
337 auto p = Interpolate(p0, s0, p1, s1, s);
338 double dx = p.x() - x;
339 double dy = p.y() - y;
340 return dx * dx + dy * dy;
341 };
342
343 return ::boost::math::tools::brent_find_minima(func_dist_square, s0, s1, 8)
344 .first;
345}
346
348 const double y) const {
349 CHECK_GE(reference_points_.size(), 0U);
350
351 auto func_distance_square = [](const ReferencePoint& point, const double x,
352 const double y) {
353 double dx = point.x() - x;
354 double dy = point.y() - y;
355 return dx * dx + dy * dy;
356 };
357
358 double d_min = func_distance_square(reference_points_.front(), x, y);
359 size_t index_min = 0;
360
361 for (size_t i = 1; i < reference_points_.size(); ++i) {
362 double d_temp = func_distance_square(reference_points_[i], x, y);
363 if (d_temp < d_min) {
364 d_min = d_temp;
365 index_min = i;
366 }
367 }
368
369 size_t index_start = index_min == 0 ? index_min : index_min - 1;
370 size_t index_end =
371 index_min + 1 == reference_points_.size() ? index_min : index_min + 1;
372
373 if (index_start == index_end) {
374 return reference_points_[index_start];
375 }
376
377 double s0 = map_path_.accumulated_s()[index_start];
378 double s1 = map_path_.accumulated_s()[index_end];
379
380 double s = ReferenceLine::FindMinDistancePoint(
381 reference_points_[index_start], s0, reference_points_[index_end], s1, x,
382 y);
383
384 return Interpolate(reference_points_[index_start], s0,
385 reference_points_[index_end], s1, s);
386}
387
388bool ReferenceLine::SLToXY(const SLPoint& sl_point,
389 common::math::Vec2d* const xy_point) const {
390 if (map_path_.num_points() < 2) {
391 AERROR << "The reference line has too few points.";
392 return false;
393 }
394
395 const auto matched_point = GetReferencePoint(sl_point.s());
396 const auto angle = common::math::Angle16::from_rad(matched_point.heading());
397 xy_point->set_x(matched_point.x() - common::math::sin(angle) * sl_point.l());
398 xy_point->set_y(matched_point.y() + common::math::cos(angle) * sl_point.l());
399 return true;
400}
401
403 common::SLPoint* const sl_point,
404 double warm_start_s) const {
405 double s = warm_start_s;
406 double l = 0.0;
407 if (warm_start_s < 0.0) {
408 if (!map_path_.GetProjection(xy_point, &s, &l)) {
409 AERROR << "Cannot get nearest point from path.";
410 return false;
411 }
412 } else {
413 if (!map_path_.GetProjectionWithWarmStartS(xy_point, &s, &l)) {
414 AERROR << "Cannot get nearest point from path with warm_start_s: "
415 << warm_start_s;
416 return false;
417 }
418 }
419
420 sl_point->set_s(s);
421 sl_point->set_l(l);
422 return true;
423}
424
425bool ReferenceLine::XYToSL(const double heading,
426 const common::math::Vec2d& xy_point,
427 common::SLPoint* const sl_point,
428 double warm_start_s) const {
429 double s = warm_start_s;
430 double l = 0.0;
431 if (warm_start_s < 0.0) {
432 if (!map_path_.GetProjection(heading, xy_point, &s, &l)) {
433 AERROR << "Cannot get nearest point from path.";
434 return false;
435 }
436 } else {
437 if (!map_path_.GetProjectionWithWarmStartS(xy_point, &s, &l)) {
438 AERROR << "Cannot get nearest point from path with warm_start_s: "
439 << warm_start_s;
440 return false;
441 }
442 }
443
444 sl_point->set_s(s);
445 sl_point->set_l(l);
446 return true;
447}
448
450 common::SLPoint* const sl_point,
451 double hueristic_start_s,
452 double hueristic_end_s) const {
453 double s = 0.0;
454 double l = 0.0;
455 double min_distance = 0.0;
456 if (!map_path_.GetProjectionWithHueristicParams(xy_point, hueristic_start_s,
457 hueristic_end_s, &s, &l,
458 &min_distance)) {
459 AERROR << "Cannot get nearest point from path with hueristic_start_s: "
460 << hueristic_start_s << " hueristic_end_s: " << hueristic_end_s;
461 return false;
462 }
463 sl_point->set_s(s);
464 sl_point->set_l(l);
465 return true;
466}
467
468ReferencePoint ReferenceLine::InterpolateWithMatchedIndex(
469 const ReferencePoint& p0, const double s0, const ReferencePoint& p1,
470 const double s1, const InterpolatedIndex& index) const {
471 if (std::fabs(s0 - s1) < common::math::kMathEpsilon) {
472 return p0;
473 }
474 double s = s0 + index.offset;
475 DCHECK_LE(s0 - 1.0e-6, s) << "s: " << s << " is less than s0 : " << s0;
476 DCHECK_LE(s, s1 + 1.0e-6) << "s: " << s << " is larger than s1: " << s1;
477
478 auto map_path_point = map_path_.GetSmoothPoint(index);
479 map_path_point.set_heading(map_path_.unit_directions()[index.id].Angle());
480 const double kappa = common::math::lerp(p0.kappa(), s0, p1.kappa(), s1, s);
481 const double dkappa = common::math::lerp(p0.dkappa(), s0, p1.dkappa(), s1, s);
482
483 return ReferencePoint(map_path_point, kappa, dkappa);
484}
485
486ReferencePoint ReferenceLine::Interpolate(const ReferencePoint& p0,
487 const double s0,
488 const ReferencePoint& p1,
489 const double s1, const double s) {
490 if (std::fabs(s0 - s1) < common::math::kMathEpsilon) {
491 return p0;
492 }
493 DCHECK_LE(s0 - 1.0e-6, s) << " s: " << s << " is less than s0 :" << s0;
494 DCHECK_LE(s, s1 + 1.0e-6) << "s: " << s << " is larger than s1: " << s1;
495
496 const double x = common::math::lerp(p0.x(), s0, p1.x(), s1, s);
497 const double y = common::math::lerp(p0.y(), s0, p1.y(), s1, s);
498 const double heading =
499 common::math::slerp(p0.heading(), s0, p1.heading(), s1, s);
500 const double kappa = common::math::lerp(p0.kappa(), s0, p1.kappa(), s1, s);
501 const double dkappa = common::math::lerp(p0.dkappa(), s0, p1.dkappa(), s1, s);
502 std::vector<hdmap::LaneWaypoint> waypoints;
503 if (!p0.lane_waypoints().empty() && !p1.lane_waypoints().empty()) {
504 const auto& p0_waypoint = p0.lane_waypoints()[0];
505 if ((s - s0) + p0_waypoint.s <= p0_waypoint.lane->total_length()) {
506 const double lane_s = p0_waypoint.s + s - s0;
507 waypoints.emplace_back(p0_waypoint.lane, lane_s);
508 }
509 const auto& p1_waypoint = p1.lane_waypoints()[0];
510 if (p1_waypoint.lane->id().id() != p0_waypoint.lane->id().id() &&
511 p1_waypoint.s - (s1 - s) >= 0) {
512 const double lane_s = p1_waypoint.s - (s1 - s);
513 waypoints.emplace_back(p1_waypoint.lane, lane_s);
514 }
515 if (waypoints.empty()) {
516 const double lane_s = p0_waypoint.s;
517 waypoints.emplace_back(p0_waypoint.lane, lane_s);
518 }
519 }
520 return ReferencePoint(hdmap::MapPathPoint({x, y}, heading, waypoints), kappa,
521 dkappa);
522}
523
524const std::vector<ReferencePoint>& ReferenceLine::reference_points() const {
525 return reference_points_;
526}
527
528const MapPath& ReferenceLine::map_path() const { return map_path_; }
529
530bool ReferenceLine::GetLaneWidth(const double s, double* const lane_left_width,
531 double* const lane_right_width) const {
532 if (map_path_.path_points().empty()) {
533 return false;
534 }
535
536 if (!map_path_.GetLaneWidth(s, lane_left_width, lane_right_width)) {
537 return false;
538 }
539 return true;
540}
541
542bool ReferenceLine::GetOffsetToMap(const double s, double* l_offset) const {
543 if (map_path_.path_points().empty()) {
544 return false;
545 }
546
547 auto ref_point = GetNearestReferencePoint(s);
548 if (ref_point.lane_waypoints().empty()) {
549 return false;
550 }
551 *l_offset = ref_point.lane_waypoints().front().l;
552 return true;
553}
554
555bool ReferenceLine::GetRoadWidth(const double s, double* const road_left_width,
556 double* const road_right_width) const {
557 if (map_path_.path_points().empty()) {
558 return false;
559 }
560 return map_path_.GetRoadWidth(s, road_left_width, road_right_width);
561}
562
565 CHECK_NOTNULL(hdmap);
566
568
569 SLPoint sl_point;
570 sl_point.set_s(s);
571 sl_point.set_l(0.0);
573 SLToXY(sl_point, &pt);
574
575 common::PointENU point;
576 point.set_x(pt.x());
577 point.set_y(pt.y());
578 point.set_z(0.0);
579 std::vector<hdmap::RoadInfoConstPtr> roads;
580 hdmap->GetRoads(point, 4.0, &roads);
581 for (auto road : roads) {
582 if (road->type() != hdmap::Road::UNKNOWN) {
583 road_type = road->type();
584 break;
585 }
586 }
587 return road_type;
588}
589
591 const double s, hdmap::LaneBoundaryType::Type* const left_boundary_type,
592 hdmap::LaneBoundaryType::Type* const right_boundary_type) const {
593 auto ref_point = GetReferencePoint(s);
594 const auto waypoint = ref_point.lane_waypoints().front();
595 *left_boundary_type = hdmap::LeftBoundaryType(waypoint);
596 *right_boundary_type = hdmap::RightBoundaryType(waypoint);
597}
598
600 const double s, std::vector<hdmap::LaneInfoConstPtr>* lanes) const {
601 CHECK_NOTNULL(lanes);
602 auto ref_point = GetReferencePoint(s);
603 std::unordered_set<hdmap::LaneInfoConstPtr> lane_set;
604 for (const auto& lane_waypoint : ref_point.lane_waypoints()) {
605 if (common::util::InsertIfNotPresent(&lane_set, lane_waypoint.lane)) {
606 lanes->push_back(lane_waypoint.lane);
607 }
608 }
609}
610
611double ReferenceLine::GetDrivingWidth(const SLBoundary& sl_boundary) const {
612 double lane_left_width = 0.0;
613 double lane_right_width = 0.0;
614 GetLaneWidth(sl_boundary.start_s(), &lane_left_width, &lane_right_width);
615
616 double driving_width = std::max(lane_left_width - sl_boundary.end_l(),
617 lane_right_width + sl_boundary.start_l());
618 driving_width = std::min(lane_left_width + lane_right_width, driving_width);
619 ADEBUG << "Driving width [" << driving_width << "].";
620 return driving_width;
621}
622
623bool ReferenceLine::IsOnLane(const common::math::Vec2d& vec2d_point) const {
624 common::SLPoint sl_point;
625 if (!XYToSL(vec2d_point, &sl_point)) {
626 return false;
627 }
628 return IsOnLane(sl_point);
629}
630
631bool ReferenceLine::IsOnLane(const SLBoundary& sl_boundary) const {
632 if (sl_boundary.end_s() < 0 || sl_boundary.start_s() > Length()) {
633 return false;
634 }
635 double middle_s = (sl_boundary.start_s() + sl_boundary.end_s()) / 2.0;
636 double lane_left_width = 0.0;
637 double lane_right_width = 0.0;
638 map_path_.GetLaneWidth(middle_s, &lane_left_width, &lane_right_width);
639 return sl_boundary.start_l() <= lane_left_width &&
640 sl_boundary.end_l() >= -lane_right_width;
641}
642
643bool ReferenceLine::IsOnLane(const SLPoint& sl_point) const {
644 if (sl_point.s() <= 0 || sl_point.s() > map_path_.length()) {
645 return false;
646 }
647 double left_width = 0.0;
648 double right_width = 0.0;
649
650 if (!GetLaneWidth(sl_point.s(), &left_width, &right_width)) {
651 return false;
652 }
653
654 return sl_point.l() >= -right_width && sl_point.l() <= left_width;
655}
656
658 double gap) const {
659 return map_path_.OverlapWith(box2d, gap);
660}
661
662bool ReferenceLine::IsOnRoad(const common::math::Vec2d& vec2d_point) const {
663 common::SLPoint sl_point;
664 return XYToSL(vec2d_point, &sl_point) && IsOnRoad(sl_point);
665}
666
667bool ReferenceLine::IsOnRoad(const SLBoundary& sl_boundary) const {
668 if (sl_boundary.end_s() < 0 || sl_boundary.start_s() > Length()) {
669 return false;
670 }
671 double middle_s = (sl_boundary.start_s() + sl_boundary.end_s()) / 2.0;
672 double road_left_width = 0.0;
673 double road_right_width = 0.0;
674 map_path_.GetRoadWidth(middle_s, &road_left_width, &road_right_width);
675 return sl_boundary.start_l() <= road_left_width &&
676 sl_boundary.end_l() >= -road_right_width;
677}
678
679bool ReferenceLine::IsOnRoad(const SLPoint& sl_point) const {
680 if (sl_point.s() <= 0 || sl_point.s() > map_path_.length()) {
681 return false;
682 }
683 double road_left_width = 0.0;
684 double road_right_width = 0.0;
685
686 if (!GetRoadWidth(sl_point.s(), &road_left_width, &road_right_width)) {
687 return false;
688 }
689
690 return sl_point.l() >= -road_right_width && sl_point.l() <= road_left_width;
691}
692
693// Return a rough approximated SLBoundary using box length. It is guaranteed to
694// be larger than the accurate SL boundary.
696 const common::math::Box2d& box, const double start_s, const double end_s,
697 SLBoundary* const sl_boundary) const {
698 double s = 0.0;
699 double l = 0.0;
700 double distance = 0.0;
701 if (!map_path_.GetProjectionWithHueristicParams(box.center(), start_s, end_s,
702 &s, &l, &distance)) {
703 AERROR << "Cannot get projection point from path.";
704 return false;
705 }
706
707 auto projected_point = map_path_.GetSmoothPoint(s);
708 auto rotated_box = box;
709 rotated_box.RotateFromCenter(-projected_point.heading());
710
711 std::vector<common::math::Vec2d> corners;
712 rotated_box.GetAllCorners(&corners);
713
714 double min_s(std::numeric_limits<double>::max());
715 double max_s(std::numeric_limits<double>::lowest());
716 double min_l(std::numeric_limits<double>::max());
717 double max_l(std::numeric_limits<double>::lowest());
718
719 for (const auto& point : corners) {
720 // x <--> s, y <--> l
721 // Because the box is rotated to align the reference line
722 min_s = std::fmin(min_s, point.x() - rotated_box.center().x() + s);
723 max_s = std::fmax(max_s, point.x() - rotated_box.center().x() + s);
724 min_l = std::fmin(min_l, point.y() - rotated_box.center().y() + l);
725 max_l = std::fmax(max_l, point.y() - rotated_box.center().y() + l);
726 }
727 sl_boundary->set_start_s(min_s);
728 sl_boundary->set_end_s(max_s);
729 sl_boundary->set_start_l(min_l);
730 sl_boundary->set_end_l(max_l);
731 return true;
732}
733
735 SLBoundary* const sl_boundary,
736 double warm_start_s) const {
737 std::vector<common::math::Vec2d> corners;
738 box.GetAllCorners(&corners);
739 return GetSLBoundary(corners, sl_boundary, warm_start_s);
740}
741
743 SLBoundary* const sl_boundary,
744 double warm_start_s) const {
745 std::vector<common::math::Vec2d> corners = polygon.points();
746 return GetSLBoundary(corners, sl_boundary, warm_start_s);
747}
748
750 const std::vector<common::math::Vec2d>& corners,
751 SLBoundary* const sl_boundary, double warm_start_s) const {
752 double start_s(std::numeric_limits<double>::max());
753 double end_s(std::numeric_limits<double>::lowest());
754 double start_l(std::numeric_limits<double>::max());
755 double end_l(std::numeric_limits<double>::lowest());
756
757 // The order must be counter-clockwise
758 std::vector<SLPoint> sl_corners;
759 std::vector<common::math::Vec2d> obs_corners = corners;
760 // get first point which is closest to ego position
761 {
762 int first_index = 0;
763 double min_dist = std::numeric_limits<double>::max();
764 for (int i = 0; i < obs_corners.size(); ++i) {
765 double ego_dist = ego_position_.DistanceTo(obs_corners[i]);
766 if (ego_dist < min_dist) {
767 min_dist = ego_dist;
768 first_index = i;
769 }
770 }
771 std::rotate(obs_corners.begin(), obs_corners.begin() + first_index,
772 obs_corners.end());
773 const common::math::Vec2d& first_point = obs_corners.front();
774 ADEBUG << "first_point: " << std::setprecision(9) << first_point.x() << ", "
775 << first_point.y();
776 SLPoint first_sl_point;
777 if (!XYToSL(first_point, &first_sl_point, warm_start_s)) {
778 AERROR << "Failed to get projection for point: "
779 << first_point.DebugString() << " on reference line.";
780 return false;
781 }
782 sl_corners.push_back(std::move(first_sl_point));
783 }
784
785 double hueristic_start_s = 0.0;
786 double hueristic_end_s = 0.0;
787 double distance = 0.0;
788 SLPoint sl_point;
789 for (size_t i = 1; i < obs_corners.size(); ++i) {
790 distance = obs_corners[i].DistanceTo(obs_corners[i - 1]);
791 hueristic_start_s = sl_corners.back().s() - 2.0 * distance;
792 hueristic_end_s = sl_corners.back().s() + 2.0 * distance;
793 if (!XYToSL(obs_corners[i], &sl_point, hueristic_start_s,
794 hueristic_end_s)) {
795 AERROR << "Failed to get projection for point: "
796 << obs_corners[i].DebugString() << " on reference line.";
797 return false;
798 }
799 sl_corners.push_back(std::move(sl_point));
800 }
801
802 for (size_t i = 0; i < obs_corners.size(); ++i) {
803 auto index0 = i;
804 auto index1 = (i + 1) % obs_corners.size();
805 const auto& p0 = obs_corners[index0];
806 const auto& p1 = obs_corners[index1];
807
808 const auto p_mid = (p0 + p1) * 0.5;
809 distance = obs_corners[index0].DistanceTo(p_mid);
810 hueristic_start_s = sl_corners[index0].s() - 2.0 * distance;
811 hueristic_end_s = sl_corners[index0].s() + 2.0 * distance;
812 SLPoint sl_point_mid;
813 if (!XYToSL(p_mid, &sl_point_mid, hueristic_start_s, hueristic_end_s)) {
814 AERROR << "Failed to get projection for point: " << p_mid.DebugString()
815 << " on reference line.";
816 return false;
817 }
818
819 Vec2d v0(sl_corners[index1].s() - sl_corners[index0].s(),
820 sl_corners[index1].l() - sl_corners[index0].l());
821
822 Vec2d v1(sl_point_mid.s() - sl_corners[index0].s(),
823 sl_point_mid.l() - sl_corners[index0].l());
824
825 *sl_boundary->add_boundary_point() = sl_corners[index0];
826
827 // sl_point is outside of polygon; add to the vertex list
828 if (v0.CrossProd(v1) < 0.0) {
829 *sl_boundary->add_boundary_point() = sl_point_mid;
830 }
831 }
832
833 for (const auto& sl_point : sl_boundary->boundary_point()) {
834 start_s = std::fmin(start_s, sl_point.s());
835 end_s = std::fmax(end_s, sl_point.s());
836 start_l = std::fmin(start_l, sl_point.l());
837 end_l = std::fmax(end_l, sl_point.l());
838 }
839
840 sl_boundary->set_start_s(start_s);
841 sl_boundary->set_end_s(end_s);
842 sl_boundary->set_start_l(start_l);
843 sl_boundary->set_end_l(end_l);
844 return true;
845}
846
847std::vector<hdmap::LaneSegment> ReferenceLine::GetLaneSegments(
848 const double start_s, const double end_s) const {
849 return map_path_.GetLaneSegments(start_s, end_s);
850}
851
853 SLBoundary* const sl_boundary) const {
854 double start_s(std::numeric_limits<double>::max());
855 double end_s(std::numeric_limits<double>::lowest());
856 double start_l(std::numeric_limits<double>::max());
857 double end_l(std::numeric_limits<double>::lowest());
858 for (const auto& point : polygon.point()) {
859 SLPoint sl_point;
860 if (!XYToSL(point, &sl_point)) {
861 AERROR << "Failed to get projection for point: " << point.DebugString()
862 << " on reference line.";
863 return false;
864 }
865 start_s = std::fmin(start_s, sl_point.s());
866 end_s = std::fmax(end_s, sl_point.s());
867 start_l = std::fmin(start_l, sl_point.l());
868 end_l = std::fmax(end_l, sl_point.l());
869 }
870 sl_boundary->set_start_s(start_s);
871 sl_boundary->set_end_s(end_s);
872 sl_boundary->set_start_l(start_l);
873 sl_boundary->set_end_l(end_l);
874 return true;
875}
876
878 SLBoundary sl_boundary;
879 if (!GetSLBoundary(box, &sl_boundary)) {
880 AERROR << "Failed to get sl boundary for box: " << box.DebugString();
881 return false;
882 }
883 if (sl_boundary.end_s() < 0 || sl_boundary.start_s() > Length()) {
884 return false;
885 }
886 if (sl_boundary.start_l() * sl_boundary.end_l() < 0) {
887 return false;
888 }
889
890 double lane_left_width = 0.0;
891 double lane_right_width = 0.0;
892 const double mid_s = (sl_boundary.start_s() + sl_boundary.end_s()) / 2.0;
893 if (mid_s < 0 || mid_s > Length()) {
894 ADEBUG << "ref_s is out of range: " << mid_s;
895 return false;
896 }
897 if (!map_path_.GetLaneWidth(mid_s, &lane_left_width, &lane_right_width)) {
898 AERROR << "Failed to get width at s = " << mid_s;
899 return false;
900 }
901 if (sl_boundary.start_l() > 0) {
902 return sl_boundary.start_l() < lane_left_width;
903 } else {
904 return sl_boundary.end_l() > -lane_right_width;
905 }
906}
907
908std::string ReferenceLine::DebugString() const {
909 const auto limit =
910 std::min(reference_points_.size(),
911 static_cast<size_t>(FLAGS_trajectory_point_num_for_debug));
912 return absl::StrCat(
913 "point num:", reference_points_.size(),
914 absl::StrJoin(reference_points_.begin(),
915 reference_points_.begin() + limit, "",
917}
918
919double ReferenceLine::GetSpeedLimitFromS(const double s) const {
920 for (const auto& speed_limit : speed_limit_) {
921 if (s >= speed_limit.start_s && s <= speed_limit.end_s) {
922 return speed_limit.speed_limit;
923 }
924 }
925 const auto& map_path_point = GetReferencePoint(s);
926
927 double speed_limit = FLAGS_planning_upper_speed_limit;
928 bool speed_limit_found = false;
929 for (const auto& lane_waypoint : map_path_point.lane_waypoints()) {
930 if (lane_waypoint.lane == nullptr) {
931 AWARN << "lane_waypoint.lane is nullptr.";
932 continue;
933 }
934 speed_limit_found = true;
935 speed_limit =
936 std::fmin(lane_waypoint.lane->lane().speed_limit(), speed_limit);
937 }
938
939 if (!speed_limit_found) {
940 // use default speed limit based on road_type
941 speed_limit = FLAGS_default_city_road_speed_limit;
942 hdmap::Road::Type road_type = GetRoadType(s);
943 if (road_type == hdmap::Road::HIGHWAY) {
944 speed_limit = FLAGS_default_highway_speed_limit;
945 }
946 }
947
948 return speed_limit;
949}
950
951void ReferenceLine::AddSpeedLimit(double start_s, double end_s,
952 double speed_limit) {
953 std::vector<SpeedLimit> new_speed_limit;
954 for (const auto& limit : speed_limit_) {
955 if (start_s >= limit.end_s || end_s <= limit.start_s) {
956 new_speed_limit.emplace_back(limit);
957 } else {
958 // start_s < speed_limit.end_s && end_s > speed_limit.start_s
959 double min_speed = std::min(limit.speed_limit, speed_limit);
960 if (start_s >= limit.start_s) {
961 new_speed_limit.emplace_back(limit.start_s, start_s, min_speed);
962 if (end_s <= limit.end_s) {
963 new_speed_limit.emplace_back(start_s, end_s, min_speed);
964 new_speed_limit.emplace_back(end_s, limit.end_s, limit.speed_limit);
965 } else {
966 new_speed_limit.emplace_back(start_s, limit.end_s, min_speed);
967 }
968 } else {
969 new_speed_limit.emplace_back(start_s, limit.start_s, speed_limit);
970 if (end_s <= limit.end_s) {
971 new_speed_limit.emplace_back(limit.start_s, end_s, min_speed);
972 new_speed_limit.emplace_back(end_s, limit.end_s, limit.speed_limit);
973 } else {
974 new_speed_limit.emplace_back(limit.start_s, limit.end_s, min_speed);
975 }
976 }
977 start_s = limit.end_s;
978 end_s = std::max(end_s, limit.end_s);
979 }
980 }
981 speed_limit_.clear();
982 if (end_s > start_s) {
983 new_speed_limit.emplace_back(start_s, end_s, speed_limit);
984 }
985 for (const auto& limit : new_speed_limit) {
986 if (limit.start_s < limit.end_s) {
987 speed_limit_.emplace_back(limit);
988 }
989 }
990 std::sort(speed_limit_.begin(), speed_limit_.end(),
991 [](const SpeedLimit& a, const SpeedLimit& b) {
992 if (a.start_s != b.start_s) {
993 return a.start_s < b.start_s;
994 }
995 if (a.end_s != b.end_s) {
996 return a.end_s < b.end_s;
997 }
998 return a.speed_limit < b.speed_limit;
999 });
1000}
1001
1002} // namespace planning
1003} // namespace apollo
Defines the templated Angle class.
static Angle from_rad(const double value)
Constructs an Angle object from an angle in radians (factory).
Definition angle.h:78
Rectangular (undirected) bounding box in 2-D.
Definition box2d.h:52
std::string DebugString() const
Gets a human-readable description of the box
Definition box2d.cc:418
void GetAllCorners(std::vector< Vec2d > *const corners) const
Getter of the corners of the box
Definition box2d.cc:140
void RotateFromCenter(const double rotate_angle)
Rotate from center.
Definition box2d.cc:386
const Vec2d & center() const
Getter of the center of the box
Definition box2d.h:106
static void cartesian_to_frenet(const double rs, const double rx, const double ry, const double rtheta, const double rkappa, const double rdkappa, const double x, const double y, const double v, const double a, const double theta, const double kappa, std::array< double, 3 > *const ptr_s_condition, std::array< double, 3 > *const ptr_d_condition)
Convert a vehicle state in Cartesian frame to Frenet frame.
static double CalculateSecondOrderLateralDerivative(const double theta_ref, const double theta, const double kappa_ref, const double kappa, const double dkappa_ref, const double l)
static double CalculateLateralDerivative(const double theta_ref, const double theta, const double l, const double kappa_ref)
: given sl, theta, and road's theta, kappa, extract derivative l, second order derivative l:
The class of polygon in 2-D.
Definition polygon2d.h:42
const std::vector< Vec2d > & points() const
Get the vertices of the polygon.
Definition polygon2d.h:65
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
void set_x(const double x)
Setter for x component
Definition vec2d.h:60
std::string DebugString() const
Returns a human-readable string representing this object
Definition vec2d.cc:125
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 set_y(const double y)
Setter for y component
Definition vec2d.h:63
double CrossProd(const Vec2d &other) const
Returns the "cross" product between these two Vec2d (non-standard).
Definition vec2d.cc:57
static const HDMap * BaseMapPtr()
High-precision map loader interface.
Definition hdmap.h:54
int GetRoads(const apollo::common::PointENU &point, double distance, std::vector< RoadInfoConstPtr > *roads) const
get all roads in certain range
Definition hdmap.cc:144
double heading() const
Definition path.h:118
void set_heading(const double heading)
Definition path.h:119
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 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
bool GetLaneWidth(const double s, double *lane_left_width, double *lane_right_width) const
Definition path.cc:981
std::vector< hdmap::LaneSegment > GetLaneSegments(const double start_s, const double end_s) const
Definition path.cc:690
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
MapPathPoint GetSmoothPoint(const InterpolatedIndex &index) const
Definition path.cc:591
bool OverlapWith(const common::math::Box2d &box, double width) const
Definition path.cc:1049
const std::vector< common::math::Vec2d > & unit_directions() const
Definition path.h:286
int num_points() const
Definition path.h:277
const std::vector< MapPathPoint > & path_points() const
Definition path.h:279
const std::vector< double > & accumulated_s() const
Definition path.h:289
bool GetApproximateSLBoundary(const common::math::Box2d &box, const double start_s, const double end_s, SLBoundary *const sl_boundary) const
bool IsOnRoad(const common::SLPoint &sl_point) const
: check if a box/point is on road (not on sideways/medians) along reference line
bool Segment(const common::math::Vec2d &point, const double distance_backward, const double distance_forward)
const hdmap::Path & map_path() const
bool IsOnLane(const common::SLPoint &sl_point) const
: check if a box/point is on lane along reference line
void AddSpeedLimit(double start_s, double end_s, double speed_limit)
void GetLaneBoundaryType(const double s, hdmap::LaneBoundaryType::Type *const left_boundary_type, hdmap::LaneBoundaryType::Type *const right_boundary_type) const
ReferencePoint GetReferencePoint(const double s) const
std::vector< hdmap::LaneSegment > GetLaneSegments(const double start_s, const double end_s) const
std::pair< std::array< double, 3 >, std::array< double, 3 > > ToFrenetFrame(const common::TrajectoryPoint &traj_point) const
double GetDrivingWidth(const SLBoundary &sl_boundary) const
size_t GetNearestReferenceIndex(const double s) const
bool GetSLBoundary(const common::math::Box2d &box, SLBoundary *const sl_boundary, double warm_start_s=-1.0) const
Get the SL Boundary of the box.
bool Stitch(const ReferenceLine &other)
Stitch current reference line with the other reference line The stitching strategy is to use current ...
bool GetRoadWidth(const double s, double *const road_left_width, double *const road_right_width) const
void GetLaneFromS(const double s, std::vector< hdmap::LaneInfoConstPtr > *lanes) const
bool SLToXY(const common::SLPoint &sl_point, common::math::Vec2d *const xy_point) const
bool XYToSL(const common::math::Vec2d &xy_point, common::SLPoint *const sl_point, double warm_start_s=-1.0) const
Transvert Cartesian coordinates to Frenet.
std::vector< ReferencePoint > GetReferencePoints(double start_s, double end_s) const
hdmap::Road::Type GetRoadType(const double s) const
ReferencePoint GetNearestReferencePoint(const common::math::Vec2d &xy) const
bool HasOverlap(const common::math::Box2d &box) const
check if any part of the box has overlap with the road.
common::FrenetFramePoint GetFrenetPoint(const common::PathPoint &path_point) const
double GetSpeedLimitFromS(const double s) const
bool IsBlockRoad(const common::math::Box2d &box2d, double gap) const
Check if a box is blocking the road surface.
bool GetLaneWidth(const double s, double *const lane_left_width, double *const lane_right_width) const
const std::vector< ReferencePoint > & reference_points() const
bool GetOffsetToMap(const double s, double *l_offset) const
Planning module main class.
Linear interpolation functions.
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
Some map util functions.
Some util functions.
float cos(Angle16 a)
Definition angle.cc:42
T lerp(const T &x0, const double t0, const T &x1, const double t1, const double t)
Linear interpolation between two points of type T.
constexpr double kMathEpsilon
Definition vec2d.h:35
float sin(Angle16 a)
Definition angle.cc:25
double slerp(const double a0, const double t0, const double a1, const double t1, const double t)
Spherical linear interpolation between two angles.
double DistanceXY(const U &u, const V &v)
calculate the distance beteween Point u and Point v, which are all have member function x() and y() i...
Definition util.h:97
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
hdmap::Path MapPath
class register implement
Definition arena_queue.h:37
Definition future.h:29
Some string util functions.
repeated apollo::common::PointENU point
repeated apollo::common::SLPoint boundary_point
Defines the Vec2d class.