Apollo 11.0
自动驾驶开放平台
reuse_path.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2023 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
18
19#include <algorithm>
20#include <memory>
21#include <string>
22#include <utility>
23#include <vector>
26
27namespace apollo {
28namespace planning {
29
33
34bool ReusePath::Init(const std::string& config_dir, const std::string& name,
35 const std::shared_ptr<DependencyInjector>& injector) {
36 if (!Task::Init(config_dir, name, injector)) {
37 return false;
38 }
39 // Load the config this task.
40 return Task::LoadConfig<ReusePathConfig>(&config_);
41}
42
43apollo::common::Status ReusePath::Process(
44 Frame* frame, ReferenceLineInfo* reference_line_info) {
45 if (!reference_line_info->path_data().Empty()) {
46 return Status::OK();
47 }
48 reference_line_info->set_path_reusable(false);
49 if (!IsPathReusable(frame, reference_line_info)) {
50 path_reusable_ = false;
51 return Status::OK();
52 }
53 path_reusable_ = true;
54 if (!TrimHistoryPath(frame, reference_line_info)) {
55 path_reusable_ = false;
56 return Status::OK();
57 }
58
59 reference_line_info->set_path_reusable(true);
60
61 return Status::OK();
62}
63
64bool ReusePath::IsPathReusable(Frame* frame,
65 ReferenceLineInfo* const reference_line_info) {
66 // active path reuse during change_lane only
67 auto* lane_change_status = injector_->planning_context()
68 ->mutable_planning_status()
69 ->mutable_change_lane();
70 ADEBUG << "lane change status: " << lane_change_status->ShortDebugString();
71 if (!reference_line_info->IsChangeLanePath() &&
73 ADEBUG << "skipping reusing path: not in lane_change";
74 return false;
75 }
76 if (reference_line_info->IsChangeLanePath() &&
77 lane_change_status->status() != ChangeLaneStatus::IN_CHANGE_LANE) {
78 return false;
79 }
80 // stop reusing current path:
81 // 1. replan path
82 // 2. collision
83 // 3. failed to trim previous path
84 // 4. speed optimization failed on previous path
85 bool speed_optimization_successful = false;
86 const auto& history_frame = injector_->frame_history()->Latest();
87 if (history_frame) {
88 const auto history_trajectory_type =
89 history_frame->reference_line_info().front().trajectory_type();
90 speed_optimization_successful =
91 (history_trajectory_type != ADCTrajectory::SPEED_FALLBACK);
92 if (history_frame->current_frame_planned_path().empty()) {
93 return false;
94 }
95 }
96 if (path_reusable_) {
97 if (!frame->current_frame_planned_trajectory().is_replan() &&
98 speed_optimization_successful && IsCollisionFree(reference_line_info)) {
99 ADEBUG << "reuse path";
100 return true;
101 } else {
102 // stop reuse path
103 ADEBUG << "stop reuse path";
104 return false;
105 }
106 } else {
107 // F -> T
108 auto* mutable_path_decider_status = injector_->planning_context()
109 ->mutable_planning_status()
110 ->mutable_path_decider();
111 static constexpr int kWaitCycle = -2; // wait 2 cycle
112
113 const int front_static_obstacle_cycle_counter =
114 mutable_path_decider_status->front_static_obstacle_cycle_counter();
115 const bool ignore_blocking_obstacle =
116 IsIgnoredBlockingObstacle(reference_line_info);
117 ADEBUG << "counter[" << front_static_obstacle_cycle_counter
118 << "] IsIgnoredBlockingObstacle[" << ignore_blocking_obstacle << "]";
119 // stop reusing current path:
120 // 1. blocking obstacle disappeared or moving far away
121 // 2. trimming successful
122 // 3. no statical obstacle collision.
123 if ((front_static_obstacle_cycle_counter <= kWaitCycle ||
124 ignore_blocking_obstacle) &&
125 speed_optimization_successful && IsCollisionFree(reference_line_info)) {
126 // enable reuse path
127 ADEBUG << "reuse path: front_blocking_obstacle ignorable";
128 return true;
129 }
130 }
131 return path_reusable_;
132}
133
134bool ReusePath::IsIgnoredBlockingObstacle(
135 ReferenceLineInfo* const reference_line_info) {
136 const ReferenceLine& reference_line = reference_line_info->reference_line();
137 static constexpr double kSDistBuffer = 30.0; // meter
138 static constexpr int kTimeBuffer = 3; // second
139 // vehicle speed
140 double adc_speed = injector_->vehicle_state()->linear_velocity();
141 double final_s_buffer = std::max(kSDistBuffer, kTimeBuffer * adc_speed);
142 // current vehicle s position
143 common::SLPoint adc_position_sl;
144 GetADCSLPoint(reference_line, &adc_position_sl);
145 // blocking obstacle start s
146 double blocking_obstacle_start_s;
147 if (GetBlockingObstacleS(reference_line_info, &blocking_obstacle_start_s) &&
148 // distance to blocking obstacle
149 (blocking_obstacle_start_s - adc_position_sl.s() > final_s_buffer)) {
150 ADEBUG << "blocking obstacle distance: "
151 << blocking_obstacle_start_s - adc_position_sl.s();
152 return true;
153 } else {
154 return false;
155 }
156}
157
158bool ReusePath::GetBlockingObstacleS(
159 ReferenceLineInfo* const reference_line_info, double* blocking_obstacle_s) {
160 auto* mutable_path_decider_status = injector_->planning_context()
161 ->mutable_planning_status()
162 ->mutable_path_decider();
163 // get blocking obstacle ID (front_static_obstacle_id)
164 const std::string& blocking_obstacle_ID =
165 mutable_path_decider_status->front_static_obstacle_id();
166 const IndexedList<std::string, Obstacle>& indexed_obstacles =
167 reference_line_info->path_decision()->obstacles();
168 const auto* blocking_obstacle = indexed_obstacles.Find(blocking_obstacle_ID);
169
170 if (blocking_obstacle == nullptr) {
171 return false;
172 }
173
174 const auto& obstacle_sl = blocking_obstacle->PerceptionSLBoundary();
175 *blocking_obstacle_s = obstacle_sl.start_s();
176 ADEBUG << "blocking obstacle distance: " << obstacle_sl.start_s();
177 return true;
178}
179
180void ReusePath::GetADCSLPoint(const ReferenceLine& reference_line,
181 common::SLPoint* adc_position_sl) {
182 common::math::Vec2d adc_position = {injector_->vehicle_state()->x(),
183 injector_->vehicle_state()->y()};
184 reference_line.XYToSL(adc_position, adc_position_sl);
185}
186
187bool ReusePath::IsCollisionFree(ReferenceLineInfo* const reference_line_info) {
188 const ReferenceLine& reference_line = reference_line_info->reference_line();
189 static constexpr double kMinObstacleArea = 1e-4;
190 const double kSBuffer = 0.5;
191 // current vehicle sl position
192 common::SLPoint adc_position_sl;
193 GetADCSLPoint(reference_line, &adc_position_sl);
194
195 // current obstacles
196 std::vector<Polygon2d> obstacle_polygons;
197 for (auto obstacle :
198 reference_line_info->path_decision()->obstacles().Items()) {
199 // filtered all non-static objects and virtual obstacle
200 if (!obstacle->IsStatic() || obstacle->IsVirtual()) {
201 if (!obstacle->IsStatic()) {
202 ADEBUG << "SPOT a dynamic obstacle";
203 }
204 if (obstacle->IsVirtual()) {
205 ADEBUG << "SPOT a virtual obstacle";
206 }
207 continue;
208 }
209
210 const auto& obstacle_sl = obstacle->PerceptionSLBoundary();
211 // Ignore obstacles behind ADC
212 if ((obstacle_sl.end_s() < adc_position_sl.s() - kSBuffer) ||
213 // Ignore too small obstacles.
214 (obstacle_sl.end_s() - obstacle_sl.start_s()) *
215 (obstacle_sl.end_l() - obstacle_sl.start_l()) <
217 continue;
218 }
219 obstacle_polygons.push_back(
220 Polygon2d({Vec2d(obstacle_sl.start_s(), obstacle_sl.start_l()),
221 Vec2d(obstacle_sl.start_s(), obstacle_sl.end_l()),
222 Vec2d(obstacle_sl.end_s(), obstacle_sl.end_l()),
223 Vec2d(obstacle_sl.end_s(), obstacle_sl.start_l())}));
224 }
225
226 if (obstacle_polygons.empty()) {
227 return true;
228 }
229
230 const auto& history_frame = injector_->frame_history()->Latest();
231 if (!history_frame) {
232 return false;
233 }
234 const DiscretizedPath& history_path =
235 history_frame->current_frame_planned_path();
236 if (history_path.empty()) {
237 AINFO << "No history path skip reuse";
238 return false;
239 }
240 // path end point
241 common::SLPoint path_end_position_sl;
242 common::math::Vec2d path_end_position = {history_path.back().x(),
243 history_path.back().y()};
244 reference_line.XYToSL(path_end_position, &path_end_position_sl);
245 const double min_distance_to_end =
246 FLAGS_path_bounds_decider_resolution * FLAGS_num_extra_tail_bound_point;
247 for (size_t i = 0; i < history_path.size(); ++i) {
248 common::SLPoint path_position_sl;
249 common::math::Vec2d path_position = {history_path[i].x(),
250 history_path[i].y()};
251 reference_line.XYToSL(path_position, &path_position_sl);
252 if (path_end_position_sl.s() - path_position_sl.s() <=
253 min_distance_to_end) {
254 break;
255 }
256 if (path_position_sl.s() < adc_position_sl.s() - kSBuffer) {
257 continue;
258 }
259 const auto& vehicle_box =
260 common::VehicleConfigHelper::Instance()->GetBoundingBox(
261 history_path[i]);
262 std::vector<Vec2d> ABCDpoints = vehicle_box.GetAllCorners();
263 for (const auto& corner_point : ABCDpoints) {
264 // For each corner point, project it onto reference_line
265 common::SLPoint curr_point_sl;
266 if (!reference_line.XYToSL(corner_point, &curr_point_sl)) {
267 AERROR << "Failed to get the projection from point onto "
268 "reference_line";
269 return false;
270 }
271 auto curr_point = Vec2d(curr_point_sl.s(), curr_point_sl.l());
272 // Check if it's in any polygon of other static obstacles.
273 for (const auto& obstacle_polygon : obstacle_polygons) {
274 if (obstacle_polygon.IsPointIn(curr_point)) {
275 // for debug
276 ADEBUG << "s distance to end point:" << path_end_position_sl.s();
277 ADEBUG << "s distance to end point:" << path_position_sl.s();
278 ADEBUG << "[" << i << "]"
279 << ", history_path[i].x(): " << std::setprecision(9)
280 << history_path[i].x() << ", history_path[i].y()"
281 << std::setprecision(9) << history_path[i].y();
282 ADEBUG << "collision:" << curr_point.x() << ", " << curr_point.y();
283 Vec2d xy_point;
284 reference_line.SLToXY(curr_point_sl, &xy_point);
285 ADEBUG << "collision:" << xy_point.x() << ", " << xy_point.y();
286
287 return false;
288 }
289 }
290 }
291 }
292 return true;
293}
294
295// check the length of the path
296bool ReusePath::NotShortPath(const DiscretizedPath& current_path) {
297 // TODO(shu): use gflag
298 return current_path.size() >= config_.short_path_threshold();
299}
300
301bool ReusePath::TrimHistoryPath(Frame* frame,
302 ReferenceLineInfo* const reference_line_info) {
303 const ReferenceLine& reference_line = reference_line_info->reference_line();
304 const auto& history_frame = injector_->frame_history()->Latest();
305 if (!history_frame) {
306 ADEBUG << "no history frame";
307 return false;
308 }
309
310 const common::TrajectoryPoint history_planning_start_point =
311 history_frame->PlanningStartPoint();
312 common::PathPoint history_init_path_point =
313 history_planning_start_point.path_point();
314 ADEBUG << "history_init_path_point x:[" << std::setprecision(9)
315 << history_init_path_point.x() << "], y["
316 << history_init_path_point.y() << "], s: ["
317 << history_init_path_point.s() << "]";
318
319 const common::TrajectoryPoint planning_start_point =
320 frame->PlanningStartPoint();
321 common::PathPoint init_path_point = planning_start_point.path_point();
322 ADEBUG << "init_path_point x:[" << std::setprecision(9) << init_path_point.x()
323 << "], y[" << init_path_point.y() << "], s: [" << init_path_point.s()
324 << "]";
325
326 const DiscretizedPath& history_path =
327 history_frame->current_frame_planned_path();
328 DiscretizedPath trimmed_path;
329 common::SLPoint adc_position_sl; // current vehicle sl position
330 GetADCSLPoint(reference_line, &adc_position_sl);
331 ADEBUG << "adc_position_sl.s(): " << adc_position_sl.s();
332 ADEBUG << "history_path.size(): " << history_path.size();
333 size_t path_start_index = 0;
334
335 for (size_t i = 0; i < history_path.size(); ++i) {
336 // find previous init point
337 if (history_path[i].s() > 0) {
338 path_start_index = i;
339 break;
340 }
341 }
342 ADEBUG << "!!!path_start_index[" << path_start_index << "]";
343
344 // get current s=0
345 common::SLPoint init_path_position_sl;
346 reference_line.XYToSL(init_path_point, &init_path_position_sl);
347 bool inserted_init_point = false;
348
349 for (size_t i = path_start_index; i < history_path.size(); ++i) {
350 common::SLPoint path_position_sl;
351 common::math::Vec2d path_position = {history_path[i].x(),
352 history_path[i].y()};
353
354 reference_line.XYToSL(path_position, &path_position_sl);
355
356 double updated_s = path_position_sl.s() - init_path_position_sl.s();
357 // insert init point
358 if (updated_s > 0 && !inserted_init_point) {
359 trimmed_path.emplace_back(init_path_point);
360 trimmed_path.back().set_s(0);
361 inserted_init_point = true;
362 }
363
364 trimmed_path.emplace_back(history_path[i]);
365
366 // if (i < 50) {
367 // ADEBUG << "path_point:[" << i << "]" << updated_s;
368 // path_position_sl.s();
369 // ADEBUG << std::setprecision(9) << "path_point:[" << i << "]"
370 // << "x: [" << history_path[i].x() << "], y:[" <<
371 // history_path[i].y()
372 // << "]. s[" << history_path[i].s() << "]";
373 // }
374 trimmed_path.back().set_s(updated_s);
375 }
376
377 ADEBUG << "trimmed_path[0]: " << trimmed_path.front().s();
378 ADEBUG << "[END] trimmed_path.size(): " << trimmed_path.size();
379
380 if (!NotShortPath(trimmed_path)) {
381 ADEBUG << "short path: " << trimmed_path.size();
382 return false;
383 }
384
385 // set path
386 auto path_data = reference_line_info->mutable_path_data();
387 ADEBUG << "previous path_data size: " << history_path.size();
388 path_data->SetReferenceLine(&reference_line);
389 ADEBUG << "previous path_data size: " << path_data->discretized_path().size();
390 path_data->SetDiscretizedPath(DiscretizedPath(std::move(trimmed_path)));
391 ADEBUG << "not short path: " << trimmed_path.size();
392 ADEBUG << "current path size: "
393 << reference_line_info->path_data().discretized_path().size();
394 RecordDebugInfo(*path_data, path_data->path_label(), reference_line_info);
395 return true;
396}
397
398} // namespace planning
399} // 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
The class of polygon in 2-D.
Definition polygon2d.h:42
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
Frame holds all data for one planning cycle.
Definition frame.h:62
void RecordDebugInfo(const PathBound &path_boundaries, const std::string &debug_name, ReferenceLineInfo *const reference_line_info)
add path_boundary debug info for PnC monitor
ReferenceLineInfo holds all data for one reference line.
void set_path_reusable(const bool path_reusable)
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
Definition reuse_path.cc:34
std::shared_ptr< DependencyInjector > injector_
Definition task.h:59
virtual bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
Definition task.cc:40
Planning module main class.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
class register implement
Definition arena_queue.h:37
optional bool enable_reuse_path_in_lane_follow