26#include "modules/planning/planning_base/proto/planning_config.pb.h"
40using common::PathPoint;
43using common::TrajectoryPoint;
44using common::math::Box2d;
45using common::math::LineSegment2d;
46using common::math::Vec2d;
48int PathReferenceDecider::valid_path_reference_counter_ = 0;
49int PathReferenceDecider::total_path_counter_ = 0;
52 const std::string &config_dir,
const std::string &name,
53 const std::shared_ptr<DependencyInjector> &injector) {
58 return Task::LoadConfig<PathReferenceDeciderConfig>(&config_);
64 return Process(frame, reference_line_info);
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.";
81 ->mutable_planning_data()
82 ->mutable_hybrid_model()
83 ->set_learning_model_output_fail_reason(err_msg);
85 ->mutable_planning_data()
86 ->mutable_hybrid_model()
87 ->set_learning_model_output_usage_ratio(
88 static_cast<double>(valid_path_reference_counter_) /
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.";
103 ->mutable_planning_data()
104 ->mutable_hybrid_model()
105 ->set_learning_model_output_fail_reason(err_msg);
107 ->mutable_planning_data()
108 ->mutable_hybrid_model()
109 ->set_learning_model_output_usage_ratio(
110 static_cast<double>(valid_path_reference_counter_) /
116 const std::vector<PathBoundary> &path_boundaries =
118 ADEBUG <<
"There are " << path_boundaries.size() <<
" path boundaries.";
121 const std::vector<common::TrajectoryPoint> &learning_model_trajectory =
123 ->learning_data_adc_future_trajectory_points();
124 ADEBUG <<
"There are " << learning_model_trajectory.size() <<
" path points.";
127 size_t regular_path_bound_idx = GetRegularPathBound(path_boundaries);
128 if (regular_path_bound_idx == path_boundaries.size()) {
131 const std::string msg =
"No regular path boundary";
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";
137 ->mutable_planning_data()
138 ->mutable_hybrid_model()
139 ->set_learning_model_output_fail_reason(err_msg);
141 ->mutable_planning_data()
142 ->mutable_hybrid_model()
143 ->set_learning_model_output_usage_ratio(
144 static_cast<double>(valid_path_reference_counter_) /
146 return Status(ErrorCode::PLANNING_ERROR, msg);
149 ++total_path_counter_;
152 if (learning_model_trajectory.size() == 0) {
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";
159 ->mutable_planning_data()
160 ->mutable_hybrid_model()
161 ->set_learning_model_output_fail_reason(err_msg);
163 ->mutable_planning_data()
164 ->mutable_hybrid_model()
165 ->set_learning_model_output_usage_ratio(
166 static_cast<double>(valid_path_reference_counter_) /
170 std::vector<PathPoint> path_reference;
172 DiscretizedTrajectory stitched_learning_model_trajectory;
175 &stitched_learning_model_trajectory);
177 if (stitched_learning_model_trajectory.size() <= 1) {
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";
184 ->mutable_planning_data()
185 ->mutable_hybrid_model()
186 ->set_learning_model_output_fail_reason(err_msg);
188 ->mutable_planning_data()
189 ->mutable_hybrid_model()
190 ->set_learning_model_output_usage_ratio(
191 static_cast<double>(valid_path_reference_counter_) /
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);
201 if (!IsValidPathReference(*reference_line_info,
202 path_boundaries[regular_path_bound_idx],
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";
210 ->mutable_planning_data()
211 ->mutable_hybrid_model()
212 ->set_learning_model_output_fail_reason(err_msg);
215 ->mutable_planning_data()
216 ->mutable_hybrid_model()
217 ->set_learning_model_output_usage_ratio(
218 static_cast<double>(valid_path_reference_counter_) /
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();
233 ->mutable_planning_data()
234 ->mutable_hybrid_model()
235 ->set_using_learning_model_output(
true);
238 ->mutable_planning_data()
239 ->mutable_hybrid_model()
240 ->mutable_evaluated_path_reference()
241 ->mutable_path_point()
243 {evaluated_path_reference.begin(), evaluated_path_reference.end()});
246 std::move(evaluated_path_reference));
252 ++valid_path_reference_counter_;
253 ADEBUG <<
"valid_path_reference_counter[" << valid_path_reference_counter_
254 <<
"] total_path_counter[" << total_path_counter_ <<
"]";
258 ->mutable_planning_data()
259 ->mutable_hybrid_model()
260 ->set_learning_model_output_usage_ratio(
261 static_cast<double>(valid_path_reference_counter_) /
264 ADEBUG <<
"path reference size:" << path_reference.size();
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());
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);
285 return path_bounds.size();
288bool PathReferenceDecider::IsValidPathReference(
289 const ReferenceLineInfo &reference_line_info,
290 const PathBoundary ®ular_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,
297 ADEBUG <<
", x: " << std::setprecision(9) << cur_x
298 <<
", y: " << std::setprecision(9) << cur_y;
305bool PathReferenceDecider::IsADCBoxAlongPathReferenceWithinPathBounds(
306 const std::vector<TrajectoryPoint> &path_reference,
307 const PathBoundary ®ular_path_bound) {
312 std::vector<std::vector<LineSegment2d>> segmented_path_bounds;
313 PathBoundToLineSegments(regular_path_bound, &segmented_path_bounds);
315 std::vector<Box2d> vehicle_boxes;
316 for (
const auto path_reference_point : path_reference) {
318 const auto &path_point = path_reference_point.path_point();
320 common::VehicleConfigHelper::Instance()->GetBoundingBox(path_point);
321 vehicle_boxes.emplace_back(vehicle_box);
325 for (
auto segmented_path_bound : segmented_path_bounds) {
327 for (
auto line_segment : segmented_path_bound) {
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()
336 <<
"Violate path bound at [" << line_segment.start().x() <<
","
337 << line_segment.start().y() <<
"];"
338 <<
"[" << line_segment.end().x() <<
","
339 << line_segment.end().y() <<
"]";
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();
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);
367 Vec2d prev_left_cartesian_point;
368 Vec2d prev_right_cartesian_point;
370 &prev_left_cartesian_point);
372 &prev_right_cartesian_point);
373 for (
size_t i = 1; i < path_bound_size; ++i) {
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;
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);
387 &left_cartesian_point);
389 &right_cartesian_point);
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);
401 path_bound_segments->emplace_back(cur_left_bound_segments);
402 path_bound_segments->emplace_back(cur_right_bound_segments);
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);
416 if (point_sl.s() > end_s ||
417 point_sl.s() < start_s - kPathBoundsDeciderResolution * 2) {
418 AERROR <<
"Longitudinally outside the boundary.";
422 while (idx_after < path_bound_size &&
423 start_s + idx_after * delta_s < point_sl.s()) {
426 if (idx_after == 0) {
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()) {
440 ADEBUG <<
"Laterally outside the boundary.";
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);
455 for (idx = 0; idx < path_bound.boundary().size(); ++idx) {
457 double cur_s =
static_cast<double>(idx) * delta_s;
458 if (cur_s > path_reference_end_s) {
461 evaluated_path_reference->emplace_back(
462 discrete_path_reference.Evaluate(cur_s));
466void PathReferenceDecider::RecordDebugInfo(
467 const std::vector<PathPoint> &path_points,
const std::string &path_name,
468 ReferenceLineInfo *
const reference_line_info) {
470 ACHECK(!path_points.empty());
471 CHECK_NOTNULL(reference_line_info);
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()});
A general class to denote the return status of an API call.
static Status OK()
generate a success status.
Frame holds all data for one planning cycle.
const std::list< ReferenceLineInfo > & reference_line_info() const
const common::TrajectoryPoint & PlanningStartPoint() const
void set_is_valid_path_reference(bool is_valid_path_reference)
void set_path_reference(const std::vector< common::PathPoint > &path_reference)
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
bool is_path_lane_borrow() 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)
PathData * mutable_path_data()
bool SLToXY(const common::SLPoint &sl_point, common::math::Vec2d *const xy_point) const
std::shared_ptr< DependencyInjector > injector_
ReferenceLineInfo * reference_line_info_
virtual bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
virtual common::Status Execute(Frame *frame, ReferenceLineInfo *reference_line_info)
Planning module main class.
Define the LineSegment2d class.
constexpr double kMathEpsilon
optional bool skip_path_reference_in_side_pass
optional bool skip_path_reference_in_change_lane