trajectory_collection
CubicHermiteSpline.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <Eigen/Core>
4 
5 #include <TrajColl/Func.h>
6 
7 namespace TrajColl
8 {
12 template<class T>
14 {
15 public:
20  CubicHermiteSpline(int dim, const std::map<double, std::pair<T, T>> & points = {}) : dim_(dim), points_(points) {}
21 
23  const std::map<double, std::pair<T, T>> & points() const noexcept
24  {
25  return points_;
26  }
27 
29  void clearPoints()
30  {
31  points_.clear();
32  }
33 
37  void appendPoint(const std::pair<double, std::pair<T, T>> & point)
38  {
39  points_.insert(point);
40  }
41 
46  void calcCoeff()
47  {
48  this->funcs_.clear();
49 
50  // Set piecewise CubicPolynomial
51  size_t n = points_.size();
52  if(n < 2)
53  {
54  throw std::runtime_error("[CubicHermiteSpline] Invalid points size: " + std::to_string(n));
55  }
56 
57  {
58  auto pointIt = points_.begin();
59  for(size_t k = 0; k < n - 1; k++, pointIt++)
60  {
61  const T & pk = pointIt->second.first;
62  const T & pk1 = std::next(pointIt)->second.first;
63  const T & vk = pointIt->second.second;
64  const T & vk1 = std::next(pointIt)->second.second;
65  double deltaT = std::next(pointIt)->first - pointIt->first;
66 
67  // clang-format off
68  std::array<T, 4> coeff = {
69  pk,
70  deltaT * vk,
71  -3 * pk - 2 * deltaT * vk + 3 * pk1 - deltaT * vk1,
72  2 * pk + deltaT * vk - 2 * pk1 + deltaT * vk1};
73  // clang-format on
74  std::shared_ptr<CubicPolynomial<T>> cubicFunc = std::make_shared<CubicPolynomial<T>>(coeff);
75  this->funcs_.emplace(std::next(pointIt)->first, cubicFunc);
76  }
77  }
78 
79  // Set tLowerLimit_
80  this->tLowerLimit_ = points_.begin()->first;
81  }
82 
86  virtual T operator()(double t) const override
87  {
88  this->checkArg(t);
89  auto funcIt = this->funcs_.lower_bound(t);
90 
91  const auto & seg = argSegment(t);
92  double scaledT = (t - seg.first) / (seg.second - seg.first);
93  return (*(funcIt->second))(scaledT);
94  }
95 
100  virtual T derivative(double t, int order = 1) const override
101  {
102  this->checkArg(t);
103  auto funcIt = this->funcs_.lower_bound(t);
104 
105  const auto & seg = argSegment(t);
106  double scaledT = (t - seg.first) / (seg.second - seg.first);
107  return (funcIt->second)->derivative(scaledT, order) / std::pow(seg.second - seg.first, order);
108  }
109 
117  void calcMonotoneVelocity(bool keepStartVel = false, bool keepEndVel = false)
118  {
119  std::vector<T> delta;
120  std::vector<T> alpha;
121  std::vector<T> beta;
122 
123  // 1.
124  for(auto it = points_.begin(); it != std::prev(points_.end()); it++)
125  {
126  delta.push_back((std::next(it)->second.first - it->second.first) / (std::next(it)->first - it->first));
127  }
128 
129  // 2.
130  {
131  int i = 0;
132  for(auto it = points_.begin(); it != points_.end(); it++)
133  {
134  if(it == points_.begin())
135  {
136  if(!keepStartVel)
137  {
138  it->second.second = delta[i];
139  }
140  }
141  else if(it == std::prev(points_.end()))
142  {
143  if(!keepEndVel)
144  {
145  it->second.second = delta[i - 1];
146  }
147  }
148  else
149  {
150  it->second.second = (delta[i - 1] + delta[i]) / 2;
151  for(int j = 0; j < dim_; j++)
152  {
153  if(delta[i - 1][j] * delta[i][j] < 0)
154  {
155  it->second.second[j] = 0;
156  }
157  }
158  }
159  i++;
160  }
161  }
162 
163  // 3.
164  {
165  int i = 0;
166  for(auto it = points_.begin(); it != std::prev(points_.end()); it++)
167  {
168  for(int j = 0; j < dim_; j++)
169  {
170  if(std::abs(delta[i][j]) < std::numeric_limits<double>::min())
171  {
172  it->second.second[j] = 0;
173  std::next(it)->second.second[j] = 0;
174  }
175  }
176  i++;
177  }
178  }
179 
180  // 4.
181  {
182  int i = 0;
183  for(auto it = points_.begin(); it != std::prev(points_.end()); it++)
184  {
185  alpha.push_back(it->second.second.cwiseProduct(delta[i].cwiseInverse()));
186  beta.push_back(std::next(it)->second.second.cwiseProduct(delta[i].cwiseInverse()));
187  for(int j = 0; j < dim_; j++)
188  {
189  if(alpha[i][j] < 0)
190  {
191  it->second.second[j] = 0;
192  }
193  if(beta[i][j] < 0)
194  {
195  std::next(it)->second.second[j] = 0;
196  }
197  }
198  i++;
199  }
200  }
201 
202  // 5.
203  {
204  int i = 0;
205  for(auto it = points_.begin(); it != std::prev(points_.end()); it++)
206  {
207  for(int j = 0; j < dim_; j++)
208  {
209  if(std::abs(delta[i][j]) < std::numeric_limits<double>::min())
210  {
211  continue;
212  }
213  if(!(alpha[i][j] - std::pow(2 * alpha[i][j] + beta[i][j] - 3, 2) / (3 * (alpha[i][j] + beta[i][j] - 2)) > 0
214  || alpha[i][j] + 2 * beta[i][j] - 3 <= 0 || 2 * alpha[i][j] + beta[i][j] - 3 <= 0))
215  {
216  double tau = 3 / std::sqrt(std::pow(alpha[i][j], 2) + std::pow(beta[i][j], 2));
217  it->second.second[j] = tau * alpha[i][j] * delta[i][j];
218  std::next(it)->second.second[j] = tau * beta[i][j] * delta[i][j];
219  }
220  }
221  i++;
222  }
223  }
224  }
225 
226 protected:
230  std::pair<double, double> argSegment(double t) const
231  {
232  auto funcIt = points_.lower_bound(t);
233  if(funcIt == points_.begin())
234  {
235  funcIt++;
236  }
237  return {std::prev(funcIt)->first, funcIt->first};
238  }
239 
240 protected:
242  int dim_;
243 
245  std::map<double, std::pair<T, T>> points_;
246 };
247 } // namespace TrajColl
TrajColl::CubicHermiteSpline::appendPoint
void appendPoint(const std::pair< double, std::pair< T, T >> &point)
Add point.
Definition: CubicHermiteSpline.h:37
TrajColl::CubicHermiteSpline::points_
std::map< double, std::pair< T, T > > points_
Times, positions, and velocities in way points.
Definition: CubicHermiteSpline.h:245
TrajColl::CubicHermiteSpline::argSegment
std::pair< double, double > argSegment(double t) const
Get the piecewise segment.
Definition: CubicHermiteSpline.h:230
TrajColl::CubicHermiteSpline::CubicHermiteSpline
CubicHermiteSpline(int dim, const std::map< double, std::pair< T, T >> &points={})
Constructor.
Definition: CubicHermiteSpline.h:20
TrajColl::CubicHermiteSpline::derivative
virtual T derivative(double t, int order=1) const override
Evaluate function derivative value.
Definition: CubicHermiteSpline.h:100
TrajColl::CubicHermiteSpline::operator()
virtual T operator()(double t) const override
Evaluate function value.
Definition: CubicHermiteSpline.h:86
TrajColl::CubicHermiteSpline::points
const std::map< double, std::pair< T, T > > & points() const noexcept
Access points.
Definition: CubicHermiteSpline.h:23
Func.h
TrajColl::PiecewiseFunc
Piecewise function.
Definition: Func.h:51
TrajColl
Definition: BangBangInterpolator.h:7
TrajColl::PiecewiseFunc::tLowerLimit_
double tLowerLimit_
Lower limit of domain of this function.
Definition: Func.h:146
TrajColl::CubicHermiteSpline::calcCoeff
void calcCoeff()
Calculate coefficients.
Definition: CubicHermiteSpline.h:46
TrajColl::CubicHermiteSpline::dim_
int dim_
Dimension of value.
Definition: CubicHermiteSpline.h:242
TrajColl::CubicHermiteSpline::calcMonotoneVelocity
void calcMonotoneVelocity(bool keepStartVel=false, bool keepEndVel=false)
Overwrite the velocity with keeping the time and position for making cubic Hermite spline monotone.
Definition: CubicHermiteSpline.h:117
TrajColl::PiecewiseFunc::checkArg
void checkArg(double t) const
Check argument of function.
Definition: Func.h:131
TrajColl::PiecewiseFunc::funcs_
std::map< double, std::shared_ptr< Func< T > > > funcs_
Map of upper bound of domain and function.
Definition: Func.h:143
TrajColl::CubicHermiteSpline
Cubic Hermite spline.
Definition: CubicHermiteSpline.h:13
TrajColl::CubicHermiteSpline::clearPoints
void clearPoints()
Clear points.
Definition: CubicHermiteSpline.h:29