/// @file /// Numerical differentiation using finite differences #ifndef SOPHUS_NUM_DIFF_HPP #define SOPHUS_NUM_DIFF_HPP #include #include #include #include "types.hpp" namespace Sophus { namespace details { template class Curve { public: template static auto num_diff(Fn curve, Scalar t, Scalar h) -> decltype(curve(t)) { using ReturnType = decltype(curve(t)); static_assert(std::is_floating_point::value, "Scalar must be a floating point type."); static_assert(IsFloatingPoint::value, "ReturnType must be either a floating point scalar, " "vector or matrix."); return (curve(t + h) - curve(t - h)) / (Scalar(2) * h); } }; template class VectorField { public: static Eigen::Matrix num_diff( std::function(Sophus::Vector)> vector_field, Sophus::Vector const& a, Scalar eps) { static_assert(std::is_floating_point::value, "Scalar must be a floating point type."); Eigen::Matrix J; Sophus::Vector h; h.setZero(); for (int i = 0; i < M; ++i) { h[i] = eps; J.col(i) = (vector_field(a + h) - vector_field(a - h)) / (Scalar(2) * eps); h[i] = Scalar(0); } return J; } }; template class VectorField { public: static Eigen::Matrix num_diff( std::function(Scalar)> vector_field, Scalar const& a, Scalar eps) { return details::Curve::num_diff(std::move(vector_field), a, eps); } }; } // namespace details /// Calculates the derivative of a curve at a point ``t``. /// /// Here, a curve is a function from a Scalar to a Euclidean space. Thus, it /// returns either a Scalar, a vector or a matrix. /// template auto curveNumDiff(Fn curve, Scalar t, Scalar h = Constants::epsilonSqrt()) -> decltype(details::Curve::num_diff(std::move(curve), t, h)) { return details::Curve::num_diff(std::move(curve), t, h); } /// Calculates the derivative of a vector field at a point ``a``. /// /// Here, a vector field is a function from a vector space to another vector /// space. /// template Eigen::Matrix vectorFieldNumDiff( Fn vector_field, ScalarOrVector const& a, Scalar eps = Constants::epsilonSqrt()) { return details::VectorField::num_diff(std::move(vector_field), a, eps); } } // namespace Sophus #endif // SOPHUS_NUM_DIFF_HPP