polynomials.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2019, CNRS-UM LIRMM
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #pragma once
29 
30 #include <Eigen/Dense>
31 
32 namespace utils
33 {
34 
38 template<typename T>
40 {
41  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
42 
48  virtual T pos(double t) const = 0;
49 
55  virtual T vel(double t) const = 0;
56 
62  virtual T accel(double t) const = 0;
63 
69  T tangent(double t) const
70  {
71  T v = this->vel(t);
72  return v / v.norm();
73  }
74 
93  double arcLength(double t_start, double t_end) const
94  {
95  struct GaussLengendreCoefficient
96  {
97  double t;
98  double w;
99  };
100  static constexpr GaussLengendreCoefficient coeffs[] = {{0.0, 128. / 225.},
101  {-0.53846931010568311, 0.47862867049936647},
102  {+0.53846931010568311, 0.47862867049936647},
103  {-0.90617984593866396, 0.23692688505618908},
104  {+0.90617984593866396, 0.23692688505618908}};
105  double a = (t_end - t_start) / 2.;
106  double b = (t_end + t_start) / 2.;
107  double length = 0.;
108  for(auto coeff : coeffs)
109  {
110  length += coeff.w * this->vel(a * coeff.t + b).norm();
111  }
112  return a * length;
113  }
114 
128  double arcLengthInverse(double t_start, double length, double t_guess = -1.) const
129  {
130  constexpr double PRECISION = 1e-3;
131  if(t_guess < 0.)
132  {
133  t_guess = t_start + 1.;
134  }
135  double l_guess = arcLength(t_start, t_guess);
136  if(std::abs(l_guess - length) < PRECISION)
137  {
138  return t_guess;
139  }
140  else if(l_guess < length)
141  {
142  return arcLengthInverse(t_guess, length - l_guess, 2. * t_guess - t_start);
143  }
144  else // (l_guess > length)
145  {
146  return arcLengthInverse(t_start, length, (t_guess + t_start) / 2.);
147  }
148  }
149 };
150 
154 template<typename T>
156 {
157  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
158 
170  CubicPolynomialBase(const T & C0, const T & C1, const T & C2, const T & C3) : C0_(C0), C1_(C1), C2_(C2), C3_(C3) {}
171 
177  T pos(double t) const
178  {
179  return C0_ + t * (C1_ + t * (C2_ + t * C3_));
180  }
181 
187  T vel(double t) const
188  {
189  return C1_ + t * (2 * C2_ + 3 * t * C3_);
190  }
191 
197  T accel(double t) const
198  {
199  return 2 * C2_ + 6 * t * C3_;
200  }
201 
202 protected:
203  T C0_;
204  T C1_;
205  T C2_;
206  T C3_;
207 };
208 
209 template<typename T>
211 {
212  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
213 
217  T zero()
218  {
219  return T::Zero();
220  }
221 
225  CubicPolynomial() : CubicPolynomialBase<T>(T::Zero(), T::Zero(), T::Zero(), T::Zero()) {}
226 };
227 
228 template<>
229 struct CubicPolynomial<double> : CubicPolynomialBase<double>
230 {
231  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
232 
236  double zero()
237  {
238  return 0.;
239  }
240 
244  CubicPolynomial() : CubicPolynomialBase<double>(0., 0., 0., 0.) {}
245 };
246 
250 template<typename T>
252 {
253  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
254 
259  {
260  CubicHermitePolynomial(this->zero(), this->zero(), this->zero(), this->zero());
261  }
262 
274  CubicHermitePolynomial(const T & initPos, const T & initVel, const T & targetPos, const T & targetVel)
275  {
276  reset(initPos, initVel, targetPos, targetVel);
277  }
278 
290  void reset(const T & initPos, const T & initVel, const T & targetPos, const T & targetVel)
291  {
292  initPos_ = initPos;
293  initVel_ = initVel;
294  targetPos_ = targetPos;
295  targetVel_ = targetVel;
296  reset();
297  }
298 
306  void reset(const T & initPos, const T & targetPos)
307  {
308  initPos_ = initPos;
309  initVel_ = this->zero();
310  targetPos_ = targetPos;
311  targetVel_ = this->zero();
312  reset();
313  }
314 
318  virtual void reset()
319  {
320  this->C0_ = initPos_;
321  this->C1_ = initVel_;
322  this->C2_ = 3. * (targetPos_ - initPos_) - 2. * initVel_ - targetVel_;
323  this->C3_ = -2. * (targetPos_ - initPos_) + initVel_ + targetVel_;
324  }
325 
326 protected:
331 };
332 
339 template<typename T>
341 {
342  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
343 
349 
353  void reset() override
354  {
355  T Delta = this->targetPos_ - this->initPos_;
356  double Delta_v0 = Delta.dot(this->initVel_);
357  double Delta_v1 = Delta.dot(this->targetVel_);
358  double v0_v0 = this->initVel_.dot(this->initVel_);
359  double v0_v1 = this->initVel_.dot(this->targetVel_);
360  double v1_v1 = this->targetVel_.dot(this->targetVel_);
361  double houbaInitVelScaling =
362  6. * (3. * Delta_v0 * v1_v1 - 2. * Delta_v1 * v0_v1) / (9. * v0_v0 * v1_v1 - 4. * v0_v1 * v0_v1);
363  if(houbaInitVelScaling < 0.)
364  {
365  houbaInitVelScaling *= -1.;
366  }
367  double houbaTargetVelScaling =
368  6. * (-2. * Delta_v0 * v0_v1 + 3. * Delta_v1 * v0_v0) / (9. * v0_v0 * v1_v1 - 4. * v0_v1 * v0_v1);
369  if(houbaTargetVelScaling < 0.)
370  {
371  houbaTargetVelScaling *= -1.;
372  }
373  this->initVel_ *= houbaInitVelScaling;
374  this->initVel_ *= extraInitVelScaling_;
375  this->targetVel_ *= houbaTargetVelScaling;
376  this->targetVel_ *= extraTargetVelScaling_;
378  }
379 
384  {
385  return extraInitVelScaling_;
386  }
387 
391  void extraInitVelScaling(double scaling)
392  {
393  extraInitVelScaling_ = scaling;
394  }
395 
400  {
401  return extraTargetVelScaling_;
402  }
403 
407  void extraTargetVelScaling(double scaling)
408  {
409  extraTargetVelScaling_ = scaling;
410  }
411 
412 protected:
413  double extraInitVelScaling_ = 1.0;
414  double extraTargetVelScaling_ = 1.0;
415 };
416 
420 template<typename T>
422 {
423  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
424 
440  QuinticPolynomialBase(const T & C0, const T & C1, const T & C2, const T & C3, const T & C4, const T & C5)
441  : C0_(C0), C1_(C1), C2_(C2), C3_(C3), C4_(C4), C5_(C5)
442  {
443  }
444 
450  T pos(double t) const
451  {
452  return C0_ + t * (C1_ + t * (C2_ + t * (C3_ + t * (C4_ + t * C5_))));
453  }
454 
460  T vel(double t) const
461  {
462  return C1_ + t * (2 * C2_ + t * (3 * C3_ + t * (4 * C4_ + t * 5 * C5_)));
463  }
464 
470  T accel(double t) const
471  {
472  return 2 * C2_ + t * (6 * C3_ + t * (12 * C4_ + t * 20 * C5_));
473  }
474 
475 protected:
476  T C0_;
477  T C1_;
478  T C2_;
479  T C3_;
480  T C4_;
481  T C5_;
482 };
483 
487 template<typename T>
489 {
490  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
491 
495  T zero()
496  {
497  return T::Zero();
498  }
499 
503  QuinticPolynomial() : QuinticPolynomialBase<T>(T::Zero(), T::Zero(), T::Zero(), T::Zero(), T::Zero(), T::Zero()) {}
504 };
505 
509 template<>
510 struct QuinticPolynomial<double> : QuinticPolynomialBase<double>
511 {
512  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
513 
517  double zero()
518  {
519  return 0.;
520  }
521 
525  QuinticPolynomial() : QuinticPolynomialBase<double>(0., 0., 0., 0., 0., 0.) {}
526 };
527 
531 template<typename T>
533 {
534  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
535 
540  {
541  QuinticHermitePolynomial(this->zero(), this->zero(), this->zero(), this->zero());
542  }
543 
555  QuinticHermitePolynomial(const T & initPos, const T & initVel, const T & targetPos, const T & targetVel)
556  {
557  reset(initPos, initVel, targetPos, targetVel);
558  }
559 
575  void reset(const T & initPos,
576  const T & initVel,
577  const T & initAccel,
578  const T & targetPos,
579  const T & targetVel,
580  const T & targetAccel)
581  {
582  initPos_ = initPos;
583  initVel_ = initVel;
584  initAccel_ = initAccel;
585  targetPos_ = targetPos;
586  targetVel_ = targetVel;
587  targetAccel_ = targetAccel;
588  reset();
589  }
590 
602  void reset(const T & initPos, const T & initVel, const T & targetPos, const T & targetVel)
603  {
604  initPos_ = initPos;
605  initVel_ = initVel;
606  initAccel_ = this->zero();
607  targetPos_ = targetPos;
608  targetVel_ = targetVel;
609  targetAccel_ = this->zero();
610  reset();
611  }
612 
620  void reset(const T & initPos, const T & targetPos)
621  {
622  initPos_ = initPos;
623  initVel_ = this->zero();
624  initAccel_ = this->zero();
625  targetPos_ = targetPos;
626  targetVel_ = this->zero();
627  targetAccel_ = this->zero();
628  reset();
629  }
630 
634  void reset()
635  {
636  auto Delta = targetPos_ - initPos_;
637  auto Sigma = initVel_ + targetVel_;
638  auto Gamma = 0.5 * (targetAccel_ - initAccel_);
639  auto kappa = initVel_ + 0.5 * initAccel_;
640  this->C0_ = initPos_;
641  this->C1_ = initVel_;
642  this->C2_ = 0.5 * initAccel_;
643  this->C3_ = 10 * Delta - 4 * Sigma + Gamma - 2 * kappa;
644  this->C4_ = -15 * Delta + 7 * Sigma - 2 * Gamma + kappa;
645  this->C5_ = 6 * Delta - 3 * Sigma + Gamma;
646  }
647 
648 protected:
655 };
656 
661 template<template<class> class Polynomial, typename T>
663 {
664  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
665 
669  RetimedPolynomial() : duration_(0.) {}
670 
678  RetimedPolynomial(Polynomial<T> poly, double duration) : poly_(poly), duration_(duration) {}
679 
683  double duration() const
684  {
685  return duration_;
686  }
687 
697  void reset(const T & initPos, const T & targetPos, double duration)
698  {
699  duration_ = duration;
700  poly_.reset(initPos, targetPos);
701  }
702 
716  void reset(const T & initPos, const T & initVel, const T & targetPos, const T & targetVel, double duration)
717  {
718  duration_ = duration;
719  poly_.reset(initPos, duration * initVel, targetPos, duration * targetVel);
720  }
721 
739  void reset(const T & initPos,
740  const T & initVel,
741  const T & initAccel,
742  const T & targetPos,
743  const T & targetVel,
744  const T & targetAccel,
745  double duration)
746  {
747  duration_ = duration;
748  double duration2 = duration * duration;
749  poly_.reset(initPos, duration * initVel, duration2 * initAccel, targetPos, duration * targetVel,
750  duration2 * targetAccel);
751  }
752 
756  double s(double t) const
757  {
758  return (t < 0.) ? 0. : (t > duration_) ? 1. : t / duration_;
759  }
760 
765  double sd(double t) const
766  {
767  return (t < 0.) ? 0. : (t > duration_) ? 0. : 1. / duration_;
768  }
769 
775  T pos(double t) const
776  {
777  return poly_.pos(s(t));
778  }
779 
785  T vel(double t) const
786  {
787  return sd(t) * poly_.vel(s(t));
788  }
789 
795  T accel(double t) const
796  {
797  return std::pow(sd(t), 2) * poly_.accel(s(t));
798  }
799 
800 protected:
801  double duration_;
802  Polynomial<T> poly_;
803 };
804 
805 } // namespace utils
806 
Hermite polynomial with Overall Uniformly-Bounded Accelerations (HOUBA).
Definition: polynomials.h:340
double extraTargetVelScaling()
Get extra target velocity scaling.
Definition: polynomials.h:399
void reset(const T &initPos, const T &targetPos)
Reset boundaries with zero tangents.
Definition: polynomials.h:620
void reset(const T &initPos, const T &targetPos, double duration)
Reset duration and boundary positions.
Definition: polynomials.h:697
EIGEN_MAKE_ALIGNED_OPERATOR_NEW T zero()
Return T&#39;s zero.
Definition: polynomials.h:217
void reset(const T &initPos, const T &initVel, const T &targetPos, const T &targetVel)
Reset boundaries with zero boundary velocities.
Definition: polynomials.h:602
Cubic polynomial curve.
Definition: polynomials.h:155
T vel(double t) const
Velocity along the retimed trajectory.
Definition: polynomials.h:785
QuinticPolynomial()
Empty constructor.
Definition: polynomials.h:525
void reset(const T &initPos, const T &targetPos)
Reset boundaries with zero tangents.
Definition: polynomials.h:306
void reset()
Reset underlying cubic polynomial coefficients.
Definition: polynomials.h:634
T vel(double t) const
Get the value of the first-order derivative (velocity) at time t.
Definition: polynomials.h:187
T accel(double t) const
Acceleration along the retimed trajectory.
Definition: polynomials.h:795
QuinticPolynomial()
Empty constructor.
Definition: polynomials.h:503
EIGEN_MAKE_ALIGNED_OPERATOR_NEW CubicPolynomialBase(const T &C0, const T &C1, const T &C2, const T &C3)
Build a new curve from its monomial vector coefficients.
Definition: polynomials.h:170
EIGEN_MAKE_ALIGNED_OPERATOR_NEW QuinticPolynomialBase(const T &C0, const T &C1, const T &C2, const T &C3, const T &C4, const T &C5)
Build a new curve from its monomial vector coefficients.
Definition: polynomials.h:440
T vel(double t) const
Get the value of the first-order derivative (velocity) at time t.
Definition: polynomials.h:460
RetimedPolynomial(Polynomial< T > poly, double duration)
Constructor.
Definition: polynomials.h:678
EIGEN_MAKE_ALIGNED_OPERATOR_NEW RetimedPolynomial()
Empty constructor.
Definition: polynomials.h:669
T accel(double t) const
Get the value of the second-order derivative (acceleration) at time t.
Definition: polynomials.h:470
Cubic Hermite polynomial.
Definition: polynomials.h:251
virtual void reset()
Reset underlying cubic polynomial coefficients.
Definition: polynomials.h:318
double duration() const
Get trajectory duration.
Definition: polynomials.h:683
double extraInitVelScaling()
Get extra initial velocity scaling.
Definition: polynomials.h:383
CubicPolynomial()
Empty constructor.
Definition: polynomials.h:244
T pos(double t) const
Get the value of the polynomial at time t.
Definition: polynomials.h:177
void reset(const T &initPos, const T &initVel, const T &targetPos, const T &targetVel)
Reset boundaries.
Definition: polynomials.h:290
Quintic polynomial over vectors.
Definition: polynomials.h:488
Quintic polynomial.
Definition: polynomials.h:421
virtual EIGEN_MAKE_ALIGNED_OPERATOR_NEW T pos(double t) const =0
Get the value of the polynomial at time t.
Quintic polynomial with zero velocity and zero acceleration at 0 and 1.
Definition: polynomials.h:532
CubicPolynomial()
Empty constructor.
Definition: polynomials.h:225
void extraTargetVelScaling(double scaling)
Add extra target velocity scaling to the HOUBA one.
Definition: polynomials.h:407
Polynomial whose argument is retimed to by .
Definition: polynomials.h:662
T pos(double t) const
Position along the retimed trajectory.
Definition: polynomials.h:775
double arcLengthInverse(double t_start, double length, double t_guess=-1.) const
Inverse of the arc length function.
Definition: polynomials.h:128
T accel(double t) const
Get the value of the second-order derivative (acceleration) at time t.
Definition: polynomials.h:197
virtual T accel(double t) const =0
Get the value of the second-order derivative (acceleration) at time t.
EIGEN_MAKE_ALIGNED_OPERATOR_NEW double zero()
Zero function used for double specialization.
Definition: polynomials.h:517
EIGEN_MAKE_ALIGNED_OPERATOR_NEW QuinticHermitePolynomial()
Empty constructor.
Definition: polynomials.h:539
EIGEN_MAKE_ALIGNED_OPERATOR_NEW T zero()
Return T&#39;s zero.
Definition: polynomials.h:495
double arcLength(double t_start, double t_end) const
Compute the arc length between two points of the polynomial curve.
Definition: polynomials.h:93
QuinticHermitePolynomial(const T &initPos, const T &initVel, const T &targetPos, const T &targetVel)
Build a new cubic Hermite polynomial.
Definition: polynomials.h:555
EIGEN_MAKE_ALIGNED_OPERATOR_NEW CubicHermitePolynomial()
Empty constructor.
Definition: polynomials.h:258
void reset(const T &initPos, const T &initVel, const T &targetPos, const T &targetVel, double duration)
Reset duration and boundary positions and velocities.
Definition: polynomials.h:716
Utility functions and classes.
Definition: clamp.h:35
Polynomial function.
Definition: polynomials.h:39
double s(double t) const
Mapping from to .
Definition: polynomials.h:756
virtual T vel(double t) const =0
Get the value of the first-order derivative (velocity) at time t.
void reset(const T &initPos, const T &initVel, const T &initAccel, const T &targetPos, const T &targetVel, const T &targetAccel, double duration)
Reset duration and boundary positions, velocities and accelerations.
Definition: polynomials.h:739
void extraInitVelScaling(double scaling)
Add extra initial velocity scaling to the HOUBA one.
Definition: polynomials.h:391
T tangent(double t) const
Get the value of the tangent vector at time t.
Definition: polynomials.h:69
Polynomial< T > poly_
Definition: polynomials.h:802
CubicHermitePolynomial(const T &initPos, const T &initVel, const T &targetPos, const T &targetVel)
Build a new cubic Hermite polynomial.
Definition: polynomials.h:274
void reset(const T &initPos, const T &initVel, const T &initAccel, const T &targetPos, const T &targetVel, const T &targetAccel)
Reset boundary values.
Definition: polynomials.h:575
T pos(double t) const
Get the value of the polynomial at time t.
Definition: polynomials.h:450
void reset() override
Rescale boundary velocities, then reset as Hermite polynomial.
Definition: polynomials.h:353
double sd(double t) const
Mapping from to .
Definition: polynomials.h:765
EIGEN_MAKE_ALIGNED_OPERATOR_NEW double zero()
Zero function used for double specialization.
Definition: polynomials.h:236