Apollo 11.0
自动驾驶开放平台
path_reference_decider.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2020 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
21
22#include <string>
23#include <utility>
24#include <vector>
25
26#include "modules/planning/planning_base/proto/planning_config.pb.h"
27
35
36namespace apollo {
37namespace planning {
38
40using common::PathPoint;
41using common::SLPoint;
42using common::Status;
43using common::TrajectoryPoint;
44using common::math::Box2d;
45using common::math::LineSegment2d;
46using common::math::Vec2d;
47
48int PathReferenceDecider::valid_path_reference_counter_ = 0;
49int PathReferenceDecider::total_path_counter_ = 0;
50
52 const std::string &config_dir, const std::string &name,
53 const std::shared_ptr<DependencyInjector> &injector) {
54 if (!Task::Init(config_dir, name, injector)) {
55 return false;
56 }
57 // Load the config this task.
58 return Task::LoadConfig<PathReferenceDeciderConfig>(&config_);
59}
60
62 ReferenceLineInfo *reference_line_info) {
63 Task::Execute(frame, reference_line_info);
64 return Process(frame, reference_line_info);
65}
66
67Status PathReferenceDecider::Process(Frame *frame,
68 ReferenceLineInfo *reference_line_info) {
69 constexpr double kMathEpsilon = 1e-10;
70 // skip using path reference during lane changing
71 // There are two reference line during change lane
73 frame->reference_line_info().size() > 1) {
74 reference_line_info->mutable_path_data()->set_is_valid_path_reference(
75 false);
76 ADEBUG << "Skip path reference when changing lane.";
77 ADEBUG << "valid_path_reference_counter[" << valid_path_reference_counter_
78 << "] total_path_counter[" << total_path_counter_ << "]";
79 std::string err_msg = "Skip path reference when changing lane.";
80 reference_line_info->mutable_debug()
81 ->mutable_planning_data()
82 ->mutable_hybrid_model()
83 ->set_learning_model_output_fail_reason(err_msg);
84 reference_line_info->mutable_debug()
85 ->mutable_planning_data()
86 ->mutable_hybrid_model()
87 ->set_learning_model_output_usage_ratio(
88 static_cast<double>(valid_path_reference_counter_) /
89 (total_path_counter_ + kMathEpsilon));
90 return Status::OK();
91 }
92
93 // skip using path reference during side pass
95 reference_line_info->is_path_lane_borrow()) {
96 reference_line_info->mutable_path_data()->set_is_valid_path_reference(
97 false);
98 ADEBUG << "Skip path reference when sidepass.";
99 ADEBUG << "valid_path_reference_counter[" << valid_path_reference_counter_
100 << "] total_path_counter[" << total_path_counter_ << "]";
101 std::string err_msg = "Skip path reference when sidepass.";
102 reference_line_info->mutable_debug()
103 ->mutable_planning_data()
104 ->mutable_hybrid_model()
105 ->set_learning_model_output_fail_reason(err_msg);
106 reference_line_info->mutable_debug()
107 ->mutable_planning_data()
108 ->mutable_hybrid_model()
109 ->set_learning_model_output_usage_ratio(
110 static_cast<double>(valid_path_reference_counter_) /
111 (total_path_counter_ + kMathEpsilon));
112 return Status::OK();
113 }
114
115 // get path bounds info from reference line info
116 const std::vector<PathBoundary> &path_boundaries =
118 ADEBUG << "There are " << path_boundaries.size() << " path boundaries.";
119
120 // get learning model output (trajectory) from frame
121 const std::vector<common::TrajectoryPoint> &learning_model_trajectory =
122 injector_->learning_based_data()
123 ->learning_data_adc_future_trajectory_points();
124 ADEBUG << "There are " << learning_model_trajectory.size() << " path points.";
125
126 // get regular path bound
127 size_t regular_path_bound_idx = GetRegularPathBound(path_boundaries);
128 if (regular_path_bound_idx == path_boundaries.size()) {
129 reference_line_info->mutable_path_data()->set_is_valid_path_reference(
130 false);
131 const std::string msg = "No regular path boundary";
132 AERROR << msg;
133 ADEBUG << "valid_path_reference_counter[" << valid_path_reference_counter_
134 << "] total_path_counter[" << total_path_counter_ << "]";
135 std::string err_msg = "No regular path boundary";
136 reference_line_info->mutable_debug()
137 ->mutable_planning_data()
138 ->mutable_hybrid_model()
139 ->set_learning_model_output_fail_reason(err_msg);
140 reference_line_info->mutable_debug()
141 ->mutable_planning_data()
142 ->mutable_hybrid_model()
143 ->set_learning_model_output_usage_ratio(
144 static_cast<double>(valid_path_reference_counter_) /
145 (total_path_counter_ + kMathEpsilon));
146 return Status(ErrorCode::PLANNING_ERROR, msg);
147 }
148
149 ++total_path_counter_;
150
151 // when learning model has no output, use rule-based model instead.
152 if (learning_model_trajectory.size() == 0) {
153 reference_line_info->mutable_path_data()->set_is_valid_path_reference(
154 false);
155 ADEBUG << "valid_path_reference_counter[" << valid_path_reference_counter_
156 << "] total_path_counter[" << total_path_counter_ << "]";
157 std::string err_msg = "No learning model output";
158 reference_line_info->mutable_debug()
159 ->mutable_planning_data()
160 ->mutable_hybrid_model()
161 ->set_learning_model_output_fail_reason(err_msg);
162 reference_line_info->mutable_debug()
163 ->mutable_planning_data()
164 ->mutable_hybrid_model()
165 ->set_learning_model_output_usage_ratio(
166 static_cast<double>(valid_path_reference_counter_) /
167 (total_path_counter_ + kMathEpsilon));
168 return Status::OK();
169 }
170 std::vector<PathPoint> path_reference;
171 // adjusting trajectory init point
172 DiscretizedTrajectory stitched_learning_model_trajectory;
174 frame->PlanningStartPoint(), learning_model_trajectory,
175 &stitched_learning_model_trajectory);
176 // when path_reference is too short not valid path reference
177 if (stitched_learning_model_trajectory.size() <= 1) {
178 reference_line_info->mutable_path_data()->set_is_valid_path_reference(
179 false);
180 ADEBUG << "valid_path_reference_counter[" << valid_path_reference_counter_
181 << "] total_path_counter[" << total_path_counter_ << "]";
182 std::string err_msg = "Stitched path reference is too short";
183 reference_line_info->mutable_debug()
184 ->mutable_planning_data()
185 ->mutable_hybrid_model()
186 ->set_learning_model_output_fail_reason(err_msg);
187 reference_line_info->mutable_debug()
188 ->mutable_planning_data()
189 ->mutable_hybrid_model()
190 ->set_learning_model_output_usage_ratio(
191 static_cast<double>(valid_path_reference_counter_) /
192 (total_path_counter_ + kMathEpsilon));
193 return Status::OK();
194 }
195 ConvertTrajectoryToPath(stitched_learning_model_trajectory, &path_reference);
196 const std::string path_reference_name = "path_reference";
197 RecordDebugInfo(path_reference, path_reference_name, reference_line_info);
198
199 // check if path reference is valid
200 // current, only check if path reference point is within path bounds
201 if (!IsValidPathReference(*reference_line_info,
202 path_boundaries[regular_path_bound_idx],
203 path_reference)) {
204 reference_line_info->mutable_path_data()->set_is_valid_path_reference(
205 false);
206 ADEBUG << "valid_path_reference_counter[" << valid_path_reference_counter_
207 << "] total_path_counter[" << total_path_counter_ << "]";
208 std::string err_msg = "Learning model output violates path bounds";
209 reference_line_info->mutable_debug()
210 ->mutable_planning_data()
211 ->mutable_hybrid_model()
212 ->set_learning_model_output_fail_reason(err_msg);
213 // export reuse ratio to debug info
214 reference_line_info->mutable_debug()
215 ->mutable_planning_data()
216 ->mutable_hybrid_model()
217 ->set_learning_model_output_usage_ratio(
218 static_cast<double>(valid_path_reference_counter_) /
219 (total_path_counter_ + kMathEpsilon));
220 return Status::OK();
221 }
222
223 // evaluate path reference
224 std::vector<PathPoint> evaluated_path_reference;
225 EvaluatePathReference(path_boundaries[regular_path_bound_idx], path_reference,
226 &evaluated_path_reference);
227 ADEBUG << "evaluated_path_reference: " << evaluated_path_reference.size();
228
229 // mark learning trajectory as path reference
230 reference_line_info->mutable_path_data()->set_is_valid_path_reference(true);
231 // export decider result to debug info
232 reference_line_info->mutable_debug()
233 ->mutable_planning_data()
234 ->mutable_hybrid_model()
235 ->set_using_learning_model_output(true);
236 // export evaluated path reference
237 reference_line_info->mutable_debug()
238 ->mutable_planning_data()
239 ->mutable_hybrid_model()
240 ->mutable_evaluated_path_reference()
241 ->mutable_path_point()
242 ->CopyFrom(
243 {evaluated_path_reference.begin(), evaluated_path_reference.end()});
244 // set evaluated path data
245 reference_line_info->mutable_path_data()->set_path_reference(
246 std::move(evaluated_path_reference));
247 // uncomment this for debug
248 // const std::string evaluation_path_name = "evaluated_path_reference";
249 // RecordDebugInfo(evaluated_path_reference, evaluation_path_name,
250 // reference_line_info);
251
252 ++valid_path_reference_counter_;
253 ADEBUG << "valid_path_reference_counter[" << valid_path_reference_counter_
254 << "] total_path_counter[" << total_path_counter_ << "]";
255
256 // export reuse ratio to debug info
257 reference_line_info->mutable_debug()
258 ->mutable_planning_data()
259 ->mutable_hybrid_model()
260 ->set_learning_model_output_usage_ratio(
261 static_cast<double>(valid_path_reference_counter_) /
262 (total_path_counter_ + kMathEpsilon));
263
264 ADEBUG << "path reference size:" << path_reference.size();
265
266 return Status::OK();
267}
268
269void PathReferenceDecider::ConvertTrajectoryToPath(
270 const std::vector<TrajectoryPoint> &trajectory_points,
271 std::vector<PathPoint> *path_points) {
272 for (auto trajectory_point : trajectory_points) {
273 if (trajectory_point.has_path_point()) {
274 path_points->push_back(trajectory_point.path_point());
275 }
276 }
277}
278size_t PathReferenceDecider::GetRegularPathBound(
279 const std::vector<PathBoundary> &path_bounds) const {
280 for (auto iter = begin(path_bounds); iter != end(path_bounds); ++iter) {
281 if (iter->label().find("regular") != std::string::npos) {
282 return distance(begin(path_bounds), iter);
283 }
284 }
285 return path_bounds.size();
286}
287
288bool PathReferenceDecider::IsValidPathReference(
289 const ReferenceLineInfo &reference_line_info,
290 const PathBoundary &regular_path_bound,
291 const std::vector<PathPoint> &path_reference) {
292 for (auto path_referece_point : path_reference) {
293 const double cur_x = path_referece_point.x();
294 const double cur_y = path_referece_point.y();
295 if (-1 == IsPointWithinPathBounds(reference_line_info, regular_path_bound,
296 cur_x, cur_y)) {
297 ADEBUG << ", x: " << std::setprecision(9) << cur_x
298 << ", y: " << std::setprecision(9) << cur_y;
299 return false;
300 }
301 }
302 return true;
303}
304
305bool PathReferenceDecider::IsADCBoxAlongPathReferenceWithinPathBounds(
306 const std::vector<TrajectoryPoint> &path_reference,
307 const PathBoundary &regular_path_bound) {
308 /* check adc box has overlap with each path line segment*/
309 // loop over output trajectory points
310 // check if path reference point is valid or not
311 // 1. line segment formed by two adjacent boundary point
312 std::vector<std::vector<LineSegment2d>> segmented_path_bounds;
313 PathBoundToLineSegments(regular_path_bound, &segmented_path_bounds);
314 // has intersection with
315 std::vector<Box2d> vehicle_boxes;
316 for (const auto path_reference_point : path_reference) {
317 // add ADC box to current path_reference_point
318 const auto &path_point = path_reference_point.path_point();
319 Box2d vehicle_box =
320 common::VehicleConfigHelper::Instance()->GetBoundingBox(path_point);
321 vehicle_boxes.emplace_back(vehicle_box);
322 }
323 // check intersection of linesegments and adc boxes
324 // left & right path bounds
325 for (auto segmented_path_bound : segmented_path_bounds) {
326 // line segment for each bound
327 for (auto line_segment : segmented_path_bound) {
328 // check if all vehicle boxes along learning model outputhas
329 // overlap with ADC box
330 // TODO(Shu): early stop when vehicle box is far away.
331 for (auto vehicle_box : vehicle_boxes) {
332 if (vehicle_box.HasOverlap(line_segment)) {
333 ADEBUG << std::setprecision(9) << "Vehicle box:["
334 << vehicle_box.center_x() << "," << vehicle_box.center_y()
335 << "]"
336 << "Violate path bound at [" << line_segment.start().x() << ","
337 << line_segment.start().y() << "];"
338 << "[" << line_segment.end().x() << ","
339 << line_segment.end().y() << "]";
340 return false;
341 }
342 }
343 }
344 }
345
346 return true;
347}
348
349void PathReferenceDecider::PathBoundToLineSegments(
350 const PathBoundary &path_bound,
351 std::vector<std::vector<LineSegment2d>> *path_bound_segments) {
352 const double start_s = path_bound.start_s();
353 const double delta_s = path_bound.delta_s();
354 const size_t path_bound_size = path_bound.boundary().size();
355 std::vector<LineSegment2d> cur_left_bound_segments;
356 std::vector<LineSegment2d> cur_right_bound_segments;
357 const std::vector<std::pair<double, double>> &path_bound_points =
358 path_bound.boundary();
359 // setup the init path bound point
360 SLPoint prev_left_sl_point;
361 SLPoint prev_right_sl_point;
362 prev_left_sl_point.set_l(std::get<0>(path_bound_points[0]));
363 prev_left_sl_point.set_s(start_s);
364 prev_right_sl_point.set_l(std::get<1>(path_bound_points[0]));
365 prev_right_sl_point.set_s(start_s);
366 // slpoint to cartesion point
367 Vec2d prev_left_cartesian_point;
368 Vec2d prev_right_cartesian_point;
369 reference_line_info_->reference_line().SLToXY(prev_left_sl_point,
370 &prev_left_cartesian_point);
371 reference_line_info_->reference_line().SLToXY(prev_right_sl_point,
372 &prev_right_cartesian_point);
373 for (size_t i = 1; i < path_bound_size; ++i) {
374 // s = start_s + i * delta_s
375 double current_s = start_s + i * delta_s;
376 SLPoint left_sl_point;
377 Vec2d left_cartesian_point;
378 SLPoint right_sl_point;
379 Vec2d right_cartesian_point;
380
381 left_sl_point.set_l(std::get<0>(path_bound_points[i]));
382 left_sl_point.set_s(current_s);
383 right_sl_point.set_l(std::get<1>(path_bound_points[i]));
384 right_sl_point.set_s(current_s);
385
387 &left_cartesian_point);
389 &right_cartesian_point);
390
391 // together with previous point form line segment
392 LineSegment2d cur_left_segment(prev_left_cartesian_point,
393 left_cartesian_point);
394 LineSegment2d cur_right_segment(prev_right_cartesian_point,
395 right_cartesian_point);
396 prev_left_cartesian_point = left_cartesian_point;
397 prev_right_cartesian_point = right_cartesian_point;
398 cur_left_bound_segments.emplace_back(cur_left_segment);
399 cur_right_bound_segments.emplace_back(cur_right_segment);
400 }
401 path_bound_segments->emplace_back(cur_left_bound_segments);
402 path_bound_segments->emplace_back(cur_right_bound_segments);
403}
404
405int PathReferenceDecider::IsPointWithinPathBounds(
406 const ReferenceLineInfo &reference_line_info,
407 const PathBoundary &path_bound, const double x, const double y) {
408 const double kPathBoundsDeciderResolution = 0.5;
409 common::SLPoint point_sl;
410 reference_line_info.reference_line().XYToSL({x, y}, &point_sl);
411 const double start_s = path_bound.start_s();
412 const double delta_s = path_bound.delta_s();
413 const int path_bound_size = path_bound.boundary().size();
414 const double end_s = start_s + delta_s * (path_bound_size - 1);
415
416 if (point_sl.s() > end_s ||
417 point_sl.s() < start_s - kPathBoundsDeciderResolution * 2) {
418 AERROR << "Longitudinally outside the boundary.";
419 return -1;
420 }
421 int idx_after = 0;
422 while (idx_after < path_bound_size &&
423 start_s + idx_after * delta_s < point_sl.s()) {
424 ++idx_after;
425 }
426 if (idx_after == 0) {
427 // consider as a valid point if the starting point is before path bound
428 // begining point
429 return idx_after;
430 } else {
431 ADEBUG << "idx_after[" << idx_after << "] point_l[" << point_sl.l() << "]";
432 int idx_before = idx_after - 1;
433 if (std::get<0>(path_bound.boundary().at(idx_before)) <= point_sl.l() &&
434 std::get<1>(path_bound.boundary().at(idx_before)) >= point_sl.l() &&
435 std::get<0>(path_bound.boundary().at(idx_after)) <= point_sl.l() &&
436 std::get<1>(path_bound.boundary().at(idx_after)) >= point_sl.l()) {
437 return idx_after;
438 }
439 }
440 ADEBUG << "Laterally outside the boundary.";
441 return -1;
442}
443
444void PathReferenceDecider::EvaluatePathReference(
445 const PathBoundary &path_bound,
446 const std::vector<PathPoint> &path_reference,
447 std::vector<PathPoint> *evaluated_path_reference) {
448 const double delta_s = path_bound.delta_s();
449 const double path_reference_end_s = path_reference.back().s();
450 DiscretizedPath discrete_path_reference;
451 for (auto path_point : path_reference) {
452 discrete_path_reference.emplace_back(path_point);
453 }
454 size_t idx;
455 for (idx = 0; idx < path_bound.boundary().size(); ++idx) {
456 // relative s
457 double cur_s = static_cast<double>(idx) * delta_s;
458 if (cur_s > path_reference_end_s) {
459 break;
460 }
461 evaluated_path_reference->emplace_back(
462 discrete_path_reference.Evaluate(cur_s));
463 }
464}
465
466void PathReferenceDecider::RecordDebugInfo(
467 const std::vector<PathPoint> &path_points, const std::string &path_name,
468 ReferenceLineInfo *const reference_line_info) {
469 // Sanity checks.
470 ACHECK(!path_points.empty());
471 CHECK_NOTNULL(reference_line_info);
472 // Insert the transformed PathData into the simulator display.
473 auto *ptr_display_path =
474 reference_line_info->mutable_debug()->mutable_planning_data()->add_path();
475 ptr_display_path->set_name(path_name);
476 ptr_display_path->mutable_path_point()->CopyFrom(
477 {path_points.begin(), path_points.end()});
478}
479
480} // namespace planning
481} // namespace apollo
The class of Box2d.
A general class to denote the return status of an API call.
Definition status.h:43
static Status OK()
generate a success status.
Definition status.h:60
Frame holds all data for one planning cycle.
Definition frame.h:62
const std::list< ReferenceLineInfo > & reference_line_info() const
Definition frame.cc:123
const common::TrajectoryPoint & PlanningStartPoint() const
Definition frame.cc:79
void set_is_valid_path_reference(bool is_valid_path_reference)
Definition path_data.h:98
void set_path_reference(const std::vector< common::PathPoint > &path_reference)
Definition path_data.cc:270
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
apollo::common::Status Execute(Frame *frame, ReferenceLineInfo *reference_line_info) override
ReferenceLineInfo holds all data for one reference line.
const std::vector< PathBoundary > & GetCandidatePathBoundaries() const
const ReferenceLine & reference_line() const
planning_internal::Debug * mutable_debug()
bool AdjustTrajectoryWhichStartsFromCurrentPos(const common::TrajectoryPoint &planning_start_point, const std::vector< common::TrajectoryPoint > &trajectory, DiscretizedTrajectory *adjusted_trajectory)
bool SLToXY(const common::SLPoint &sl_point, common::math::Vec2d *const xy_point) const
std::shared_ptr< DependencyInjector > injector_
Definition task.h:59
ReferenceLineInfo * reference_line_info_
Definition task.h:58
virtual bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
Definition task.cc:40
virtual common::Status Execute(Frame *frame, ReferenceLineInfo *reference_line_info)
Definition task.cc:60
Planning module main class.
Define the LineSegment2d class.
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
constexpr double kMathEpsilon
class register implement
Definition arena_queue.h:37