Blame include/ceres/dynamic_cost_function_to_functor.h

Packit ea1746
// Ceres Solver - A fast non-linear least squares minimizer
Packit ea1746
// Copyright 2015 Google Inc. All rights reserved.
Packit ea1746
// http://ceres-solver.org/
Packit ea1746
//
Packit ea1746
// Redistribution and use in source and binary forms, with or without
Packit ea1746
// modification, are permitted provided that the following conditions are met:
Packit ea1746
//
Packit ea1746
// * Redistributions of source code must retain the above copyright notice,
Packit ea1746
//   this list of conditions and the following disclaimer.
Packit ea1746
// * Redistributions in binary form must reproduce the above copyright notice,
Packit ea1746
//   this list of conditions and the following disclaimer in the documentation
Packit ea1746
//   and/or other materials provided with the distribution.
Packit ea1746
// * Neither the name of Google Inc. nor the names of its contributors may be
Packit ea1746
//   used to endorse or promote products derived from this software without
Packit ea1746
//   specific prior written permission.
Packit ea1746
//
Packit ea1746
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit ea1746
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit ea1746
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit ea1746
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
Packit ea1746
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit ea1746
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit ea1746
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit ea1746
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Packit ea1746
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit ea1746
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit ea1746
// POSSIBILITY OF SUCH DAMAGE.
Packit ea1746
//
Packit ea1746
// Author: sameeragarwal@google.com (Sameer Agarwal)
Packit ea1746
//         dgossow@google.com (David Gossow)
Packit ea1746
Packit ea1746
#ifndef CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
Packit ea1746
#define CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
Packit ea1746
Packit ea1746
#include <numeric>
Packit ea1746
#include <vector>
Packit ea1746
Packit ea1746
#include "ceres/dynamic_cost_function.h"
Packit ea1746
#include "ceres/internal/fixed_array.h"
Packit ea1746
#include "ceres/internal/port.h"
Packit ea1746
#include "ceres/internal/scoped_ptr.h"
Packit ea1746
Packit ea1746
namespace ceres {
Packit ea1746
Packit ea1746
// DynamicCostFunctionToFunctor allows users to use CostFunction
Packit ea1746
// objects in templated functors which are to be used for automatic
Packit ea1746
// differentiation. It works similar to CostFunctionToFunctor, with the
Packit ea1746
// difference that it allows you to wrap a cost function with dynamic numbers
Packit ea1746
// of parameters and residuals.
Packit ea1746
//
Packit ea1746
// For example, let us assume that
Packit ea1746
//
Packit ea1746
//  class IntrinsicProjection : public CostFunction {
Packit ea1746
//    public:
Packit ea1746
//      IntrinsicProjection(const double* observation);
Packit ea1746
//      virtual bool Evaluate(double const* const* parameters,
Packit ea1746
//                            double* residuals,
Packit ea1746
//                            double** jacobians) const;
Packit ea1746
//  };
Packit ea1746
//
Packit ea1746
// is a cost function that implements the projection of a point in its
Packit ea1746
// local coordinate system onto its image plane and subtracts it from
Packit ea1746
// the observed point projection. It can compute its residual and
Packit ea1746
// either via analytic or numerical differentiation can compute its
Packit ea1746
// jacobians. The intrinsics are passed in as parameters[0] and the point as
Packit ea1746
// parameters[1].
Packit ea1746
//
Packit ea1746
// Now we would like to compose the action of this CostFunction with
Packit ea1746
// the action of camera extrinsics, i.e., rotation and
Packit ea1746
// translation. Say we have a templated function
Packit ea1746
//
Packit ea1746
//   template<typename T>
Packit ea1746
//   void RotateAndTranslatePoint(double const* const* parameters,
Packit ea1746
//                                double* residuals);
Packit ea1746
//
Packit ea1746
// Then we can now do the following,
Packit ea1746
//
Packit ea1746
// struct CameraProjection {
Packit ea1746
//   CameraProjection(const double* observation)
Packit ea1746
//       : intrinsic_projection_.(new IntrinsicProjection(observation)) {
Packit ea1746
//   }
Packit ea1746
//   template <typename T>
Packit ea1746
//   bool operator()(T const* const* parameters,
Packit ea1746
//                   T* residual) const {
Packit ea1746
//     const T* rotation = parameters[0];
Packit ea1746
//     const T* translation = parameters[1];
Packit ea1746
//     const T* intrinsics = parameters[2];
Packit ea1746
//     const T* point = parameters[3];
Packit ea1746
//     T transformed_point[3];
Packit ea1746
//     RotateAndTranslatePoint(rotation, translation, point, transformed_point);
Packit ea1746
//
Packit ea1746
//     // Note that we call intrinsic_projection_, just like it was
Packit ea1746
//     // any other templated functor.
Packit ea1746
//     const T* projection_parameters[2];
Packit ea1746
//     projection_parameters[0] = intrinsics;
Packit ea1746
//     projection_parameters[1] = transformed_point;
Packit ea1746
//     return intrinsic_projection_(projection_parameters, residual);
Packit ea1746
//   }
Packit ea1746
//
Packit ea1746
//  private:
Packit ea1746
//   DynamicCostFunctionToFunctor intrinsic_projection_;
Packit ea1746
// };
Packit ea1746
class DynamicCostFunctionToFunctor {
Packit ea1746
 public:
Packit ea1746
  // Takes ownership of cost_function.
Packit ea1746
  explicit DynamicCostFunctionToFunctor(CostFunction* cost_function)
Packit ea1746
      : cost_function_(cost_function) {
Packit ea1746
    CHECK_NOTNULL(cost_function);
Packit ea1746
  }
Packit ea1746
Packit ea1746
  bool operator()(double const* const* parameters, double* residuals) const {
Packit ea1746
    return cost_function_->Evaluate(parameters, residuals, NULL);
Packit ea1746
  }
Packit ea1746
Packit ea1746
  template <typename JetT>
Packit ea1746
  bool operator()(JetT const* const* inputs, JetT* output) const {
Packit ea1746
    const std::vector<int32>& parameter_block_sizes =
Packit ea1746
        cost_function_->parameter_block_sizes();
Packit ea1746
    const int num_parameter_blocks =
Packit ea1746
        static_cast<int>(parameter_block_sizes.size());
Packit ea1746
    const int num_residuals = cost_function_->num_residuals();
Packit ea1746
    const int num_parameters = std::accumulate(parameter_block_sizes.begin(),
Packit ea1746
                                               parameter_block_sizes.end(), 0);
Packit ea1746
Packit ea1746
    internal::FixedArray<double> parameters(num_parameters);
Packit ea1746
    internal::FixedArray<double*> parameter_blocks(num_parameter_blocks);
Packit ea1746
    internal::FixedArray<double> jacobians(num_residuals * num_parameters);
Packit ea1746
    internal::FixedArray<double*> jacobian_blocks(num_parameter_blocks);
Packit ea1746
    internal::FixedArray<double> residuals(num_residuals);
Packit ea1746
Packit ea1746
    // Build a set of arrays to get the residuals and jacobians from
Packit ea1746
    // the CostFunction wrapped by this functor.
Packit ea1746
    double* parameter_ptr = parameters.get();
Packit ea1746
    double* jacobian_ptr = jacobians.get();
Packit ea1746
    for (int i = 0; i < num_parameter_blocks; ++i) {
Packit ea1746
      parameter_blocks[i] = parameter_ptr;
Packit ea1746
      jacobian_blocks[i] = jacobian_ptr;
Packit ea1746
      for (int j = 0; j < parameter_block_sizes[i]; ++j) {
Packit ea1746
        *parameter_ptr++ = inputs[i][j].a;
Packit ea1746
      }
Packit ea1746
      jacobian_ptr += num_residuals * parameter_block_sizes[i];
Packit ea1746
    }
Packit ea1746
Packit ea1746
    if (!cost_function_->Evaluate(parameter_blocks.get(),
Packit ea1746
                                  residuals.get(),
Packit ea1746
                                  jacobian_blocks.get())) {
Packit ea1746
      return false;
Packit ea1746
    }
Packit ea1746
Packit ea1746
    // Now that we have the incoming Jets, which are carrying the
Packit ea1746
    // partial derivatives of each of the inputs w.r.t to some other
Packit ea1746
    // underlying parameters. The derivative of the outputs of the
Packit ea1746
    // cost function w.r.t to the same underlying parameters can now
Packit ea1746
    // be computed by applying the chain rule.
Packit ea1746
    //
Packit ea1746
    //  d output[i]               d output[i]   d input[j]
Packit ea1746
    //  --------------  = sum_j   ----------- * ------------
Packit ea1746
    //  d parameter[k]            d input[j]    d parameter[k]
Packit ea1746
    //
Packit ea1746
    // d input[j]
Packit ea1746
    // --------------  = inputs[j], so
Packit ea1746
    // d parameter[k]
Packit ea1746
    //
Packit ea1746
    //  outputJet[i]  = sum_k jacobian[i][k] * inputJet[k]
Packit ea1746
    //
Packit ea1746
    // The following loop, iterates over the residuals, computing one
Packit ea1746
    // output jet at a time.
Packit ea1746
    for (int i = 0; i < num_residuals; ++i) {
Packit ea1746
      output[i].a = residuals[i];
Packit ea1746
      output[i].v.setZero();
Packit ea1746
Packit ea1746
      for (int j = 0; j < num_parameter_blocks; ++j) {
Packit ea1746
        const int32 block_size = parameter_block_sizes[j];
Packit ea1746
        for (int k = 0; k < parameter_block_sizes[j]; ++k) {
Packit ea1746
          output[i].v +=
Packit ea1746
              jacobian_blocks[j][i * block_size + k] * inputs[j][k].v;
Packit ea1746
        }
Packit ea1746
      }
Packit ea1746
    }
Packit ea1746
Packit ea1746
    return true;
Packit ea1746
  }
Packit ea1746
Packit ea1746
 private:
Packit ea1746
  internal::scoped_ptr<CostFunction> cost_function_;
Packit ea1746
};
Packit ea1746
Packit ea1746
}  // namespace ceres
Packit ea1746
Packit ea1746
#endif  // CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_