24#include <fmt/format.h>
40template<std::
floating_po
int T>
41constexpr T
round(
const T& value,
size_t digits)
43 auto factor = std::pow(10, digits);
44 return std::round(value * factor) / factor;
51template<std::
floating_po
int T>
54 if (value == 0.0) {
return 0.0; }
56 auto absVal = gcem::abs(value);
57 auto log10 =
static_cast<int32_t
>(gcem::log10(absVal));
58 auto exp = log10 + (log10 > 0 || (log10 == 0 && absVal >= 1.0));
59 auto fac =
static_cast<T
>(digits) -
static_cast<T
>(exp);
61 auto factor =
static_cast<T
>(gcem::pow(10.0, fac));
64 return static_cast<T
>(gcem::round(value * factor) / factor);
73template<std::
integral Out,
size_t Bits, std::
integral In>
76 static_assert(Bits <
sizeof(In) * 8);
77 static_assert(Bits <
sizeof(Out) * 8);
79 constexpr size_t N =
sizeof(Out) * 8 - Bits;
80 return static_cast<Out
>(
static_cast<Out
>((in &
static_cast<In
>(gcem::pow(2, Bits) - 1)) << N) >> N);
89template<
typename Derived>
95 Eigen::Matrix<typename Derived::Scalar, 3, 3> skewMat;
96 skewMat << 0, -a(2), a(1),
107template<
typename Derived>
113 Eigen::Matrix<typename Derived::Scalar, 3, 3> skewMat2;
114 skewMat2 << std::pow(a(2), 2) + std::pow(a(1), 2), a(0) * a(1), a(0) * a(2),
115 a(0) * a(1), std::pow(a(2), 2) + std::pow(a(0), 2), a(1) * a(2),
116 a(0) * a(2), a(1) * a(2), std::pow(a(0), 2) + std::pow(a(1), 2);
125template<
typename Derived>
126Eigen::Matrix<typename Derived::Scalar, 3, 3>
expMapMatrix(
const Eigen::MatrixBase<Derived>& v)
138template<
typename Derived>
139Eigen::Quaternion<typename Derived::Scalar>
expMapQuat(
const Eigen::MatrixBase<Derived>& v)
144 Eigen::Vector3<typename Derived::Scalar> omega = 0.5 * v;
145 auto omegaNorm = omega.norm();
146 if (omegaNorm < 1e-9) {
return Eigen::Quaternion<typename Derived::Scalar>::Identity(); }
147 Eigen::Vector3<typename Derived::Scalar> quatVec = omega / omegaNorm * std::sin(omegaNorm);
149 return { std::cos(omegaNorm), quatVec.x(), quatVec.y(), quatVec.z() };
155template<
typename Derived>
156[[nodiscard]] Eigen::Matrix3<typename Derived::Scalar>
J_r(
const Eigen::MatrixBase<Derived>& phi)
161 auto phiNorm = phi.norm();
162 auto phiNorm2 = phiNorm * phiNorm;
163 auto phiNorm3 = phiNorm2 * phiNorm;
164 return Eigen::Matrix3<typename Derived::Scalar>::Identity()
170template<std::
floating_po
int T>
173 return 1.0 / std::cos(x);
177template<std::
floating_po
int T>
180 return 1.0 / std::sin(x);
189 return (T(0) < val) - (val < T(0));
196template<
typename Derived>
197typename Derived::PlainObject
expm(
const Eigen::MatrixBase<Derived>& X,
size_t order)
199 INS_ASSERT_USER_ERROR(X.rows() == X.cols(),
"Matrix exponential calculation only possible for n x n matrices");
201 typename Derived::PlainObject e_X;
203 if constexpr (Derived::RowsAtCompileTime == Eigen::Dynamic)
205 e_X = Eigen::MatrixBase<Derived>::Identity(X.rows(), X.cols());
209 e_X = Eigen::MatrixBase<Derived>::Identity();
211 typename Derived::PlainObject Xpower = X;
212 for (
size_t i = 1; i <= order; i++)
231template<
typename Derived>
232std::optional<std::pair<Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime>,
233 Eigen::Vector<typename Derived::Scalar, Derived::RowsAtCompileTime>>>
238 auto n = Qmatrix.rows();
239 Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime> Q = Qmatrix.template triangularView<Eigen::Lower>();
240 Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime> L;
241 Eigen::Vector<typename Derived::Scalar, Derived::RowsAtCompileTime> D;
243 if constexpr (Derived::RowsAtCompileTime == Eigen::Dynamic)
245 L = Eigen::Matrix<typename Derived::Scalar, Eigen::Dynamic, Eigen::Dynamic>::Zero(n, n);
250 L = Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime>::Zero();
254 for (Eigen::Index i = n - 1; i >= 0; i--)
257 if (Q(i, i) <= 0.0) {
return {}; }
258 L(i, seq(0, i)) = Q(i, seq(0, i)) / std::sqrt(Q(i, i));
260 for (Eigen::Index j = 0; j <= i - 1; j++)
262 Q(j, seq(0, j)) -= L(i, seq(0, j)) * L(i, j);
264 L(i, seq(0, i)) /= L(i, i);
267 return std::make_pair(L, D);
275template<
typename Derived>
276std::optional<std::pair<Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime>,
277 Eigen::Vector<typename Derived::Scalar, Derived::RowsAtCompileTime>>>
283 typename Derived::PlainObject L = Q.template triangularView<Eigen::Lower>();
284 Eigen::Vector<typename Derived::Scalar, Derived::RowsAtCompileTime> D;
287 if constexpr (Derived::RowsAtCompileTime == Eigen::Dynamic) { D.setZero(n); }
288 else { D.setZero(); }
290 for (Eigen::Index j = n - 1; j >= 0; j--)
292 for (Eigen::Index i = n - 1; i >= j + 1; i--)
294 L(i, j) = (L(i, j) - L(seq(i + 1, n - 1), j).dot(L(seq(i + 1, n - 1), i))) / L(i, i);
296 double t = L(j, j) - L(seq(j + 1, n - 1), j).dot(L(seq(j + 1, n - 1), j));
297 if (t <= 0.0) {
return {}; }
298 double c = t / L(j, j);
299 cmin = std::min(c, cmin);
300 L(j, j) = std::sqrt(t);
302 for (Eigen::Index i = 0; i < n; i++)
304 L.row(i).leftCols(i) /= L(i, i);
305 D(i) = std::pow(L(i, i), 2.0);
309 return std::make_pair(L, D);
320template<
typename DerivedA,
typename DerivedQ>
323 static_assert(DerivedA::ColsAtCompileTime == Eigen::Dynamic || DerivedA::ColsAtCompileTime == 1);
328 return a.transpose() * Q.inverse() * a;
361template<
typename Derived>
362[[nodiscard]]
typename Derived::PlainObject
inverseSqrt(
const Eigen::MatrixBase<Derived>& matrix)
365 if constexpr (std::is_floating_point_v<typename Derived::Scalar>)
367 return matrix.inverse().sqrt();
371 Eigen::JacobiSVD<Eigen::MatrixX<typename Derived::Scalar>> svd(matrix.inverse(), Eigen::ComputeFullV);
372 typename Derived::PlainObject sqrtInverse = svd.matrixV() * svd.singularValues().cwiseSqrt().asDiagonal() * svd.matrixV().transpose();
390 return -1.0 * fabs(x);
398template<
typename Derived>
399typename Derived::PlainObject
lerp(
const Eigen::MatrixBase<Derived>& a,
const Eigen::MatrixBase<Derived>& b,
auto t)
401 return a + t * (b - a);
417 auto i =
static_cast<size_t>(std::distance(data.begin(), std::upper_bound(data.begin(), data.end(), value)));
419 if (i == data.size() - 1) { i--; }
420 const auto& lb = data.at(i);
421 const auto& ub = data.at(i + 1);
422 double t = (value - lb) / (ub - lb);
424 return { .l = i, .u = i + 1, .t = t };
443 const auto& c00,
const auto& c10,
444 const auto& c01,
const auto& c11)
446 auto a = c00 * (1.0 - tx) + c10 * tx;
447 auto b = c01 * (1.0 - tx) + c11 * tx;
448 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.