10ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Ceres Solver - A fast non-linear least squares minimizer 20ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. 30ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// http://code.google.com/p/ceres-solver/ 40ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 50ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Redistribution and use in source and binary forms, with or without 60ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// modification, are permitted provided that the following conditions are met: 70ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 80ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions of source code must retain the above copyright notice, 90ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// this list of conditions and the following disclaimer. 100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions in binary form must reproduce the above copyright notice, 110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// this list of conditions and the following disclaimer in the documentation 120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// and/or other materials provided with the distribution. 130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Neither the name of Google Inc. nor the names of its contributors may be 140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// used to endorse or promote products derived from this software without 150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// specific prior written permission. 160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// POSSIBILITY OF SUCH DAMAGE. 280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Copyright 2007 Google Inc. All Rights Reserved. 290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Author: wjr@google.com (William Rucklidge) 310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// This file contains a class that exercises a cost function, to make sure 330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// that it is computing reasonable derivatives. It compares the Jacobians 340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// computed by the cost function with those obtained by finite 350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// differences. 360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#ifndef CERES_PUBLIC_GRADIENT_CHECKER_H_ 380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#define CERES_PUBLIC_GRADIENT_CHECKER_H_ 390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <cstddef> 411d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#include <algorithm> 420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <vector> 430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/internal/eigen.h" 450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/internal/fixed_array.h" 460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/internal/macros.h" 470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/internal/scoped_ptr.h" 480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/numeric_diff_cost_function.h" 491d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#include "glog/logging.h" 500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace ceres { 520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// An object that exercises a cost function, to compare the answers that it 540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// gives with derivatives estimated using finite differencing. 550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// The only likely usage of this is for testing. 570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// How to use: Fill in an array of pointers to parameter blocks for your 590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CostFunction, and then call Probe(). Check that the return value is 600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 'true'. See prober_test.cc for an example. 610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// This is templated similarly to NumericDiffCostFunction, as it internally 630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// uses that. 640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate <typename CostFunctionToProbe, 650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong int M = 0, int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0> 660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongclass GradientChecker { 670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong public: 680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Here we stash some results from the probe, for later 690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // inspection. 700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong struct GradientCheckResults { 710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Computed cost. 720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong Vector cost; 730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // The sizes of these matrices are dictated by the cost function's 750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // parameter and residual block sizes. Each vector's length will 760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // term->parameter_block_sizes().size(), and each matrix is the 770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Jacobian of the residual with respect to the corresponding parameter 780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // block. 790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Derivatives as computed by the cost function. 810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong vector<Matrix> term_jacobians; 820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Derivatives as computed by finite differencing. 840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong vector<Matrix> finite_difference_jacobians; 850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Infinity-norm of term_jacobians - finite_difference_jacobians. 870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double error_jacobians; 880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong }; 890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Checks the Jacobian computed by a cost function. 910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // 920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // probe_point: The parameter values at which to probe. 930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // error_tolerance: A threshold for the infinity-norm difference 940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // between the Jacobians. If the Jacobians differ by more than 950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // this amount, then the probe fails. 960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // 970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // term: The cost function to test. Not retained after this call returns. 980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // 990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // results: On return, the two Jacobians (and other information) 1000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // will be stored here. May be NULL. 1010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // 1020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Returns true if no problems are detected and the difference between the 1030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Jacobians is less than error_tolerance. 1040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong static bool Probe(double const* const* probe_point, 1050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double error_tolerance, 1060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CostFunctionToProbe *term, 1070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong GradientCheckResults* results) { 1080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_NOTNULL(probe_point); 1090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_NOTNULL(term); 1100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << "-------------------- Starting Probe() --------------------"; 1110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // We need a GradientCheckeresults, whether or not they supplied one. 1130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong internal::scoped_ptr<GradientCheckResults> owned_results; 1140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (results == NULL) { 1150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong owned_results.reset(new GradientCheckResults); 1160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results = owned_results.get(); 1170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Do a consistency check between the term and the template parameters. 1200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_EQ(M, term->num_residuals()); 1210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong const int num_residuals = M; 12279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez const vector<int32>& block_sizes = term->parameter_block_sizes(); 1230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong const int num_blocks = block_sizes.size(); 1240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_LE(num_blocks, 5) << "Unable to test functions that take more " 1260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong << "than 5 parameter blocks"; 1270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (N0) { 1280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_EQ(N0, block_sizes[0]); 1290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_GE(num_blocks, 1); 1300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } else { 1310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_LT(num_blocks, 1); 1320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (N1) { 1340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_EQ(N1, block_sizes[1]); 1350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_GE(num_blocks, 2); 1360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } else { 1370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_LT(num_blocks, 2); 1380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (N2) { 1400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_EQ(N2, block_sizes[2]); 1410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_GE(num_blocks, 3); 1420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } else { 1430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_LT(num_blocks, 3); 1440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (N3) { 1460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_EQ(N3, block_sizes[3]); 1470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_GE(num_blocks, 4); 1480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } else { 1490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_LT(num_blocks, 4); 1500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (N4) { 1520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_EQ(N4, block_sizes[4]); 1530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_GE(num_blocks, 5); 1540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } else { 1550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK_LT(num_blocks, 5); 1560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->term_jacobians.clear(); 1590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->term_jacobians.resize(num_blocks); 1600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->finite_difference_jacobians.clear(); 1610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->finite_difference_jacobians.resize(num_blocks); 1620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong internal::FixedArray<double*> term_jacobian_pointers(num_blocks); 1641d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling internal::FixedArray<double*> 1651d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling finite_difference_jacobian_pointers(num_blocks); 1660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong for (int i = 0; i < num_blocks; i++) { 1670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->term_jacobians[i].resize(num_residuals, block_sizes[i]); 1680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong term_jacobian_pointers[i] = results->term_jacobians[i].data(); 1690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->finite_difference_jacobians[i].resize( 1700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong num_residuals, block_sizes[i]); 1710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong finite_difference_jacobian_pointers[i] = 1720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->finite_difference_jacobians[i].data(); 1730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->cost.resize(num_residuals, 1); 1750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK(term->Evaluate(probe_point, results->cost.data(), 1770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong term_jacobian_pointers.get())); 1780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong NumericDiffCostFunction<CostFunctionToProbe, CENTRAL, M, N0, N1, N2, N3, N4> 1790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong numeric_term(term, DO_NOT_TAKE_OWNERSHIP); 1800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK(numeric_term.Evaluate(probe_point, results->cost.data(), 1810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong finite_difference_jacobian_pointers.get())); 1820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->error_jacobians = 0; 1840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong for (int i = 0; i < num_blocks; i++) { 1850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong Matrix jacobian_difference = results->term_jacobians[i] - 1860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->finite_difference_jacobians[i]; 1870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->error_jacobians = 1880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong std::max(results->error_jacobians, 1890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong jacobian_difference.lpNorm<Eigen::Infinity>()); 1900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << "========== term-computed derivatives =========="; 1930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong for (int i = 0; i < num_blocks; i++) { 1940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << "term_computed block " << i; 1950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << "\n" << results->term_jacobians[i]; 1960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << "========== finite-difference derivatives =========="; 1990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong for (int i = 0; i < num_blocks; i++) { 2000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << "finite_difference block " << i; 2010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << "\n" << results->finite_difference_jacobians[i]; 2020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 2030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 2040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << "========== difference =========="; 2050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong for (int i = 0; i < num_blocks; i++) { 2060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << "difference block " << i; 2070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << (results->term_jacobians[i] - 2080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong results->finite_difference_jacobians[i]); 2090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 2100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 2110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong LOG(INFO) << "||difference|| = " << results->error_jacobians; 2120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 2130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return results->error_jacobians < error_tolerance; 2140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 2150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 2160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong private: 2170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CERES_DISALLOW_IMPLICIT_CONSTRUCTORS(GradientChecker); 2180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}; 2190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 2200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} // namespace ceres 2210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 2220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#endif // CERES_PUBLIC_GRADIENT_CHECKER_H_ 223