dynamic_cost_function_to_functor.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Ceres Solver - A fast non-linear least squares minimizer
  2. // Copyright 2019 Google Inc. All rights reserved.
  3. // http://ceres-solver.org/
  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: sameeragarwal@google.com (Sameer Agarwal)
  30. // dgossow@google.com (David Gossow)
  31. #ifndef CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
  32. #define CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
  33. #include <memory>
  34. #include <numeric>
  35. #include <vector>
  36. #include "ceres/dynamic_cost_function.h"
  37. #include "ceres/internal/disable_warnings.h"
  38. #include "ceres/internal/export.h"
  39. #include "ceres/internal/fixed_array.h"
  40. #include "glog/logging.h"
  41. namespace ceres {
  42. // DynamicCostFunctionToFunctor allows users to use CostFunction
  43. // objects in templated functors which are to be used for automatic
  44. // differentiation. It works similar to CostFunctionToFunctor, with the
  45. // difference that it allows you to wrap a cost function with dynamic numbers
  46. // of parameters and residuals.
  47. //
  48. // For example, let us assume that
  49. //
  50. // class IntrinsicProjection : public CostFunction {
  51. // public:
  52. // IntrinsicProjection(const double* observation);
  53. // bool Evaluate(double const* const* parameters,
  54. // double* residuals,
  55. // double** jacobians) const override;
  56. // };
  57. //
  58. // is a cost function that implements the projection of a point in its
  59. // local coordinate system onto its image plane and subtracts it from
  60. // the observed point projection. It can compute its residual and
  61. // either via analytic or numerical differentiation can compute its
  62. // jacobians. The intrinsics are passed in as parameters[0] and the point as
  63. // parameters[1].
  64. //
  65. // Now we would like to compose the action of this CostFunction with
  66. // the action of camera extrinsics, i.e., rotation and
  67. // translation. Say we have a templated function
  68. //
  69. // template<typename T>
  70. // void RotateAndTranslatePoint(double const* const* parameters,
  71. // double* residuals);
  72. //
  73. // Then we can now do the following,
  74. //
  75. // struct CameraProjection {
  76. // CameraProjection(const double* observation)
  77. // : intrinsic_projection_.(new IntrinsicProjection(observation)) {
  78. // }
  79. // template <typename T>
  80. // bool operator()(T const* const* parameters,
  81. // T* residual) const {
  82. // const T* rotation = parameters[0];
  83. // const T* translation = parameters[1];
  84. // const T* intrinsics = parameters[2];
  85. // const T* point = parameters[3];
  86. // T transformed_point[3];
  87. // RotateAndTranslatePoint(rotation, translation, point, transformed_point);
  88. //
  89. // // Note that we call intrinsic_projection_, just like it was
  90. // // any other templated functor.
  91. // const T* projection_parameters[2];
  92. // projection_parameters[0] = intrinsics;
  93. // projection_parameters[1] = transformed_point;
  94. // return intrinsic_projection_(projection_parameters, residual);
  95. // }
  96. //
  97. // private:
  98. // DynamicCostFunctionToFunctor intrinsic_projection_;
  99. // };
  100. class CERES_EXPORT DynamicCostFunctionToFunctor {
  101. public:
  102. // Takes ownership of cost_function.
  103. explicit DynamicCostFunctionToFunctor(CostFunction* cost_function)
  104. : cost_function_(cost_function) {
  105. CHECK(cost_function != nullptr);
  106. }
  107. bool operator()(double const* const* parameters, double* residuals) const {
  108. return cost_function_->Evaluate(parameters, residuals, nullptr);
  109. }
  110. template <typename JetT>
  111. bool operator()(JetT const* const* inputs, JetT* output) const {
  112. const std::vector<int32_t>& parameter_block_sizes =
  113. cost_function_->parameter_block_sizes();
  114. const int num_parameter_blocks =
  115. static_cast<int>(parameter_block_sizes.size());
  116. const int num_residuals = cost_function_->num_residuals();
  117. const int num_parameters = std::accumulate(
  118. parameter_block_sizes.begin(), parameter_block_sizes.end(), 0);
  119. internal::FixedArray<double> parameters(num_parameters);
  120. internal::FixedArray<double*> parameter_blocks(num_parameter_blocks);
  121. internal::FixedArray<double> jacobians(num_residuals * num_parameters);
  122. internal::FixedArray<double*> jacobian_blocks(num_parameter_blocks);
  123. internal::FixedArray<double> residuals(num_residuals);
  124. // Build a set of arrays to get the residuals and jacobians from
  125. // the CostFunction wrapped by this functor.
  126. double* parameter_ptr = parameters.data();
  127. double* jacobian_ptr = jacobians.data();
  128. for (int i = 0; i < num_parameter_blocks; ++i) {
  129. parameter_blocks[i] = parameter_ptr;
  130. jacobian_blocks[i] = jacobian_ptr;
  131. for (int j = 0; j < parameter_block_sizes[i]; ++j) {
  132. *parameter_ptr++ = inputs[i][j].a;
  133. }
  134. jacobian_ptr += num_residuals * parameter_block_sizes[i];
  135. }
  136. if (!cost_function_->Evaluate(parameter_blocks.data(),
  137. residuals.data(),
  138. jacobian_blocks.data())) {
  139. return false;
  140. }
  141. // Now that we have the incoming Jets, which are carrying the
  142. // partial derivatives of each of the inputs w.r.t to some other
  143. // underlying parameters. The derivative of the outputs of the
  144. // cost function w.r.t to the same underlying parameters can now
  145. // be computed by applying the chain rule.
  146. //
  147. // d output[i] d output[i] d input[j]
  148. // -------------- = sum_j ----------- * ------------
  149. // d parameter[k] d input[j] d parameter[k]
  150. //
  151. // d input[j]
  152. // -------------- = inputs[j], so
  153. // d parameter[k]
  154. //
  155. // outputJet[i] = sum_k jacobian[i][k] * inputJet[k]
  156. //
  157. // The following loop, iterates over the residuals, computing one
  158. // output jet at a time.
  159. for (int i = 0; i < num_residuals; ++i) {
  160. output[i].a = residuals[i];
  161. output[i].v.setZero();
  162. for (int j = 0; j < num_parameter_blocks; ++j) {
  163. const int32_t block_size = parameter_block_sizes[j];
  164. for (int k = 0; k < parameter_block_sizes[j]; ++k) {
  165. output[i].v +=
  166. jacobian_blocks[j][i * block_size + k] * inputs[j][k].v;
  167. }
  168. }
  169. }
  170. return true;
  171. }
  172. private:
  173. std::unique_ptr<CostFunction> cost_function_;
  174. };
  175. } // namespace ceres
  176. #include "ceres/internal/reenable_warnings.h"
  177. #endif // CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_