/* ---------------------------------------------------------------------------- * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) * See LICENSE for the license information * -------------------------------------------------------------------------- */ /** * @file AdaptAutoDiff.h * @date October 22, 2014 * @author Frank Dellaert * @brief Adaptor for Ceres style auto-differentiated functions */ #pragma once #include #include #include #include #include namespace gtsam { /** * The AdaptAutoDiff class uses ceres-style autodiff to adapt a ceres-style * Function evaluation, i.e., a function FUNCTOR that defines an operator * template bool operator()(const T* const, const T* const, T* * predicted) const; * For now only binary operators are supported. */ template class AdaptAutoDiff { typedef Eigen::Matrix RowMajor1; typedef Eigen::Matrix RowMajor2; typedef Eigen::Matrix VectorT; typedef Eigen::Matrix Vector1; typedef Eigen::Matrix Vector2; FUNCTOR f; public: VectorT operator()(const Vector1& v1, const Vector2& v2, OptionalJacobian H1 = boost::none, OptionalJacobian H2 = boost::none) { using ceres::internal::AutoDiff; bool success; VectorT result; if (H1 || H2) { // Get derivatives with AutoDiff const double* parameters[] = {v1.data(), v2.data()}; double rowMajor1[M * N1], rowMajor2[M * N2]; // on the stack double* jacobians[] = {rowMajor1, rowMajor2}; success = AutoDiff::Differentiate( f, parameters, M, result.data(), jacobians); // Convert from row-major to columnn-major // TODO: if this is a bottleneck (probably not!) fix Autodiff to be // Column-Major if (H1) *H1 = Eigen::Map(rowMajor1); if (H2) *H2 = Eigen::Map(rowMajor2); } else { // Apply the mapping, to get result success = f(v1.data(), v2.data(), result.data()); } if (!success) throw std::runtime_error( "AdaptAutoDiff: function call resulted in failure"); return result; } }; } // namespace gtsam