Home | History | Annotate | Download | only in ceres
      1 // Ceres Solver - A fast non-linear least squares minimizer
      2 // Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
      3 // http://code.google.com/p/ceres-solver/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are met:
      7 //
      8 // * Redistributions of source code must retain the above copyright notice,
      9 //   this list of conditions and the following disclaimer.
     10 // * Redistributions in binary form must reproduce the above copyright notice,
     11 //   this list of conditions and the following disclaimer in the documentation
     12 //   and/or other materials provided with the distribution.
     13 // * Neither the name of Google Inc. nor the names of its contributors may be
     14 //   used to endorse or promote products derived from this software without
     15 //   specific prior written permission.
     16 //
     17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27 // POSSIBILITY OF SUCH DAMAGE.
     28 //
     29 // Author: keir (at) google.com (Keir Mierle)
     30 //         sameeragarwal (at) google.com (Sameer Agarwal)
     31 
     32 #include "ceres/residual_block.h"
     33 
     34 #include <algorithm>
     35 #include <cstddef>
     36 #include <vector>
     37 #include "ceres/corrector.h"
     38 #include "ceres/parameter_block.h"
     39 #include "ceres/residual_block_utils.h"
     40 #include "ceres/cost_function.h"
     41 #include "ceres/internal/eigen.h"
     42 #include "ceres/internal/fixed_array.h"
     43 #include "ceres/local_parameterization.h"
     44 #include "ceres/loss_function.h"
     45 #include "ceres/small_blas.h"
     46 
     47 using Eigen::Dynamic;
     48 
     49 namespace ceres {
     50 namespace internal {
     51 
     52 ResidualBlock::ResidualBlock(const CostFunction* cost_function,
     53                              const LossFunction* loss_function,
     54                              const vector<ParameterBlock*>& parameter_blocks,
     55                              int index)
     56     : cost_function_(cost_function),
     57       loss_function_(loss_function),
     58       parameter_blocks_(
     59           new ParameterBlock* [
     60               cost_function->parameter_block_sizes().size()]),
     61       index_(index) {
     62   std::copy(parameter_blocks.begin(),
     63             parameter_blocks.end(),
     64             parameter_blocks_.get());
     65 }
     66 
     67 bool ResidualBlock::Evaluate(const bool apply_loss_function,
     68                              double* cost,
     69                              double* residuals,
     70                              double** jacobians,
     71                              double* scratch) const {
     72   const int num_parameter_blocks = NumParameterBlocks();
     73   const int num_residuals = cost_function_->num_residuals();
     74 
     75   // Collect the parameters from their blocks. This will rarely allocate, since
     76   // residuals taking more than 8 parameter block arguments are rare.
     77   FixedArray<const double*, 8> parameters(num_parameter_blocks);
     78   for (int i = 0; i < num_parameter_blocks; ++i) {
     79     parameters[i] = parameter_blocks_[i]->state();
     80   }
     81 
     82   // Put pointers into the scratch space into global_jacobians as appropriate.
     83   FixedArray<double*, 8> global_jacobians(num_parameter_blocks);
     84   if (jacobians != NULL) {
     85     for (int i = 0; i < num_parameter_blocks; ++i) {
     86       const ParameterBlock* parameter_block = parameter_blocks_[i];
     87       if (jacobians[i] != NULL &&
     88           parameter_block->LocalParameterizationJacobian() != NULL) {
     89         global_jacobians[i] = scratch;
     90         scratch += num_residuals * parameter_block->Size();
     91       } else {
     92         global_jacobians[i] = jacobians[i];
     93       }
     94     }
     95   }
     96 
     97   // If the caller didn't request residuals, use the scratch space for them.
     98   bool outputting_residuals = (residuals != NULL);
     99   if (!outputting_residuals) {
    100     residuals = scratch;
    101   }
    102 
    103   // Invalidate the evaluation buffers so that we can check them after
    104   // the CostFunction::Evaluate call, to see if all the return values
    105   // that were required were written to and that they are finite.
    106   double** eval_jacobians = (jacobians != NULL) ? global_jacobians.get() : NULL;
    107 
    108   InvalidateEvaluation(*this, cost, residuals, eval_jacobians);
    109 
    110   if (!cost_function_->Evaluate(parameters.get(), residuals, eval_jacobians)) {
    111     return false;
    112   }
    113 
    114   if (!IsEvaluationValid(*this,
    115                          parameters.get(),
    116                          cost,
    117                          residuals,
    118                          eval_jacobians)) {
    119     string message =
    120         "\n\n"
    121         "Error in evaluating the ResidualBlock.\n\n"
    122         "There are two possible reasons. Either the CostFunction did not evaluate and fill all    \n"  // NOLINT
    123         "residual and jacobians that were requested or there was a non-finite value (nan/infinite)\n"  // NOLINT
    124         "generated during the or jacobian computation. \n\n" +
    125         EvaluationToString(*this,
    126                            parameters.get(),
    127                            cost,
    128                            residuals,
    129                            eval_jacobians);
    130     LOG(WARNING) << message;
    131     return false;
    132   }
    133 
    134   double squared_norm = VectorRef(residuals, num_residuals).squaredNorm();
    135 
    136   // Update the jacobians with the local parameterizations.
    137   if (jacobians != NULL) {
    138     for (int i = 0; i < num_parameter_blocks; ++i) {
    139       if (jacobians[i] != NULL) {
    140         const ParameterBlock* parameter_block = parameter_blocks_[i];
    141 
    142         // Apply local reparameterization to the jacobians.
    143         if (parameter_block->LocalParameterizationJacobian() != NULL) {
    144           // jacobians[i] = global_jacobians[i] * global_to_local_jacobian.
    145           MatrixMatrixMultiply<Dynamic, Dynamic, Dynamic, Dynamic, 0>(
    146               global_jacobians[i],
    147               num_residuals,
    148               parameter_block->Size(),
    149               parameter_block->LocalParameterizationJacobian(),
    150               parameter_block->Size(),
    151               parameter_block->LocalSize(),
    152               jacobians[i], 0, 0,  num_residuals, parameter_block->LocalSize());
    153         }
    154       }
    155     }
    156   }
    157 
    158   if (loss_function_ == NULL || !apply_loss_function) {
    159     *cost = 0.5 * squared_norm;
    160     return true;
    161   }
    162 
    163   double rho[3];
    164   loss_function_->Evaluate(squared_norm, rho);
    165   *cost = 0.5 * rho[0];
    166 
    167   // No jacobians and not outputting residuals? All done. Doing an early exit
    168   // here avoids constructing the "Corrector" object below in a common case.
    169   if (jacobians == NULL && !outputting_residuals) {
    170     return true;
    171   }
    172 
    173   // Correct for the effects of the loss function. The jacobians need to be
    174   // corrected before the residuals, since they use the uncorrected residuals.
    175   Corrector correct(squared_norm, rho);
    176   if (jacobians != NULL) {
    177     for (int i = 0; i < num_parameter_blocks; ++i) {
    178       if (jacobians[i] != NULL) {
    179         const ParameterBlock* parameter_block = parameter_blocks_[i];
    180 
    181         // Correct the jacobians for the loss function.
    182         correct.CorrectJacobian(num_residuals,
    183                                 parameter_block->LocalSize(),
    184                                 residuals,
    185                                 jacobians[i]);
    186       }
    187     }
    188   }
    189 
    190   // Correct the residuals with the loss function.
    191   if (outputting_residuals) {
    192     correct.CorrectResiduals(num_residuals, residuals);
    193   }
    194   return true;
    195 }
    196 
    197 int ResidualBlock::NumScratchDoublesForEvaluate() const {
    198   // Compute the amount of scratch space needed to store the full-sized
    199   // jacobians. For parameters that have no local parameterization  no storage
    200   // is needed and the passed-in jacobian array is used directly. Also include
    201   // space to store the residuals, which is needed for cost-only evaluations.
    202   // This is slightly pessimistic, since both won't be needed all the time, but
    203   // the amount of excess should not cause problems for the caller.
    204   int num_parameters = NumParameterBlocks();
    205   int scratch_doubles = 1;
    206   for (int i = 0; i < num_parameters; ++i) {
    207     const ParameterBlock* parameter_block = parameter_blocks_[i];
    208     if (!parameter_block->IsConstant() &&
    209         parameter_block->LocalParameterizationJacobian() != NULL) {
    210       scratch_doubles += parameter_block->Size();
    211     }
    212   }
    213   scratch_doubles *= NumResiduals();
    214   return scratch_doubles;
    215 }
    216 
    217 }  // namespace internal
    218 }  // namespace ceres
    219