9#ifndef CROCODDYL_CORE_UTILS_MATH_HPP_
10#define CROCODDYL_CORE_UTILS_MATH_HPP_
12#include <Eigen/Cholesky>
19#include "crocoddyl/core/utils/scalar.hpp"
21#ifdef CROCODDYL_WITH_CODEGEN
22#include <cppad/cg/support/cppadcg_eigen.hpp>
23#include <cppad/cppad.hpp>
28template <
typename Scalar>
29constexpr Scalar pi() {
30 return static_cast<Scalar
>(3.14159265358979323846264338327950288);
33template <
typename Scalar>
34typename std::enable_if<std::is_floating_point<Scalar>::value,
bool>::type
35isfinite(
const Scalar& value) {
36 return std::isfinite(value);
39template <
typename MatrixLike,
41 (Eigen::NumTraits<typename MatrixLike::Scalar>::IsInteger == 0)>
43 typedef typename MatrixLike::Scalar Scalar;
44 typedef typename MatrixLike::RealScalar RealScalar;
46 static MatrixLike run(
const Eigen::MatrixBase<MatrixLike>& a,
47 const RealScalar& epsilon) {
49 Eigen::JacobiSVD<MatrixLike> svd(a,
50 Eigen::ComputeThinU | Eigen::ComputeThinV);
51 RealScalar tolerance = epsilon *
52 static_cast<Scalar
>(max(a.cols(), a.rows())) *
53 svd.singularValues().array().abs()(0);
55 Eigen::Matrix<typename MatrixLike::Scalar, Eigen::Dynamic, 1>
57 svd.singularValues().unaryExpr([&](
const Scalar& x) {
58 return (x > tolerance) ? Scalar(1) / x : Scalar(0);
60 return svd.matrixV() * invSingularValues.asDiagonal() *
61 svd.matrixU().adjoint();
65template <
typename MatrixLike>
67 typedef typename MatrixLike::Scalar Scalar;
68 typedef typename MatrixLike::RealScalar RealScalar;
70 static MatrixLike run(
const Eigen::MatrixBase<MatrixLike>& a,
72 return Eigen::MatrixBase<MatrixLike>::Zero(a.rows(), a.cols());
76template <
typename MatrixLike>
77MatrixLike pseudoInverse(
78 const Eigen::MatrixBase<MatrixLike>& a,
79 const typename MatrixLike::RealScalar& epsilon =
80 Eigen::NumTraits<typename MatrixLike::Scalar>::dummy_precision()) {
84template <
typename Scalar>
85typename std::enable_if<std::is_floating_point<Scalar>::value,
bool>::type
86checkPSD(
const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>& a) {
87 Eigen::SelfAdjointEigenSolver<
88 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>>
90 if (eig.info() != Eigen::Success ||
91 eig.eigenvalues().minCoeff() < ScaleNumerics<Scalar>(-1e-9)) {
97template <
typename Scalar>
98typename std::enable_if<!std::is_floating_point<Scalar>::value,
bool>::type
99checkPSD(
const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>&) {
106#ifdef CROCODDYL_WITH_CODEGEN
107template <
typename Scalar>
108bool isfinite(
const CppAD::AD<Scalar>& value) {
109 return std::isfinite(CppAD::Value(value));
113template <
class Scalar>
114bool isfinite(
const CppAD::AD<CppAD::cg::CG<Scalar>>& x) {
115 return std::isfinite(
static_cast<Scalar
>(CppAD::Value(x).getValue()));
122template <
typename Derived>
123auto pow(
const Eigen::ArrayBase<Derived>& base,
double exponent) {
124 return base.unaryExpr([exponent](
const typename Derived::Scalar& x) {
125 return CppAD::pow(x,
typename Derived::Scalar(exponent));
130template <
typename Derived>
131typename std::enable_if<std::is_base_of<CppAD::cg::CG<typename Derived::Scalar>,
132 typename Derived::Scalar>::value,
133 Eigen::Array<
typename Derived::Scalar, Eigen::Dynamic,
134 Eigen::Dynamic>>::type
135sqrt(
const Eigen::ArrayBase<Derived>& base) {
136 return base.unaryExpr(
137 [](
const typename Derived::Scalar& x) {
return CppAD::sqrt(x); });