| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 | 
// Ceres Solver - A fast non-linear least squares minimizer// Copyright 2017 Google Inc. All rights reserved.// http://ceres-solver.org///// 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: mierle@gmail.com (Keir Mierle)#include "ceres/tiny_solver_autodiff_function.h"#include "ceres/tiny_solver.h"#include "ceres/tiny_solver_test_util.h"#include <algorithm>#include <cmath>#include <limits>#include "gtest/gtest.h"namespace ceres {struct AutoDiffTestFunctor {  template<typename T>  bool operator()(const T* const parameters, T* residuals) const {    // Shift the parameters so the solution is not at the origin, to prevent    // accidentally showing "PASS".    const T& a = parameters[0] - T(1.0);    const T& b = parameters[1] - T(2.0);    const T& c = parameters[2] - T(3.0);    residuals[0] = 2.*a + 0.*b + 1.*c;    residuals[1] = 0.*a + 4.*b + 6.*c;    return true;  }};// Leave a factor of 10 slop since these tests tend to mysteriously break on// other compilers or architectures if the tolerance is too tight.static double const kTolerance = std::numeric_limits<double>::epsilon() * 10;TEST(TinySolverAutoDiffFunction, SimpleFunction) {  typedef TinySolverAutoDiffFunction<AutoDiffTestFunctor, 2, 3>      AutoDiffTestFunction;  AutoDiffTestFunctor autodiff_test_functor;  AutoDiffTestFunction f(autodiff_test_functor);  Eigen::Vector3d x(2.0, 1.0, 4.0);  Eigen::Vector2d residuals;  // Check the case with cost-only evaluation.  residuals.setConstant(555);  // Arbitrary.  EXPECT_TRUE(f(&x(0), &residuals(0), nullptr));  EXPECT_NEAR(3.0, residuals(0), kTolerance);  EXPECT_NEAR(2.0, residuals(1), kTolerance);  // Check the case with cost and Jacobian evaluation.  Eigen::Matrix<double, 2, 3> jacobian;  residuals.setConstant(555);  // Arbitrary.  jacobian.setConstant(555);  EXPECT_TRUE(f(&x(0), &residuals(0), &jacobian(0, 0)));  // Verify cost.  EXPECT_NEAR(3.0, residuals(0), kTolerance);  EXPECT_NEAR(2.0, residuals(1), kTolerance);  // Verify Jacobian Row 1.  EXPECT_NEAR(2.0, jacobian(0, 0), kTolerance);  EXPECT_NEAR(0.0, jacobian(0, 1), kTolerance);  EXPECT_NEAR(1.0, jacobian(0, 2), kTolerance);  // Verify Jacobian row 2.  EXPECT_NEAR(0.0, jacobian(1, 0), kTolerance);  EXPECT_NEAR(4.0, jacobian(1, 1), kTolerance);  EXPECT_NEAR(6.0, jacobian(1, 2), kTolerance);}class DynamicResidualsFunctor { public:  typedef double Scalar;  enum {    NUM_RESIDUALS = Eigen::Dynamic,    NUM_PARAMETERS = 3,  };  int NumResiduals() const {    return 2;  }  template<typename T>  bool operator()(const T* parameters, T* residuals) const {    // Jacobian is not evaluated by cost function, but by autodiff.    T* jacobian = nullptr;    return EvaluateResidualsAndJacobians(parameters, residuals, jacobian);  }};template<typename Function, typename Vector>void TestHelper(const Function& f, const Vector& x0) {  Vector x = x0;  Eigen::Vector2d residuals;  f(x.data(), residuals.data(), nullptr);  EXPECT_GT(residuals.squaredNorm() / 2.0, 1e-10);  TinySolver<Function> solver;  solver.Solve(f, &x);  EXPECT_NEAR(0.0, solver.summary.final_cost, 1e-10);}// A test case for when the number of residuals is// dynamically sized and we use autodiffTEST(TinySolverAutoDiffFunction, ResidualsDynamicAutoDiff) {  Eigen::Vector3d x0(0.76026643, -30.01799744, 0.55192142);  DynamicResidualsFunctor f;  using AutoDiffCostFunctor =      ceres::TinySolverAutoDiffFunction<DynamicResidualsFunctor,                                        Eigen::Dynamic,                                        3>;  AutoDiffCostFunctor f_autodiff(f);  Eigen::Vector2d residuals;  f_autodiff(x0.data(), residuals.data(), nullptr);  EXPECT_GT(residuals.squaredNorm() / 2.0, 1e-10);  TinySolver<AutoDiffCostFunctor> solver;  solver.Solve(f, &x0);  EXPECT_NEAR(0.0, solver.summary.final_cost, 1e-10);}}  // namespace ceres
 |