Apollo 11.0
自动驾驶开放平台
quintic_spiral_path_with_derivation.h
浏览该文件的文档.
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
21#pragma once
22
23#include <unordered_map>
24#include <utility>
25
26#include "cyber/common/log.h"
29
30namespace apollo {
31namespace planning {
32
33template <size_t N>
35 public:
37
38 QuinticSpiralPathWithDerivation(const std::array<double, 3>& start,
39 const std::array<double, 3>& end,
40 const double delta_s);
41
42 QuinticSpiralPathWithDerivation(const double theta0, const double kappa0,
43 const double dkappa0, const double theta1,
44 const double kappa1, const double dkappa1,
45 const double delta_s);
46
48
49 double evaluate(const size_t order, const size_t i, const size_t n);
50
51 double ComputeCartesianDeviationX() const { return dx_; }
52
53 double ComputeCartesianDeviationY() const { return dy_; }
54
55 std::pair<double, double> DeriveCartesianDeviation(const size_t param_index);
56
57 double DeriveKappaDerivative(const size_t param_index, const int i,
58 const int n);
59
60 double DeriveDKappaDerivative(const size_t param_index, const int i,
61 const int n);
62
63 static const size_t THETA0 = 0;
64 static const size_t KAPPA0 = 1;
65 static const size_t DKAPPA0 = 2;
66 static const size_t THETA1 = 3;
67 static const size_t KAPPA1 = 4;
68 static const size_t DKAPPA1 = 5;
69 static const size_t DELTA_S = 6;
70
71 static const size_t INDEX_MAX = 7;
72
73 double ComputeCartesianDeviationX(const double s) const {
74 auto cos_theta = [this](const double s) {
75 const auto a = Evaluate(0, s);
76 return std::cos(a);
77 };
78 return common::math::IntegrateByGaussLegendre<N>(cos_theta, 0.0, s);
79 }
80
81 double ComputeCartesianDeviationY(const double s) const {
82 auto sin_theta = [this](const double s) {
83 const auto a = Evaluate(0, s);
84 return std::sin(a);
85 };
86 return common::math::IntegrateByGaussLegendre<N>(sin_theta, 0.0, s);
87 }
88
89 private:
90 double DeriveCosTheta(const size_t param_index, const double r) const;
91
92 double DeriveSinTheta(const size_t param_index, const double r) const;
93
94 double DeriveThetaDerivative(const size_t param_index, const double r) const;
95
96 std::array<std::array<double, 7>, 6> coef_deriv_;
97
98 std::unordered_map<size_t, double> cache_evaluate_;
99
100 std::unordered_map<size_t, std::pair<double, double>> cache_cartesian_deriv_;
101
102 std::unordered_map<size_t, double> cache_kappa_deriv_;
103
104 std::unordered_map<size_t, double> cache_dkappa_deriv_;
105
106 double dx_ = 0.0;
107
108 double dy_ = 0.0;
109
110 std::array<double, N> gauss_points_;
111
112 std::array<double, N> gauss_point_weights_;
113};
114
115template <size_t N>
117 const double x0, const double dx0, const double ddx0, const double x1,
118 const double dx1, const double ddx1, const double s)
119 : QuinticPolynomialCurve1d(x0, dx0, ddx0, x1, dx1, ddx1, s) {
120 ACHECK(s > 0.0);
121
122 auto gauss_points = common::math::GetGaussLegendrePoints<N>();
123 gauss_points_ = gauss_points.first;
124 gauss_point_weights_ = gauss_points.second;
125
127
129
130 double s2 = s * s;
131 double s3 = s2 * s;
132 double s4 = s3 * s;
133 double s5 = s2 * s3;
134 double s6 = s3 * s3;
135
136 for (size_t i = 0; i < 6; ++i) {
137 for (size_t j = 0; j < 7; ++j) {
138 coef_deriv_[i][j] = 0.0;
139 }
140 }
141 // derive a
142 // double a = -6.0 * x0 / p5 - 3.0 * dx0 / p4 - 0.5 * ddx0 / p3 + 6.0 * x1 /
143 // p5 - 3.0 * dx1 / p4 + 0.5 * ddx1 / p3;
144 coef_deriv_[5][0] = -6.0 / s5;
145 coef_deriv_[5][1] = -3.0 / s4;
146 coef_deriv_[5][2] = -0.5 / s3;
147 coef_deriv_[5][3] = 6.0 / s5;
148 coef_deriv_[5][4] = -3.0 / s4;
149 coef_deriv_[5][5] = 0.5 / s3;
150 coef_deriv_[5][6] = 30.0 * x0 / s6 + 12.0 * dx0 / s5 + 1.5 * ddx0 / s4 -
151 30.0 * x1 / s6 + 12.0 * dx1 / s5 - 1.5 * ddx1 / s4;
152
153 // derive b
154 // double b = 15.0 * x0 / p4 + 8.0 * dx0 / p3 + 1.5 * ddx0 / p2 - 15.0 * x1 /
155 // p4 + 7.0 * dx1 / p3 - ddx1 / p2;
156 coef_deriv_[4][0] = 15.0 / s4;
157 coef_deriv_[4][1] = 8.0 / s3;
158 coef_deriv_[4][2] = 1.5 / s2;
159 coef_deriv_[4][3] = -15.0 / s4;
160 coef_deriv_[4][4] = 7.0 / s3;
161 coef_deriv_[4][5] = -1.0 / s2;
162 coef_deriv_[4][6] = -60.0 * x0 / s5 - 24.0 * dx0 / s4 - 3.0 * ddx0 / s3 +
163 60.0 * x1 / s5 - 21.0 * dx1 / s4 + 2.0 * ddx1 / s3;
164
165 // derive c
166 // double c = -10.0 * x0 / p3 - 6.0 * dx0 / p2 - 1.5 * ddx0 / p + 10.0 * x1 /
167 // p3 - 4.0 * dx1 / p2 + 0.5 * ddx1 / p;
168 coef_deriv_[3][0] = -10.0 / s3;
169 coef_deriv_[3][1] = -6.0 / s2;
170 coef_deriv_[3][2] = -1.5 / s;
171 coef_deriv_[3][3] = 10.0 / s3;
172 coef_deriv_[3][4] = -4.0 / s2;
173 coef_deriv_[3][5] = 0.5 / s;
174 coef_deriv_[3][6] = 30.0 * x0 / s4 + 12.0 * dx0 / s3 + 1.5 * ddx0 / s2 -
175 30.0 * x1 / s4 + 8.0 * dx1 / s3 - 0.5 * ddx1 / s2;
176
177 // derive d
178 // double d = 0.5 * ddx0;
179 coef_deriv_[2][2] = 0.5;
180
181 // derive e
182 // double e = dx0;
183 coef_deriv_[1][1] = 1.0;
184
185 // derive f
186 // double f = x0;
187 coef_deriv_[0][0] = 1.0;
188}
189
190template <size_t N>
192 const std::array<double, 3>& start, const std::array<double, 3>& end,
193 const double delta_s)
194 : QuinticSpiralPathWithDerivation<N>(start[0], start[1], start[2], end[0],
195 end[1], end[2], delta_s) {}
196
197template <size_t N>
199 const size_t i,
200 const size_t n) {
201 auto key = order * 100 + n * 10 + i;
202 if (cache_evaluate_.find(key) != cache_evaluate_.end()) {
203 return cache_evaluate_[key];
204 }
205 auto res =
206 Evaluate(order, static_cast<double>(i) / static_cast<double>(n) * param_);
207 cache_evaluate_[key] = res;
208 return res;
209}
210
211template <size_t N>
212std::pair<double, double>
214 const size_t param_index) {
215 if (cache_cartesian_deriv_.find(param_index) !=
216 cache_cartesian_deriv_.end()) {
217 return cache_cartesian_deriv_[param_index];
218 }
219
220 const auto& g = gauss_points_;
221 const auto& w = gauss_point_weights_;
222
223 std::pair<double, double> cartesian_deviation = {0.0, 0.0};
224 if (param_index != DELTA_S) {
225 for (size_t i = 0; i < N; ++i) {
226 double r = 0.5 * g[i] + 0.5;
227 cartesian_deviation.first += w[i] * DeriveCosTheta(param_index, r);
228 cartesian_deviation.second += w[i] * DeriveSinTheta(param_index, r);
229 }
230
231 cartesian_deviation.first *= param_ * 0.5;
232 cartesian_deviation.second *= param_ * 0.5;
233 } else {
234 for (size_t i = 0; i < N; ++i) {
235 double r = 0.5 * g[i] + 0.5;
236 cartesian_deviation.first += w[i] * DeriveCosTheta(param_index, r);
237 cartesian_deviation.second += w[i] * DeriveSinTheta(param_index, r);
238 }
239
240 cartesian_deviation.first *= param_ * 0.5;
241 cartesian_deviation.second *= param_ * 0.5;
242
243 for (size_t i = 0; i < N; ++i) {
244 double r = 0.5 * g[i] + 0.5;
245 auto theta = Evaluate(0, r * param_);
246
247 cartesian_deviation.first += 0.5 * w[i] * std::cos(theta);
248 cartesian_deviation.second += 0.5 * w[i] * std::sin(theta);
249 }
250 }
251 cache_cartesian_deriv_[param_index] = cartesian_deviation;
252 return cartesian_deviation;
253}
254
255template <size_t N>
257 const size_t param_index, const int i, const int n) {
258 auto key = param_index * INDEX_MAX + i;
259 if (cache_kappa_deriv_.find(key) != cache_kappa_deriv_.end()) {
260 return cache_kappa_deriv_[key];
261 }
262
263 auto r = static_cast<double>(i) / static_cast<double>(n);
264 double s = param_ * r;
265 double s2 = s * s;
266 double s3 = s2 * s;
267 double s4 = s2 * s2;
268
269 double derivative = 5.0 * coef_deriv_[5][param_index] * s4 +
270 4.0 * coef_deriv_[4][param_index] * s3 +
271 3.0 * coef_deriv_[3][param_index] * s2 +
272 2.0 * coef_deriv_[2][param_index] * s +
273 coef_deriv_[1][param_index];
274
275 if (param_index == DELTA_S) {
276 derivative += 20.0 * coef_[5] * s3 * r + 12.0 * coef_[4] * s2 * r +
277 6.0 * coef_[3] * s * r + 2.0 * coef_[2] * r;
278 }
279
280 cache_kappa_deriv_[key] = derivative;
281 return derivative;
282}
283
284template <size_t N>
286 const size_t param_index, const int i, const int n) {
287 auto key = param_index * INDEX_MAX + i;
288 if (cache_dkappa_deriv_.find(key) != cache_dkappa_deriv_.end()) {
289 return cache_dkappa_deriv_[key];
290 }
291
292 auto r = static_cast<double>(i) / static_cast<double>(n);
293 double s = param_ * r;
294 double s2 = s * s;
295 double s3 = s2 * s;
296
297 double derivative = 20.0 * coef_deriv_[5][param_index] * s3 +
298 12.0 * coef_deriv_[4][param_index] * s2 +
299 6.0 * coef_deriv_[3][param_index] * s +
300 2.0 * coef_deriv_[2][param_index];
301
302 if (param_index == DELTA_S) {
303 derivative +=
304 60.0 * coef_[5] * s2 * r + 24.0 * coef_[4] * s * r + 6.0 * coef_[3] * r;
305 }
306
307 cache_dkappa_deriv_[key] = derivative;
308 return derivative;
309}
310
311template <size_t N>
313 const size_t param_index, const double r) const {
314 double s = param_ * r;
315 double s2 = s * s;
316 double s3 = s2 * s;
317 double s4 = s2 * s2;
318 double s5 = s3 * s2;
319
320 double derivative =
321 coef_deriv_[5][param_index] * s5 + coef_deriv_[4][param_index] * s4 +
322 coef_deriv_[3][param_index] * s3 + coef_deriv_[2][param_index] * s2 +
323 coef_deriv_[1][param_index] * s + coef_deriv_[0][param_index];
324
325 if (param_index == DELTA_S) {
326 derivative += coef_[5] * 5.0 * s4 * r + coef_[4] * 4.0 * s3 * r +
327 coef_[3] * 3.0 * s2 * r + coef_[2] * 2.0 * s * r +
328 coef_[1] * r;
329 }
330 return derivative;
331}
332
333template <size_t N>
334double QuinticSpiralPathWithDerivation<N>::DeriveCosTheta(
335 const size_t param_index, const double r) const {
336 double g = param_ * r;
337 double theta = Evaluate(0, g);
338
339 double derivative = -std::sin(theta) * DeriveThetaDerivative(param_index, r);
340 return derivative;
341}
342
343template <size_t N>
344double QuinticSpiralPathWithDerivation<N>::DeriveSinTheta(
345 const size_t param_index, const double r) const {
346 double g = param_ * r;
347 double theta = Evaluate(0, g);
348
349 double derivative = std::cos(theta) * DeriveThetaDerivative(param_index, r);
350 return derivative;
351}
352
353} // namespace planning
354} // namespace apollo
double Evaluate(const std::uint32_t order, const double p) const override
double DeriveKappaDerivative(const size_t param_index, const int i, const int n)
double DeriveDKappaDerivative(const size_t param_index, const int i, const int n)
double evaluate(const size_t order, const size_t i, const size_t n)
std::pair< double, double > DeriveCartesianDeviation(const size_t param_index)
Planning module main class.
Functions to compute integral.
#define ACHECK(cond)
Definition log.h:80
class register implement
Definition arena_queue.h:37