23#include <unsupported/Eigen/MatrixFunctions>
25#include <fmt/format.h>
41template<std::
floating_po
int T>
42constexpr T
round(
const T& value,
size_t digits)
44 auto factor = std::pow(10, digits);
45 return std::round(value * factor) / factor;
52template<std::
floating_po
int T>
55 if (value == T(0) || digits == 0)
60 if (!std::isfinite(value))
66 T absValue = std::fabs(value);
67 T exponent = std::floor(std::log10(absValue));
70 T scale = std::pow(T(10), exponent - T(digits - 1));
73 return std::round(value / scale) * scale;
82template<std::
integral Out,
size_t Bits, std::
integral In>
85 static_assert(Bits <
sizeof(In) * 8);
86 static_assert(Bits <
sizeof(Out) * 8);
88 constexpr size_t N =
sizeof(Out) * 8 - Bits;
89 return static_cast<Out
>(
static_cast<Out
>((in &
static_cast<In
>(gcem::pow(2, Bits) - 1)) << N) >> N);
98template<
typename Derived>
104 Eigen::Matrix<typename Derived::Scalar, 3, 3> skewMat;
105 skewMat << 0, -a(2), a(1),
116template<
typename Derived>
122 Eigen::Matrix<typename Derived::Scalar, 3, 3> skewMat2;
123 skewMat2 << std::pow(a(2), 2) + std::pow(a(1), 2), a(0) * a(1), a(0) * a(2),
124 a(0) * a(1), std::pow(a(2), 2) + std::pow(a(0), 2), a(1) * a(2),
125 a(0) * a(2), a(1) * a(2), std::pow(a(0), 2) + std::pow(a(1), 2);
134template<
typename Derived>
135Eigen::Matrix<typename Derived::Scalar, 3, 3>
expMapMatrix(
const Eigen::MatrixBase<Derived>& v)
147template<
typename Derived>
148Eigen::Quaternion<typename Derived::Scalar>
expMapQuat(
const Eigen::MatrixBase<Derived>& v)
153 Eigen::Vector3<typename Derived::Scalar> omega = 0.5 * v;
154 auto omegaNorm = omega.norm();
155 if (omegaNorm < 1e-9) {
return Eigen::Quaternion<typename Derived::Scalar>::Identity(); }
156 Eigen::Vector3<typename Derived::Scalar> quatVec = omega / omegaNorm * std::sin(omegaNorm);
158 return { std::cos(omegaNorm), quatVec.x(), quatVec.y(), quatVec.z() };
164template<
typename Derived>
165[[nodiscard]] Eigen::Matrix3<typename Derived::Scalar>
J_r(
const Eigen::MatrixBase<Derived>& phi)
170 auto phiNorm = phi.norm();
171 auto phiNorm2 = phiNorm * phiNorm;
172 auto phiNorm3 = phiNorm2 * phiNorm;
173 return Eigen::Matrix3<typename Derived::Scalar>::Identity()
179template<std::
floating_po
int T>
182 return 1.0 / std::cos(x);
186template<std::
floating_po
int T>
189 return 1.0 / std::sin(x);
198 return (T(0) < val) - (val < T(0));
205template<
typename Derived>
206typename Derived::PlainObject
expm(
const Eigen::MatrixBase<Derived>& X,
size_t order)
208 INS_ASSERT_USER_ERROR(X.rows() == X.cols(),
"Matrix exponential calculation only possible for n x n matrices");
210 typename Derived::PlainObject e_X;
212 if constexpr (Derived::RowsAtCompileTime == Eigen::Dynamic)
214 e_X = Eigen::MatrixBase<Derived>::Identity(X.rows(), X.cols());
218 e_X = Eigen::MatrixBase<Derived>::Identity();
220 typename Derived::PlainObject Xpower = X;
221 for (
size_t i = 1; i <= order; i++)
240template<
typename Derived>
241std::optional<std::pair<Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime>,
242 Eigen::Vector<typename Derived::Scalar, Derived::RowsAtCompileTime>>>
247 auto n = Qmatrix.rows();
248 Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime> Q = Qmatrix.template triangularView<Eigen::Lower>();
249 Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime> L;
250 Eigen::Vector<typename Derived::Scalar, Derived::RowsAtCompileTime> D;
252 if constexpr (Derived::RowsAtCompileTime == Eigen::Dynamic)
254 L = Eigen::Matrix<typename Derived::Scalar, Eigen::Dynamic, Eigen::Dynamic>::Zero(n, n);
259 L = Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime>::Zero();
263 for (Eigen::Index i = n - 1; i >= 0; i--)
266 if (Q(i, i) <= 0.0) {
return {}; }
267 L(i, seq(0, i)) = Q(i, seq(0, i)) / std::sqrt(Q(i, i));
269 for (Eigen::Index j = 0; j <= i - 1; j++)
271 Q(j, seq(0, j)) -= L(i, seq(0, j)) * L(i, j);
273 L(i, seq(0, i)) /= L(i, i);
276 return std::make_pair(L, D);
284template<
typename Derived>
285std::optional<std::pair<Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime>,
286 Eigen::Vector<typename Derived::Scalar, Derived::RowsAtCompileTime>>>
292 typename Derived::PlainObject L = Q.template triangularView<Eigen::Lower>();
293 Eigen::Vector<typename Derived::Scalar, Derived::RowsAtCompileTime> D;
296 if constexpr (Derived::RowsAtCompileTime == Eigen::Dynamic) { D.setZero(n); }
302 for (Eigen::Index j = n - 1; j >= 0; j--)
304 for (Eigen::Index i = n - 1; i >= j + 1; i--)
306 L(i, j) = (L(i, j) - L(seq(i + 1, n - 1), j).dot(L(seq(i + 1, n - 1), i))) / L(i, i);
308 double t = L(j, j) - L(seq(j + 1, n - 1), j).dot(L(seq(j + 1, n - 1), j));
309 if (t <= 0.0) {
return {}; }
310 double c = t / L(j, j);
311 cmin = std::min(c, cmin);
312 L(j, j) = std::sqrt(t);
314 for (Eigen::Index i = 0; i < n; i++)
316 L.row(i).leftCols(i) /= L(i, i);
317 D(i) = std::pow(L(i, i), 2.0);
321 return std::make_pair(L, D);
332template<
typename DerivedA,
typename DerivedQ>
335 static_assert(DerivedA::ColsAtCompileTime == Eigen::Dynamic || DerivedA::ColsAtCompileTime == 1);
340 return a.transpose() * Q.inverse() * a;
373template<
typename Derived>
374[[nodiscard]]
typename Derived::PlainObject
inverseSqrt(
const Eigen::MatrixBase<Derived>& matrix)
377 if constexpr (std::is_floating_point_v<typename Derived::Scalar>)
379 return matrix.inverse().sqrt();
383 Eigen::JacobiSVD<Eigen::MatrixX<typename Derived::Scalar>> svd(matrix.inverse(), Eigen::ComputeFullV);
384 typename Derived::PlainObject sqrtInverse = svd.matrixV() * svd.singularValues().cwiseSqrt().asDiagonal() * svd.matrixV().transpose();
402 return -1.0 * fabs(x);
410template<
typename Derived>
411typename Derived::PlainObject
lerp(
const Eigen::MatrixBase<Derived>& a,
const Eigen::MatrixBase<Derived>& b,
auto t)
413 return a + t * (b - a);
429 auto i =
static_cast<size_t>(std::distance(data.begin(), std::upper_bound(data.begin(), data.end(), value)));
431 if (i == data.size() - 1) { i--; }
432 const auto& lb = data.at(i);
433 const auto& ub = data.at(i + 1);
434 double t = (value - lb) / (ub - lb);
436 return { .l = i, .u = i + 1, .t = t };
455 const auto& c00,
const auto& c10,
456 const auto& c01,
const auto& c11)
458 auto a = c00 * (1.0 - tx) + c10 * tx;
459 auto b = c01 * (1.0 - tx) + c11 * tx;
460 return a * (1.0 - ty) + b * ty;
#define INS_ASSERT_USER_ERROR(_EXP, _MSG)
Assert function with message.
T sec(const T &x)
Calculates the secant of a value (sec(x) = csc(pi/2 - x) = 1 / cos(x))
LerpSearchResult lerpSearch(const auto &data, const auto &value)
Searches the value in the data container.
Eigen::Quaternion< typename Derived::Scalar > expMapQuat(const Eigen::MatrixBase< Derived > &v)
Calculates the quaternionic exponential map of the given vector.
T csc(const T &x)
Calculates the cosecant of a value (csc(x) = sec(pi/2 - x) = 1 / sin(x))
DerivedA::Scalar squaredNormVectorMatrix(const Eigen::MatrixBase< DerivedA > &a, const Eigen::MatrixBase< DerivedQ > &Q)
Calculates the squared norm of the vector and matrix.
Derived::PlainObject expm(const Eigen::MatrixBase< Derived > &X, size_t order)
Calculates the state transition matrix 𝚽 limited to specified order in 𝐅𝜏ₛ
Eigen::Matrix< typename Derived::Scalar, 3, 3 > expMapMatrix(const Eigen::MatrixBase< Derived > &v)
Calculates the matrix exponential map of the given vector.
int sgn(const T &val)
Returns the sign of the given value.
std::optional< std::pair< Eigen::Matrix< typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime >, Eigen::Vector< typename Derived::Scalar, Derived::RowsAtCompileTime > > > LtDLdecomp_outerProduct(const Eigen::MatrixBase< Derived > &Qmatrix)
Find (L^T D L)-decomposition of Q-matrix via outer product method.
T sign(const T &x, const T &y)
Change the sign of x according to the value of y.
Eigen::Matrix< typename Derived::Scalar, 3, 3 > skewSymmetricMatrixSquared(const Eigen::MatrixBase< Derived > &a)
Calculates the square of a skew symmetric matrix of the given vector.
auto bilinearInterpolation(const auto &tx, const auto &ty, const auto &c00, const auto &c10, const auto &c01, const auto &c11)
Bilinear interpolation.
constexpr T roundSignificantDigits(T value, size_t digits)
Round the number to the specified amount of significant digits.
Derived::PlainObject lerp(const Eigen::MatrixBase< Derived > &a, const Eigen::MatrixBase< Derived > &b, auto t)
Linear interpolation between vectors.
Eigen::Matrix3< typename Derived::Scalar > J_r(const Eigen::MatrixBase< Derived > &phi)
Calculates the right Jacobian of SO(3) which relates additive increments in the tangent space to mult...
double calcEllipticalIntegral(double phi, double m)
Calculates the incomplete elliptical integral of the second kind.
Eigen::Matrix< typename Derived::Scalar, 3, 3 > skewSymmetricMatrix(const Eigen::MatrixBase< Derived > &a)
Calculates the skew symmetric matrix of the given vector. This is needed to perform the cross product...
uint64_t factorial(uint64_t n)
Calculates the factorial of an unsigned integer.
double normalCDF(double value)
Calculates the cumulative distribution function (CDF) of the standard normal distribution.
constexpr T round(const T &value, size_t digits)
Round the number to the specified amount of digits.
constexpr Out interpretAs(In in)
Interprets the input integer with certain amount of Bits as Output type. Takes care of sign extension...
Derived::PlainObject inverseSqrt(const Eigen::MatrixBase< Derived > &matrix)
Returns the inverse square root of a matrix.
std::optional< std::pair< Eigen::Matrix< typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime >, Eigen::Vector< typename Derived::Scalar, Derived::RowsAtCompileTime > > > LtDLdecomp_choleskyFact(const Eigen::MatrixBase< Derived > &Q)
Find (L^T D L)-decomposition of Q-matrix via a backward Cholesky factorization in a bordering method ...
size_t u
Upper bound index (l + 1)
double t
[0, 1] for Interpolation, otherwise Extrapolation
size_t l
Lower bound index.