Apollo 11.0
自动驾驶开放平台
navi_speed_ts_graph.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
26#include "cyber/common/log.h"
28
29namespace apollo {
30namespace planning {
31
35
36namespace {
37constexpr double kDoubleEpsilon = 1.0e-6;
38constexpr double kDefaultSStep = 1.0;
39constexpr double kDefaultSMax = 2.0;
40constexpr double kDefaultSafeDistanceRatio = 1.0;
41constexpr double kDefaultSafeDistanceBase = 2.0;
42constexpr double kSafeDistanceSmooth = 3.0;
43constexpr double kFollowSpeedSmooth = 0.25;
44constexpr double kInfinityValue = 1.0e8;
45} // namespace
46
47static void CheckConstraints(const NaviSpeedTsConstraints& constraints) {
48 CHECK_GE(constraints.t_min, 0.0);
49 CHECK_GE(constraints.v_max, 0.0);
50 CHECK_GE(constraints.v_max, constraints.v_preffered);
51 CHECK_GE(constraints.a_max, 0.0);
52 CHECK_GE(constraints.a_max, constraints.a_preffered);
53 CHECK_GE(constraints.b_max, 0.0);
54 CHECK_GE(constraints.b_max, constraints.b_preffered);
55 CHECK_GE(constraints.da_max, 0.0);
56 CHECK_GE(constraints.da_max, constraints.da_preffered);
57}
58
59static void CombineConstraints(const NaviSpeedTsConstraints& constraints,
60 NaviSpeedTsConstraints* dst) {
61 dst->t_min = std::max(constraints.t_min, dst->t_min);
62 dst->v_max = std::min(constraints.v_max, dst->v_max);
63 dst->v_preffered = std::min(constraints.v_preffered, dst->v_preffered);
64 dst->a_max = std::min(constraints.a_max, dst->a_max);
65 dst->a_preffered = std::min(constraints.a_preffered, dst->a_preffered);
66 dst->b_max = std::min(constraints.b_max, dst->b_max);
67 dst->b_preffered = std::min(constraints.b_preffered, dst->b_preffered);
68 dst->da_max = std::min(constraints.da_max, dst->da_max);
69 dst->da_preffered = std::min(constraints.da_preffered, dst->da_preffered);
70}
71
73 Reset(kDefaultSStep, kDefaultSMax, 0.0, 0.0, 0.0);
74}
75
76void NaviSpeedTsGraph::Reset(double s_step, double s_max, double start_v,
77 double start_a, double start_da) {
78 CHECK_GT(s_step, 0.0);
79 CHECK_GE(s_max, s_step);
80 CHECK_GE(start_v, 0.0);
81
82 s_step_ = s_step;
83 start_v_ = start_v;
84 start_a_ = start_a;
85 start_da_ = start_da;
86
87 auto point_num = (size_t)((s_max + s_step_) / s_step_);
88 constraints_.clear();
89 constraints_.resize(point_num);
90}
91
93 const NaviSpeedTsConstraints& constraints) {
94 CheckConstraints(constraints);
95
96 for (auto& pc : constraints_) {
97 CombineConstraints(constraints, &pc);
98 }
99}
100
102 double start_s, double end_s, const NaviSpeedTsConstraints& constraints) {
103 CHECK_GE(start_s, 0.0);
104 CHECK_GE(end_s, start_s);
105 CheckConstraints(constraints);
106
107 auto start_idx = (size_t)(std::floor(start_s / s_step_));
108 auto end_idx = (size_t)(std::ceil(end_s / s_step_));
109 if (start_idx == end_idx) {
110 CombineConstraints(constraints, &constraints_[start_idx]);
111 } else {
112 for (size_t i = start_idx; i < end_idx && i < constraints_.size(); i++)
113 CombineConstraints(constraints, &constraints_[i]);
114 }
115}
116
118 double safe_distance,
119 double following_accel_ratio,
120 double v,
121 double cruise_speed) {
122 CHECK_GE(distance, 0.0);
123 CHECK_GE(safe_distance, 0.0);
124 CHECK_GT(following_accel_ratio, 0.0);
125
126 // smooth obstacle following
127 if (distance > safe_distance &&
128 distance - safe_distance < kSafeDistanceSmooth &&
129 std::abs(v - start_v_) < kFollowSpeedSmooth) {
130 distance = safe_distance;
131 v = start_v_;
132 }
133
134 // TODO(all): if v < 0
135 v = std::max(v, 0.0);
136
137 // update t_min
138 double s = 0.0;
139 for (auto& pc : constraints_) {
140 auto t = (s - distance) / v;
141 if (t >= 0.0) {
142 NaviSpeedTsConstraints constraints;
143 constraints.t_min = t;
144 CombineConstraints(constraints, &pc);
145 }
146 s += s_step_;
147 }
148
149 // update v_preffered
150 auto od = distance - safe_distance;
151 auto v0 = start_v_;
152 auto v1 = v;
153 auto r0 = (distance - safe_distance) / (distance + safe_distance);
154 auto vm = std::max(cruise_speed * r0, 0.0) +
155 (1.0 + following_accel_ratio * r0) * v1;
156 auto ra = (v1 - vm) * (v1 - vm) * (v1 + v0 - 2.0 * vm) / (od * od);
157 auto rb = (v1 - vm) * (v1 + 2.0 * v0 - 3.0 * vm) / od;
158 auto rc = v0;
159 auto t1 = -1.0 * od / (v1 - vm);
160 auto s1 = ra * t1 * t1 * t1 + rb * t1 * t1 + rc * t1;
161
162 double t;
163 double prev_v;
164 bool first = true;
165 for (auto& pc : constraints_) {
166 NaviSpeedTsConstraints constraints;
167
168 if (first) {
169 first = false;
170 auto cur_v = rc;
171 t = 0.0;
172 s = 0.0;
173 prev_v = cur_v;
174 constraints.v_preffered = cur_v;
175 } else if (s <= s1 && t <= t1) {
176 auto a = 6.0 * ra * t + 2.0 * rb;
177 t += (std::sqrt(prev_v * prev_v + 2.0 * a * s_step_) - prev_v) / a;
178 auto cur_v = 3.0 * ra * t * t + 2.0 * rb * t + rc;
179 s += s_step_;
180 prev_v = cur_v;
181 constraints.v_preffered = std::max(cur_v, 0.0);
182 } else {
183 auto cur_v = v;
184 t += 2.0 * s_step_ / (prev_v + cur_v);
185 s += s_step_;
186 prev_v = cur_v;
187 constraints.v_preffered = cur_v;
188 }
189
190 CombineConstraints(constraints, &pc);
191 }
192}
193
194Status NaviSpeedTsGraph::Solve(std::vector<NaviSpeedTsPoint>* output) {
195 CHECK_NOTNULL(output);
196
197 // make constraints of the first point
198 auto& constraints = constraints_[0];
199 constraints.v_max = start_v_;
200 constraints.v_preffered = start_v_;
201 constraints.a_max = start_a_;
202 constraints.a_preffered = start_a_;
203 constraints.da_max = start_da_;
204 constraints.da_preffered = start_da_;
205
206 // preprocess v_max base on b_max
207 for (ssize_t i = constraints_.size() - 2; i >= 0; i--) {
208 const auto& next = constraints_[i + 1];
209 auto& cur = constraints_[i];
210 cur.v_max =
211 std::min(std::sqrt(next.v_max * next.v_max + 2 * next.b_max * s_step_),
212 cur.v_max);
213 cur.v_preffered = std::min(cur.v_max, cur.v_preffered);
214 }
215
216 // preprocess v_max base on a_max
217 for (size_t i = 1; i < constraints_.size(); i++) {
218 const auto& prev = constraints_[i - 1];
219 auto& cur = constraints_[i];
220 cur.v_max =
221 std::min(std::sqrt(prev.v_max * prev.v_max + 2 * cur.a_max * s_step_),
222 cur.v_max);
223 cur.v_preffered = std::min(cur.v_max, cur.v_preffered);
224 }
225
226 // preprocess v_preffered base on b_preffered
227 for (ssize_t i = constraints_.size() - 2; i >= 0; i--) {
228 const auto& next = constraints_[i + 1];
229 auto& cur = constraints_[i];
230 cur.v_preffered = std::min(std::sqrt(next.v_preffered * next.v_preffered +
231 2 * next.b_preffered * s_step_),
232 cur.v_preffered);
233 }
234
235 // preprocess v_preffered base on a_preffered
236 for (size_t i = 1; i < constraints_.size(); i++) {
237 const auto& prev = constraints_[i - 1];
238 auto& cur = constraints_[i];
239 cur.v_preffered = std::min(std::sqrt(prev.v_preffered * prev.v_preffered +
240 2 * cur.a_preffered * s_step_),
241 cur.v_preffered);
242 }
243
244 auto& points = *output;
245 points.resize(constraints_.size());
246
247 // compute the first point
248 auto& point = points[0];
249 point.s = 0.0;
250 point.t = 0.0;
251 point.v = start_v_;
252 point.a = start_a_;
253 point.da = start_da_;
254
255 // compute the remaining points
256 for (size_t i = 1; i < points.size(); i++) {
257 const auto& prev = points[i - 1];
258 const auto& constraints = constraints_[i];
259 auto& cur = points[i];
260
261 // compute t_min base on v_max
262 auto t_min = std::max(prev.t, constraints.t_min);
263 auto v_max = constraints.v_max;
264 t_min = std::max(prev.t + 2.0 * s_step_ / (prev.v + v_max), t_min);
265
266 // compute t_max base on b_max
267 auto t_max = std::numeric_limits<double>::infinity();
268 auto b_max = constraints.b_max;
269 auto r0 = prev.v * prev.v - 2 * b_max * s_step_;
270 if (r0 > 0.0) {
271 t_max = prev.t + (prev.v - std::sqrt(r0)) / b_max;
272 }
273 // if t_max < t_min
274 if (t_max < t_min) {
275 AERROR << "failure to satisfy the constraints.";
276 return Status(ErrorCode::PLANNING_ERROR,
277 "failure to satisfy the constraints.");
278 }
279
280 // compute t_preffered base on v_preffered
281 auto v_preffered = constraints.v_preffered;
282 auto t_preffered = prev.t + 2 * s_step_ / (prev.v + v_preffered);
283
284 cur.s = prev.s + s_step_;
285 cur.t = Clamp(t_preffered, t_min, t_max);
286 auto dt = cur.t - prev.t;
287 cur.v = std::max(2.0 * s_step_ / dt - prev.v, 0.0);
288
289 // if t is infinity
290 if (std::isinf(cur.t)) {
291 points.resize(i + 1);
292 break;
293 }
294 }
295
296 for (size_t i = 1; i < points.size() - 1; i++) {
297 const auto& prev = points[i - 1];
298 const auto& next = points[i + 1];
299 auto& cur = points[i];
300 auto ds = next.s - prev.s;
301 auto dt = next.t - prev.t;
302 cur.v = ds / dt;
303 }
304
305 auto& first = points[0];
306 const auto& second = points[1];
307 first.a = (second.v - first.v) / (2.0 * (second.t - first.t));
308
309 for (size_t i = 1; i < points.size() - 1; i++) {
310 const auto& prev = points[i - 1];
311 const auto& next = points[i + 1];
312 auto& cur = points[i];
313 auto dv = next.v - prev.v;
314 auto dt = next.t - prev.t;
315 cur.a = dv / dt;
316 }
317
318 for (size_t i = 1; i < points.size() - 1; i++) {
319 const auto& prev = points[i - 1];
320 const auto& next = points[i + 1];
321 auto& cur = points[i];
322 auto da = next.a - prev.a;
323 auto dt = next.t - prev.t;
324 cur.da = da / dt;
325 }
326
327 for (size_t i = 0; i < points.size(); i++) {
328 auto& point = points[i];
329 point.s = std::min(kInfinityValue, point.s);
330 point.t = std::min(kInfinityValue, point.t);
331 point.v = std::min(kInfinityValue, point.v);
332 point.a = std::min(kInfinityValue, point.a);
333 point.da = std::min(kInfinityValue, point.da);
334
335 if (std::abs(point.t - kInfinityValue) < kDoubleEpsilon)
336 points.resize(i + 1);
337 }
338
339 return Status::OK();
340}
341
342} // namespace planning
343} // 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
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.
Planning module main class.
Math-related util functions.
#define AERROR
Definition log.h:44
T Clamp(const T value, T bound1, T bound2)
Clamp a value between two bounds.
Definition math_utils.h:155
const double kDoubleEpsilon
class register implement
Definition arena_queue.h:37
This file provides the declaration of the class "NaviSpeedTsGraph".
NaviSpeedTsConstraints is used to describe constraints of a t-s point.