Apollo 11.0
自动驾驶开放平台
navi_speed_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 <limits>
26
27#include "cyber/common/log.h"
31
32namespace apollo {
33namespace planning {
34
40
41namespace {
42constexpr double kTsGraphSStep = 0.4;
43constexpr size_t kFallbackSpeedPointNum = 4;
44constexpr double kSpeedPointSLimit = 200.0;
45constexpr double kSpeedPointTimeLimit = 50.0;
46constexpr double kZeroSpeedEpsilon = 1.0e-3;
47constexpr double kZeroAccelEpsilon = 1.0e-3;
48constexpr double kDecelCompensationLimit = 2.0;
49constexpr double kKappaAdjustRatio = 20.0;
50} // namespace
51
53
55 CHECK_GT(FLAGS_planning_upper_speed_limit, 0.0);
56 ACHECK(config.has_navi_speed_decider_config());
57 ACHECK(config.navi_speed_decider_config().has_preferred_accel());
58 ACHECK(config.navi_speed_decider_config().has_preferred_decel());
59 ACHECK(config.navi_speed_decider_config().has_max_accel());
60 ACHECK(config.navi_speed_decider_config().has_max_decel());
61 ACHECK(config.navi_speed_decider_config().has_preferred_jerk());
62 ACHECK(config.navi_speed_decider_config().has_obstacle_buffer());
63 ACHECK(config.navi_speed_decider_config().has_safe_distance_base());
64 ACHECK(config.navi_speed_decider_config().has_safe_distance_ratio());
65 ACHECK(config.navi_speed_decider_config().has_following_accel_ratio());
66 ACHECK(config.navi_speed_decider_config().has_soft_centric_accel_limit());
67 ACHECK(config.navi_speed_decider_config().has_hard_centric_accel_limit());
68 ACHECK(config.navi_speed_decider_config().has_hard_speed_limit());
69 ACHECK(config.navi_speed_decider_config().has_hard_accel_limit());
70 ACHECK(config.navi_speed_decider_config().has_enable_safe_path());
71 ACHECK(config.navi_speed_decider_config().has_enable_planning_start_point());
72 ACHECK(
73 config.navi_speed_decider_config().has_enable_accel_auto_compensation());
74 ACHECK(config.navi_speed_decider_config().has_kappa_preview());
75 ACHECK(config.navi_speed_decider_config().has_kappa_threshold());
76
77 max_speed_ = FLAGS_planning_upper_speed_limit;
78 preferred_accel_ =
79 std::abs(config.navi_speed_decider_config().preferred_accel());
80 preferred_decel_ =
81 std::abs(config.navi_speed_decider_config().preferred_decel());
82 preferred_jerk_ =
83 std::abs(config.navi_speed_decider_config().preferred_jerk());
84 max_accel_ = std::abs(config.navi_speed_decider_config().max_accel());
85 max_decel_ = std::abs(config.navi_speed_decider_config().max_decel());
86 preferred_accel_ = std::min(max_accel_, preferred_accel_);
87 preferred_decel_ = std::min(max_decel_, preferred_accel_);
88
89 obstacle_buffer_ =
90 std::abs(config.navi_speed_decider_config().obstacle_buffer());
91 safe_distance_base_ =
93 safe_distance_ratio_ =
95 following_accel_ratio_ =
97 soft_centric_accel_limit_ =
99 hard_centric_accel_limit_ =
101 soft_centric_accel_limit_ =
102 std::min(hard_centric_accel_limit_, soft_centric_accel_limit_);
103 hard_speed_limit_ =
104 std::abs(config.navi_speed_decider_config().hard_speed_limit());
105 hard_accel_limit_ =
106 std::abs(config.navi_speed_decider_config().hard_accel_limit());
107 enable_safe_path_ = config.navi_speed_decider_config().enable_safe_path();
108 enable_planning_start_point_ =
110 enable_accel_auto_compensation_ =
112 kappa_preview_ = config.navi_speed_decider_config().kappa_preview();
113 kappa_threshold_ = config.navi_speed_decider_config().kappa_threshold();
114
115 return obstacle_decider_.Init(config);
116}
117
119 ReferenceLineInfo* reference_line_info) {
120 NaviTask::Execute(frame, reference_line_info);
121
122 // get cruise speed
123 const auto& planning_target = reference_line_info_->planning_target();
124 preferred_speed_ = planning_target.has_cruise_speed()
125 ? std::abs(planning_target.cruise_speed())
126 : 0.0;
127 preferred_speed_ = std::min(max_speed_, preferred_speed_);
128
129 // expected status of vehicle
130 const auto& planning_start_point = frame->PlanningStartPoint();
131 auto expected_v =
132 planning_start_point.has_v() ? planning_start_point.v() : 0.0;
133 auto expected_a =
134 planning_start_point.has_a() ? planning_start_point.a() : 0.0;
135
136 // current status of vehicle
137 const auto& vehicle_state = frame->vehicle_state();
138 auto current_v = vehicle_state.has_linear_velocity()
139 ? vehicle_state.linear_velocity()
140 : 0.0;
141 auto current_a = vehicle_state.has_linear_acceleration()
142 ? vehicle_state.linear_acceleration()
143 : 0.0;
144
145 // get the start point
146 double start_v;
147 double start_a;
148 double start_da;
149
150 if (enable_planning_start_point_) {
151 start_v = std::max(0.0, expected_v);
152 start_a = expected_a;
153 start_da = 0.0;
154 } else {
155 start_v = std::max(0.0, current_v);
156 start_a = current_a;
157 start_da = 0.0;
158 }
159
160 // acceleration auto compensation
161 if (enable_accel_auto_compensation_) {
162 if (prev_v_ > 0.0 && current_v > 0.0 && prev_v_ > expected_v) {
163 auto raw_ratio = (prev_v_ - expected_v) / (prev_v_ - current_v);
164 raw_ratio = Clamp(raw_ratio, 0.0, kDecelCompensationLimit);
165 decel_compensation_ratio_ = (decel_compensation_ratio_ + raw_ratio) / 2.0;
166 decel_compensation_ratio_ =
167 Clamp(decel_compensation_ratio_, 1.0, kDecelCompensationLimit);
168 ADEBUG << "change decel_compensation_ratio: " << decel_compensation_ratio_
169 << " raw: " << raw_ratio;
170 }
171 prev_v_ = current_v;
172 }
173
174 // get the path
175 auto& discretized_path = reference_line_info_->path_data().discretized_path();
176
177 auto ret = MakeSpeedDecision(
178 start_v, start_a, start_da, discretized_path, frame_->obstacles(),
179 [&](const std::string& id) { return frame_->Find(id); },
181 RecordDebugInfo(reference_line_info->speed_data());
182 if (ret != Status::OK()) {
183 reference_line_info->SetDrivable(false);
184 AERROR << "Reference Line " << reference_line_info->Lanes().Id()
185 << " is not drivable after " << Name();
186 }
187
188 return ret;
189}
190
191Status NaviSpeedDecider::MakeSpeedDecision(
192 double start_v, double start_a, double start_da,
193 const std::vector<PathPoint>& path_points,
194 const std::vector<const Obstacle*>& obstacles,
195 const std::function<const Obstacle*(const std::string&)>& find_obstacle,
196 SpeedData* const speed_data) {
197 CHECK_NOTNULL(speed_data);
198 CHECK_GE(path_points.size(), 2U);
199
200 auto start_s = path_points.front().has_s() ? path_points.front().s() : 0.0;
201 auto end_s = path_points.back().has_s() ? path_points.back().s() : start_s;
202 auto planning_length = end_s - start_s;
203
204 ADEBUG << "start to make speed decision, start_v: " << start_v
205 << " start_a: " << start_a << " start_da: " << start_da
206 << " start_s: " << start_s << " planning_length: " << planning_length;
207
208 if (start_v > max_speed_) {
209 const std::string msg = "exceeding maximum allowable speed.";
210 AERROR << msg;
211 return Status(ErrorCode::PLANNING_ERROR, msg);
212 }
213 start_v = std::max(0.0, start_v);
214
215 auto s_step = planning_length > kTsGraphSStep
216 ? kTsGraphSStep
217 : planning_length / kFallbackSpeedPointNum;
218
219 // init t-s graph
220 ts_graph_.Reset(s_step, planning_length, start_v, start_a, start_da);
221
222 // add t-s constraints
223 auto ret = AddPerceptionRangeConstraints();
224 if (ret != Status::OK()) {
225 AERROR << "Add t-s constraints base on range of perception failed";
226 return ret;
227 }
228
229 ret = AddObstaclesConstraints(start_v, planning_length, path_points,
230 obstacles, find_obstacle);
231 if (ret != Status::OK()) {
232 AERROR << "Add t-s constraints base on obstacles failed";
233 return ret;
234 }
235
236 ret = AddCentricAccelerationConstraints(path_points);
237 if (ret != Status::OK()) {
238 AERROR << "Add t-s constraints base on centric acceleration failed";
239 return ret;
240 }
241
242 ret = AddConfiguredConstraints();
243 if (ret != Status::OK()) {
244 AERROR << "Add t-s constraints base on configs failed";
245 return ret;
246 }
247
248 // create speed-points
249 std::vector<NaviSpeedTsPoint> ts_points;
250 if (ts_graph_.Solve(&ts_points) != Status::OK()) {
251 AERROR << "Solve speed points failed";
252 speed_data->clear();
253 speed_data->AppendSpeedPoint(0.0 + start_s, 0.0, 0.0, -max_decel_, 0.0);
254 speed_data->AppendSpeedPoint(0.0 + start_s, 1.0, 0.0, -max_decel_, 0.0);
255 return Status::OK();
256 }
257
258 speed_data->clear();
259 for (auto& ts_point : ts_points) {
260 if (ts_point.s > kSpeedPointSLimit || ts_point.t > kSpeedPointTimeLimit)
261 break;
262
263 if (ts_point.v > hard_speed_limit_) {
264 AERROR << "The v: " << ts_point.v << " of point with s: " << ts_point.s
265 << " and t: " << ts_point.t << "is greater than hard_speed_limit "
266 << hard_speed_limit_;
267 ts_point.v = hard_speed_limit_;
268 }
269
270 if (std::abs(ts_point.v) < kZeroSpeedEpsilon) {
271 ts_point.v = 0.0;
272 }
273 if (ts_point.a > hard_accel_limit_) {
274 AERROR << "The a: " << ts_point.a << " of point with s: " << ts_point.s
275 << " and t: " << ts_point.t << "is greater than hard_accel_limit "
276 << hard_accel_limit_;
277 ts_point.a = hard_accel_limit_;
278 }
279
280 if (std::abs(ts_point.a) < kZeroAccelEpsilon) {
281 ts_point.a = 0.0;
282 }
283 // apply acceleration adjust
284 if (enable_accel_auto_compensation_) {
285 if (ts_point.a > 0)
286 ts_point.a *= accel_compensation_ratio_;
287 else
288 ts_point.a *= decel_compensation_ratio_;
289 }
290
291 speed_data->AppendSpeedPoint(ts_point.s + start_s, ts_point.t, ts_point.v,
292 ts_point.a, ts_point.da);
293 }
294
295 if (speed_data->size() == 1) {
296 const auto& prev = speed_data->back();
297 speed_data->AppendSpeedPoint(prev.s(), prev.t() + 1.0, 0.0, 0.0, 0.0);
298 }
299
300 return Status::OK();
301}
302
303Status NaviSpeedDecider::AddPerceptionRangeConstraints() {
304 // TODO(all):
305 return Status::OK();
306}
307
308Status NaviSpeedDecider::AddObstaclesConstraints(
309 double vehicle_speed, double path_length,
310 const std::vector<PathPoint>& path_points,
311 const std::vector<const Obstacle*>& obstacles,
312 const std::function<const Obstacle*(const std::string&)>& find_obstacle) {
313 const auto& vehicle_config = VehicleConfigHelper::Instance()->GetConfig();
314 auto front_edge_to_center =
315 vehicle_config.vehicle_param().front_edge_to_center();
316 auto get_obstacle_distance = [&](double d) -> double {
317 return std::max(0.0, d - front_edge_to_center - obstacle_buffer_);
318 };
319 auto get_safe_distance = [&](double v) -> double {
320 return safe_distance_ratio_ * v + safe_distance_base_ +
321 front_edge_to_center + obstacle_buffer_;
322 };
323
324 // add obstacles from perception
325 obstacle_decider_.GetUnsafeObstaclesInfo(path_points, obstacles);
326 for (const auto& info : obstacle_decider_.UnsafeObstacles()) {
327 const auto& id = std::get<0>(info);
328 const auto* obstacle = find_obstacle(id);
329 if (obstacle != nullptr) {
330 auto s = std::get<1>(info);
331 auto obstacle_distance = get_obstacle_distance(s);
332 auto obstacle_speed = std::max(std::get<2>(info), 0.0);
333 auto safe_distance = get_safe_distance(obstacle_speed);
334 AINFO << "obstacle with id: " << id << " s: " << s
335 << " distance: " << obstacle_distance
336 << " speed: " << obstacle_speed
337 << " safe_distance: " << safe_distance;
338
339 ts_graph_.UpdateObstacleConstraints(obstacle_distance, safe_distance,
340 following_accel_ratio_,
341 obstacle_speed, preferred_speed_);
342 }
343 }
344
345 // the end of path just as an obstacle
346 if (enable_safe_path_) {
347 auto obstacle_distance = get_obstacle_distance(path_length);
348 auto safe_distance = get_safe_distance(0.0);
349 ts_graph_.UpdateObstacleConstraints(obstacle_distance, safe_distance,
350 following_accel_ratio_, 0.0,
351 preferred_speed_);
352 }
353
354 return Status::OK();
355}
356
358 // TODO(all):
359 return Status::OK();
360}
361
362Status NaviSpeedDecider::AddCentricAccelerationConstraints(
363 const std::vector<PathPoint>& path_points) {
364 if (path_points.size() < 2) {
365 const std::string msg = "Too few path points";
366 AERROR << msg;
367 return Status(ErrorCode::PLANNING_ERROR, msg);
368 }
369
370 double max_kappa = 0.0;
371 double max_kappa_v = std::numeric_limits<double>::max();
372 double preffered_kappa_v = std::numeric_limits<double>::max();
373 double max_kappa_s = 0.0;
374 const auto bs = path_points[0].has_s() ? path_points[0].s() : 0.0;
375
376 struct CLimit {
377 double s;
378 double v_max;
379 double v_preffered;
380 };
381 std::vector<CLimit> c_limits;
382 c_limits.resize(path_points.size() - 1);
383
384 for (size_t i = 1; i < path_points.size(); i++) {
385 const auto& prev = path_points[i - 1];
386 const auto& cur = path_points[i];
387 auto start_s = prev.has_s() ? prev.s() - bs : 0.0;
388 start_s = std::max(0.0, start_s);
389 auto end_s = cur.has_s() ? cur.s() - bs : 0.0;
390 end_s = std::max(0.0, end_s);
391 auto start_k = prev.has_kappa() ? prev.kappa() : 0.0;
392 auto end_k = cur.has_kappa() ? cur.kappa() : 0.0;
393 auto kappa = std::abs((start_k + end_k) / 2.0);
394 if (std::abs(kappa) < kappa_threshold_) {
395 kappa /= kKappaAdjustRatio;
396 }
397 auto v_preffered = std::min(std::sqrt(soft_centric_accel_limit_ / kappa),
398 std::numeric_limits<double>::max());
399 auto v_max = std::min(std::sqrt(hard_centric_accel_limit_ / kappa),
400 std::numeric_limits<double>::max());
401
402 c_limits[i - 1].s = end_s;
403 c_limits[i - 1].v_max = v_max;
404 c_limits[i - 1].v_preffered = v_preffered;
405
406 if (kappa > max_kappa) {
407 max_kappa = kappa;
408 max_kappa_v = v_max;
409 preffered_kappa_v = v_preffered;
410 max_kappa_s = start_s;
411 }
412 }
413
414 // kappa preview
415 for (size_t i = 0; i < c_limits.size(); i++) {
416 for (size_t j = i; j - i < (size_t)(kappa_preview_ / kTsGraphSStep) &&
417 j < c_limits.size();
418 j++)
419 c_limits[i].v_preffered =
420 std::min(c_limits[j].v_preffered, c_limits[i].v_preffered);
421 }
422
423 double start_s = 0.0;
424 for (size_t i = 0; i < c_limits.size(); i++) {
425 auto end_s = c_limits[i].s;
426 auto v_max = c_limits[i].v_max;
427 auto v_preffered = c_limits[i].v_preffered;
428
429 NaviSpeedTsConstraints constraints;
430 constraints.v_max = v_max;
431 constraints.v_preffered = v_preffered;
432 ts_graph_.UpdateRangeConstraints(start_s, end_s, constraints);
433
434 start_s = end_s;
435 }
436
437 AINFO << "add speed limit for centric acceleration with kappa: " << max_kappa
438 << " v_max: " << max_kappa_v << " v_preffered: " << preffered_kappa_v
439 << " s: " << max_kappa_s;
440
441 return Status::OK();
442}
443
444Status NaviSpeedDecider::AddConfiguredConstraints() {
445 NaviSpeedTsConstraints constraints;
446 constraints.v_max = max_speed_;
447 constraints.v_preffered = preferred_speed_;
448 constraints.a_max = max_accel_;
449 constraints.a_preffered = preferred_accel_;
450 constraints.b_max = max_decel_;
451 constraints.b_preffered = preferred_decel_;
452 constraints.da_preffered = preferred_jerk_;
453 ts_graph_.UpdateConstraints(constraints);
454
455 return Status::OK();
456}
457
458void NaviSpeedDecider::RecordDebugInfo(const SpeedData& speed_data) {
459 auto* debug = reference_line_info_->mutable_debug();
460 auto ptr_speed_plan = debug->mutable_planning_data()->add_speed_plan();
461 ptr_speed_plan->set_name(Name());
462 ptr_speed_plan->mutable_speed_point()->CopyFrom(
463 {speed_data.begin(), speed_data.end()});
464}
465
466} // namespace planning
467} // 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.
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
void GetUnsafeObstaclesInfo(const std::vector< common::PathPoint > &path_data_points, const std::vector< const Obstacle * > &obstacles)
get the unsafe obstacles between trajectory and reference line.
apollo::common::Status Execute(Frame *frame, ReferenceLineInfo *reference_line_info) override
Overrided implementation of the virtual function "Execute" in the base class "Task".
bool Init(const PlannerNaviConfig &config) override
void UpdateObstacleConstraints(double distance, double safe_distance, double following_accel_ratio, double v, double cruise_speed)
Assign constraints for an obstacle.
void Reset(double s_step, double s_max, double start_v, double start_a, double start_da)
Reset points's num and time step etc.
void UpdateRangeConstraints(double start_s, double end_s, const NaviSpeedTsConstraints &constraints)
Assign constraints to a range.
void UpdateConstraints(const NaviSpeedTsConstraints &constraints)
Assign constraints to all points.
apollo::common::Status Solve(std::vector< NaviSpeedTsPoint > *points)
Solving the t-s curve.
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
This is the class that associates an Obstacle with its path properties.
Definition obstacle.h:62
const DiscretizedPath & discretized_path() const
Definition path_data.cc:90
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 PlanningTarget & planning_target() const
const hdmap::RouteSegments & Lanes() const
planning_internal::Debug * mutable_debug()
void AppendSpeedPoint(const double s, const double time, const double v, const double a, const double da)
Definition speed_data.cc:48
Planning module main class.
Math-related util functions.
#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
T Clamp(const T value, T bound1, T bound2)
Clamp a value between two bounds.
Definition math_utils.h:155
Status AddTrafficDecisionConstraints()
class register implement
Definition arena_queue.h:37
This file provides the declaration of the class "NaviSpeedDecider".
optional NaviSpeedDeciderConfig navi_speed_decider_config