Apollo 11.0
自动驾驶开放平台
path_decider.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 <memory>
25
26#include "modules/common_msgs/planning_msgs/decision.pb.h"
27
33
34namespace apollo {
35namespace planning {
36
40
41bool PathDecider::Init(const std::string &config_dir, const std::string &name,
42 const std::shared_ptr<DependencyInjector> &injector) {
43 if (!Task::Init(config_dir, name, injector)) {
44 return false;
45 }
46 // Load the config this task.
47 return Task::LoadConfig<PathDeciderConfig>(&config_);
48}
49
51 ReferenceLineInfo *reference_line_info) {
52 Task::Execute(frame, reference_line_info);
53 return Process(reference_line_info, reference_line_info->path_data(),
54 reference_line_info->path_decision());
55}
56
57Status PathDecider::Process(const ReferenceLineInfo *reference_line_info,
58 const PathData &path_data,
59 PathDecision *const path_decision) {
60 // skip path_decider if reused path
61 if (FLAGS_enable_skip_path_tasks && reference_line_info->path_reusable()) {
62 return Status::OK();
63 }
64 PrintCurves debug_info;
65 const auto &path = path_data.discretized_path();
66 if (!path.empty()) {
67 const auto &vehicle_box =
68 common::VehicleConfigHelper::Instance()->GetBoundingBox(path[0]);
69 debug_info.AddPoint("start_point_box", vehicle_box.GetAllCorners());
70 }
71
72 for (const auto &path_pt : path) {
73 debug_info.AddPoint("output_path", path_pt.x(), path_pt.y());
74 }
75 debug_info.PrintToLog();
76 std::string blocking_obstacle_id;
77 auto *mutable_path_decider_status = injector_->planning_context()
78 ->mutable_planning_status()
79 ->mutable_path_decider();
80 if (reference_line_info->GetBlockingObstacle() != nullptr) {
81 blocking_obstacle_id = reference_line_info->GetBlockingObstacle()->Id();
82 int front_static_obstacle_cycle_counter =
83 mutable_path_decider_status->front_static_obstacle_cycle_counter();
84 mutable_path_decider_status->set_front_static_obstacle_cycle_counter(
85 std::max(front_static_obstacle_cycle_counter, 0));
86 mutable_path_decider_status->set_front_static_obstacle_cycle_counter(
87 std::min(front_static_obstacle_cycle_counter + 1, 10));
88 mutable_path_decider_status->set_front_static_obstacle_id(
89 reference_line_info->GetBlockingObstacle()->Id());
90 } else {
91 int front_static_obstacle_cycle_counter =
92 mutable_path_decider_status->front_static_obstacle_cycle_counter();
93 mutable_path_decider_status->set_front_static_obstacle_cycle_counter(
94 std::min(front_static_obstacle_cycle_counter, 0));
95 mutable_path_decider_status->set_front_static_obstacle_cycle_counter(
96 std::max(front_static_obstacle_cycle_counter - 1, -10));
97 if (mutable_path_decider_status->front_static_obstacle_cycle_counter() <
98 -2) {
99 std::string id = " ";
100 mutable_path_decider_status->set_front_static_obstacle_id(id);
101 }
102 }
103 if (!MakeObjectDecision(path_data, blocking_obstacle_id, path_decision)) {
104 const std::string msg = "Failed to make decision based on tunnel";
105 AERROR << msg;
106 return Status(ErrorCode::PLANNING_ERROR, msg);
107 }
108 return Status::OK();
109}
110
111bool PathDecider::MakeObjectDecision(const PathData &path_data,
112 const std::string &blocking_obstacle_id,
113 PathDecision *const path_decision) {
114 if (!MakeStaticObstacleDecision(path_data, blocking_obstacle_id,
115 path_decision)) {
116 AERROR << "Failed to make decisions for static obstacles";
117 return false;
118 }
119 if (config_.ignore_backward_obstacle()) {
120 IgnoreBackwardObstacle(path_decision);
121 }
122
123 return true;
124}
125
126// TODO(jiacheng): eventually this entire "path_decider" should be retired.
127// Before it gets retired, its logics are slightly modified so that everything
128// still works well for now.
129bool PathDecider::MakeStaticObstacleDecision(
130 const PathData &path_data, const std::string &blocking_obstacle_id,
131 PathDecision *const path_decision) {
132 // Sanity checks and get important values.
133 ACHECK(path_decision);
134 const auto &frenet_path = path_data.frenet_frame_path();
135 if (frenet_path.empty()) {
136 AERROR << "Path is empty.";
137 return false;
138 }
139 const double half_width =
141 const double lateral_radius = half_width + FLAGS_lateral_ignore_buffer;
142
143 // Go through every obstacle and make decisions.
144 for (const auto *obstacle : path_decision->obstacles().Items()) {
145 const std::string &obstacle_id = obstacle->Id();
146 const std::string obstacle_type_name =
147 PerceptionObstacle_Type_Name(obstacle->Perception().type());
148 ADEBUG << "obstacle_id[<< " << obstacle_id << "] type["
149 << obstacle_type_name << "]";
150
151 if (!obstacle->IsStatic() || obstacle->IsVirtual()) {
152 continue;
153 }
154 // - skip decision making for obstacles with IGNORE/STOP decisions already.
155 if (obstacle->HasLongitudinalDecision() &&
156 obstacle->LongitudinalDecision().has_ignore() &&
157 obstacle->HasLateralDecision() &&
158 obstacle->LateralDecision().has_ignore()) {
159 continue;
160 }
161 if (obstacle->HasLongitudinalDecision() &&
162 obstacle->LongitudinalDecision().has_stop()) {
163 // STOP decision
164 continue;
165 }
166 // - add STOP decision for blocking obstacles.
167 if (obstacle->Id() == blocking_obstacle_id &&
168 !injector_->planning_context()
169 ->planning_status()
170 .path_decider()
171 .is_in_path_lane_borrow_scenario()) {
172 // Add stop decision
173 ADEBUG << "Blocking obstacle = " << blocking_obstacle_id;
174 ObjectDecisionType object_decision;
175 *object_decision.mutable_stop() = GenerateObjectStopDecision(*obstacle);
176 path_decision->AddLongitudinalDecision("PathDecider/blocking_obstacle",
177 obstacle->Id(), object_decision);
178 continue;
179 }
180 // - skip decision making for clear-zone obstacles.
181 if (obstacle->reference_line_st_boundary().boundary_type() ==
183 continue;
184 }
185
186 // 0. IGNORE by default and if obstacle is not in path s at all.
187 ObjectDecisionType object_decision;
188 object_decision.mutable_ignore();
189 const auto &sl_boundary = obstacle->PerceptionSLBoundary();
190 if (sl_boundary.end_s() < frenet_path.front().s() ||
191 sl_boundary.start_s() > frenet_path.back().s()) {
192 path_decision->AddLongitudinalDecision("PathDecider/not-in-s",
193 obstacle->Id(), object_decision);
194 path_decision->AddLateralDecision("PathDecider/not-in-s", obstacle->Id(),
195 object_decision);
196 continue;
197 }
198
199 const auto frenet_point = frenet_path.GetNearestPoint(sl_boundary);
200 const double curr_l = frenet_point.l();
201 double min_nudge_l = half_width + config_.static_obstacle_buffer() / 2.0;
202
203 if (curr_l - lateral_radius > sl_boundary.end_l() ||
204 curr_l + lateral_radius < sl_boundary.start_l()) {
205 // 1. IGNORE if laterally too far away.
206 path_decision->AddLateralDecision("PathDecider/not-in-l", obstacle->Id(),
207 object_decision);
208 } else if (sl_boundary.end_l() >= curr_l - min_nudge_l &&
209 sl_boundary.start_l() <= curr_l + min_nudge_l) {
210 if (config_.skip_overlap_stop_check()) {
211 AINFO << "skip_overlap_stop_check";
212 } else {
213 // 2. STOP if laterally too overlapping.
214 *object_decision.mutable_stop() = GenerateObjectStopDecision(*obstacle);
215
216 if (path_decision->MergeWithMainStop(
217 object_decision.stop(), obstacle->Id(),
220 path_decision->AddLongitudinalDecision(
221 "PathDecider/nearest-stop", obstacle->Id(), object_decision);
222 } else {
223 ObjectDecisionType object_decision;
224 object_decision.mutable_ignore();
225 path_decision->AddLongitudinalDecision(
226 "PathDecider/not-nearest-stop", obstacle->Id(), object_decision);
227 }
228 AINFO << "Add stop decision for static obs " << obstacle->Id()
229 << "start l" << sl_boundary.start_l() << "end l"
230 << sl_boundary.end_l() << "curr_l" << curr_l << "min_nudge_l"
231 << min_nudge_l;
232 }
233 } else {
234 // 3. NUDGE if laterally very close.
235 if (sl_boundary.end_l() < curr_l - min_nudge_l) { // &&
236 // sl_boundary.end_l() > curr_l - min_nudge_l - 0.3) {
237 // LEFT_NUDGE
238 ObjectNudge *object_nudge_ptr = object_decision.mutable_nudge();
239 object_nudge_ptr->set_type(ObjectNudge::LEFT_NUDGE);
240 object_nudge_ptr->set_distance_l(config_.static_obstacle_buffer());
241 path_decision->AddLateralDecision("PathDecider/left-nudge",
242 obstacle->Id(), object_decision);
243 } else if (sl_boundary.start_l() > curr_l + min_nudge_l) { // &&
244 // sl_boundary.start_l() < curr_l + min_nudge_l + 0.3) {
245 // RIGHT_NUDGE
246 ObjectNudge *object_nudge_ptr = object_decision.mutable_nudge();
247 object_nudge_ptr->set_type(ObjectNudge::RIGHT_NUDGE);
248 object_nudge_ptr->set_distance_l(-config_.static_obstacle_buffer());
249 path_decision->AddLateralDecision("PathDecider/right-nudge",
250 obstacle->Id(), object_decision);
251 }
252 }
253 }
254
255 return true;
256}
257
258ObjectStop PathDecider::GenerateObjectStopDecision(
259 const Obstacle &obstacle) const {
260 ObjectStop object_stop;
261
262 double stop_distance = obstacle.MinRadiusStopDistance(
263 VehicleConfigHelper::GetConfig().vehicle_param());
264 object_stop.set_reason_code(StopReasonCode::STOP_REASON_OBSTACLE);
265 object_stop.set_distance_s(-stop_distance);
266
267 const double stop_ref_s =
268 obstacle.PerceptionSLBoundary().start_s() - stop_distance;
269 const auto stop_ref_point =
271 object_stop.mutable_stop_point()->set_x(stop_ref_point.x());
272 object_stop.mutable_stop_point()->set_y(stop_ref_point.y());
273 object_stop.set_stop_heading(stop_ref_point.heading());
274 return object_stop;
275}
276
277bool PathDecider::IgnoreBackwardObstacle(PathDecision *const path_decision) {
278 double adc_start_s = reference_line_info_->AdcSlBoundary().start_s();
279 for (const auto *obstacle : path_decision->obstacles().Items()) {
280 if (obstacle->IsStatic() || obstacle->IsVirtual()) {
281 continue;
282 }
283 if (obstacle->Obstacle::PerceptionSLBoundary().end_s() < adc_start_s) {
284 ObjectDecisionType object_decision;
285 object_decision.mutable_ignore();
286 path_decision->AddLongitudinalDecision(
287 "PathDecider/ignore-backward-obstacle", obstacle->Id(),
288 object_decision);
289 }
290 }
291 return true;
292}
293
294} // namespace planning
295} // namespace apollo
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
@Brief This is a helper class that can load vehicle configurations.
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
void set_x(const double x)
Setter for x component
Definition vec2d.h:60
Frame holds all data for one planning cycle.
Definition frame.h:62
const std::string & Id() const
Definition obstacle.h:75
const DiscretizedPath & discretized_path() const
Definition path_data.cc:90
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
PathDecision represents all obstacle decisions on one path.
ReferenceLineInfo holds all data for one reference line.
const ReferenceLine & reference_line() const
const SLBoundary & AdcSlBoundary() const
ReferencePoint GetReferencePoint(const double s) 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 ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
Some util functions.
class register implement
Definition arena_queue.h:37
optional VehicleParam vehicle_param