Apollo 11.0
自动驾驶开放平台
navi_path_decider.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 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 <utility>
26
27#include "modules/common_msgs/planning_msgs/sl_boundary.pb.h"
28
29#include "cyber/common/log.h"
33
34namespace apollo {
35namespace planning {
36
40
42 // TODO(all): Add your other initialization.
43}
44
46 move_dest_lane_config_talbe_.clear();
47 max_speed_levels_.clear();
48 config_ = config.navi_path_decider_config();
49 auto move_dest_lane_config_talbe = config_.move_dest_lane_config_talbe();
50 for (const auto& item : move_dest_lane_config_talbe.lateral_shift()) {
51 double max_speed_level = item.max_speed();
52 double max_move_dest_lane_shift_y = item.max_move_dest_lane_shift_y();
53 if (move_dest_lane_config_talbe_.find(max_speed_level) ==
54 move_dest_lane_config_talbe_.end()) {
55 move_dest_lane_config_talbe_.emplace(
56 std::make_pair(max_speed_level, max_move_dest_lane_shift_y));
57 max_speed_levels_.push_back(max_speed_level);
58 }
59 }
60 AINFO << "Maximum speeds and move to dest lane config: ";
61 for (const auto& data : move_dest_lane_config_talbe_) {
62 auto max_speed = data.first;
63 auto max_move_dest_lane_shift_y = data.second;
64 AINFO << "[max_speed : " << max_speed
65 << " ,max move dest lane shift y : " << max_move_dest_lane_shift_y
66 << "]";
67 }
68 max_keep_lane_distance_ = config_.max_keep_lane_distance();
69 max_keep_lane_shift_y_ = config_.max_keep_lane_shift_y();
70 min_keep_lane_offset_ = config_.min_keep_lane_offset();
71 keep_lane_shift_compensation_ = config_.keep_lane_shift_compensation();
72 start_plan_point_from_ = config_.start_plan_point_from();
73 move_dest_lane_compensation_ = config_.move_dest_lane_compensation();
74
75 is_init_ = obstacle_decider_.Init(config);
76 return is_init_;
77}
78
80 ReferenceLineInfo* const reference_line_info) {
81 NaviTask::Execute(frame, reference_line_info);
82 vehicle_state_ = frame->vehicle_state();
83 cur_reference_line_lane_id_ = reference_line_info->Lanes().Id();
84 auto ret = Process(reference_line_info->reference_line(),
85 frame->PlanningStartPoint(), frame->obstacles(),
86 reference_line_info->path_decision(),
87 reference_line_info->mutable_path_data());
88 RecordDebugInfo(reference_line_info->path_data());
89 if (ret != Status::OK()) {
90 reference_line_info->SetDrivable(false);
91 AERROR << "Reference Line " << reference_line_info->Lanes().Id()
92 << " is not drivable after " << Name();
93 }
94 return ret;
95}
96
97apollo::common::Status NaviPathDecider::Process(
98 const ReferenceLine& reference_line,
99 const common::TrajectoryPoint& init_point,
100 const std::vector<const Obstacle*>& obstacles,
101 PathDecision* const path_decision, PathData* const path_data) {
102 CHECK_NOTNULL(path_decision);
103 CHECK_NOTNULL(path_data);
104 start_plan_point_.set_x(vehicle_state_.x());
105 start_plan_point_.set_y(vehicle_state_.y());
106 start_plan_point_.set_theta(vehicle_state_.heading());
107 start_plan_v_ = vehicle_state_.linear_velocity();
108 start_plan_a_ = vehicle_state_.linear_acceleration();
109 if (start_plan_point_from_ == 1) {
110 // start plan point from planning schedule
111 start_plan_point_.set_x(init_point.path_point().x());
112 start_plan_point_.set_y(init_point.path_point().y());
113 start_plan_point_.set_theta(init_point.path_point().theta());
114 start_plan_v_ = init_point.v();
115 start_plan_a_ = init_point.a();
116 }
117
118 // intercept path points from reference line
119 std::vector<apollo::common::PathPoint> path_points;
120 if (!GetBasicPathData(reference_line, &path_points)) {
121 AERROR << "Get path points from reference line failed";
123 "NaviPathDecider GetBasicPathData");
124 }
125
126 // according to the position of the start plan point and the reference line,
127 // the path trajectory intercepted from the reference line is shifted on the
128 // y-axis to adc.
129 double dest_ref_line_y = path_points[0].y();
130
131 ADEBUG << "in current plan cycle, adc to ref line distance : "
132 << dest_ref_line_y << "lane id : " << cur_reference_line_lane_id_;
133 MoveToDestLane(dest_ref_line_y, &path_points);
134
135 KeepLane(dest_ref_line_y, &path_points);
136
138 if (!path_data->SetDiscretizedPath(DiscretizedPath(std::move(path_points)))) {
139 AERROR << "Set path data failed.";
141 "NaviPathDecider SetDiscretizedPath");
142 }
143
144 return Status::OK();
145}
146
147void NaviPathDecider::MoveToDestLane(
148 const double dest_ref_line_y,
149 std::vector<common::PathPoint>* const path_points) {
150 double dest_lateral_distance = std::fabs(dest_ref_line_y);
151 if (dest_lateral_distance < max_keep_lane_distance_) {
152 return;
153 }
154
155 // calculate lateral shift range and theta chage ratio
156 double max_shift_y = CalculateDistanceToDestLane();
157
158 double actual_start_point_y = std::copysign(max_shift_y, dest_ref_line_y);
159 // lateral shift path_points to the max_y
160 double lateral_shift_value = -dest_ref_line_y + actual_start_point_y;
161 // The steering wheel is more sensitive to the left than to the right and
162 // requires a compensation value to the right
163 lateral_shift_value =
164 lateral_shift_value > 0.0
165 ? (lateral_shift_value - move_dest_lane_compensation_)
166 : lateral_shift_value;
167 ADEBUG << "in current plan cycle move to dest lane, adc shift to dest "
168 "reference line : "
169 << lateral_shift_value;
170 std::transform(path_points->begin(), path_points->end(), path_points->begin(),
171 [lateral_shift_value](common::PathPoint& old_path_point) {
172 common::PathPoint new_path_point = old_path_point;
173 double new_path_point_y =
174 old_path_point.y() + lateral_shift_value;
175 new_path_point.set_y(new_path_point_y);
176 return new_path_point;
177 });
178}
179
180void NaviPathDecider::KeepLane(
181 const double dest_ref_line_y,
182 std::vector<common::PathPoint>* const path_points) {
183 double dest_lateral_distance = std::fabs(dest_ref_line_y);
184 if (dest_lateral_distance <= max_keep_lane_distance_) {
185 auto& reference_line = reference_line_info_->reference_line();
186 auto obstacles = frame_->obstacles();
187 auto* path_decision = reference_line_info_->path_decision();
188 double actual_dest_point_y =
189 NudgeProcess(reference_line, *path_points, obstacles, *path_decision,
190 vehicle_state_);
191
192 double actual_dest_lateral_distance = std::fabs(actual_dest_point_y);
193 double actual_shift_y = 0.0;
194 if (actual_dest_lateral_distance > min_keep_lane_offset_) {
195 double lateral_shift_value = 0.0;
196 lateral_shift_value =
197 (actual_dest_lateral_distance < max_keep_lane_shift_y_ +
198 min_keep_lane_offset_ -
199 keep_lane_shift_compensation_)
200 ? (actual_dest_lateral_distance - min_keep_lane_offset_ +
201 keep_lane_shift_compensation_)
202 : max_keep_lane_shift_y_;
203 actual_shift_y = std::copysign(lateral_shift_value, actual_dest_point_y);
204 }
205
206 ADEBUG << "in current plan cycle keep lane, actual dest : "
207 << actual_dest_point_y << " adc shift to dest : " << actual_shift_y;
208 std::transform(
209 path_points->begin(), path_points->end(), path_points->begin(),
210 [actual_shift_y](common::PathPoint& old_path_point) {
211 common::PathPoint new_path_point = old_path_point;
212 double new_path_point_y = old_path_point.y() + actual_shift_y;
213 new_path_point.set_y(new_path_point_y);
214 return new_path_point;
215 });
216 }
217}
218
219void NaviPathDecider::RecordDebugInfo(const PathData& path_data) {
220 const auto& path_points = path_data.discretized_path();
221 auto* ptr_optimized_path = reference_line_info_->mutable_debug()
222 ->mutable_planning_data()
223 ->add_path();
224 ptr_optimized_path->set_name(Name());
225 ptr_optimized_path->mutable_path_point()->CopyFrom(
226 {path_points.begin(), path_points.end()});
227}
228
229bool NaviPathDecider::GetBasicPathData(
230 const ReferenceLine& reference_line,
231 std::vector<common::PathPoint>* const path_points) {
232 CHECK_NOTNULL(path_points);
233
234 double min_path_len = config_.min_path_length();
235 // get min path plan length s = v0 * t + 1 / 2.0 * a * t^2
236 double path_len =
237 start_plan_v_ * config_.min_look_forward_time() +
238 start_plan_a_ * pow(config_.min_look_forward_time(), 2) / 2.0;
239 path_len = std::max(path_len, min_path_len);
240
241 const double reference_line_len = reference_line.Length();
242 if (reference_line_len < path_len) {
243 AERROR << "Reference line is too short to generate path trajectory( s = "
244 << reference_line_len << ").";
245 return false;
246 }
247
248 // get the start plan point project s on reference line and get the length of
249 // reference line
250 auto start_plan_point_project = reference_line.GetReferencePoint(
251 start_plan_point_.x(), start_plan_point_.y());
252 common::SLPoint sl_point;
253 if (!reference_line.XYToSL(start_plan_point_project.ToPathPoint(0.0),
254 &sl_point)) {
255 AERROR << "Failed to get start plan point s from reference "
256 "line.";
257 return false;
258 }
259 auto start_plan_point_project_s = sl_point.has_s() ? sl_point.s() : 0.0;
260
261 // get basic path points form reference_line
262 ADEBUG << "Basic path data len ; " << reference_line_len;
263 static constexpr double KDenseSampleUnit = 0.50;
264 static constexpr double KSparseSmapleUnit = 2.0;
265 for (double s = start_plan_point_project_s; s < reference_line_len;
266 s += ((s < path_len) ? KDenseSampleUnit : KSparseSmapleUnit)) {
267 const auto& ref_point = reference_line.GetReferencePoint(s);
268 auto path_point = ref_point.ToPathPoint(s - start_plan_point_project_s);
269 path_points->emplace_back(path_point);
270 }
271
272 if (path_points->empty()) {
273 AERROR << "path poins is empty.";
274 return false;
275 }
276
277 return true;
278}
279
280bool NaviPathDecider::IsSafeChangeLane(const ReferenceLine& reference_line,
281 const PathDecision& path_decision) {
282 const auto& adc_param =
284
285 Vec2d adc_position(start_plan_point_.x(), start_plan_point_.y());
286 Vec2d vec_to_center(
287 (adc_param.front_edge_to_center() - adc_param.back_edge_to_center()) /
288 2.0,
289 (adc_param.left_edge_to_center() - adc_param.right_edge_to_center()) /
290 2.0);
291 Vec2d adc_center(adc_position +
292 vec_to_center.rotate(start_plan_point_.theta()));
293 Box2d adc_box(adc_center, start_plan_point_.theta(), adc_param.length(),
294 adc_param.width());
295 SLBoundary adc_sl_boundary;
296 if (!reference_line.GetSLBoundary(adc_box, &adc_sl_boundary)) {
297 AERROR << "Failed to get ADC boundary from box: " << adc_box.DebugString();
298 return false;
299 }
300
301 for (const auto* obstacle : path_decision.obstacles().Items()) {
302 const auto& sl_boundary = obstacle->PerceptionSLBoundary();
303 static constexpr double kLateralShift = 6.0;
304 if (sl_boundary.start_l() < -kLateralShift ||
305 sl_boundary.end_l() > kLateralShift) {
306 continue;
307 }
308
309 static constexpr double kSafeTime = 3.0;
310 static constexpr double kForwardMinSafeDistance = 6.0;
311 static constexpr double kBackwardMinSafeDistance = 8.0;
312
313 const double kForwardSafeDistance = std::max(
314 kForwardMinSafeDistance,
315 ((vehicle_state_.linear_velocity() - obstacle->speed()) * kSafeTime));
316 const double kBackwardSafeDistance = std::max(
317 kBackwardMinSafeDistance,
318 ((obstacle->speed() - vehicle_state_.linear_velocity()) * kSafeTime));
319 if (sl_boundary.end_s() >
320 adc_sl_boundary.start_s() - kBackwardSafeDistance &&
321 sl_boundary.start_s() <
322 adc_sl_boundary.end_s() + kForwardSafeDistance) {
323 return false;
324 }
325 }
326
327 return true;
328}
329
330double NaviPathDecider::NudgeProcess(
331 const ReferenceLine& reference_line,
332 const std::vector<common::PathPoint>& path_data_points,
333 const std::vector<const Obstacle*>& obstacles,
334 const PathDecision& path_decision,
335 const common::VehicleState& vehicle_state) {
336 double nudge_position_y = 0.0;
337
338 // get nudge latteral position
339 int lane_obstacles_num = 0;
340 static constexpr double KNudgeEpsilon = 1e-6;
341 double nudge_distance = obstacle_decider_.GetNudgeDistance(
342 obstacles, reference_line, path_decision, path_data_points, vehicle_state,
343 &lane_obstacles_num);
344 // adjust plan start point
345 if (std::fabs(nudge_distance) > KNudgeEpsilon) {
346 ADEBUG << "need latteral nudge distance : " << nudge_distance;
347 nudge_position_y = nudge_distance;
348 last_lane_id_to_nudge_flag_[cur_reference_line_lane_id_] = true;
349 } else {
350 // no nudge distance but current lane has obstacles ,keepping path in
351 // the last nudge path direction
352 bool last_plan_has_nudge = false;
353 if (last_lane_id_to_nudge_flag_.find(cur_reference_line_lane_id_) !=
354 last_lane_id_to_nudge_flag_.end()) {
355 last_plan_has_nudge =
356 last_lane_id_to_nudge_flag_[cur_reference_line_lane_id_];
357 }
358
359 if (last_plan_has_nudge && lane_obstacles_num != 0) {
360 ADEBUG << "Keepping last nudge path direction";
361 nudge_position_y = vehicle_state_.y();
362 } else {
363 // not need nudge or not need nudge keepping
364 last_lane_id_to_nudge_flag_[cur_reference_line_lane_id_] = false;
365 nudge_position_y = path_data_points[0].y();
366 }
367 }
368
369 return nudge_position_y;
370}
371
372double NaviPathDecider::CalculateDistanceToDestLane() {
373 // match an appropriate lateral shift param from the configuration file
374 // based on the current state of the vehicle state
375 double move_distance = 0.0;
376 double max_adc_speed =
377 start_plan_v_ + start_plan_a_ * 1.0 / FLAGS_planning_loop_rate;
378 auto max_speed_level_itr = std::upper_bound(
379 max_speed_levels_.begin(), max_speed_levels_.end(), max_adc_speed);
380 if (max_speed_level_itr != max_speed_levels_.end()) {
381 auto max_speed_level = *max_speed_level_itr;
382 move_distance = move_dest_lane_config_talbe_[max_speed_level];
383 }
384
385 return move_distance;
386}
387
388} // namespace planning
389} // 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
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
Rectangular (undirected) bounding box in 2-D.
Definition box2d.h:52
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
const std::string & Id() const
Frame holds all data for one planning cycle.
Definition frame.h:62
const std::vector< const Obstacle * > obstacles() const
Definition frame.cc:577
const common::VehicleState & vehicle_state() const
Definition frame.cc:83
const common::TrajectoryPoint & PlanningStartPoint() const
Definition frame.cc:79
bool Init(const PlannerNaviConfig &config) override
Initialization parameters
double GetNudgeDistance(const std::vector< const Obstacle * > &obstacles, const ReferenceLine &reference_line, const PathDecision &path_decision, const std::vector< common::PathPoint > &path_data_points, const common::VehicleState &vehicle_state, int *lane_obstacles_num)
get the actual nudgable distance according to the position of the obstacle
bool Init(const PlannerNaviConfig &config) override
apollo::common::Status Execute(Frame *frame, ReferenceLineInfo *reference_line_info) override
Overrided implementation of the virtual function "Execute" in the base class "Task".
virtual const std::string & Name() const
Definition navi_task.cc:32
virtual apollo::common::Status Execute(Frame *frame, ReferenceLineInfo *reference_line_info)
Definition navi_task.cc:36
ReferenceLineInfo * reference_line_info_
Definition navi_task.h:48
void SetReferenceLine(const ReferenceLine *reference_line)
Definition path_data.cc:107
bool SetDiscretizedPath(DiscretizedPath path)
Definition path_data.cc:43
PathDecision represents all obstacle decisions on one path.
ReferenceLineInfo holds all data for one reference line.
void SetDrivable(bool drivable)
Set if the vehicle can drive following this reference line A planner need to set this value to true i...
const hdmap::RouteSegments & Lanes() const
const ReferenceLine & reference_line() const
planning_internal::Debug * mutable_debug()
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
This file provides the declaration of the class "NaviPathDecider".
optional VehicleParam vehicle_param
optional MoveDestLaneConfigTable move_dest_lane_config_talbe
optional NaviPathDeciderConfig navi_path_decider_config
Defines the Vec2d class.