Apollo  6.0
Open source self driving car software
hermite_spline.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 <array>
24 #include <utility>
25 
26 #include "cyber/common/log.h"
27 
28 namespace apollo {
29 namespace common {
30 namespace math {
31 
32 // Hermite spline implementation that works for 1d and 2d space interpolation.
33 // Valid input type T: double, Eigen::Vector2d
34 template <typename T, std::size_t N>
36  public:
37  HermiteSpline(std::array<T, (N + 1) / 2> x0, std::array<T, (N + 1) / 2> x1,
38  const double z0 = 0.0, const double z1 = 1.0);
39 
40  virtual ~HermiteSpline() = default;
41 
42  virtual T Evaluate(const std::uint32_t order, const double z) const;
43 
44  private:
45  std::array<T, (N + 1) / 2> x0_;
46 
47  std::array<T, (N + 1) / 2> x1_;
48 
49  double z0_ = 0.0;
50 
51  double delta_z_ = 0.0;
52 };
53 
54 template <typename T, std::size_t N>
55 inline HermiteSpline<T, N>::HermiteSpline(std::array<T, (N + 1) / 2> x0,
56  std::array<T, (N + 1) / 2> x1,
57  const double z0, const double z1)
58  : x0_(std::move(x0)), x1_(std::move(x1)), z0_(z0), delta_z_(z1 - z0) {
59  ACHECK(N == 3 || N == 5)
60  << "Error: currently we only support cubic and quintic hermite splines!";
61 }
62 
63 template <typename T, std::size_t N>
64 inline T HermiteSpline<T, N>::Evaluate(const std::uint32_t order,
65  const double z) const {
66  CHECK_LE(z0_, z);
67  CHECK_LE(z, z0_ + delta_z_);
68 
69  // if N == 3, cubic hermite spline, N == 5, quintic hermite spline
70  if (N == 3) {
71  const T& p0 = x0_[0];
72  const T& v0 = x0_[1];
73  const T& p1 = x1_[0];
74  const T& v1 = x1_[1];
75  switch (order) {
76  case 0: {
77  const double t = (z - z0_) / delta_z_;
78  const double t2 = t * t;
79  const double t3 = t2 * t;
80 
81  return (2.0 * t3 - 3.0 * t2 + 1.0) * p0 + (t3 - 2 * t2 + t) * v0 +
82  (-2.0 * t3 + 3.0 * t2) * p1 + (t3 - t2) * v1;
83  }
84  case 1: {
85  const double t = (z - z0_) / delta_z_;
86  const double t2 = t * t;
87 
88  return (6.0 * t2 - 6.0 * t) * p0 + (3.0 * t2 - 4 * t + 1.0) * v0 +
89  (-6.0 * t2 + 6.0 * t) * p1 + (3.0 * t2 - 2.0 * t) * v1;
90  }
91  case 2: {
92  const double t = (z - z0_) / delta_z_;
93  return (12.0 * t - 6.0) * p0 + (6.0 * t - 4.0) * v0 +
94  (-12.0 * t + 6.0) * p1 + (6.0 * t - 2.0) * v1;
95  }
96  case 3: {
97  return 12.0 * p0 + 6.0 * v0 - 12.0 * p1 + 6.0 * v1;
98  }
99  default: { break; }
100  }
101  } else {
102  CHECK_EQ(5, N);
103  const T& p0 = x0_[0];
104  const T& v0 = x0_[1];
105  const T& a0 = x0_[2];
106  const T& p1 = x1_[0];
107  const T& v1 = x1_[1];
108  const T& a1 = x1_[2];
109 
110  switch (order) {
111  case 0: {
112  const double t = (z - z0_) / delta_z_;
113  const double t2 = t * t;
114  const double t3 = t * t2;
115  const double t4 = t2 * t2;
116  const double t5 = t2 * t3;
117  const double det0 = t3 - t4;
118  const double det1 = t4 - t5;
119  const double h0 = 1.0 - 10.0 * t3 + 15.0 * t4 - 6.0 * t5;
120  const double h1 = t - 6.0 * t3 + 8.0 * t4 - 3.0 * t5;
121  const double h2 = 0.5 * (t2 - t5) - 1.5 * det0;
122  const double h3 = 10.0 * t3 - 15.0 * t4 + 6.0 * t5;
123  const double h4 = -4.0 * det0 + 3.0 * det1;
124  const double h5 = 0.5 * (det0 - det1);
125 
126  return h0 * p0 + h1 * v0 + h2 * a0 + h3 * p1 + h4 * v1 + h5 * a1;
127  }
128  case 1: {
129  const double t = (z - z0_) / delta_z_;
130  const double t2 = t * t;
131  const double t3 = t * t2;
132  const double t4 = t2 * t2;
133  const double det0 = t2 - t3;
134  const double det1 = t3 - t4;
135  const double dh0 = -30.0 * det0 + 30.0 * det1;
136  const double dh1 = 1 - 18.0 * t2 + 32.0 * t3 - 15.0 * t4;
137  const double dh2 = t - 4.5 * t2 + 6.0 * t3 - 2.5 * t4;
138  const double dh3 = 30.0 * det0 - 30.0 * det1;
139  const double dh4 = -12.0 * t2 + 28.0 * t3 - 15.0 * t4;
140  const double dh5 = 1.5 * det0 - 2.5 * det1;
141 
142  return dh0 * p0 + dh1 * v0 + dh2 * a0 + dh3 * p1 + dh4 * v1 + dh5 * a1;
143  }
144  case 2: {
145  const double t = (z - z0_) / delta_z_;
146  const double t2 = t * t;
147  const double t3 = t * t2;
148  const double det0 = t - t2;
149  const double det1 = t2 - t3;
150  const double ddh0 = -60.0 * det0 + 120.0 * det1;
151  const double ddh1 = -36.0 * det0 + 60.0 * det1;
152  const double ddh2 = 1.0 - 9.0 * t + 18.0 * t2 - 10.0 * t3;
153  const double ddh3 = 60.0 * det0 - 120.0 * det1;
154  const double ddh4 = -24.0 * det0 + 60.0 * det1;
155  const double ddh5 = 3.0 * t - 12.0 * t2 + 10.0 * t3;
156 
157  return ddh0 * p0 + ddh1 * v0 + ddh2 * a0 + ddh3 * p1 + ddh4 * v1 +
158  ddh5 * a1;
159  }
160  case 3: {
161  const double t = (z - z0_) / delta_z_;
162  const double t2 = t * t;
163  const double det = t - t2;
164  const double dddh0 = -60.0 + 360.0 * det;
165  const double dddh1 = -36.0 + 192.0 * t - 180.0 * t2;
166  const double dddh2 = -9.0 + 36.0 * t - 30.0 * t2;
167  const double dddh3 = 60.0 - 360.0 * det;
168  const double dddh4 = -24.0 + 168.0 * t - 180.0 * t2;
169  const double dddh5 = 3.0 - 24.0 * t + 30.0 * t2;
170 
171  return dddh0 * p0 + dddh1 * v0 + dddh2 * a0 + dddh3 * p1 + dddh4 * v1 +
172  dddh5 * a1;
173  }
174  case 4: {
175  const double t = (z - z0_) / delta_z_;
176  const double d4h0 = 360.0 - 720.0 * t;
177  const double d4h1 = 192.0 - 360.0 * t;
178  const double d4h2 = 36.0 - 60.0 * t;
179  const double d4h3 = -360.0 + 720.0 * t;
180  const double d4h4 = 168.0 - 360.0 * t;
181  const double d4h5 = -24.0 + 60.0 * t;
182 
183  return d4h0 * p0 + d4h1 * v0 + d4h2 * a0 + d4h3 * p1 + d4h4 * v1 +
184  d4h5 * a1;
185  }
186  case 5: {
187  const double d5h0 = -720.0;
188  const double d5h1 = -360.0;
189  const double d5h2 = -60.0;
190  const double d5h3 = 720.0;
191  const double d5h4 = -360.0;
192  const double d5h5 = 60.0;
193 
194  return d5h0 * p0 + d5h1 * v0 + d5h2 * a0 + d5h3 * p1 + d5h4 * v1 +
195  d5h5 * a1;
196  }
197  default: { break; }
198  }
199  }
200  return T();
201 }
202 
203 } // namespace math
204 } // namespace common
205 } // namespace apollo
#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
Definition: future.h:29
virtual T Evaluate(const std::uint32_t order, const double z) const
Definition: hermite_spline.h:64
HermiteSpline(std::array< T,(N+1)/2 > x0, std::array< T,(N+1)/2 > x1, const double z0=0.0, const double z1=1.0)
Definition: hermite_spline.h:55
Definition: hermite_spline.h:35