Apollo 11.0
自动驾驶开放平台
reference_line_provider.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
23
24#include <algorithm>
25#include <limits>
26#include <utility>
27
28#include "cyber/common/file.h"
30#include "cyber/task/task.h"
31#include "cyber/time/clock.h"
40
45namespace apollo {
46namespace planning {
47
57
59
61 const common::VehicleStateProvider *vehicle_state_provider,
62 const ReferenceLineConfig *reference_line_config,
63 const std::shared_ptr<relative_map::MapMsg> &relative_map)
64 : vehicle_state_provider_(vehicle_state_provider) {
65 current_pnc_map_ = nullptr;
66 if (!FLAGS_use_navigation_mode) {
67 relative_map_ = nullptr;
68 } else {
69 relative_map_ = relative_map;
70 }
71
72 ACHECK(cyber::common::GetProtoFromFile(FLAGS_smoother_config_filename,
73 &smoother_config_))
74 << "Failed to load smoother config file "
75 << FLAGS_smoother_config_filename;
76 if (smoother_config_.has_qp_spline()) {
77 smoother_.reset(new QpSplineReferenceLineSmoother(smoother_config_));
78 } else if (smoother_config_.has_spiral()) {
79 smoother_.reset(new SpiralReferenceLineSmoother(smoother_config_));
80 } else if (smoother_config_.has_discrete_points()) {
81 smoother_.reset(new DiscretePointsReferenceLineSmoother(smoother_config_));
82 } else {
83 ACHECK(false) << "unknown smoother config "
84 << smoother_config_.DebugString();
85 }
86 // Load pnc map plugins.
87 pnc_map_list_.clear();
88 // Set "apollo::planning::LaneFollowMap" as default if pnc_map_class is empty.
89 if (nullptr == reference_line_config ||
90 reference_line_config->pnc_map_class().empty()) {
91 const auto &pnc_map =
94 "apollo::planning::LaneFollowMap");
95 pnc_map_list_.emplace_back(pnc_map);
96 } else {
97 const auto &pnc_map_names = reference_line_config->pnc_map_class();
98 for (const auto &map_name : pnc_map_names) {
99 const auto &pnc_map =
102 pnc_map_list_.emplace_back(pnc_map);
103 }
104 }
105
106 is_initialized_ = true;
107}
108
110 const planning::PlanningCommand &command) {
111 std::lock_guard<std::mutex> routing_lock(routing_mutex_);
112 bool find_matched_pnc_map = false;
113 for (const auto &pnc_map : pnc_map_list_) {
114 if (pnc_map->CanProcess(command)) {
115 current_pnc_map_ = pnc_map;
116 find_matched_pnc_map = true;
117 break;
118 }
119 }
120 if (nullptr == current_pnc_map_) {
121 AERROR << "Cannot find pnc map to process input command!"
122 << command.DebugString();
123 return false;
124 }
125 if (!find_matched_pnc_map) {
126 AWARN << "Find no pnc map for the input command and the old one will be "
127 "used!";
128 }
129 // Update routing in pnc_map
130 std::lock_guard<std::mutex> lock(pnc_map_mutex_);
131 if (current_pnc_map_->IsNewPlanningCommand(command)) {
132 is_new_command_ = true;
133 if (!current_pnc_map_->UpdatePlanningCommand(command)) {
134 AERROR << "Failed to update routing in pnc map: "
135 << command.DebugString();
136 return false;
137 }
138 }
139 planning_command_ = command;
140 has_planning_command_ = true;
141 return true;
142}
143
144std::vector<routing::LaneWaypoint>
146 if (!FLAGS_use_navigation_mode && nullptr != current_pnc_map_) {
147 std::lock_guard<std::mutex> lock(pnc_map_mutex_);
148 return current_pnc_map_->FutureRouteWaypoints();
149 }
150
151 // return an empty routing::LaneWaypoint vector in Navigation mode.
152 return std::vector<routing::LaneWaypoint>();
153}
154
156 std::shared_ptr<routing::LaneWaypoint> &end_point) const {
157 if (nullptr == current_pnc_map_) {
158 end_point = nullptr;
159 return;
160 }
161 current_pnc_map_->GetEndLaneWayPoint(end_point);
162}
163
165 const hdmap::Id &id) const {
166 if (nullptr == current_pnc_map_) {
167 return nullptr;
168 }
169 return current_pnc_map_->GetLaneById(id);
170}
171
173 const VehicleState &vehicle_state) {
174 std::lock_guard<std::mutex> lock(vehicle_state_mutex_);
175 vehicle_state_ = vehicle_state;
176}
177
179 if (FLAGS_use_navigation_mode) {
180 return true;
181 }
182 if (!is_initialized_) {
183 AERROR << "ReferenceLineProvider has NOT been initiated.";
184 return false;
185 }
186
187 if (FLAGS_enable_reference_line_provider_thread) {
188 task_future_ = cyber::Async(&ReferenceLineProvider::GenerateThread, this);
189 }
190 return true;
191}
192
194 is_stop_ = true;
195 if (FLAGS_enable_reference_line_provider_thread) {
196 task_future_.get();
197 }
198}
199
201 std::lock_guard<std::mutex> lock(routing_mutex_);
202 has_planning_command_ = false;
203 is_new_command_ = false;
204 reference_lines_.clear();
205 route_segments_.clear();
206 is_reference_line_updated_ = false;
207 planning_command_.Clear();
208 while (!reference_line_history_.empty()) {
209 reference_line_history_.pop();
210 }
211}
212
213void ReferenceLineProvider::UpdateReferenceLine(
214 const std::list<ReferenceLine> &reference_lines,
215 const std::list<hdmap::RouteSegments> &route_segments) {
216 if (reference_lines.size() != route_segments.size()) {
217 AERROR << "The calculated reference line size(" << reference_lines.size()
218 << ") and route_segments size(" << route_segments.size()
219 << ") are different";
220 return;
221 }
222 if (reference_lines.empty()) {
223 return;
224 }
225 std::lock_guard<std::mutex> lock(reference_lines_mutex_);
226 if (reference_lines_.size() != reference_lines.size()) {
227 reference_lines_ = reference_lines;
228 route_segments_ = route_segments;
229 } else {
230 auto segment_iter = route_segments.begin();
231 auto internal_iter = reference_lines_.begin();
232 auto internal_segment_iter = route_segments_.begin();
233 for (auto iter = reference_lines.begin();
234 iter != reference_lines.end() &&
235 segment_iter != route_segments.end() &&
236 internal_iter != reference_lines_.end() &&
237 internal_segment_iter != route_segments_.end();
238 ++iter, ++segment_iter, ++internal_iter, ++internal_segment_iter) {
239 if (iter->reference_points().empty()) {
240 *internal_iter = *iter;
241 *internal_segment_iter = *segment_iter;
242 continue;
243 }
245 iter->reference_points().front(),
246 internal_iter->reference_points().front()) &&
247 common::util::SamePointXY(iter->reference_points().back(),
248 internal_iter->reference_points().back()) &&
249 std::fabs(iter->Length() - internal_iter->Length()) <
251 continue;
252 }
253 *internal_iter = *iter;
254 *internal_segment_iter = *segment_iter;
255 }
256 }
257 // update history
258 reference_line_history_.push(reference_lines_);
259 route_segments_history_.push(route_segments_);
260 static constexpr int kMaxHistoryNum = 3;
261 if (reference_line_history_.size() > kMaxHistoryNum) {
262 reference_line_history_.pop();
263 route_segments_history_.pop();
264 }
265}
266
267void ReferenceLineProvider::GenerateThread() {
268 while (!is_stop_) {
269 static constexpr int32_t kSleepTime = 50; // milliseconds
270 cyber::SleepFor(std::chrono::milliseconds(kSleepTime));
271 const double start_time = Clock::NowInSeconds();
272 if (!has_planning_command_) {
273 continue;
274 }
275 std::list<ReferenceLine> reference_lines;
276 std::list<hdmap::RouteSegments> segments;
277 if (!CreateReferenceLine(&reference_lines, &segments)) {
278 is_reference_line_updated_ = false;
279 AERROR << "Fail to get reference line";
280 continue;
281 }
282 UpdateReferenceLine(reference_lines, segments);
283 const double end_time = Clock::NowInSeconds();
284 std::lock_guard<std::mutex> lock(reference_lines_mutex_);
285 last_calculation_time_ = end_time - start_time;
286 is_reference_line_updated_ = true;
287 }
288}
289
291 if (FLAGS_enable_reference_line_provider_thread &&
292 !FLAGS_use_navigation_mode) {
293 std::lock_guard<std::mutex> lock(reference_lines_mutex_);
294 return last_calculation_time_;
295 } else {
296 return last_calculation_time_;
297 }
298}
299
301 std::list<ReferenceLine> *reference_lines,
302 std::list<hdmap::RouteSegments> *segments) {
303 CHECK_NOTNULL(reference_lines);
304 CHECK_NOTNULL(segments);
305 if (!has_planning_command_) {
306 return true;
307 }
308 if (FLAGS_use_navigation_mode) {
309 double start_time = Clock::NowInSeconds();
310 bool result = GetReferenceLinesFromRelativeMap(reference_lines, segments);
311 if (!result) {
312 AERROR << "Failed to get reference line from relative map";
313 }
314 double end_time = Clock::NowInSeconds();
315 last_calculation_time_ = end_time - start_time;
316 return result;
317 }
318
319 if (FLAGS_enable_reference_line_provider_thread) {
320 std::lock_guard<std::mutex> lock(reference_lines_mutex_);
321 if (!reference_lines_.empty()) {
322 reference_lines->assign(reference_lines_.begin(), reference_lines_.end());
323 segments->assign(route_segments_.begin(), route_segments_.end());
324 return true;
325 }
326 } else {
327 double start_time = Clock::NowInSeconds();
328 if (CreateReferenceLine(reference_lines, segments)) {
329 UpdateReferenceLine(*reference_lines, *segments);
330 double end_time = Clock::NowInSeconds();
331 last_calculation_time_ = end_time - start_time;
332 return true;
333 }
334 }
335
336 AINFO << "Reference line is NOT ready.";
337 if (reference_line_history_.empty()) {
338 AINFO << "Failed to use reference line latest history";
339 return false;
340 }
341
342 reference_lines->assign(reference_line_history_.back().begin(),
343 reference_line_history_.back().end());
344 segments->assign(route_segments_history_.back().begin(),
345 route_segments_history_.back().end());
346 AWARN << "Use reference line from history!";
347 return true;
348}
349
350void ReferenceLineProvider::PrioritizeChangeLane(
351 std::list<hdmap::RouteSegments> *route_segments) {
352 CHECK_NOTNULL(route_segments);
353 auto iter = route_segments->begin();
354 while (iter != route_segments->end()) {
355 if (!iter->IsOnSegment()) {
356 route_segments->splice(route_segments->begin(), *route_segments, iter);
357 break;
358 }
359 ++iter;
360 }
361}
362
363bool ReferenceLineProvider::GetReferenceLinesFromRelativeMap(
364 std::list<ReferenceLine> *reference_lines,
365 std::list<hdmap::RouteSegments> *segments) {
366 CHECK_GE(relative_map_->navigation_path_size(), 0);
367 CHECK_NOTNULL(reference_lines);
368 CHECK_NOTNULL(segments);
369
370 if (relative_map_->navigation_path().empty()) {
371 AERROR << "There isn't any navigation path in current relative map.";
372 return false;
373 }
374
375 auto *hdmap = HDMapUtil::BaseMapPtr(*relative_map_);
376 if (!hdmap) {
377 AERROR << "hdmap is null";
378 return false;
379 }
380
381 // 1.get adc current lane info ,such as lane_id,lane_priority,neighbor lanes
382 std::unordered_set<std::string> navigation_lane_ids;
383 for (const auto &path_pair : relative_map_->navigation_path()) {
384 const auto lane_id = path_pair.first;
385 navigation_lane_ids.insert(lane_id);
386 }
387 if (navigation_lane_ids.empty()) {
388 AERROR << "navigation path ids is empty";
389 return false;
390 }
391 // get current adc lane info by vehicle state
392 common::VehicleState vehicle_state = vehicle_state_provider_->vehicle_state();
393 hdmap::LaneWaypoint adc_lane_way_point;
394 if (!GetNearestWayPointFromNavigationPath(vehicle_state, navigation_lane_ids,
395 &adc_lane_way_point)) {
396 return false;
397 }
398 const std::string adc_lane_id = adc_lane_way_point.lane->id().id();
399 auto *adc_navigation_path = apollo::common::util::FindOrNull(
400 relative_map_->navigation_path(), adc_lane_id);
401 if (adc_navigation_path == nullptr) {
402 AERROR << "adc lane cannot be found in relative_map_->navigation_path";
403 return false;
404 }
405 const uint32_t adc_lane_priority = adc_navigation_path->path_priority();
406 // get adc left neighbor lanes
407 std::vector<std::string> left_neighbor_lane_ids;
408 auto left_lane_ptr = adc_lane_way_point.lane;
409 while (left_lane_ptr != nullptr &&
410 left_lane_ptr->lane().left_neighbor_forward_lane_id_size() > 0) {
411 auto neighbor_lane_id =
412 left_lane_ptr->lane().left_neighbor_forward_lane_id(0);
413 left_neighbor_lane_ids.emplace_back(neighbor_lane_id.id());
414 left_lane_ptr = hdmap->GetLaneById(neighbor_lane_id);
415 }
416 ADEBUG << adc_lane_id
417 << " left neighbor size : " << left_neighbor_lane_ids.size();
418 for (const auto &neighbor : left_neighbor_lane_ids) {
419 ADEBUG << adc_lane_id << " left neighbor : " << neighbor;
420 }
421 // get adc right neighbor lanes
422 std::vector<std::string> right_neighbor_lane_ids;
423 auto right_lane_ptr = adc_lane_way_point.lane;
424 while (right_lane_ptr != nullptr &&
425 right_lane_ptr->lane().right_neighbor_forward_lane_id_size() > 0) {
426 auto neighbor_lane_id =
427 right_lane_ptr->lane().right_neighbor_forward_lane_id(0);
428 right_neighbor_lane_ids.emplace_back(neighbor_lane_id.id());
429 right_lane_ptr = hdmap->GetLaneById(neighbor_lane_id);
430 }
431 ADEBUG << adc_lane_id
432 << " right neighbor size : " << right_neighbor_lane_ids.size();
433 for (const auto &neighbor : right_neighbor_lane_ids) {
434 ADEBUG << adc_lane_id << " right neighbor : " << neighbor;
435 }
436 // 2.get the higher priority lane info list which priority higher
437 // than current lane and get the highest one as the target lane
438 using LaneIdPair = std::pair<std::string, uint32_t>;
439 std::vector<LaneIdPair> high_priority_lane_pairs;
440 ADEBUG << "relative_map_->navigation_path_size = "
441 << relative_map_->navigation_path_size();
442 for (const auto &path_pair : relative_map_->navigation_path()) {
443 const auto lane_id = path_pair.first;
444 const uint32_t priority = path_pair.second.path_priority();
445 ADEBUG << "lane_id = " << lane_id << " priority = " << priority
446 << " adc_lane_id = " << adc_lane_id
447 << " adc_lane_priority = " << adc_lane_priority;
448 // the smaller the number, the higher the priority
449 if (adc_lane_id != lane_id && priority < adc_lane_priority) {
450 high_priority_lane_pairs.emplace_back(lane_id, priority);
451 }
452 }
453 // get the target lane
454 bool is_lane_change_needed = false;
455 LaneIdPair target_lane_pair;
456 if (!high_priority_lane_pairs.empty()) {
457 std::sort(high_priority_lane_pairs.begin(), high_priority_lane_pairs.end(),
458 [](const LaneIdPair &left, const LaneIdPair &right) {
459 return left.second < right.second;
460 });
461 ADEBUG << "need to change lane";
462 // the highest priority lane as the target navigation lane
463 target_lane_pair = high_priority_lane_pairs.front();
464 is_lane_change_needed = true;
465 }
466 // 3.get current lane's the nearest neighbor lane to the target lane
467 // and make sure it position is left or right on the current lane
468 routing::ChangeLaneType lane_change_type = routing::FORWARD;
469 std::string nearest_neighbor_lane_id;
470 if (is_lane_change_needed) {
471 // target on the left of adc
472 if (left_neighbor_lane_ids.end() !=
473 std::find(left_neighbor_lane_ids.begin(), left_neighbor_lane_ids.end(),
474 target_lane_pair.first)) {
475 // take the id of the first adjacent lane on the left of adc as
476 // the nearest_neighbor_lane_id
477 lane_change_type = routing::LEFT;
478 nearest_neighbor_lane_id =
479 adc_lane_way_point.lane->lane().left_neighbor_forward_lane_id(0).id();
480 } else if (right_neighbor_lane_ids.end() !=
481 std::find(right_neighbor_lane_ids.begin(),
482 right_neighbor_lane_ids.end(),
483 target_lane_pair.first)) {
484 // target lane on the right of adc
485 // take the id of the first adjacent lane on the right of adc as
486 // the nearest_neighbor_lane_id
487 lane_change_type = routing::RIGHT;
488 nearest_neighbor_lane_id = adc_lane_way_point.lane->lane()
489 .right_neighbor_forward_lane_id(0)
490 .id();
491 }
492 }
493
494 for (const auto &path_pair : relative_map_->navigation_path()) {
495 const auto &lane_id = path_pair.first;
496 const auto &path_points = path_pair.second.path().path_point();
497 auto lane_ptr = hdmap->GetLaneById(hdmap::MakeMapId(lane_id));
498 RouteSegments segment;
499 segment.emplace_back(lane_ptr, 0.0, lane_ptr->total_length());
500 segment.SetCanExit(true);
501 segment.SetId(lane_id);
502 segment.SetNextAction(routing::FORWARD);
503 segment.SetStopForDestination(false);
504 segment.SetPreviousAction(routing::FORWARD);
505
506 if (is_lane_change_needed) {
507 if (lane_id == nearest_neighbor_lane_id) {
508 ADEBUG << "adc lane_id = " << adc_lane_id
509 << " nearest_neighbor_lane_id = " << lane_id;
510 segment.SetIsNeighborSegment(true);
511 segment.SetPreviousAction(lane_change_type);
512 } else if (lane_id == adc_lane_id) {
513 segment.SetIsOnSegment(true);
514 segment.SetNextAction(lane_change_type);
515 }
516 }
517
518 segments->emplace_back(segment);
519 std::vector<ReferencePoint> ref_points;
520 for (const auto &path_point : path_points) {
521 ref_points.emplace_back(
522 MapPathPoint{Vec2d{path_point.x(), path_point.y()},
523 path_point.theta(),
524 LaneWaypoint(lane_ptr, path_point.s())},
525 path_point.kappa(), path_point.dkappa());
526 }
527 reference_lines->emplace_back(ref_points.begin(), ref_points.end());
528 reference_lines->back().SetPriority(path_pair.second.path_priority());
529 }
530 return !segments->empty();
531}
532
533bool ReferenceLineProvider::GetNearestWayPointFromNavigationPath(
534 const common::VehicleState &state,
535 const std::unordered_set<std::string> &navigation_lane_ids,
536 hdmap::LaneWaypoint *waypoint) {
537 const double kMaxDistance = 10.0;
538 waypoint->lane = nullptr;
539 std::vector<hdmap::LaneInfoConstPtr> lanes;
540 auto point = common::util::PointFactory::ToPointENU(state);
541 if (std::isnan(point.x()) || std::isnan(point.y())) {
542 AERROR << "vehicle state is invalid";
543 return false;
544 }
545 auto *hdmap = HDMapUtil::BaseMapPtr();
546 if (!hdmap) {
547 AERROR << "hdmap is null";
548 return false;
549 }
550
551 // get all adc direction lanes from map in kMaxDistance range
552 // by vehicle point in map
553 const int status = hdmap->GetLanesWithHeading(
554 point, kMaxDistance, state.heading(), M_PI / 2.0, &lanes);
555 if (status < 0) {
556 AERROR << "failed to get lane from point " << point.ShortDebugString();
557 return false;
558 }
559
560 // get lanes that exist in both map and navigation paths as valid lanes
561 std::vector<hdmap::LaneInfoConstPtr> valid_lanes;
562 std::copy_if(lanes.begin(), lanes.end(), std::back_inserter(valid_lanes),
563 [&](hdmap::LaneInfoConstPtr ptr) {
564 return navigation_lane_ids.count(ptr->lane().id().id()) > 0;
565 });
566 if (valid_lanes.empty()) {
567 AERROR << "no valid lane found within " << kMaxDistance
568 << " meters with heading " << state.heading();
569 return false;
570 }
571
572 // get nearest lane waypoints for current adc position
573 double min_distance = std::numeric_limits<double>::infinity();
574 for (const auto &lane : valid_lanes) {
575 // project adc point to lane to check if it is out of lane range
576 double s = 0.0;
577 double l = 0.0;
578 if (!lane->GetProjection({point.x(), point.y()}, state.heading(), &s, &l)) {
579 continue;
580 }
581 static constexpr double kEpsilon = 1e-6;
582 if (s > (lane->total_length() + kEpsilon) || (s + kEpsilon) < 0.0) {
583 continue;
584 }
585
586 // get the nearest distance between adc point and lane
587 double distance = 0.0;
588 common::PointENU map_point =
589 lane->GetNearestPoint({point.x(), point.y()}, &distance);
590 // record the near distance lane
591 if (distance < min_distance) {
592 double s = 0.0;
593 double l = 0.0;
594 if (!lane->GetProjection({map_point.x(), map_point.y()}, &s, &l)) {
595 AERROR << "failed to get projection for map_point "
596 << map_point.DebugString();
597 continue;
598 }
599 min_distance = distance;
600 waypoint->lane = lane;
601 waypoint->s = s;
602 }
603 }
604
605 if (waypoint->lane == nullptr) {
606 AERROR << "failed to find nearest point " << point.ShortDebugString();
607 }
608 return waypoint->lane != nullptr;
609}
610
611bool ReferenceLineProvider::CreateRouteSegments(
612 const common::VehicleState &vehicle_state,
613 std::list<hdmap::RouteSegments> *segments) {
614 {
615 std::lock_guard<std::mutex> lock(pnc_map_mutex_);
616 if (!current_pnc_map_->GetRouteSegments(vehicle_state, segments)) {
617 AERROR << "Failed to extract segments from routing";
618 return false;
619 }
620 }
621 for (auto &seg : *segments) {
622 ADEBUG << seg.DebugString();
623 }
624 if (FLAGS_prioritize_change_lane) {
625 PrioritizeChangeLane(segments);
626 }
627 return !segments->empty();
628}
629
630bool ReferenceLineProvider::CreateReferenceLine(
631 std::list<ReferenceLine> *reference_lines,
632 std::list<hdmap::RouteSegments> *segments) {
633 CHECK_NOTNULL(reference_lines);
634 CHECK_NOTNULL(segments);
635
636 common::VehicleState vehicle_state;
637 {
638 std::lock_guard<std::mutex> lock(vehicle_state_mutex_);
639 vehicle_state = vehicle_state_;
640 }
641
642 planning::PlanningCommand command;
643 {
644 std::lock_guard<std::mutex> lock(routing_mutex_);
645 command = planning_command_;
646 }
647 if (nullptr == current_pnc_map_) {
648 AERROR << "Current pnc map is null! " << command.DebugString();
649 return false;
650 }
651
652 if (!CreateRouteSegments(vehicle_state, segments)) {
653 AERROR << "Failed to create reference line from routing";
654 return false;
655 }
656 if (is_new_command_ || !FLAGS_enable_reference_line_stitching) {
657 for (auto iter = segments->begin(); iter != segments->end();) {
658 reference_lines->emplace_back();
659 if (!SmoothRouteSegment(*iter, &reference_lines->back())) {
660 AERROR << "Failed to create reference line from route segments";
661 reference_lines->pop_back();
662 iter = segments->erase(iter);
663 } else {
664 common::SLPoint sl;
665 if (!reference_lines->back().XYToSL(
666 vehicle_state.heading(),
667 common::math::Vec2d(vehicle_state.x(), vehicle_state.y()),
668 &sl)) {
669 AWARN << "Failed to project point: {" << vehicle_state.x() << ","
670 << vehicle_state.y() << "} to stitched reference line";
671 }
672 Shrink(sl, &reference_lines->back(), &(*iter));
673 ++iter;
674 }
675 }
676 is_new_command_ = false;
677 return true;
678 } else { // stitching reference line
679 for (auto iter = segments->begin(); iter != segments->end();) {
680 reference_lines->emplace_back();
681 if (!ExtendReferenceLine(vehicle_state, &(*iter),
682 &reference_lines->back())) {
683 AERROR << "Failed to extend reference line";
684 reference_lines->pop_back();
685 iter = segments->erase(iter);
686 } else {
687 ++iter;
688 }
689 }
690 }
691 return true;
692}
693
694bool ReferenceLineProvider::ExtendReferenceLine(const VehicleState &state,
695 RouteSegments *segments,
696 ReferenceLine *reference_line) {
697 RouteSegments segment_properties;
698 segment_properties.SetProperties(*segments);
699 auto prev_segment = route_segments_.begin();
700 auto prev_ref = reference_lines_.begin();
701 while (prev_segment != route_segments_.end()) {
702 if (prev_segment->IsConnectedSegment(*segments)) {
703 break;
704 }
705 ++prev_segment;
706 ++prev_ref;
707 }
708 if (prev_segment == route_segments_.end()) {
709 if (!route_segments_.empty() && segments->IsOnSegment()) {
710 AWARN << "Current route segment is not connected with previous route "
711 "segment";
712 }
713 return SmoothRouteSegment(*segments, reference_line);
714 }
715 common::SLPoint sl_point;
716 Vec2d vec2d(state.x(), state.y());
717 LaneWaypoint waypoint;
718 if (!prev_segment->GetProjection(vec2d, state.heading(), &sl_point,
719 &waypoint)) {
720 AWARN << "Vehicle current point: " << vec2d.DebugString()
721 << " not on previous reference line";
722 return SmoothRouteSegment(*segments, reference_line);
723 }
724 const double prev_segment_length = RouteSegments::Length(*prev_segment);
725 const double remain_s = prev_segment_length - sl_point.s();
726 const double look_forward_required_distance =
727 planning::PncMapBase::LookForwardDistance(state.linear_velocity());
728 if (remain_s > look_forward_required_distance) {
729 *segments = *prev_segment;
730 segments->SetProperties(segment_properties);
731 *reference_line = *prev_ref;
732 ADEBUG << "Reference line remain " << remain_s
733 << ", which is more than required " << look_forward_required_distance
734 << " and no need to extend";
735 return true;
736 }
737 double future_start_s =
738 std::max(sl_point.s(), prev_segment_length -
739 FLAGS_reference_line_stitch_overlap_distance);
740 double future_end_s =
741 prev_segment_length + FLAGS_look_forward_extend_distance;
742 RouteSegments shifted_segments;
743 std::unique_lock<std::mutex> lock(pnc_map_mutex_);
744 if (!current_pnc_map_->ExtendSegments(*prev_segment, future_start_s,
745 future_end_s, &shifted_segments)) {
746 lock.unlock();
747 AERROR << "Failed to shift route segments forward";
748 return SmoothRouteSegment(*segments, reference_line);
749 }
750 lock.unlock();
751 if (prev_segment->IsWaypointOnSegment(shifted_segments.LastWaypoint())) {
752 *segments = *prev_segment;
753 segments->SetProperties(segment_properties);
754 *reference_line = *prev_ref;
755 ADEBUG << "Could not further extend reference line";
756 return true;
757 }
758 hdmap::Path path(shifted_segments);
759 ReferenceLine new_ref(path);
760 if (!SmoothPrefixedReferenceLine(*prev_ref, new_ref, reference_line)) {
761 AWARN << "Failed to smooth forward shifted reference line";
762 return SmoothRouteSegment(*segments, reference_line);
763 }
764 if (!reference_line->Stitch(*prev_ref)) {
765 AWARN << "Failed to stitch reference line";
766 return SmoothRouteSegment(*segments, reference_line);
767 }
768 if (!shifted_segments.Stitch(*prev_segment)) {
769 AWARN << "Failed to stitch route segments";
770 return SmoothRouteSegment(*segments, reference_line);
771 }
772 *segments = shifted_segments;
773 segments->SetProperties(segment_properties);
774 common::SLPoint sl;
775 if (!reference_line->XYToSL(state.heading(), vec2d, &sl)) {
776 AWARN << "Failed to project point: " << vec2d.DebugString()
777 << " to stitched reference line";
778 }
779 return Shrink(sl, reference_line, segments);
780}
781
782bool ReferenceLineProvider::Shrink(const common::SLPoint &sl,
783 ReferenceLine *reference_line,
784 RouteSegments *segments) {
785 // shrink reference line
786 double new_backward_distance = sl.s();
787 double new_forward_distance = reference_line->Length() - sl.s();
788 bool need_shrink = false;
789 if (sl.s() > planning::FLAGS_look_backward_distance * 1.5) {
790 ADEBUG << "reference line back side is " << sl.s()
791 << ", shrink reference line: origin length: "
792 << reference_line->Length();
793 new_backward_distance = planning::FLAGS_look_backward_distance;
794 need_shrink = true;
795 }
796 // check heading
797 const auto index = reference_line->GetNearestReferenceIndex(sl.s());
798 const auto &ref_points = reference_line->reference_points();
799 const double cur_heading = ref_points[index].heading();
800 auto last_index = index;
801 while (last_index < ref_points.size() &&
802 std::fabs(AngleDiff(cur_heading, ref_points[last_index].heading())) <
803 FLAGS_reference_line_max_forward_heading_diff) {
804 ++last_index;
805 }
806 --last_index;
807 if (last_index != ref_points.size() - 1) {
808 need_shrink = true;
809 common::SLPoint forward_sl;
810 reference_line->XYToSL(ref_points[last_index], &forward_sl);
811 new_forward_distance = forward_sl.s() - sl.s();
812 }
813
814 // check backward heading
815 last_index = index;
816 while (last_index > 0 &&
817 abs(AngleDiff(cur_heading, ref_points[last_index].heading())) <
818 FLAGS_reference_line_max_backward_heading_diff) {
819 --last_index;
820 }
821 if (last_index != 0) {
822 need_shrink = true;
823 common::SLPoint backward_sl;
824 reference_line->XYToSL(ref_points[last_index], &backward_sl);
825 new_backward_distance = sl.s() - backward_sl.s();
826 }
827
828 if (need_shrink) {
829 if (!reference_line->Segment(sl.s(), new_backward_distance,
830 new_forward_distance)) {
831 AWARN << "Failed to shrink reference line";
832 }
833 if (!segments->Shrink(sl.s(), new_backward_distance,
834 new_forward_distance)) {
835 AWARN << "Failed to shrink route segment";
836 }
837 }
838 return true;
839}
840
841bool ReferenceLineProvider::IsReferenceLineSmoothValid(
842 const ReferenceLine &raw, const ReferenceLine &smoothed) const {
843 static constexpr double kReferenceLineDiffCheckStep = 10.0;
844 for (double s = 0.0; s < smoothed.Length();
845 s += kReferenceLineDiffCheckStep) {
846 auto xy_new = smoothed.GetReferencePoint(s);
847
848 common::SLPoint sl_new;
849 if (!raw.XYToSL(xy_new, &sl_new)) {
850 AERROR << "Fail to change xy point on smoothed reference line to sl "
851 "point respect to raw reference line.";
852 return false;
853 }
854
855 const double diff = std::fabs(sl_new.l());
856 if (diff > FLAGS_smoothed_reference_line_max_diff) {
857 AERROR << "Fail to provide reference line because too large diff "
858 "between smoothed and raw reference lines. diff: "
859 << diff;
860 return false;
861 }
862 }
863 return true;
864}
865
866AnchorPoint ReferenceLineProvider::GetAnchorPoint(
867 const ReferenceLine &reference_line, double s) const {
868 AnchorPoint anchor;
869 anchor.longitudinal_bound = smoother_config_.longitudinal_boundary_bound();
870 auto ref_point = reference_line.GetReferencePoint(s);
871 if (ref_point.lane_waypoints().empty()) {
872 anchor.path_point = ref_point.ToPathPoint(s);
873 anchor.lateral_bound = smoother_config_.max_lateral_boundary_bound();
874 return anchor;
875 }
876
877 const double adc_width =
879 const Vec2d left_vec =
880 Vec2d::CreateUnitVec2d(ref_point.heading() + M_PI / 2.0);
881 auto waypoint = ref_point.lane_waypoints().front();
882 double left_width = 0.0;
883 double right_width = 0.0;
884 waypoint.lane->GetWidth(waypoint.s, &left_width, &right_width);
885 const double kEpislon = 1e-8;
886 double effective_width = 0.0;
887
888 // shrink width by vehicle width, curb
889 double safe_lane_width = left_width + right_width;
890 safe_lane_width -= adc_width;
891 bool is_lane_width_safe = true;
892
893 if (safe_lane_width < kEpislon) {
894 ADEBUG << "lane width [" << left_width + right_width << "] "
895 << "is smaller than adc width [" << adc_width << "]";
896 effective_width = kEpislon;
897 is_lane_width_safe = false;
898 }
899
900 double center_shift = 0.0;
902 safe_lane_width -= smoother_config_.curb_shift();
903 if (safe_lane_width < kEpislon) {
904 ADEBUG << "lane width smaller than adc width and right curb shift";
905 effective_width = kEpislon;
906 is_lane_width_safe = false;
907 } else {
908 center_shift += 0.5 * smoother_config_.curb_shift();
909 }
910 }
912 safe_lane_width -= smoother_config_.curb_shift();
913 if (safe_lane_width < kEpislon) {
914 ADEBUG << "lane width smaller than adc width and left curb shift";
915 effective_width = kEpislon;
916 is_lane_width_safe = false;
917 } else {
918 center_shift -= 0.5 * smoother_config_.curb_shift();
919 }
920 }
921
922 // apply buffer if possible
923 const double buffered_width =
924 safe_lane_width - 2.0 * smoother_config_.lateral_buffer();
925 safe_lane_width =
926 buffered_width < kEpislon ? safe_lane_width : buffered_width;
927
928 // shift center depending on the road width
929 if (is_lane_width_safe) {
930 effective_width = 0.5 * safe_lane_width;
931 }
932
933 ref_point += left_vec * center_shift;
934 anchor.path_point = ref_point.ToPathPoint(s);
935 anchor.lateral_bound = common::math::Clamp(
936 effective_width, smoother_config_.min_lateral_boundary_bound(),
937 smoother_config_.max_lateral_boundary_bound());
938 return anchor;
939}
940
941void ReferenceLineProvider::GetAnchorPoints(
942 const ReferenceLine &reference_line,
943 std::vector<AnchorPoint> *anchor_points) const {
944 CHECK_NOTNULL(anchor_points);
945 const double interval = smoother_config_.max_constraint_interval();
946 int num_of_anchors =
947 std::max(2, static_cast<int>(reference_line.Length() / interval + 0.5));
948 std::vector<double> anchor_s;
949 common::util::uniform_slice(0.0, reference_line.Length(), num_of_anchors - 1,
950 &anchor_s);
951 for (const double s : anchor_s) {
952 AnchorPoint anchor = GetAnchorPoint(reference_line, s);
953 anchor_points->emplace_back(anchor);
954 }
955 anchor_points->front().longitudinal_bound = 1e-6;
956 anchor_points->front().lateral_bound = 1e-6;
957 anchor_points->front().enforced = true;
958 anchor_points->back().longitudinal_bound = 1e-6;
959 anchor_points->back().lateral_bound = 1e-6;
960 anchor_points->back().enforced = true;
961}
962
963bool ReferenceLineProvider::SmoothRouteSegment(const RouteSegments &segments,
964 ReferenceLine *reference_line) {
965 hdmap::Path path(segments);
966 return SmoothReferenceLine(ReferenceLine(path), reference_line);
967}
968
969bool ReferenceLineProvider::SmoothPrefixedReferenceLine(
970 const ReferenceLine &prefix_ref, const ReferenceLine &raw_ref,
971 ReferenceLine *reference_line) {
972 if (!FLAGS_enable_smooth_reference_line) {
973 *reference_line = raw_ref;
974 return true;
975 }
976 // generate anchor points:
977 std::vector<AnchorPoint> anchor_points;
978 GetAnchorPoints(raw_ref, &anchor_points);
979 // modify anchor points based on prefix_ref
980 for (auto &point : anchor_points) {
981 common::SLPoint sl_point;
982 if (!prefix_ref.XYToSL(point.path_point, &sl_point)) {
983 continue;
984 }
985 if (sl_point.s() < 0 || sl_point.s() > prefix_ref.Length()) {
986 continue;
987 }
988 auto prefix_ref_point = prefix_ref.GetNearestReferencePoint(sl_point.s());
989 point.path_point.set_x(prefix_ref_point.x());
990 point.path_point.set_y(prefix_ref_point.y());
991 point.path_point.set_z(0.0);
992 point.path_point.set_theta(prefix_ref_point.heading());
993 point.longitudinal_bound = 1e-6;
994 point.lateral_bound = 1e-6;
995 point.enforced = true;
996 break;
997 }
998
999 smoother_->SetAnchorPoints(anchor_points);
1000 if (!smoother_->Smooth(raw_ref, reference_line)) {
1001 AERROR << "Failed to smooth prefixed reference line with anchor points";
1002 return false;
1003 }
1004 if (!IsReferenceLineSmoothValid(raw_ref, *reference_line)) {
1005 AERROR << "The smoothed reference line error is too large";
1006 return false;
1007 }
1008 return true;
1009}
1010
1011bool ReferenceLineProvider::SmoothReferenceLine(
1012 const ReferenceLine &raw_reference_line, ReferenceLine *reference_line) {
1013 if (!FLAGS_enable_smooth_reference_line) {
1014 *reference_line = raw_reference_line;
1015 return true;
1016 }
1017 // generate anchor points:
1018 std::vector<AnchorPoint> anchor_points;
1019 GetAnchorPoints(raw_reference_line, &anchor_points);
1020 smoother_->SetAnchorPoints(anchor_points);
1021 if (!smoother_->Smooth(raw_reference_line, reference_line)) {
1022 AERROR << "Failed to smooth reference line with anchor points";
1023 return false;
1024 }
1025 if (!IsReferenceLineSmoothValid(raw_reference_line, *reference_line)) {
1026 AERROR << "The smoothed reference line error is too large";
1027 return false;
1028 }
1029 return true;
1030}
1031
1033 if (nullptr == current_pnc_map_) {
1034 AERROR << "Cannot find pnc map to get adc waypoint!";
1035 return false;
1036 }
1037 *waypoint = current_pnc_map_->GetAdcWaypoint();
1038 return true;
1039}
1040
1042 if (nullptr == current_pnc_map_) {
1043 AERROR << "Cannot find pnc map to get adc distance to destination!";
1044 return false;
1045 }
1046 *dis = current_pnc_map_->GetDistanceToDestination();
1047 return true;
1048}
1049
1050} // namespace planning
1051} // namespace apollo
@Brief This is a helper class that can load vehicle configurations.
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
static Vec2d CreateUnitVec2d(const double angle)
Creates a unit-vector with a given angle to the positive x semi-axis
Definition vec2d.cc:29
static PointENU ToPointENU(const double x, const double y, const double z=0)
a singleton clock that can be used to get the current timestamp.
Definition clock.h:39
static double NowInSeconds()
gets the current time in second.
Definition clock.cc:56
static PluginManager * Instance()
get singleton instance of PluginManager
std::shared_ptr< Base > CreateInstance(const std::string &derived_class)
create plugin instance of derived class based on Base
static const HDMap * BaseMapPtr()
static double Length(const RouteSegments &segments)
static double LookForwardDistance(const double velocity)
bool GetReferenceLines(std::list< ReferenceLine > *reference_lines, std::list< hdmap::RouteSegments > *segments)
void UpdateVehicleState(const common::VehicleState &vehicle_state)
void GetEndLaneWayPoint(std::shared_ptr< routing::LaneWaypoint > &end_point) const
bool GetAdcWaypoint(hdmap::LaneWaypoint *waypoint) const
bool UpdatePlanningCommand(const planning::PlanningCommand &command)
Update when new PlanningCommand is received.
hdmap::LaneInfoConstPtr GetLaneById(const hdmap::Id &id) const
std::vector< routing::LaneWaypoint > FutureRouteWaypoints()
Planning module main class.
Math-related util 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
constexpr double kMathEpsilon
Definition vec2d.h:35
T Clamp(const T value, T bound1, T bound2)
Clamp a value between two bounds.
Definition math_utils.h:155
double AngleDiff(const double from, const double to)
Calculate the difference between angle from and to
Definition math_utils.cc:61
bool SamePointXY(const U &u, const V &v)
Check if two points u and v are the same point on XY dimension.
Definition util.h:109
void uniform_slice(const T start, const T end, uint32_t num, std::vector< T > *sliced)
uniformly slice a segment [start, end] to num + 1 pieces the result sliced will contain the n + 1 poi...
Definition util.h:74
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
apollo::hdmap::Id MakeMapId(const std::string &id)
create a Map ID given a string.
Definition hdmap_util.h:85
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
float diff(Image< float > *I, int x1, int y1, int x2, int y2)
Dissimilarity measure between pixels
T abs(const T &x)
Get absolute value of x
Definition misc.h:63
class register implement
Definition arena_queue.h:37
Declaration of the class ReferenceLineProvider.
optional VehicleParam vehicle_param