MRSL Motion Primitive Library  1.2
A motion primitive library for generating trajectory for mobile robots
math.h
Go to the documentation of this file.
1 
9 #pragma once
10 #include <mpl_basis/data_type.h>
11 
12 #include <iostream>
13 #include <unsupported/Eigen/Polynomials>
14 
15 inline decimal_t normalize_angle(decimal_t angle) {
16  while (angle > M_PI) angle -= 2.0 * M_PI;
17  while (angle < -M_PI) angle += 2.0 * M_PI;
18  return angle;
19 }
20 
22 inline std::vector<decimal_t> quad(decimal_t b, decimal_t c, decimal_t d) {
23  std::vector<decimal_t> dts;
24  decimal_t p = c * c - 4 * b * d;
25  if (p < 0)
26  return dts;
27  else {
28  dts.push_back((-c - sqrt(p)) / (2 * b));
29  dts.push_back((-c + sqrt(p)) / (2 * b));
30  return dts;
31  }
32 }
33 
35 inline std::vector<decimal_t> cubic(decimal_t a, decimal_t b, decimal_t c,
36  decimal_t d) {
37  std::vector<decimal_t> dts;
38 
39  decimal_t a2 = b / a;
40  decimal_t a1 = c / a;
41  decimal_t a0 = d / a;
42  // printf("a: %f, b: %f, c: %f, d: %f\n", a, b, c, d);
43 
44  decimal_t Q = (3 * a1 - a2 * a2) / 9;
45  decimal_t R = (9 * a1 * a2 - 27 * a0 - 2 * a2 * a2 * a2) / 54;
46  decimal_t D = Q * Q * Q + R * R;
47  // printf("R: %f, Q: %f, D: %f\n", R, Q, D);
48  if (D > 0) {
49  decimal_t S = std::cbrt(R + sqrt(D));
50  decimal_t T = std::cbrt(R - sqrt(D));
51  // printf("S: %f, T: %f\n", S, T);
52  dts.push_back(-a2 / 3 + (S + T));
53  return dts;
54  } else if (D == 0) {
55  decimal_t S = std::cbrt(R);
56  dts.push_back(-a2 / 3 + S + S);
57  dts.push_back(-a2 / 3 - S);
58  return dts;
59  } else {
60  decimal_t theta = acos(R / sqrt(-Q * Q * Q));
61  dts.push_back(2 * sqrt(-Q) * cos(theta / 3) - a2 / 3);
62  dts.push_back(2 * sqrt(-Q) * cos((theta + 2 * M_PI) / 3) - a2 / 3);
63  dts.push_back(2 * sqrt(-Q) * cos((theta + 4 * M_PI) / 3) - a2 / 3);
64  return dts;
65  }
66 }
67 
69 inline std::vector<decimal_t> quartic(decimal_t a, decimal_t b, decimal_t c,
70  decimal_t d, decimal_t e) {
71  std::vector<decimal_t> dts;
72 
73  decimal_t a3 = b / a;
74  decimal_t a2 = c / a;
75  decimal_t a1 = d / a;
76  decimal_t a0 = e / a;
77 
78  std::vector<decimal_t> ys =
79  cubic(1, -a2, a1 * a3 - 4 * a0, 4 * a2 * a0 - a1 * a1 - a3 * a3 * a0);
80  decimal_t y1 = ys.front();
81  // printf("y1: %f\n", y1);
82  decimal_t r = a3 * a3 / 4 - a2 + y1;
83  // printf("r: %f\n", r);
84 
85  // printf("a = %f, b = %f, c = %f, d = %f, e = %f\n", a, b, c, d, e);
86  if (r < 0) return dts;
87 
88  decimal_t R = sqrt(r);
89  decimal_t D, E;
90  if (R != 0) {
91  D = sqrt(0.75 * a3 * a3 - R * R - 2 * a2 +
92  0.25 * (4 * a3 * a2 - 8 * a1 - a3 * a3 * a3) / R);
93  E = sqrt(0.75 * a3 * a3 - R * R - 2 * a2 -
94  0.25 * (4 * a3 * a2 - 8 * a1 - a3 * a3 * a3) / R);
95  } else {
96  D = sqrt(0.75 * a3 * a3 - 2 * a2 + 2 * sqrt(y1 * y1 - 4 * a0));
97  E = sqrt(0.75 * a3 * a3 - 2 * a2 - 2 * sqrt(y1 * y1 - 4 * a0));
98  }
99 
100  if (!std::isnan(D)) {
101  dts.push_back(-a3 / 4 + R / 2 + D / 2);
102  dts.push_back(-a3 / 4 + R / 2 - D / 2);
103  }
104  if (!std::isnan(E)) {
105  dts.push_back(-a3 / 4 - R / 2 + E / 2);
106  dts.push_back(-a3 / 4 - R / 2 - E / 2);
107  }
108 
109  return dts;
110 }
111 
117 inline std::vector<decimal_t> solve(decimal_t a, decimal_t b, decimal_t c,
118  decimal_t d, decimal_t e) {
119  std::vector<decimal_t> ts;
120  if (a != 0)
121  return quartic(a, b, c, d, e);
122  else if (b != 0)
123  return cubic(b, c, d, e);
124  else if (c != 0)
125  return quad(c, d, e);
126  else if (d != 0) {
127  ts.push_back(-e / d);
128  return ts;
129  } else
130  return ts;
131 }
132 
134 inline std::vector<decimal_t> solve(decimal_t a, decimal_t b, decimal_t c,
135  decimal_t d, decimal_t e, decimal_t f) {
136  std::vector<decimal_t> ts;
137  if (a == 0)
138  return solve(b, c, d, e, f);
139  else {
140  Eigen::VectorXd coeff(6);
141  coeff << f, e, d, c, b, a;
142  Eigen::PolynomialSolver<double, 5> solver;
143  solver.compute(coeff);
144 
145  const Eigen::PolynomialSolver<double, 5>::RootsType &r = solver.roots();
146  std::vector<decimal_t> ts;
147  // std::cout << coeff.transpose() << std::endl;
148  for (int i = 0; i < r.rows(); ++i) {
149  if (r[i].imag() == 0) {
150  // std::cout << r[i] << std::endl;
151  ts.push_back(r[i].real());
152  }
153  }
154 
155  return ts;
156  }
157 }
158 
160 inline std::vector<decimal_t> solve(decimal_t a, decimal_t b, decimal_t c,
161  decimal_t d, decimal_t e, decimal_t f,
162  decimal_t g) {
163  std::vector<decimal_t> ts;
164  if (a == 0 && b == 0)
165  return solve(c, d, e, f, g);
166  else {
167  Eigen::VectorXd coeff(7);
168  coeff << g, f, e, d, c, b, a;
169  Eigen::PolynomialSolver<double, 6> solver;
170  solver.compute(coeff);
171 
172  const Eigen::PolynomialSolver<double, 6>::RootsType &r = solver.roots();
173  std::vector<decimal_t> ts;
174  // std::cout << coeff.transpose() << std::endl;
175  for (int i = 0; i < r.rows(); ++i) {
176  if (r[i].imag() == 0) {
177  // std::cout << r[i] << std::endl;
178  ts.push_back(r[i].real());
179  }
180  }
181 
182  return ts;
183  }
184 }
185 
187 inline int factorial(int n) {
188  int nf = 1;
189  while (n > 0) {
190  nf *= n;
191  n--;
192  }
193  return nf;
194 }
195 
197 inline decimal_t power(decimal_t t, int n) {
198  decimal_t tn = 1;
199  while (n > 0) {
200  tn *= t;
201  n--;
202  }
203  return tn;
204  // return n <= 0 ? 1 : power(t, n-1);
205 }
206 
207 template <typename Derived>
208 typename Derived::PlainObject pseudoInverse(
209  Eigen::MatrixBase<Derived> const &m) {
210  // JacobiSVD: thin U and V are only available when your matrix has a dynamic
211  // number of columns.
212  constexpr auto flags = (Derived::ColsAtCompileTime == Eigen::Dynamic)
213  ? (Eigen::ComputeThinU | Eigen::ComputeThinV)
214  : (Eigen::ComputeFullU | Eigen::ComputeFullV);
215  Eigen::JacobiSVD<typename Derived::PlainObject> m_svd(m, flags);
216  // std::cout << "singular values: " << m_svd.singularValues().transpose()
217  // << "\n";
218  return m_svd.solve(Derived::PlainObject::Identity(m.rows(), m.rows()));
219 }
220 
221 template <typename Derived>
222 typename Derived::PlainObject matrixSquareRoot(
223  Eigen::MatrixBase<Derived> const &mat, bool semidefinite_mat = false) {
224  if (!semidefinite_mat) {
225  Eigen::LLT<typename Derived::PlainObject> cov_chol{mat};
226  if (cov_chol.info() == Eigen::Success) return cov_chol.matrixL();
227  }
228  Eigen::LDLT<typename Derived::PlainObject> cov_chol{mat};
229  if (cov_chol.info() == Eigen::Success) {
230  typename Derived::PlainObject const L = cov_chol.matrixL();
231  auto const P = cov_chol.transpositionsP();
232  auto const D_sqrt = cov_chol.vectorD().array().sqrt().matrix().asDiagonal();
233  return P.transpose() * L * D_sqrt;
234  }
235  return Derived::PlainObject::Zero(mat.rows(), mat.cols());
236 }
237 
std::vector< decimal_t > quartic(decimal_t a, decimal_t b, decimal_t c, decimal_t d, decimal_t e)
Quartic equation: .
Definition: math.h:69
decimal_t power(decimal_t t, int n)
Return .
Definition: math.h:197
std::vector< decimal_t > solve(decimal_t a, decimal_t b, decimal_t c, decimal_t d, decimal_t e)
General solver for .
Definition: math.h:117
std::vector< decimal_t > quad(decimal_t b, decimal_t c, decimal_t d)
Quadratic equation: .
Definition: math.h:22
int factorial(int n)
Return .
Definition: math.h:187
double decimal_t
Rename the float type used in lib.
Definition: data_type.h:49
Defines all data types used in this lib.
std::vector< decimal_t > cubic(decimal_t a, decimal_t b, decimal_t c, decimal_t d)
Cubic equation: .
Definition: math.h:35