Remove NumericDiffFunctor. Its API was broken, and its implementation was an unnecessary layer of abstraction over CostFunctionToFunctor. Change-Id: I18fc261fc6a3620b51a9eeb4dde0af03d753af69
diff --git a/docs/source/modeling.rst b/docs/source/modeling.rst index 5bbd441..4b333c4 100644 --- a/docs/source/modeling.rst +++ b/docs/source/modeling.rst
@@ -567,105 +567,15 @@ As a rule of thumb, try using :class:`NumericDiffCostFunction` before you use :class:`DynamicNumericDiffCostFunction`. - -:class:`NumericDiffFunctor` ---------------------------- - -.. class:: NumericDiffFunctor - - Sometimes parts of a cost function can be differentiated - automatically or analytically but others require numeric - differentiation. :class:`NumericDiffFunctor` is a wrapper class - that takes a variadic functor evaluating a function, numerically - differentiates it and makes it available as a templated functor so - that it can be easily used as part of Ceres' automatic - differentiation framework. - - For example, let us assume that - - .. code-block:: c++ - - struct IntrinsicProjection - IntrinsicProjection(const double* observations); - bool operator()(const double* calibration, - const double* point, - double* residuals); - }; - - is a functor that implements the projection of a point in its local - coordinate system onto its image plane and subtracts it from the - observed point projection. - - Now we would like to compose the action of this functor with the - action of camera extrinsics, i.e., rotation and translation, which - is given by the following templated function - - .. code-block:: c++ - - template<typename T> - void RotateAndTranslatePoint(const T* rotation, - const T* translation, - const T* point, - T* result); - - To compose the extrinsics and intrinsics, we can construct a - ``CameraProjection`` functor as follows. - - .. code-block:: c++ - - struct CameraProjection { - typedef NumericDiffFunctor<IntrinsicProjection, CENTRAL, 2, 5, 3> - IntrinsicProjectionFunctor; - - CameraProjection(double* observation) { - intrinsic_projection_.reset( - new IntrinsicProjectionFunctor(observation)) { - } - - template <typename T> - bool operator()(const T* rotation, - const T* translation, - const T* intrinsics, - const T* point, - T* residuals) const { - T transformed_point[3]; - RotateAndTranslatePoint(rotation, translation, point, transformed_point); - return (*intrinsic_projection_)(intrinsics, transformed_point, residual); - } - - private: - scoped_ptr<IntrinsicProjectionFunctor> intrinsic_projection_; - }; - - Here, we made the choice of using ``CENTRAL`` differences to compute - the jacobian of ``IntrinsicProjection``. - - Now, we are ready to construct an automatically differentiated cost - function as - - .. code-block:: c++ - - CostFunction* cost_function = - new AutoDiffCostFunction<CameraProjection, 2, 3, 3, 5>( - new CameraProjection(observations)); - - ``cost_function`` now seamlessly integrates automatic - differentiation of ``RotateAndTranslatePoint`` with a numerically - differentiated version of ``IntrinsicProjection``. - - :class:`CostFunctionToFunctor` ------------------------------ .. class:: CostFunctionToFunctor - Just like :class:`NumericDiffFunctor` allows numeric - differentiation to be mixed with automatic differentiation, - :class:`CostFunctionToFunctor` provides an even more general - mechanism. :class:`CostFunctionToFunctor` is an adapter class that - allows users to use :class:`CostFunction` objects in templated - functors which are to be used for automatic differentiation. This - allows the user to seamlessly mix analytic, numeric and automatic + :class:`CostFunctionToFunctor` is an adapter class that allows + users to use :class:`CostFunction` objects in templated functors + which are to be used for automatic differentiation. This allows + the user to seamlessly mix analytic, numeric and automatic differentiation. For example, let us assume that @@ -704,10 +614,10 @@ .. code-block:: c++ struct CameraProjection { - CameraProjection(double* observation) { - intrinsic_projection_.reset( - new CostFunctionToFunctor<2, 5, 3>(new IntrinsicProjection(observation_))); + CameraProjection(double* observation) + : intrinsic_projection_(new IntrinsicProjection(observation_)) { } + template <typename T> bool operator()(const T* rotation, const T* translation, @@ -719,14 +629,71 @@ // Note that we call intrinsic_projection_, just like it was // any other templated functor. - return (*intrinsic_projection_)(intrinsics, transformed_point, residual); + return intrinsic_projection_(intrinsics, transformed_point, residual); } private: - scoped_ptr<CostFunctionToFunctor<2,5,3> > intrinsic_projection_; + CostFunctionToFunctor<2,5,3> intrinsic_projection_; }; + In the above example, we assumed that ``IntrinsicProjection`` is a + ``CostFunction`` capable of evaluating its value and its + derivatives. Suppose, if that were not the case and + ``IntrinsicProjection`` was defined as follows: + + .. code-block:: c++ + + struct IntrinsicProjection + IntrinsicProjection(const double* observations) { + observations_[0] = observations[0]; + observations_[1] = observations[1]; + } + + bool operator()(const double* calibration, + const double* point, + double* residuals) { + double projection[2]; + ThirdPartyProjectionFunction(calibration, point, projection); + residuals[0] = observations_[0] - projection[0]; + residuals[1] = observations_[1] - projection[1]; + return true; + } + double observations_[2]; + }; + + + Here ``ThirdPartyProjectionFunction`` is some third party library + function that we have no control over. So this function can compute + its value and we would like to use numeric differentiation to + compute its derivatives. In this case we can use a combination of + ``NumericDiffCostFunction`` and ``CostFunctionToFunctor`` to get the + job done. + + .. code-block:: c++ + + struct CameraProjection { + CameraProjection(double* observation) + intrinsic_projection_( + new NumericDiffCostFunction<IntrinsicProjection, CENTRAL, 2, 5, 3>( + new IntrinsicProjection(observations)) { + } + + template <typename T> + bool operator()(const T* rotation, + const T* translation, + const T* intrinsics, + const T* point, + T* residuals) const { + T transformed_point[3]; + RotateAndTranslatePoint(rotation, translation, point, transformed_point); + return intrinsic_projection_(intrinsics, transformed_point, residual); + } + + private: + CostFunctionToFunctor<2,5,3> intrinsic_projection_; + }; + :class:`ConditionedCostFunction` --------------------------------
diff --git a/docs/source/version_history.rst b/docs/source/version_history.rst index 8853fb7..cbbad65 100644 --- a/docs/source/version_history.rst +++ b/docs/source/version_history.rst
@@ -16,6 +16,10 @@ Backward Incompatible API Changes --------------------------------- +#. ``NumericDiffFunctor`` has been removed. It's API was broken, and + the implementation was an unnecessary layer of abstraction over + ``CostFunctionToFunctor``. + #. ``Solver::Options::solver_log`` has been removed. If needed this iteration callback can easily be implemented in user code.
diff --git a/include/ceres/numeric_diff_functor.h b/include/ceres/numeric_diff_functor.h deleted file mode 100644 index a29eb97..0000000 --- a/include/ceres/numeric_diff_functor.h +++ /dev/null
@@ -1,351 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2013 Google Inc. All rights reserved. -// http://code.google.com/p/ceres-solver/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Author: sameeragarwal@google.com (Sameer Agarwal) -// -// A wrapper class that takes a variadic functor evaluating a -// function, numerically differentiates it and makes it available as a -// templated functor so that it can be easily used as part of Ceres' -// automatic differentiation framework. -// -// For example: -// -// For example, let us assume that -// -// struct IntrinsicProjection -// IntrinsicProjection(const double* observations); -// bool operator()(const double* calibration, -// const double* point, -// double* residuals); -// }; -// -// is a functor that implements the projection of a point in its local -// coordinate system onto its image plane and subtracts it from the -// observed point projection. -// -// Now we would like to compose the action of this functor with the -// action of camera extrinsics, i.e., rotation and translation, which -// is given by the following templated function -// -// template<typename T> -// void RotateAndTranslatePoint(const T* rotation, -// const T* translation, -// const T* point, -// T* result); -// -// To compose the extrinsics and intrinsics, we can construct a -// CameraProjection functor as follows. -// -// struct CameraProjection { -// typedef NumericDiffFunctor<IntrinsicProjection, CENTRAL, 2, 5, 3> -// IntrinsicProjectionFunctor; -// -// CameraProjection(double* observation) { -// intrinsic_projection_.reset( -// new IntrinsicProjectionFunctor(observation)) { -// } -// -// template <typename T> -// bool operator()(const T* rotation, -// const T* translation, -// const T* intrinsics, -// const T* point, -// T* residuals) const { -// T transformed_point[3]; -// RotateAndTranslatePoint(rotation, translation, point, transformed_point); -// return (*intrinsic_projection_)(intrinsics, transformed_point, residual); -// } -// -// private: -// scoped_ptr<IntrinsicProjectionFunctor> intrinsic_projection_; -// }; -// -// Here, we made the choice of using CENTRAL differences to compute -// the jacobian of IntrinsicProjection. -// -// Now, we are ready to construct an automatically differentiated cost -// function as -// -// CostFunction* cost_function = -// new AutoDiffCostFunction<CameraProjection, 2, 3, 3, 5>( -// new CameraProjection(observations)); -// -// cost_function now seamlessly integrates automatic differentiation -// of RotateAndTranslatePoint with a numerically differentiated -// version of IntrinsicProjection. - -#ifndef CERES_PUBLIC_NUMERIC_DIFF_FUNCTOR_H_ -#define CERES_PUBLIC_NUMERIC_DIFF_FUNCTOR_H_ - -#include "ceres/numeric_diff_cost_function.h" -#include "ceres/types.h" -#include "ceres/cost_function_to_functor.h" - -namespace ceres { - -template<typename Functor, - NumericDiffMethod kMethod = CENTRAL, - int kNumResiduals = 0, - int N0 = 0, int N1 = 0 , int N2 = 0, int N3 = 0, int N4 = 0, - int N5 = 0, int N6 = 0 , int N7 = 0, int N8 = 0, int N9 = 0> -class NumericDiffFunctor { - public: - // relative_step_size controls the step size used by the numeric - // differentiation process. - explicit NumericDiffFunctor(double relative_step_size = 1e-6) - : functor_( - new NumericDiffCostFunction<Functor, - kMethod, - kNumResiduals, - N0, N1, N2, N3, N4, - N5, N6, N7, N8, N9>(new Functor, - TAKE_OWNERSHIP, - kNumResiduals, - relative_step_size)) { - } - - NumericDiffFunctor(Functor* functor, double relative_step_size = 1e-6) - : functor_(new NumericDiffCostFunction<Functor, - kMethod, - kNumResiduals, - N0, N1, N2, N3, N4, - N5, N6, N7, N8, N9>( - functor, - TAKE_OWNERSHIP, - kNumResiduals, - relative_step_size)) { - } - - bool operator()(const double* x0, double* residuals) const { - return functor_(x0, residuals); - } - - bool operator()(const double* x0, - const double* x1, - double* residuals) const { - return functor_(x0, x1, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - double* residuals) const { - return functor_(x0, x1, x2, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - double* residuals) const { - return functor_(x0, x1, x2, x3, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - const double* x5, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - const double* x5, - const double* x6, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - const double* x5, - const double* x6, - const double* x7, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - const double* x5, - const double* x6, - const double* x7, - const double* x8, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - const double* x5, - const double* x6, - const double* x7, - const double* x8, - const double* x9, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, residuals); - } - - template <typename T> - bool operator()(const T* x0, T* residuals) const { - return functor_(x0, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - T* residuals) const { - return functor_(x0, x1, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - T* residuals) const { - return functor_(x0, x1, x2, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - T* residuals) const { - return functor_(x0, x1, x2, x3, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - const T* x5, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - const T* x5, - const T* x6, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - const T* x5, - const T* x6, - const T* x7, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - const T* x5, - const T* x6, - const T* x7, - const T* x8, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - const T* x5, - const T* x6, - const T* x7, - const T* x8, - const T* x9, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, residuals); - } - - - private: - CostFunctionToFunctor<kNumResiduals, - N0, N1, N2, N3, N4, - N5, N6, N7, N8, N9> functor_; -}; - -} // namespace ceres - -#endif // CERES_PUBLIC_NUMERIC_DIFF_FUNCTOR_H_
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt index 85b4906..ec9dee3 100644 --- a/internal/ceres/CMakeLists.txt +++ b/internal/ceres/CMakeLists.txt
@@ -263,7 +263,6 @@ CERES_TEST(minimizer) CERES_TEST(normal_prior) CERES_TEST(numeric_diff_cost_function) - CERES_TEST(numeric_diff_functor) CERES_TEST(ordered_groups) CERES_TEST(parameter_block) CERES_TEST(parameter_block_ordering)
diff --git a/internal/ceres/numeric_diff_functor_test.cc b/internal/ceres/numeric_diff_functor_test.cc deleted file mode 100644 index acd7ff9..0000000 --- a/internal/ceres/numeric_diff_functor_test.cc +++ /dev/null
@@ -1,125 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2013 Google Inc. All rights reserved. -// http://code.google.com/p/ceres-solver/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Author: sameeragarwal@google.com (Sameer Agarwal) - -#include "ceres/numeric_diff_functor.h" - -#include <algorithm> -#include <cmath> -#include <string> -#include <vector> -#include "ceres/autodiff_cost_function.h" -#include "ceres/internal/scoped_ptr.h" -#include "ceres/numeric_diff_test_utils.h" -#include "ceres/test_util.h" -#include "ceres/types.h" -#include "glog/logging.h" -#include "gtest/gtest.h" - -namespace ceres { -namespace internal { - -TEST(NumericDiffCostFunction, EasyCaseCentralDifferences) { - typedef NumericDiffFunctor<EasyFunctor, CENTRAL, 3, 5, 5> - NumericDiffEasyFunctor; - - internal::scoped_ptr<CostFunction> cost_function; - EasyFunctor functor; - - cost_function.reset( - new AutoDiffCostFunction<NumericDiffEasyFunctor, 3, 5, 5>( - new NumericDiffEasyFunctor)); - - functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, CENTRAL); - - cost_function.reset( - new AutoDiffCostFunction<NumericDiffEasyFunctor, 3, 5, 5>( - new NumericDiffEasyFunctor(new EasyFunctor))); - functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, CENTRAL); -} - -TEST(NumericDiffCostFunction, EasyCaseForwardDifferences) { - typedef NumericDiffFunctor<EasyFunctor, FORWARD, 3, 5, 5> - NumericDiffEasyFunctor; - - internal::scoped_ptr<CostFunction> cost_function; - EasyFunctor functor; - - cost_function.reset( - new AutoDiffCostFunction<NumericDiffEasyFunctor, 3, 5, 5>( - new NumericDiffEasyFunctor)); - - functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, FORWARD); - - cost_function.reset( - new AutoDiffCostFunction<NumericDiffEasyFunctor, 3, 5, 5>( - new NumericDiffEasyFunctor(new EasyFunctor))); - functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, FORWARD); -} - -TEST(NumericDiffCostFunction, TranscendentalCaseCentralDifferences) { - typedef NumericDiffFunctor<TranscendentalFunctor, CENTRAL, 2, 5, 5> - NumericDiffTranscendentalFunctor; - - internal::scoped_ptr<CostFunction> cost_function; - TranscendentalFunctor functor; - - cost_function.reset( - new AutoDiffCostFunction<NumericDiffTranscendentalFunctor, 2, 5, 5>( - new NumericDiffTranscendentalFunctor)); - - functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, CENTRAL); - - cost_function.reset( - new AutoDiffCostFunction<NumericDiffTranscendentalFunctor, 2, 5, 5>( - new NumericDiffTranscendentalFunctor(new TranscendentalFunctor))); - functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, CENTRAL); -} - -TEST(NumericDiffCostFunction, TranscendentalCaseForwardDifferences) { - typedef NumericDiffFunctor<TranscendentalFunctor, FORWARD, 2, 5, 5> - NumericDiffTranscendentalFunctor; - - internal::scoped_ptr<CostFunction> cost_function; - TranscendentalFunctor functor; - - cost_function.reset( - new AutoDiffCostFunction<NumericDiffTranscendentalFunctor, 2, 5, 5>( - new NumericDiffTranscendentalFunctor)); - - functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, FORWARD); - - cost_function.reset( - new AutoDiffCostFunction<NumericDiffTranscendentalFunctor, 2, 5, 5>( - new NumericDiffTranscendentalFunctor(new TranscendentalFunctor))); - functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, FORWARD); -} - -} // namespace internal -} // namespace ceres