Apollo  6.0
Open source self driving car software
quintic_spiral_path_with_derivation.h
Go to the documentation of this file.
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 
30 namespace apollo {
31 namespace planning {
32 
33 template <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 
47  virtual ~QuinticSpiralPathWithDerivation() = default;
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 
115 template <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 
190 template <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 
197 template <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 
211 template <size_t N>
212 std::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 
255 template <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 
284 template <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 
311 template <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 
333 template <size_t N>
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 
343 template <size_t N>
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 ComputeCartesianDeviationY() const
Definition: quintic_spiral_path_with_derivation.h:53
std::pair< double, double > DeriveCartesianDeviation(const size_t param_index)
Definition: quintic_spiral_path_with_derivation.h:213
static const size_t DKAPPA1
Definition: quintic_spiral_path_with_derivation.h:68
float sin(Angle16 a)
static const size_t KAPPA0
Definition: quintic_spiral_path_with_derivation.h:64
static const size_t DELTA_S
Definition: quintic_spiral_path_with_derivation.h:69
#define ACHECK(cond)
Definition: log.h:80
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
std::array< double, 6 > coef_
Definition: quintic_polynomial_curve1d.h:71
Planning module main class. It processes GPS and IMU as input, to generate planning info...
double Evaluate(const std::uint32_t order, const double p) const override
Definition: quintic_polynomial_curve1d.h:33
double param_
Definition: polynomial_curve1d.h:37
static const size_t DKAPPA0
Definition: quintic_spiral_path_with_derivation.h:65
double evaluate(const size_t order, const size_t i, const size_t n)
Definition: quintic_spiral_path_with_derivation.h:198
double ComputeCartesianDeviationY(const double s) const
Definition: quintic_spiral_path_with_derivation.h:81
Definition: quintic_spiral_path_with_derivation.h:34
float cos(Angle16 a)
Functions to compute integral.
double DeriveDKappaDerivative(const size_t param_index, const int i, const int n)
Definition: quintic_spiral_path_with_derivation.h:285
double ComputeCartesianDeviationX(const double s) const
Definition: quintic_spiral_path_with_derivation.h:73
double ComputeCartesianDeviationX() const
Definition: quintic_spiral_path_with_derivation.h:51
static const size_t THETA1
Definition: quintic_spiral_path_with_derivation.h:66
static const size_t INDEX_MAX
Definition: quintic_spiral_path_with_derivation.h:71
double DeriveKappaDerivative(const size_t param_index, const int i, const int n)
Definition: quintic_spiral_path_with_derivation.h:256
static const size_t KAPPA1
Definition: quintic_spiral_path_with_derivation.h:67
static const size_t THETA0
Definition: quintic_spiral_path_with_derivation.h:63