ceres-solver-v2
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +1 -0
- ceres-v2/include/autodiff_cost_function.h +228 -0
- ceres-v2/include/autodiff_first_order_function.h +151 -0
- ceres-v2/include/autodiff_local_parameterization.h +158 -0
- ceres-v2/include/autodiff_manifold.h +259 -0
- ceres-v2/include/c_api.h +148 -0
- ceres-v2/include/ceres.h +74 -0
- ceres-v2/include/conditioned_cost_function.h +101 -0
- ceres-v2/include/context.h +58 -0
- ceres-v2/include/cost_function.h +144 -0
- ceres-v2/include/cost_function_to_functor.h +171 -0
- ceres-v2/include/covariance.h +459 -0
- ceres-v2/include/crs_matrix.h +87 -0
- ceres-v2/include/cubic_interpolation.h +436 -0
- ceres-v2/include/dynamic_autodiff_cost_function.h +274 -0
- ceres-v2/include/dynamic_cost_function.h +57 -0
- ceres-v2/include/dynamic_cost_function_to_functor.h +194 -0
- ceres-v2/include/dynamic_numeric_diff_cost_function.h +164 -0
- ceres-v2/include/evaluation_callback.h +80 -0
- ceres-v2/include/first_order_function.h +54 -0
- ceres-v2/include/gradient_checker.h +189 -0
- ceres-v2/include/gradient_problem.h +185 -0
- ceres-v2/include/gradient_problem_solver.h +357 -0
- ceres-v2/include/internal/array_selector.h +97 -0
- ceres-v2/include/internal/autodiff.h +365 -0
- ceres-v2/include/internal/config.h +123 -0
- ceres-v2/include/internal/disable_warnings.h +44 -0
- ceres-v2/include/internal/eigen.h +75 -0
- ceres-v2/include/internal/export.h +42 -0
- ceres-v2/include/internal/fixed_array.h +467 -0
- ceres-v2/include/internal/householder_vector.h +96 -0
- ceres-v2/include/internal/integer_sequence_algorithm.h +291 -0
- ceres-v2/include/internal/jet_traits.h +223 -0
- ceres-v2/include/internal/line_parameterization.h +183 -0
- ceres-v2/include/internal/memory.h +90 -0
- ceres-v2/include/internal/numeric_diff.h +508 -0
- ceres-v2/include/internal/parameter_dims.h +124 -0
- ceres-v2/include/internal/port.h +88 -0
- ceres-v2/include/internal/reenable_warnings.h +38 -0
- ceres-v2/include/internal/sphere_manifold_functions.h +162 -0
- ceres-v2/include/internal/variadic_evaluate.h +113 -0
- ceres-v2/include/iteration_callback.h +204 -0
- ceres-v2/include/jet.h +1387 -0
- ceres-v2/include/jet_fwd.h +44 -0
- ceres-v2/include/line_manifold.h +304 -0
- ceres-v2/include/local_parameterization.h +371 -0
- ceres-v2/include/loss_function.h +433 -0
- ceres-v2/include/manifold.h +411 -0
- ceres-v2/include/manifold_test_utils.h +328 -0
- ceres-v2/include/normal_prior.h +78 -0
.gitattributes
CHANGED
|
@@ -50,3 +50,4 @@ colmap/lib/libpba.a filter=lfs diff=lfs merge=lfs -text
|
|
| 50 |
colmap/lib/libpoisson_recon.a filter=lfs diff=lfs merge=lfs -text
|
| 51 |
colmap/lib/libsift_gpu.a filter=lfs diff=lfs merge=lfs -text
|
| 52 |
ceres/lib/libceres.a filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 50 |
colmap/lib/libpoisson_recon.a filter=lfs diff=lfs merge=lfs -text
|
| 51 |
colmap/lib/libsift_gpu.a filter=lfs diff=lfs merge=lfs -text
|
| 52 |
ceres/lib/libceres.a filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
ceres-v2/lib/libceres.a filter=lfs diff=lfs merge=lfs -text
|
ceres-v2/include/autodiff_cost_function.h
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
//
|
| 31 |
+
// Create CostFunctions as needed by the least squares framework, with
|
| 32 |
+
// Jacobians computed via automatic differentiation. For more
|
| 33 |
+
// information on automatic differentiation, see the wikipedia article
|
| 34 |
+
// at http://en.wikipedia.org/wiki/Automatic_differentiation
|
| 35 |
+
//
|
| 36 |
+
// To get an auto differentiated cost function, you must define a class with a
|
| 37 |
+
// templated operator() (a functor) that computes the cost function in terms of
|
| 38 |
+
// the template parameter T. The autodiff framework substitutes appropriate
|
| 39 |
+
// "jet" objects for T in order to compute the derivative when necessary, but
|
| 40 |
+
// this is hidden, and you should write the function as if T were a scalar type
|
| 41 |
+
// (e.g. a double-precision floating point number).
|
| 42 |
+
//
|
| 43 |
+
// The function must write the computed value in the last argument
|
| 44 |
+
// (the only non-const one) and return true to indicate
|
| 45 |
+
// success. Please see cost_function.h for details on how the return
|
| 46 |
+
// value maybe used to impose simple constraints on the parameter
|
| 47 |
+
// block.
|
| 48 |
+
//
|
| 49 |
+
// For example, consider a scalar error e = k - x'y, where both x and y are
|
| 50 |
+
// two-dimensional column vector parameters, the prime sign indicates
|
| 51 |
+
// transposition, and k is a constant. The form of this error, which is the
|
| 52 |
+
// difference between a constant and an expression, is a common pattern in least
|
| 53 |
+
// squares problems. For example, the value x'y might be the model expectation
|
| 54 |
+
// for a series of measurements, where there is an instance of the cost function
|
| 55 |
+
// for each measurement k.
|
| 56 |
+
//
|
| 57 |
+
// The actual cost added to the total problem is e^2, or (k - x'y)^2; however,
|
| 58 |
+
// the squaring is implicitly done by the optimization framework.
|
| 59 |
+
//
|
| 60 |
+
// To write an auto-differentiable cost function for the above model, first
|
| 61 |
+
// define the object
|
| 62 |
+
//
|
| 63 |
+
// class MyScalarCostFunctor {
|
| 64 |
+
// MyScalarCostFunctor(double k): k_(k) {}
|
| 65 |
+
//
|
| 66 |
+
// template <typename T>
|
| 67 |
+
// bool operator()(const T* const x , const T* const y, T* e) const {
|
| 68 |
+
// e[0] = T(k_) - x[0] * y[0] + x[1] * y[1];
|
| 69 |
+
// return true;
|
| 70 |
+
// }
|
| 71 |
+
//
|
| 72 |
+
// private:
|
| 73 |
+
// double k_;
|
| 74 |
+
// };
|
| 75 |
+
//
|
| 76 |
+
// Note that in the declaration of operator() the input parameters x and y come
|
| 77 |
+
// first, and are passed as const pointers to arrays of T. If there were three
|
| 78 |
+
// input parameters, then the third input parameter would come after y. The
|
| 79 |
+
// output is always the last parameter, and is also a pointer to an array. In
|
| 80 |
+
// the example above, e is a scalar, so only e[0] is set.
|
| 81 |
+
//
|
| 82 |
+
// Then given this class definition, the auto differentiated cost function for
|
| 83 |
+
// it can be constructed as follows.
|
| 84 |
+
//
|
| 85 |
+
// CostFunction* cost_function
|
| 86 |
+
// = new AutoDiffCostFunction<MyScalarCostFunctor, 1, 2, 2>(
|
| 87 |
+
// new MyScalarCostFunctor(1.0)); ^ ^ ^
|
| 88 |
+
// | | |
|
| 89 |
+
// Dimension of residual -----+ | |
|
| 90 |
+
// Dimension of x ---------------+ |
|
| 91 |
+
// Dimension of y ------------------+
|
| 92 |
+
//
|
| 93 |
+
// In this example, there is usually an instance for each measurement of k.
|
| 94 |
+
//
|
| 95 |
+
// In the instantiation above, the template parameters following
|
| 96 |
+
// "MyScalarCostFunctor", "1, 2, 2", describe the functor as computing a
|
| 97 |
+
// 1-dimensional output from two arguments, both 2-dimensional.
|
| 98 |
+
//
|
| 99 |
+
// AutoDiffCostFunction also supports cost functions with a
|
| 100 |
+
// runtime-determined number of residuals. For example:
|
| 101 |
+
//
|
| 102 |
+
// CostFunction* cost_function
|
| 103 |
+
// = new AutoDiffCostFunction<MyScalarCostFunctor, DYNAMIC, 2, 2>(
|
| 104 |
+
// new CostFunctorWithDynamicNumResiduals(1.0), ^ ^ ^
|
| 105 |
+
// runtime_number_of_residuals); <----+ | | |
|
| 106 |
+
// | | | |
|
| 107 |
+
// | | | |
|
| 108 |
+
// Actual number of residuals ------+ | | |
|
| 109 |
+
// Indicate dynamic number of residuals --------+ | |
|
| 110 |
+
// Dimension of x ------------------------------------+ |
|
| 111 |
+
// Dimension of y ---------------------------------------+
|
| 112 |
+
//
|
| 113 |
+
// WARNING #1: Since the functor will get instantiated with different types for
|
| 114 |
+
// T, you must convert from other numeric types to T before mixing
|
| 115 |
+
// computations with other variables of type T. In the example above, this is
|
| 116 |
+
// seen where instead of using k_ directly, k_ is wrapped with T(k_).
|
| 117 |
+
//
|
| 118 |
+
// WARNING #2: A common beginner's error when first using autodiff cost
|
| 119 |
+
// functions is to get the sizing wrong. In particular, there is a tendency to
|
| 120 |
+
// set the template parameters to (dimension of residual, number of parameters)
|
| 121 |
+
// instead of passing a dimension parameter for *every parameter*. In the
|
| 122 |
+
// example above, that would be <MyScalarCostFunctor, 1, 2>, which is missing
|
| 123 |
+
// the last '2' argument. Please be careful when setting the size parameters.
|
| 124 |
+
|
| 125 |
+
#ifndef CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
|
| 126 |
+
#define CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
|
| 127 |
+
|
| 128 |
+
#include <memory>
|
| 129 |
+
|
| 130 |
+
#include "ceres/internal/autodiff.h"
|
| 131 |
+
#include "ceres/sized_cost_function.h"
|
| 132 |
+
#include "ceres/types.h"
|
| 133 |
+
#include "glog/logging.h"
|
| 134 |
+
|
| 135 |
+
namespace ceres {
|
| 136 |
+
|
| 137 |
+
// A cost function which computes the derivative of the cost with respect to
|
| 138 |
+
// the parameters (a.k.a. the jacobian) using an auto differentiation framework.
|
| 139 |
+
// The first template argument is the functor object, described in the header
|
| 140 |
+
// comment. The second argument is the dimension of the residual (or
|
| 141 |
+
// ceres::DYNAMIC to indicate it will be set at runtime), and subsequent
|
| 142 |
+
// arguments describe the size of the Nth parameter, one per parameter.
|
| 143 |
+
//
|
| 144 |
+
// The constructors take ownership of the cost functor.
|
| 145 |
+
//
|
| 146 |
+
// If the number of residuals (argument kNumResiduals below) is
|
| 147 |
+
// ceres::DYNAMIC, then the two-argument constructor must be used. The
|
| 148 |
+
// second constructor takes a number of residuals (in addition to the
|
| 149 |
+
// templated number of residuals). This allows for varying the number
|
| 150 |
+
// of residuals for a single autodiff cost function at runtime.
|
| 151 |
+
template <typename CostFunctor,
|
| 152 |
+
int kNumResiduals, // Number of residuals, or ceres::DYNAMIC.
|
| 153 |
+
int... Ns> // Number of parameters in each parameter block.
|
| 154 |
+
class AutoDiffCostFunction final
|
| 155 |
+
: public SizedCostFunction<kNumResiduals, Ns...> {
|
| 156 |
+
public:
|
| 157 |
+
// Takes ownership of functor by default. Uses the template-provided
|
| 158 |
+
// value for the number of residuals ("kNumResiduals").
|
| 159 |
+
explicit AutoDiffCostFunction(CostFunctor* functor,
|
| 160 |
+
Ownership ownership = TAKE_OWNERSHIP)
|
| 161 |
+
: functor_(functor), ownership_(ownership) {
|
| 162 |
+
static_assert(kNumResiduals != DYNAMIC,
|
| 163 |
+
"Can't run the fixed-size constructor if the number of "
|
| 164 |
+
"residuals is set to ceres::DYNAMIC.");
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
// Takes ownership of functor by default. Ignores the template-provided
|
| 168 |
+
// kNumResiduals in favor of the "num_residuals" argument provided.
|
| 169 |
+
//
|
| 170 |
+
// This allows for having autodiff cost functions which return varying
|
| 171 |
+
// numbers of residuals at runtime.
|
| 172 |
+
AutoDiffCostFunction(CostFunctor* functor,
|
| 173 |
+
int num_residuals,
|
| 174 |
+
Ownership ownership = TAKE_OWNERSHIP)
|
| 175 |
+
: functor_(functor), ownership_(ownership) {
|
| 176 |
+
static_assert(kNumResiduals == DYNAMIC,
|
| 177 |
+
"Can't run the dynamic-size constructor if the number of "
|
| 178 |
+
"residuals is not ceres::DYNAMIC.");
|
| 179 |
+
SizedCostFunction<kNumResiduals, Ns...>::set_num_residuals(num_residuals);
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
AutoDiffCostFunction(AutoDiffCostFunction&& other)
|
| 183 |
+
: functor_(std::move(other.functor_)), ownership_(other.ownership_) {}
|
| 184 |
+
|
| 185 |
+
virtual ~AutoDiffCostFunction() {
|
| 186 |
+
// Manually release pointer if configured to not take ownership rather than
|
| 187 |
+
// deleting only if ownership is taken.
|
| 188 |
+
// This is to stay maximally compatible to old user code which may have
|
| 189 |
+
// forgotten to implement a virtual destructor, from when the
|
| 190 |
+
// AutoDiffCostFunction always took ownership.
|
| 191 |
+
if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
|
| 192 |
+
functor_.release();
|
| 193 |
+
}
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
// Implementation details follow; clients of the autodiff cost function should
|
| 197 |
+
// not have to examine below here.
|
| 198 |
+
//
|
| 199 |
+
// To handle variadic cost functions, some template magic is needed. It's
|
| 200 |
+
// mostly hidden inside autodiff.h.
|
| 201 |
+
bool Evaluate(double const* const* parameters,
|
| 202 |
+
double* residuals,
|
| 203 |
+
double** jacobians) const override {
|
| 204 |
+
using ParameterDims =
|
| 205 |
+
typename SizedCostFunction<kNumResiduals, Ns...>::ParameterDims;
|
| 206 |
+
|
| 207 |
+
if (!jacobians) {
|
| 208 |
+
return internal::VariadicEvaluate<ParameterDims>(
|
| 209 |
+
*functor_, parameters, residuals);
|
| 210 |
+
}
|
| 211 |
+
return internal::AutoDifferentiate<kNumResiduals, ParameterDims>(
|
| 212 |
+
*functor_,
|
| 213 |
+
parameters,
|
| 214 |
+
SizedCostFunction<kNumResiduals, Ns...>::num_residuals(),
|
| 215 |
+
residuals,
|
| 216 |
+
jacobians);
|
| 217 |
+
};
|
| 218 |
+
|
| 219 |
+
const CostFunctor& functor() const { return *functor_; }
|
| 220 |
+
|
| 221 |
+
private:
|
| 222 |
+
std::unique_ptr<CostFunctor> functor_;
|
| 223 |
+
Ownership ownership_;
|
| 224 |
+
};
|
| 225 |
+
|
| 226 |
+
} // namespace ceres
|
| 227 |
+
|
| 228 |
+
#endif // CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
|
ceres-v2/include/autodiff_first_order_function.h
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_AUTODIFF_FIRST_ORDER_FUNCTION_H_
|
| 32 |
+
#define CERES_PUBLIC_AUTODIFF_FIRST_ORDER_FUNCTION_H_
|
| 33 |
+
|
| 34 |
+
#include <memory>
|
| 35 |
+
|
| 36 |
+
#include "ceres/first_order_function.h"
|
| 37 |
+
#include "ceres/internal/eigen.h"
|
| 38 |
+
#include "ceres/internal/fixed_array.h"
|
| 39 |
+
#include "ceres/jet.h"
|
| 40 |
+
#include "ceres/types.h"
|
| 41 |
+
|
| 42 |
+
namespace ceres {
|
| 43 |
+
|
| 44 |
+
// Create FirstOrderFunctions as needed by the GradientProblem
|
| 45 |
+
// framework, with gradients computed via automatic
|
| 46 |
+
// differentiation. For more information on automatic differentiation,
|
| 47 |
+
// see the wikipedia article at
|
| 48 |
+
// http://en.wikipedia.org/wiki/Automatic_differentiation
|
| 49 |
+
//
|
| 50 |
+
// To get an auto differentiated function, you must define a class
|
| 51 |
+
// with a templated operator() (a functor) that computes the cost
|
| 52 |
+
// function in terms of the template parameter T. The autodiff
|
| 53 |
+
// framework substitutes appropriate "jet" objects for T in order to
|
| 54 |
+
// compute the derivative when necessary, but this is hidden, and you
|
| 55 |
+
// should write the function as if T were a scalar type (e.g. a
|
| 56 |
+
// double-precision floating point number).
|
| 57 |
+
//
|
| 58 |
+
// The function must write the computed value in the last argument
|
| 59 |
+
// (the only non-const one) and return true to indicate
|
| 60 |
+
// success.
|
| 61 |
+
//
|
| 62 |
+
// For example, consider a scalar error e = x'y - a, where both x and y are
|
| 63 |
+
// two-dimensional column vector parameters, the prime sign indicates
|
| 64 |
+
// transposition, and a is a constant.
|
| 65 |
+
//
|
| 66 |
+
// To write an auto-differentiable FirstOrderFunction for the above model, first
|
| 67 |
+
// define the object
|
| 68 |
+
//
|
| 69 |
+
// class QuadraticCostFunctor {
|
| 70 |
+
// public:
|
| 71 |
+
// explicit QuadraticCostFunctor(double a) : a_(a) {}
|
| 72 |
+
// template <typename T>
|
| 73 |
+
// bool operator()(const T* const xy, T* cost) const {
|
| 74 |
+
// const T* const x = xy;
|
| 75 |
+
// const T* const y = xy + 2;
|
| 76 |
+
// *cost = x[0] * y[0] + x[1] * y[1] - T(a_);
|
| 77 |
+
// return true;
|
| 78 |
+
// }
|
| 79 |
+
//
|
| 80 |
+
// private:
|
| 81 |
+
// double a_;
|
| 82 |
+
// };
|
| 83 |
+
//
|
| 84 |
+
// Note that in the declaration of operator() the input parameters xy come
|
| 85 |
+
// first, and are passed as const pointers to arrays of T. The
|
| 86 |
+
// output is the last parameter.
|
| 87 |
+
//
|
| 88 |
+
// Then given this class definition, the auto differentiated FirstOrderFunction
|
| 89 |
+
// for it can be constructed as follows.
|
| 90 |
+
//
|
| 91 |
+
// FirstOrderFunction* function =
|
| 92 |
+
// new AutoDiffFirstOrderFunction<QuadraticCostFunctor, 4>(
|
| 93 |
+
// new QuadraticCostFunctor(1.0)));
|
| 94 |
+
//
|
| 95 |
+
// In the instantiation above, the template parameters following
|
| 96 |
+
// "QuadraticCostFunctor", "4", describe the functor as computing a
|
| 97 |
+
// 1-dimensional output from a four dimensional vector.
|
| 98 |
+
//
|
| 99 |
+
// WARNING: Since the functor will get instantiated with different types for
|
| 100 |
+
// T, you must convert from other numeric types to T before mixing
|
| 101 |
+
// computations with other variables of type T. In the example above, this is
|
| 102 |
+
// seen where instead of using a_ directly, a_ is wrapped with T(a_).
|
| 103 |
+
|
| 104 |
+
template <typename FirstOrderFunctor, int kNumParameters>
|
| 105 |
+
class AutoDiffFirstOrderFunction final : public FirstOrderFunction {
|
| 106 |
+
public:
|
| 107 |
+
// Takes ownership of functor.
|
| 108 |
+
explicit AutoDiffFirstOrderFunction(FirstOrderFunctor* functor)
|
| 109 |
+
: functor_(functor) {
|
| 110 |
+
static_assert(kNumParameters > 0, "kNumParameters must be positive");
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
bool Evaluate(const double* const parameters,
|
| 114 |
+
double* cost,
|
| 115 |
+
double* gradient) const override {
|
| 116 |
+
if (gradient == nullptr) {
|
| 117 |
+
return (*functor_)(parameters, cost);
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
using JetT = Jet<double, kNumParameters>;
|
| 121 |
+
internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(kNumParameters);
|
| 122 |
+
for (int i = 0; i < kNumParameters; ++i) {
|
| 123 |
+
x[i].a = parameters[i];
|
| 124 |
+
x[i].v.setZero();
|
| 125 |
+
x[i].v[i] = 1.0;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
JetT output;
|
| 129 |
+
output.a = kImpossibleValue;
|
| 130 |
+
output.v.setConstant(kImpossibleValue);
|
| 131 |
+
|
| 132 |
+
if (!(*functor_)(x.data(), &output)) {
|
| 133 |
+
return false;
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
*cost = output.a;
|
| 137 |
+
VectorRef(gradient, kNumParameters) = output.v;
|
| 138 |
+
return true;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
int NumParameters() const override { return kNumParameters; }
|
| 142 |
+
|
| 143 |
+
const FirstOrderFunctor& functor() const { return *functor_; }
|
| 144 |
+
|
| 145 |
+
private:
|
| 146 |
+
std::unique_ptr<FirstOrderFunctor> functor_;
|
| 147 |
+
};
|
| 148 |
+
|
| 149 |
+
} // namespace ceres
|
| 150 |
+
|
| 151 |
+
#endif // CERES_PUBLIC_AUTODIFF_FIRST_ORDER_FUNCTION_H_
|
ceres-v2/include/autodiff_local_parameterization.h
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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: sergey.vfx@gmail.com (Sergey Sharybin)
|
| 30 |
+
// mierle@gmail.com (Keir Mierle)
|
| 31 |
+
// sameeragarwal@google.com (Sameer Agarwal)
|
| 32 |
+
|
| 33 |
+
#ifndef CERES_PUBLIC_AUTODIFF_LOCAL_PARAMETERIZATION_H_
|
| 34 |
+
#define CERES_PUBLIC_AUTODIFF_LOCAL_PARAMETERIZATION_H_
|
| 35 |
+
|
| 36 |
+
#include <memory>
|
| 37 |
+
|
| 38 |
+
#include "ceres/internal/autodiff.h"
|
| 39 |
+
#include "ceres/local_parameterization.h"
|
| 40 |
+
|
| 41 |
+
namespace ceres {
|
| 42 |
+
|
| 43 |
+
// WARNING: LocalParameterizations are deprecated, so is
|
| 44 |
+
// AutoDiffLocalParameterization. They will be removed from Ceres Solver in
|
| 45 |
+
// version 2.2.0. Please use Manifolds and AutoDiffManifold instead.
|
| 46 |
+
|
| 47 |
+
// Create local parameterization with Jacobians computed via automatic
|
| 48 |
+
// differentiation. For more information on local parameterizations,
|
| 49 |
+
// see include/ceres/local_parameterization.h
|
| 50 |
+
//
|
| 51 |
+
// To get an auto differentiated local parameterization, you must define
|
| 52 |
+
// a class with a templated operator() (a functor) that computes
|
| 53 |
+
//
|
| 54 |
+
// x_plus_delta = Plus(x, delta);
|
| 55 |
+
//
|
| 56 |
+
// the template parameter T. The autodiff framework substitutes appropriate
|
| 57 |
+
// "Jet" objects for T in order to compute the derivative when necessary, but
|
| 58 |
+
// this is hidden, and you should write the function as if T were a scalar type
|
| 59 |
+
// (e.g. a double-precision floating point number).
|
| 60 |
+
//
|
| 61 |
+
// The function must write the computed value in the last argument (the only
|
| 62 |
+
// non-const one) and return true to indicate success.
|
| 63 |
+
//
|
| 64 |
+
// For example, Quaternions have a three dimensional local
|
| 65 |
+
// parameterization. It's plus operation can be implemented as (taken
|
| 66 |
+
// from internal/ceres/auto_diff_local_parameterization_test.cc)
|
| 67 |
+
//
|
| 68 |
+
// struct QuaternionPlus {
|
| 69 |
+
// template<typename T>
|
| 70 |
+
// bool operator()(const T* x, const T* delta, T* x_plus_delta) const {
|
| 71 |
+
// const T squared_norm_delta =
|
| 72 |
+
// delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2];
|
| 73 |
+
//
|
| 74 |
+
// T q_delta[4];
|
| 75 |
+
// if (squared_norm_delta > T(0.0)) {
|
| 76 |
+
// T norm_delta = sqrt(squared_norm_delta);
|
| 77 |
+
// const T sin_delta_by_delta = sin(norm_delta) / norm_delta;
|
| 78 |
+
// q_delta[0] = cos(norm_delta);
|
| 79 |
+
// q_delta[1] = sin_delta_by_delta * delta[0];
|
| 80 |
+
// q_delta[2] = sin_delta_by_delta * delta[1];
|
| 81 |
+
// q_delta[3] = sin_delta_by_delta * delta[2];
|
| 82 |
+
// } else {
|
| 83 |
+
// // We do not just use q_delta = [1,0,0,0] here because that is a
|
| 84 |
+
// // constant and when used for automatic differentiation will
|
| 85 |
+
// // lead to a zero derivative. Instead we take a first order
|
| 86 |
+
// // approximation and evaluate it at zero.
|
| 87 |
+
// q_delta[0] = T(1.0);
|
| 88 |
+
// q_delta[1] = delta[0];
|
| 89 |
+
// q_delta[2] = delta[1];
|
| 90 |
+
// q_delta[3] = delta[2];
|
| 91 |
+
// }
|
| 92 |
+
//
|
| 93 |
+
// QuaternionProduct(q_delta, x, x_plus_delta);
|
| 94 |
+
// return true;
|
| 95 |
+
// }
|
| 96 |
+
// };
|
| 97 |
+
//
|
| 98 |
+
// Then given this struct, the auto differentiated local
|
| 99 |
+
// parameterization can now be constructed as
|
| 100 |
+
//
|
| 101 |
+
// LocalParameterization* local_parameterization =
|
| 102 |
+
// new AutoDiffLocalParameterization<QuaternionPlus, 4, 3>;
|
| 103 |
+
// | |
|
| 104 |
+
// Global Size ---------------+ |
|
| 105 |
+
// Local Size -------------------+
|
| 106 |
+
//
|
| 107 |
+
// WARNING: Since the functor will get instantiated with different types for
|
| 108 |
+
// T, you must to convert from other numeric types to T before mixing
|
| 109 |
+
// computations with other variables of type T. In the example above, this is
|
| 110 |
+
// seen where instead of using k_ directly, k_ is wrapped with T(k_).
|
| 111 |
+
|
| 112 |
+
template <typename Functor, int kGlobalSize, int kLocalSize>
|
| 113 |
+
class CERES_DEPRECATED_WITH_MSG("Use AutoDiffManifold instead.")
|
| 114 |
+
AutoDiffLocalParameterization : public LocalParameterization {
|
| 115 |
+
public:
|
| 116 |
+
AutoDiffLocalParameterization() : functor_(new Functor()) {}
|
| 117 |
+
|
| 118 |
+
// Takes ownership of functor.
|
| 119 |
+
explicit AutoDiffLocalParameterization(Functor* functor)
|
| 120 |
+
: functor_(functor) {}
|
| 121 |
+
|
| 122 |
+
bool Plus(const double* x,
|
| 123 |
+
const double* delta,
|
| 124 |
+
double* x_plus_delta) const override {
|
| 125 |
+
return (*functor_)(x, delta, x_plus_delta);
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
bool ComputeJacobian(const double* x, double* jacobian) const override {
|
| 129 |
+
double zero_delta[kLocalSize];
|
| 130 |
+
for (int i = 0; i < kLocalSize; ++i) {
|
| 131 |
+
zero_delta[i] = 0.0;
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
double x_plus_delta[kGlobalSize];
|
| 135 |
+
for (int i = 0; i < kGlobalSize; ++i) {
|
| 136 |
+
x_plus_delta[i] = 0.0;
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
const double* parameter_ptrs[2] = {x, zero_delta};
|
| 140 |
+
double* jacobian_ptrs[2] = {nullptr, jacobian};
|
| 141 |
+
return internal::AutoDifferentiate<
|
| 142 |
+
kGlobalSize,
|
| 143 |
+
internal::StaticParameterDims<kGlobalSize, kLocalSize>>(
|
| 144 |
+
*functor_, parameter_ptrs, kGlobalSize, x_plus_delta, jacobian_ptrs);
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
int GlobalSize() const override { return kGlobalSize; }
|
| 148 |
+
int LocalSize() const override { return kLocalSize; }
|
| 149 |
+
|
| 150 |
+
const Functor& functor() const { return *functor_; }
|
| 151 |
+
|
| 152 |
+
private:
|
| 153 |
+
std::unique_ptr<Functor> functor_;
|
| 154 |
+
};
|
| 155 |
+
|
| 156 |
+
} // namespace ceres
|
| 157 |
+
|
| 158 |
+
#endif // CERES_PUBLIC_AUTODIFF_LOCAL_PARAMETERIZATION_H_
|
ceres-v2/include/autodiff_manifold.h
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_AUTODIFF_MANIFOLD_H_
|
| 32 |
+
#define CERES_PUBLIC_AUTODIFF_MANIFOLD_H_
|
| 33 |
+
|
| 34 |
+
#include <memory>
|
| 35 |
+
|
| 36 |
+
#include "ceres/internal/autodiff.h"
|
| 37 |
+
#include "ceres/manifold.h"
|
| 38 |
+
|
| 39 |
+
namespace ceres {
|
| 40 |
+
|
| 41 |
+
// Create a Manifold with Jacobians computed via automatic differentiation. For
|
| 42 |
+
// more information on manifolds, see include/ceres/manifold.h
|
| 43 |
+
//
|
| 44 |
+
// To get an auto differentiated manifold, you must define a class/struct with
|
| 45 |
+
// templated Plus and Minus functions that compute
|
| 46 |
+
//
|
| 47 |
+
// x_plus_delta = Plus(x, delta);
|
| 48 |
+
// y_minus_x = Minus(y, x);
|
| 49 |
+
//
|
| 50 |
+
// Where, x, y and x_plus_y are vectors on the manifold in the ambient space (so
|
| 51 |
+
// they are kAmbientSize vectors) and delta, y_minus_x are vectors in the
|
| 52 |
+
// tangent space (so they are kTangentSize vectors).
|
| 53 |
+
//
|
| 54 |
+
// The Functor should have the signature:
|
| 55 |
+
//
|
| 56 |
+
// struct Functor {
|
| 57 |
+
// template <typename T>
|
| 58 |
+
// bool Plus(const T* x, const T* delta, T* x_plus_delta) const;
|
| 59 |
+
//
|
| 60 |
+
// template <typename T>
|
| 61 |
+
// bool Minus(const T* y, const T* x, T* y_minus_x) const;
|
| 62 |
+
// };
|
| 63 |
+
//
|
| 64 |
+
// Observe that the Plus and Minus operations are templated on the parameter T.
|
| 65 |
+
// The autodiff framework substitutes appropriate "Jet" objects for T in order
|
| 66 |
+
// to compute the derivative when necessary. This is the same mechanism that is
|
| 67 |
+
// used to compute derivatives when using AutoDiffCostFunction.
|
| 68 |
+
//
|
| 69 |
+
// Plus and Minus should return true if the computation is successful and false
|
| 70 |
+
// otherwise, in which case the result will not be used.
|
| 71 |
+
//
|
| 72 |
+
// Given this Functor, the corresponding Manifold can be constructed as:
|
| 73 |
+
//
|
| 74 |
+
// AutoDiffManifold<Functor, kAmbientSize, kTangentSize> manifold;
|
| 75 |
+
//
|
| 76 |
+
// As a concrete example consider the case of Quaternions. Quaternions form a
|
| 77 |
+
// three dimensional manifold embedded in R^4, i.e. they have an ambient
|
| 78 |
+
// dimension of 4 and their tangent space has dimension 3. The following Functor
|
| 79 |
+
// (taken from autodiff_manifold_test.cc) defines the Plus and Minus operations
|
| 80 |
+
// on the Quaternion manifold:
|
| 81 |
+
//
|
| 82 |
+
// NOTE: The following is only used for illustration purposes. Ceres Solver
|
| 83 |
+
// ships with optimized production grade QuaternionManifold implementation. See
|
| 84 |
+
// manifold.h.
|
| 85 |
+
//
|
| 86 |
+
// This functor assumes that the quaternions are laid out as [w,x,y,z] in
|
| 87 |
+
// memory, i.e. the real or scalar part is the first coordinate.
|
| 88 |
+
//
|
| 89 |
+
// struct QuaternionFunctor {
|
| 90 |
+
// template <typename T>
|
| 91 |
+
// bool Plus(const T* x, const T* delta, T* x_plus_delta) const {
|
| 92 |
+
// const T squared_norm_delta =
|
| 93 |
+
// delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2];
|
| 94 |
+
//
|
| 95 |
+
// T q_delta[4];
|
| 96 |
+
// if (squared_norm_delta > T(0.0)) {
|
| 97 |
+
// T norm_delta = sqrt(squared_norm_delta);
|
| 98 |
+
// const T sin_delta_by_delta = sin(norm_delta) / norm_delta;
|
| 99 |
+
// q_delta[0] = cos(norm_delta);
|
| 100 |
+
// q_delta[1] = sin_delta_by_delta * delta[0];
|
| 101 |
+
// q_delta[2] = sin_delta_by_delta * delta[1];
|
| 102 |
+
// q_delta[3] = sin_delta_by_delta * delta[2];
|
| 103 |
+
// } else {
|
| 104 |
+
// // We do not just use q_delta = [1,0,0,0] here because that is a
|
| 105 |
+
// // constant and when used for automatic differentiation will
|
| 106 |
+
// // lead to a zero derivative. Instead we take a first order
|
| 107 |
+
// // approximation and evaluate it at zero.
|
| 108 |
+
// q_delta[0] = T(1.0);
|
| 109 |
+
// q_delta[1] = delta[0];
|
| 110 |
+
// q_delta[2] = delta[1];
|
| 111 |
+
// q_delta[3] = delta[2];
|
| 112 |
+
// }
|
| 113 |
+
//
|
| 114 |
+
// QuaternionProduct(q_delta, x, x_plus_delta);
|
| 115 |
+
// return true;
|
| 116 |
+
// }
|
| 117 |
+
//
|
| 118 |
+
// template <typename T>
|
| 119 |
+
// bool Minus(const T* y, const T* x, T* y_minus_x) const {
|
| 120 |
+
// T minus_x[4] = {x[0], -x[1], -x[2], -x[3]};
|
| 121 |
+
// T ambient_y_minus_x[4];
|
| 122 |
+
// QuaternionProduct(y, minus_x, ambient_y_minus_x);
|
| 123 |
+
// T u_norm = sqrt(ambient_y_minus_x[1] * ambient_y_minus_x[1] +
|
| 124 |
+
// ambient_y_minus_x[2] * ambient_y_minus_x[2] +
|
| 125 |
+
// ambient_y_minus_x[3] * ambient_y_minus_x[3]);
|
| 126 |
+
// if (u_norm > 0.0) {
|
| 127 |
+
// T theta = atan2(u_norm, ambient_y_minus_x[0]);
|
| 128 |
+
// y_minus_x[0] = theta * ambient_y_minus_x[1] / u_norm;
|
| 129 |
+
// y_minus_x[1] = theta * ambient_y_minus_x[2] / u_norm;
|
| 130 |
+
// y_minus_x[2] = theta * ambient_y_minus_x[3] / u_norm;
|
| 131 |
+
// } else {
|
| 132 |
+
// // We do not use [0,0,0] here because even though the value part is
|
| 133 |
+
// // a constant, the derivative part is not.
|
| 134 |
+
// y_minus_x[0] = ambient_y_minus_x[1];
|
| 135 |
+
// y_minus_x[1] = ambient_y_minus_x[2];
|
| 136 |
+
// y_minus_x[2] = ambient_y_minus_x[3];
|
| 137 |
+
// }
|
| 138 |
+
// return true;
|
| 139 |
+
// }
|
| 140 |
+
// };
|
| 141 |
+
//
|
| 142 |
+
// Then given this struct, the auto differentiated Quaternion Manifold can now
|
| 143 |
+
// be constructed as
|
| 144 |
+
//
|
| 145 |
+
// Manifold* manifold = new AutoDiffManifold<QuaternionFunctor, 4, 3>;
|
| 146 |
+
|
| 147 |
+
template <typename Functor, int kAmbientSize, int kTangentSize>
|
| 148 |
+
class AutoDiffManifold final : public Manifold {
|
| 149 |
+
public:
|
| 150 |
+
AutoDiffManifold() : functor_(std::make_unique<Functor>()) {}
|
| 151 |
+
|
| 152 |
+
// Takes ownership of functor.
|
| 153 |
+
explicit AutoDiffManifold(Functor* functor) : functor_(functor) {}
|
| 154 |
+
|
| 155 |
+
int AmbientSize() const override { return kAmbientSize; }
|
| 156 |
+
int TangentSize() const override { return kTangentSize; }
|
| 157 |
+
|
| 158 |
+
bool Plus(const double* x,
|
| 159 |
+
const double* delta,
|
| 160 |
+
double* x_plus_delta) const override {
|
| 161 |
+
return functor_->Plus(x, delta, x_plus_delta);
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
bool PlusJacobian(const double* x, double* jacobian) const override;
|
| 165 |
+
|
| 166 |
+
bool Minus(const double* y,
|
| 167 |
+
const double* x,
|
| 168 |
+
double* y_minus_x) const override {
|
| 169 |
+
return functor_->Minus(y, x, y_minus_x);
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
bool MinusJacobian(const double* x, double* jacobian) const override;
|
| 173 |
+
|
| 174 |
+
const Functor& functor() const { return *functor_; }
|
| 175 |
+
|
| 176 |
+
private:
|
| 177 |
+
std::unique_ptr<Functor> functor_;
|
| 178 |
+
};
|
| 179 |
+
|
| 180 |
+
namespace internal {
|
| 181 |
+
|
| 182 |
+
// The following two helper structs are needed to interface the Plus and Minus
|
| 183 |
+
// methods of the ManifoldFunctor with the automatic differentiation which
|
| 184 |
+
// expects a Functor with operator().
|
| 185 |
+
template <typename Functor>
|
| 186 |
+
struct PlusWrapper {
|
| 187 |
+
explicit PlusWrapper(const Functor& functor) : functor(functor) {}
|
| 188 |
+
template <typename T>
|
| 189 |
+
bool operator()(const T* x, const T* delta, T* x_plus_delta) const {
|
| 190 |
+
return functor.Plus(x, delta, x_plus_delta);
|
| 191 |
+
}
|
| 192 |
+
const Functor& functor;
|
| 193 |
+
};
|
| 194 |
+
|
| 195 |
+
template <typename Functor>
|
| 196 |
+
struct MinusWrapper {
|
| 197 |
+
explicit MinusWrapper(const Functor& functor) : functor(functor) {}
|
| 198 |
+
template <typename T>
|
| 199 |
+
bool operator()(const T* y, const T* x, T* y_minus_x) const {
|
| 200 |
+
return functor.Minus(y, x, y_minus_x);
|
| 201 |
+
}
|
| 202 |
+
const Functor& functor;
|
| 203 |
+
};
|
| 204 |
+
} // namespace internal
|
| 205 |
+
|
| 206 |
+
template <typename Functor, int kAmbientSize, int kTangentSize>
|
| 207 |
+
bool AutoDiffManifold<Functor, kAmbientSize, kTangentSize>::PlusJacobian(
|
| 208 |
+
const double* x, double* jacobian) const {
|
| 209 |
+
double zero_delta[kTangentSize];
|
| 210 |
+
for (int i = 0; i < kTangentSize; ++i) {
|
| 211 |
+
zero_delta[i] = 0.0;
|
| 212 |
+
}
|
| 213 |
+
|
| 214 |
+
double x_plus_delta[kAmbientSize];
|
| 215 |
+
for (int i = 0; i < kAmbientSize; ++i) {
|
| 216 |
+
x_plus_delta[i] = 0.0;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
const double* parameter_ptrs[2] = {x, zero_delta};
|
| 220 |
+
|
| 221 |
+
// PlusJacobian is D_2 Plus(x,0) so we only need to compute the Jacobian
|
| 222 |
+
// w.r.t. the second argument.
|
| 223 |
+
double* jacobian_ptrs[2] = {nullptr, jacobian};
|
| 224 |
+
return internal::AutoDifferentiate<
|
| 225 |
+
kAmbientSize,
|
| 226 |
+
internal::StaticParameterDims<kAmbientSize, kTangentSize>>(
|
| 227 |
+
internal::PlusWrapper<Functor>(*functor_),
|
| 228 |
+
parameter_ptrs,
|
| 229 |
+
kAmbientSize,
|
| 230 |
+
x_plus_delta,
|
| 231 |
+
jacobian_ptrs);
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
template <typename Functor, int kAmbientSize, int kTangentSize>
|
| 235 |
+
bool AutoDiffManifold<Functor, kAmbientSize, kTangentSize>::MinusJacobian(
|
| 236 |
+
const double* x, double* jacobian) const {
|
| 237 |
+
double y_minus_x[kTangentSize];
|
| 238 |
+
for (int i = 0; i < kTangentSize; ++i) {
|
| 239 |
+
y_minus_x[i] = 0.0;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
const double* parameter_ptrs[2] = {x, x};
|
| 243 |
+
|
| 244 |
+
// MinusJacobian is D_1 Minus(x,x), so we only need to compute the Jacobian
|
| 245 |
+
// w.r.t. the first argument.
|
| 246 |
+
double* jacobian_ptrs[2] = {jacobian, nullptr};
|
| 247 |
+
return internal::AutoDifferentiate<
|
| 248 |
+
kTangentSize,
|
| 249 |
+
internal::StaticParameterDims<kAmbientSize, kAmbientSize>>(
|
| 250 |
+
internal::MinusWrapper<Functor>(*functor_),
|
| 251 |
+
parameter_ptrs,
|
| 252 |
+
kTangentSize,
|
| 253 |
+
y_minus_x,
|
| 254 |
+
jacobian_ptrs);
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
} // namespace ceres
|
| 258 |
+
|
| 259 |
+
#endif // CERES_PUBLIC_AUTODIFF_MANIFOLD_H_
|
ceres-v2/include/c_api.h
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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: mierle@gmail.com (Keir Mierle)
|
| 30 |
+
*
|
| 31 |
+
* A minimal C API for Ceres. Not all functionality is included. This API is
|
| 32 |
+
* not intended for clients of Ceres, but is instead intended for easing the
|
| 33 |
+
* process of binding Ceres to other languages.
|
| 34 |
+
*
|
| 35 |
+
* Currently this is a work in progress.
|
| 36 |
+
*/
|
| 37 |
+
|
| 38 |
+
#ifndef CERES_PUBLIC_C_API_H_
|
| 39 |
+
#define CERES_PUBLIC_C_API_H_
|
| 40 |
+
|
| 41 |
+
// clang-format off
|
| 42 |
+
#include "ceres/internal/export.h"
|
| 43 |
+
#include "ceres/internal/disable_warnings.h"
|
| 44 |
+
// clang-format on
|
| 45 |
+
|
| 46 |
+
#ifdef __cplusplus
|
| 47 |
+
extern "C" {
|
| 48 |
+
#endif
|
| 49 |
+
|
| 50 |
+
/* Init the Ceres private data. Must be called before anything else. */
|
| 51 |
+
CERES_EXPORT void ceres_init();
|
| 52 |
+
|
| 53 |
+
/* Equivalent to CostFunction::Evaluate() in the C++ API.
|
| 54 |
+
*
|
| 55 |
+
* The user may keep private information inside the opaque user_data object.
|
| 56 |
+
* The pointer here is the same one passed in the ceres_add_residual_block().
|
| 57 |
+
*/
|
| 58 |
+
typedef int (*ceres_cost_function_t)(void* user_data,
|
| 59 |
+
double** parameters,
|
| 60 |
+
double* residuals,
|
| 61 |
+
double** jacobians);
|
| 62 |
+
|
| 63 |
+
/* Equivalent to LossFunction::Evaluate() from the C++ API. */
|
| 64 |
+
typedef void (*ceres_loss_function_t)(void* user_data,
|
| 65 |
+
double squared_norm,
|
| 66 |
+
double out[3]);
|
| 67 |
+
|
| 68 |
+
/* Create callback data for Ceres' stock loss functions.
|
| 69 |
+
*
|
| 70 |
+
* Ceres has several loss functions available by default, and these functions
|
| 71 |
+
* expose those to the C API. To use the stock loss functions, call
|
| 72 |
+
* ceres_create_*_loss_data(), which internally creates an instance of one of
|
| 73 |
+
* the stock loss functions (for example ceres::CauchyLoss), and pass the
|
| 74 |
+
* returned "loss_function_data" along with the ceres_stock_loss_function to
|
| 75 |
+
* ceres_add_residual_block().
|
| 76 |
+
*
|
| 77 |
+
* For example:
|
| 78 |
+
*
|
| 79 |
+
* void* cauchy_loss_function_data =
|
| 80 |
+
* ceres_create_cauchy_loss_function_data(1.2, 0.0);
|
| 81 |
+
* ceres_problem_add_residual_block(
|
| 82 |
+
* problem,
|
| 83 |
+
* my_cost_function,
|
| 84 |
+
* my_cost_function_data,
|
| 85 |
+
* ceres_stock_loss_function,
|
| 86 |
+
* cauchy_loss_function_data,
|
| 87 |
+
* 1,
|
| 88 |
+
* 2,
|
| 89 |
+
* parameter_sizes,
|
| 90 |
+
* parameter_pointers);
|
| 91 |
+
* ...
|
| 92 |
+
* ceres_free_stock_loss_function_data(cauchy_loss_function_data);
|
| 93 |
+
*
|
| 94 |
+
* See loss_function.h for the details of each loss function.
|
| 95 |
+
*/
|
| 96 |
+
CERES_EXPORT void* ceres_create_huber_loss_function_data(double a);
|
| 97 |
+
CERES_EXPORT void* ceres_create_softl1_loss_function_data(double a);
|
| 98 |
+
CERES_EXPORT void* ceres_create_cauchy_loss_function_data(double a);
|
| 99 |
+
CERES_EXPORT void* ceres_create_arctan_loss_function_data(double a);
|
| 100 |
+
CERES_EXPORT void* ceres_create_tolerant_loss_function_data(double a, double b);
|
| 101 |
+
|
| 102 |
+
/* Free the given stock loss function data. */
|
| 103 |
+
CERES_EXPORT void ceres_free_stock_loss_function_data(void* loss_function_data);
|
| 104 |
+
|
| 105 |
+
/* This is an implementation of ceres_loss_function_t contained within Ceres
|
| 106 |
+
* itself, intended as a way to access the various stock Ceres loss functions
|
| 107 |
+
* from the C API. This should be passed to ceres_add_residual() below, in
|
| 108 |
+
* combination with a user_data pointer generated by
|
| 109 |
+
* ceres_create_stock_loss_function() above. */
|
| 110 |
+
CERES_EXPORT void ceres_stock_loss_function(void* user_data,
|
| 111 |
+
double squared_norm,
|
| 112 |
+
double out[3]);
|
| 113 |
+
|
| 114 |
+
/* Equivalent to Problem from the C++ API. */
|
| 115 |
+
struct ceres_problem_s;
|
| 116 |
+
typedef struct ceres_problem_s ceres_problem_t;
|
| 117 |
+
|
| 118 |
+
struct ceres_residual_block_id_s;
|
| 119 |
+
typedef struct ceres_residual_block_id_s ceres_residual_block_id_t;
|
| 120 |
+
|
| 121 |
+
/* Create and destroy a problem */
|
| 122 |
+
/* TODO(keir): Add options for the problem. */
|
| 123 |
+
CERES_EXPORT ceres_problem_t* ceres_create_problem();
|
| 124 |
+
CERES_EXPORT void ceres_free_problem(ceres_problem_t* problem);
|
| 125 |
+
|
| 126 |
+
/* Add a residual block. */
|
| 127 |
+
CERES_EXPORT ceres_residual_block_id_t* ceres_problem_add_residual_block(
|
| 128 |
+
ceres_problem_t* problem,
|
| 129 |
+
ceres_cost_function_t cost_function,
|
| 130 |
+
void* cost_function_data,
|
| 131 |
+
ceres_loss_function_t loss_function,
|
| 132 |
+
void* loss_function_data,
|
| 133 |
+
int num_residuals,
|
| 134 |
+
int num_parameter_blocks,
|
| 135 |
+
int* parameter_block_sizes,
|
| 136 |
+
double** parameters);
|
| 137 |
+
|
| 138 |
+
CERES_EXPORT void ceres_solve(ceres_problem_t* problem);
|
| 139 |
+
|
| 140 |
+
/* TODO(keir): Figure out a way to pass a config in. */
|
| 141 |
+
|
| 142 |
+
#ifdef __cplusplus
|
| 143 |
+
}
|
| 144 |
+
#endif
|
| 145 |
+
|
| 146 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 147 |
+
|
| 148 |
+
#endif /* CERES_PUBLIC_C_API_H_ */
|
ceres-v2/include/ceres.h
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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: keir@google.com (Keir Mierle)
|
| 30 |
+
//
|
| 31 |
+
// This is a forwarding header containing the public symbols exported from
|
| 32 |
+
// Ceres. Anything in the "ceres" namespace is available for use.
|
| 33 |
+
|
| 34 |
+
#ifndef CERES_PUBLIC_CERES_H_
|
| 35 |
+
#define CERES_PUBLIC_CERES_H_
|
| 36 |
+
|
| 37 |
+
#include "ceres/autodiff_cost_function.h"
|
| 38 |
+
#include "ceres/autodiff_first_order_function.h"
|
| 39 |
+
#include "ceres/autodiff_local_parameterization.h"
|
| 40 |
+
#include "ceres/autodiff_manifold.h"
|
| 41 |
+
#include "ceres/conditioned_cost_function.h"
|
| 42 |
+
#include "ceres/context.h"
|
| 43 |
+
#include "ceres/cost_function.h"
|
| 44 |
+
#include "ceres/cost_function_to_functor.h"
|
| 45 |
+
#include "ceres/covariance.h"
|
| 46 |
+
#include "ceres/crs_matrix.h"
|
| 47 |
+
#include "ceres/dynamic_autodiff_cost_function.h"
|
| 48 |
+
#include "ceres/dynamic_cost_function.h"
|
| 49 |
+
#include "ceres/dynamic_cost_function_to_functor.h"
|
| 50 |
+
#include "ceres/dynamic_numeric_diff_cost_function.h"
|
| 51 |
+
#include "ceres/evaluation_callback.h"
|
| 52 |
+
#include "ceres/first_order_function.h"
|
| 53 |
+
#include "ceres/gradient_checker.h"
|
| 54 |
+
#include "ceres/gradient_problem.h"
|
| 55 |
+
#include "ceres/gradient_problem_solver.h"
|
| 56 |
+
#include "ceres/iteration_callback.h"
|
| 57 |
+
#include "ceres/jet.h"
|
| 58 |
+
#include "ceres/line_manifold.h"
|
| 59 |
+
#include "ceres/local_parameterization.h"
|
| 60 |
+
#include "ceres/loss_function.h"
|
| 61 |
+
#include "ceres/manifold.h"
|
| 62 |
+
#include "ceres/numeric_diff_cost_function.h"
|
| 63 |
+
#include "ceres/numeric_diff_first_order_function.h"
|
| 64 |
+
#include "ceres/numeric_diff_options.h"
|
| 65 |
+
#include "ceres/ordered_groups.h"
|
| 66 |
+
#include "ceres/problem.h"
|
| 67 |
+
#include "ceres/product_manifold.h"
|
| 68 |
+
#include "ceres/sized_cost_function.h"
|
| 69 |
+
#include "ceres/solver.h"
|
| 70 |
+
#include "ceres/sphere_manifold.h"
|
| 71 |
+
#include "ceres/types.h"
|
| 72 |
+
#include "ceres/version.h"
|
| 73 |
+
|
| 74 |
+
#endif // CERES_PUBLIC_CERES_H_
|
ceres-v2/include/conditioned_cost_function.h
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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: wjr@google.com (William Rucklidge)
|
| 30 |
+
//
|
| 31 |
+
// This file contains a cost function that can apply a transformation to
|
| 32 |
+
// each residual value before they are square-summed.
|
| 33 |
+
|
| 34 |
+
#ifndef CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_
|
| 35 |
+
#define CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_
|
| 36 |
+
|
| 37 |
+
#include <memory>
|
| 38 |
+
#include <vector>
|
| 39 |
+
|
| 40 |
+
#include "ceres/cost_function.h"
|
| 41 |
+
#include "ceres/internal/disable_warnings.h"
|
| 42 |
+
#include "ceres/types.h"
|
| 43 |
+
|
| 44 |
+
namespace ceres {
|
| 45 |
+
|
| 46 |
+
// This class allows you to apply different conditioning to the residual
|
| 47 |
+
// values of a wrapped cost function. An example where this is useful is
|
| 48 |
+
// where you have an existing cost function that produces N values, but you
|
| 49 |
+
// want the total cost to be something other than just the sum of these
|
| 50 |
+
// squared values - maybe you want to apply a different scaling to some
|
| 51 |
+
// values, to change their contribution to the cost.
|
| 52 |
+
//
|
| 53 |
+
// Usage:
|
| 54 |
+
//
|
| 55 |
+
// // my_cost_function produces N residuals
|
| 56 |
+
// CostFunction* my_cost_function = ...
|
| 57 |
+
// CHECK_EQ(N, my_cost_function->num_residuals());
|
| 58 |
+
// vector<CostFunction*> conditioners;
|
| 59 |
+
//
|
| 60 |
+
// // Make N 1x1 cost functions (1 parameter, 1 residual)
|
| 61 |
+
// CostFunction* f_1 = ...
|
| 62 |
+
// conditioners.push_back(f_1);
|
| 63 |
+
// ...
|
| 64 |
+
// CostFunction* f_N = ...
|
| 65 |
+
// conditioners.push_back(f_N);
|
| 66 |
+
// ConditionedCostFunction* ccf =
|
| 67 |
+
// new ConditionedCostFunction(my_cost_function, conditioners);
|
| 68 |
+
//
|
| 69 |
+
// Now ccf's residual i (i=0..N-1) will be passed though the i'th conditioner.
|
| 70 |
+
//
|
| 71 |
+
// ccf_residual[i] = f_i(my_cost_function_residual[i])
|
| 72 |
+
//
|
| 73 |
+
// and the Jacobian will be affected appropriately.
|
| 74 |
+
class CERES_EXPORT ConditionedCostFunction final : public CostFunction {
|
| 75 |
+
public:
|
| 76 |
+
// Builds a cost function based on a wrapped cost function, and a
|
| 77 |
+
// per-residual conditioner. Takes ownership of all of the wrapped cost
|
| 78 |
+
// functions, or not, depending on the ownership parameter. Conditioners
|
| 79 |
+
// may be nullptr, in which case the corresponding residual is not modified.
|
| 80 |
+
//
|
| 81 |
+
// The conditioners can repeat.
|
| 82 |
+
ConditionedCostFunction(CostFunction* wrapped_cost_function,
|
| 83 |
+
const std::vector<CostFunction*>& conditioners,
|
| 84 |
+
Ownership ownership);
|
| 85 |
+
~ConditionedCostFunction() override;
|
| 86 |
+
|
| 87 |
+
bool Evaluate(double const* const* parameters,
|
| 88 |
+
double* residuals,
|
| 89 |
+
double** jacobians) const override;
|
| 90 |
+
|
| 91 |
+
private:
|
| 92 |
+
std::unique_ptr<CostFunction> wrapped_cost_function_;
|
| 93 |
+
std::vector<CostFunction*> conditioners_;
|
| 94 |
+
Ownership ownership_;
|
| 95 |
+
};
|
| 96 |
+
|
| 97 |
+
} // namespace ceres
|
| 98 |
+
|
| 99 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 100 |
+
|
| 101 |
+
#endif // CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_
|
ceres-v2/include/context.h
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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: vitus@google.com (Michael Vitus)
|
| 30 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_CONTEXT_H_
|
| 32 |
+
#define CERES_PUBLIC_CONTEXT_H_
|
| 33 |
+
|
| 34 |
+
#include "ceres/internal/export.h"
|
| 35 |
+
|
| 36 |
+
namespace ceres {
|
| 37 |
+
|
| 38 |
+
// A global context for processing data in Ceres. This provides a mechanism to
|
| 39 |
+
// allow Ceres to reuse items that are expensive to create between multiple
|
| 40 |
+
// calls; for example, thread pools. The same Context can be used on multiple
|
| 41 |
+
// Problems, either serially or in parallel. When using it with multiple
|
| 42 |
+
// Problems at the same time, they may end up contending for resources
|
| 43 |
+
// (e.g. threads) managed by the Context.
|
| 44 |
+
class CERES_EXPORT Context {
|
| 45 |
+
public:
|
| 46 |
+
Context();
|
| 47 |
+
Context(const Context&) = delete;
|
| 48 |
+
void operator=(const Context&) = delete;
|
| 49 |
+
|
| 50 |
+
virtual ~Context();
|
| 51 |
+
|
| 52 |
+
// Creates a context object and the caller takes ownership.
|
| 53 |
+
static Context* Create();
|
| 54 |
+
};
|
| 55 |
+
|
| 56 |
+
} // namespace ceres
|
| 57 |
+
|
| 58 |
+
#endif // CERES_PUBLIC_CONTEXT_H_
|
ceres-v2/include/cost_function.h
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
// keir@google.m (Keir Mierle)
|
| 31 |
+
//
|
| 32 |
+
// This is the interface through which the least squares solver accesses the
|
| 33 |
+
// residual and Jacobian of the least squares problem. Users are expected to
|
| 34 |
+
// subclass CostFunction to define their own terms in the least squares problem.
|
| 35 |
+
//
|
| 36 |
+
// It is recommended that users define templated residual functors for use as
|
| 37 |
+
// arguments for AutoDiffCostFunction (see autodiff_cost_function.h), instead of
|
| 38 |
+
// directly implementing the CostFunction interface. This often results in both
|
| 39 |
+
// shorter code and faster execution than hand-coded derivatives. However,
|
| 40 |
+
// specialized cases may demand direct implementation of the lower-level
|
| 41 |
+
// CostFunction interface; for example, this is true when calling legacy code
|
| 42 |
+
// which is not templated on numeric types.
|
| 43 |
+
|
| 44 |
+
#ifndef CERES_PUBLIC_COST_FUNCTION_H_
|
| 45 |
+
#define CERES_PUBLIC_COST_FUNCTION_H_
|
| 46 |
+
|
| 47 |
+
#include <cstdint>
|
| 48 |
+
#include <vector>
|
| 49 |
+
|
| 50 |
+
#include "ceres/internal/disable_warnings.h"
|
| 51 |
+
#include "ceres/internal/export.h"
|
| 52 |
+
|
| 53 |
+
namespace ceres {
|
| 54 |
+
|
| 55 |
+
// This class implements the computation of the cost (a.k.a. residual) terms as
|
| 56 |
+
// a function of the input (control) variables, and is the interface for users
|
| 57 |
+
// to describe their least squares problem to Ceres. In other words, this is the
|
| 58 |
+
// modeling layer between users and the Ceres optimizer. The signature of the
|
| 59 |
+
// function (number and sizes of input parameter blocks and number of outputs)
|
| 60 |
+
// is stored in parameter_block_sizes_ and num_residuals_ respectively. User
|
| 61 |
+
// code inheriting from this class is expected to set these two members with the
|
| 62 |
+
// corresponding accessors. This information will be verified by the Problem
|
| 63 |
+
// when added with AddResidualBlock().
|
| 64 |
+
class CERES_EXPORT CostFunction {
|
| 65 |
+
public:
|
| 66 |
+
CostFunction();
|
| 67 |
+
CostFunction(const CostFunction&) = delete;
|
| 68 |
+
void operator=(const CostFunction&) = delete;
|
| 69 |
+
|
| 70 |
+
virtual ~CostFunction();
|
| 71 |
+
|
| 72 |
+
// Inputs:
|
| 73 |
+
//
|
| 74 |
+
// parameters is an array of pointers to arrays containing the
|
| 75 |
+
// various parameter blocks. parameters has the same number of
|
| 76 |
+
// elements as parameter_block_sizes_. Parameter blocks are in the
|
| 77 |
+
// same order as parameter_block_sizes_.i.e.,
|
| 78 |
+
//
|
| 79 |
+
// parameters_[i] = double[parameter_block_sizes_[i]]
|
| 80 |
+
//
|
| 81 |
+
// Outputs:
|
| 82 |
+
//
|
| 83 |
+
// residuals is an array of size num_residuals_.
|
| 84 |
+
//
|
| 85 |
+
// jacobians is an array of size parameter_block_sizes_ containing
|
| 86 |
+
// pointers to storage for jacobian blocks corresponding to each
|
| 87 |
+
// parameter block. Jacobian blocks are in the same order as
|
| 88 |
+
// parameter_block_sizes, i.e. jacobians[i], is an
|
| 89 |
+
// array that contains num_residuals_* parameter_block_sizes_[i]
|
| 90 |
+
// elements. Each jacobian block is stored in row-major order, i.e.,
|
| 91 |
+
//
|
| 92 |
+
// jacobians[i][r*parameter_block_size_[i] + c] =
|
| 93 |
+
// d residual[r] / d parameters[i][c]
|
| 94 |
+
//
|
| 95 |
+
// If jacobians is nullptr, then no derivatives are returned; this is
|
| 96 |
+
// the case when computing cost only. If jacobians[i] is nullptr, then
|
| 97 |
+
// the jacobian block corresponding to the i'th parameter block must
|
| 98 |
+
// not to be returned.
|
| 99 |
+
//
|
| 100 |
+
// The return value indicates whether the computation of the
|
| 101 |
+
// residuals and/or jacobians was successful or not.
|
| 102 |
+
//
|
| 103 |
+
// This can be used to communicate numerical failures in jacobian
|
| 104 |
+
// computations for instance.
|
| 105 |
+
//
|
| 106 |
+
// A more interesting and common use is to impose constraints on the
|
| 107 |
+
// parameters. If the initial values of the parameter blocks satisfy
|
| 108 |
+
// the constraints, then returning false whenever the constraints
|
| 109 |
+
// are not satisfied will prevent the solver from moving into the
|
| 110 |
+
// infeasible region. This is not a very sophisticated mechanism for
|
| 111 |
+
// enforcing constraints, but is often good enough.
|
| 112 |
+
//
|
| 113 |
+
// Note that it is important that the initial values of the
|
| 114 |
+
// parameter block must be feasible, otherwise the solver will
|
| 115 |
+
// declare a numerical problem at iteration 0.
|
| 116 |
+
virtual bool Evaluate(double const* const* parameters,
|
| 117 |
+
double* residuals,
|
| 118 |
+
double** jacobians) const = 0;
|
| 119 |
+
|
| 120 |
+
const std::vector<int32_t>& parameter_block_sizes() const {
|
| 121 |
+
return parameter_block_sizes_;
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
int num_residuals() const { return num_residuals_; }
|
| 125 |
+
|
| 126 |
+
protected:
|
| 127 |
+
std::vector<int32_t>* mutable_parameter_block_sizes() {
|
| 128 |
+
return ¶meter_block_sizes_;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
void set_num_residuals(int num_residuals) { num_residuals_ = num_residuals; }
|
| 132 |
+
|
| 133 |
+
private:
|
| 134 |
+
// Cost function signature metadata: number of inputs & their sizes,
|
| 135 |
+
// number of outputs (residuals).
|
| 136 |
+
std::vector<int32_t> parameter_block_sizes_;
|
| 137 |
+
int num_residuals_;
|
| 138 |
+
};
|
| 139 |
+
|
| 140 |
+
} // namespace ceres
|
| 141 |
+
|
| 142 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 143 |
+
|
| 144 |
+
#endif // CERES_PUBLIC_COST_FUNCTION_H_
|
ceres-v2/include/cost_function_to_functor.h
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
//
|
| 31 |
+
// CostFunctionToFunctor is an adapter class that allows users to use
|
| 32 |
+
// SizedCostFunction objects in templated functors which are to be used for
|
| 33 |
+
// automatic differentiation. This allows the user to seamlessly mix
|
| 34 |
+
// analytic, numeric and automatic differentiation.
|
| 35 |
+
//
|
| 36 |
+
// For example, let us assume that
|
| 37 |
+
//
|
| 38 |
+
// class IntrinsicProjection : public SizedCostFunction<2, 5, 3> {
|
| 39 |
+
// public:
|
| 40 |
+
// IntrinsicProjection(const double* observation);
|
| 41 |
+
// bool Evaluate(double const* const* parameters,
|
| 42 |
+
// double* residuals,
|
| 43 |
+
// double** jacobians) const override;
|
| 44 |
+
// };
|
| 45 |
+
//
|
| 46 |
+
// is a cost function that implements the projection of a point in its
|
| 47 |
+
// local coordinate system onto its image plane and subtracts it from
|
| 48 |
+
// the observed point projection. It can compute its residual and
|
| 49 |
+
// jacobians either via analytic or numerical differentiation.
|
| 50 |
+
//
|
| 51 |
+
// Now we would like to compose the action of this CostFunction with
|
| 52 |
+
// the action of camera extrinsics, i.e., rotation and
|
| 53 |
+
// translation. Say we have a templated function
|
| 54 |
+
//
|
| 55 |
+
// template<typename T>
|
| 56 |
+
// void RotateAndTranslatePoint(const T* rotation,
|
| 57 |
+
// const T* translation,
|
| 58 |
+
// const T* point,
|
| 59 |
+
// T* result);
|
| 60 |
+
//
|
| 61 |
+
// Then we can now do the following,
|
| 62 |
+
//
|
| 63 |
+
// struct CameraProjection {
|
| 64 |
+
// CameraProjection(const double* observation)
|
| 65 |
+
// : intrinsic_projection_(new IntrinsicProjection(observation)) {
|
| 66 |
+
// }
|
| 67 |
+
// template <typename T>
|
| 68 |
+
// bool operator()(const T* rotation,
|
| 69 |
+
// const T* translation,
|
| 70 |
+
// const T* intrinsics,
|
| 71 |
+
// const T* point,
|
| 72 |
+
// T* residual) const {
|
| 73 |
+
// T transformed_point[3];
|
| 74 |
+
// RotateAndTranslatePoint(rotation, translation, point, transformed_point);
|
| 75 |
+
//
|
| 76 |
+
// // Note that we call intrinsic_projection_, just like it was
|
| 77 |
+
// // any other templated functor.
|
| 78 |
+
//
|
| 79 |
+
// return intrinsic_projection_(intrinsics, transformed_point, residual);
|
| 80 |
+
// }
|
| 81 |
+
//
|
| 82 |
+
// private:
|
| 83 |
+
// CostFunctionToFunctor<2,5,3> intrinsic_projection_;
|
| 84 |
+
// };
|
| 85 |
+
|
| 86 |
+
#ifndef CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
|
| 87 |
+
#define CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
|
| 88 |
+
|
| 89 |
+
#include <cstdint>
|
| 90 |
+
#include <numeric>
|
| 91 |
+
#include <tuple>
|
| 92 |
+
#include <utility>
|
| 93 |
+
#include <vector>
|
| 94 |
+
|
| 95 |
+
#include "ceres/cost_function.h"
|
| 96 |
+
#include "ceres/dynamic_cost_function_to_functor.h"
|
| 97 |
+
#include "ceres/internal/export.h"
|
| 98 |
+
#include "ceres/internal/fixed_array.h"
|
| 99 |
+
#include "ceres/internal/parameter_dims.h"
|
| 100 |
+
#include "ceres/types.h"
|
| 101 |
+
#include "glog/logging.h"
|
| 102 |
+
|
| 103 |
+
namespace ceres {
|
| 104 |
+
|
| 105 |
+
template <int kNumResiduals, int... Ns>
|
| 106 |
+
class CostFunctionToFunctor {
|
| 107 |
+
public:
|
| 108 |
+
// Takes ownership of cost_function.
|
| 109 |
+
explicit CostFunctionToFunctor(CostFunction* cost_function)
|
| 110 |
+
: cost_functor_(cost_function) {
|
| 111 |
+
CHECK(cost_function != nullptr);
|
| 112 |
+
CHECK(kNumResiduals > 0 || kNumResiduals == DYNAMIC);
|
| 113 |
+
|
| 114 |
+
const std::vector<int32_t>& parameter_block_sizes =
|
| 115 |
+
cost_function->parameter_block_sizes();
|
| 116 |
+
const int num_parameter_blocks = ParameterDims::kNumParameterBlocks;
|
| 117 |
+
CHECK_EQ(static_cast<int>(parameter_block_sizes.size()),
|
| 118 |
+
num_parameter_blocks);
|
| 119 |
+
|
| 120 |
+
if (parameter_block_sizes.size() == num_parameter_blocks) {
|
| 121 |
+
for (int block = 0; block < num_parameter_blocks; ++block) {
|
| 122 |
+
CHECK_EQ(ParameterDims::GetDim(block), parameter_block_sizes[block])
|
| 123 |
+
<< "Parameter block size missmatch. The specified static parameter "
|
| 124 |
+
"block dimension does not match the one from the cost function.";
|
| 125 |
+
}
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
CHECK_EQ(accumulate(
|
| 129 |
+
parameter_block_sizes.begin(), parameter_block_sizes.end(), 0),
|
| 130 |
+
ParameterDims::kNumParameters);
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
template <typename T, typename... Ts>
|
| 134 |
+
bool operator()(const T* p1, Ts*... ps) const {
|
| 135 |
+
// Add one because of residual block.
|
| 136 |
+
static_assert(sizeof...(Ts) + 1 == ParameterDims::kNumParameterBlocks + 1,
|
| 137 |
+
"Invalid number of parameter blocks specified.");
|
| 138 |
+
|
| 139 |
+
auto params = std::make_tuple(p1, ps...);
|
| 140 |
+
|
| 141 |
+
// Extract residual pointer from params. The residual pointer is the
|
| 142 |
+
// last pointer.
|
| 143 |
+
constexpr int kResidualIndex = ParameterDims::kNumParameterBlocks;
|
| 144 |
+
T* residuals = std::get<kResidualIndex>(params);
|
| 145 |
+
|
| 146 |
+
// Extract parameter block pointers from params.
|
| 147 |
+
using Indices =
|
| 148 |
+
std::make_integer_sequence<int, ParameterDims::kNumParameterBlocks>;
|
| 149 |
+
std::array<const T*, ParameterDims::kNumParameterBlocks> parameter_blocks =
|
| 150 |
+
GetParameterPointers<T>(params, Indices());
|
| 151 |
+
|
| 152 |
+
return cost_functor_(parameter_blocks.data(), residuals);
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
private:
|
| 156 |
+
using ParameterDims = internal::StaticParameterDims<Ns...>;
|
| 157 |
+
|
| 158 |
+
template <typename T, typename Tuple, int... Indices>
|
| 159 |
+
static std::array<const T*, ParameterDims::kNumParameterBlocks>
|
| 160 |
+
GetParameterPointers(const Tuple& paramPointers,
|
| 161 |
+
std::integer_sequence<int, Indices...>) {
|
| 162 |
+
return std::array<const T*, ParameterDims::kNumParameterBlocks>{
|
| 163 |
+
{std::get<Indices>(paramPointers)...}};
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
DynamicCostFunctionToFunctor cost_functor_;
|
| 167 |
+
};
|
| 168 |
+
|
| 169 |
+
} // namespace ceres
|
| 170 |
+
|
| 171 |
+
#endif // CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
|
ceres-v2/include/covariance.h
ADDED
|
@@ -0,0 +1,459 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_COVARIANCE_H_
|
| 32 |
+
#define CERES_PUBLIC_COVARIANCE_H_
|
| 33 |
+
|
| 34 |
+
#include <memory>
|
| 35 |
+
#include <utility>
|
| 36 |
+
#include <vector>
|
| 37 |
+
|
| 38 |
+
#include "ceres/internal/config.h"
|
| 39 |
+
#include "ceres/internal/disable_warnings.h"
|
| 40 |
+
#include "ceres/internal/export.h"
|
| 41 |
+
#include "ceres/types.h"
|
| 42 |
+
|
| 43 |
+
namespace ceres {
|
| 44 |
+
|
| 45 |
+
class Problem;
|
| 46 |
+
|
| 47 |
+
namespace internal {
|
| 48 |
+
class CovarianceImpl;
|
| 49 |
+
} // namespace internal
|
| 50 |
+
|
| 51 |
+
// WARNING
|
| 52 |
+
// =======
|
| 53 |
+
// It is very easy to use this class incorrectly without understanding
|
| 54 |
+
// the underlying mathematics. Please read and understand the
|
| 55 |
+
// documentation completely before attempting to use it.
|
| 56 |
+
//
|
| 57 |
+
//
|
| 58 |
+
// This class allows the user to evaluate the covariance for a
|
| 59 |
+
// non-linear least squares problem and provides random access to its
|
| 60 |
+
// blocks
|
| 61 |
+
//
|
| 62 |
+
// Background
|
| 63 |
+
// ==========
|
| 64 |
+
// One way to assess the quality of the solution returned by a
|
| 65 |
+
// non-linear least squares solver is to analyze the covariance of the
|
| 66 |
+
// solution.
|
| 67 |
+
//
|
| 68 |
+
// Let us consider the non-linear regression problem
|
| 69 |
+
//
|
| 70 |
+
// y = f(x) + N(0, I)
|
| 71 |
+
//
|
| 72 |
+
// i.e., the observation y is a random non-linear function of the
|
| 73 |
+
// independent variable x with mean f(x) and identity covariance. Then
|
| 74 |
+
// the maximum likelihood estimate of x given observations y is the
|
| 75 |
+
// solution to the non-linear least squares problem:
|
| 76 |
+
//
|
| 77 |
+
// x* = arg min_x |f(x) - y|^2
|
| 78 |
+
//
|
| 79 |
+
// And the covariance of x* is given by
|
| 80 |
+
//
|
| 81 |
+
// C(x*) = inverse[J'(x*)J(x*)]
|
| 82 |
+
//
|
| 83 |
+
// Here J(x*) is the Jacobian of f at x*. The above formula assumes
|
| 84 |
+
// that J(x*) has full column rank.
|
| 85 |
+
//
|
| 86 |
+
// If J(x*) is rank deficient, then the covariance matrix C(x*) is
|
| 87 |
+
// also rank deficient and is given by
|
| 88 |
+
//
|
| 89 |
+
// C(x*) = pseudoinverse[J'(x*)J(x*)]
|
| 90 |
+
//
|
| 91 |
+
// Note that in the above, we assumed that the covariance
|
| 92 |
+
// matrix for y was identity. This is an important assumption. If this
|
| 93 |
+
// is not the case and we have
|
| 94 |
+
//
|
| 95 |
+
// y = f(x) + N(0, S)
|
| 96 |
+
//
|
| 97 |
+
// Where S is a positive semi-definite matrix denoting the covariance
|
| 98 |
+
// of y, then the maximum likelihood problem to be solved is
|
| 99 |
+
//
|
| 100 |
+
// x* = arg min_x f'(x) inverse[S] f(x)
|
| 101 |
+
//
|
| 102 |
+
// and the corresponding covariance estimate of x* is given by
|
| 103 |
+
//
|
| 104 |
+
// C(x*) = inverse[J'(x*) inverse[S] J(x*)]
|
| 105 |
+
//
|
| 106 |
+
// So, if it is the case that the observations being fitted to have a
|
| 107 |
+
// covariance matrix not equal to identity, then it is the user's
|
| 108 |
+
// responsibility that the corresponding cost functions are correctly
|
| 109 |
+
// scaled, e.g. in the above case the cost function for this problem
|
| 110 |
+
// should evaluate S^{-1/2} f(x) instead of just f(x), where S^{-1/2}
|
| 111 |
+
// is the inverse square root of the covariance matrix S.
|
| 112 |
+
//
|
| 113 |
+
// This class allows the user to evaluate the covariance for a
|
| 114 |
+
// non-linear least squares problem and provides random access to its
|
| 115 |
+
// blocks. The computation assumes that the CostFunctions compute
|
| 116 |
+
// residuals such that their covariance is identity.
|
| 117 |
+
//
|
| 118 |
+
// Since the computation of the covariance matrix requires computing
|
| 119 |
+
// the inverse of a potentially large matrix, this can involve a
|
| 120 |
+
// rather large amount of time and memory. However, it is usually the
|
| 121 |
+
// case that the user is only interested in a small part of the
|
| 122 |
+
// covariance matrix. Quite often just the block diagonal. This class
|
| 123 |
+
// allows the user to specify the parts of the covariance matrix that
|
| 124 |
+
// she is interested in and then uses this information to only compute
|
| 125 |
+
// and store those parts of the covariance matrix.
|
| 126 |
+
//
|
| 127 |
+
// Rank of the Jacobian
|
| 128 |
+
// --------------------
|
| 129 |
+
// As we noted above, if the jacobian is rank deficient, then the
|
| 130 |
+
// inverse of J'J is not defined and instead a pseudo inverse needs to
|
| 131 |
+
// be computed.
|
| 132 |
+
//
|
| 133 |
+
// The rank deficiency in J can be structural -- columns which are
|
| 134 |
+
// always known to be zero or numerical -- depending on the exact
|
| 135 |
+
// values in the Jacobian.
|
| 136 |
+
//
|
| 137 |
+
// Structural rank deficiency occurs when the problem contains
|
| 138 |
+
// parameter blocks that are constant. This class correctly handles
|
| 139 |
+
// structural rank deficiency like that.
|
| 140 |
+
//
|
| 141 |
+
// Numerical rank deficiency, where the rank of the matrix cannot be
|
| 142 |
+
// predicted by its sparsity structure and requires looking at its
|
| 143 |
+
// numerical values is more complicated. Here again there are two
|
| 144 |
+
// cases.
|
| 145 |
+
//
|
| 146 |
+
// a. The rank deficiency arises from overparameterization. e.g., a
|
| 147 |
+
// four dimensional quaternion used to parameterize SO(3), which is
|
| 148 |
+
// a three dimensional manifold. In cases like this, the user should
|
| 149 |
+
// use an appropriate LocalParameterization/Manifold. Not only will this lead
|
| 150 |
+
// to better numerical behaviour of the Solver, it will also expose
|
| 151 |
+
// the rank deficiency to the Covariance object so that it can
|
| 152 |
+
// handle it correctly.
|
| 153 |
+
//
|
| 154 |
+
// b. More general numerical rank deficiency in the Jacobian
|
| 155 |
+
// requires the computation of the so called Singular Value
|
| 156 |
+
// Decomposition (SVD) of J'J. We do not know how to do this for
|
| 157 |
+
// large sparse matrices efficiently. For small and moderate sized
|
| 158 |
+
// problems this is done using dense linear algebra.
|
| 159 |
+
//
|
| 160 |
+
// Gauge Invariance
|
| 161 |
+
// ----------------
|
| 162 |
+
// In structure from motion (3D reconstruction) problems, the
|
| 163 |
+
// reconstruction is ambiguous up to a similarity transform. This is
|
| 164 |
+
// known as a Gauge Ambiguity. Handling Gauges correctly requires the
|
| 165 |
+
// use of SVD or custom inversion algorithms. For small problems the
|
| 166 |
+
// user can use the dense algorithm. For more details see
|
| 167 |
+
//
|
| 168 |
+
// Ken-ichi Kanatani, Daniel D. Morris: Gauges and gauge
|
| 169 |
+
// transformations for uncertainty description of geometric structure
|
| 170 |
+
// with indeterminacy. IEEE Transactions on Information Theory 47(5):
|
| 171 |
+
// 2017-2028 (2001)
|
| 172 |
+
//
|
| 173 |
+
// Example Usage
|
| 174 |
+
// =============
|
| 175 |
+
//
|
| 176 |
+
// double x[3];
|
| 177 |
+
// double y[2];
|
| 178 |
+
//
|
| 179 |
+
// Problem problem;
|
| 180 |
+
// problem.AddParameterBlock(x, 3);
|
| 181 |
+
// problem.AddParameterBlock(y, 2);
|
| 182 |
+
// <Build Problem>
|
| 183 |
+
// <Solve Problem>
|
| 184 |
+
//
|
| 185 |
+
// Covariance::Options options;
|
| 186 |
+
// Covariance covariance(options);
|
| 187 |
+
//
|
| 188 |
+
// std::vector<std::pair<const double*, const double*>> covariance_blocks;
|
| 189 |
+
// covariance_blocks.push_back(make_pair(x, x));
|
| 190 |
+
// covariance_blocks.push_back(make_pair(y, y));
|
| 191 |
+
// covariance_blocks.push_back(make_pair(x, y));
|
| 192 |
+
//
|
| 193 |
+
// CHECK(covariance.Compute(covariance_blocks, &problem));
|
| 194 |
+
//
|
| 195 |
+
// double covariance_xx[3 * 3];
|
| 196 |
+
// double covariance_yy[2 * 2];
|
| 197 |
+
// double covariance_xy[3 * 2];
|
| 198 |
+
// covariance.GetCovarianceBlock(x, x, covariance_xx)
|
| 199 |
+
// covariance.GetCovarianceBlock(y, y, covariance_yy)
|
| 200 |
+
// covariance.GetCovarianceBlock(x, y, covariance_xy)
|
| 201 |
+
//
|
| 202 |
+
class CERES_EXPORT Covariance {
|
| 203 |
+
public:
|
| 204 |
+
struct CERES_EXPORT Options {
|
| 205 |
+
// Sparse linear algebra library to use when a sparse matrix
|
| 206 |
+
// factorization is being used to compute the covariance matrix.
|
| 207 |
+
//
|
| 208 |
+
// Currently this only applies to SPARSE_QR.
|
| 209 |
+
SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type =
|
| 210 |
+
#if !defined(CERES_NO_SUITESPARSE)
|
| 211 |
+
SUITE_SPARSE;
|
| 212 |
+
#else
|
| 213 |
+
// Eigen's QR factorization is always available.
|
| 214 |
+
EIGEN_SPARSE;
|
| 215 |
+
#endif
|
| 216 |
+
|
| 217 |
+
// Ceres supports two different algorithms for covariance
|
| 218 |
+
// estimation, which represent different tradeoffs in speed,
|
| 219 |
+
// accuracy and reliability.
|
| 220 |
+
//
|
| 221 |
+
// 1. DENSE_SVD uses Eigen's JacobiSVD to perform the
|
| 222 |
+
// computations. It computes the singular value decomposition
|
| 223 |
+
//
|
| 224 |
+
// U * D * V' = J
|
| 225 |
+
//
|
| 226 |
+
// and then uses it to compute the pseudo inverse of J'J as
|
| 227 |
+
//
|
| 228 |
+
// pseudoinverse[J'J] = V * pseudoinverse[D^2] * V'
|
| 229 |
+
//
|
| 230 |
+
// It is an accurate but slow method and should only be used
|
| 231 |
+
// for small to moderate sized problems. It can handle
|
| 232 |
+
// full-rank as well as rank deficient Jacobians.
|
| 233 |
+
//
|
| 234 |
+
// 2. SPARSE_QR uses the sparse QR factorization algorithm
|
| 235 |
+
// to compute the decomposition
|
| 236 |
+
//
|
| 237 |
+
// Q * R = J
|
| 238 |
+
//
|
| 239 |
+
// [J'J]^-1 = [R'*R]^-1
|
| 240 |
+
//
|
| 241 |
+
// SPARSE_QR is not capable of computing the covariance if the
|
| 242 |
+
// Jacobian is rank deficient. Depending on the value of
|
| 243 |
+
// Covariance::Options::sparse_linear_algebra_library_type, either
|
| 244 |
+
// Eigen's Sparse QR factorization algorithm will be used or
|
| 245 |
+
// SuiteSparse's high performance SuiteSparseQR algorithm will be
|
| 246 |
+
// used.
|
| 247 |
+
CovarianceAlgorithmType algorithm_type = SPARSE_QR;
|
| 248 |
+
|
| 249 |
+
// If the Jacobian matrix is near singular, then inverting J'J
|
| 250 |
+
// will result in unreliable results, e.g, if
|
| 251 |
+
//
|
| 252 |
+
// J = [1.0 1.0 ]
|
| 253 |
+
// [1.0 1.0000001 ]
|
| 254 |
+
//
|
| 255 |
+
// which is essentially a rank deficient matrix, we have
|
| 256 |
+
//
|
| 257 |
+
// inv(J'J) = [ 2.0471e+14 -2.0471e+14]
|
| 258 |
+
// [-2.0471e+14 2.0471e+14]
|
| 259 |
+
//
|
| 260 |
+
// This is not a useful result. Therefore, by default
|
| 261 |
+
// Covariance::Compute will return false if a rank deficient
|
| 262 |
+
// Jacobian is encountered. How rank deficiency is detected
|
| 263 |
+
// depends on the algorithm being used.
|
| 264 |
+
//
|
| 265 |
+
// 1. DENSE_SVD
|
| 266 |
+
//
|
| 267 |
+
// min_sigma / max_sigma < sqrt(min_reciprocal_condition_number)
|
| 268 |
+
//
|
| 269 |
+
// where min_sigma and max_sigma are the minimum and maxiumum
|
| 270 |
+
// singular values of J respectively.
|
| 271 |
+
//
|
| 272 |
+
// 2. SPARSE_QR
|
| 273 |
+
//
|
| 274 |
+
// rank(J) < num_col(J)
|
| 275 |
+
//
|
| 276 |
+
// Here rank(J) is the estimate of the rank of J returned by the
|
| 277 |
+
// sparse QR factorization algorithm. It is a fairly reliable
|
| 278 |
+
// indication of rank deficiency.
|
| 279 |
+
//
|
| 280 |
+
double min_reciprocal_condition_number = 1e-14;
|
| 281 |
+
|
| 282 |
+
// When using DENSE_SVD, the user has more control in dealing with
|
| 283 |
+
// singular and near singular covariance matrices.
|
| 284 |
+
//
|
| 285 |
+
// As mentioned above, when the covariance matrix is near
|
| 286 |
+
// singular, instead of computing the inverse of J'J, the
|
| 287 |
+
// Moore-Penrose pseudoinverse of J'J should be computed.
|
| 288 |
+
//
|
| 289 |
+
// If J'J has the eigen decomposition (lambda_i, e_i), where
|
| 290 |
+
// lambda_i is the i^th eigenvalue and e_i is the corresponding
|
| 291 |
+
// eigenvector, then the inverse of J'J is
|
| 292 |
+
//
|
| 293 |
+
// inverse[J'J] = sum_i e_i e_i' / lambda_i
|
| 294 |
+
//
|
| 295 |
+
// and computing the pseudo inverse involves dropping terms from
|
| 296 |
+
// this sum that correspond to small eigenvalues.
|
| 297 |
+
//
|
| 298 |
+
// How terms are dropped is controlled by
|
| 299 |
+
// min_reciprocal_condition_number and null_space_rank.
|
| 300 |
+
//
|
| 301 |
+
// If null_space_rank is non-negative, then the smallest
|
| 302 |
+
// null_space_rank eigenvalue/eigenvectors are dropped
|
| 303 |
+
// irrespective of the magnitude of lambda_i. If the ratio of the
|
| 304 |
+
// smallest non-zero eigenvalue to the largest eigenvalue in the
|
| 305 |
+
// truncated matrix is still below
|
| 306 |
+
// min_reciprocal_condition_number, then the Covariance::Compute()
|
| 307 |
+
// will fail and return false.
|
| 308 |
+
//
|
| 309 |
+
// Setting null_space_rank = -1 drops all terms for which
|
| 310 |
+
//
|
| 311 |
+
// lambda_i / lambda_max < min_reciprocal_condition_number.
|
| 312 |
+
//
|
| 313 |
+
// This option has no effect on the SUITE_SPARSE_QR and
|
| 314 |
+
// EIGEN_SPARSE_QR algorithms.
|
| 315 |
+
int null_space_rank = 0;
|
| 316 |
+
|
| 317 |
+
int num_threads = 1;
|
| 318 |
+
|
| 319 |
+
// Even though the residual blocks in the problem may contain loss
|
| 320 |
+
// functions, setting apply_loss_function to false will turn off
|
| 321 |
+
// the application of the loss function to the output of the cost
|
| 322 |
+
// function and in turn its effect on the covariance.
|
| 323 |
+
//
|
| 324 |
+
// TODO(sameergaarwal): Expand this based on Jim's experiments.
|
| 325 |
+
bool apply_loss_function = true;
|
| 326 |
+
};
|
| 327 |
+
|
| 328 |
+
explicit Covariance(const Options& options);
|
| 329 |
+
~Covariance();
|
| 330 |
+
|
| 331 |
+
// Compute a part of the covariance matrix.
|
| 332 |
+
//
|
| 333 |
+
// The vector covariance_blocks, indexes into the covariance matrix
|
| 334 |
+
// block-wise using pairs of parameter blocks. This allows the
|
| 335 |
+
// covariance estimation algorithm to only compute and store these
|
| 336 |
+
// blocks.
|
| 337 |
+
//
|
| 338 |
+
// Since the covariance matrix is symmetric, if the user passes
|
| 339 |
+
// (block1, block2), then GetCovarianceBlock can be called with
|
| 340 |
+
// block1, block2 as well as block2, block1.
|
| 341 |
+
//
|
| 342 |
+
// covariance_blocks cannot contain duplicates. Bad things will
|
| 343 |
+
// happen if they do.
|
| 344 |
+
//
|
| 345 |
+
// Note that the list of covariance_blocks is only used to determine
|
| 346 |
+
// what parts of the covariance matrix are computed. The full
|
| 347 |
+
// Jacobian is used to do the computation, i.e. they do not have an
|
| 348 |
+
// impact on what part of the Jacobian is used for computation.
|
| 349 |
+
//
|
| 350 |
+
// The return value indicates the success or failure of the
|
| 351 |
+
// covariance computation. Please see the documentation for
|
| 352 |
+
// Covariance::Options for more on the conditions under which this
|
| 353 |
+
// function returns false.
|
| 354 |
+
bool Compute(const std::vector<std::pair<const double*, const double*>>&
|
| 355 |
+
covariance_blocks,
|
| 356 |
+
Problem* problem);
|
| 357 |
+
|
| 358 |
+
// Compute a part of the covariance matrix.
|
| 359 |
+
//
|
| 360 |
+
// The vector parameter_blocks contains the parameter blocks that
|
| 361 |
+
// are used for computing the covariance matrix. From this vector
|
| 362 |
+
// all covariance pairs are generated. This allows the covariance
|
| 363 |
+
// estimation algorithm to only compute and store these blocks.
|
| 364 |
+
//
|
| 365 |
+
// parameter_blocks cannot contain duplicates. Bad things will
|
| 366 |
+
// happen if they do.
|
| 367 |
+
//
|
| 368 |
+
// Note that the list of covariance_blocks is only used to determine
|
| 369 |
+
// what parts of the covariance matrix are computed. The full
|
| 370 |
+
// Jacobian is used to do the computation, i.e. they do not have an
|
| 371 |
+
// impact on what part of the Jacobian is used for computation.
|
| 372 |
+
//
|
| 373 |
+
// The return value indicates the success or failure of the
|
| 374 |
+
// covariance computation. Please see the documentation for
|
| 375 |
+
// Covariance::Options for more on the conditions under which this
|
| 376 |
+
// function returns false.
|
| 377 |
+
bool Compute(const std::vector<const double*>& parameter_blocks,
|
| 378 |
+
Problem* problem);
|
| 379 |
+
|
| 380 |
+
// Return the block of the cross-covariance matrix corresponding to
|
| 381 |
+
// parameter_block1 and parameter_block2.
|
| 382 |
+
//
|
| 383 |
+
// Compute must be called before the first call to
|
| 384 |
+
// GetCovarianceBlock and the pair <parameter_block1,
|
| 385 |
+
// parameter_block2> OR the pair <parameter_block2,
|
| 386 |
+
// parameter_block1> must have been present in the vector
|
| 387 |
+
// covariance_blocks when Compute was called. Otherwise
|
| 388 |
+
// GetCovarianceBlock will return false.
|
| 389 |
+
//
|
| 390 |
+
// covariance_block must point to a memory location that can store a
|
| 391 |
+
// parameter_block1_size x parameter_block2_size matrix. The
|
| 392 |
+
// returned covariance will be a row-major matrix.
|
| 393 |
+
bool GetCovarianceBlock(const double* parameter_block1,
|
| 394 |
+
const double* parameter_block2,
|
| 395 |
+
double* covariance_block) const;
|
| 396 |
+
|
| 397 |
+
// Return the block of the cross-covariance matrix corresponding to
|
| 398 |
+
// parameter_block1 and parameter_block2.
|
| 399 |
+
// Returns cross-covariance in the tangent space if a local
|
| 400 |
+
// parameterization is associated with either parameter block;
|
| 401 |
+
// else returns cross-covariance in the ambient space.
|
| 402 |
+
//
|
| 403 |
+
// Compute must be called before the first call to
|
| 404 |
+
// GetCovarianceBlock and the pair <parameter_block1,
|
| 405 |
+
// parameter_block2> OR the pair <parameter_block2,
|
| 406 |
+
// parameter_block1> must have been present in the vector
|
| 407 |
+
// covariance_blocks when Compute was called. Otherwise
|
| 408 |
+
// GetCovarianceBlock will return false.
|
| 409 |
+
//
|
| 410 |
+
// covariance_block must point to a memory location that can store a
|
| 411 |
+
// parameter_block1_local_size x parameter_block2_local_size matrix. The
|
| 412 |
+
// returned covariance will be a row-major matrix.
|
| 413 |
+
bool GetCovarianceBlockInTangentSpace(const double* parameter_block1,
|
| 414 |
+
const double* parameter_block2,
|
| 415 |
+
double* covariance_block) const;
|
| 416 |
+
|
| 417 |
+
// Return the covariance matrix corresponding to all parameter_blocks.
|
| 418 |
+
//
|
| 419 |
+
// Compute must be called before calling GetCovarianceMatrix and all
|
| 420 |
+
// parameter_blocks must have been present in the vector
|
| 421 |
+
// parameter_blocks when Compute was called. Otherwise
|
| 422 |
+
// GetCovarianceMatrix returns false.
|
| 423 |
+
//
|
| 424 |
+
// covariance_matrix must point to a memory location that can store
|
| 425 |
+
// the size of the covariance matrix. The covariance matrix will be
|
| 426 |
+
// a square matrix whose row and column count is equal to the sum of
|
| 427 |
+
// the sizes of the individual parameter blocks. The covariance
|
| 428 |
+
// matrix will be a row-major matrix.
|
| 429 |
+
bool GetCovarianceMatrix(const std::vector<const double*>& parameter_blocks,
|
| 430 |
+
double* covariance_matrix) const;
|
| 431 |
+
|
| 432 |
+
// Return the covariance matrix corresponding to parameter_blocks
|
| 433 |
+
// in the tangent space if a local parameterization is associated
|
| 434 |
+
// with one of the parameter blocks else returns the covariance
|
| 435 |
+
// matrix in the ambient space.
|
| 436 |
+
//
|
| 437 |
+
// Compute must be called before calling GetCovarianceMatrix and all
|
| 438 |
+
// parameter_blocks must have been present in the vector
|
| 439 |
+
// parameters_blocks when Compute was called. Otherwise
|
| 440 |
+
// GetCovarianceMatrix returns false.
|
| 441 |
+
//
|
| 442 |
+
// covariance_matrix must point to a memory location that can store
|
| 443 |
+
// the size of the covariance matrix. The covariance matrix will be
|
| 444 |
+
// a square matrix whose row and column count is equal to the sum of
|
| 445 |
+
// the sizes of the tangent spaces of the individual parameter
|
| 446 |
+
// blocks. The covariance matrix will be a row-major matrix.
|
| 447 |
+
bool GetCovarianceMatrixInTangentSpace(
|
| 448 |
+
const std::vector<const double*>& parameter_blocks,
|
| 449 |
+
double* covariance_matrix) const;
|
| 450 |
+
|
| 451 |
+
private:
|
| 452 |
+
std::unique_ptr<internal::CovarianceImpl> impl_;
|
| 453 |
+
};
|
| 454 |
+
|
| 455 |
+
} // namespace ceres
|
| 456 |
+
|
| 457 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 458 |
+
|
| 459 |
+
#endif // CERES_PUBLIC_COVARIANCE_H_
|
ceres-v2/include/crs_matrix.h
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_CRS_MATRIX_H_
|
| 32 |
+
#define CERES_PUBLIC_CRS_MATRIX_H_
|
| 33 |
+
|
| 34 |
+
#include <vector>
|
| 35 |
+
|
| 36 |
+
#include "ceres/internal/disable_warnings.h"
|
| 37 |
+
#include "ceres/internal/export.h"
|
| 38 |
+
|
| 39 |
+
namespace ceres {
|
| 40 |
+
|
| 41 |
+
// A compressed row sparse matrix used primarily for communicating the
|
| 42 |
+
// Jacobian matrix to the user.
|
| 43 |
+
struct CERES_EXPORT CRSMatrix {
|
| 44 |
+
CRSMatrix() = default;
|
| 45 |
+
|
| 46 |
+
int num_rows{0};
|
| 47 |
+
int num_cols{0};
|
| 48 |
+
|
| 49 |
+
// A compressed row matrix stores its contents in three arrays,
|
| 50 |
+
// rows, cols and values.
|
| 51 |
+
//
|
| 52 |
+
// rows is a num_rows + 1 sized array that points into the cols and
|
| 53 |
+
// values array. For each row i:
|
| 54 |
+
//
|
| 55 |
+
// cols[rows[i]] ... cols[rows[i + 1] - 1] are the indices of the
|
| 56 |
+
// non-zero columns of row i.
|
| 57 |
+
//
|
| 58 |
+
// values[rows[i]] .. values[rows[i + 1] - 1] are the values of the
|
| 59 |
+
// corresponding entries.
|
| 60 |
+
//
|
| 61 |
+
// cols and values contain as many entries as there are non-zeros in
|
| 62 |
+
// the matrix.
|
| 63 |
+
//
|
| 64 |
+
// e.g, consider the 3x4 sparse matrix
|
| 65 |
+
//
|
| 66 |
+
// [ 0 10 0 4 ]
|
| 67 |
+
// [ 0 2 -3 2 ]
|
| 68 |
+
// [ 1 2 0 0 ]
|
| 69 |
+
//
|
| 70 |
+
// The three arrays will be:
|
| 71 |
+
//
|
| 72 |
+
//
|
| 73 |
+
// -row0- ---row1--- -row2-
|
| 74 |
+
// rows = [ 0, 2, 5, 7]
|
| 75 |
+
// cols = [ 1, 3, 1, 2, 3, 0, 1]
|
| 76 |
+
// values = [10, 4, 2, -3, 2, 1, 2]
|
| 77 |
+
|
| 78 |
+
std::vector<int> cols;
|
| 79 |
+
std::vector<int> rows;
|
| 80 |
+
std::vector<double> values;
|
| 81 |
+
};
|
| 82 |
+
|
| 83 |
+
} // namespace ceres
|
| 84 |
+
|
| 85 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 86 |
+
|
| 87 |
+
#endif // CERES_PUBLIC_CRS_MATRIX_H_
|
ceres-v2/include/cubic_interpolation.h
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_CUBIC_INTERPOLATION_H_
|
| 32 |
+
#define CERES_PUBLIC_CUBIC_INTERPOLATION_H_
|
| 33 |
+
|
| 34 |
+
#include "Eigen/Core"
|
| 35 |
+
#include "ceres/internal/export.h"
|
| 36 |
+
#include "glog/logging.h"
|
| 37 |
+
|
| 38 |
+
namespace ceres {
|
| 39 |
+
|
| 40 |
+
// Given samples from a function sampled at four equally spaced points,
|
| 41 |
+
//
|
| 42 |
+
// p0 = f(-1)
|
| 43 |
+
// p1 = f(0)
|
| 44 |
+
// p2 = f(1)
|
| 45 |
+
// p3 = f(2)
|
| 46 |
+
//
|
| 47 |
+
// Evaluate the cubic Hermite spline (also known as the Catmull-Rom
|
| 48 |
+
// spline) at a point x that lies in the interval [0, 1].
|
| 49 |
+
//
|
| 50 |
+
// This is also the interpolation kernel (for the case of a = 0.5) as
|
| 51 |
+
// proposed by R. Keys, in:
|
| 52 |
+
//
|
| 53 |
+
// "Cubic convolution interpolation for digital image processing".
|
| 54 |
+
// IEEE Transactions on Acoustics, Speech, and Signal Processing
|
| 55 |
+
// 29 (6): 1153-1160.
|
| 56 |
+
//
|
| 57 |
+
// For more details see
|
| 58 |
+
//
|
| 59 |
+
// http://en.wikipedia.org/wiki/Cubic_Hermite_spline
|
| 60 |
+
// http://en.wikipedia.org/wiki/Bicubic_interpolation
|
| 61 |
+
//
|
| 62 |
+
// f if not nullptr will contain the interpolated function values.
|
| 63 |
+
// dfdx if not nullptr will contain the interpolated derivative values.
|
| 64 |
+
template <int kDataDimension>
|
| 65 |
+
void CubicHermiteSpline(const Eigen::Matrix<double, kDataDimension, 1>& p0,
|
| 66 |
+
const Eigen::Matrix<double, kDataDimension, 1>& p1,
|
| 67 |
+
const Eigen::Matrix<double, kDataDimension, 1>& p2,
|
| 68 |
+
const Eigen::Matrix<double, kDataDimension, 1>& p3,
|
| 69 |
+
const double x,
|
| 70 |
+
double* f,
|
| 71 |
+
double* dfdx) {
|
| 72 |
+
using VType = Eigen::Matrix<double, kDataDimension, 1>;
|
| 73 |
+
const VType a = 0.5 * (-p0 + 3.0 * p1 - 3.0 * p2 + p3);
|
| 74 |
+
const VType b = 0.5 * (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3);
|
| 75 |
+
const VType c = 0.5 * (-p0 + p2);
|
| 76 |
+
const VType d = p1;
|
| 77 |
+
|
| 78 |
+
// Use Horner's rule to evaluate the function value and its
|
| 79 |
+
// derivative.
|
| 80 |
+
|
| 81 |
+
// f = ax^3 + bx^2 + cx + d
|
| 82 |
+
if (f != nullptr) {
|
| 83 |
+
Eigen::Map<VType>(f, kDataDimension) = d + x * (c + x * (b + x * a));
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
// dfdx = 3ax^2 + 2bx + c
|
| 87 |
+
if (dfdx != nullptr) {
|
| 88 |
+
Eigen::Map<VType>(dfdx, kDataDimension) = c + x * (2.0 * b + 3.0 * a * x);
|
| 89 |
+
}
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
// Given as input an infinite one dimensional grid, which provides the
|
| 93 |
+
// following interface.
|
| 94 |
+
//
|
| 95 |
+
// class Grid {
|
| 96 |
+
// public:
|
| 97 |
+
// enum { DATA_DIMENSION = 2; };
|
| 98 |
+
// void GetValue(int n, double* f) const;
|
| 99 |
+
// };
|
| 100 |
+
//
|
| 101 |
+
// Here, GetValue gives the value of a function f (possibly vector
|
| 102 |
+
// valued) for any integer n.
|
| 103 |
+
//
|
| 104 |
+
// The enum DATA_DIMENSION indicates the dimensionality of the
|
| 105 |
+
// function being interpolated. For example if you are interpolating
|
| 106 |
+
// rotations in axis-angle format over time, then DATA_DIMENSION = 3.
|
| 107 |
+
//
|
| 108 |
+
// CubicInterpolator uses cubic Hermite splines to produce a smooth
|
| 109 |
+
// approximation to it that can be used to evaluate the f(x) and f'(x)
|
| 110 |
+
// at any point on the real number line.
|
| 111 |
+
//
|
| 112 |
+
// For more details on cubic interpolation see
|
| 113 |
+
//
|
| 114 |
+
// http://en.wikipedia.org/wiki/Cubic_Hermite_spline
|
| 115 |
+
//
|
| 116 |
+
// Example usage:
|
| 117 |
+
//
|
| 118 |
+
// const double data[] = {1.0, 2.0, 5.0, 6.0};
|
| 119 |
+
// Grid1D<double, 1> grid(data, 0, 4);
|
| 120 |
+
// CubicInterpolator<Grid1D<double, 1>> interpolator(grid);
|
| 121 |
+
// double f, dfdx;
|
| 122 |
+
// interpolator.Evaluator(1.5, &f, &dfdx);
|
| 123 |
+
template <typename Grid>
|
| 124 |
+
class CubicInterpolator {
|
| 125 |
+
public:
|
| 126 |
+
explicit CubicInterpolator(const Grid& grid) : grid_(grid) {
|
| 127 |
+
// The + casts the enum into an int before doing the
|
| 128 |
+
// comparison. It is needed to prevent
|
| 129 |
+
// "-Wunnamed-type-template-args" related errors.
|
| 130 |
+
CHECK_GE(+Grid::DATA_DIMENSION, 1);
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
void Evaluate(double x, double* f, double* dfdx) const {
|
| 134 |
+
const int n = std::floor(x);
|
| 135 |
+
Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> p0, p1, p2, p3;
|
| 136 |
+
grid_.GetValue(n - 1, p0.data());
|
| 137 |
+
grid_.GetValue(n, p1.data());
|
| 138 |
+
grid_.GetValue(n + 1, p2.data());
|
| 139 |
+
grid_.GetValue(n + 2, p3.data());
|
| 140 |
+
CubicHermiteSpline<Grid::DATA_DIMENSION>(p0, p1, p2, p3, x - n, f, dfdx);
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
// The following two Evaluate overloads are needed for interfacing
|
| 144 |
+
// with automatic differentiation. The first is for when a scalar
|
| 145 |
+
// evaluation is done, and the second one is for when Jets are used.
|
| 146 |
+
void Evaluate(const double& x, double* f) const { Evaluate(x, f, nullptr); }
|
| 147 |
+
|
| 148 |
+
template <typename JetT>
|
| 149 |
+
void Evaluate(const JetT& x, JetT* f) const {
|
| 150 |
+
double fx[Grid::DATA_DIMENSION], dfdx[Grid::DATA_DIMENSION];
|
| 151 |
+
Evaluate(x.a, fx, dfdx);
|
| 152 |
+
for (int i = 0; i < Grid::DATA_DIMENSION; ++i) {
|
| 153 |
+
f[i].a = fx[i];
|
| 154 |
+
f[i].v = dfdx[i] * x.v;
|
| 155 |
+
}
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
private:
|
| 159 |
+
const Grid& grid_;
|
| 160 |
+
};
|
| 161 |
+
|
| 162 |
+
// An object that implements an infinite one dimensional grid needed
|
| 163 |
+
// by the CubicInterpolator where the source of the function values is
|
| 164 |
+
// an array of type T on the interval
|
| 165 |
+
//
|
| 166 |
+
// [begin, ..., end - 1]
|
| 167 |
+
//
|
| 168 |
+
// Since the input array is finite and the grid is infinite, values
|
| 169 |
+
// outside this interval needs to be computed. Grid1D uses the value
|
| 170 |
+
// from the nearest edge.
|
| 171 |
+
//
|
| 172 |
+
// The function being provided can be vector valued, in which case
|
| 173 |
+
// kDataDimension > 1. The dimensional slices of the function maybe
|
| 174 |
+
// interleaved, or they maybe stacked, i.e, if the function has
|
| 175 |
+
// kDataDimension = 2, if kInterleaved = true, then it is stored as
|
| 176 |
+
//
|
| 177 |
+
// f01, f02, f11, f12 ....
|
| 178 |
+
//
|
| 179 |
+
// and if kInterleaved = false, then it is stored as
|
| 180 |
+
//
|
| 181 |
+
// f01, f11, .. fn1, f02, f12, .. , fn2
|
| 182 |
+
//
|
| 183 |
+
template <typename T, int kDataDimension = 1, bool kInterleaved = true>
|
| 184 |
+
struct Grid1D {
|
| 185 |
+
public:
|
| 186 |
+
enum { DATA_DIMENSION = kDataDimension };
|
| 187 |
+
|
| 188 |
+
Grid1D(const T* data, const int begin, const int end)
|
| 189 |
+
: data_(data), begin_(begin), end_(end), num_values_(end - begin) {
|
| 190 |
+
CHECK_LT(begin, end);
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
EIGEN_STRONG_INLINE void GetValue(const int n, double* f) const {
|
| 194 |
+
const int idx = (std::min)((std::max)(begin_, n), end_ - 1) - begin_;
|
| 195 |
+
if (kInterleaved) {
|
| 196 |
+
for (int i = 0; i < kDataDimension; ++i) {
|
| 197 |
+
f[i] = static_cast<double>(data_[kDataDimension * idx + i]);
|
| 198 |
+
}
|
| 199 |
+
} else {
|
| 200 |
+
for (int i = 0; i < kDataDimension; ++i) {
|
| 201 |
+
f[i] = static_cast<double>(data_[i * num_values_ + idx]);
|
| 202 |
+
}
|
| 203 |
+
}
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
private:
|
| 207 |
+
const T* data_;
|
| 208 |
+
const int begin_;
|
| 209 |
+
const int end_;
|
| 210 |
+
const int num_values_;
|
| 211 |
+
};
|
| 212 |
+
|
| 213 |
+
// Given as input an infinite two dimensional grid like object, which
|
| 214 |
+
// provides the following interface:
|
| 215 |
+
//
|
| 216 |
+
// struct Grid {
|
| 217 |
+
// enum { DATA_DIMENSION = 1 };
|
| 218 |
+
// void GetValue(int row, int col, double* f) const;
|
| 219 |
+
// };
|
| 220 |
+
//
|
| 221 |
+
// Where, GetValue gives us the value of a function f (possibly vector
|
| 222 |
+
// valued) for any pairs of integers (row, col), and the enum
|
| 223 |
+
// DATA_DIMENSION indicates the dimensionality of the function being
|
| 224 |
+
// interpolated. For example if you are interpolating a color image
|
| 225 |
+
// with three channels (Red, Green & Blue), then DATA_DIMENSION = 3.
|
| 226 |
+
//
|
| 227 |
+
// BiCubicInterpolator uses the cubic convolution interpolation
|
| 228 |
+
// algorithm of R. Keys, to produce a smooth approximation to it that
|
| 229 |
+
// can be used to evaluate the f(r,c), df(r, c)/dr and df(r,c)/dc at
|
| 230 |
+
// any point in the real plane.
|
| 231 |
+
//
|
| 232 |
+
// For more details on the algorithm used here see:
|
| 233 |
+
//
|
| 234 |
+
// "Cubic convolution interpolation for digital image processing".
|
| 235 |
+
// Robert G. Keys, IEEE Trans. on Acoustics, Speech, and Signal
|
| 236 |
+
// Processing 29 (6): 1153-1160, 1981.
|
| 237 |
+
//
|
| 238 |
+
// http://en.wikipedia.org/wiki/Cubic_Hermite_spline
|
| 239 |
+
// http://en.wikipedia.org/wiki/Bicubic_interpolation
|
| 240 |
+
//
|
| 241 |
+
// Example usage:
|
| 242 |
+
//
|
| 243 |
+
// const double data[] = {1.0, 3.0, -1.0, 4.0,
|
| 244 |
+
// 3.6, 2.1, 4.2, 2.0,
|
| 245 |
+
// 2.0, 1.0, 3.1, 5.2};
|
| 246 |
+
// Grid2D<double, 1> grid(data, 3, 4);
|
| 247 |
+
// BiCubicInterpolator<Grid2D<double, 1>> interpolator(grid);
|
| 248 |
+
// double f, dfdr, dfdc;
|
| 249 |
+
// interpolator.Evaluate(1.2, 2.5, &f, &dfdr, &dfdc);
|
| 250 |
+
|
| 251 |
+
template <typename Grid>
|
| 252 |
+
class BiCubicInterpolator {
|
| 253 |
+
public:
|
| 254 |
+
explicit BiCubicInterpolator(const Grid& grid) : grid_(grid) {
|
| 255 |
+
// The + casts the enum into an int before doing the
|
| 256 |
+
// comparison. It is needed to prevent
|
| 257 |
+
// "-Wunnamed-type-template-args" related errors.
|
| 258 |
+
CHECK_GE(+Grid::DATA_DIMENSION, 1);
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
// Evaluate the interpolated function value and/or its
|
| 262 |
+
// derivative. Uses the nearest point on the grid boundary if r or
|
| 263 |
+
// c is out of bounds.
|
| 264 |
+
void Evaluate(
|
| 265 |
+
double r, double c, double* f, double* dfdr, double* dfdc) const {
|
| 266 |
+
// BiCubic interpolation requires 16 values around the point being
|
| 267 |
+
// evaluated. We will use pij, to indicate the elements of the
|
| 268 |
+
// 4x4 grid of values.
|
| 269 |
+
//
|
| 270 |
+
// col
|
| 271 |
+
// p00 p01 p02 p03
|
| 272 |
+
// row p10 p11 p12 p13
|
| 273 |
+
// p20 p21 p22 p23
|
| 274 |
+
// p30 p31 p32 p33
|
| 275 |
+
//
|
| 276 |
+
// The point (r,c) being evaluated is assumed to lie in the square
|
| 277 |
+
// defined by p11, p12, p22 and p21.
|
| 278 |
+
|
| 279 |
+
const int row = std::floor(r);
|
| 280 |
+
const int col = std::floor(c);
|
| 281 |
+
|
| 282 |
+
Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> p0, p1, p2, p3;
|
| 283 |
+
|
| 284 |
+
// Interpolate along each of the four rows, evaluating the function
|
| 285 |
+
// value and the horizontal derivative in each row.
|
| 286 |
+
Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> f0, f1, f2, f3;
|
| 287 |
+
Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> df0dc, df1dc, df2dc, df3dc;
|
| 288 |
+
|
| 289 |
+
grid_.GetValue(row - 1, col - 1, p0.data());
|
| 290 |
+
grid_.GetValue(row - 1, col, p1.data());
|
| 291 |
+
grid_.GetValue(row - 1, col + 1, p2.data());
|
| 292 |
+
grid_.GetValue(row - 1, col + 2, p3.data());
|
| 293 |
+
CubicHermiteSpline<Grid::DATA_DIMENSION>(
|
| 294 |
+
p0, p1, p2, p3, c - col, f0.data(), df0dc.data());
|
| 295 |
+
|
| 296 |
+
grid_.GetValue(row, col - 1, p0.data());
|
| 297 |
+
grid_.GetValue(row, col, p1.data());
|
| 298 |
+
grid_.GetValue(row, col + 1, p2.data());
|
| 299 |
+
grid_.GetValue(row, col + 2, p3.data());
|
| 300 |
+
CubicHermiteSpline<Grid::DATA_DIMENSION>(
|
| 301 |
+
p0, p1, p2, p3, c - col, f1.data(), df1dc.data());
|
| 302 |
+
|
| 303 |
+
grid_.GetValue(row + 1, col - 1, p0.data());
|
| 304 |
+
grid_.GetValue(row + 1, col, p1.data());
|
| 305 |
+
grid_.GetValue(row + 1, col + 1, p2.data());
|
| 306 |
+
grid_.GetValue(row + 1, col + 2, p3.data());
|
| 307 |
+
CubicHermiteSpline<Grid::DATA_DIMENSION>(
|
| 308 |
+
p0, p1, p2, p3, c - col, f2.data(), df2dc.data());
|
| 309 |
+
|
| 310 |
+
grid_.GetValue(row + 2, col - 1, p0.data());
|
| 311 |
+
grid_.GetValue(row + 2, col, p1.data());
|
| 312 |
+
grid_.GetValue(row + 2, col + 1, p2.data());
|
| 313 |
+
grid_.GetValue(row + 2, col + 2, p3.data());
|
| 314 |
+
CubicHermiteSpline<Grid::DATA_DIMENSION>(
|
| 315 |
+
p0, p1, p2, p3, c - col, f3.data(), df3dc.data());
|
| 316 |
+
|
| 317 |
+
// Interpolate vertically the interpolated value from each row and
|
| 318 |
+
// compute the derivative along the columns.
|
| 319 |
+
CubicHermiteSpline<Grid::DATA_DIMENSION>(f0, f1, f2, f3, r - row, f, dfdr);
|
| 320 |
+
if (dfdc != nullptr) {
|
| 321 |
+
// Interpolate vertically the derivative along the columns.
|
| 322 |
+
CubicHermiteSpline<Grid::DATA_DIMENSION>(
|
| 323 |
+
df0dc, df1dc, df2dc, df3dc, r - row, dfdc, nullptr);
|
| 324 |
+
}
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
// The following two Evaluate overloads are needed for interfacing
|
| 328 |
+
// with automatic differentiation. The first is for when a scalar
|
| 329 |
+
// evaluation is done, and the second one is for when Jets are used.
|
| 330 |
+
void Evaluate(const double& r, const double& c, double* f) const {
|
| 331 |
+
Evaluate(r, c, f, nullptr, nullptr);
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
template <typename JetT>
|
| 335 |
+
void Evaluate(const JetT& r, const JetT& c, JetT* f) const {
|
| 336 |
+
double frc[Grid::DATA_DIMENSION];
|
| 337 |
+
double dfdr[Grid::DATA_DIMENSION];
|
| 338 |
+
double dfdc[Grid::DATA_DIMENSION];
|
| 339 |
+
Evaluate(r.a, c.a, frc, dfdr, dfdc);
|
| 340 |
+
for (int i = 0; i < Grid::DATA_DIMENSION; ++i) {
|
| 341 |
+
f[i].a = frc[i];
|
| 342 |
+
f[i].v = dfdr[i] * r.v + dfdc[i] * c.v;
|
| 343 |
+
}
|
| 344 |
+
}
|
| 345 |
+
|
| 346 |
+
private:
|
| 347 |
+
const Grid& grid_;
|
| 348 |
+
};
|
| 349 |
+
|
| 350 |
+
// An object that implements an infinite two dimensional grid needed
|
| 351 |
+
// by the BiCubicInterpolator where the source of the function values
|
| 352 |
+
// is an grid of type T on the grid
|
| 353 |
+
//
|
| 354 |
+
// [(row_start, col_start), ..., (row_start, col_end - 1)]
|
| 355 |
+
// [ ... ]
|
| 356 |
+
// [(row_end - 1, col_start), ..., (row_end - 1, col_end - 1)]
|
| 357 |
+
//
|
| 358 |
+
// Since the input grid is finite and the grid is infinite, values
|
| 359 |
+
// outside this interval needs to be computed. Grid2D uses the value
|
| 360 |
+
// from the nearest edge.
|
| 361 |
+
//
|
| 362 |
+
// The function being provided can be vector valued, in which case
|
| 363 |
+
// kDataDimension > 1. The data maybe stored in row or column major
|
| 364 |
+
// format and the various dimensional slices of the function maybe
|
| 365 |
+
// interleaved, or they maybe stacked, i.e, if the function has
|
| 366 |
+
// kDataDimension = 2, is stored in row-major format and if
|
| 367 |
+
// kInterleaved = true, then it is stored as
|
| 368 |
+
//
|
| 369 |
+
// f001, f002, f011, f012, ...
|
| 370 |
+
//
|
| 371 |
+
// A commonly occuring example are color images (RGB) where the three
|
| 372 |
+
// channels are stored interleaved.
|
| 373 |
+
//
|
| 374 |
+
// If kInterleaved = false, then it is stored as
|
| 375 |
+
//
|
| 376 |
+
// f001, f011, ..., fnm1, f002, f012, ...
|
| 377 |
+
template <typename T,
|
| 378 |
+
int kDataDimension = 1,
|
| 379 |
+
bool kRowMajor = true,
|
| 380 |
+
bool kInterleaved = true>
|
| 381 |
+
struct Grid2D {
|
| 382 |
+
public:
|
| 383 |
+
enum { DATA_DIMENSION = kDataDimension };
|
| 384 |
+
|
| 385 |
+
Grid2D(const T* data,
|
| 386 |
+
const int row_begin,
|
| 387 |
+
const int row_end,
|
| 388 |
+
const int col_begin,
|
| 389 |
+
const int col_end)
|
| 390 |
+
: data_(data),
|
| 391 |
+
row_begin_(row_begin),
|
| 392 |
+
row_end_(row_end),
|
| 393 |
+
col_begin_(col_begin),
|
| 394 |
+
col_end_(col_end),
|
| 395 |
+
num_rows_(row_end - row_begin),
|
| 396 |
+
num_cols_(col_end - col_begin),
|
| 397 |
+
num_values_(num_rows_ * num_cols_) {
|
| 398 |
+
CHECK_GE(kDataDimension, 1);
|
| 399 |
+
CHECK_LT(row_begin, row_end);
|
| 400 |
+
CHECK_LT(col_begin, col_end);
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
EIGEN_STRONG_INLINE void GetValue(const int r, const int c, double* f) const {
|
| 404 |
+
const int row_idx =
|
| 405 |
+
(std::min)((std::max)(row_begin_, r), row_end_ - 1) - row_begin_;
|
| 406 |
+
const int col_idx =
|
| 407 |
+
(std::min)((std::max)(col_begin_, c), col_end_ - 1) - col_begin_;
|
| 408 |
+
|
| 409 |
+
const int n = (kRowMajor) ? num_cols_ * row_idx + col_idx
|
| 410 |
+
: num_rows_ * col_idx + row_idx;
|
| 411 |
+
|
| 412 |
+
if (kInterleaved) {
|
| 413 |
+
for (int i = 0; i < kDataDimension; ++i) {
|
| 414 |
+
f[i] = static_cast<double>(data_[kDataDimension * n + i]);
|
| 415 |
+
}
|
| 416 |
+
} else {
|
| 417 |
+
for (int i = 0; i < kDataDimension; ++i) {
|
| 418 |
+
f[i] = static_cast<double>(data_[i * num_values_ + n]);
|
| 419 |
+
}
|
| 420 |
+
}
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
private:
|
| 424 |
+
const T* data_;
|
| 425 |
+
const int row_begin_;
|
| 426 |
+
const int row_end_;
|
| 427 |
+
const int col_begin_;
|
| 428 |
+
const int col_end_;
|
| 429 |
+
const int num_rows_;
|
| 430 |
+
const int num_cols_;
|
| 431 |
+
const int num_values_;
|
| 432 |
+
};
|
| 433 |
+
|
| 434 |
+
} // namespace ceres
|
| 435 |
+
|
| 436 |
+
#endif // CERES_PUBLIC_CUBIC_INTERPOLATOR_H_
|
ceres-v2/include/dynamic_autodiff_cost_function.h
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
// mierle@gmail.com (Keir Mierle)
|
| 31 |
+
|
| 32 |
+
#ifndef CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
|
| 33 |
+
#define CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
|
| 34 |
+
|
| 35 |
+
#include <cmath>
|
| 36 |
+
#include <memory>
|
| 37 |
+
#include <numeric>
|
| 38 |
+
#include <vector>
|
| 39 |
+
|
| 40 |
+
#include "ceres/dynamic_cost_function.h"
|
| 41 |
+
#include "ceres/internal/fixed_array.h"
|
| 42 |
+
#include "ceres/jet.h"
|
| 43 |
+
#include "ceres/types.h"
|
| 44 |
+
#include "glog/logging.h"
|
| 45 |
+
|
| 46 |
+
namespace ceres {
|
| 47 |
+
|
| 48 |
+
// This autodiff implementation differs from the one found in
|
| 49 |
+
// autodiff_cost_function.h by supporting autodiff on cost functions
|
| 50 |
+
// with variable numbers of parameters with variable sizes. With the
|
| 51 |
+
// other implementation, all the sizes (both the number of parameter
|
| 52 |
+
// blocks and the size of each block) must be fixed at compile time.
|
| 53 |
+
//
|
| 54 |
+
// The functor API differs slightly from the API for fixed size
|
| 55 |
+
// autodiff; the expected interface for the cost functors is:
|
| 56 |
+
//
|
| 57 |
+
// struct MyCostFunctor {
|
| 58 |
+
// template<typename T>
|
| 59 |
+
// bool operator()(T const* const* parameters, T* residuals) const {
|
| 60 |
+
// // Use parameters[i] to access the i'th parameter block.
|
| 61 |
+
// }
|
| 62 |
+
// };
|
| 63 |
+
//
|
| 64 |
+
// Since the sizing of the parameters is done at runtime, you must
|
| 65 |
+
// also specify the sizes after creating the dynamic autodiff cost
|
| 66 |
+
// function. For example:
|
| 67 |
+
//
|
| 68 |
+
// DynamicAutoDiffCostFunction<MyCostFunctor, 3> cost_function(
|
| 69 |
+
// new MyCostFunctor());
|
| 70 |
+
// cost_function.AddParameterBlock(5);
|
| 71 |
+
// cost_function.AddParameterBlock(10);
|
| 72 |
+
// cost_function.SetNumResiduals(21);
|
| 73 |
+
//
|
| 74 |
+
// Under the hood, the implementation evaluates the cost function
|
| 75 |
+
// multiple times, computing a small set of the derivatives (four by
|
| 76 |
+
// default, controlled by the Stride template parameter) with each
|
| 77 |
+
// pass. There is a tradeoff with the size of the passes; you may want
|
| 78 |
+
// to experiment with the stride.
|
| 79 |
+
template <typename CostFunctor, int Stride = 4>
|
| 80 |
+
class DynamicAutoDiffCostFunction final : public DynamicCostFunction {
|
| 81 |
+
public:
|
| 82 |
+
// Takes ownership by default.
|
| 83 |
+
explicit DynamicAutoDiffCostFunction(CostFunctor* functor,
|
| 84 |
+
Ownership ownership = TAKE_OWNERSHIP)
|
| 85 |
+
: functor_(functor), ownership_(ownership) {}
|
| 86 |
+
|
| 87 |
+
DynamicAutoDiffCostFunction(DynamicAutoDiffCostFunction&& other)
|
| 88 |
+
: functor_(std::move(other.functor_)), ownership_(other.ownership_) {}
|
| 89 |
+
|
| 90 |
+
~DynamicAutoDiffCostFunction() override {
|
| 91 |
+
// Manually release pointer if configured to not take ownership
|
| 92 |
+
// rather than deleting only if ownership is taken. This is to
|
| 93 |
+
// stay maximally compatible to old user code which may have
|
| 94 |
+
// forgotten to implement a virtual destructor, from when the
|
| 95 |
+
// AutoDiffCostFunction always took ownership.
|
| 96 |
+
if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
|
| 97 |
+
functor_.release();
|
| 98 |
+
}
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
bool Evaluate(double const* const* parameters,
|
| 102 |
+
double* residuals,
|
| 103 |
+
double** jacobians) const override {
|
| 104 |
+
CHECK_GT(num_residuals(), 0)
|
| 105 |
+
<< "You must call DynamicAutoDiffCostFunction::SetNumResiduals() "
|
| 106 |
+
<< "before DynamicAutoDiffCostFunction::Evaluate().";
|
| 107 |
+
|
| 108 |
+
if (jacobians == nullptr) {
|
| 109 |
+
return (*functor_)(parameters, residuals);
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
// The difficulty with Jets, as implemented in Ceres, is that they were
|
| 113 |
+
// originally designed for strictly compile-sized use. At this point, there
|
| 114 |
+
// is a large body of code that assumes inside a cost functor it is
|
| 115 |
+
// acceptable to do e.g. T(1.5) and get an appropriately sized jet back.
|
| 116 |
+
//
|
| 117 |
+
// Unfortunately, it is impossible to communicate the expected size of a
|
| 118 |
+
// dynamically sized jet to the static instantiations that existing code
|
| 119 |
+
// depends on.
|
| 120 |
+
//
|
| 121 |
+
// To work around this issue, the solution here is to evaluate the
|
| 122 |
+
// jacobians in a series of passes, each one computing Stride *
|
| 123 |
+
// num_residuals() derivatives. This is done with small, fixed-size jets.
|
| 124 |
+
const int num_parameter_blocks =
|
| 125 |
+
static_cast<int>(parameter_block_sizes().size());
|
| 126 |
+
const int num_parameters = std::accumulate(
|
| 127 |
+
parameter_block_sizes().begin(), parameter_block_sizes().end(), 0);
|
| 128 |
+
|
| 129 |
+
// Allocate scratch space for the strided evaluation.
|
| 130 |
+
using JetT = Jet<double, Stride>;
|
| 131 |
+
internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> input_jets(
|
| 132 |
+
num_parameters);
|
| 133 |
+
internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> output_jets(
|
| 134 |
+
num_residuals());
|
| 135 |
+
|
| 136 |
+
// Make the parameter pack that is sent to the functor (reused).
|
| 137 |
+
internal::FixedArray<Jet<double, Stride>*> jet_parameters(
|
| 138 |
+
num_parameter_blocks, nullptr);
|
| 139 |
+
int num_active_parameters = 0;
|
| 140 |
+
|
| 141 |
+
// To handle constant parameters between non-constant parameter blocks, the
|
| 142 |
+
// start position --- a raw parameter index --- of each contiguous block of
|
| 143 |
+
// non-constant parameters is recorded in start_derivative_section.
|
| 144 |
+
std::vector<int> start_derivative_section;
|
| 145 |
+
bool in_derivative_section = false;
|
| 146 |
+
int parameter_cursor = 0;
|
| 147 |
+
|
| 148 |
+
// Discover the derivative sections and set the parameter values.
|
| 149 |
+
for (int i = 0; i < num_parameter_blocks; ++i) {
|
| 150 |
+
jet_parameters[i] = &input_jets[parameter_cursor];
|
| 151 |
+
|
| 152 |
+
const int parameter_block_size = parameter_block_sizes()[i];
|
| 153 |
+
if (jacobians[i] != nullptr) {
|
| 154 |
+
if (!in_derivative_section) {
|
| 155 |
+
start_derivative_section.push_back(parameter_cursor);
|
| 156 |
+
in_derivative_section = true;
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
num_active_parameters += parameter_block_size;
|
| 160 |
+
} else {
|
| 161 |
+
in_derivative_section = false;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
for (int j = 0; j < parameter_block_size; ++j, parameter_cursor++) {
|
| 165 |
+
input_jets[parameter_cursor].a = parameters[i][j];
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
if (num_active_parameters == 0) {
|
| 170 |
+
return (*functor_)(parameters, residuals);
|
| 171 |
+
}
|
| 172 |
+
// When `num_active_parameters % Stride != 0` then it can be the case
|
| 173 |
+
// that `active_parameter_count < Stride` while parameter_cursor is less
|
| 174 |
+
// than the total number of parameters and with no remaining non-constant
|
| 175 |
+
// parameter blocks. Pushing parameter_cursor (the total number of
|
| 176 |
+
// parameters) as a final entry to start_derivative_section is required
|
| 177 |
+
// because if a constant parameter block is encountered after the
|
| 178 |
+
// last non-constant block then current_derivative_section is incremented
|
| 179 |
+
// and would otherwise index an invalid position in
|
| 180 |
+
// start_derivative_section. Setting the final element to the total number
|
| 181 |
+
// of parameters means that this can only happen at most once in the loop
|
| 182 |
+
// below.
|
| 183 |
+
start_derivative_section.push_back(parameter_cursor);
|
| 184 |
+
|
| 185 |
+
// Evaluate all of the strides. Each stride is a chunk of the derivative to
|
| 186 |
+
// evaluate, typically some size proportional to the size of the SIMD
|
| 187 |
+
// registers of the CPU.
|
| 188 |
+
int num_strides = static_cast<int>(
|
| 189 |
+
ceil(num_active_parameters / static_cast<float>(Stride)));
|
| 190 |
+
|
| 191 |
+
int current_derivative_section = 0;
|
| 192 |
+
int current_derivative_section_cursor = 0;
|
| 193 |
+
|
| 194 |
+
for (int pass = 0; pass < num_strides; ++pass) {
|
| 195 |
+
// Set most of the jet components to zero, except for
|
| 196 |
+
// non-constant #Stride parameters.
|
| 197 |
+
const int initial_derivative_section = current_derivative_section;
|
| 198 |
+
const int initial_derivative_section_cursor =
|
| 199 |
+
current_derivative_section_cursor;
|
| 200 |
+
|
| 201 |
+
int active_parameter_count = 0;
|
| 202 |
+
parameter_cursor = 0;
|
| 203 |
+
|
| 204 |
+
for (int i = 0; i < num_parameter_blocks; ++i) {
|
| 205 |
+
for (int j = 0; j < parameter_block_sizes()[i];
|
| 206 |
+
++j, parameter_cursor++) {
|
| 207 |
+
input_jets[parameter_cursor].v.setZero();
|
| 208 |
+
if (active_parameter_count < Stride &&
|
| 209 |
+
parameter_cursor >=
|
| 210 |
+
(start_derivative_section[current_derivative_section] +
|
| 211 |
+
current_derivative_section_cursor)) {
|
| 212 |
+
if (jacobians[i] != nullptr) {
|
| 213 |
+
input_jets[parameter_cursor].v[active_parameter_count] = 1.0;
|
| 214 |
+
++active_parameter_count;
|
| 215 |
+
++current_derivative_section_cursor;
|
| 216 |
+
} else {
|
| 217 |
+
++current_derivative_section;
|
| 218 |
+
current_derivative_section_cursor = 0;
|
| 219 |
+
}
|
| 220 |
+
}
|
| 221 |
+
}
|
| 222 |
+
}
|
| 223 |
+
|
| 224 |
+
if (!(*functor_)(&jet_parameters[0], &output_jets[0])) {
|
| 225 |
+
return false;
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
// Copy the pieces of the jacobians into their final place.
|
| 229 |
+
active_parameter_count = 0;
|
| 230 |
+
|
| 231 |
+
current_derivative_section = initial_derivative_section;
|
| 232 |
+
current_derivative_section_cursor = initial_derivative_section_cursor;
|
| 233 |
+
|
| 234 |
+
for (int i = 0, parameter_cursor = 0; i < num_parameter_blocks; ++i) {
|
| 235 |
+
for (int j = 0; j < parameter_block_sizes()[i];
|
| 236 |
+
++j, parameter_cursor++) {
|
| 237 |
+
if (active_parameter_count < Stride &&
|
| 238 |
+
parameter_cursor >=
|
| 239 |
+
(start_derivative_section[current_derivative_section] +
|
| 240 |
+
current_derivative_section_cursor)) {
|
| 241 |
+
if (jacobians[i] != nullptr) {
|
| 242 |
+
for (int k = 0; k < num_residuals(); ++k) {
|
| 243 |
+
jacobians[i][k * parameter_block_sizes()[i] + j] =
|
| 244 |
+
output_jets[k].v[active_parameter_count];
|
| 245 |
+
}
|
| 246 |
+
++active_parameter_count;
|
| 247 |
+
++current_derivative_section_cursor;
|
| 248 |
+
} else {
|
| 249 |
+
++current_derivative_section;
|
| 250 |
+
current_derivative_section_cursor = 0;
|
| 251 |
+
}
|
| 252 |
+
}
|
| 253 |
+
}
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
// Only copy the residuals over once (even though we compute them on
|
| 257 |
+
// every loop).
|
| 258 |
+
if (pass == num_strides - 1) {
|
| 259 |
+
for (int k = 0; k < num_residuals(); ++k) {
|
| 260 |
+
residuals[k] = output_jets[k].a;
|
| 261 |
+
}
|
| 262 |
+
}
|
| 263 |
+
}
|
| 264 |
+
return true;
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
private:
|
| 268 |
+
std::unique_ptr<CostFunctor> functor_;
|
| 269 |
+
Ownership ownership_;
|
| 270 |
+
};
|
| 271 |
+
|
| 272 |
+
} // namespace ceres
|
| 273 |
+
|
| 274 |
+
#endif // CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
|
ceres-v2/include/dynamic_cost_function.h
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_DYNAMIC_COST_FUNCTION_H_
|
| 32 |
+
#define CERES_PUBLIC_DYNAMIC_COST_FUNCTION_H_
|
| 33 |
+
|
| 34 |
+
#include "ceres/cost_function.h"
|
| 35 |
+
#include "ceres/internal/disable_warnings.h"
|
| 36 |
+
|
| 37 |
+
namespace ceres {
|
| 38 |
+
|
| 39 |
+
// A common base class for DynamicAutoDiffCostFunction and
|
| 40 |
+
// DynamicNumericDiffCostFunction which depend on methods that can add
|
| 41 |
+
// parameter blocks and set the number of residuals at run time.
|
| 42 |
+
class CERES_EXPORT DynamicCostFunction : public CostFunction {
|
| 43 |
+
public:
|
| 44 |
+
virtual void AddParameterBlock(int size) {
|
| 45 |
+
mutable_parameter_block_sizes()->push_back(size);
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
virtual void SetNumResiduals(int num_residuals) {
|
| 49 |
+
set_num_residuals(num_residuals);
|
| 50 |
+
}
|
| 51 |
+
};
|
| 52 |
+
|
| 53 |
+
} // namespace ceres
|
| 54 |
+
|
| 55 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 56 |
+
|
| 57 |
+
#endif // CERES_PUBLIC_DYNAMIC_COST_FUNCTION_H_
|
ceres-v2/include/dynamic_cost_function_to_functor.h
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
|
| 32 |
+
#ifndef CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
|
| 33 |
+
#define CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
|
| 34 |
+
|
| 35 |
+
#include <memory>
|
| 36 |
+
#include <numeric>
|
| 37 |
+
#include <vector>
|
| 38 |
+
|
| 39 |
+
#include "ceres/dynamic_cost_function.h"
|
| 40 |
+
#include "ceres/internal/disable_warnings.h"
|
| 41 |
+
#include "ceres/internal/export.h"
|
| 42 |
+
#include "ceres/internal/fixed_array.h"
|
| 43 |
+
#include "glog/logging.h"
|
| 44 |
+
|
| 45 |
+
namespace ceres {
|
| 46 |
+
|
| 47 |
+
// DynamicCostFunctionToFunctor allows users to use CostFunction
|
| 48 |
+
// objects in templated functors which are to be used for automatic
|
| 49 |
+
// differentiation. It works similar to CostFunctionToFunctor, with the
|
| 50 |
+
// difference that it allows you to wrap a cost function with dynamic numbers
|
| 51 |
+
// of parameters and residuals.
|
| 52 |
+
//
|
| 53 |
+
// For example, let us assume that
|
| 54 |
+
//
|
| 55 |
+
// class IntrinsicProjection : public CostFunction {
|
| 56 |
+
// public:
|
| 57 |
+
// IntrinsicProjection(const double* observation);
|
| 58 |
+
// bool Evaluate(double const* const* parameters,
|
| 59 |
+
// double* residuals,
|
| 60 |
+
// double** jacobians) const override;
|
| 61 |
+
// };
|
| 62 |
+
//
|
| 63 |
+
// is a cost function that implements the projection of a point in its
|
| 64 |
+
// local coordinate system onto its image plane and subtracts it from
|
| 65 |
+
// the observed point projection. It can compute its residual and
|
| 66 |
+
// either via analytic or numerical differentiation can compute its
|
| 67 |
+
// jacobians. The intrinsics are passed in as parameters[0] and the point as
|
| 68 |
+
// parameters[1].
|
| 69 |
+
//
|
| 70 |
+
// Now we would like to compose the action of this CostFunction with
|
| 71 |
+
// the action of camera extrinsics, i.e., rotation and
|
| 72 |
+
// translation. Say we have a templated function
|
| 73 |
+
//
|
| 74 |
+
// template<typename T>
|
| 75 |
+
// void RotateAndTranslatePoint(double const* const* parameters,
|
| 76 |
+
// double* residuals);
|
| 77 |
+
//
|
| 78 |
+
// Then we can now do the following,
|
| 79 |
+
//
|
| 80 |
+
// struct CameraProjection {
|
| 81 |
+
// CameraProjection(const double* observation)
|
| 82 |
+
// : intrinsic_projection_.(new IntrinsicProjection(observation)) {
|
| 83 |
+
// }
|
| 84 |
+
// template <typename T>
|
| 85 |
+
// bool operator()(T const* const* parameters,
|
| 86 |
+
// T* residual) const {
|
| 87 |
+
// const T* rotation = parameters[0];
|
| 88 |
+
// const T* translation = parameters[1];
|
| 89 |
+
// const T* intrinsics = parameters[2];
|
| 90 |
+
// const T* point = parameters[3];
|
| 91 |
+
// T transformed_point[3];
|
| 92 |
+
// RotateAndTranslatePoint(rotation, translation, point, transformed_point);
|
| 93 |
+
//
|
| 94 |
+
// // Note that we call intrinsic_projection_, just like it was
|
| 95 |
+
// // any other templated functor.
|
| 96 |
+
// const T* projection_parameters[2];
|
| 97 |
+
// projection_parameters[0] = intrinsics;
|
| 98 |
+
// projection_parameters[1] = transformed_point;
|
| 99 |
+
// return intrinsic_projection_(projection_parameters, residual);
|
| 100 |
+
// }
|
| 101 |
+
//
|
| 102 |
+
// private:
|
| 103 |
+
// DynamicCostFunctionToFunctor intrinsic_projection_;
|
| 104 |
+
// };
|
| 105 |
+
class CERES_EXPORT DynamicCostFunctionToFunctor {
|
| 106 |
+
public:
|
| 107 |
+
// Takes ownership of cost_function.
|
| 108 |
+
explicit DynamicCostFunctionToFunctor(CostFunction* cost_function)
|
| 109 |
+
: cost_function_(cost_function) {
|
| 110 |
+
CHECK(cost_function != nullptr);
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
bool operator()(double const* const* parameters, double* residuals) const {
|
| 114 |
+
return cost_function_->Evaluate(parameters, residuals, nullptr);
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
template <typename JetT>
|
| 118 |
+
bool operator()(JetT const* const* inputs, JetT* output) const {
|
| 119 |
+
const std::vector<int32_t>& parameter_block_sizes =
|
| 120 |
+
cost_function_->parameter_block_sizes();
|
| 121 |
+
const int num_parameter_blocks =
|
| 122 |
+
static_cast<int>(parameter_block_sizes.size());
|
| 123 |
+
const int num_residuals = cost_function_->num_residuals();
|
| 124 |
+
const int num_parameters = std::accumulate(
|
| 125 |
+
parameter_block_sizes.begin(), parameter_block_sizes.end(), 0);
|
| 126 |
+
|
| 127 |
+
internal::FixedArray<double> parameters(num_parameters);
|
| 128 |
+
internal::FixedArray<double*> parameter_blocks(num_parameter_blocks);
|
| 129 |
+
internal::FixedArray<double> jacobians(num_residuals * num_parameters);
|
| 130 |
+
internal::FixedArray<double*> jacobian_blocks(num_parameter_blocks);
|
| 131 |
+
internal::FixedArray<double> residuals(num_residuals);
|
| 132 |
+
|
| 133 |
+
// Build a set of arrays to get the residuals and jacobians from
|
| 134 |
+
// the CostFunction wrapped by this functor.
|
| 135 |
+
double* parameter_ptr = parameters.data();
|
| 136 |
+
double* jacobian_ptr = jacobians.data();
|
| 137 |
+
for (int i = 0; i < num_parameter_blocks; ++i) {
|
| 138 |
+
parameter_blocks[i] = parameter_ptr;
|
| 139 |
+
jacobian_blocks[i] = jacobian_ptr;
|
| 140 |
+
for (int j = 0; j < parameter_block_sizes[i]; ++j) {
|
| 141 |
+
*parameter_ptr++ = inputs[i][j].a;
|
| 142 |
+
}
|
| 143 |
+
jacobian_ptr += num_residuals * parameter_block_sizes[i];
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
if (!cost_function_->Evaluate(parameter_blocks.data(),
|
| 147 |
+
residuals.data(),
|
| 148 |
+
jacobian_blocks.data())) {
|
| 149 |
+
return false;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
// Now that we have the incoming Jets, which are carrying the
|
| 153 |
+
// partial derivatives of each of the inputs w.r.t to some other
|
| 154 |
+
// underlying parameters. The derivative of the outputs of the
|
| 155 |
+
// cost function w.r.t to the same underlying parameters can now
|
| 156 |
+
// be computed by applying the chain rule.
|
| 157 |
+
//
|
| 158 |
+
// d output[i] d output[i] d input[j]
|
| 159 |
+
// -------------- = sum_j ----------- * ------------
|
| 160 |
+
// d parameter[k] d input[j] d parameter[k]
|
| 161 |
+
//
|
| 162 |
+
// d input[j]
|
| 163 |
+
// -------------- = inputs[j], so
|
| 164 |
+
// d parameter[k]
|
| 165 |
+
//
|
| 166 |
+
// outputJet[i] = sum_k jacobian[i][k] * inputJet[k]
|
| 167 |
+
//
|
| 168 |
+
// The following loop, iterates over the residuals, computing one
|
| 169 |
+
// output jet at a time.
|
| 170 |
+
for (int i = 0; i < num_residuals; ++i) {
|
| 171 |
+
output[i].a = residuals[i];
|
| 172 |
+
output[i].v.setZero();
|
| 173 |
+
|
| 174 |
+
for (int j = 0; j < num_parameter_blocks; ++j) {
|
| 175 |
+
const int32_t block_size = parameter_block_sizes[j];
|
| 176 |
+
for (int k = 0; k < parameter_block_sizes[j]; ++k) {
|
| 177 |
+
output[i].v +=
|
| 178 |
+
jacobian_blocks[j][i * block_size + k] * inputs[j][k].v;
|
| 179 |
+
}
|
| 180 |
+
}
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
return true;
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
private:
|
| 187 |
+
std::unique_ptr<CostFunction> cost_function_;
|
| 188 |
+
};
|
| 189 |
+
|
| 190 |
+
} // namespace ceres
|
| 191 |
+
|
| 192 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 193 |
+
|
| 194 |
+
#endif // CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
|
ceres-v2/include/dynamic_numeric_diff_cost_function.h
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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: mierle@gmail.com (Keir Mierle)
|
| 30 |
+
// sameeragarwal@google.com (Sameer Agarwal)
|
| 31 |
+
// thadh@gmail.com (Thad Hughes)
|
| 32 |
+
// tbennun@gmail.com (Tal Ben-Nun)
|
| 33 |
+
|
| 34 |
+
#ifndef CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_
|
| 35 |
+
#define CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_
|
| 36 |
+
|
| 37 |
+
#include <cmath>
|
| 38 |
+
#include <memory>
|
| 39 |
+
#include <numeric>
|
| 40 |
+
#include <vector>
|
| 41 |
+
|
| 42 |
+
#include "ceres/dynamic_cost_function.h"
|
| 43 |
+
#include "ceres/internal/eigen.h"
|
| 44 |
+
#include "ceres/internal/numeric_diff.h"
|
| 45 |
+
#include "ceres/internal/parameter_dims.h"
|
| 46 |
+
#include "ceres/numeric_diff_options.h"
|
| 47 |
+
#include "ceres/types.h"
|
| 48 |
+
#include "glog/logging.h"
|
| 49 |
+
|
| 50 |
+
namespace ceres {
|
| 51 |
+
|
| 52 |
+
// This numeric diff implementation differs from the one found in
|
| 53 |
+
// numeric_diff_cost_function.h by supporting numericdiff on cost
|
| 54 |
+
// functions with variable numbers of parameters with variable
|
| 55 |
+
// sizes. With the other implementation, all the sizes (both the
|
| 56 |
+
// number of parameter blocks and the size of each block) must be
|
| 57 |
+
// fixed at compile time.
|
| 58 |
+
//
|
| 59 |
+
// The functor API differs slightly from the API for fixed size
|
| 60 |
+
// numeric diff; the expected interface for the cost functors is:
|
| 61 |
+
//
|
| 62 |
+
// struct MyCostFunctor {
|
| 63 |
+
// bool operator()(double const*
|
| 64 |
+
// const* parameters,
|
| 65 |
+
// double* residuals) const {
|
| 66 |
+
// // Use parameters[i] to access the i'th parameter block.
|
| 67 |
+
// }
|
| 68 |
+
// }
|
| 69 |
+
//
|
| 70 |
+
// Since the sizing of the parameters is done at runtime, you must
|
| 71 |
+
// also specify the sizes after creating the
|
| 72 |
+
// DynamicNumericDiffCostFunction. For example:
|
| 73 |
+
//
|
| 74 |
+
// DynamicAutoDiffCostFunction<MyCostFunctor, CENTRAL> cost_function(
|
| 75 |
+
// new MyCostFunctor());
|
| 76 |
+
// cost_function.AddParameterBlock(5);
|
| 77 |
+
// cost_function.AddParameterBlock(10);
|
| 78 |
+
// cost_function.SetNumResiduals(21);
|
| 79 |
+
template <typename CostFunctor, NumericDiffMethodType method = CENTRAL>
|
| 80 |
+
class DynamicNumericDiffCostFunction final : public DynamicCostFunction {
|
| 81 |
+
public:
|
| 82 |
+
explicit DynamicNumericDiffCostFunction(
|
| 83 |
+
const CostFunctor* functor,
|
| 84 |
+
Ownership ownership = TAKE_OWNERSHIP,
|
| 85 |
+
const NumericDiffOptions& options = NumericDiffOptions())
|
| 86 |
+
: functor_(functor), ownership_(ownership), options_(options) {}
|
| 87 |
+
|
| 88 |
+
DynamicNumericDiffCostFunction(DynamicNumericDiffCostFunction&& other)
|
| 89 |
+
: functor_(std::move(other.functor_)), ownership_(other.ownership_) {}
|
| 90 |
+
|
| 91 |
+
~DynamicNumericDiffCostFunction() override {
|
| 92 |
+
if (ownership_ != TAKE_OWNERSHIP) {
|
| 93 |
+
functor_.release();
|
| 94 |
+
}
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
bool Evaluate(double const* const* parameters,
|
| 98 |
+
double* residuals,
|
| 99 |
+
double** jacobians) const override {
|
| 100 |
+
using internal::NumericDiff;
|
| 101 |
+
CHECK_GT(num_residuals(), 0)
|
| 102 |
+
<< "You must call DynamicNumericDiffCostFunction::SetNumResiduals() "
|
| 103 |
+
<< "before DynamicNumericDiffCostFunction::Evaluate().";
|
| 104 |
+
|
| 105 |
+
const std::vector<int32_t>& block_sizes = parameter_block_sizes();
|
| 106 |
+
CHECK(!block_sizes.empty())
|
| 107 |
+
<< "You must call DynamicNumericDiffCostFunction::AddParameterBlock() "
|
| 108 |
+
<< "before DynamicNumericDiffCostFunction::Evaluate().";
|
| 109 |
+
|
| 110 |
+
const bool status =
|
| 111 |
+
internal::VariadicEvaluate<internal::DynamicParameterDims>(
|
| 112 |
+
*functor_.get(), parameters, residuals);
|
| 113 |
+
if (jacobians == nullptr || !status) {
|
| 114 |
+
return status;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
// Create local space for a copy of the parameters which will get mutated.
|
| 118 |
+
int parameters_size = accumulate(block_sizes.begin(), block_sizes.end(), 0);
|
| 119 |
+
std::vector<double> parameters_copy(parameters_size);
|
| 120 |
+
std::vector<double*> parameters_references_copy(block_sizes.size());
|
| 121 |
+
parameters_references_copy[0] = ¶meters_copy[0];
|
| 122 |
+
for (size_t block = 1; block < block_sizes.size(); ++block) {
|
| 123 |
+
parameters_references_copy[block] =
|
| 124 |
+
parameters_references_copy[block - 1] + block_sizes[block - 1];
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
// Copy the parameters into the local temp space.
|
| 128 |
+
for (size_t block = 0; block < block_sizes.size(); ++block) {
|
| 129 |
+
memcpy(parameters_references_copy[block],
|
| 130 |
+
parameters[block],
|
| 131 |
+
block_sizes[block] * sizeof(*parameters[block]));
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
for (size_t block = 0; block < block_sizes.size(); ++block) {
|
| 135 |
+
if (jacobians[block] != nullptr &&
|
| 136 |
+
!NumericDiff<CostFunctor,
|
| 137 |
+
method,
|
| 138 |
+
ceres::DYNAMIC,
|
| 139 |
+
internal::DynamicParameterDims,
|
| 140 |
+
ceres::DYNAMIC,
|
| 141 |
+
ceres::DYNAMIC>::
|
| 142 |
+
EvaluateJacobianForParameterBlock(functor_.get(),
|
| 143 |
+
residuals,
|
| 144 |
+
options_,
|
| 145 |
+
this->num_residuals(),
|
| 146 |
+
block,
|
| 147 |
+
block_sizes[block],
|
| 148 |
+
¶meters_references_copy[0],
|
| 149 |
+
jacobians[block])) {
|
| 150 |
+
return false;
|
| 151 |
+
}
|
| 152 |
+
}
|
| 153 |
+
return true;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
private:
|
| 157 |
+
std::unique_ptr<const CostFunctor> functor_;
|
| 158 |
+
Ownership ownership_;
|
| 159 |
+
NumericDiffOptions options_;
|
| 160 |
+
};
|
| 161 |
+
|
| 162 |
+
} // namespace ceres
|
| 163 |
+
|
| 164 |
+
#endif // CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
|
ceres-v2/include/evaluation_callback.h
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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: mierle@gmail.com (Keir Mierle)
|
| 30 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_EVALUATION_CALLBACK_H_
|
| 32 |
+
#define CERES_PUBLIC_EVALUATION_CALLBACK_H_
|
| 33 |
+
|
| 34 |
+
#include "ceres/internal/export.h"
|
| 35 |
+
|
| 36 |
+
namespace ceres {
|
| 37 |
+
|
| 38 |
+
// Using this callback interface, Ceres can notify you when it is
|
| 39 |
+
// about to evaluate the residuals or jacobians. With the callback,
|
| 40 |
+
// you can share computation between residual blocks by doing the
|
| 41 |
+
// shared computation in PrepareForEvaluation() before Ceres calls
|
| 42 |
+
// CostFunction::Evaluate(). It also enables caching results between a
|
| 43 |
+
// pure residual evaluation and a residual & jacobian evaluation, via
|
| 44 |
+
// the new_evaluation_point argument.
|
| 45 |
+
//
|
| 46 |
+
// One use case for this callback is if the cost function compute is
|
| 47 |
+
// moved to the GPU. In that case, the prepare call does the actual
|
| 48 |
+
// cost function evaluation, and subsequent calls from Ceres to the
|
| 49 |
+
// actual cost functions merely copy the results from the GPU onto the
|
| 50 |
+
// corresponding blocks for Ceres to plug into the solver.
|
| 51 |
+
//
|
| 52 |
+
// NOTE: Ceres provides no mechanism to share data other than the
|
| 53 |
+
// notification from the callback. Users must provide access to
|
| 54 |
+
// pre-computed shared data to their cost functions behind the scenes;
|
| 55 |
+
// this all happens without Ceres knowing.
|
| 56 |
+
//
|
| 57 |
+
// One approach is to put a pointer to the shared data in each cost
|
| 58 |
+
// function (recommended) or to use a global shared variable
|
| 59 |
+
// (discouraged; bug-prone). As far as Ceres is concerned, it is
|
| 60 |
+
// evaluating cost functions like any other; it just so happens that
|
| 61 |
+
// behind the scenes the cost functions reuse pre-computed data to
|
| 62 |
+
// execute faster.
|
| 63 |
+
class CERES_EXPORT EvaluationCallback {
|
| 64 |
+
public:
|
| 65 |
+
virtual ~EvaluationCallback();
|
| 66 |
+
|
| 67 |
+
// Called before Ceres requests residuals or jacobians for a given setting of
|
| 68 |
+
// the parameters. User parameters (the double* values provided to the cost
|
| 69 |
+
// functions) are fixed until the next call to PrepareForEvaluation(). If
|
| 70 |
+
// new_evaluation_point == true, then this is a new point that is different
|
| 71 |
+
// from the last evaluated point. Otherwise, it is the same point that was
|
| 72 |
+
// evaluated previously (either jacobian or residual) and the user can use
|
| 73 |
+
// cached results from previous evaluations.
|
| 74 |
+
virtual void PrepareForEvaluation(bool evaluate_jacobians,
|
| 75 |
+
bool new_evaluation_point) = 0;
|
| 76 |
+
};
|
| 77 |
+
|
| 78 |
+
} // namespace ceres
|
| 79 |
+
|
| 80 |
+
#endif // CERES_PUBLIC_EVALUATION_CALLBACK_H_
|
ceres-v2/include/first_order_function.h
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_FIRST_ORDER_FUNCTION_H_
|
| 32 |
+
#define CERES_PUBLIC_FIRST_ORDER_FUNCTION_H_
|
| 33 |
+
|
| 34 |
+
#include "ceres/internal/export.h"
|
| 35 |
+
|
| 36 |
+
namespace ceres {
|
| 37 |
+
|
| 38 |
+
// A FirstOrderFunction object implements the evaluation of a function
|
| 39 |
+
// and its gradient.
|
| 40 |
+
class CERES_EXPORT FirstOrderFunction {
|
| 41 |
+
public:
|
| 42 |
+
virtual ~FirstOrderFunction();
|
| 43 |
+
|
| 44 |
+
// cost is never null. gradient may be null. The return value
|
| 45 |
+
// indicates whether the evaluation was successful or not.
|
| 46 |
+
virtual bool Evaluate(const double* const parameters,
|
| 47 |
+
double* cost,
|
| 48 |
+
double* gradient) const = 0;
|
| 49 |
+
virtual int NumParameters() const = 0;
|
| 50 |
+
};
|
| 51 |
+
|
| 52 |
+
} // namespace ceres
|
| 53 |
+
|
| 54 |
+
#endif // CERES_PUBLIC_FIRST_ORDER_FUNCTION_H_
|
ceres-v2/include/gradient_checker.h
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
// Copyright 2007 Google Inc. All Rights Reserved.
|
| 29 |
+
//
|
| 30 |
+
// Authors: wjr@google.com (William Rucklidge),
|
| 31 |
+
// keir@google.com (Keir Mierle),
|
| 32 |
+
// dgossow@google.com (David Gossow)
|
| 33 |
+
|
| 34 |
+
#ifndef CERES_PUBLIC_GRADIENT_CHECKER_H_
|
| 35 |
+
#define CERES_PUBLIC_GRADIENT_CHECKER_H_
|
| 36 |
+
|
| 37 |
+
#include <memory>
|
| 38 |
+
#include <string>
|
| 39 |
+
#include <vector>
|
| 40 |
+
|
| 41 |
+
#include "ceres/cost_function.h"
|
| 42 |
+
#include "ceres/dynamic_numeric_diff_cost_function.h"
|
| 43 |
+
#include "ceres/internal/disable_warnings.h"
|
| 44 |
+
#include "ceres/internal/eigen.h"
|
| 45 |
+
#include "ceres/internal/export.h"
|
| 46 |
+
#include "ceres/internal/fixed_array.h"
|
| 47 |
+
#include "ceres/local_parameterization.h"
|
| 48 |
+
#include "ceres/manifold.h"
|
| 49 |
+
#include "glog/logging.h"
|
| 50 |
+
|
| 51 |
+
namespace ceres {
|
| 52 |
+
|
| 53 |
+
// GradientChecker compares the Jacobians returned by a cost function against
|
| 54 |
+
// derivatives estimated using finite differencing.
|
| 55 |
+
//
|
| 56 |
+
// The condition enforced is that
|
| 57 |
+
//
|
| 58 |
+
// (J_actual(i, j) - J_numeric(i, j))
|
| 59 |
+
// ------------------------------------ < relative_precision
|
| 60 |
+
// max(J_actual(i, j), J_numeric(i, j))
|
| 61 |
+
//
|
| 62 |
+
// where J_actual(i, j) is the jacobian as computed by the supplied cost
|
| 63 |
+
// function (by the user) multiplied by the local parameterization Jacobian
|
| 64 |
+
// and J_numeric is the jacobian as computed by finite differences, multiplied
|
| 65 |
+
// by the local parameterization Jacobian as well.
|
| 66 |
+
//
|
| 67 |
+
// How to use: Fill in an array of pointers to parameter blocks for your
|
| 68 |
+
// CostFunction, and then call Probe(). Check that the return value is 'true'.
|
| 69 |
+
class CERES_EXPORT GradientChecker {
|
| 70 |
+
public:
|
| 71 |
+
// This constructor will not take ownership of the cost function or local
|
| 72 |
+
// parameterizations.
|
| 73 |
+
//
|
| 74 |
+
// function: The cost function to probe.
|
| 75 |
+
//
|
| 76 |
+
// local_parameterizations: A vector of local parameterizations, one for each
|
| 77 |
+
// parameter block. May be nullptr or contain nullptrs to indicate that the
|
| 78 |
+
// respective parameter does not have a local parameterization.
|
| 79 |
+
//
|
| 80 |
+
// options: Options to use for numerical differentiation.
|
| 81 |
+
//
|
| 82 |
+
// NOTE: This constructor is deprecated and will be removed in the next public
|
| 83 |
+
// release of Ceres Solver. Please transition to using the Manifold based
|
| 84 |
+
// version.
|
| 85 |
+
CERES_DEPRECATED_WITH_MSG(
|
| 86 |
+
"Local Parameterizations are deprecated. Use the constructor that uses "
|
| 87 |
+
"Manifolds instead.")
|
| 88 |
+
GradientChecker(
|
| 89 |
+
const CostFunction* function,
|
| 90 |
+
const std::vector<const LocalParameterization*>* local_parameterizations,
|
| 91 |
+
const NumericDiffOptions& options);
|
| 92 |
+
|
| 93 |
+
// This will not take ownership of the cost function or manifolds.
|
| 94 |
+
//
|
| 95 |
+
// function: The cost function to probe.
|
| 96 |
+
//
|
| 97 |
+
// manifolds: A vector of manifolds for each parameter. May be nullptr or
|
| 98 |
+
// contain nullptrs to indicate that the respective parameter blocks are
|
| 99 |
+
// Euclidean.
|
| 100 |
+
//
|
| 101 |
+
// options: Options to use for numerical differentiation.
|
| 102 |
+
GradientChecker(const CostFunction* function,
|
| 103 |
+
const std::vector<const Manifold*>* manifolds,
|
| 104 |
+
const NumericDiffOptions& options);
|
| 105 |
+
~GradientChecker();
|
| 106 |
+
|
| 107 |
+
// Contains results from a call to Probe for later inspection.
|
| 108 |
+
struct CERES_EXPORT ProbeResults {
|
| 109 |
+
// The return value of the cost function.
|
| 110 |
+
bool return_value;
|
| 111 |
+
|
| 112 |
+
// Computed residual vector.
|
| 113 |
+
Vector residuals;
|
| 114 |
+
|
| 115 |
+
// The sizes of the Jacobians below are dictated by the cost function's
|
| 116 |
+
// parameter block size and residual block sizes. If a parameter block has a
|
| 117 |
+
// manifold associated with it, the size of the "local" Jacobian will be
|
| 118 |
+
// determined by the dimension of the manifold (which is the same as the
|
| 119 |
+
// dimension of the tangent space) and residual block size, otherwise it
|
| 120 |
+
// will be identical to the regular Jacobian.
|
| 121 |
+
|
| 122 |
+
// Derivatives as computed by the cost function.
|
| 123 |
+
std::vector<Matrix> jacobians;
|
| 124 |
+
|
| 125 |
+
// Derivatives as computed by the cost function in local space.
|
| 126 |
+
std::vector<Matrix> local_jacobians;
|
| 127 |
+
|
| 128 |
+
// Derivatives as computed by numerical differentiation in local space.
|
| 129 |
+
std::vector<Matrix> numeric_jacobians;
|
| 130 |
+
|
| 131 |
+
// Derivatives as computed by numerical differentiation in local space.
|
| 132 |
+
std::vector<Matrix> local_numeric_jacobians;
|
| 133 |
+
|
| 134 |
+
// Contains the maximum relative error found in the local Jacobians.
|
| 135 |
+
double maximum_relative_error;
|
| 136 |
+
|
| 137 |
+
// If an error was detected, this will contain a detailed description of
|
| 138 |
+
// that error.
|
| 139 |
+
std::string error_log;
|
| 140 |
+
};
|
| 141 |
+
|
| 142 |
+
// Call the cost function, compute alternative Jacobians using finite
|
| 143 |
+
// differencing and compare results. If manifolds are given, the Jacobians
|
| 144 |
+
// will be multiplied by the manifold Jacobians before performing the check,
|
| 145 |
+
// which effectively means that all errors along the null space of the
|
| 146 |
+
// manifold will be ignored. Returns false if the Jacobians don't match, the
|
| 147 |
+
// cost function return false, or if a cost function returns a different
|
| 148 |
+
// residual when called with a Jacobian output argument vs. calling it
|
| 149 |
+
// without. Otherwise returns true.
|
| 150 |
+
//
|
| 151 |
+
// parameters: The parameter values at which to probe.
|
| 152 |
+
// relative_precision: A threshold for the relative difference between the
|
| 153 |
+
// Jacobians. If the Jacobians differ by more than this amount, then the
|
| 154 |
+
// probe fails.
|
| 155 |
+
// results: On return, the Jacobians (and other information) will be stored
|
| 156 |
+
// here. May be nullptr.
|
| 157 |
+
//
|
| 158 |
+
// Returns true if no problems are detected and the difference between the
|
| 159 |
+
// Jacobians is less than error_tolerance.
|
| 160 |
+
bool Probe(double const* const* parameters,
|
| 161 |
+
double relative_precision,
|
| 162 |
+
ProbeResults* results) const;
|
| 163 |
+
|
| 164 |
+
private:
|
| 165 |
+
GradientChecker() = delete;
|
| 166 |
+
GradientChecker(const GradientChecker&) = delete;
|
| 167 |
+
void operator=(const GradientChecker&) = delete;
|
| 168 |
+
|
| 169 |
+
// This bool is used to determine whether the constructor with the
|
| 170 |
+
// LocalParameterizations is called or the one with Manifolds is called. If
|
| 171 |
+
// the former, then the vector of manifolds is a vector of ManifoldAdapter
|
| 172 |
+
// objects which we own and should be deleted. If the latter then they are
|
| 173 |
+
// real Manifold objects owned by the caller and will not be deleted.
|
| 174 |
+
//
|
| 175 |
+
// This bool is only needed during the LocalParameterization to Manifold
|
| 176 |
+
// transition, once this transition is complete the LocalParameterization
|
| 177 |
+
// based constructor and this bool will be removed.
|
| 178 |
+
const bool delete_manifolds_ = false;
|
| 179 |
+
|
| 180 |
+
std::vector<const Manifold*> manifolds_;
|
| 181 |
+
const CostFunction* function_;
|
| 182 |
+
std::unique_ptr<CostFunction> finite_diff_cost_function_;
|
| 183 |
+
};
|
| 184 |
+
|
| 185 |
+
} // namespace ceres
|
| 186 |
+
|
| 187 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 188 |
+
|
| 189 |
+
#endif // CERES_PUBLIC_GRADIENT_CHECKER_H_
|
ceres-v2/include/gradient_problem.h
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_GRADIENT_PROBLEM_H_
|
| 32 |
+
#define CERES_PUBLIC_GRADIENT_PROBLEM_H_
|
| 33 |
+
|
| 34 |
+
#include <memory>
|
| 35 |
+
|
| 36 |
+
#include "ceres/first_order_function.h"
|
| 37 |
+
#include "ceres/internal/disable_warnings.h"
|
| 38 |
+
#include "ceres/internal/export.h"
|
| 39 |
+
#include "ceres/local_parameterization.h"
|
| 40 |
+
#include "ceres/manifold.h"
|
| 41 |
+
|
| 42 |
+
namespace ceres {
|
| 43 |
+
|
| 44 |
+
class FirstOrderFunction;
|
| 45 |
+
|
| 46 |
+
// Instances of GradientProblem represent general non-linear
|
| 47 |
+
// optimization problems that must be solved using just the value of
|
| 48 |
+
// the objective function and its gradient.
|
| 49 |
+
|
| 50 |
+
// Unlike the Problem class, which can only be used to model non-linear least
|
| 51 |
+
// squares problems, instances of GradientProblem are not restricted in the form
|
| 52 |
+
// of the objective function.
|
| 53 |
+
//
|
| 54 |
+
// Structurally GradientProblem is a composition of a FirstOrderFunction and
|
| 55 |
+
// optionally a Manifold.
|
| 56 |
+
//
|
| 57 |
+
// The FirstOrderFunction is responsible for evaluating the cost and gradient of
|
| 58 |
+
// the objective function.
|
| 59 |
+
//
|
| 60 |
+
// The Manifold is responsible for going back and forth between the ambient
|
| 61 |
+
// space and the local tangent space. (See manifold.h for more details). When a
|
| 62 |
+
// Manifold is not provided, then the tangent space is assumed to coincide with
|
| 63 |
+
// the ambient Euclidean space that the gradient vector lives in.
|
| 64 |
+
//
|
| 65 |
+
// Example usage:
|
| 66 |
+
//
|
| 67 |
+
// The following demonstrate the problem construction for Rosenbrock's function
|
| 68 |
+
//
|
| 69 |
+
// f(x,y) = (1-x)^2 + 100(y - x^2)^2;
|
| 70 |
+
//
|
| 71 |
+
// class Rosenbrock : public ceres::FirstOrderFunction {
|
| 72 |
+
// public:
|
| 73 |
+
// virtual ~Rosenbrock() {}
|
| 74 |
+
//
|
| 75 |
+
// virtual bool Evaluate(const double* parameters,
|
| 76 |
+
// double* cost,
|
| 77 |
+
// double* gradient) const {
|
| 78 |
+
// const double x = parameters[0];
|
| 79 |
+
// const double y = parameters[1];
|
| 80 |
+
//
|
| 81 |
+
// cost[0] = (1.0 - x) * (1.0 - x) + 100.0 * (y - x * x) * (y - x * x);
|
| 82 |
+
// if (gradient != nullptr) {
|
| 83 |
+
// gradient[0] = -2.0 * (1.0 - x) - 200.0 * (y - x * x) * 2.0 * x;
|
| 84 |
+
// gradient[1] = 200.0 * (y - x * x);
|
| 85 |
+
// }
|
| 86 |
+
// return true;
|
| 87 |
+
// };
|
| 88 |
+
//
|
| 89 |
+
// virtual int NumParameters() const { return 2; };
|
| 90 |
+
// };
|
| 91 |
+
//
|
| 92 |
+
// ceres::GradientProblem problem(new Rosenbrock());
|
| 93 |
+
//
|
| 94 |
+
// NOTE: We are currently in the process of transitioning from
|
| 95 |
+
// LocalParameterization to Manifolds in the Ceres API. During this period,
|
| 96 |
+
// GradientProblem will support using both Manifold and LocalParameterization
|
| 97 |
+
// objects interchangably. For methods in the API affected by this change, see
|
| 98 |
+
// their documentation below.
|
| 99 |
+
class CERES_EXPORT GradientProblem {
|
| 100 |
+
public:
|
| 101 |
+
// Takes ownership of the function.
|
| 102 |
+
explicit GradientProblem(FirstOrderFunction* function);
|
| 103 |
+
|
| 104 |
+
// Takes ownership of the function and the parameterization.
|
| 105 |
+
//
|
| 106 |
+
// NOTE: This constructor is deprecated and will be removed in the next public
|
| 107 |
+
// release of Ceres Solver. Please move to using the Manifold based
|
| 108 |
+
// constructor.
|
| 109 |
+
CERES_DEPRECATED_WITH_MSG(
|
| 110 |
+
"LocalParameterizations are deprecated. Please use the constructor that "
|
| 111 |
+
"uses Manifold instead.")
|
| 112 |
+
GradientProblem(FirstOrderFunction* function,
|
| 113 |
+
LocalParameterization* parameterization);
|
| 114 |
+
|
| 115 |
+
// Takes ownership of the function and the manifold.
|
| 116 |
+
GradientProblem(FirstOrderFunction* function, Manifold* manifold);
|
| 117 |
+
|
| 118 |
+
int NumParameters() const;
|
| 119 |
+
|
| 120 |
+
// Dimension of the manifold (and its tangent space).
|
| 121 |
+
//
|
| 122 |
+
// During the transition from LocalParameterization to Manifold, this method
|
| 123 |
+
// reports the LocalSize of the LocalParameterization or the TangentSize of
|
| 124 |
+
// the Manifold object associated with this problem.
|
| 125 |
+
int NumTangentParameters() const;
|
| 126 |
+
|
| 127 |
+
// Dimension of the manifold (and its tangent space).
|
| 128 |
+
//
|
| 129 |
+
// NOTE: This method is deprecated and will be removed in the next public
|
| 130 |
+
// release of Ceres Solver. Please move to using NumTangentParameters()
|
| 131 |
+
// instead.
|
| 132 |
+
int NumLocalParameters() const { return NumTangentParameters(); }
|
| 133 |
+
|
| 134 |
+
// This call is not thread safe.
|
| 135 |
+
bool Evaluate(const double* parameters, double* cost, double* gradient) const;
|
| 136 |
+
bool Plus(const double* x, const double* delta, double* x_plus_delta) const;
|
| 137 |
+
|
| 138 |
+
const FirstOrderFunction* function() const { return function_.get(); }
|
| 139 |
+
FirstOrderFunction* mutable_function() { return function_.get(); }
|
| 140 |
+
|
| 141 |
+
// NOTE: During the transition from LocalParameterization to Manifold we need
|
| 142 |
+
// to support both The LocalParameterization and Manifold based constructors.
|
| 143 |
+
//
|
| 144 |
+
// When the user uses the LocalParameterization, internally the solver will
|
| 145 |
+
// wrap it in a ManifoldAdapter object and return it when manifold or
|
| 146 |
+
// mutable_manifold are called.
|
| 147 |
+
//
|
| 148 |
+
// As a result this method will return a non-nullptr result if a Manifold or a
|
| 149 |
+
// LocalParameterization was used when constructing the GradientProblem.
|
| 150 |
+
const Manifold* manifold() const { return manifold_.get(); }
|
| 151 |
+
Manifold* mutable_manifold() { return manifold_.get(); }
|
| 152 |
+
|
| 153 |
+
// If the problem is constructed without a LocalParameterization or with a
|
| 154 |
+
// Manifold this method will return a nullptr.
|
| 155 |
+
//
|
| 156 |
+
// NOTE: This method is deprecated and will be removed in the next public
|
| 157 |
+
// release of Ceres Solver.
|
| 158 |
+
CERES_DEPRECATED_WITH_MSG("Use Manifolds instead.")
|
| 159 |
+
const LocalParameterization* parameterization() const {
|
| 160 |
+
return parameterization_.get();
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
// If the problem is constructed without a LocalParameterization or with a
|
| 164 |
+
// Manifold this method will return a nullptr.
|
| 165 |
+
//
|
| 166 |
+
// NOTE: This method is deprecated and will be removed in the next public
|
| 167 |
+
// release of Ceres Solver.
|
| 168 |
+
CERES_DEPRECATED_WITH_MSG("Use Manifolds instead.")
|
| 169 |
+
LocalParameterization* mutable_parameterization() {
|
| 170 |
+
return parameterization_.get();
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
private:
|
| 174 |
+
std::unique_ptr<FirstOrderFunction> function_;
|
| 175 |
+
CERES_DEPRECATED_WITH_MSG("")
|
| 176 |
+
std::unique_ptr<LocalParameterization> parameterization_;
|
| 177 |
+
std::unique_ptr<Manifold> manifold_;
|
| 178 |
+
std::unique_ptr<double[]> scratch_;
|
| 179 |
+
};
|
| 180 |
+
|
| 181 |
+
} // namespace ceres
|
| 182 |
+
|
| 183 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 184 |
+
|
| 185 |
+
#endif // CERES_PUBLIC_GRADIENT_PROBLEM_H_
|
ceres-v2/include/gradient_problem_solver.h
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_GRADIENT_PROBLEM_SOLVER_H_
|
| 32 |
+
#define CERES_PUBLIC_GRADIENT_PROBLEM_SOLVER_H_
|
| 33 |
+
|
| 34 |
+
#include <cmath>
|
| 35 |
+
#include <string>
|
| 36 |
+
#include <vector>
|
| 37 |
+
|
| 38 |
+
#include "ceres/internal/disable_warnings.h"
|
| 39 |
+
#include "ceres/internal/export.h"
|
| 40 |
+
#include "ceres/internal/port.h"
|
| 41 |
+
#include "ceres/iteration_callback.h"
|
| 42 |
+
#include "ceres/types.h"
|
| 43 |
+
|
| 44 |
+
namespace ceres {
|
| 45 |
+
|
| 46 |
+
class GradientProblem;
|
| 47 |
+
|
| 48 |
+
class CERES_EXPORT GradientProblemSolver {
|
| 49 |
+
public:
|
| 50 |
+
virtual ~GradientProblemSolver();
|
| 51 |
+
|
| 52 |
+
// The options structure contains, not surprisingly, options that control how
|
| 53 |
+
// the solver operates. The defaults should be suitable for a wide range of
|
| 54 |
+
// problems; however, better performance is often obtainable with tweaking.
|
| 55 |
+
//
|
| 56 |
+
// The constants are defined inside types.h
|
| 57 |
+
struct CERES_EXPORT Options {
|
| 58 |
+
// Returns true if the options struct has a valid
|
| 59 |
+
// configuration. Returns false otherwise, and fills in *error
|
| 60 |
+
// with a message describing the problem.
|
| 61 |
+
bool IsValid(std::string* error) const;
|
| 62 |
+
|
| 63 |
+
// Minimizer options ----------------------------------------
|
| 64 |
+
LineSearchDirectionType line_search_direction_type = LBFGS;
|
| 65 |
+
LineSearchType line_search_type = WOLFE;
|
| 66 |
+
NonlinearConjugateGradientType nonlinear_conjugate_gradient_type =
|
| 67 |
+
FLETCHER_REEVES;
|
| 68 |
+
|
| 69 |
+
// The LBFGS hessian approximation is a low rank approximation to
|
| 70 |
+
// the inverse of the Hessian matrix. The rank of the
|
| 71 |
+
// approximation determines (linearly) the space and time
|
| 72 |
+
// complexity of using the approximation. Higher the rank, the
|
| 73 |
+
// better is the quality of the approximation. The increase in
|
| 74 |
+
// quality is however is bounded for a number of reasons.
|
| 75 |
+
//
|
| 76 |
+
// 1. The method only uses secant information and not actual
|
| 77 |
+
// derivatives.
|
| 78 |
+
//
|
| 79 |
+
// 2. The Hessian approximation is constrained to be positive
|
| 80 |
+
// definite.
|
| 81 |
+
//
|
| 82 |
+
// So increasing this rank to a large number will cost time and
|
| 83 |
+
// space complexity without the corresponding increase in solution
|
| 84 |
+
// quality. There are no hard and fast rules for choosing the
|
| 85 |
+
// maximum rank. The best choice usually requires some problem
|
| 86 |
+
// specific experimentation.
|
| 87 |
+
//
|
| 88 |
+
// For more theoretical and implementation details of the LBFGS
|
| 89 |
+
// method, please see:
|
| 90 |
+
//
|
| 91 |
+
// Nocedal, J. (1980). "Updating Quasi-Newton Matrices with
|
| 92 |
+
// Limited Storage". Mathematics of Computation 35 (151): 773-782.
|
| 93 |
+
int max_lbfgs_rank = 20;
|
| 94 |
+
|
| 95 |
+
// As part of the (L)BFGS update step (BFGS) / right-multiply step (L-BFGS),
|
| 96 |
+
// the initial inverse Hessian approximation is taken to be the Identity.
|
| 97 |
+
// However, Oren showed that using instead I * \gamma, where \gamma is
|
| 98 |
+
// chosen to approximate an eigenvalue of the true inverse Hessian can
|
| 99 |
+
// result in improved convergence in a wide variety of cases. Setting
|
| 100 |
+
// use_approximate_eigenvalue_bfgs_scaling to true enables this scaling.
|
| 101 |
+
//
|
| 102 |
+
// It is important to note that approximate eigenvalue scaling does not
|
| 103 |
+
// always improve convergence, and that it can in fact significantly degrade
|
| 104 |
+
// performance for certain classes of problem, which is why it is disabled
|
| 105 |
+
// by default. In particular it can degrade performance when the
|
| 106 |
+
// sensitivity of the problem to different parameters varies significantly,
|
| 107 |
+
// as in this case a single scalar factor fails to capture this variation
|
| 108 |
+
// and detrimentally downscales parts of the jacobian approximation which
|
| 109 |
+
// correspond to low-sensitivity parameters. It can also reduce the
|
| 110 |
+
// robustness of the solution to errors in the jacobians.
|
| 111 |
+
//
|
| 112 |
+
// Oren S.S., Self-scaling variable metric (SSVM) algorithms
|
| 113 |
+
// Part II: Implementation and experiments, Management Science,
|
| 114 |
+
// 20(5), 863-874, 1974.
|
| 115 |
+
bool use_approximate_eigenvalue_bfgs_scaling = false;
|
| 116 |
+
|
| 117 |
+
// Degree of the polynomial used to approximate the objective
|
| 118 |
+
// function. Valid values are BISECTION, QUADRATIC and CUBIC.
|
| 119 |
+
//
|
| 120 |
+
// BISECTION corresponds to pure backtracking search with no
|
| 121 |
+
// interpolation.
|
| 122 |
+
LineSearchInterpolationType line_search_interpolation_type = CUBIC;
|
| 123 |
+
|
| 124 |
+
// If during the line search, the step_size falls below this
|
| 125 |
+
// value, it is truncated to zero.
|
| 126 |
+
double min_line_search_step_size = 1e-9;
|
| 127 |
+
|
| 128 |
+
// Line search parameters.
|
| 129 |
+
|
| 130 |
+
// Solving the line search problem exactly is computationally
|
| 131 |
+
// prohibitive. Fortunately, line search based optimization
|
| 132 |
+
// algorithms can still guarantee convergence if instead of an
|
| 133 |
+
// exact solution, the line search algorithm returns a solution
|
| 134 |
+
// which decreases the value of the objective function
|
| 135 |
+
// sufficiently. More precisely, we are looking for a step_size
|
| 136 |
+
// s.t.
|
| 137 |
+
//
|
| 138 |
+
// f(step_size) <= f(0) + sufficient_decrease * f'(0) * step_size
|
| 139 |
+
//
|
| 140 |
+
double line_search_sufficient_function_decrease = 1e-4;
|
| 141 |
+
|
| 142 |
+
// In each iteration of the line search,
|
| 143 |
+
//
|
| 144 |
+
// new_step_size >= max_line_search_step_contraction * step_size
|
| 145 |
+
//
|
| 146 |
+
// Note that by definition, for contraction:
|
| 147 |
+
//
|
| 148 |
+
// 0 < max_step_contraction < min_step_contraction < 1
|
| 149 |
+
//
|
| 150 |
+
double max_line_search_step_contraction = 1e-3;
|
| 151 |
+
|
| 152 |
+
// In each iteration of the line search,
|
| 153 |
+
//
|
| 154 |
+
// new_step_size <= min_line_search_step_contraction * step_size
|
| 155 |
+
//
|
| 156 |
+
// Note that by definition, for contraction:
|
| 157 |
+
//
|
| 158 |
+
// 0 < max_step_contraction < min_step_contraction < 1
|
| 159 |
+
//
|
| 160 |
+
double min_line_search_step_contraction = 0.6;
|
| 161 |
+
|
| 162 |
+
// Maximum number of trial step size iterations during each line search,
|
| 163 |
+
// if a step size satisfying the search conditions cannot be found within
|
| 164 |
+
// this number of trials, the line search will terminate.
|
| 165 |
+
int max_num_line_search_step_size_iterations = 20;
|
| 166 |
+
|
| 167 |
+
// Maximum number of restarts of the line search direction algorithm before
|
| 168 |
+
// terminating the optimization. Restarts of the line search direction
|
| 169 |
+
// algorithm occur when the current algorithm fails to produce a new descent
|
| 170 |
+
// direction. This typically indicates a numerical failure, or a breakdown
|
| 171 |
+
// in the validity of the approximations used.
|
| 172 |
+
int max_num_line_search_direction_restarts = 5;
|
| 173 |
+
|
| 174 |
+
// The strong Wolfe conditions consist of the Armijo sufficient
|
| 175 |
+
// decrease condition, and an additional requirement that the
|
| 176 |
+
// step-size be chosen s.t. the _magnitude_ ('strong' Wolfe
|
| 177 |
+
// conditions) of the gradient along the search direction
|
| 178 |
+
// decreases sufficiently. Precisely, this second condition
|
| 179 |
+
// is that we seek a step_size s.t.
|
| 180 |
+
//
|
| 181 |
+
// |f'(step_size)| <= sufficient_curvature_decrease * |f'(0)|
|
| 182 |
+
//
|
| 183 |
+
// Where f() is the line search objective and f'() is the derivative
|
| 184 |
+
// of f w.r.t step_size (d f / d step_size).
|
| 185 |
+
double line_search_sufficient_curvature_decrease = 0.9;
|
| 186 |
+
|
| 187 |
+
// During the bracketing phase of the Wolfe search, the step size is
|
| 188 |
+
// increased until either a point satisfying the Wolfe conditions is
|
| 189 |
+
// found, or an upper bound for a bracket containing a point satisfying
|
| 190 |
+
// the conditions is found. Precisely, at each iteration of the
|
| 191 |
+
// expansion:
|
| 192 |
+
//
|
| 193 |
+
// new_step_size <= max_step_expansion * step_size.
|
| 194 |
+
//
|
| 195 |
+
// By definition for expansion, max_step_expansion > 1.0.
|
| 196 |
+
double max_line_search_step_expansion = 10.0;
|
| 197 |
+
|
| 198 |
+
// Maximum number of iterations for the minimizer to run for.
|
| 199 |
+
int max_num_iterations = 50;
|
| 200 |
+
|
| 201 |
+
// Maximum time for which the minimizer should run for.
|
| 202 |
+
double max_solver_time_in_seconds = 1e9;
|
| 203 |
+
|
| 204 |
+
// Minimizer terminates when
|
| 205 |
+
//
|
| 206 |
+
// (new_cost - old_cost) < function_tolerance * old_cost;
|
| 207 |
+
//
|
| 208 |
+
double function_tolerance = 1e-6;
|
| 209 |
+
|
| 210 |
+
// Minimizer terminates when
|
| 211 |
+
//
|
| 212 |
+
// max_i |x - Project(Plus(x, -g(x))| < gradient_tolerance
|
| 213 |
+
//
|
| 214 |
+
// This value should typically be 1e-4 * function_tolerance.
|
| 215 |
+
double gradient_tolerance = 1e-10;
|
| 216 |
+
|
| 217 |
+
// Minimizer terminates when
|
| 218 |
+
//
|
| 219 |
+
// |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance)
|
| 220 |
+
//
|
| 221 |
+
double parameter_tolerance = 1e-8;
|
| 222 |
+
|
| 223 |
+
// Logging options ---------------------------------------------------------
|
| 224 |
+
|
| 225 |
+
LoggingType logging_type = PER_MINIMIZER_ITERATION;
|
| 226 |
+
|
| 227 |
+
// By default the Minimizer progress is logged to VLOG(1), which
|
| 228 |
+
// is sent to STDERR depending on the vlog level. If this flag is
|
| 229 |
+
// set to true, and logging_type is not SILENT, the logging output
|
| 230 |
+
// is sent to STDOUT.
|
| 231 |
+
bool minimizer_progress_to_stdout = false;
|
| 232 |
+
|
| 233 |
+
// If true, the user's parameter blocks are updated at the end of
|
| 234 |
+
// every Minimizer iteration, otherwise they are updated when the
|
| 235 |
+
// Minimizer terminates. This is useful if, for example, the user
|
| 236 |
+
// wishes to visualize the state of the optimization every
|
| 237 |
+
// iteration.
|
| 238 |
+
bool update_state_every_iteration = false;
|
| 239 |
+
|
| 240 |
+
// Callbacks that are executed at the end of each iteration of the
|
| 241 |
+
// Minimizer. An iteration may terminate midway, either due to
|
| 242 |
+
// numerical failures or because one of the convergence tests has
|
| 243 |
+
// been satisfied. In this case none of the callbacks are
|
| 244 |
+
// executed.
|
| 245 |
+
|
| 246 |
+
// Callbacks are executed in the order that they are specified in
|
| 247 |
+
// this vector. By default, parameter blocks are updated only at
|
| 248 |
+
// the end of the optimization, i.e when the Minimizer
|
| 249 |
+
// terminates. This behaviour is controlled by
|
| 250 |
+
// update_state_every_variable. If the user wishes to have access
|
| 251 |
+
// to the update parameter blocks when his/her callbacks are
|
| 252 |
+
// executed, then set update_state_every_iteration to true.
|
| 253 |
+
//
|
| 254 |
+
// The solver does NOT take ownership of these pointers.
|
| 255 |
+
std::vector<IterationCallback*> callbacks;
|
| 256 |
+
};
|
| 257 |
+
|
| 258 |
+
struct CERES_EXPORT Summary {
|
| 259 |
+
// A brief one line description of the state of the solver after
|
| 260 |
+
// termination.
|
| 261 |
+
std::string BriefReport() const;
|
| 262 |
+
|
| 263 |
+
// A full multiline description of the state of the solver after
|
| 264 |
+
// termination.
|
| 265 |
+
std::string FullReport() const;
|
| 266 |
+
|
| 267 |
+
bool IsSolutionUsable() const;
|
| 268 |
+
|
| 269 |
+
// Minimizer summary -------------------------------------------------
|
| 270 |
+
TerminationType termination_type = FAILURE;
|
| 271 |
+
|
| 272 |
+
// Reason why the solver terminated.
|
| 273 |
+
std::string message = "ceres::GradientProblemSolve was not called.";
|
| 274 |
+
|
| 275 |
+
// Cost of the problem (value of the objective function) before
|
| 276 |
+
// the optimization.
|
| 277 |
+
double initial_cost = -1.0;
|
| 278 |
+
|
| 279 |
+
// Cost of the problem (value of the objective function) after the
|
| 280 |
+
// optimization.
|
| 281 |
+
double final_cost = -1.0;
|
| 282 |
+
|
| 283 |
+
// IterationSummary for each minimizer iteration in order.
|
| 284 |
+
std::vector<IterationSummary> iterations;
|
| 285 |
+
|
| 286 |
+
// Number of times the cost (and not the gradient) was evaluated.
|
| 287 |
+
int num_cost_evaluations = -1;
|
| 288 |
+
|
| 289 |
+
// Number of times the gradient (and the cost) were evaluated.
|
| 290 |
+
int num_gradient_evaluations = -1;
|
| 291 |
+
|
| 292 |
+
// Sum total of all time spent inside Ceres when Solve is called.
|
| 293 |
+
double total_time_in_seconds = -1.0;
|
| 294 |
+
|
| 295 |
+
// Time (in seconds) spent evaluating the cost.
|
| 296 |
+
double cost_evaluation_time_in_seconds = -1.0;
|
| 297 |
+
|
| 298 |
+
// Time (in seconds) spent evaluating the gradient.
|
| 299 |
+
double gradient_evaluation_time_in_seconds = -1.0;
|
| 300 |
+
|
| 301 |
+
// Time (in seconds) spent minimizing the interpolating polynomial
|
| 302 |
+
// to compute the next candidate step size as part of a line search.
|
| 303 |
+
double line_search_polynomial_minimization_time_in_seconds = -1.0;
|
| 304 |
+
|
| 305 |
+
// Number of parameters in the problem.
|
| 306 |
+
int num_parameters = -1;
|
| 307 |
+
|
| 308 |
+
// Dimension of the tangent space of the problem.
|
| 309 |
+
CERES_DEPRECATED_WITH_MSG("Use num_tangent_parameters.")
|
| 310 |
+
int num_local_parameters = -1;
|
| 311 |
+
|
| 312 |
+
// Dimension of the tangent space of the problem.
|
| 313 |
+
int num_tangent_parameters = -1;
|
| 314 |
+
|
| 315 |
+
// Type of line search direction used.
|
| 316 |
+
LineSearchDirectionType line_search_direction_type = LBFGS;
|
| 317 |
+
|
| 318 |
+
// Type of the line search algorithm used.
|
| 319 |
+
LineSearchType line_search_type = WOLFE;
|
| 320 |
+
|
| 321 |
+
// When performing line search, the degree of the polynomial used
|
| 322 |
+
// to approximate the objective function.
|
| 323 |
+
LineSearchInterpolationType line_search_interpolation_type = CUBIC;
|
| 324 |
+
|
| 325 |
+
// If the line search direction is NONLINEAR_CONJUGATE_GRADIENT,
|
| 326 |
+
// then this indicates the particular variant of non-linear
|
| 327 |
+
// conjugate gradient used.
|
| 328 |
+
NonlinearConjugateGradientType nonlinear_conjugate_gradient_type =
|
| 329 |
+
FLETCHER_REEVES;
|
| 330 |
+
|
| 331 |
+
// If the type of the line search direction is LBFGS, then this
|
| 332 |
+
// indicates the rank of the Hessian approximation.
|
| 333 |
+
int max_lbfgs_rank = -1;
|
| 334 |
+
};
|
| 335 |
+
|
| 336 |
+
// Once a least squares problem has been built, this function takes
|
| 337 |
+
// the problem and optimizes it based on the values of the options
|
| 338 |
+
// parameters. Upon return, a detailed summary of the work performed
|
| 339 |
+
// by the preprocessor, the non-linear minimizer and the linear
|
| 340 |
+
// solver are reported in the summary object.
|
| 341 |
+
virtual void Solve(const GradientProblemSolver::Options& options,
|
| 342 |
+
const GradientProblem& problem,
|
| 343 |
+
double* parameters,
|
| 344 |
+
GradientProblemSolver::Summary* summary);
|
| 345 |
+
};
|
| 346 |
+
|
| 347 |
+
// Helper function which avoids going through the interface.
|
| 348 |
+
CERES_EXPORT void Solve(const GradientProblemSolver::Options& options,
|
| 349 |
+
const GradientProblem& problem,
|
| 350 |
+
double* parameters,
|
| 351 |
+
GradientProblemSolver::Summary* summary);
|
| 352 |
+
|
| 353 |
+
} // namespace ceres
|
| 354 |
+
|
| 355 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 356 |
+
|
| 357 |
+
#endif // CERES_PUBLIC_GRADIENT_PROBLEM_SOLVER_H_
|
ceres-v2/include/internal/array_selector.h
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2020 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: darius.rueckert@fau.de (Darius Rueckert)
|
| 30 |
+
//
|
| 31 |
+
|
| 32 |
+
#ifndef CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
|
| 33 |
+
#define CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
|
| 34 |
+
|
| 35 |
+
#include <array>
|
| 36 |
+
#include <vector>
|
| 37 |
+
|
| 38 |
+
#include "ceres/internal/fixed_array.h"
|
| 39 |
+
#include "ceres/types.h"
|
| 40 |
+
|
| 41 |
+
namespace ceres {
|
| 42 |
+
namespace internal {
|
| 43 |
+
|
| 44 |
+
// StaticFixedArray selects the best array implementation based on template
|
| 45 |
+
// arguments. If the size is not known at compile-time, pass
|
| 46 |
+
// ceres::DYNAMIC as a size-template argument.
|
| 47 |
+
//
|
| 48 |
+
// Three different containers are selected in different scenarios:
|
| 49 |
+
//
|
| 50 |
+
// num_elements == DYNAMIC:
|
| 51 |
+
// -> ceres::internal::FixedArray<T, max_stack_size>(size)
|
| 52 |
+
|
| 53 |
+
// num_elements != DYNAMIC && num_elements <= max_stack_size
|
| 54 |
+
// -> std::array<T,num_elements>
|
| 55 |
+
|
| 56 |
+
// num_elements != DYNAMIC && num_elements > max_stack_size
|
| 57 |
+
// -> std::vector<T>(num_elements)
|
| 58 |
+
//
|
| 59 |
+
template <typename T,
|
| 60 |
+
int num_elements,
|
| 61 |
+
int max_num_elements_on_stack,
|
| 62 |
+
bool dynamic = (num_elements == DYNAMIC),
|
| 63 |
+
bool fits_on_stack = (num_elements <= max_num_elements_on_stack)>
|
| 64 |
+
struct ArraySelector {};
|
| 65 |
+
|
| 66 |
+
template <typename T,
|
| 67 |
+
int num_elements,
|
| 68 |
+
int max_num_elements_on_stack,
|
| 69 |
+
bool fits_on_stack>
|
| 70 |
+
struct ArraySelector<T,
|
| 71 |
+
num_elements,
|
| 72 |
+
max_num_elements_on_stack,
|
| 73 |
+
true,
|
| 74 |
+
fits_on_stack>
|
| 75 |
+
: ceres::internal::FixedArray<T, max_num_elements_on_stack> {
|
| 76 |
+
explicit ArraySelector(int s)
|
| 77 |
+
: ceres::internal::FixedArray<T, max_num_elements_on_stack>(s) {}
|
| 78 |
+
};
|
| 79 |
+
|
| 80 |
+
template <typename T, int num_elements, int max_num_elements_on_stack>
|
| 81 |
+
struct ArraySelector<T, num_elements, max_num_elements_on_stack, false, true>
|
| 82 |
+
: std::array<T, num_elements> {
|
| 83 |
+
explicit ArraySelector(int s) { CHECK_EQ(s, num_elements); }
|
| 84 |
+
};
|
| 85 |
+
|
| 86 |
+
template <typename T, int num_elements, int max_num_elements_on_stack>
|
| 87 |
+
struct ArraySelector<T, num_elements, max_num_elements_on_stack, false, false>
|
| 88 |
+
: std::vector<T> {
|
| 89 |
+
explicit ArraySelector(int s) : std::vector<T>(s) {
|
| 90 |
+
CHECK_EQ(s, num_elements);
|
| 91 |
+
}
|
| 92 |
+
};
|
| 93 |
+
|
| 94 |
+
} // namespace internal
|
| 95 |
+
} // namespace ceres
|
| 96 |
+
|
| 97 |
+
#endif // CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
|
ceres-v2/include/internal/autodiff.h
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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: keir@google.com (Keir Mierle)
|
| 30 |
+
//
|
| 31 |
+
// Computation of the Jacobian matrix for vector-valued functions of multiple
|
| 32 |
+
// variables, using automatic differentiation based on the implementation of
|
| 33 |
+
// dual numbers in jet.h. Before reading the rest of this file, it is advisable
|
| 34 |
+
// to read jet.h's header comment in detail.
|
| 35 |
+
//
|
| 36 |
+
// The helper wrapper AutoDifferentiate() computes the jacobian of
|
| 37 |
+
// functors with templated operator() taking this form:
|
| 38 |
+
//
|
| 39 |
+
// struct F {
|
| 40 |
+
// template<typename T>
|
| 41 |
+
// bool operator()(const T *x, const T *y, ..., T *z) {
|
| 42 |
+
// // Compute z[] based on x[], y[], ...
|
| 43 |
+
// // return true if computation succeeded, false otherwise.
|
| 44 |
+
// }
|
| 45 |
+
// };
|
| 46 |
+
//
|
| 47 |
+
// All inputs and outputs may be vector-valued.
|
| 48 |
+
//
|
| 49 |
+
// To understand how jets are used to compute the jacobian, a
|
| 50 |
+
// picture may help. Consider a vector-valued function, F, returning 3
|
| 51 |
+
// dimensions and taking a vector-valued parameter of 4 dimensions:
|
| 52 |
+
//
|
| 53 |
+
// y x
|
| 54 |
+
// [ * ] F [ * ]
|
| 55 |
+
// [ * ] <--- [ * ]
|
| 56 |
+
// [ * ] [ * ]
|
| 57 |
+
// [ * ]
|
| 58 |
+
//
|
| 59 |
+
// Similar to the 2-parameter example for f described in jet.h, computing the
|
| 60 |
+
// jacobian dy/dx is done by substituting a suitable jet object for x and all
|
| 61 |
+
// intermediate steps of the computation of F. Since x is has 4 dimensions, use
|
| 62 |
+
// a Jet<double, 4>.
|
| 63 |
+
//
|
| 64 |
+
// Before substituting a jet object for x, the dual components are set
|
| 65 |
+
// appropriately for each dimension of x:
|
| 66 |
+
//
|
| 67 |
+
// y x
|
| 68 |
+
// [ * | * * * * ] f [ * | 1 0 0 0 ] x0
|
| 69 |
+
// [ * | * * * * ] <--- [ * | 0 1 0 0 ] x1
|
| 70 |
+
// [ * | * * * * ] [ * | 0 0 1 0 ] x2
|
| 71 |
+
// ---+--- [ * | 0 0 0 1 ] x3
|
| 72 |
+
// | ^ ^ ^ ^
|
| 73 |
+
// dy/dx | | | +----- infinitesimal for x3
|
| 74 |
+
// | | +------- infinitesimal for x2
|
| 75 |
+
// | +--------- infinitesimal for x1
|
| 76 |
+
// +----------- infinitesimal for x0
|
| 77 |
+
//
|
| 78 |
+
// The reason to set the internal 4x4 submatrix to the identity is that we wish
|
| 79 |
+
// to take the derivative of y separately with respect to each dimension of x.
|
| 80 |
+
// Each column of the 4x4 identity is therefore for a single component of the
|
| 81 |
+
// independent variable x.
|
| 82 |
+
//
|
| 83 |
+
// Then the jacobian of the mapping, dy/dx, is the 3x4 sub-matrix of the
|
| 84 |
+
// extended y vector, indicated in the above diagram.
|
| 85 |
+
//
|
| 86 |
+
// Functors with multiple parameters
|
| 87 |
+
// ---------------------------------
|
| 88 |
+
// In practice, it is often convenient to use a function f of two or more
|
| 89 |
+
// vector-valued parameters, for example, x[3] and z[6]. Unfortunately, the jet
|
| 90 |
+
// framework is designed for a single-parameter vector-valued input. The wrapper
|
| 91 |
+
// in this file addresses this issue adding support for functions with one or
|
| 92 |
+
// more parameter vectors.
|
| 93 |
+
//
|
| 94 |
+
// To support multiple parameters, all the parameter vectors are concatenated
|
| 95 |
+
// into one and treated as a single parameter vector, except that since the
|
| 96 |
+
// functor expects different inputs, we need to construct the jets as if they
|
| 97 |
+
// were part of a single parameter vector. The extended jets are passed
|
| 98 |
+
// separately for each parameter.
|
| 99 |
+
//
|
| 100 |
+
// For example, consider a functor F taking two vector parameters, p[2] and
|
| 101 |
+
// q[3], and producing an output y[4]:
|
| 102 |
+
//
|
| 103 |
+
// struct F {
|
| 104 |
+
// template<typename T>
|
| 105 |
+
// bool operator()(const T *p, const T *q, T *z) {
|
| 106 |
+
// // ...
|
| 107 |
+
// }
|
| 108 |
+
// };
|
| 109 |
+
//
|
| 110 |
+
// In this case, the necessary jet type is Jet<double, 5>. Here is a
|
| 111 |
+
// visualization of the jet objects in this case:
|
| 112 |
+
//
|
| 113 |
+
// Dual components for p ----+
|
| 114 |
+
// |
|
| 115 |
+
// -+-
|
| 116 |
+
// y [ * | 1 0 | 0 0 0 ] --- p[0]
|
| 117 |
+
// [ * | 0 1 | 0 0 0 ] --- p[1]
|
| 118 |
+
// [ * | . . | + + + ] |
|
| 119 |
+
// [ * | . . | + + + ] v
|
| 120 |
+
// [ * | . . | + + + ] <--- F(p, q)
|
| 121 |
+
// [ * | . . | + + + ] ^
|
| 122 |
+
// ^^^ ^^^^^ |
|
| 123 |
+
// dy/dp dy/dq [ * | 0 0 | 1 0 0 ] --- q[0]
|
| 124 |
+
// [ * | 0 0 | 0 1 0 ] --- q[1]
|
| 125 |
+
// [ * | 0 0 | 0 0 1 ] --- q[2]
|
| 126 |
+
// --+--
|
| 127 |
+
// |
|
| 128 |
+
// Dual components for q --------------+
|
| 129 |
+
//
|
| 130 |
+
// where the 4x2 submatrix (marked with ".") and 4x3 submatrix (marked with "+"
|
| 131 |
+
// of y in the above diagram are the derivatives of y with respect to p and q
|
| 132 |
+
// respectively. This is how autodiff works for functors taking multiple vector
|
| 133 |
+
// valued arguments (up to 6).
|
| 134 |
+
//
|
| 135 |
+
// Jacobian null pointers (nullptr)
|
| 136 |
+
// --------------------------------
|
| 137 |
+
// In general, the functions below will accept nullptr for all or some of the
|
| 138 |
+
// Jacobian parameters, meaning that those Jacobians will not be computed.
|
| 139 |
+
|
| 140 |
+
#ifndef CERES_PUBLIC_INTERNAL_AUTODIFF_H_
|
| 141 |
+
#define CERES_PUBLIC_INTERNAL_AUTODIFF_H_
|
| 142 |
+
|
| 143 |
+
#include <array>
|
| 144 |
+
#include <cstddef>
|
| 145 |
+
#include <utility>
|
| 146 |
+
|
| 147 |
+
#include "ceres/internal/array_selector.h"
|
| 148 |
+
#include "ceres/internal/eigen.h"
|
| 149 |
+
#include "ceres/internal/fixed_array.h"
|
| 150 |
+
#include "ceres/internal/parameter_dims.h"
|
| 151 |
+
#include "ceres/internal/variadic_evaluate.h"
|
| 152 |
+
#include "ceres/jet.h"
|
| 153 |
+
#include "ceres/types.h"
|
| 154 |
+
#include "glog/logging.h"
|
| 155 |
+
|
| 156 |
+
// If the number of parameters exceeds this values, the corresponding jets are
|
| 157 |
+
// placed on the heap. This will reduce performance by a factor of 2-5 on
|
| 158 |
+
// current compilers.
|
| 159 |
+
#ifndef CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK
|
| 160 |
+
#define CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK 50
|
| 161 |
+
#endif
|
| 162 |
+
|
| 163 |
+
#ifndef CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK
|
| 164 |
+
#define CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK 20
|
| 165 |
+
#endif
|
| 166 |
+
|
| 167 |
+
namespace ceres {
|
| 168 |
+
namespace internal {
|
| 169 |
+
|
| 170 |
+
// Extends src by a 1st order perturbation for every dimension and puts it in
|
| 171 |
+
// dst. The size of src is N. Since this is also used for perturbations in
|
| 172 |
+
// blocked arrays, offset is used to shift which part of the jet the
|
| 173 |
+
// perturbation occurs. This is used to set up the extended x augmented by an
|
| 174 |
+
// identity matrix. The JetT type should be a Jet type, and T should be a
|
| 175 |
+
// numeric type (e.g. double). For example,
|
| 176 |
+
//
|
| 177 |
+
// 0 1 2 3 4 5 6 7 8
|
| 178 |
+
// dst[0] [ * | . . | 1 0 0 | . . . ]
|
| 179 |
+
// dst[1] [ * | . . | 0 1 0 | . . . ]
|
| 180 |
+
// dst[2] [ * | . . | 0 0 1 | . . . ]
|
| 181 |
+
//
|
| 182 |
+
// is what would get put in dst if N was 3, offset was 3, and the jet type JetT
|
| 183 |
+
// was 8-dimensional.
|
| 184 |
+
template <int j, int N, int Offset, typename T, typename JetT>
|
| 185 |
+
struct Make1stOrderPerturbation {
|
| 186 |
+
public:
|
| 187 |
+
inline static void Apply(const T* src, JetT* dst) {
|
| 188 |
+
if (j == 0) {
|
| 189 |
+
DCHECK(src);
|
| 190 |
+
DCHECK(dst);
|
| 191 |
+
}
|
| 192 |
+
dst[j] = JetT(src[j], j + Offset);
|
| 193 |
+
Make1stOrderPerturbation<j + 1, N, Offset, T, JetT>::Apply(src, dst);
|
| 194 |
+
}
|
| 195 |
+
};
|
| 196 |
+
|
| 197 |
+
template <int N, int Offset, typename T, typename JetT>
|
| 198 |
+
struct Make1stOrderPerturbation<N, N, Offset, T, JetT> {
|
| 199 |
+
public:
|
| 200 |
+
static void Apply(const T* /* NOT USED */, JetT* /* NOT USED */) {}
|
| 201 |
+
};
|
| 202 |
+
|
| 203 |
+
// Calls Make1stOrderPerturbation for every parameter block.
|
| 204 |
+
//
|
| 205 |
+
// Example:
|
| 206 |
+
// If one having three parameter blocks with dimensions (3, 2, 4), the call
|
| 207 |
+
// Make1stOrderPerturbations<integer_sequence<3, 2, 4>::Apply(params, x);
|
| 208 |
+
// will result in the following calls to Make1stOrderPerturbation:
|
| 209 |
+
// Make1stOrderPerturbation<0, 3, 0>::Apply(params[0], x + 0);
|
| 210 |
+
// Make1stOrderPerturbation<0, 2, 3>::Apply(params[1], x + 3);
|
| 211 |
+
// Make1stOrderPerturbation<0, 4, 5>::Apply(params[2], x + 5);
|
| 212 |
+
template <typename Seq, int ParameterIdx = 0, int Offset = 0>
|
| 213 |
+
struct Make1stOrderPerturbations;
|
| 214 |
+
|
| 215 |
+
template <int N, int... Ns, int ParameterIdx, int Offset>
|
| 216 |
+
struct Make1stOrderPerturbations<std::integer_sequence<int, N, Ns...>,
|
| 217 |
+
ParameterIdx,
|
| 218 |
+
Offset> {
|
| 219 |
+
template <typename T, typename JetT>
|
| 220 |
+
inline static void Apply(T const* const* parameters, JetT* x) {
|
| 221 |
+
Make1stOrderPerturbation<0, N, Offset, T, JetT>::Apply(
|
| 222 |
+
parameters[ParameterIdx], x + Offset);
|
| 223 |
+
Make1stOrderPerturbations<std::integer_sequence<int, Ns...>,
|
| 224 |
+
ParameterIdx + 1,
|
| 225 |
+
Offset + N>::Apply(parameters, x);
|
| 226 |
+
}
|
| 227 |
+
};
|
| 228 |
+
|
| 229 |
+
// End of 'recursion'. Nothing more to do.
|
| 230 |
+
template <int ParameterIdx, int Total>
|
| 231 |
+
struct Make1stOrderPerturbations<std::integer_sequence<int>,
|
| 232 |
+
ParameterIdx,
|
| 233 |
+
Total> {
|
| 234 |
+
template <typename T, typename JetT>
|
| 235 |
+
static void Apply(T const* const* /* NOT USED */, JetT* /* NOT USED */) {}
|
| 236 |
+
};
|
| 237 |
+
|
| 238 |
+
// Takes the 0th order part of src, assumed to be a Jet type, and puts it in
|
| 239 |
+
// dst. This is used to pick out the "vector" part of the extended y.
|
| 240 |
+
template <typename JetT, typename T>
|
| 241 |
+
inline void Take0thOrderPart(int M, const JetT* src, T dst) {
|
| 242 |
+
DCHECK(src);
|
| 243 |
+
for (int i = 0; i < M; ++i) {
|
| 244 |
+
dst[i] = src[i].a;
|
| 245 |
+
}
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
// Takes N 1st order parts, starting at index N0, and puts them in the M x N
|
| 249 |
+
// matrix 'dst'. This is used to pick out the "matrix" parts of the extended y.
|
| 250 |
+
template <int N0, int N, typename JetT, typename T>
|
| 251 |
+
inline void Take1stOrderPart(const int M, const JetT* src, T* dst) {
|
| 252 |
+
DCHECK(src);
|
| 253 |
+
DCHECK(dst);
|
| 254 |
+
for (int i = 0; i < M; ++i) {
|
| 255 |
+
Eigen::Map<Eigen::Matrix<T, N, 1>>(dst + N * i, N) =
|
| 256 |
+
src[i].v.template segment<N>(N0);
|
| 257 |
+
}
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
// Calls Take1stOrderPart for every parameter block.
|
| 261 |
+
//
|
| 262 |
+
// Example:
|
| 263 |
+
// If one having three parameter blocks with dimensions (3, 2, 4), the call
|
| 264 |
+
// Take1stOrderParts<integer_sequence<3, 2, 4>::Apply(num_outputs,
|
| 265 |
+
// output,
|
| 266 |
+
// jacobians);
|
| 267 |
+
// will result in the following calls to Take1stOrderPart:
|
| 268 |
+
// if (jacobians[0]) {
|
| 269 |
+
// Take1stOrderPart<0, 3>(num_outputs, output, jacobians[0]);
|
| 270 |
+
// }
|
| 271 |
+
// if (jacobians[1]) {
|
| 272 |
+
// Take1stOrderPart<3, 2>(num_outputs, output, jacobians[1]);
|
| 273 |
+
// }
|
| 274 |
+
// if (jacobians[2]) {
|
| 275 |
+
// Take1stOrderPart<5, 4>(num_outputs, output, jacobians[2]);
|
| 276 |
+
// }
|
| 277 |
+
template <typename Seq, int ParameterIdx = 0, int Offset = 0>
|
| 278 |
+
struct Take1stOrderParts;
|
| 279 |
+
|
| 280 |
+
template <int N, int... Ns, int ParameterIdx, int Offset>
|
| 281 |
+
struct Take1stOrderParts<std::integer_sequence<int, N, Ns...>,
|
| 282 |
+
ParameterIdx,
|
| 283 |
+
Offset> {
|
| 284 |
+
template <typename JetT, typename T>
|
| 285 |
+
inline static void Apply(int num_outputs, JetT* output, T** jacobians) {
|
| 286 |
+
if (jacobians[ParameterIdx]) {
|
| 287 |
+
Take1stOrderPart<Offset, N>(num_outputs, output, jacobians[ParameterIdx]);
|
| 288 |
+
}
|
| 289 |
+
Take1stOrderParts<std::integer_sequence<int, Ns...>,
|
| 290 |
+
ParameterIdx + 1,
|
| 291 |
+
Offset + N>::Apply(num_outputs, output, jacobians);
|
| 292 |
+
}
|
| 293 |
+
};
|
| 294 |
+
|
| 295 |
+
// End of 'recursion'. Nothing more to do.
|
| 296 |
+
template <int ParameterIdx, int Offset>
|
| 297 |
+
struct Take1stOrderParts<std::integer_sequence<int>, ParameterIdx, Offset> {
|
| 298 |
+
template <typename T, typename JetT>
|
| 299 |
+
static void Apply(int /* NOT USED*/,
|
| 300 |
+
JetT* /* NOT USED*/,
|
| 301 |
+
T** /* NOT USED */) {}
|
| 302 |
+
};
|
| 303 |
+
|
| 304 |
+
template <int kNumResiduals,
|
| 305 |
+
typename ParameterDims,
|
| 306 |
+
typename Functor,
|
| 307 |
+
typename T>
|
| 308 |
+
inline bool AutoDifferentiate(const Functor& functor,
|
| 309 |
+
T const* const* parameters,
|
| 310 |
+
int dynamic_num_outputs,
|
| 311 |
+
T* function_value,
|
| 312 |
+
T** jacobians) {
|
| 313 |
+
using JetT = Jet<T, ParameterDims::kNumParameters>;
|
| 314 |
+
using Parameters = typename ParameterDims::Parameters;
|
| 315 |
+
|
| 316 |
+
if (kNumResiduals != DYNAMIC) {
|
| 317 |
+
DCHECK_EQ(kNumResiduals, dynamic_num_outputs);
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
ArraySelector<JetT,
|
| 321 |
+
ParameterDims::kNumParameters,
|
| 322 |
+
CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK>
|
| 323 |
+
parameters_as_jets(ParameterDims::kNumParameters);
|
| 324 |
+
|
| 325 |
+
// Pointers to the beginning of each parameter block
|
| 326 |
+
std::array<JetT*, ParameterDims::kNumParameterBlocks> unpacked_parameters =
|
| 327 |
+
ParameterDims::GetUnpackedParameters(parameters_as_jets.data());
|
| 328 |
+
|
| 329 |
+
// If the number of residuals is fixed, we use the template argument as the
|
| 330 |
+
// number of outputs. Otherwise we use the num_outputs parameter. Note: The
|
| 331 |
+
// ?-operator here is compile-time evaluated, therefore num_outputs is also
|
| 332 |
+
// a compile-time constant for functors with fixed residuals.
|
| 333 |
+
const int num_outputs =
|
| 334 |
+
kNumResiduals == DYNAMIC ? dynamic_num_outputs : kNumResiduals;
|
| 335 |
+
DCHECK_GT(num_outputs, 0);
|
| 336 |
+
|
| 337 |
+
ArraySelector<JetT, kNumResiduals, CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK>
|
| 338 |
+
residuals_as_jets(num_outputs);
|
| 339 |
+
|
| 340 |
+
// Invalidate the output Jets, so that we can detect if the user
|
| 341 |
+
// did not assign values to all of them.
|
| 342 |
+
for (int i = 0; i < num_outputs; ++i) {
|
| 343 |
+
residuals_as_jets[i].a = kImpossibleValue;
|
| 344 |
+
residuals_as_jets[i].v.setConstant(kImpossibleValue);
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
Make1stOrderPerturbations<Parameters>::Apply(parameters,
|
| 348 |
+
parameters_as_jets.data());
|
| 349 |
+
|
| 350 |
+
if (!VariadicEvaluate<ParameterDims>(
|
| 351 |
+
functor, unpacked_parameters.data(), residuals_as_jets.data())) {
|
| 352 |
+
return false;
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
Take0thOrderPart(num_outputs, residuals_as_jets.data(), function_value);
|
| 356 |
+
Take1stOrderParts<Parameters>::Apply(
|
| 357 |
+
num_outputs, residuals_as_jets.data(), jacobians);
|
| 358 |
+
|
| 359 |
+
return true;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
} // namespace internal
|
| 363 |
+
} // namespace ceres
|
| 364 |
+
|
| 365 |
+
#endif // CERES_PUBLIC_INTERNAL_AUTODIFF_H_
|
ceres-v2/include/internal/config.h
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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: alexs.mac@gmail.com (Alex Stewart)
|
| 30 |
+
|
| 31 |
+
// Configuration options for Ceres.
|
| 32 |
+
//
|
| 33 |
+
// Do not edit this file, it was automatically configured by CMake when
|
| 34 |
+
// Ceres was compiled with the relevant configuration for the machine
|
| 35 |
+
// on which Ceres was compiled.
|
| 36 |
+
//
|
| 37 |
+
// Ceres Developers: All options should have the same name as their mapped
|
| 38 |
+
// CMake options, in the preconfigured version of this file
|
| 39 |
+
// all options should be enclosed in '@'.
|
| 40 |
+
|
| 41 |
+
#ifndef CERES_PUBLIC_INTERNAL_CONFIG_H_
|
| 42 |
+
#define CERES_PUBLIC_INTERNAL_CONFIG_H_
|
| 43 |
+
|
| 44 |
+
// If defined, use the LGPL code in Eigen.
|
| 45 |
+
#define CERES_USE_EIGEN_SPARSE
|
| 46 |
+
|
| 47 |
+
// If defined, Ceres was compiled without LAPACK.
|
| 48 |
+
// #define CERES_NO_LAPACK
|
| 49 |
+
|
| 50 |
+
// If defined, Ceres was compiled without SuiteSparse.
|
| 51 |
+
// #define CERES_NO_SUITESPARSE
|
| 52 |
+
|
| 53 |
+
// If defined, Ceres was compiled without CXSparse.
|
| 54 |
+
// #define CERES_NO_CXSPARSE
|
| 55 |
+
|
| 56 |
+
// If defined, Ceres was compiled without CUDA.
|
| 57 |
+
// #define CERES_NO_CUDA
|
| 58 |
+
|
| 59 |
+
// If defined, Ceres was compiled without Apple's Accelerate framework solvers.
|
| 60 |
+
#define CERES_NO_ACCELERATE_SPARSE
|
| 61 |
+
|
| 62 |
+
#if defined(CERES_NO_SUITESPARSE) && \
|
| 63 |
+
defined(CERES_NO_ACCELERATE_SPARSE) && \
|
| 64 |
+
defined(CERES_NO_CXSPARSE) && \
|
| 65 |
+
!defined(CERES_USE_EIGEN_SPARSE) // NOLINT
|
| 66 |
+
// If defined Ceres was compiled without any sparse linear algebra support.
|
| 67 |
+
#define CERES_NO_SPARSE
|
| 68 |
+
#endif
|
| 69 |
+
|
| 70 |
+
// If defined, Ceres was compiled without Schur specializations.
|
| 71 |
+
// #define CERES_RESTRICT_SCHUR_SPECIALIZATION
|
| 72 |
+
|
| 73 |
+
// If defined, Ceres was compiled to use Eigen instead of hardcoded BLAS
|
| 74 |
+
// routines.
|
| 75 |
+
// #define CERES_NO_CUSTOM_BLAS
|
| 76 |
+
|
| 77 |
+
// If defined, Ceres was compiled without multithreading support.
|
| 78 |
+
// #define CERES_NO_THREADS
|
| 79 |
+
// If defined Ceres was compiled with OpenMP multithreading.
|
| 80 |
+
// #define CERES_USE_OPENMP
|
| 81 |
+
// If defined Ceres was compiled with modern C++ multithreading.
|
| 82 |
+
#define CERES_USE_CXX_THREADS
|
| 83 |
+
|
| 84 |
+
// If defined, Ceres was compiled with a version MSVC >= 2005 which
|
| 85 |
+
// deprecated the standard POSIX names for bessel functions, replacing them
|
| 86 |
+
// with underscore prefixed versions (e.g. j0() -> _j0()).
|
| 87 |
+
// #define CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS
|
| 88 |
+
|
| 89 |
+
#if defined(CERES_USE_OPENMP)
|
| 90 |
+
#if defined(CERES_USE_CXX_THREADS) || defined(CERES_NO_THREADS)
|
| 91 |
+
#error CERES_USE_OPENMP is mutually exclusive to CERES_USE_CXX_THREADS and CERES_NO_THREADS
|
| 92 |
+
#endif
|
| 93 |
+
#elif defined(CERES_USE_CXX_THREADS)
|
| 94 |
+
#if defined(CERES_USE_OPENMP) || defined(CERES_NO_THREADS)
|
| 95 |
+
#error CERES_USE_CXX_THREADS is mutually exclusive to CERES_USE_OPENMP, CERES_USE_CXX_THREADS and CERES_NO_THREADS
|
| 96 |
+
#endif
|
| 97 |
+
#elif defined(CERES_NO_THREADS)
|
| 98 |
+
#if defined(CERES_USE_OPENMP) || defined(CERES_USE_CXX_THREADS)
|
| 99 |
+
#error CERES_NO_THREADS is mutually exclusive to CERES_USE_OPENMP and CERES_USE_CXX_THREADS
|
| 100 |
+
#endif
|
| 101 |
+
#else
|
| 102 |
+
# error One of CERES_USE_OPENMP, CERES_USE_CXX_THREADS or CERES_NO_THREADS must be defined.
|
| 103 |
+
#endif
|
| 104 |
+
|
| 105 |
+
// CERES_NO_SPARSE should be automatically defined by config.h if Ceres was
|
| 106 |
+
// compiled without any sparse back-end. Verify that it has not subsequently
|
| 107 |
+
// been inconsistently redefined.
|
| 108 |
+
#if defined(CERES_NO_SPARSE)
|
| 109 |
+
#if !defined(CERES_NO_SUITESPARSE)
|
| 110 |
+
#error CERES_NO_SPARSE requires CERES_NO_SUITESPARSE.
|
| 111 |
+
#endif
|
| 112 |
+
#if !defined(CERES_NO_CXSPARSE)
|
| 113 |
+
#error CERES_NO_SPARSE requires CERES_NO_CXSPARSE
|
| 114 |
+
#endif
|
| 115 |
+
#if !defined(CERES_NO_ACCELERATE_SPARSE)
|
| 116 |
+
#error CERES_NO_SPARSE requires CERES_NO_ACCELERATE_SPARSE
|
| 117 |
+
#endif
|
| 118 |
+
#if defined(CERES_USE_EIGEN_SPARSE)
|
| 119 |
+
#error CERES_NO_SPARSE requires !CERES_USE_EIGEN_SPARSE
|
| 120 |
+
#endif
|
| 121 |
+
#endif
|
| 122 |
+
|
| 123 |
+
#endif // CERES_PUBLIC_INTERNAL_CONFIG_H_
|
ceres-v2/include/internal/disable_warnings.h
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2015 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 |
+
// This file has the sole purpose to silence warnings when including Ceres.
|
| 30 |
+
|
| 31 |
+
// This is not your usual header guard. The macro CERES_WARNINGS_DISABLED
|
| 32 |
+
// shows up again in reenable_warnings.h.
|
| 33 |
+
#ifndef CERES_WARNINGS_DISABLED
|
| 34 |
+
#define CERES_WARNINGS_DISABLED
|
| 35 |
+
|
| 36 |
+
#ifdef _MSC_VER
|
| 37 |
+
#pragma warning(push)
|
| 38 |
+
// Disable the warning C4251 which is triggered by stl classes in
|
| 39 |
+
// Ceres' public interface. To quote MSDN: "C4251 can be ignored "
|
| 40 |
+
// "if you are deriving from a type in the Standard C++ Library"
|
| 41 |
+
#pragma warning(disable : 4251)
|
| 42 |
+
#endif
|
| 43 |
+
|
| 44 |
+
#endif // CERES_WARNINGS_DISABLED
|
ceres-v2/include/internal/eigen.h
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2015 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 |
+
|
| 31 |
+
#ifndef CERES_INTERNAL_EIGEN_H_
|
| 32 |
+
#define CERES_INTERNAL_EIGEN_H_
|
| 33 |
+
|
| 34 |
+
#include "Eigen/Core"
|
| 35 |
+
|
| 36 |
+
namespace ceres {
|
| 37 |
+
|
| 38 |
+
using Vector = Eigen::Matrix<double, Eigen::Dynamic, 1>;
|
| 39 |
+
using Matrix =
|
| 40 |
+
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
|
| 41 |
+
using VectorRef = Eigen::Map<Vector>;
|
| 42 |
+
using MatrixRef = Eigen::Map<Matrix>;
|
| 43 |
+
using ConstVectorRef = Eigen::Map<const Vector>;
|
| 44 |
+
using ConstMatrixRef = Eigen::Map<const Matrix>;
|
| 45 |
+
|
| 46 |
+
// Column major matrices for DenseSparseMatrix/DenseQRSolver
|
| 47 |
+
using ColMajorMatrix =
|
| 48 |
+
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
|
| 49 |
+
|
| 50 |
+
using ColMajorMatrixRef =
|
| 51 |
+
Eigen::Map<ColMajorMatrix, 0, Eigen::Stride<Eigen::Dynamic, 1>>;
|
| 52 |
+
|
| 53 |
+
using ConstColMajorMatrixRef =
|
| 54 |
+
Eigen::Map<const ColMajorMatrix, 0, Eigen::Stride<Eigen::Dynamic, 1>>;
|
| 55 |
+
|
| 56 |
+
// C++ does not support templated typdefs, thus the need for this
|
| 57 |
+
// struct so that we can support statically sized Matrix and Maps.
|
| 58 |
+
template <int num_rows = Eigen::Dynamic, int num_cols = Eigen::Dynamic>
|
| 59 |
+
struct EigenTypes {
|
| 60 |
+
using Matrix =
|
| 61 |
+
Eigen::Matrix<double,
|
| 62 |
+
num_rows,
|
| 63 |
+
num_cols,
|
| 64 |
+
num_cols == 1 ? Eigen::ColMajor : Eigen::RowMajor>;
|
| 65 |
+
|
| 66 |
+
using MatrixRef = Eigen::Map<Matrix>;
|
| 67 |
+
using ConstMatrixRef = Eigen::Map<const Matrix>;
|
| 68 |
+
using Vector = Eigen::Matrix<double, num_rows, 1>;
|
| 69 |
+
using VectorRef = Eigen::Map<Eigen::Matrix<double, num_rows, 1>>;
|
| 70 |
+
using ConstVectorRef = Eigen::Map<const Eigen::Matrix<double, num_rows, 1>>;
|
| 71 |
+
};
|
| 72 |
+
|
| 73 |
+
} // namespace ceres
|
| 74 |
+
|
| 75 |
+
#endif // CERES_INTERNAL_EIGEN_H_
|
ceres-v2/include/internal/export.h
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
#ifndef CERES_EXPORT_H
|
| 3 |
+
#define CERES_EXPORT_H
|
| 4 |
+
|
| 5 |
+
#ifdef CERES_STATIC_DEFINE
|
| 6 |
+
# define CERES_EXPORT
|
| 7 |
+
# define CERES_NO_EXPORT
|
| 8 |
+
#else
|
| 9 |
+
# ifndef CERES_EXPORT
|
| 10 |
+
# ifdef ceres_EXPORTS
|
| 11 |
+
/* We are building this library */
|
| 12 |
+
# define CERES_EXPORT
|
| 13 |
+
# else
|
| 14 |
+
/* We are using this library */
|
| 15 |
+
# define CERES_EXPORT
|
| 16 |
+
# endif
|
| 17 |
+
# endif
|
| 18 |
+
|
| 19 |
+
# ifndef CERES_NO_EXPORT
|
| 20 |
+
# define CERES_NO_EXPORT
|
| 21 |
+
# endif
|
| 22 |
+
#endif
|
| 23 |
+
|
| 24 |
+
#ifndef CERES_DEPRECATED
|
| 25 |
+
# define CERES_DEPRECATED __attribute__ ((__deprecated__))
|
| 26 |
+
#endif
|
| 27 |
+
|
| 28 |
+
#ifndef CERES_DEPRECATED_EXPORT
|
| 29 |
+
# define CERES_DEPRECATED_EXPORT CERES_EXPORT CERES_DEPRECATED
|
| 30 |
+
#endif
|
| 31 |
+
|
| 32 |
+
#ifndef CERES_DEPRECATED_NO_EXPORT
|
| 33 |
+
# define CERES_DEPRECATED_NO_EXPORT CERES_NO_EXPORT CERES_DEPRECATED
|
| 34 |
+
#endif
|
| 35 |
+
|
| 36 |
+
#if 0 /* DEFINE_NO_DEPRECATED */
|
| 37 |
+
# ifndef CERES_NO_DEPRECATED
|
| 38 |
+
# define CERES_NO_DEPRECATED
|
| 39 |
+
# endif
|
| 40 |
+
#endif
|
| 41 |
+
|
| 42 |
+
#endif /* CERES_EXPORT_H */
|
ceres-v2/include/internal/fixed_array.h
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright 2018 The Abseil Authors.
|
| 2 |
+
//
|
| 3 |
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
// you may not use this file except in compliance with the License.
|
| 5 |
+
// You may obtain a copy of the License at
|
| 6 |
+
//
|
| 7 |
+
// https://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
//
|
| 9 |
+
// Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
// See the License for the specific language governing permissions and
|
| 13 |
+
// limitations under the License.
|
| 14 |
+
//
|
| 15 |
+
// -----------------------------------------------------------------------------
|
| 16 |
+
// File: fixed_array.h
|
| 17 |
+
// -----------------------------------------------------------------------------
|
| 18 |
+
//
|
| 19 |
+
// A `FixedArray<T>` represents a non-resizable array of `T` where the length of
|
| 20 |
+
// the array can be determined at run-time. It is a good replacement for
|
| 21 |
+
// non-standard and deprecated uses of `alloca()` and variable length arrays
|
| 22 |
+
// within the GCC extension. (See
|
| 23 |
+
// https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html).
|
| 24 |
+
//
|
| 25 |
+
// `FixedArray` allocates small arrays inline, keeping performance fast by
|
| 26 |
+
// avoiding heap operations. It also helps reduce the chances of
|
| 27 |
+
// accidentally overflowing your stack if large input is passed to
|
| 28 |
+
// your function.
|
| 29 |
+
|
| 30 |
+
#ifndef CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
|
| 31 |
+
#define CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
|
| 32 |
+
|
| 33 |
+
#include <Eigen/Core> // For Eigen::aligned_allocator
|
| 34 |
+
#include <algorithm>
|
| 35 |
+
#include <array>
|
| 36 |
+
#include <cstddef>
|
| 37 |
+
#include <memory>
|
| 38 |
+
#include <tuple>
|
| 39 |
+
#include <type_traits>
|
| 40 |
+
|
| 41 |
+
#include "ceres/internal/memory.h"
|
| 42 |
+
#include "glog/logging.h"
|
| 43 |
+
|
| 44 |
+
namespace ceres {
|
| 45 |
+
namespace internal {
|
| 46 |
+
|
| 47 |
+
constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
|
| 48 |
+
|
| 49 |
+
// The default fixed array allocator.
|
| 50 |
+
//
|
| 51 |
+
// As one can not easily detect if a struct contains or inherits from a fixed
|
| 52 |
+
// size Eigen type, to be safe the Eigen::aligned_allocator is used by default.
|
| 53 |
+
// But trivial types can never contain Eigen types, so std::allocator is used to
|
| 54 |
+
// safe some heap memory.
|
| 55 |
+
template <typename T>
|
| 56 |
+
using FixedArrayDefaultAllocator =
|
| 57 |
+
typename std::conditional<std::is_trivial<T>::value,
|
| 58 |
+
std::allocator<T>,
|
| 59 |
+
Eigen::aligned_allocator<T>>::type;
|
| 60 |
+
|
| 61 |
+
// -----------------------------------------------------------------------------
|
| 62 |
+
// FixedArray
|
| 63 |
+
// -----------------------------------------------------------------------------
|
| 64 |
+
//
|
| 65 |
+
// A `FixedArray` provides a run-time fixed-size array, allocating a small array
|
| 66 |
+
// inline for efficiency.
|
| 67 |
+
//
|
| 68 |
+
// Most users should not specify an `inline_elements` argument and let
|
| 69 |
+
// `FixedArray` automatically determine the number of elements
|
| 70 |
+
// to store inline based on `sizeof(T)`. If `inline_elements` is specified, the
|
| 71 |
+
// `FixedArray` implementation will use inline storage for arrays with a
|
| 72 |
+
// length <= `inline_elements`.
|
| 73 |
+
//
|
| 74 |
+
// Note that a `FixedArray` constructed with a `size_type` argument will
|
| 75 |
+
// default-initialize its values by leaving trivially constructible types
|
| 76 |
+
// uninitialized (e.g. int, int[4], double), and others default-constructed.
|
| 77 |
+
// This matches the behavior of c-style arrays and `std::array`, but not
|
| 78 |
+
// `std::vector`.
|
| 79 |
+
//
|
| 80 |
+
// Note that `FixedArray` does not provide a public allocator; if it requires a
|
| 81 |
+
// heap allocation, it will do so with global `::operator new[]()` and
|
| 82 |
+
// `::operator delete[]()`, even if T provides class-scope overrides for these
|
| 83 |
+
// operators.
|
| 84 |
+
template <typename T,
|
| 85 |
+
size_t N = kFixedArrayUseDefault,
|
| 86 |
+
typename A = FixedArrayDefaultAllocator<T>>
|
| 87 |
+
class FixedArray {
|
| 88 |
+
static_assert(!std::is_array<T>::value || std::extent<T>::value > 0,
|
| 89 |
+
"Arrays with unknown bounds cannot be used with FixedArray.");
|
| 90 |
+
|
| 91 |
+
static constexpr size_t kInlineBytesDefault = 256;
|
| 92 |
+
|
| 93 |
+
using AllocatorTraits = std::allocator_traits<A>;
|
| 94 |
+
// std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17,
|
| 95 |
+
// but this seems to be mostly pedantic.
|
| 96 |
+
template <typename Iterator>
|
| 97 |
+
using EnableIfForwardIterator = typename std::enable_if<std::is_convertible<
|
| 98 |
+
typename std::iterator_traits<Iterator>::iterator_category,
|
| 99 |
+
std::forward_iterator_tag>::value>::type;
|
| 100 |
+
static constexpr bool DefaultConstructorIsNonTrivial() {
|
| 101 |
+
return !std::is_trivially_default_constructible<StorageElement>::value;
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
public:
|
| 105 |
+
using allocator_type = typename AllocatorTraits::allocator_type;
|
| 106 |
+
using value_type = typename AllocatorTraits::value_type;
|
| 107 |
+
using pointer = typename AllocatorTraits::pointer;
|
| 108 |
+
using const_pointer = typename AllocatorTraits::const_pointer;
|
| 109 |
+
using reference = value_type&;
|
| 110 |
+
using const_reference = const value_type&;
|
| 111 |
+
using size_type = typename AllocatorTraits::size_type;
|
| 112 |
+
using difference_type = typename AllocatorTraits::difference_type;
|
| 113 |
+
using iterator = pointer;
|
| 114 |
+
using const_iterator = const_pointer;
|
| 115 |
+
using reverse_iterator = std::reverse_iterator<iterator>;
|
| 116 |
+
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
| 117 |
+
|
| 118 |
+
static constexpr size_type inline_elements =
|
| 119 |
+
(N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type)
|
| 120 |
+
: static_cast<size_type>(N));
|
| 121 |
+
|
| 122 |
+
FixedArray(const FixedArray& other,
|
| 123 |
+
const allocator_type& a = allocator_type())
|
| 124 |
+
: FixedArray(other.begin(), other.end(), a) {}
|
| 125 |
+
|
| 126 |
+
FixedArray(FixedArray&& other, const allocator_type& a = allocator_type())
|
| 127 |
+
: FixedArray(std::make_move_iterator(other.begin()),
|
| 128 |
+
std::make_move_iterator(other.end()),
|
| 129 |
+
a) {}
|
| 130 |
+
|
| 131 |
+
// Creates an array object that can store `n` elements.
|
| 132 |
+
// Note that trivially constructible elements will be uninitialized.
|
| 133 |
+
explicit FixedArray(size_type n, const allocator_type& a = allocator_type())
|
| 134 |
+
: storage_(n, a) {
|
| 135 |
+
if (DefaultConstructorIsNonTrivial()) {
|
| 136 |
+
ConstructRange(storage_.alloc(), storage_.begin(), storage_.end());
|
| 137 |
+
}
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
// Creates an array initialized with `n` copies of `val`.
|
| 141 |
+
FixedArray(size_type n,
|
| 142 |
+
const value_type& val,
|
| 143 |
+
const allocator_type& a = allocator_type())
|
| 144 |
+
: storage_(n, a) {
|
| 145 |
+
ConstructRange(storage_.alloc(), storage_.begin(), storage_.end(), val);
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
// Creates an array initialized with the size and contents of `init_list`.
|
| 149 |
+
FixedArray(std::initializer_list<value_type> init_list,
|
| 150 |
+
const allocator_type& a = allocator_type())
|
| 151 |
+
: FixedArray(init_list.begin(), init_list.end(), a) {}
|
| 152 |
+
|
| 153 |
+
// Creates an array initialized with the elements from the input
|
| 154 |
+
// range. The array's size will always be `std::distance(first, last)`.
|
| 155 |
+
// REQUIRES: Iterator must be a forward_iterator or better.
|
| 156 |
+
template <typename Iterator, EnableIfForwardIterator<Iterator>* = nullptr>
|
| 157 |
+
FixedArray(Iterator first,
|
| 158 |
+
Iterator last,
|
| 159 |
+
const allocator_type& a = allocator_type())
|
| 160 |
+
: storage_(std::distance(first, last), a) {
|
| 161 |
+
CopyRange(storage_.alloc(), storage_.begin(), first, last);
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
~FixedArray() noexcept {
|
| 165 |
+
for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) {
|
| 166 |
+
AllocatorTraits::destroy(storage_.alloc(), cur);
|
| 167 |
+
}
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
// Assignments are deleted because they break the invariant that the size of a
|
| 171 |
+
// `FixedArray` never changes.
|
| 172 |
+
void operator=(FixedArray&&) = delete;
|
| 173 |
+
void operator=(const FixedArray&) = delete;
|
| 174 |
+
|
| 175 |
+
// FixedArray::size()
|
| 176 |
+
//
|
| 177 |
+
// Returns the length of the fixed array.
|
| 178 |
+
size_type size() const { return storage_.size(); }
|
| 179 |
+
|
| 180 |
+
// FixedArray::max_size()
|
| 181 |
+
//
|
| 182 |
+
// Returns the largest possible value of `std::distance(begin(), end())` for a
|
| 183 |
+
// `FixedArray<T>`. This is equivalent to the most possible addressable bytes
|
| 184 |
+
// over the number of bytes taken by T.
|
| 185 |
+
constexpr size_type max_size() const {
|
| 186 |
+
return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
// FixedArray::empty()
|
| 190 |
+
//
|
| 191 |
+
// Returns whether or not the fixed array is empty.
|
| 192 |
+
bool empty() const { return size() == 0; }
|
| 193 |
+
|
| 194 |
+
// FixedArray::memsize()
|
| 195 |
+
//
|
| 196 |
+
// Returns the memory size of the fixed array in bytes.
|
| 197 |
+
size_t memsize() const { return size() * sizeof(value_type); }
|
| 198 |
+
|
| 199 |
+
// FixedArray::data()
|
| 200 |
+
//
|
| 201 |
+
// Returns a const T* pointer to elements of the `FixedArray`. This pointer
|
| 202 |
+
// can be used to access (but not modify) the contained elements.
|
| 203 |
+
const_pointer data() const { return AsValueType(storage_.begin()); }
|
| 204 |
+
|
| 205 |
+
// Overload of FixedArray::data() to return a T* pointer to elements of the
|
| 206 |
+
// fixed array. This pointer can be used to access and modify the contained
|
| 207 |
+
// elements.
|
| 208 |
+
pointer data() { return AsValueType(storage_.begin()); }
|
| 209 |
+
|
| 210 |
+
// FixedArray::operator[]
|
| 211 |
+
//
|
| 212 |
+
// Returns a reference the ith element of the fixed array.
|
| 213 |
+
// REQUIRES: 0 <= i < size()
|
| 214 |
+
reference operator[](size_type i) {
|
| 215 |
+
DCHECK_LT(i, size());
|
| 216 |
+
return data()[i];
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
// Overload of FixedArray::operator()[] to return a const reference to the
|
| 220 |
+
// ith element of the fixed array.
|
| 221 |
+
// REQUIRES: 0 <= i < size()
|
| 222 |
+
const_reference operator[](size_type i) const {
|
| 223 |
+
DCHECK_LT(i, size());
|
| 224 |
+
return data()[i];
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
// FixedArray::front()
|
| 228 |
+
//
|
| 229 |
+
// Returns a reference to the first element of the fixed array.
|
| 230 |
+
reference front() { return *begin(); }
|
| 231 |
+
|
| 232 |
+
// Overload of FixedArray::front() to return a reference to the first element
|
| 233 |
+
// of a fixed array of const values.
|
| 234 |
+
const_reference front() const { return *begin(); }
|
| 235 |
+
|
| 236 |
+
// FixedArray::back()
|
| 237 |
+
//
|
| 238 |
+
// Returns a reference to the last element of the fixed array.
|
| 239 |
+
reference back() { return *(end() - 1); }
|
| 240 |
+
|
| 241 |
+
// Overload of FixedArray::back() to return a reference to the last element
|
| 242 |
+
// of a fixed array of const values.
|
| 243 |
+
const_reference back() const { return *(end() - 1); }
|
| 244 |
+
|
| 245 |
+
// FixedArray::begin()
|
| 246 |
+
//
|
| 247 |
+
// Returns an iterator to the beginning of the fixed array.
|
| 248 |
+
iterator begin() { return data(); }
|
| 249 |
+
|
| 250 |
+
// Overload of FixedArray::begin() to return a const iterator to the
|
| 251 |
+
// beginning of the fixed array.
|
| 252 |
+
const_iterator begin() const { return data(); }
|
| 253 |
+
|
| 254 |
+
// FixedArray::cbegin()
|
| 255 |
+
//
|
| 256 |
+
// Returns a const iterator to the beginning of the fixed array.
|
| 257 |
+
const_iterator cbegin() const { return begin(); }
|
| 258 |
+
|
| 259 |
+
// FixedArray::end()
|
| 260 |
+
//
|
| 261 |
+
// Returns an iterator to the end of the fixed array.
|
| 262 |
+
iterator end() { return data() + size(); }
|
| 263 |
+
|
| 264 |
+
// Overload of FixedArray::end() to return a const iterator to the end of the
|
| 265 |
+
// fixed array.
|
| 266 |
+
const_iterator end() const { return data() + size(); }
|
| 267 |
+
|
| 268 |
+
// FixedArray::cend()
|
| 269 |
+
//
|
| 270 |
+
// Returns a const iterator to the end of the fixed array.
|
| 271 |
+
const_iterator cend() const { return end(); }
|
| 272 |
+
|
| 273 |
+
// FixedArray::rbegin()
|
| 274 |
+
//
|
| 275 |
+
// Returns a reverse iterator from the end of the fixed array.
|
| 276 |
+
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
| 277 |
+
|
| 278 |
+
// Overload of FixedArray::rbegin() to return a const reverse iterator from
|
| 279 |
+
// the end of the fixed array.
|
| 280 |
+
const_reverse_iterator rbegin() const {
|
| 281 |
+
return const_reverse_iterator(end());
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
// FixedArray::crbegin()
|
| 285 |
+
//
|
| 286 |
+
// Returns a const reverse iterator from the end of the fixed array.
|
| 287 |
+
const_reverse_iterator crbegin() const { return rbegin(); }
|
| 288 |
+
|
| 289 |
+
// FixedArray::rend()
|
| 290 |
+
//
|
| 291 |
+
// Returns a reverse iterator from the beginning of the fixed array.
|
| 292 |
+
reverse_iterator rend() { return reverse_iterator(begin()); }
|
| 293 |
+
|
| 294 |
+
// Overload of FixedArray::rend() for returning a const reverse iterator
|
| 295 |
+
// from the beginning of the fixed array.
|
| 296 |
+
const_reverse_iterator rend() const {
|
| 297 |
+
return const_reverse_iterator(begin());
|
| 298 |
+
}
|
| 299 |
+
|
| 300 |
+
// FixedArray::crend()
|
| 301 |
+
//
|
| 302 |
+
// Returns a reverse iterator from the beginning of the fixed array.
|
| 303 |
+
const_reverse_iterator crend() const { return rend(); }
|
| 304 |
+
|
| 305 |
+
// FixedArray::fill()
|
| 306 |
+
//
|
| 307 |
+
// Assigns the given `value` to all elements in the fixed array.
|
| 308 |
+
void fill(const value_type& val) { std::fill(begin(), end(), val); }
|
| 309 |
+
|
| 310 |
+
// Relational operators. Equality operators are elementwise using
|
| 311 |
+
// `operator==`, while order operators order FixedArrays lexicographically.
|
| 312 |
+
friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) {
|
| 313 |
+
return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) {
|
| 317 |
+
return !(lhs == rhs);
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
friend bool operator<(const FixedArray& lhs, const FixedArray& rhs) {
|
| 321 |
+
return std::lexicographical_compare(
|
| 322 |
+
lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
| 323 |
+
}
|
| 324 |
+
|
| 325 |
+
friend bool operator>(const FixedArray& lhs, const FixedArray& rhs) {
|
| 326 |
+
return rhs < lhs;
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
friend bool operator<=(const FixedArray& lhs, const FixedArray& rhs) {
|
| 330 |
+
return !(rhs < lhs);
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) {
|
| 334 |
+
return !(lhs < rhs);
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
private:
|
| 338 |
+
// StorageElement
|
| 339 |
+
//
|
| 340 |
+
// For FixedArrays with a C-style-array value_type, StorageElement is a POD
|
| 341 |
+
// wrapper struct called StorageElementWrapper that holds the value_type
|
| 342 |
+
// instance inside. This is needed for construction and destruction of the
|
| 343 |
+
// entire array regardless of how many dimensions it has. For all other cases,
|
| 344 |
+
// StorageElement is just an alias of value_type.
|
| 345 |
+
//
|
| 346 |
+
// Maintainer's Note: The simpler solution would be to simply wrap value_type
|
| 347 |
+
// in a struct whether it's an array or not. That causes some paranoid
|
| 348 |
+
// diagnostics to misfire, believing that 'data()' returns a pointer to a
|
| 349 |
+
// single element, rather than the packed array that it really is.
|
| 350 |
+
// e.g.:
|
| 351 |
+
//
|
| 352 |
+
// FixedArray<char> buf(1);
|
| 353 |
+
// sprintf(buf.data(), "foo");
|
| 354 |
+
//
|
| 355 |
+
// error: call to int __builtin___sprintf_chk(etc...)
|
| 356 |
+
// will always overflow destination buffer [-Werror]
|
| 357 |
+
//
|
| 358 |
+
template <typename OuterT,
|
| 359 |
+
typename InnerT = typename std::remove_extent<OuterT>::type,
|
| 360 |
+
size_t InnerN = std::extent<OuterT>::value>
|
| 361 |
+
struct StorageElementWrapper {
|
| 362 |
+
InnerT array[InnerN];
|
| 363 |
+
};
|
| 364 |
+
|
| 365 |
+
using StorageElement =
|
| 366 |
+
typename std::conditional<std::is_array<value_type>::value,
|
| 367 |
+
StorageElementWrapper<value_type>,
|
| 368 |
+
value_type>::type;
|
| 369 |
+
|
| 370 |
+
static pointer AsValueType(pointer ptr) { return ptr; }
|
| 371 |
+
static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
|
| 372 |
+
return std::addressof(ptr->array);
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
static_assert(sizeof(StorageElement) == sizeof(value_type), "");
|
| 376 |
+
static_assert(alignof(StorageElement) == alignof(value_type), "");
|
| 377 |
+
|
| 378 |
+
class NonEmptyInlinedStorage {
|
| 379 |
+
public:
|
| 380 |
+
StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }
|
| 381 |
+
void AnnotateConstruct(size_type) {}
|
| 382 |
+
void AnnotateDestruct(size_type) {}
|
| 383 |
+
|
| 384 |
+
// #ifdef ADDRESS_SANITIZER
|
| 385 |
+
// void* RedzoneBegin() { return &redzone_begin_; }
|
| 386 |
+
// void* RedzoneEnd() { return &redzone_end_ + 1; }
|
| 387 |
+
// #endif // ADDRESS_SANITIZER
|
| 388 |
+
|
| 389 |
+
private:
|
| 390 |
+
// ADDRESS_SANITIZER_REDZONE(redzone_begin_);
|
| 391 |
+
alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
|
| 392 |
+
// ADDRESS_SANITIZER_REDZONE(redzone_end_);
|
| 393 |
+
};
|
| 394 |
+
|
| 395 |
+
class EmptyInlinedStorage {
|
| 396 |
+
public:
|
| 397 |
+
StorageElement* data() { return nullptr; }
|
| 398 |
+
void AnnotateConstruct(size_type) {}
|
| 399 |
+
void AnnotateDestruct(size_type) {}
|
| 400 |
+
};
|
| 401 |
+
|
| 402 |
+
using InlinedStorage =
|
| 403 |
+
typename std::conditional<inline_elements == 0,
|
| 404 |
+
EmptyInlinedStorage,
|
| 405 |
+
NonEmptyInlinedStorage>::type;
|
| 406 |
+
|
| 407 |
+
// Storage
|
| 408 |
+
//
|
| 409 |
+
// An instance of Storage manages the inline and out-of-line memory for
|
| 410 |
+
// instances of FixedArray. This guarantees that even when construction of
|
| 411 |
+
// individual elements fails in the FixedArray constructor body, the
|
| 412 |
+
// destructor for Storage will still be called and out-of-line memory will be
|
| 413 |
+
// properly deallocated.
|
| 414 |
+
//
|
| 415 |
+
class Storage : public InlinedStorage {
|
| 416 |
+
public:
|
| 417 |
+
Storage(size_type n, const allocator_type& a)
|
| 418 |
+
: size_alloc_(n, a), data_(InitializeData()) {}
|
| 419 |
+
|
| 420 |
+
~Storage() noexcept {
|
| 421 |
+
if (UsingInlinedStorage(size())) {
|
| 422 |
+
InlinedStorage::AnnotateDestruct(size());
|
| 423 |
+
} else {
|
| 424 |
+
AllocatorTraits::deallocate(alloc(), AsValueType(begin()), size());
|
| 425 |
+
}
|
| 426 |
+
}
|
| 427 |
+
|
| 428 |
+
size_type size() const { return std::get<0>(size_alloc_); }
|
| 429 |
+
StorageElement* begin() const { return data_; }
|
| 430 |
+
StorageElement* end() const { return begin() + size(); }
|
| 431 |
+
allocator_type& alloc() { return std::get<1>(size_alloc_); }
|
| 432 |
+
|
| 433 |
+
private:
|
| 434 |
+
static bool UsingInlinedStorage(size_type n) {
|
| 435 |
+
return n <= inline_elements;
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
StorageElement* InitializeData() {
|
| 439 |
+
if (UsingInlinedStorage(size())) {
|
| 440 |
+
InlinedStorage::AnnotateConstruct(size());
|
| 441 |
+
return InlinedStorage::data();
|
| 442 |
+
} else {
|
| 443 |
+
return reinterpret_cast<StorageElement*>(
|
| 444 |
+
AllocatorTraits::allocate(alloc(), size()));
|
| 445 |
+
}
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
// Using std::tuple and not absl::CompressedTuple, as it has a lot of
|
| 449 |
+
// dependencies to other absl headers.
|
| 450 |
+
std::tuple<size_type, allocator_type> size_alloc_;
|
| 451 |
+
StorageElement* data_;
|
| 452 |
+
};
|
| 453 |
+
|
| 454 |
+
Storage storage_;
|
| 455 |
+
};
|
| 456 |
+
|
| 457 |
+
template <typename T, size_t N, typename A>
|
| 458 |
+
constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault;
|
| 459 |
+
|
| 460 |
+
template <typename T, size_t N, typename A>
|
| 461 |
+
constexpr typename FixedArray<T, N, A>::size_type
|
| 462 |
+
FixedArray<T, N, A>::inline_elements;
|
| 463 |
+
|
| 464 |
+
} // namespace internal
|
| 465 |
+
} // namespace ceres
|
| 466 |
+
|
| 467 |
+
#endif // CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
|
ceres-v2/include/internal/householder_vector.h
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2015 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: vitus@google.com (Michael Vitus)
|
| 30 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
|
| 32 |
+
#define CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
|
| 33 |
+
|
| 34 |
+
#include "Eigen/Core"
|
| 35 |
+
#include "glog/logging.h"
|
| 36 |
+
|
| 37 |
+
namespace ceres {
|
| 38 |
+
namespace internal {
|
| 39 |
+
|
| 40 |
+
// Algorithm 5.1.1 from 'Matrix Computations' by Golub et al. (Johns Hopkins
|
| 41 |
+
// Studies in Mathematical Sciences) but using the nth element of the input
|
| 42 |
+
// vector as pivot instead of first. This computes the vector v with v(n) = 1
|
| 43 |
+
// and beta such that H = I - beta * v * v^T is orthogonal and
|
| 44 |
+
// H * x = ||x||_2 * e_n.
|
| 45 |
+
//
|
| 46 |
+
// NOTE: Some versions of MSVC have trouble deducing the type of v if
|
| 47 |
+
// you do not specify all the template arguments explicitly.
|
| 48 |
+
template <typename XVectorType, typename Scalar, int N>
|
| 49 |
+
void ComputeHouseholderVector(const XVectorType& x,
|
| 50 |
+
Eigen::Matrix<Scalar, N, 1>* v,
|
| 51 |
+
Scalar* beta) {
|
| 52 |
+
CHECK(beta != nullptr);
|
| 53 |
+
CHECK(v != nullptr);
|
| 54 |
+
CHECK_GT(x.rows(), 1);
|
| 55 |
+
CHECK_EQ(x.rows(), v->rows());
|
| 56 |
+
|
| 57 |
+
Scalar sigma = x.head(x.rows() - 1).squaredNorm();
|
| 58 |
+
*v = x;
|
| 59 |
+
(*v)(v->rows() - 1) = Scalar(1.0);
|
| 60 |
+
|
| 61 |
+
*beta = Scalar(0.0);
|
| 62 |
+
const Scalar& x_pivot = x(x.rows() - 1);
|
| 63 |
+
|
| 64 |
+
if (sigma <= Scalar(std::numeric_limits<double>::epsilon())) {
|
| 65 |
+
if (x_pivot < Scalar(0.0)) {
|
| 66 |
+
*beta = Scalar(2.0);
|
| 67 |
+
}
|
| 68 |
+
return;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
const Scalar mu = sqrt(x_pivot * x_pivot + sigma);
|
| 72 |
+
Scalar v_pivot = Scalar(1.0);
|
| 73 |
+
|
| 74 |
+
if (x_pivot <= Scalar(0.0)) {
|
| 75 |
+
v_pivot = x_pivot - mu;
|
| 76 |
+
} else {
|
| 77 |
+
v_pivot = -sigma / (x_pivot + mu);
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
*beta = Scalar(2.0) * v_pivot * v_pivot / (sigma + v_pivot * v_pivot);
|
| 81 |
+
|
| 82 |
+
v->head(v->rows() - 1) /= v_pivot;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
template <typename XVectorType, typename Derived>
|
| 86 |
+
typename Derived::PlainObject ApplyHouseholderVector(
|
| 87 |
+
const XVectorType& y,
|
| 88 |
+
const Eigen::MatrixBase<Derived>& v,
|
| 89 |
+
const typename Derived::Scalar& beta) {
|
| 90 |
+
return (y - v * (beta * (v.transpose() * y)));
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
} // namespace internal
|
| 94 |
+
} // namespace ceres
|
| 95 |
+
|
| 96 |
+
#endif // CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
|
ceres-v2/include/internal/integer_sequence_algorithm.h
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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: jodebo_beck@gmx.de (Johannes Beck)
|
| 30 |
+
// sergiu.deitsch@gmail.com (Sergiu Deitsch)
|
| 31 |
+
//
|
| 32 |
+
// Algorithms to be used together with integer_sequence, like computing the sum
|
| 33 |
+
// or the exclusive scan (sometimes called exclusive prefix sum) at compile
|
| 34 |
+
// time.
|
| 35 |
+
|
| 36 |
+
#ifndef CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
|
| 37 |
+
#define CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
|
| 38 |
+
|
| 39 |
+
#include <utility>
|
| 40 |
+
|
| 41 |
+
#include "ceres/jet_fwd.h"
|
| 42 |
+
|
| 43 |
+
namespace ceres {
|
| 44 |
+
namespace internal {
|
| 45 |
+
|
| 46 |
+
// Implementation of calculating the sum of an integer sequence.
|
| 47 |
+
// Recursively instantiate SumImpl and calculate the sum of the N first
|
| 48 |
+
// numbers. This reduces the number of instantiations and speeds up
|
| 49 |
+
// compilation.
|
| 50 |
+
//
|
| 51 |
+
// Examples:
|
| 52 |
+
// 1) integer_sequence<int, 5>:
|
| 53 |
+
// Value = 5
|
| 54 |
+
//
|
| 55 |
+
// 2) integer_sequence<int, 4, 2>:
|
| 56 |
+
// Value = 4 + 2 + SumImpl<integer_sequence<int>>::Value
|
| 57 |
+
// Value = 4 + 2 + 0
|
| 58 |
+
//
|
| 59 |
+
// 3) integer_sequence<int, 2, 1, 4>:
|
| 60 |
+
// Value = 2 + 1 + SumImpl<integer_sequence<int, 4>>::Value
|
| 61 |
+
// Value = 2 + 1 + 4
|
| 62 |
+
template <typename Seq>
|
| 63 |
+
struct SumImpl;
|
| 64 |
+
|
| 65 |
+
// Strip of and sum the first number.
|
| 66 |
+
template <typename T, T N, T... Ns>
|
| 67 |
+
struct SumImpl<std::integer_sequence<T, N, Ns...>> {
|
| 68 |
+
static constexpr T Value =
|
| 69 |
+
N + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
| 70 |
+
};
|
| 71 |
+
|
| 72 |
+
// Strip of and sum the first two numbers.
|
| 73 |
+
template <typename T, T N1, T N2, T... Ns>
|
| 74 |
+
struct SumImpl<std::integer_sequence<T, N1, N2, Ns...>> {
|
| 75 |
+
static constexpr T Value =
|
| 76 |
+
N1 + N2 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
| 77 |
+
};
|
| 78 |
+
|
| 79 |
+
// Strip of and sum the first four numbers.
|
| 80 |
+
template <typename T, T N1, T N2, T N3, T N4, T... Ns>
|
| 81 |
+
struct SumImpl<std::integer_sequence<T, N1, N2, N3, N4, Ns...>> {
|
| 82 |
+
static constexpr T Value =
|
| 83 |
+
N1 + N2 + N3 + N4 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
| 84 |
+
};
|
| 85 |
+
|
| 86 |
+
// Only one number is left. 'Value' is just that number ('recursion' ends).
|
| 87 |
+
template <typename T, T N>
|
| 88 |
+
struct SumImpl<std::integer_sequence<T, N>> {
|
| 89 |
+
static constexpr T Value = N;
|
| 90 |
+
};
|
| 91 |
+
|
| 92 |
+
// No number is left. 'Value' is the identity element (for sum this is zero).
|
| 93 |
+
template <typename T>
|
| 94 |
+
struct SumImpl<std::integer_sequence<T>> {
|
| 95 |
+
static constexpr T Value = T(0);
|
| 96 |
+
};
|
| 97 |
+
|
| 98 |
+
// Calculate the sum of an integer sequence. The resulting sum will be stored in
|
| 99 |
+
// 'Value'.
|
| 100 |
+
template <typename Seq>
|
| 101 |
+
class Sum {
|
| 102 |
+
using T = typename Seq::value_type;
|
| 103 |
+
|
| 104 |
+
public:
|
| 105 |
+
static constexpr T Value = SumImpl<Seq>::Value;
|
| 106 |
+
};
|
| 107 |
+
|
| 108 |
+
// Implementation of calculating an exclusive scan (exclusive prefix sum) of an
|
| 109 |
+
// integer sequence. Exclusive means that the i-th input element is not included
|
| 110 |
+
// in the i-th sum. Calculating the exclusive scan for an input array I results
|
| 111 |
+
// in the following output R:
|
| 112 |
+
//
|
| 113 |
+
// R[0] = 0
|
| 114 |
+
// R[1] = I[0];
|
| 115 |
+
// R[2] = I[0] + I[1];
|
| 116 |
+
// R[3] = I[0] + I[1] + I[2];
|
| 117 |
+
// ...
|
| 118 |
+
//
|
| 119 |
+
// In C++17 std::exclusive_scan does the same operation at runtime (but
|
| 120 |
+
// cannot be used to calculate the prefix sum at compile time). See
|
| 121 |
+
// https://en.cppreference.com/w/cpp/algorithm/exclusive_scan for a more
|
| 122 |
+
// detailed description.
|
| 123 |
+
//
|
| 124 |
+
// Example for integer_sequence<int, 1, 4, 3> (seq := integer_sequence):
|
| 125 |
+
// T , Sum, Ns... , Rs...
|
| 126 |
+
// ExclusiveScanImpl<int, 0, seq<int, 1, 4, 3>, seq<int >>
|
| 127 |
+
// ExclusiveScanImpl<int, 1, seq<int, 4, 3>, seq<int, 0 >>
|
| 128 |
+
// ExclusiveScanImpl<int, 5, seq<int, 3>, seq<int, 0, 1 >>
|
| 129 |
+
// ExclusiveScanImpl<int, 8, seq<int >, seq<int, 0, 1, 5>>
|
| 130 |
+
// ^^^^^^^^^^^^^^^^^
|
| 131 |
+
// resulting sequence
|
| 132 |
+
template <typename T, T Sum, typename SeqIn, typename SeqOut>
|
| 133 |
+
struct ExclusiveScanImpl;
|
| 134 |
+
|
| 135 |
+
template <typename T, T Sum, T N, T... Ns, T... Rs>
|
| 136 |
+
struct ExclusiveScanImpl<T,
|
| 137 |
+
Sum,
|
| 138 |
+
std::integer_sequence<T, N, Ns...>,
|
| 139 |
+
std::integer_sequence<T, Rs...>> {
|
| 140 |
+
using Type =
|
| 141 |
+
typename ExclusiveScanImpl<T,
|
| 142 |
+
Sum + N,
|
| 143 |
+
std::integer_sequence<T, Ns...>,
|
| 144 |
+
std::integer_sequence<T, Rs..., Sum>>::Type;
|
| 145 |
+
};
|
| 146 |
+
|
| 147 |
+
// End of 'recursion'. The resulting type is SeqOut.
|
| 148 |
+
template <typename T, T Sum, typename SeqOut>
|
| 149 |
+
struct ExclusiveScanImpl<T, Sum, std::integer_sequence<T>, SeqOut> {
|
| 150 |
+
using Type = SeqOut;
|
| 151 |
+
};
|
| 152 |
+
|
| 153 |
+
// Calculates the exclusive scan of the specified integer sequence. The last
|
| 154 |
+
// element (the total) is not included in the resulting sequence so they have
|
| 155 |
+
// same length. This means the exclusive scan of integer_sequence<int, 1, 2, 3>
|
| 156 |
+
// will be integer_sequence<int, 0, 1, 3>.
|
| 157 |
+
template <typename Seq>
|
| 158 |
+
class ExclusiveScanT {
|
| 159 |
+
using T = typename Seq::value_type;
|
| 160 |
+
|
| 161 |
+
public:
|
| 162 |
+
using Type =
|
| 163 |
+
typename ExclusiveScanImpl<T, T(0), Seq, std::integer_sequence<T>>::Type;
|
| 164 |
+
};
|
| 165 |
+
|
| 166 |
+
// Helper to use exclusive scan without typename.
|
| 167 |
+
template <typename Seq>
|
| 168 |
+
using ExclusiveScan = typename ExclusiveScanT<Seq>::Type;
|
| 169 |
+
|
| 170 |
+
// Removes all elements from a integer sequence corresponding to specified
|
| 171 |
+
// ValueToRemove.
|
| 172 |
+
//
|
| 173 |
+
// This type should not be used directly but instead RemoveValue.
|
| 174 |
+
template <typename T, T ValueToRemove, typename... Sequence>
|
| 175 |
+
struct RemoveValueImpl;
|
| 176 |
+
|
| 177 |
+
// Final filtered sequence
|
| 178 |
+
template <typename T, T ValueToRemove, T... Values>
|
| 179 |
+
struct RemoveValueImpl<T,
|
| 180 |
+
ValueToRemove,
|
| 181 |
+
std::integer_sequence<T, Values...>,
|
| 182 |
+
std::integer_sequence<T>> {
|
| 183 |
+
using type = std::integer_sequence<T, Values...>;
|
| 184 |
+
};
|
| 185 |
+
|
| 186 |
+
// Found a matching value
|
| 187 |
+
template <typename T, T ValueToRemove, T... Head, T... Tail>
|
| 188 |
+
struct RemoveValueImpl<T,
|
| 189 |
+
ValueToRemove,
|
| 190 |
+
std::integer_sequence<T, Head...>,
|
| 191 |
+
std::integer_sequence<T, ValueToRemove, Tail...>>
|
| 192 |
+
: RemoveValueImpl<T,
|
| 193 |
+
ValueToRemove,
|
| 194 |
+
std::integer_sequence<T, Head...>,
|
| 195 |
+
std::integer_sequence<T, Tail...>> {};
|
| 196 |
+
|
| 197 |
+
// Move one element from the tail to the head
|
| 198 |
+
template <typename T, T ValueToRemove, T... Head, T MiddleValue, T... Tail>
|
| 199 |
+
struct RemoveValueImpl<T,
|
| 200 |
+
ValueToRemove,
|
| 201 |
+
std::integer_sequence<T, Head...>,
|
| 202 |
+
std::integer_sequence<T, MiddleValue, Tail...>>
|
| 203 |
+
: RemoveValueImpl<T,
|
| 204 |
+
ValueToRemove,
|
| 205 |
+
std::integer_sequence<T, Head..., MiddleValue>,
|
| 206 |
+
std::integer_sequence<T, Tail...>> {};
|
| 207 |
+
|
| 208 |
+
// Start recursion by splitting the integer sequence into two separate ones
|
| 209 |
+
template <typename T, T ValueToRemove, T... Tail>
|
| 210 |
+
struct RemoveValueImpl<T, ValueToRemove, std::integer_sequence<T, Tail...>>
|
| 211 |
+
: RemoveValueImpl<T,
|
| 212 |
+
ValueToRemove,
|
| 213 |
+
std::integer_sequence<T>,
|
| 214 |
+
std::integer_sequence<T, Tail...>> {};
|
| 215 |
+
|
| 216 |
+
// RemoveValue takes an integer Sequence of arbitrary type and removes all
|
| 217 |
+
// elements matching ValueToRemove.
|
| 218 |
+
//
|
| 219 |
+
// In contrast to RemoveValueImpl, this implementation deduces the value type
|
| 220 |
+
// eliminating the need to specify it explicitly.
|
| 221 |
+
//
|
| 222 |
+
// As an example, RemoveValue<std::integer_sequence<int, 1, 2, 3>, 4>::type will
|
| 223 |
+
// not transform the type of the original sequence. However,
|
| 224 |
+
// RemoveValue<std::integer_sequence<int, 0, 0, 2>, 2>::type will generate a new
|
| 225 |
+
// sequence of type std::integer_sequence<int, 0, 0> by removing the value 2.
|
| 226 |
+
template <typename Sequence, typename Sequence::value_type ValueToRemove>
|
| 227 |
+
struct RemoveValue
|
| 228 |
+
: RemoveValueImpl<typename Sequence::value_type, ValueToRemove, Sequence> {
|
| 229 |
+
};
|
| 230 |
+
|
| 231 |
+
// Convenience template alias for RemoveValue.
|
| 232 |
+
template <typename Sequence, typename Sequence::value_type ValueToRemove>
|
| 233 |
+
using RemoveValue_t = typename RemoveValue<Sequence, ValueToRemove>::type;
|
| 234 |
+
|
| 235 |
+
// Determines whether the values of an integer sequence are all the same.
|
| 236 |
+
//
|
| 237 |
+
// The integer sequence must contain at least one value. The predicate is
|
| 238 |
+
// undefined for empty sequences. The evaluation result of the predicate for a
|
| 239 |
+
// sequence containing only one value is defined to be true.
|
| 240 |
+
template <typename... Sequence>
|
| 241 |
+
struct AreAllEqual;
|
| 242 |
+
|
| 243 |
+
// The predicate result for a sequence containing one element is defined to be
|
| 244 |
+
// true.
|
| 245 |
+
template <typename T, T Value>
|
| 246 |
+
struct AreAllEqual<std::integer_sequence<T, Value>> : std::true_type {};
|
| 247 |
+
|
| 248 |
+
// Recursion end.
|
| 249 |
+
template <typename T, T Value1, T Value2>
|
| 250 |
+
struct AreAllEqual<std::integer_sequence<T, Value1, Value2>>
|
| 251 |
+
: std::integral_constant<bool, Value1 == Value2> {};
|
| 252 |
+
|
| 253 |
+
// Recursion for sequences containing at least two elements.
|
| 254 |
+
template <typename T, T Value1, T Value2, T... Values>
|
| 255 |
+
// clang-format off
|
| 256 |
+
struct AreAllEqual<std::integer_sequence<T, Value1, Value2, Values...> >
|
| 257 |
+
: std::integral_constant
|
| 258 |
+
<
|
| 259 |
+
bool,
|
| 260 |
+
AreAllEqual<std::integer_sequence<T, Value1, Value2> >::value &&
|
| 261 |
+
AreAllEqual<std::integer_sequence<T, Value2, Values...> >::value
|
| 262 |
+
>
|
| 263 |
+
// clang-format on
|
| 264 |
+
{};
|
| 265 |
+
|
| 266 |
+
// Convenience variable template for AreAllEqual.
|
| 267 |
+
template <class Sequence>
|
| 268 |
+
constexpr bool AreAllEqual_v = AreAllEqual<Sequence>::value;
|
| 269 |
+
|
| 270 |
+
// Predicate determining whether an integer sequence is either empty or all
|
| 271 |
+
// values are equal.
|
| 272 |
+
template <typename Sequence>
|
| 273 |
+
struct IsEmptyOrAreAllEqual;
|
| 274 |
+
|
| 275 |
+
// Empty case.
|
| 276 |
+
template <typename T>
|
| 277 |
+
struct IsEmptyOrAreAllEqual<std::integer_sequence<T>> : std::true_type {};
|
| 278 |
+
|
| 279 |
+
// General case for sequences containing at least one value.
|
| 280 |
+
template <typename T, T HeadValue, T... Values>
|
| 281 |
+
struct IsEmptyOrAreAllEqual<std::integer_sequence<T, HeadValue, Values...>>
|
| 282 |
+
: AreAllEqual<std::integer_sequence<T, HeadValue, Values...>> {};
|
| 283 |
+
|
| 284 |
+
// Convenience variable template for IsEmptyOrAreAllEqual.
|
| 285 |
+
template <class Sequence>
|
| 286 |
+
constexpr bool IsEmptyOrAreAllEqual_v = IsEmptyOrAreAllEqual<Sequence>::value;
|
| 287 |
+
|
| 288 |
+
} // namespace internal
|
| 289 |
+
} // namespace ceres
|
| 290 |
+
|
| 291 |
+
#endif // CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
|
ceres-v2/include/internal/jet_traits.h
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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: sergiu.deitsch@gmail.com (Sergiu Deitsch)
|
| 30 |
+
//
|
| 31 |
+
|
| 32 |
+
#ifndef CERES_PUBLIC_INTERNAL_JET_TRAITS_H_
|
| 33 |
+
#define CERES_PUBLIC_INTERNAL_JET_TRAITS_H_
|
| 34 |
+
|
| 35 |
+
#include <tuple>
|
| 36 |
+
#include <type_traits>
|
| 37 |
+
#include <utility>
|
| 38 |
+
|
| 39 |
+
#include "ceres/internal/integer_sequence_algorithm.h"
|
| 40 |
+
#include "ceres/jet_fwd.h"
|
| 41 |
+
|
| 42 |
+
namespace ceres {
|
| 43 |
+
namespace internal {
|
| 44 |
+
|
| 45 |
+
// Predicate that determines whether T is a Jet.
|
| 46 |
+
template <typename T, typename E = void>
|
| 47 |
+
struct IsJet : std::false_type {};
|
| 48 |
+
|
| 49 |
+
template <typename T, int N>
|
| 50 |
+
struct IsJet<Jet<T, N>> : std::true_type {};
|
| 51 |
+
|
| 52 |
+
// Convenience variable template for IsJet.
|
| 53 |
+
template <typename T>
|
| 54 |
+
constexpr bool IsJet_v = IsJet<T>::value;
|
| 55 |
+
|
| 56 |
+
// Predicate that determines whether any of the Types is a Jet.
|
| 57 |
+
template <typename... Types>
|
| 58 |
+
struct AreAnyJet : std::false_type {};
|
| 59 |
+
|
| 60 |
+
template <typename T, typename... Types>
|
| 61 |
+
struct AreAnyJet<T, Types...> : AreAnyJet<Types...> {};
|
| 62 |
+
|
| 63 |
+
template <typename T, int N, typename... Types>
|
| 64 |
+
struct AreAnyJet<Jet<T, N>, Types...> : std::true_type {};
|
| 65 |
+
|
| 66 |
+
// Convenience variable template for AreAnyJet.
|
| 67 |
+
template <typename... Types>
|
| 68 |
+
constexpr bool AreAnyJet_v = AreAnyJet<Types...>::value;
|
| 69 |
+
|
| 70 |
+
// Extracts the underlying floating-point from a type T.
|
| 71 |
+
template <typename T, typename E = void>
|
| 72 |
+
struct UnderlyingScalar {
|
| 73 |
+
using type = T;
|
| 74 |
+
};
|
| 75 |
+
|
| 76 |
+
template <typename T, int N>
|
| 77 |
+
struct UnderlyingScalar<Jet<T, N>> : UnderlyingScalar<T> {};
|
| 78 |
+
|
| 79 |
+
// Convenience template alias for UnderlyingScalar type trait.
|
| 80 |
+
template <typename T>
|
| 81 |
+
using UnderlyingScalar_t = typename UnderlyingScalar<T>::type;
|
| 82 |
+
|
| 83 |
+
// Predicate determining whether all Types in the pack are the same.
|
| 84 |
+
//
|
| 85 |
+
// Specifically, the predicate applies std::is_same recursively to pairs of
|
| 86 |
+
// Types in the pack.
|
| 87 |
+
//
|
| 88 |
+
// The predicate is defined only for template packs containing at least two
|
| 89 |
+
// types.
|
| 90 |
+
template <typename T1, typename T2, typename... Types>
|
| 91 |
+
// clang-format off
|
| 92 |
+
struct AreAllSame : std::integral_constant
|
| 93 |
+
<
|
| 94 |
+
bool,
|
| 95 |
+
AreAllSame<T1, T2>::value &&
|
| 96 |
+
AreAllSame<T2, Types...>::value
|
| 97 |
+
>
|
| 98 |
+
// clang-format on
|
| 99 |
+
{};
|
| 100 |
+
|
| 101 |
+
// AreAllSame pairwise test.
|
| 102 |
+
template <typename T1, typename T2>
|
| 103 |
+
struct AreAllSame<T1, T2> : std::is_same<T1, T2> {};
|
| 104 |
+
|
| 105 |
+
// Convenience variable template for AreAllSame.
|
| 106 |
+
template <typename... Types>
|
| 107 |
+
constexpr bool AreAllSame_v = AreAllSame<Types...>::value;
|
| 108 |
+
|
| 109 |
+
// Determines the rank of a type. This allows to ensure that types passed as
|
| 110 |
+
// arguments are compatible to each other. The rank of Jet is determined by the
|
| 111 |
+
// dimensions of the dual part. The rank of a scalar is always 0.
|
| 112 |
+
// Non-specialized types default to a rank of -1.
|
| 113 |
+
template <typename T, typename E = void>
|
| 114 |
+
struct Rank : std::integral_constant<int, -1> {};
|
| 115 |
+
|
| 116 |
+
// The rank of a scalar is 0.
|
| 117 |
+
template <typename T>
|
| 118 |
+
struct Rank<T, std::enable_if_t<std::is_scalar<T>::value>>
|
| 119 |
+
: std::integral_constant<int, 0> {};
|
| 120 |
+
|
| 121 |
+
// The rank of a Jet is given by its dimensionality.
|
| 122 |
+
template <typename T, int N>
|
| 123 |
+
struct Rank<Jet<T, N>> : std::integral_constant<int, N> {};
|
| 124 |
+
|
| 125 |
+
// Convenience variable template for Rank.
|
| 126 |
+
template <typename T>
|
| 127 |
+
constexpr int Rank_v = Rank<T>::value;
|
| 128 |
+
|
| 129 |
+
// Constructs an integer sequence of ranks for each of the Types in the pack.
|
| 130 |
+
template <typename... Types>
|
| 131 |
+
using Ranks_t = std::integer_sequence<int, Rank_v<Types>...>;
|
| 132 |
+
|
| 133 |
+
// Returns the scalar part of a type. This overload acts as an identity.
|
| 134 |
+
template <typename T>
|
| 135 |
+
constexpr decltype(auto) AsScalar(T&& value) noexcept {
|
| 136 |
+
return std::forward<T>(value);
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
// Recursively unwraps the scalar part of a Jet until a non-Jet scalar type is
|
| 140 |
+
// encountered.
|
| 141 |
+
template <typename T, int N>
|
| 142 |
+
constexpr decltype(auto) AsScalar(const Jet<T, N>& value) noexcept(
|
| 143 |
+
noexcept(AsScalar(value.a))) {
|
| 144 |
+
return AsScalar(value.a);
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
} // namespace internal
|
| 148 |
+
|
| 149 |
+
// Type trait ensuring at least one of the types is a Jet,
|
| 150 |
+
// the underlying scalar types are the same and Jet dimensions match.
|
| 151 |
+
//
|
| 152 |
+
// The type trait can be further specialized if necessary.
|
| 153 |
+
//
|
| 154 |
+
// This trait is a candidate for a concept definition once C++20 features can
|
| 155 |
+
// be used.
|
| 156 |
+
template <typename... Types>
|
| 157 |
+
// clang-format off
|
| 158 |
+
struct CompatibleJetOperands : std::integral_constant
|
| 159 |
+
<
|
| 160 |
+
bool,
|
| 161 |
+
// At least one of the types is a Jet
|
| 162 |
+
internal::AreAnyJet_v<Types...> &&
|
| 163 |
+
// The underlying floating-point types are exactly the same
|
| 164 |
+
internal::AreAllSame_v<internal::UnderlyingScalar_t<Types>...> &&
|
| 165 |
+
// Non-zero ranks of types are equal
|
| 166 |
+
internal::IsEmptyOrAreAllEqual_v<internal::RemoveValue_t<internal::Ranks_t<Types...>, 0>>
|
| 167 |
+
>
|
| 168 |
+
// clang-format on
|
| 169 |
+
{};
|
| 170 |
+
|
| 171 |
+
// Single Jet operand is always compatible.
|
| 172 |
+
template <typename T, int N>
|
| 173 |
+
struct CompatibleJetOperands<Jet<T, N>> : std::true_type {};
|
| 174 |
+
|
| 175 |
+
// Single non-Jet operand is always incompatible.
|
| 176 |
+
template <typename T>
|
| 177 |
+
struct CompatibleJetOperands<T> : std::false_type {};
|
| 178 |
+
|
| 179 |
+
// Empty operands are always incompatible.
|
| 180 |
+
template <>
|
| 181 |
+
struct CompatibleJetOperands<> : std::false_type {};
|
| 182 |
+
|
| 183 |
+
// Convenience variable template ensuring at least one of the types is a Jet,
|
| 184 |
+
// the underlying scalar types are the same and Jet dimensions match.
|
| 185 |
+
//
|
| 186 |
+
// This trait is a candidate for a concept definition once C++20 features can
|
| 187 |
+
// be used.
|
| 188 |
+
template <typename... Types>
|
| 189 |
+
constexpr bool CompatibleJetOperands_v = CompatibleJetOperands<Types...>::value;
|
| 190 |
+
|
| 191 |
+
// Type trait ensuring at least one of the types is a Jet,
|
| 192 |
+
// the underlying scalar types are compatible among each other and Jet
|
| 193 |
+
// dimensions match.
|
| 194 |
+
//
|
| 195 |
+
// The type trait can be further specialized if necessary.
|
| 196 |
+
//
|
| 197 |
+
// This trait is a candidate for a concept definition once C++20 features can
|
| 198 |
+
// be used.
|
| 199 |
+
template <typename... Types>
|
| 200 |
+
// clang-format off
|
| 201 |
+
struct PromotableJetOperands : std::integral_constant
|
| 202 |
+
<
|
| 203 |
+
bool,
|
| 204 |
+
// Types can be compatible among each other
|
| 205 |
+
internal::AreAnyJet_v<Types...> &&
|
| 206 |
+
// Non-zero ranks of types are equal
|
| 207 |
+
internal::IsEmptyOrAreAllEqual_v<internal::RemoveValue_t<internal::Ranks_t<Types...>, 0>>
|
| 208 |
+
>
|
| 209 |
+
// clang-format on
|
| 210 |
+
{};
|
| 211 |
+
|
| 212 |
+
// Convenience variable template ensuring at least one of the types is a Jet,
|
| 213 |
+
// the underlying scalar types are compatible among each other and Jet
|
| 214 |
+
// dimensions match.
|
| 215 |
+
//
|
| 216 |
+
// This trait is a candidate for a concept definition once C++20 features can
|
| 217 |
+
// be used.
|
| 218 |
+
template <typename... Types>
|
| 219 |
+
constexpr bool PromotableJetOperands_v = PromotableJetOperands<Types...>::value;
|
| 220 |
+
|
| 221 |
+
} // namespace ceres
|
| 222 |
+
|
| 223 |
+
#endif // CERES_PUBLIC_INTERNAL_JET_TRAITS_H_
|
ceres-v2/include/internal/line_parameterization.h
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2020 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: jodebo_beck@gmx.de (Johannes Beck)
|
| 30 |
+
//
|
| 31 |
+
|
| 32 |
+
#ifndef CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
|
| 33 |
+
#define CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
|
| 34 |
+
|
| 35 |
+
#include "householder_vector.h"
|
| 36 |
+
|
| 37 |
+
namespace ceres {
|
| 38 |
+
|
| 39 |
+
template <int AmbientSpaceDimension>
|
| 40 |
+
bool LineParameterization<AmbientSpaceDimension>::Plus(
|
| 41 |
+
const double* x_ptr,
|
| 42 |
+
const double* delta_ptr,
|
| 43 |
+
double* x_plus_delta_ptr) const {
|
| 44 |
+
// We seek a box plus operator of the form
|
| 45 |
+
//
|
| 46 |
+
// [o*, d*] = Plus([o, d], [delta_o, delta_d])
|
| 47 |
+
//
|
| 48 |
+
// where o is the origin point, d is the direction vector, delta_o is
|
| 49 |
+
// the delta of the origin point and delta_d the delta of the direction and
|
| 50 |
+
// o* and d* is the updated origin point and direction.
|
| 51 |
+
//
|
| 52 |
+
// We separate the Plus operator into the origin point and directional part
|
| 53 |
+
// d* = Plus_d(d, delta_d)
|
| 54 |
+
// o* = Plus_o(o, d, delta_o)
|
| 55 |
+
//
|
| 56 |
+
// The direction update function Plus_d is the same as for the homogeneous
|
| 57 |
+
// vector parameterization:
|
| 58 |
+
//
|
| 59 |
+
// d* = H_{v(d)} [0.5 sinc(0.5 |delta_d|) delta_d, cos(0.5 |delta_d|)]^T
|
| 60 |
+
//
|
| 61 |
+
// where H is the householder matrix
|
| 62 |
+
// H_{v} = I - (2 / |v|^2) v v^T
|
| 63 |
+
// and
|
| 64 |
+
// v(d) = d - sign(d_n) |d| e_n.
|
| 65 |
+
//
|
| 66 |
+
// The origin point update function Plus_o is defined as
|
| 67 |
+
//
|
| 68 |
+
// o* = o + H_{v(d)} [0.5 delta_o, 0]^T.
|
| 69 |
+
|
| 70 |
+
static constexpr int kDim = AmbientSpaceDimension;
|
| 71 |
+
using AmbientVector = Eigen::Matrix<double, kDim, 1>;
|
| 72 |
+
using AmbientVectorRef = Eigen::Map<Eigen::Matrix<double, kDim, 1>>;
|
| 73 |
+
using ConstAmbientVectorRef =
|
| 74 |
+
Eigen::Map<const Eigen::Matrix<double, kDim, 1>>;
|
| 75 |
+
using ConstTangentVectorRef =
|
| 76 |
+
Eigen::Map<const Eigen::Matrix<double, kDim - 1, 1>>;
|
| 77 |
+
|
| 78 |
+
ConstAmbientVectorRef o(x_ptr);
|
| 79 |
+
ConstAmbientVectorRef d(x_ptr + kDim);
|
| 80 |
+
|
| 81 |
+
ConstTangentVectorRef delta_o(delta_ptr);
|
| 82 |
+
ConstTangentVectorRef delta_d(delta_ptr + kDim - 1);
|
| 83 |
+
AmbientVectorRef o_plus_delta(x_plus_delta_ptr);
|
| 84 |
+
AmbientVectorRef d_plus_delta(x_plus_delta_ptr + kDim);
|
| 85 |
+
|
| 86 |
+
const double norm_delta_d = delta_d.norm();
|
| 87 |
+
|
| 88 |
+
o_plus_delta = o;
|
| 89 |
+
|
| 90 |
+
// Shortcut for zero delta direction.
|
| 91 |
+
if (norm_delta_d == 0.0) {
|
| 92 |
+
d_plus_delta = d;
|
| 93 |
+
|
| 94 |
+
if (delta_o.isZero(0.0)) {
|
| 95 |
+
return true;
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
// Calculate the householder transformation which is needed for f_d and f_o.
|
| 100 |
+
AmbientVector v;
|
| 101 |
+
double beta;
|
| 102 |
+
|
| 103 |
+
// NOTE: The explicit template arguments are needed here because
|
| 104 |
+
// ComputeHouseholderVector is templated and some versions of MSVC
|
| 105 |
+
// have trouble deducing the type of v automatically.
|
| 106 |
+
internal::ComputeHouseholderVector<ConstAmbientVectorRef, double, kDim>(
|
| 107 |
+
d, &v, &beta);
|
| 108 |
+
|
| 109 |
+
if (norm_delta_d != 0.0) {
|
| 110 |
+
// Map the delta from the minimum representation to the over parameterized
|
| 111 |
+
// homogeneous vector. See section A6.9.2 on page 624 of Hartley & Zisserman
|
| 112 |
+
// (2nd Edition) for a detailed description. Note there is a typo on Page
|
| 113 |
+
// 625, line 4 so check the book errata.
|
| 114 |
+
const double norm_delta_div_2 = 0.5 * norm_delta_d;
|
| 115 |
+
const double sin_delta_by_delta =
|
| 116 |
+
std::sin(norm_delta_div_2) / norm_delta_div_2;
|
| 117 |
+
|
| 118 |
+
// Apply the delta update to remain on the unit sphere. See section A6.9.3
|
| 119 |
+
// on page 625 of Hartley & Zisserman (2nd Edition) for a detailed
|
| 120 |
+
// description.
|
| 121 |
+
AmbientVector y;
|
| 122 |
+
y.template head<kDim - 1>() = 0.5 * sin_delta_by_delta * delta_d;
|
| 123 |
+
y[kDim - 1] = std::cos(norm_delta_div_2);
|
| 124 |
+
|
| 125 |
+
d_plus_delta = d.norm() * (y - v * (beta * (v.transpose() * y)));
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
// The null space is in the direction of the line, so the tangent space is
|
| 129 |
+
// perpendicular to the line direction. This is achieved by using the
|
| 130 |
+
// householder matrix of the direction and allow only movements
|
| 131 |
+
// perpendicular to e_n.
|
| 132 |
+
//
|
| 133 |
+
// The factor of 0.5 is used to be consistent with the line direction
|
| 134 |
+
// update.
|
| 135 |
+
AmbientVector y;
|
| 136 |
+
y << 0.5 * delta_o, 0;
|
| 137 |
+
o_plus_delta += y - v * (beta * (v.transpose() * y));
|
| 138 |
+
|
| 139 |
+
return true;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
template <int AmbientSpaceDimension>
|
| 143 |
+
bool LineParameterization<AmbientSpaceDimension>::ComputeJacobian(
|
| 144 |
+
const double* x_ptr, double* jacobian_ptr) const {
|
| 145 |
+
static constexpr int kDim = AmbientSpaceDimension;
|
| 146 |
+
using AmbientVector = Eigen::Matrix<double, kDim, 1>;
|
| 147 |
+
using ConstAmbientVectorRef =
|
| 148 |
+
Eigen::Map<const Eigen::Matrix<double, kDim, 1>>;
|
| 149 |
+
using MatrixRef = Eigen::Map<
|
| 150 |
+
Eigen::Matrix<double, 2 * kDim, 2 * (kDim - 1), Eigen::RowMajor>>;
|
| 151 |
+
|
| 152 |
+
ConstAmbientVectorRef d(x_ptr + kDim);
|
| 153 |
+
MatrixRef jacobian(jacobian_ptr);
|
| 154 |
+
|
| 155 |
+
// Clear the Jacobian as only half of the matrix is not zero.
|
| 156 |
+
jacobian.setZero();
|
| 157 |
+
|
| 158 |
+
AmbientVector v;
|
| 159 |
+
double beta;
|
| 160 |
+
|
| 161 |
+
// NOTE: The explicit template arguments are needed here because
|
| 162 |
+
// ComputeHouseholderVector is templated and some versions of MSVC
|
| 163 |
+
// have trouble deducing the type of v automatically.
|
| 164 |
+
internal::ComputeHouseholderVector<ConstAmbientVectorRef, double, kDim>(
|
| 165 |
+
d, &v, &beta);
|
| 166 |
+
|
| 167 |
+
// The Jacobian is equal to J = 0.5 * H.leftCols(kDim - 1) where H is
|
| 168 |
+
// the Householder matrix (H = I - beta * v * v') for the origin point. For
|
| 169 |
+
// the line direction part the Jacobian is scaled by the norm of the
|
| 170 |
+
// direction.
|
| 171 |
+
for (int i = 0; i < kDim - 1; ++i) {
|
| 172 |
+
jacobian.block(0, i, kDim, 1) = -0.5 * beta * v(i) * v;
|
| 173 |
+
jacobian.col(i)(i) += 0.5;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
jacobian.template block<kDim, kDim - 1>(kDim, kDim - 1) =
|
| 177 |
+
jacobian.template block<kDim, kDim - 1>(0, 0) * d.norm();
|
| 178 |
+
return true;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
} // namespace ceres
|
| 182 |
+
|
| 183 |
+
#endif // CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
|
ceres-v2/include/internal/memory.h
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright 2017 The Abseil Authors.
|
| 2 |
+
//
|
| 3 |
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
// you may not use this file except in compliance with the License.
|
| 5 |
+
// You may obtain a copy of the License at
|
| 6 |
+
//
|
| 7 |
+
// https://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
//
|
| 9 |
+
// Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
// See the License for the specific language governing permissions and
|
| 13 |
+
// limitations under the License.
|
| 14 |
+
//
|
| 15 |
+
// -----------------------------------------------------------------------------
|
| 16 |
+
// File: memory.h
|
| 17 |
+
// -----------------------------------------------------------------------------
|
| 18 |
+
//
|
| 19 |
+
// This header file contains utility functions for managing the creation and
|
| 20 |
+
// conversion of smart pointers. This file is an extension to the C++
|
| 21 |
+
// standard <memory> library header file.
|
| 22 |
+
|
| 23 |
+
#ifndef CERES_PUBLIC_INTERNAL_MEMORY_H_
|
| 24 |
+
#define CERES_PUBLIC_INTERNAL_MEMORY_H_
|
| 25 |
+
|
| 26 |
+
#include <memory>
|
| 27 |
+
|
| 28 |
+
#ifdef CERES_HAVE_EXCEPTIONS
|
| 29 |
+
#define CERES_INTERNAL_TRY try
|
| 30 |
+
#define CERES_INTERNAL_CATCH_ANY catch (...)
|
| 31 |
+
#define CERES_INTERNAL_RETHROW \
|
| 32 |
+
do { \
|
| 33 |
+
throw; \
|
| 34 |
+
} while (false)
|
| 35 |
+
#else // CERES_HAVE_EXCEPTIONS
|
| 36 |
+
#define CERES_INTERNAL_TRY if (true)
|
| 37 |
+
#define CERES_INTERNAL_CATCH_ANY else if (false)
|
| 38 |
+
#define CERES_INTERNAL_RETHROW \
|
| 39 |
+
do { \
|
| 40 |
+
} while (false)
|
| 41 |
+
#endif // CERES_HAVE_EXCEPTIONS
|
| 42 |
+
|
| 43 |
+
namespace ceres {
|
| 44 |
+
namespace internal {
|
| 45 |
+
|
| 46 |
+
template <typename Allocator, typename Iterator, typename... Args>
|
| 47 |
+
void ConstructRange(Allocator& alloc,
|
| 48 |
+
Iterator first,
|
| 49 |
+
Iterator last,
|
| 50 |
+
const Args&... args) {
|
| 51 |
+
for (Iterator cur = first; cur != last; ++cur) {
|
| 52 |
+
CERES_INTERNAL_TRY {
|
| 53 |
+
std::allocator_traits<Allocator>::construct(
|
| 54 |
+
alloc, std::addressof(*cur), args...);
|
| 55 |
+
}
|
| 56 |
+
CERES_INTERNAL_CATCH_ANY {
|
| 57 |
+
while (cur != first) {
|
| 58 |
+
--cur;
|
| 59 |
+
std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
|
| 60 |
+
}
|
| 61 |
+
CERES_INTERNAL_RETHROW;
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
template <typename Allocator, typename Iterator, typename InputIterator>
|
| 67 |
+
void CopyRange(Allocator& alloc,
|
| 68 |
+
Iterator destination,
|
| 69 |
+
InputIterator first,
|
| 70 |
+
InputIterator last) {
|
| 71 |
+
for (Iterator cur = destination; first != last;
|
| 72 |
+
static_cast<void>(++cur), static_cast<void>(++first)) {
|
| 73 |
+
CERES_INTERNAL_TRY {
|
| 74 |
+
std::allocator_traits<Allocator>::construct(
|
| 75 |
+
alloc, std::addressof(*cur), *first);
|
| 76 |
+
}
|
| 77 |
+
CERES_INTERNAL_CATCH_ANY {
|
| 78 |
+
while (cur != destination) {
|
| 79 |
+
--cur;
|
| 80 |
+
std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
|
| 81 |
+
}
|
| 82 |
+
CERES_INTERNAL_RETHROW;
|
| 83 |
+
}
|
| 84 |
+
}
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
} // namespace internal
|
| 88 |
+
} // namespace ceres
|
| 89 |
+
|
| 90 |
+
#endif // CERES_PUBLIC_INTERNAL_MEMORY_H_
|
ceres-v2/include/internal/numeric_diff.h
ADDED
|
@@ -0,0 +1,508 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2015 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 |
+
// mierle@gmail.com (Keir Mierle)
|
| 31 |
+
// tbennun@gmail.com (Tal Ben-Nun)
|
| 32 |
+
//
|
| 33 |
+
// Finite differencing routines used by NumericDiffCostFunction.
|
| 34 |
+
|
| 35 |
+
#ifndef CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
|
| 36 |
+
#define CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
|
| 37 |
+
|
| 38 |
+
#include <cstring>
|
| 39 |
+
#include <utility>
|
| 40 |
+
|
| 41 |
+
#include "Eigen/Dense"
|
| 42 |
+
#include "Eigen/StdVector"
|
| 43 |
+
#include "ceres/cost_function.h"
|
| 44 |
+
#include "ceres/internal/fixed_array.h"
|
| 45 |
+
#include "ceres/internal/variadic_evaluate.h"
|
| 46 |
+
#include "ceres/numeric_diff_options.h"
|
| 47 |
+
#include "ceres/types.h"
|
| 48 |
+
#include "glog/logging.h"
|
| 49 |
+
|
| 50 |
+
namespace ceres {
|
| 51 |
+
namespace internal {
|
| 52 |
+
|
| 53 |
+
// This is split from the main class because C++ doesn't allow partial template
|
| 54 |
+
// specializations for member functions. The alternative is to repeat the main
|
| 55 |
+
// class for differing numbers of parameters, which is also unfortunate.
|
| 56 |
+
template <typename CostFunctor,
|
| 57 |
+
NumericDiffMethodType kMethod,
|
| 58 |
+
int kNumResiduals,
|
| 59 |
+
typename ParameterDims,
|
| 60 |
+
int kParameterBlock,
|
| 61 |
+
int kParameterBlockSize>
|
| 62 |
+
struct NumericDiff {
|
| 63 |
+
// Mutates parameters but must restore them before return.
|
| 64 |
+
static bool EvaluateJacobianForParameterBlock(
|
| 65 |
+
const CostFunctor* functor,
|
| 66 |
+
const double* residuals_at_eval_point,
|
| 67 |
+
const NumericDiffOptions& options,
|
| 68 |
+
int num_residuals,
|
| 69 |
+
int parameter_block_index,
|
| 70 |
+
int parameter_block_size,
|
| 71 |
+
double** parameters,
|
| 72 |
+
double* jacobian) {
|
| 73 |
+
using Eigen::ColMajor;
|
| 74 |
+
using Eigen::Map;
|
| 75 |
+
using Eigen::Matrix;
|
| 76 |
+
using Eigen::RowMajor;
|
| 77 |
+
|
| 78 |
+
DCHECK(jacobian);
|
| 79 |
+
|
| 80 |
+
const int num_residuals_internal =
|
| 81 |
+
(kNumResiduals != ceres::DYNAMIC ? kNumResiduals : num_residuals);
|
| 82 |
+
const int parameter_block_index_internal =
|
| 83 |
+
(kParameterBlock != ceres::DYNAMIC ? kParameterBlock
|
| 84 |
+
: parameter_block_index);
|
| 85 |
+
const int parameter_block_size_internal =
|
| 86 |
+
(kParameterBlockSize != ceres::DYNAMIC ? kParameterBlockSize
|
| 87 |
+
: parameter_block_size);
|
| 88 |
+
|
| 89 |
+
using ResidualVector = Matrix<double, kNumResiduals, 1>;
|
| 90 |
+
using ParameterVector = Matrix<double, kParameterBlockSize, 1>;
|
| 91 |
+
|
| 92 |
+
// The convoluted reasoning for choosing the Row/Column major
|
| 93 |
+
// ordering of the matrix is an artifact of the restrictions in
|
| 94 |
+
// Eigen that prevent it from creating RowMajor matrices with a
|
| 95 |
+
// single column. In these cases, we ask for a ColMajor matrix.
|
| 96 |
+
using JacobianMatrix =
|
| 97 |
+
Matrix<double,
|
| 98 |
+
kNumResiduals,
|
| 99 |
+
kParameterBlockSize,
|
| 100 |
+
(kParameterBlockSize == 1) ? ColMajor : RowMajor>;
|
| 101 |
+
|
| 102 |
+
Map<JacobianMatrix> parameter_jacobian(
|
| 103 |
+
jacobian, num_residuals_internal, parameter_block_size_internal);
|
| 104 |
+
|
| 105 |
+
Map<ParameterVector> x_plus_delta(
|
| 106 |
+
parameters[parameter_block_index_internal],
|
| 107 |
+
parameter_block_size_internal);
|
| 108 |
+
ParameterVector x(x_plus_delta);
|
| 109 |
+
ParameterVector step_size =
|
| 110 |
+
x.array().abs() * ((kMethod == RIDDERS)
|
| 111 |
+
? options.ridders_relative_initial_step_size
|
| 112 |
+
: options.relative_step_size);
|
| 113 |
+
|
| 114 |
+
// It is not a good idea to make the step size arbitrarily
|
| 115 |
+
// small. This will lead to problems with round off and numerical
|
| 116 |
+
// instability when dividing by the step size. The general
|
| 117 |
+
// recommendation is to not go down below sqrt(epsilon).
|
| 118 |
+
double min_step_size = std::sqrt(std::numeric_limits<double>::epsilon());
|
| 119 |
+
|
| 120 |
+
// For Ridders' method, the initial step size is required to be large,
|
| 121 |
+
// thus ridders_relative_initial_step_size is used.
|
| 122 |
+
if (kMethod == RIDDERS) {
|
| 123 |
+
min_step_size =
|
| 124 |
+
(std::max)(min_step_size, options.ridders_relative_initial_step_size);
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
// For each parameter in the parameter block, use finite differences to
|
| 128 |
+
// compute the derivative for that parameter.
|
| 129 |
+
FixedArray<double> temp_residual_array(num_residuals_internal);
|
| 130 |
+
FixedArray<double> residual_array(num_residuals_internal);
|
| 131 |
+
Map<ResidualVector> residuals(residual_array.data(),
|
| 132 |
+
num_residuals_internal);
|
| 133 |
+
|
| 134 |
+
for (int j = 0; j < parameter_block_size_internal; ++j) {
|
| 135 |
+
const double delta = (std::max)(min_step_size, step_size(j));
|
| 136 |
+
|
| 137 |
+
if (kMethod == RIDDERS) {
|
| 138 |
+
if (!EvaluateRiddersJacobianColumn(functor,
|
| 139 |
+
j,
|
| 140 |
+
delta,
|
| 141 |
+
options,
|
| 142 |
+
num_residuals_internal,
|
| 143 |
+
parameter_block_size_internal,
|
| 144 |
+
x.data(),
|
| 145 |
+
residuals_at_eval_point,
|
| 146 |
+
parameters,
|
| 147 |
+
x_plus_delta.data(),
|
| 148 |
+
temp_residual_array.data(),
|
| 149 |
+
residual_array.data())) {
|
| 150 |
+
return false;
|
| 151 |
+
}
|
| 152 |
+
} else {
|
| 153 |
+
if (!EvaluateJacobianColumn(functor,
|
| 154 |
+
j,
|
| 155 |
+
delta,
|
| 156 |
+
num_residuals_internal,
|
| 157 |
+
parameter_block_size_internal,
|
| 158 |
+
x.data(),
|
| 159 |
+
residuals_at_eval_point,
|
| 160 |
+
parameters,
|
| 161 |
+
x_plus_delta.data(),
|
| 162 |
+
temp_residual_array.data(),
|
| 163 |
+
residual_array.data())) {
|
| 164 |
+
return false;
|
| 165 |
+
}
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
parameter_jacobian.col(j).matrix() = residuals;
|
| 169 |
+
}
|
| 170 |
+
return true;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
static bool EvaluateJacobianColumn(const CostFunctor* functor,
|
| 174 |
+
int parameter_index,
|
| 175 |
+
double delta,
|
| 176 |
+
int num_residuals,
|
| 177 |
+
int parameter_block_size,
|
| 178 |
+
const double* x_ptr,
|
| 179 |
+
const double* residuals_at_eval_point,
|
| 180 |
+
double** parameters,
|
| 181 |
+
double* x_plus_delta_ptr,
|
| 182 |
+
double* temp_residuals_ptr,
|
| 183 |
+
double* residuals_ptr) {
|
| 184 |
+
using Eigen::Map;
|
| 185 |
+
using Eigen::Matrix;
|
| 186 |
+
|
| 187 |
+
using ResidualVector = Matrix<double, kNumResiduals, 1>;
|
| 188 |
+
using ParameterVector = Matrix<double, kParameterBlockSize, 1>;
|
| 189 |
+
|
| 190 |
+
Map<const ParameterVector> x(x_ptr, parameter_block_size);
|
| 191 |
+
Map<ParameterVector> x_plus_delta(x_plus_delta_ptr, parameter_block_size);
|
| 192 |
+
|
| 193 |
+
Map<ResidualVector> residuals(residuals_ptr, num_residuals);
|
| 194 |
+
Map<ResidualVector> temp_residuals(temp_residuals_ptr, num_residuals);
|
| 195 |
+
|
| 196 |
+
// Mutate 1 element at a time and then restore.
|
| 197 |
+
x_plus_delta(parameter_index) = x(parameter_index) + delta;
|
| 198 |
+
|
| 199 |
+
if (!VariadicEvaluate<ParameterDims>(
|
| 200 |
+
*functor, parameters, residuals.data())) {
|
| 201 |
+
return false;
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
// Compute this column of the jacobian in 3 steps:
|
| 205 |
+
// 1. Store residuals for the forward part.
|
| 206 |
+
// 2. Subtract residuals for the backward (or 0) part.
|
| 207 |
+
// 3. Divide out the run.
|
| 208 |
+
double one_over_delta = 1.0 / delta;
|
| 209 |
+
if (kMethod == CENTRAL || kMethod == RIDDERS) {
|
| 210 |
+
// Compute the function on the other side of x(parameter_index).
|
| 211 |
+
x_plus_delta(parameter_index) = x(parameter_index) - delta;
|
| 212 |
+
|
| 213 |
+
if (!VariadicEvaluate<ParameterDims>(
|
| 214 |
+
*functor, parameters, temp_residuals.data())) {
|
| 215 |
+
return false;
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
residuals -= temp_residuals;
|
| 219 |
+
one_over_delta /= 2;
|
| 220 |
+
} else {
|
| 221 |
+
// Forward difference only; reuse existing residuals evaluation.
|
| 222 |
+
residuals -=
|
| 223 |
+
Map<const ResidualVector>(residuals_at_eval_point, num_residuals);
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
// Restore x_plus_delta.
|
| 227 |
+
x_plus_delta(parameter_index) = x(parameter_index);
|
| 228 |
+
|
| 229 |
+
// Divide out the run to get slope.
|
| 230 |
+
residuals *= one_over_delta;
|
| 231 |
+
|
| 232 |
+
return true;
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
// This numeric difference implementation uses adaptive differentiation
|
| 236 |
+
// on the parameters to obtain the Jacobian matrix. The adaptive algorithm
|
| 237 |
+
// is based on Ridders' method for adaptive differentiation, which creates
|
| 238 |
+
// a Romberg tableau from varying step sizes and extrapolates the
|
| 239 |
+
// intermediate results to obtain the current computational error.
|
| 240 |
+
//
|
| 241 |
+
// References:
|
| 242 |
+
// C.J.F. Ridders, Accurate computation of F'(x) and F'(x) F"(x), Advances
|
| 243 |
+
// in Engineering Software (1978), Volume 4, Issue 2, April 1982,
|
| 244 |
+
// Pages 75-76, ISSN 0141-1195,
|
| 245 |
+
// http://dx.doi.org/10.1016/S0141-1195(82)80057-0.
|
| 246 |
+
static bool EvaluateRiddersJacobianColumn(
|
| 247 |
+
const CostFunctor* functor,
|
| 248 |
+
int parameter_index,
|
| 249 |
+
double delta,
|
| 250 |
+
const NumericDiffOptions& options,
|
| 251 |
+
int num_residuals,
|
| 252 |
+
int parameter_block_size,
|
| 253 |
+
const double* x_ptr,
|
| 254 |
+
const double* residuals_at_eval_point,
|
| 255 |
+
double** parameters,
|
| 256 |
+
double* x_plus_delta_ptr,
|
| 257 |
+
double* temp_residuals_ptr,
|
| 258 |
+
double* residuals_ptr) {
|
| 259 |
+
using Eigen::aligned_allocator;
|
| 260 |
+
using Eigen::Map;
|
| 261 |
+
using Eigen::Matrix;
|
| 262 |
+
|
| 263 |
+
using ResidualVector = Matrix<double, kNumResiduals, 1>;
|
| 264 |
+
using ResidualCandidateMatrix =
|
| 265 |
+
Matrix<double, kNumResiduals, Eigen::Dynamic>;
|
| 266 |
+
using ParameterVector = Matrix<double, kParameterBlockSize, 1>;
|
| 267 |
+
|
| 268 |
+
Map<const ParameterVector> x(x_ptr, parameter_block_size);
|
| 269 |
+
Map<ParameterVector> x_plus_delta(x_plus_delta_ptr, parameter_block_size);
|
| 270 |
+
|
| 271 |
+
Map<ResidualVector> residuals(residuals_ptr, num_residuals);
|
| 272 |
+
Map<ResidualVector> temp_residuals(temp_residuals_ptr, num_residuals);
|
| 273 |
+
|
| 274 |
+
// In order for the algorithm to converge, the step size should be
|
| 275 |
+
// initialized to a value that is large enough to produce a significant
|
| 276 |
+
// change in the function.
|
| 277 |
+
// As the derivative is estimated, the step size decreases.
|
| 278 |
+
// By default, the step sizes are chosen so that the middle column
|
| 279 |
+
// of the Romberg tableau uses the input delta.
|
| 280 |
+
double current_step_size =
|
| 281 |
+
delta * pow(options.ridders_step_shrink_factor,
|
| 282 |
+
options.max_num_ridders_extrapolations / 2);
|
| 283 |
+
|
| 284 |
+
// Double-buffering temporary differential candidate vectors
|
| 285 |
+
// from previous step size.
|
| 286 |
+
ResidualCandidateMatrix stepsize_candidates_a(
|
| 287 |
+
num_residuals, options.max_num_ridders_extrapolations);
|
| 288 |
+
ResidualCandidateMatrix stepsize_candidates_b(
|
| 289 |
+
num_residuals, options.max_num_ridders_extrapolations);
|
| 290 |
+
ResidualCandidateMatrix* current_candidates = &stepsize_candidates_a;
|
| 291 |
+
ResidualCandidateMatrix* previous_candidates = &stepsize_candidates_b;
|
| 292 |
+
|
| 293 |
+
// Represents the computational error of the derivative. This variable is
|
| 294 |
+
// initially set to a large value, and is set to the difference between
|
| 295 |
+
// current and previous finite difference extrapolations.
|
| 296 |
+
// norm_error is supposed to decrease as the finite difference tableau
|
| 297 |
+
// generation progresses, serving both as an estimate for differentiation
|
| 298 |
+
// error and as a measure of differentiation numerical stability.
|
| 299 |
+
double norm_error = (std::numeric_limits<double>::max)();
|
| 300 |
+
|
| 301 |
+
// Loop over decreasing step sizes until:
|
| 302 |
+
// 1. Error is smaller than a given value (ridders_epsilon),
|
| 303 |
+
// 2. Maximal order of extrapolation reached, or
|
| 304 |
+
// 3. Extrapolation becomes numerically unstable.
|
| 305 |
+
for (int i = 0; i < options.max_num_ridders_extrapolations; ++i) {
|
| 306 |
+
// Compute the numerical derivative at this step size.
|
| 307 |
+
if (!EvaluateJacobianColumn(functor,
|
| 308 |
+
parameter_index,
|
| 309 |
+
current_step_size,
|
| 310 |
+
num_residuals,
|
| 311 |
+
parameter_block_size,
|
| 312 |
+
x.data(),
|
| 313 |
+
residuals_at_eval_point,
|
| 314 |
+
parameters,
|
| 315 |
+
x_plus_delta.data(),
|
| 316 |
+
temp_residuals.data(),
|
| 317 |
+
current_candidates->col(0).data())) {
|
| 318 |
+
// Something went wrong; bail.
|
| 319 |
+
return false;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
// Store initial results.
|
| 323 |
+
if (i == 0) {
|
| 324 |
+
residuals = current_candidates->col(0);
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
// Shrink differentiation step size.
|
| 328 |
+
current_step_size /= options.ridders_step_shrink_factor;
|
| 329 |
+
|
| 330 |
+
// Extrapolation factor for Richardson acceleration method (see below).
|
| 331 |
+
double richardson_factor = options.ridders_step_shrink_factor *
|
| 332 |
+
options.ridders_step_shrink_factor;
|
| 333 |
+
for (int k = 1; k <= i; ++k) {
|
| 334 |
+
// Extrapolate the various orders of finite differences using
|
| 335 |
+
// the Richardson acceleration method.
|
| 336 |
+
current_candidates->col(k) =
|
| 337 |
+
(richardson_factor * current_candidates->col(k - 1) -
|
| 338 |
+
previous_candidates->col(k - 1)) /
|
| 339 |
+
(richardson_factor - 1.0);
|
| 340 |
+
|
| 341 |
+
richardson_factor *= options.ridders_step_shrink_factor *
|
| 342 |
+
options.ridders_step_shrink_factor;
|
| 343 |
+
|
| 344 |
+
// Compute the difference between the previous value and the current.
|
| 345 |
+
double candidate_error = (std::max)(
|
| 346 |
+
(current_candidates->col(k) - current_candidates->col(k - 1))
|
| 347 |
+
.norm(),
|
| 348 |
+
(current_candidates->col(k) - previous_candidates->col(k - 1))
|
| 349 |
+
.norm());
|
| 350 |
+
|
| 351 |
+
// If the error has decreased, update results.
|
| 352 |
+
if (candidate_error <= norm_error) {
|
| 353 |
+
norm_error = candidate_error;
|
| 354 |
+
residuals = current_candidates->col(k);
|
| 355 |
+
|
| 356 |
+
// If the error is small enough, stop.
|
| 357 |
+
if (norm_error < options.ridders_epsilon) {
|
| 358 |
+
break;
|
| 359 |
+
}
|
| 360 |
+
}
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
// After breaking out of the inner loop, declare convergence.
|
| 364 |
+
if (norm_error < options.ridders_epsilon) {
|
| 365 |
+
break;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
// Check to see if the current gradient estimate is numerically unstable.
|
| 369 |
+
// If so, bail out and return the last stable result.
|
| 370 |
+
if (i > 0) {
|
| 371 |
+
double tableau_error =
|
| 372 |
+
(current_candidates->col(i) - previous_candidates->col(i - 1))
|
| 373 |
+
.norm();
|
| 374 |
+
|
| 375 |
+
// Compare current error to the chosen candidate's error.
|
| 376 |
+
if (tableau_error >= 2 * norm_error) {
|
| 377 |
+
break;
|
| 378 |
+
}
|
| 379 |
+
}
|
| 380 |
+
|
| 381 |
+
std::swap(current_candidates, previous_candidates);
|
| 382 |
+
}
|
| 383 |
+
return true;
|
| 384 |
+
}
|
| 385 |
+
};
|
| 386 |
+
|
| 387 |
+
// This function calls NumericDiff<...>::EvaluateJacobianForParameterBlock for
|
| 388 |
+
// each parameter block.
|
| 389 |
+
//
|
| 390 |
+
// Example:
|
| 391 |
+
// A call to
|
| 392 |
+
// EvaluateJacobianForParameterBlocks<StaticParameterDims<2, 3>>(
|
| 393 |
+
// functor,
|
| 394 |
+
// residuals_at_eval_point,
|
| 395 |
+
// options,
|
| 396 |
+
// num_residuals,
|
| 397 |
+
// parameters,
|
| 398 |
+
// jacobians);
|
| 399 |
+
// will result in the following calls to
|
| 400 |
+
// NumericDiff<...>::EvaluateJacobianForParameterBlock:
|
| 401 |
+
//
|
| 402 |
+
// if (jacobians[0] != nullptr) {
|
| 403 |
+
// if (!NumericDiff<
|
| 404 |
+
// CostFunctor,
|
| 405 |
+
// method,
|
| 406 |
+
// kNumResiduals,
|
| 407 |
+
// StaticParameterDims<2, 3>,
|
| 408 |
+
// 0,
|
| 409 |
+
// 2>::EvaluateJacobianForParameterBlock(functor,
|
| 410 |
+
// residuals_at_eval_point,
|
| 411 |
+
// options,
|
| 412 |
+
// num_residuals,
|
| 413 |
+
// 0,
|
| 414 |
+
// 2,
|
| 415 |
+
// parameters,
|
| 416 |
+
// jacobians[0])) {
|
| 417 |
+
// return false;
|
| 418 |
+
// }
|
| 419 |
+
// }
|
| 420 |
+
// if (jacobians[1] != nullptr) {
|
| 421 |
+
// if (!NumericDiff<
|
| 422 |
+
// CostFunctor,
|
| 423 |
+
// method,
|
| 424 |
+
// kNumResiduals,
|
| 425 |
+
// StaticParameterDims<2, 3>,
|
| 426 |
+
// 1,
|
| 427 |
+
// 3>::EvaluateJacobianForParameterBlock(functor,
|
| 428 |
+
// residuals_at_eval_point,
|
| 429 |
+
// options,
|
| 430 |
+
// num_residuals,
|
| 431 |
+
// 1,
|
| 432 |
+
// 3,
|
| 433 |
+
// parameters,
|
| 434 |
+
// jacobians[1])) {
|
| 435 |
+
// return false;
|
| 436 |
+
// }
|
| 437 |
+
// }
|
| 438 |
+
template <typename ParameterDims,
|
| 439 |
+
typename Parameters = typename ParameterDims::Parameters,
|
| 440 |
+
int ParameterIdx = 0>
|
| 441 |
+
struct EvaluateJacobianForParameterBlocks;
|
| 442 |
+
|
| 443 |
+
template <typename ParameterDims, int N, int... Ns, int ParameterIdx>
|
| 444 |
+
struct EvaluateJacobianForParameterBlocks<ParameterDims,
|
| 445 |
+
std::integer_sequence<int, N, Ns...>,
|
| 446 |
+
ParameterIdx> {
|
| 447 |
+
template <NumericDiffMethodType method,
|
| 448 |
+
int kNumResiduals,
|
| 449 |
+
typename CostFunctor>
|
| 450 |
+
static bool Apply(const CostFunctor* functor,
|
| 451 |
+
const double* residuals_at_eval_point,
|
| 452 |
+
const NumericDiffOptions& options,
|
| 453 |
+
int num_residuals,
|
| 454 |
+
double** parameters,
|
| 455 |
+
double** jacobians) {
|
| 456 |
+
if (jacobians[ParameterIdx] != nullptr) {
|
| 457 |
+
if (!NumericDiff<
|
| 458 |
+
CostFunctor,
|
| 459 |
+
method,
|
| 460 |
+
kNumResiduals,
|
| 461 |
+
ParameterDims,
|
| 462 |
+
ParameterIdx,
|
| 463 |
+
N>::EvaluateJacobianForParameterBlock(functor,
|
| 464 |
+
residuals_at_eval_point,
|
| 465 |
+
options,
|
| 466 |
+
num_residuals,
|
| 467 |
+
ParameterIdx,
|
| 468 |
+
N,
|
| 469 |
+
parameters,
|
| 470 |
+
jacobians[ParameterIdx])) {
|
| 471 |
+
return false;
|
| 472 |
+
}
|
| 473 |
+
}
|
| 474 |
+
|
| 475 |
+
return EvaluateJacobianForParameterBlocks<ParameterDims,
|
| 476 |
+
std::integer_sequence<int, Ns...>,
|
| 477 |
+
ParameterIdx + 1>::
|
| 478 |
+
template Apply<method, kNumResiduals>(functor,
|
| 479 |
+
residuals_at_eval_point,
|
| 480 |
+
options,
|
| 481 |
+
num_residuals,
|
| 482 |
+
parameters,
|
| 483 |
+
jacobians);
|
| 484 |
+
}
|
| 485 |
+
};
|
| 486 |
+
|
| 487 |
+
// End of 'recursion'. Nothing more to do.
|
| 488 |
+
template <typename ParameterDims, int ParameterIdx>
|
| 489 |
+
struct EvaluateJacobianForParameterBlocks<ParameterDims,
|
| 490 |
+
std::integer_sequence<int>,
|
| 491 |
+
ParameterIdx> {
|
| 492 |
+
template <NumericDiffMethodType method,
|
| 493 |
+
int kNumResiduals,
|
| 494 |
+
typename CostFunctor>
|
| 495 |
+
static bool Apply(const CostFunctor* /* NOT USED*/,
|
| 496 |
+
const double* /* NOT USED*/,
|
| 497 |
+
const NumericDiffOptions& /* NOT USED*/,
|
| 498 |
+
int /* NOT USED*/,
|
| 499 |
+
double** /* NOT USED*/,
|
| 500 |
+
double** /* NOT USED*/) {
|
| 501 |
+
return true;
|
| 502 |
+
}
|
| 503 |
+
};
|
| 504 |
+
|
| 505 |
+
} // namespace internal
|
| 506 |
+
} // namespace ceres
|
| 507 |
+
|
| 508 |
+
#endif // CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
|
ceres-v2/include/internal/parameter_dims.h
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2018 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: jodebo_beck@gmx.de (Johannes Beck)
|
| 30 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_INTERNAL_PARAMETER_DIMS_H_
|
| 32 |
+
#define CERES_PUBLIC_INTERNAL_PARAMETER_DIMS_H_
|
| 33 |
+
|
| 34 |
+
#include <array>
|
| 35 |
+
#include <utility>
|
| 36 |
+
|
| 37 |
+
#include "ceres/internal/integer_sequence_algorithm.h"
|
| 38 |
+
|
| 39 |
+
namespace ceres {
|
| 40 |
+
namespace internal {
|
| 41 |
+
|
| 42 |
+
// Checks, whether the given parameter block sizes are valid. Valid means every
|
| 43 |
+
// dimension is bigger than zero.
|
| 44 |
+
constexpr bool IsValidParameterDimensionSequence(std::integer_sequence<int>) {
|
| 45 |
+
return true;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
template <int N, int... Ts>
|
| 49 |
+
constexpr bool IsValidParameterDimensionSequence(
|
| 50 |
+
std::integer_sequence<int, N, Ts...>) {
|
| 51 |
+
return (N <= 0) ? false
|
| 52 |
+
: IsValidParameterDimensionSequence(
|
| 53 |
+
std::integer_sequence<int, Ts...>());
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
// Helper class that represents the parameter dimensions. The parameter
|
| 57 |
+
// dimensions are either dynamic or the sizes are known at compile time. It is
|
| 58 |
+
// used to pass parameter block dimensions around (e.g. between functions or
|
| 59 |
+
// classes).
|
| 60 |
+
//
|
| 61 |
+
// As an example if one have three parameter blocks with dimensions (2, 4, 1),
|
| 62 |
+
// one would use 'StaticParameterDims<2, 4, 1>' which is a synonym for
|
| 63 |
+
// 'ParameterDims<false, 2, 4, 1>'.
|
| 64 |
+
// For dynamic parameter dims, one would just use 'DynamicParameterDims', which
|
| 65 |
+
// is a synonym for 'ParameterDims<true>'.
|
| 66 |
+
template <bool IsDynamic, int... Ns>
|
| 67 |
+
class ParameterDims {
|
| 68 |
+
public:
|
| 69 |
+
using Parameters = std::integer_sequence<int, Ns...>;
|
| 70 |
+
|
| 71 |
+
// The parameter dimensions are only valid if all parameter block dimensions
|
| 72 |
+
// are greater than zero.
|
| 73 |
+
static constexpr bool kIsValid =
|
| 74 |
+
IsValidParameterDimensionSequence(Parameters());
|
| 75 |
+
static_assert(kIsValid,
|
| 76 |
+
"Invalid parameter block dimension detected. Each parameter "
|
| 77 |
+
"block dimension must be bigger than zero.");
|
| 78 |
+
|
| 79 |
+
static constexpr bool kIsDynamic = IsDynamic;
|
| 80 |
+
static constexpr int kNumParameterBlocks = sizeof...(Ns);
|
| 81 |
+
static_assert(kIsDynamic || kNumParameterBlocks > 0,
|
| 82 |
+
"At least one parameter block must be specified.");
|
| 83 |
+
|
| 84 |
+
static constexpr int kNumParameters =
|
| 85 |
+
Sum<std::integer_sequence<int, Ns...>>::Value;
|
| 86 |
+
|
| 87 |
+
static constexpr int GetDim(int dim) { return params_[dim]; }
|
| 88 |
+
|
| 89 |
+
// If one has all parameters packed into a single array this function unpacks
|
| 90 |
+
// the parameters.
|
| 91 |
+
template <typename T>
|
| 92 |
+
static inline std::array<T*, kNumParameterBlocks> GetUnpackedParameters(
|
| 93 |
+
T* ptr) {
|
| 94 |
+
using Offsets = ExclusiveScan<Parameters>;
|
| 95 |
+
return GetUnpackedParameters(ptr, Offsets());
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
private:
|
| 99 |
+
template <typename T, int... Indices>
|
| 100 |
+
static inline std::array<T*, kNumParameterBlocks> GetUnpackedParameters(
|
| 101 |
+
T* ptr, std::integer_sequence<int, Indices...>) {
|
| 102 |
+
return std::array<T*, kNumParameterBlocks>{{ptr + Indices...}};
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
static constexpr std::array<int, kNumParameterBlocks> params_{Ns...};
|
| 106 |
+
};
|
| 107 |
+
|
| 108 |
+
// Even static constexpr member variables needs to be defined (not only
|
| 109 |
+
// declared). As the ParameterDims class is tempalted this definition must
|
| 110 |
+
// be in the header file.
|
| 111 |
+
template <bool IsDynamic, int... Ns>
|
| 112 |
+
constexpr std::array<int, ParameterDims<IsDynamic, Ns...>::kNumParameterBlocks>
|
| 113 |
+
ParameterDims<IsDynamic, Ns...>::params_;
|
| 114 |
+
|
| 115 |
+
// Using declarations for static and dynamic parameter dims. This makes client
|
| 116 |
+
// code easier to read.
|
| 117 |
+
template <int... Ns>
|
| 118 |
+
using StaticParameterDims = ParameterDims<false, Ns...>;
|
| 119 |
+
using DynamicParameterDims = ParameterDims<true>;
|
| 120 |
+
|
| 121 |
+
} // namespace internal
|
| 122 |
+
} // namespace ceres
|
| 123 |
+
|
| 124 |
+
#endif // CERES_PUBLIC_INTERNAL_PARAMETER_DIMS_H_
|
ceres-v2/include/internal/port.h
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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: keir@google.com (Keir Mierle)
|
| 30 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_INTERNAL_PORT_H_
|
| 32 |
+
#define CERES_PUBLIC_INTERNAL_PORT_H_
|
| 33 |
+
|
| 34 |
+
// A macro to mark a function/variable/class as deprecated.
|
| 35 |
+
// We use compiler specific attributes rather than the c++
|
| 36 |
+
// attribute because they do not mix well with each other.
|
| 37 |
+
#if defined(_MSC_VER)
|
| 38 |
+
#define CERES_DEPRECATED_WITH_MSG(message) __declspec(deprecated(message))
|
| 39 |
+
#elif defined(__GNUC__)
|
| 40 |
+
#define CERES_DEPRECATED_WITH_MSG(message) __attribute__((deprecated(message)))
|
| 41 |
+
#else
|
| 42 |
+
// In the worst case fall back to c++ attribute.
|
| 43 |
+
#define CERES_DEPRECATED_WITH_MSG(message) [[deprecated(message)]]
|
| 44 |
+
#endif
|
| 45 |
+
|
| 46 |
+
#ifndef CERES_GET_FLAG
|
| 47 |
+
#define CERES_GET_FLAG(X) X
|
| 48 |
+
#endif
|
| 49 |
+
|
| 50 |
+
// Indicates whether C++17 is currently active
|
| 51 |
+
#ifndef CERES_HAS_CPP17
|
| 52 |
+
#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
| 53 |
+
#define CERES_HAS_CPP17
|
| 54 |
+
#endif // __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >=
|
| 55 |
+
// 201703L)
|
| 56 |
+
#endif // !defined(CERES_HAS_CPP17)
|
| 57 |
+
|
| 58 |
+
// Indicates whether C++20 is currently active
|
| 59 |
+
#ifndef CERES_HAS_CPP20
|
| 60 |
+
#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
| 61 |
+
#define CERES_HAS_CPP20
|
| 62 |
+
#endif // __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >=
|
| 63 |
+
// 202002L)
|
| 64 |
+
#endif // !defined(CERES_HAS_CPP20)
|
| 65 |
+
|
| 66 |
+
// Prevents symbols from being substituted by the corresponding macro definition
|
| 67 |
+
// under the same name. For instance, min and max are defined as macros on
|
| 68 |
+
// Windows (unless NOMINMAX is defined) which causes compilation errors when
|
| 69 |
+
// defining or referencing symbols under the same name.
|
| 70 |
+
//
|
| 71 |
+
// To be robust in all cases particularly when NOMINMAX cannot be used, use this
|
| 72 |
+
// macro to annotate min/max declarations/definitions. Examples:
|
| 73 |
+
//
|
| 74 |
+
// int max CERES_PREVENT_MACRO_SUBSTITUTION();
|
| 75 |
+
// min CERES_PREVENT_MACRO_SUBSTITUTION(a, b);
|
| 76 |
+
// max CERES_PREVENT_MACRO_SUBSTITUTION(a, b);
|
| 77 |
+
//
|
| 78 |
+
// NOTE: In case the symbols for which the substitution must be prevented are
|
| 79 |
+
// used within another macro, the substitution must be inhibited using parens as
|
| 80 |
+
//
|
| 81 |
+
// (std::numerical_limits<double>::max)()
|
| 82 |
+
//
|
| 83 |
+
// since the helper macro will not work here. Do not use this technique in
|
| 84 |
+
// general case, because it will prevent argument-dependent lookup (ADL).
|
| 85 |
+
//
|
| 86 |
+
#define CERES_PREVENT_MACRO_SUBSTITUTION // Yes, it's empty
|
| 87 |
+
|
| 88 |
+
#endif // CERES_PUBLIC_INTERNAL_PORT_H_
|
ceres-v2/include/internal/reenable_warnings.h
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2015 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 |
+
|
| 30 |
+
// This is not your usual header guard. See disable_warnings.h
|
| 31 |
+
#ifdef CERES_WARNINGS_DISABLED
|
| 32 |
+
#undef CERES_WARNINGS_DISABLED
|
| 33 |
+
|
| 34 |
+
#ifdef _MSC_VER
|
| 35 |
+
#pragma warning(pop)
|
| 36 |
+
#endif
|
| 37 |
+
|
| 38 |
+
#endif // CERES_WARNINGS_DISABLED
|
ceres-v2/include/internal/sphere_manifold_functions.h
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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: vitus@google.com (Mike Vitus)
|
| 30 |
+
// jodebo_beck@gmx.de (Johannes Beck)
|
| 31 |
+
|
| 32 |
+
#ifndef CERES_PUBLIC_INTERNAL_SPHERE_MANIFOLD_HELPERS_H_
|
| 33 |
+
#define CERES_PUBLIC_INTERNAL_SPHERE_MANIFOLD_HELPERS_H_
|
| 34 |
+
|
| 35 |
+
#include "ceres/internal/householder_vector.h"
|
| 36 |
+
|
| 37 |
+
// This module contains functions to compute the SphereManifold plus and minus
|
| 38 |
+
// operator and their Jacobians.
|
| 39 |
+
//
|
| 40 |
+
// As the parameters to these functions are shared between them, they are
|
| 41 |
+
// described here: The following variable names are used:
|
| 42 |
+
// Plus(x, delta) = x + delta = x_plus_delta,
|
| 43 |
+
// Minus(y, x) = y - x = y_minus_x.
|
| 44 |
+
//
|
| 45 |
+
// The remaining ones are v and beta which describe the Householder
|
| 46 |
+
// transformation of x, and norm_delta which is the norm of delta.
|
| 47 |
+
//
|
| 48 |
+
// The types of x, y, x_plus_delta and y_minus_x need to be equivalent to
|
| 49 |
+
// Eigen::Matrix<double, AmbientSpaceDimension, 1> and the type of delta needs
|
| 50 |
+
// to be equivalent to Eigen::Matrix<double, TangentSpaceDimension, 1>.
|
| 51 |
+
//
|
| 52 |
+
// The type of Jacobian plus needs to be equivalent to Eigen::Matrix<double,
|
| 53 |
+
// AmbientSpaceDimension, TangentSpaceDimension, Eigen::RowMajor> and for
|
| 54 |
+
// Jacobian minus Eigen::Matrix<double, TangentSpaceDimension,
|
| 55 |
+
// AmbientSpaceDimension, Eigen::RowMajor>.
|
| 56 |
+
//
|
| 57 |
+
// For all vector / matrix inputs and outputs, template parameters are
|
| 58 |
+
// used in order to allow also Eigen::Ref and Eigen block expressions to
|
| 59 |
+
// be passed to the function.
|
| 60 |
+
|
| 61 |
+
namespace ceres {
|
| 62 |
+
namespace internal {
|
| 63 |
+
|
| 64 |
+
template <typename VT, typename XT, typename DeltaT, typename XPlusDeltaT>
|
| 65 |
+
inline void ComputeSphereManifoldPlus(const VT& v,
|
| 66 |
+
double beta,
|
| 67 |
+
const XT& x,
|
| 68 |
+
const DeltaT& delta,
|
| 69 |
+
double norm_delta,
|
| 70 |
+
XPlusDeltaT* x_plus_delta) {
|
| 71 |
+
constexpr int AmbientDim = VT::RowsAtCompileTime;
|
| 72 |
+
|
| 73 |
+
// Map the delta from the minimum representation to the over parameterized
|
| 74 |
+
// homogeneous vector. See B.2 p.25 equation (106) - (107) for more details.
|
| 75 |
+
const double norm_delta_div_2 = 0.5 * norm_delta;
|
| 76 |
+
const double sin_delta_by_delta =
|
| 77 |
+
std::sin(norm_delta_div_2) / norm_delta_div_2;
|
| 78 |
+
|
| 79 |
+
Eigen::Matrix<double, AmbientDim, 1> y(v.size());
|
| 80 |
+
y << 0.5 * sin_delta_by_delta * delta, std::cos(norm_delta_div_2);
|
| 81 |
+
|
| 82 |
+
// Apply the delta update to remain on the sphere.
|
| 83 |
+
*x_plus_delta = x.norm() * ApplyHouseholderVector(y, v, beta);
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
template <typename VT, typename JacobianT>
|
| 87 |
+
inline void ComputeSphereManifoldPlusJacobian(const VT& x,
|
| 88 |
+
JacobianT* jacobian) {
|
| 89 |
+
constexpr int AmbientSpaceDim = VT::RowsAtCompileTime;
|
| 90 |
+
using AmbientVector = Eigen::Matrix<double, AmbientSpaceDim, 1>;
|
| 91 |
+
const int ambient_size = x.size();
|
| 92 |
+
const int tangent_size = x.size() - 1;
|
| 93 |
+
|
| 94 |
+
AmbientVector v(ambient_size);
|
| 95 |
+
double beta;
|
| 96 |
+
|
| 97 |
+
// NOTE: The explicit template arguments are needed here because
|
| 98 |
+
// ComputeHouseholderVector is templated and some versions of MSVC
|
| 99 |
+
// have trouble deducing the type of v automatically.
|
| 100 |
+
ComputeHouseholderVector<VT, double, AmbientSpaceDim>(x, &v, &beta);
|
| 101 |
+
|
| 102 |
+
// The Jacobian is equal to J = 0.5 * H.leftCols(size_ - 1) where H is the
|
| 103 |
+
// Householder matrix (H = I - beta * v * v').
|
| 104 |
+
for (int i = 0; i < tangent_size; ++i) {
|
| 105 |
+
(*jacobian).col(i) = -0.5 * beta * v(i) * v;
|
| 106 |
+
(*jacobian)(i, i) += 0.5;
|
| 107 |
+
}
|
| 108 |
+
(*jacobian) *= x.norm();
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
template <typename VT, typename XT, typename YT, typename YMinusXT>
|
| 112 |
+
inline void ComputeSphereManifoldMinus(
|
| 113 |
+
const VT& v, double beta, const XT& x, const YT& y, YMinusXT* y_minus_x) {
|
| 114 |
+
constexpr int AmbientSpaceDim = VT::RowsAtCompileTime;
|
| 115 |
+
constexpr int TangentSpaceDim =
|
| 116 |
+
AmbientSpaceDim == Eigen::Dynamic ? Eigen::Dynamic : AmbientSpaceDim - 1;
|
| 117 |
+
using AmbientVector = Eigen::Matrix<double, AmbientSpaceDim, 1>;
|
| 118 |
+
|
| 119 |
+
const int tanget_size = v.size() - 1;
|
| 120 |
+
|
| 121 |
+
const AmbientVector hy = ApplyHouseholderVector(y, v, beta) / x.norm();
|
| 122 |
+
|
| 123 |
+
// Calculate y - x. See B.2 p.25 equation (108).
|
| 124 |
+
double y_last = hy[tanget_size];
|
| 125 |
+
double hy_norm = hy.template head<TangentSpaceDim>(tanget_size).norm();
|
| 126 |
+
if (hy_norm == 0.0) {
|
| 127 |
+
y_minus_x->setZero();
|
| 128 |
+
} else {
|
| 129 |
+
*y_minus_x = 2.0 * std::atan2(hy_norm, y_last) / hy_norm *
|
| 130 |
+
hy.template head<TangentSpaceDim>(tanget_size);
|
| 131 |
+
}
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
template <typename VT, typename JacobianT>
|
| 135 |
+
inline void ComputeSphereManifoldMinusJacobian(const VT& x,
|
| 136 |
+
JacobianT* jacobian) {
|
| 137 |
+
constexpr int AmbientSpaceDim = VT::RowsAtCompileTime;
|
| 138 |
+
using AmbientVector = Eigen::Matrix<double, AmbientSpaceDim, 1>;
|
| 139 |
+
const int ambient_size = x.size();
|
| 140 |
+
const int tangent_size = x.size() - 1;
|
| 141 |
+
|
| 142 |
+
AmbientVector v(ambient_size);
|
| 143 |
+
double beta;
|
| 144 |
+
|
| 145 |
+
// NOTE: The explicit template arguments are needed here because
|
| 146 |
+
// ComputeHouseholderVector is templated and some versions of MSVC
|
| 147 |
+
// have trouble deducing the type of v automatically.
|
| 148 |
+
ComputeHouseholderVector<VT, double, AmbientSpaceDim>(x, &v, &beta);
|
| 149 |
+
|
| 150 |
+
// The Jacobian is equal to J = 2.0 * H.leftCols(size_ - 1) where H is the
|
| 151 |
+
// Householder matrix (H = I - beta * v * v').
|
| 152 |
+
for (int i = 0; i < tangent_size; ++i) {
|
| 153 |
+
(*jacobian).row(i) = -2.0 * beta * v(i) * v;
|
| 154 |
+
(*jacobian)(i, i) += 2.0;
|
| 155 |
+
}
|
| 156 |
+
(*jacobian) /= x.norm();
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
} // namespace internal
|
| 160 |
+
} // namespace ceres
|
| 161 |
+
|
| 162 |
+
#endif
|
ceres-v2/include/internal/variadic_evaluate.h
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2015 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 |
+
// mierle@gmail.com (Keir Mierle)
|
| 31 |
+
// jodebo_beck@gmx.de (Johannes Beck)
|
| 32 |
+
|
| 33 |
+
#ifndef CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
|
| 34 |
+
#define CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
|
| 35 |
+
|
| 36 |
+
#include <cstddef>
|
| 37 |
+
#include <type_traits>
|
| 38 |
+
#include <utility>
|
| 39 |
+
|
| 40 |
+
#include "ceres/cost_function.h"
|
| 41 |
+
#include "ceres/internal/parameter_dims.h"
|
| 42 |
+
|
| 43 |
+
namespace ceres {
|
| 44 |
+
namespace internal {
|
| 45 |
+
|
| 46 |
+
// For fixed size cost functors
|
| 47 |
+
template <typename Functor, typename T, int... Indices>
|
| 48 |
+
inline bool VariadicEvaluateImpl(const Functor& functor,
|
| 49 |
+
T const* const* input,
|
| 50 |
+
T* output,
|
| 51 |
+
std::false_type /*is_dynamic*/,
|
| 52 |
+
std::integer_sequence<int, Indices...>) {
|
| 53 |
+
static_assert(sizeof...(Indices),
|
| 54 |
+
"Invalid number of parameter blocks. At least one parameter "
|
| 55 |
+
"block must be specified.");
|
| 56 |
+
return functor(input[Indices]..., output);
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
// For dynamic sized cost functors
|
| 60 |
+
template <typename Functor, typename T>
|
| 61 |
+
inline bool VariadicEvaluateImpl(const Functor& functor,
|
| 62 |
+
T const* const* input,
|
| 63 |
+
T* output,
|
| 64 |
+
std::true_type /*is_dynamic*/,
|
| 65 |
+
std::integer_sequence<int>) {
|
| 66 |
+
return functor(input, output);
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
// For ceres cost functors (not ceres::CostFunction)
|
| 70 |
+
template <typename ParameterDims, typename Functor, typename T>
|
| 71 |
+
inline bool VariadicEvaluateImpl(const Functor& functor,
|
| 72 |
+
T const* const* input,
|
| 73 |
+
T* output,
|
| 74 |
+
const void* /* NOT USED */) {
|
| 75 |
+
using ParameterBlockIndices =
|
| 76 |
+
std::make_integer_sequence<int, ParameterDims::kNumParameterBlocks>;
|
| 77 |
+
using IsDynamic = std::integral_constant<bool, ParameterDims::kIsDynamic>;
|
| 78 |
+
return VariadicEvaluateImpl(
|
| 79 |
+
functor, input, output, IsDynamic(), ParameterBlockIndices());
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
// For ceres::CostFunction
|
| 83 |
+
template <typename ParameterDims, typename Functor, typename T>
|
| 84 |
+
inline bool VariadicEvaluateImpl(const Functor& functor,
|
| 85 |
+
T const* const* input,
|
| 86 |
+
T* output,
|
| 87 |
+
const CostFunction* /* NOT USED */) {
|
| 88 |
+
return functor.Evaluate(input, output, nullptr);
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
// Variadic evaluate is a helper function to evaluate ceres cost function or
|
| 92 |
+
// functors using an input, output and the parameter dimensions. There are
|
| 93 |
+
// several ways different possibilities:
|
| 94 |
+
// 1) If the passed functor is a 'ceres::CostFunction' its evaluate method is
|
| 95 |
+
// called.
|
| 96 |
+
// 2) If the functor is not a 'ceres::CostFunction' and the specified parameter
|
| 97 |
+
// dims is dynamic, the functor must have the following signature
|
| 98 |
+
// 'bool(T const* const* input, T* output)'.
|
| 99 |
+
// 3) If the functor is not a 'ceres::CostFunction' and the specified parameter
|
| 100 |
+
// dims is not dynamic, the input is expanded by using the number of parameter
|
| 101 |
+
// blocks. The signature of the functor must have the following signature
|
| 102 |
+
// 'bool()(const T* i_1, const T* i_2, ... const T* i_n, T* output)'.
|
| 103 |
+
template <typename ParameterDims, typename Functor, typename T>
|
| 104 |
+
inline bool VariadicEvaluate(const Functor& functor,
|
| 105 |
+
T const* const* input,
|
| 106 |
+
T* output) {
|
| 107 |
+
return VariadicEvaluateImpl<ParameterDims>(functor, input, output, &functor);
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
} // namespace internal
|
| 111 |
+
} // namespace ceres
|
| 112 |
+
|
| 113 |
+
#endif // CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
|
ceres-v2/include/iteration_callback.h
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
//
|
| 31 |
+
// When an iteration callback is specified, Ceres calls the callback
|
| 32 |
+
// after each minimizer step (if the minimizer has not converged) and
|
| 33 |
+
// passes it an IterationSummary object, defined below.
|
| 34 |
+
|
| 35 |
+
#ifndef CERES_PUBLIC_ITERATION_CALLBACK_H_
|
| 36 |
+
#define CERES_PUBLIC_ITERATION_CALLBACK_H_
|
| 37 |
+
|
| 38 |
+
#include "ceres/internal/disable_warnings.h"
|
| 39 |
+
#include "ceres/internal/export.h"
|
| 40 |
+
#include "ceres/types.h"
|
| 41 |
+
|
| 42 |
+
namespace ceres {
|
| 43 |
+
|
| 44 |
+
// This struct describes the state of the optimizer after each
|
| 45 |
+
// iteration of the minimization.
|
| 46 |
+
struct CERES_EXPORT IterationSummary {
|
| 47 |
+
// Current iteration number.
|
| 48 |
+
int iteration = 0;
|
| 49 |
+
|
| 50 |
+
// Step was numerically valid, i.e., all values are finite and the
|
| 51 |
+
// step reduces the value of the linearized model.
|
| 52 |
+
//
|
| 53 |
+
// Note: step_is_valid is always true when iteration = 0.
|
| 54 |
+
bool step_is_valid = false;
|
| 55 |
+
|
| 56 |
+
// Step did not reduce the value of the objective function
|
| 57 |
+
// sufficiently, but it was accepted because of the relaxed
|
| 58 |
+
// acceptance criterion used by the non-monotonic trust region
|
| 59 |
+
// algorithm.
|
| 60 |
+
//
|
| 61 |
+
// Note: step_is_nonmonotonic is always false when iteration = 0;
|
| 62 |
+
bool step_is_nonmonotonic = false;
|
| 63 |
+
|
| 64 |
+
// Whether or not the minimizer accepted this step or not. If the
|
| 65 |
+
// ordinary trust region algorithm is used, this means that the
|
| 66 |
+
// relative reduction in the objective function value was greater
|
| 67 |
+
// than Solver::Options::min_relative_decrease. However, if the
|
| 68 |
+
// non-monotonic trust region algorithm is used
|
| 69 |
+
// (Solver::Options:use_nonmonotonic_steps = true), then even if the
|
| 70 |
+
// relative decrease is not sufficient, the algorithm may accept the
|
| 71 |
+
// step and the step is declared successful.
|
| 72 |
+
//
|
| 73 |
+
// Note: step_is_successful is always true when iteration = 0.
|
| 74 |
+
bool step_is_successful = false;
|
| 75 |
+
|
| 76 |
+
// Value of the objective function.
|
| 77 |
+
double cost = 0.0;
|
| 78 |
+
|
| 79 |
+
// Change in the value of the objective function in this
|
| 80 |
+
// iteration. This can be positive or negative.
|
| 81 |
+
double cost_change = 0.0;
|
| 82 |
+
|
| 83 |
+
// Infinity norm of the gradient vector.
|
| 84 |
+
double gradient_max_norm = 0.0;
|
| 85 |
+
|
| 86 |
+
// 2-norm of the gradient vector.
|
| 87 |
+
double gradient_norm = 0.0;
|
| 88 |
+
|
| 89 |
+
// 2-norm of the size of the step computed by the optimization
|
| 90 |
+
// algorithm.
|
| 91 |
+
double step_norm = 0.0;
|
| 92 |
+
|
| 93 |
+
// For trust region algorithms, the ratio of the actual change in
|
| 94 |
+
// cost and the change in the cost of the linearized approximation.
|
| 95 |
+
double relative_decrease = 0.0;
|
| 96 |
+
|
| 97 |
+
// Size of the trust region at the end of the current iteration. For
|
| 98 |
+
// the Levenberg-Marquardt algorithm, the regularization parameter
|
| 99 |
+
// mu = 1.0 / trust_region_radius.
|
| 100 |
+
double trust_region_radius = 0.0;
|
| 101 |
+
|
| 102 |
+
// For the inexact step Levenberg-Marquardt algorithm, this is the
|
| 103 |
+
// relative accuracy with which the Newton(LM) step is solved. This
|
| 104 |
+
// number affects only the iterative solvers capable of solving
|
| 105 |
+
// linear systems inexactly. Factorization-based exact solvers
|
| 106 |
+
// ignore it.
|
| 107 |
+
double eta = 0.0;
|
| 108 |
+
|
| 109 |
+
// Step sized computed by the line search algorithm.
|
| 110 |
+
double step_size = 0.0;
|
| 111 |
+
|
| 112 |
+
// Number of function value evaluations used by the line search algorithm.
|
| 113 |
+
int line_search_function_evaluations = 0;
|
| 114 |
+
|
| 115 |
+
// Number of function gradient evaluations used by the line search algorithm.
|
| 116 |
+
int line_search_gradient_evaluations = 0;
|
| 117 |
+
|
| 118 |
+
// Number of iterations taken by the line search algorithm.
|
| 119 |
+
int line_search_iterations = 0;
|
| 120 |
+
|
| 121 |
+
// Number of iterations taken by the linear solver to solve for the
|
| 122 |
+
// Newton step.
|
| 123 |
+
int linear_solver_iterations = 0;
|
| 124 |
+
|
| 125 |
+
// All times reported below are wall times.
|
| 126 |
+
|
| 127 |
+
// Time (in seconds) spent inside the minimizer loop in the current
|
| 128 |
+
// iteration.
|
| 129 |
+
double iteration_time_in_seconds = 0.0;
|
| 130 |
+
|
| 131 |
+
// Time (in seconds) spent inside the trust region step solver.
|
| 132 |
+
double step_solver_time_in_seconds = 0.0;
|
| 133 |
+
|
| 134 |
+
// Time (in seconds) since the user called Solve().
|
| 135 |
+
double cumulative_time_in_seconds = 0.0;
|
| 136 |
+
};
|
| 137 |
+
|
| 138 |
+
// Interface for specifying callbacks that are executed at the end of
|
| 139 |
+
// each iteration of the Minimizer. The solver uses the return value
|
| 140 |
+
// of operator() to decide whether to continue solving or to
|
| 141 |
+
// terminate. The user can return three values.
|
| 142 |
+
//
|
| 143 |
+
// SOLVER_ABORT indicates that the callback detected an abnormal
|
| 144 |
+
// situation. The solver returns without updating the parameter blocks
|
| 145 |
+
// (unless Solver::Options::update_state_every_iteration is set
|
| 146 |
+
// true). Solver returns with Solver::Summary::termination_type set to
|
| 147 |
+
// USER_ABORT.
|
| 148 |
+
//
|
| 149 |
+
// SOLVER_TERMINATE_SUCCESSFULLY indicates that there is no need to
|
| 150 |
+
// optimize anymore (some user specified termination criterion has
|
| 151 |
+
// been met). Solver returns with Solver::Summary::termination_type
|
| 152 |
+
// set to USER_SUCCESS.
|
| 153 |
+
//
|
| 154 |
+
// SOLVER_CONTINUE indicates that the solver should continue
|
| 155 |
+
// optimizing.
|
| 156 |
+
//
|
| 157 |
+
// For example, the following Callback is used internally by Ceres to
|
| 158 |
+
// log the progress of the optimization.
|
| 159 |
+
//
|
| 160 |
+
// Callback for logging the state of the minimizer to STDERR or STDOUT
|
| 161 |
+
// depending on the user's preferences and logging level.
|
| 162 |
+
//
|
| 163 |
+
// class LoggingCallback : public IterationCallback {
|
| 164 |
+
// public:
|
| 165 |
+
// explicit LoggingCallback(bool log_to_stdout)
|
| 166 |
+
// : log_to_stdout_(log_to_stdout) {}
|
| 167 |
+
//
|
| 168 |
+
// CallbackReturnType operator()(const IterationSummary& summary) {
|
| 169 |
+
// const char* kReportRowFormat =
|
| 170 |
+
// "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e "
|
| 171 |
+
// "rho:% 3.2e mu:% 3.2e eta:% 3.2e li:% 3d";
|
| 172 |
+
// string output = StringPrintf(kReportRowFormat,
|
| 173 |
+
// summary.iteration,
|
| 174 |
+
// summary.cost,
|
| 175 |
+
// summary.cost_change,
|
| 176 |
+
// summary.gradient_max_norm,
|
| 177 |
+
// summary.step_norm,
|
| 178 |
+
// summary.relative_decrease,
|
| 179 |
+
// summary.trust_region_radius,
|
| 180 |
+
// summary.eta,
|
| 181 |
+
// summary.linear_solver_iterations);
|
| 182 |
+
// if (log_to_stdout_) {
|
| 183 |
+
// cout << output << endl;
|
| 184 |
+
// } else {
|
| 185 |
+
// VLOG(1) << output;
|
| 186 |
+
// }
|
| 187 |
+
// return SOLVER_CONTINUE;
|
| 188 |
+
// }
|
| 189 |
+
//
|
| 190 |
+
// private:
|
| 191 |
+
// const bool log_to_stdout_;
|
| 192 |
+
// };
|
| 193 |
+
//
|
| 194 |
+
class CERES_EXPORT IterationCallback {
|
| 195 |
+
public:
|
| 196 |
+
virtual ~IterationCallback();
|
| 197 |
+
virtual CallbackReturnType operator()(const IterationSummary& summary) = 0;
|
| 198 |
+
};
|
| 199 |
+
|
| 200 |
+
} // namespace ceres
|
| 201 |
+
|
| 202 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 203 |
+
|
| 204 |
+
#endif // CERES_PUBLIC_ITERATION_CALLBACK_H_
|
ceres-v2/include/jet.h
ADDED
|
@@ -0,0 +1,1387 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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: keir@google.com (Keir Mierle)
|
| 30 |
+
//
|
| 31 |
+
// A simple implementation of N-dimensional dual numbers, for automatically
|
| 32 |
+
// computing exact derivatives of functions.
|
| 33 |
+
//
|
| 34 |
+
// While a complete treatment of the mechanics of automatic differentiation is
|
| 35 |
+
// beyond the scope of this header (see
|
| 36 |
+
// http://en.wikipedia.org/wiki/Automatic_differentiation for details), the
|
| 37 |
+
// basic idea is to extend normal arithmetic with an extra element, "e," often
|
| 38 |
+
// denoted with the greek symbol epsilon, such that e != 0 but e^2 = 0. Dual
|
| 39 |
+
// numbers are extensions of the real numbers analogous to complex numbers:
|
| 40 |
+
// whereas complex numbers augment the reals by introducing an imaginary unit i
|
| 41 |
+
// such that i^2 = -1, dual numbers introduce an "infinitesimal" unit e such
|
| 42 |
+
// that e^2 = 0. Dual numbers have two components: the "real" component and the
|
| 43 |
+
// "infinitesimal" component, generally written as x + y*e. Surprisingly, this
|
| 44 |
+
// leads to a convenient method for computing exact derivatives without needing
|
| 45 |
+
// to manipulate complicated symbolic expressions.
|
| 46 |
+
//
|
| 47 |
+
// For example, consider the function
|
| 48 |
+
//
|
| 49 |
+
// f(x) = x^2 ,
|
| 50 |
+
//
|
| 51 |
+
// evaluated at 10. Using normal arithmetic, f(10) = 100, and df/dx(10) = 20.
|
| 52 |
+
// Next, argument 10 with an infinitesimal to get:
|
| 53 |
+
//
|
| 54 |
+
// f(10 + e) = (10 + e)^2
|
| 55 |
+
// = 100 + 2 * 10 * e + e^2
|
| 56 |
+
// = 100 + 20 * e -+-
|
| 57 |
+
// -- |
|
| 58 |
+
// | +--- This is zero, since e^2 = 0
|
| 59 |
+
// |
|
| 60 |
+
// +----------------- This is df/dx!
|
| 61 |
+
//
|
| 62 |
+
// Note that the derivative of f with respect to x is simply the infinitesimal
|
| 63 |
+
// component of the value of f(x + e). So, in order to take the derivative of
|
| 64 |
+
// any function, it is only necessary to replace the numeric "object" used in
|
| 65 |
+
// the function with one extended with infinitesimals. The class Jet, defined in
|
| 66 |
+
// this header, is one such example of this, where substitution is done with
|
| 67 |
+
// templates.
|
| 68 |
+
//
|
| 69 |
+
// To handle derivatives of functions taking multiple arguments, different
|
| 70 |
+
// infinitesimals are used, one for each variable to take the derivative of. For
|
| 71 |
+
// example, consider a scalar function of two scalar parameters x and y:
|
| 72 |
+
//
|
| 73 |
+
// f(x, y) = x^2 + x * y
|
| 74 |
+
//
|
| 75 |
+
// Following the technique above, to compute the derivatives df/dx and df/dy for
|
| 76 |
+
// f(1, 3) involves doing two evaluations of f, the first time replacing x with
|
| 77 |
+
// x + e, the second time replacing y with y + e.
|
| 78 |
+
//
|
| 79 |
+
// For df/dx:
|
| 80 |
+
//
|
| 81 |
+
// f(1 + e, y) = (1 + e)^2 + (1 + e) * 3
|
| 82 |
+
// = 1 + 2 * e + 3 + 3 * e
|
| 83 |
+
// = 4 + 5 * e
|
| 84 |
+
//
|
| 85 |
+
// --> df/dx = 5
|
| 86 |
+
//
|
| 87 |
+
// For df/dy:
|
| 88 |
+
//
|
| 89 |
+
// f(1, 3 + e) = 1^2 + 1 * (3 + e)
|
| 90 |
+
// = 1 + 3 + e
|
| 91 |
+
// = 4 + e
|
| 92 |
+
//
|
| 93 |
+
// --> df/dy = 1
|
| 94 |
+
//
|
| 95 |
+
// To take the gradient of f with the implementation of dual numbers ("jets") in
|
| 96 |
+
// this file, it is necessary to create a single jet type which has components
|
| 97 |
+
// for the derivative in x and y, and passing them to a templated version of f:
|
| 98 |
+
//
|
| 99 |
+
// template<typename T>
|
| 100 |
+
// T f(const T &x, const T &y) {
|
| 101 |
+
// return x * x + x * y;
|
| 102 |
+
// }
|
| 103 |
+
//
|
| 104 |
+
// // The "2" means there should be 2 dual number components.
|
| 105 |
+
// // It computes the partial derivative at x=10, y=20.
|
| 106 |
+
// Jet<double, 2> x(10, 0); // Pick the 0th dual number for x.
|
| 107 |
+
// Jet<double, 2> y(20, 1); // Pick the 1st dual number for y.
|
| 108 |
+
// Jet<double, 2> z = f(x, y);
|
| 109 |
+
//
|
| 110 |
+
// LOG(INFO) << "df/dx = " << z.v[0]
|
| 111 |
+
// << "df/dy = " << z.v[1];
|
| 112 |
+
//
|
| 113 |
+
// Most users should not use Jet objects directly; a wrapper around Jet objects,
|
| 114 |
+
// which makes computing the derivative, gradient, or jacobian of templated
|
| 115 |
+
// functors simple, is in autodiff.h. Even autodiff.h should not be used
|
| 116 |
+
// directly; instead autodiff_cost_function.h is typically the file of interest.
|
| 117 |
+
//
|
| 118 |
+
// For the more mathematically inclined, this file implements first-order
|
| 119 |
+
// "jets". A 1st order jet is an element of the ring
|
| 120 |
+
//
|
| 121 |
+
// T[N] = T[t_1, ..., t_N] / (t_1, ..., t_N)^2
|
| 122 |
+
//
|
| 123 |
+
// which essentially means that each jet consists of a "scalar" value 'a' from T
|
| 124 |
+
// and a 1st order perturbation vector 'v' of length N:
|
| 125 |
+
//
|
| 126 |
+
// x = a + \sum_i v[i] t_i
|
| 127 |
+
//
|
| 128 |
+
// A shorthand is to write an element as x = a + u, where u is the perturbation.
|
| 129 |
+
// Then, the main point about the arithmetic of jets is that the product of
|
| 130 |
+
// perturbations is zero:
|
| 131 |
+
//
|
| 132 |
+
// (a + u) * (b + v) = ab + av + bu + uv
|
| 133 |
+
// = ab + (av + bu) + 0
|
| 134 |
+
//
|
| 135 |
+
// which is what operator* implements below. Addition is simpler:
|
| 136 |
+
//
|
| 137 |
+
// (a + u) + (b + v) = (a + b) + (u + v).
|
| 138 |
+
//
|
| 139 |
+
// The only remaining question is how to evaluate the function of a jet, for
|
| 140 |
+
// which we use the chain rule:
|
| 141 |
+
//
|
| 142 |
+
// f(a + u) = f(a) + f'(a) u
|
| 143 |
+
//
|
| 144 |
+
// where f'(a) is the (scalar) derivative of f at a.
|
| 145 |
+
//
|
| 146 |
+
// By pushing these things through sufficiently and suitably templated
|
| 147 |
+
// functions, we can do automatic differentiation. Just be sure to turn on
|
| 148 |
+
// function inlining and common-subexpression elimination, or it will be very
|
| 149 |
+
// slow!
|
| 150 |
+
//
|
| 151 |
+
// WARNING: Most Ceres users should not directly include this file or know the
|
| 152 |
+
// details of how jets work. Instead the suggested method for automatic
|
| 153 |
+
// derivatives is to use autodiff_cost_function.h, which is a wrapper around
|
| 154 |
+
// both jets.h and autodiff.h to make taking derivatives of cost functions for
|
| 155 |
+
// use in Ceres easier.
|
| 156 |
+
|
| 157 |
+
#ifndef CERES_PUBLIC_JET_H_
|
| 158 |
+
#define CERES_PUBLIC_JET_H_
|
| 159 |
+
|
| 160 |
+
#include <cmath>
|
| 161 |
+
#include <complex>
|
| 162 |
+
#include <iosfwd>
|
| 163 |
+
#include <iostream> // NOLINT
|
| 164 |
+
#include <limits>
|
| 165 |
+
#include <numeric>
|
| 166 |
+
#include <string>
|
| 167 |
+
#include <type_traits>
|
| 168 |
+
|
| 169 |
+
#include "Eigen/Core"
|
| 170 |
+
#include "ceres/internal/jet_traits.h"
|
| 171 |
+
#include "ceres/internal/port.h"
|
| 172 |
+
#include "ceres/jet_fwd.h"
|
| 173 |
+
|
| 174 |
+
// Here we provide partial specializations of std::common_type for the Jet class
|
| 175 |
+
// to allow determining a Jet type with a common underlying arithmetic type.
|
| 176 |
+
// Such an arithmetic type can be either a scalar or an another Jet. An example
|
| 177 |
+
// for a common type, say, between a float and a Jet<double, N> is a Jet<double,
|
| 178 |
+
// N> (i.e., std::common_type_t<float, ceres::Jet<double, N>> and
|
| 179 |
+
// ceres::Jet<double, N> refer to the same type.)
|
| 180 |
+
//
|
| 181 |
+
// The partial specialization are also used for determining compatible types by
|
| 182 |
+
// means of SFINAE and thus allow such types to be expressed as operands of
|
| 183 |
+
// logical comparison operators. Missing (partial) specialization of
|
| 184 |
+
// std::common_type for a particular (custom) type will therefore disable the
|
| 185 |
+
// use of comparison operators defined by Ceres.
|
| 186 |
+
//
|
| 187 |
+
// Since these partial specializations are used as SFINAE constraints, they
|
| 188 |
+
// enable standard promotion rules between various scalar types and consequently
|
| 189 |
+
// their use in comparison against a Jet without providing implicit
|
| 190 |
+
// conversions from a scalar, such as an int, to a Jet (see the implementation
|
| 191 |
+
// of logical comparison operators below).
|
| 192 |
+
|
| 193 |
+
template <typename T, int N, typename U>
|
| 194 |
+
struct std::common_type<T, ceres::Jet<U, N>> {
|
| 195 |
+
using type = ceres::Jet<common_type_t<T, U>, N>;
|
| 196 |
+
};
|
| 197 |
+
|
| 198 |
+
template <typename T, int N, typename U>
|
| 199 |
+
struct std::common_type<ceres::Jet<T, N>, U> {
|
| 200 |
+
using type = ceres::Jet<common_type_t<T, U>, N>;
|
| 201 |
+
};
|
| 202 |
+
|
| 203 |
+
template <typename T, int N, typename U>
|
| 204 |
+
struct std::common_type<ceres::Jet<T, N>, ceres::Jet<U, N>> {
|
| 205 |
+
using type = ceres::Jet<common_type_t<T, U>, N>;
|
| 206 |
+
};
|
| 207 |
+
|
| 208 |
+
namespace ceres {
|
| 209 |
+
|
| 210 |
+
template <typename T, int N>
|
| 211 |
+
struct Jet {
|
| 212 |
+
enum { DIMENSION = N };
|
| 213 |
+
using Scalar = T;
|
| 214 |
+
|
| 215 |
+
// Default-construct "a" because otherwise this can lead to false errors about
|
| 216 |
+
// uninitialized uses when other classes relying on default constructed T
|
| 217 |
+
// (where T is a Jet<T, N>). This usually only happens in opt mode. Note that
|
| 218 |
+
// the C++ standard mandates that e.g. default constructed doubles are
|
| 219 |
+
// initialized to 0.0; see sections 8.5 of the C++03 standard.
|
| 220 |
+
Jet() : a() { v.setConstant(Scalar()); }
|
| 221 |
+
|
| 222 |
+
// Constructor from scalar: a + 0.
|
| 223 |
+
explicit Jet(const T& value) {
|
| 224 |
+
a = value;
|
| 225 |
+
v.setConstant(Scalar());
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
// Constructor from scalar plus variable: a + t_i.
|
| 229 |
+
Jet(const T& value, int k) {
|
| 230 |
+
a = value;
|
| 231 |
+
v.setConstant(Scalar());
|
| 232 |
+
v[k] = T(1.0);
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
// Constructor from scalar and vector part
|
| 236 |
+
// The use of Eigen::DenseBase allows Eigen expressions
|
| 237 |
+
// to be passed in without being fully evaluated until
|
| 238 |
+
// they are assigned to v
|
| 239 |
+
template <typename Derived>
|
| 240 |
+
EIGEN_STRONG_INLINE Jet(const T& a, const Eigen::DenseBase<Derived>& v)
|
| 241 |
+
: a(a), v(v) {}
|
| 242 |
+
|
| 243 |
+
// Compound operators
|
| 244 |
+
Jet<T, N>& operator+=(const Jet<T, N>& y) {
|
| 245 |
+
*this = *this + y;
|
| 246 |
+
return *this;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
Jet<T, N>& operator-=(const Jet<T, N>& y) {
|
| 250 |
+
*this = *this - y;
|
| 251 |
+
return *this;
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
Jet<T, N>& operator*=(const Jet<T, N>& y) {
|
| 255 |
+
*this = *this * y;
|
| 256 |
+
return *this;
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
Jet<T, N>& operator/=(const Jet<T, N>& y) {
|
| 260 |
+
*this = *this / y;
|
| 261 |
+
return *this;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
// Compound with scalar operators.
|
| 265 |
+
Jet<T, N>& operator+=(const T& s) {
|
| 266 |
+
*this = *this + s;
|
| 267 |
+
return *this;
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
Jet<T, N>& operator-=(const T& s) {
|
| 271 |
+
*this = *this - s;
|
| 272 |
+
return *this;
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
Jet<T, N>& operator*=(const T& s) {
|
| 276 |
+
*this = *this * s;
|
| 277 |
+
return *this;
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
Jet<T, N>& operator/=(const T& s) {
|
| 281 |
+
*this = *this / s;
|
| 282 |
+
return *this;
|
| 283 |
+
}
|
| 284 |
+
|
| 285 |
+
// The scalar part.
|
| 286 |
+
T a;
|
| 287 |
+
|
| 288 |
+
// The infinitesimal part.
|
| 289 |
+
Eigen::Matrix<T, N, 1> v;
|
| 290 |
+
|
| 291 |
+
// This struct needs to have an Eigen aligned operator new as it contains
|
| 292 |
+
// fixed-size Eigen types.
|
| 293 |
+
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
| 294 |
+
};
|
| 295 |
+
|
| 296 |
+
// Unary +
|
| 297 |
+
template <typename T, int N>
|
| 298 |
+
inline Jet<T, N> const& operator+(const Jet<T, N>& f) {
|
| 299 |
+
return f;
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
// TODO(keir): Try adding __attribute__((always_inline)) to these functions to
|
| 303 |
+
// see if it causes a performance increase.
|
| 304 |
+
|
| 305 |
+
// Unary -
|
| 306 |
+
template <typename T, int N>
|
| 307 |
+
inline Jet<T, N> operator-(const Jet<T, N>& f) {
|
| 308 |
+
return Jet<T, N>(-f.a, -f.v);
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
// Binary +
|
| 312 |
+
template <typename T, int N>
|
| 313 |
+
inline Jet<T, N> operator+(const Jet<T, N>& f, const Jet<T, N>& g) {
|
| 314 |
+
return Jet<T, N>(f.a + g.a, f.v + g.v);
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
// Binary + with a scalar: x + s
|
| 318 |
+
template <typename T, int N>
|
| 319 |
+
inline Jet<T, N> operator+(const Jet<T, N>& f, T s) {
|
| 320 |
+
return Jet<T, N>(f.a + s, f.v);
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
// Binary + with a scalar: s + x
|
| 324 |
+
template <typename T, int N>
|
| 325 |
+
inline Jet<T, N> operator+(T s, const Jet<T, N>& f) {
|
| 326 |
+
return Jet<T, N>(f.a + s, f.v);
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
// Binary -
|
| 330 |
+
template <typename T, int N>
|
| 331 |
+
inline Jet<T, N> operator-(const Jet<T, N>& f, const Jet<T, N>& g) {
|
| 332 |
+
return Jet<T, N>(f.a - g.a, f.v - g.v);
|
| 333 |
+
}
|
| 334 |
+
|
| 335 |
+
// Binary - with a scalar: x - s
|
| 336 |
+
template <typename T, int N>
|
| 337 |
+
inline Jet<T, N> operator-(const Jet<T, N>& f, T s) {
|
| 338 |
+
return Jet<T, N>(f.a - s, f.v);
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
// Binary - with a scalar: s - x
|
| 342 |
+
template <typename T, int N>
|
| 343 |
+
inline Jet<T, N> operator-(T s, const Jet<T, N>& f) {
|
| 344 |
+
return Jet<T, N>(s - f.a, -f.v);
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
// Binary *
|
| 348 |
+
template <typename T, int N>
|
| 349 |
+
inline Jet<T, N> operator*(const Jet<T, N>& f, const Jet<T, N>& g) {
|
| 350 |
+
return Jet<T, N>(f.a * g.a, f.a * g.v + f.v * g.a);
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
// Binary * with a scalar: x * s
|
| 354 |
+
template <typename T, int N>
|
| 355 |
+
inline Jet<T, N> operator*(const Jet<T, N>& f, T s) {
|
| 356 |
+
return Jet<T, N>(f.a * s, f.v * s);
|
| 357 |
+
}
|
| 358 |
+
|
| 359 |
+
// Binary * with a scalar: s * x
|
| 360 |
+
template <typename T, int N>
|
| 361 |
+
inline Jet<T, N> operator*(T s, const Jet<T, N>& f) {
|
| 362 |
+
return Jet<T, N>(f.a * s, f.v * s);
|
| 363 |
+
}
|
| 364 |
+
|
| 365 |
+
// Binary /
|
| 366 |
+
template <typename T, int N>
|
| 367 |
+
inline Jet<T, N> operator/(const Jet<T, N>& f, const Jet<T, N>& g) {
|
| 368 |
+
// This uses:
|
| 369 |
+
//
|
| 370 |
+
// a + u (a + u)(b - v) (a + u)(b - v)
|
| 371 |
+
// ----- = -------------- = --------------
|
| 372 |
+
// b + v (b + v)(b - v) b^2
|
| 373 |
+
//
|
| 374 |
+
// which holds because v*v = 0.
|
| 375 |
+
const T g_a_inverse = T(1.0) / g.a;
|
| 376 |
+
const T f_a_by_g_a = f.a * g_a_inverse;
|
| 377 |
+
return Jet<T, N>(f_a_by_g_a, (f.v - f_a_by_g_a * g.v) * g_a_inverse);
|
| 378 |
+
}
|
| 379 |
+
|
| 380 |
+
// Binary / with a scalar: s / x
|
| 381 |
+
template <typename T, int N>
|
| 382 |
+
inline Jet<T, N> operator/(T s, const Jet<T, N>& g) {
|
| 383 |
+
const T minus_s_g_a_inverse2 = -s / (g.a * g.a);
|
| 384 |
+
return Jet<T, N>(s / g.a, g.v * minus_s_g_a_inverse2);
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
// Binary / with a scalar: x / s
|
| 388 |
+
template <typename T, int N>
|
| 389 |
+
inline Jet<T, N> operator/(const Jet<T, N>& f, T s) {
|
| 390 |
+
const T s_inverse = T(1.0) / s;
|
| 391 |
+
return Jet<T, N>(f.a * s_inverse, f.v * s_inverse);
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
// Binary comparison operators for both scalars and jets. At least one of the
|
| 395 |
+
// operands must be a Jet. Promotable scalars (e.g., int, float, double etc.)
|
| 396 |
+
// can appear on either side of the operator. std::common_type_t is used as an
|
| 397 |
+
// SFINAE constraint to selectively enable compatible operand types. This allows
|
| 398 |
+
// comparison, for instance, against int literals without implicit conversion.
|
| 399 |
+
// In case the Jet arithmetic type is a Jet itself, a recursive expansion of Jet
|
| 400 |
+
// value is performed.
|
| 401 |
+
#define CERES_DEFINE_JET_COMPARISON_OPERATOR(op) \
|
| 402 |
+
template <typename Lhs, \
|
| 403 |
+
typename Rhs, \
|
| 404 |
+
std::enable_if_t<PromotableJetOperands_v<Lhs, Rhs>>* = nullptr> \
|
| 405 |
+
constexpr bool operator op(const Lhs& f, const Rhs& g) noexcept( \
|
| 406 |
+
noexcept(internal::AsScalar(f) op internal::AsScalar(g))) { \
|
| 407 |
+
using internal::AsScalar; \
|
| 408 |
+
return AsScalar(f) op AsScalar(g); \
|
| 409 |
+
}
|
| 410 |
+
CERES_DEFINE_JET_COMPARISON_OPERATOR(<) // NOLINT
|
| 411 |
+
CERES_DEFINE_JET_COMPARISON_OPERATOR(<=) // NOLINT
|
| 412 |
+
CERES_DEFINE_JET_COMPARISON_OPERATOR(>) // NOLINT
|
| 413 |
+
CERES_DEFINE_JET_COMPARISON_OPERATOR(>=) // NOLINT
|
| 414 |
+
CERES_DEFINE_JET_COMPARISON_OPERATOR(==) // NOLINT
|
| 415 |
+
CERES_DEFINE_JET_COMPARISON_OPERATOR(!=) // NOLINT
|
| 416 |
+
#undef CERES_DEFINE_JET_COMPARISON_OPERATOR
|
| 417 |
+
|
| 418 |
+
// Pull some functions from namespace std.
|
| 419 |
+
//
|
| 420 |
+
// This is necessary because we want to use the same name (e.g. 'sqrt') for
|
| 421 |
+
// double-valued and Jet-valued functions, but we are not allowed to put
|
| 422 |
+
// Jet-valued functions inside namespace std.
|
| 423 |
+
using std::abs;
|
| 424 |
+
using std::acos;
|
| 425 |
+
using std::asin;
|
| 426 |
+
using std::atan;
|
| 427 |
+
using std::atan2;
|
| 428 |
+
using std::cbrt;
|
| 429 |
+
using std::ceil;
|
| 430 |
+
using std::copysign;
|
| 431 |
+
using std::cos;
|
| 432 |
+
using std::cosh;
|
| 433 |
+
using std::erf;
|
| 434 |
+
using std::erfc;
|
| 435 |
+
using std::exp;
|
| 436 |
+
using std::exp2;
|
| 437 |
+
using std::expm1;
|
| 438 |
+
using std::fdim;
|
| 439 |
+
using std::floor;
|
| 440 |
+
using std::fma;
|
| 441 |
+
using std::fmax;
|
| 442 |
+
using std::fmin;
|
| 443 |
+
using std::fpclassify;
|
| 444 |
+
using std::hypot;
|
| 445 |
+
using std::isfinite;
|
| 446 |
+
using std::isinf;
|
| 447 |
+
using std::isnan;
|
| 448 |
+
using std::isnormal;
|
| 449 |
+
using std::log;
|
| 450 |
+
using std::log10;
|
| 451 |
+
using std::log1p;
|
| 452 |
+
using std::log2;
|
| 453 |
+
using std::norm;
|
| 454 |
+
using std::pow;
|
| 455 |
+
using std::signbit;
|
| 456 |
+
using std::sin;
|
| 457 |
+
using std::sinh;
|
| 458 |
+
using std::sqrt;
|
| 459 |
+
using std::tan;
|
| 460 |
+
using std::tanh;
|
| 461 |
+
|
| 462 |
+
// MSVC (up to 1930) defines quiet comparison functions as template functions
|
| 463 |
+
// which causes compilation errors due to ambiguity in the template parameter
|
| 464 |
+
// type resolution for using declarations in the ceres namespace. Workaround the
|
| 465 |
+
// issue by defining specific overload and bypass MSVC standard library
|
| 466 |
+
// definitions.
|
| 467 |
+
#if defined(_MSC_VER)
|
| 468 |
+
inline bool isgreater(double lhs,
|
| 469 |
+
double rhs) noexcept(noexcept(std::isgreater(lhs, rhs))) {
|
| 470 |
+
return std::isgreater(lhs, rhs);
|
| 471 |
+
}
|
| 472 |
+
inline bool isless(double lhs,
|
| 473 |
+
double rhs) noexcept(noexcept(std::isless(lhs, rhs))) {
|
| 474 |
+
return std::isless(lhs, rhs);
|
| 475 |
+
}
|
| 476 |
+
inline bool islessequal(double lhs,
|
| 477 |
+
double rhs) noexcept(noexcept(std::islessequal(lhs,
|
| 478 |
+
rhs))) {
|
| 479 |
+
return std::islessequal(lhs, rhs);
|
| 480 |
+
}
|
| 481 |
+
inline bool isgreaterequal(double lhs, double rhs) noexcept(
|
| 482 |
+
noexcept(std::isgreaterequal(lhs, rhs))) {
|
| 483 |
+
return std::isgreaterequal(lhs, rhs);
|
| 484 |
+
}
|
| 485 |
+
inline bool islessgreater(double lhs, double rhs) noexcept(
|
| 486 |
+
noexcept(std::islessgreater(lhs, rhs))) {
|
| 487 |
+
return std::islessgreater(lhs, rhs);
|
| 488 |
+
}
|
| 489 |
+
inline bool isunordered(double lhs,
|
| 490 |
+
double rhs) noexcept(noexcept(std::isunordered(lhs,
|
| 491 |
+
rhs))) {
|
| 492 |
+
return std::isunordered(lhs, rhs);
|
| 493 |
+
}
|
| 494 |
+
#else
|
| 495 |
+
using std::isgreater;
|
| 496 |
+
using std::isgreaterequal;
|
| 497 |
+
using std::isless;
|
| 498 |
+
using std::islessequal;
|
| 499 |
+
using std::islessgreater;
|
| 500 |
+
using std::isunordered;
|
| 501 |
+
#endif
|
| 502 |
+
|
| 503 |
+
#ifdef CERES_HAS_CPP20
|
| 504 |
+
using std::lerp;
|
| 505 |
+
using std::midpoint;
|
| 506 |
+
#endif // defined(CERES_HAS_CPP20)
|
| 507 |
+
|
| 508 |
+
// Legacy names from pre-C++11 days.
|
| 509 |
+
// clang-format off
|
| 510 |
+
CERES_DEPRECATED_WITH_MSG("ceres::IsFinite will be removed in a future Ceres Solver release. Please use ceres::isfinite.")
|
| 511 |
+
inline bool IsFinite(double x) { return std::isfinite(x); }
|
| 512 |
+
CERES_DEPRECATED_WITH_MSG("ceres::IsInfinite will be removed in a future Ceres Solver release. Please use ceres::isinf.")
|
| 513 |
+
inline bool IsInfinite(double x) { return std::isinf(x); }
|
| 514 |
+
CERES_DEPRECATED_WITH_MSG("ceres::IsNaN will be removed in a future Ceres Solver release. Please use ceres::isnan.")
|
| 515 |
+
inline bool IsNaN(double x) { return std::isnan(x); }
|
| 516 |
+
CERES_DEPRECATED_WITH_MSG("ceres::IsNormal will be removed in a future Ceres Solver release. Please use ceres::isnormal.")
|
| 517 |
+
inline bool IsNormal(double x) { return std::isnormal(x); }
|
| 518 |
+
// clang-format on
|
| 519 |
+
|
| 520 |
+
// In general, f(a + h) ~= f(a) + f'(a) h, via the chain rule.
|
| 521 |
+
|
| 522 |
+
// abs(x + h) ~= abs(x) + sgn(x)h
|
| 523 |
+
template <typename T, int N>
|
| 524 |
+
inline Jet<T, N> abs(const Jet<T, N>& f) {
|
| 525 |
+
return Jet<T, N>(abs(f.a), copysign(T(1), f.a) * f.v);
|
| 526 |
+
}
|
| 527 |
+
|
| 528 |
+
// copysign(a, b) composes a float with the magnitude of a and the sign of b.
|
| 529 |
+
// Therefore, the function can be formally defined as
|
| 530 |
+
//
|
| 531 |
+
// copysign(a, b) = sgn(b)|a|
|
| 532 |
+
//
|
| 533 |
+
// where
|
| 534 |
+
//
|
| 535 |
+
// d/dx |x| = sgn(x)
|
| 536 |
+
// d/dx sgn(x) = 2δ(x)
|
| 537 |
+
//
|
| 538 |
+
// sgn(x) being the signum function. Differentiating copysign(a, b) with respect
|
| 539 |
+
// to a and b gives:
|
| 540 |
+
//
|
| 541 |
+
// d/da sgn(b)|a| = sgn(a) sgn(b)
|
| 542 |
+
// d/db sgn(b)|a| = 2|a|δ(b)
|
| 543 |
+
//
|
| 544 |
+
// with the dual representation given by
|
| 545 |
+
//
|
| 546 |
+
// copysign(a + da, b + db) ~= sgn(b)|a| + (sgn(a)sgn(b) da + 2|a|δ(b) db)
|
| 547 |
+
//
|
| 548 |
+
// where δ(b) is the Dirac delta function.
|
| 549 |
+
template <typename T, int N>
|
| 550 |
+
inline Jet<T, N> copysign(const Jet<T, N>& f, const Jet<T, N> g) {
|
| 551 |
+
// The Dirac delta function δ(b) is undefined at b=0 (here it's
|
| 552 |
+
// infinite) and 0 everywhere else.
|
| 553 |
+
T d = fpclassify(g) == FP_ZERO ? std::numeric_limits<T>::infinity() : T(0);
|
| 554 |
+
T sa = copysign(T(1), f.a); // sgn(a)
|
| 555 |
+
T sb = copysign(T(1), g.a); // sgn(b)
|
| 556 |
+
// The second part of the infinitesimal is 2|a|δ(b) which is either infinity
|
| 557 |
+
// or 0 unless a or any of the values of the b infinitesimal are 0. In the
|
| 558 |
+
// latter case, the corresponding values become NaNs (multiplying 0 by
|
| 559 |
+
// infinity gives NaN). We drop the constant factor 2 since it does not change
|
| 560 |
+
// the result (its values will still be either 0, infinity or NaN).
|
| 561 |
+
return Jet<T, N>(copysign(f.a, g.a), sa * sb * f.v + abs(f.a) * d * g.v);
|
| 562 |
+
}
|
| 563 |
+
|
| 564 |
+
// log(a + h) ~= log(a) + h / a
|
| 565 |
+
template <typename T, int N>
|
| 566 |
+
inline Jet<T, N> log(const Jet<T, N>& f) {
|
| 567 |
+
const T a_inverse = T(1.0) / f.a;
|
| 568 |
+
return Jet<T, N>(log(f.a), f.v * a_inverse);
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
// log10(a + h) ~= log10(a) + h / (a log(10))
|
| 572 |
+
template <typename T, int N>
|
| 573 |
+
inline Jet<T, N> log10(const Jet<T, N>& f) {
|
| 574 |
+
// Most compilers will expand log(10) to a constant.
|
| 575 |
+
const T a_inverse = T(1.0) / (f.a * log(T(10.0)));
|
| 576 |
+
return Jet<T, N>(log10(f.a), f.v * a_inverse);
|
| 577 |
+
}
|
| 578 |
+
|
| 579 |
+
// log1p(a + h) ~= log1p(a) + h / (1 + a)
|
| 580 |
+
template <typename T, int N>
|
| 581 |
+
inline Jet<T, N> log1p(const Jet<T, N>& f) {
|
| 582 |
+
const T a_inverse = T(1.0) / (T(1.0) + f.a);
|
| 583 |
+
return Jet<T, N>(log1p(f.a), f.v * a_inverse);
|
| 584 |
+
}
|
| 585 |
+
|
| 586 |
+
// exp(a + h) ~= exp(a) + exp(a) h
|
| 587 |
+
template <typename T, int N>
|
| 588 |
+
inline Jet<T, N> exp(const Jet<T, N>& f) {
|
| 589 |
+
const T tmp = exp(f.a);
|
| 590 |
+
return Jet<T, N>(tmp, tmp * f.v);
|
| 591 |
+
}
|
| 592 |
+
|
| 593 |
+
// expm1(a + h) ~= expm1(a) + exp(a) h
|
| 594 |
+
template <typename T, int N>
|
| 595 |
+
inline Jet<T, N> expm1(const Jet<T, N>& f) {
|
| 596 |
+
const T tmp = expm1(f.a);
|
| 597 |
+
const T expa = tmp + T(1.0); // exp(a) = expm1(a) + 1
|
| 598 |
+
return Jet<T, N>(tmp, expa * f.v);
|
| 599 |
+
}
|
| 600 |
+
|
| 601 |
+
// sqrt(a + h) ~= sqrt(a) + h / (2 sqrt(a))
|
| 602 |
+
template <typename T, int N>
|
| 603 |
+
inline Jet<T, N> sqrt(const Jet<T, N>& f) {
|
| 604 |
+
const T tmp = sqrt(f.a);
|
| 605 |
+
const T two_a_inverse = T(1.0) / (T(2.0) * tmp);
|
| 606 |
+
return Jet<T, N>(tmp, f.v * two_a_inverse);
|
| 607 |
+
}
|
| 608 |
+
|
| 609 |
+
// cos(a + h) ~= cos(a) - sin(a) h
|
| 610 |
+
template <typename T, int N>
|
| 611 |
+
inline Jet<T, N> cos(const Jet<T, N>& f) {
|
| 612 |
+
return Jet<T, N>(cos(f.a), -sin(f.a) * f.v);
|
| 613 |
+
}
|
| 614 |
+
|
| 615 |
+
// acos(a + h) ~= acos(a) - 1 / sqrt(1 - a^2) h
|
| 616 |
+
template <typename T, int N>
|
| 617 |
+
inline Jet<T, N> acos(const Jet<T, N>& f) {
|
| 618 |
+
const T tmp = -T(1.0) / sqrt(T(1.0) - f.a * f.a);
|
| 619 |
+
return Jet<T, N>(acos(f.a), tmp * f.v);
|
| 620 |
+
}
|
| 621 |
+
|
| 622 |
+
// sin(a + h) ~= sin(a) + cos(a) h
|
| 623 |
+
template <typename T, int N>
|
| 624 |
+
inline Jet<T, N> sin(const Jet<T, N>& f) {
|
| 625 |
+
return Jet<T, N>(sin(f.a), cos(f.a) * f.v);
|
| 626 |
+
}
|
| 627 |
+
|
| 628 |
+
// asin(a + h) ~= asin(a) + 1 / sqrt(1 - a^2) h
|
| 629 |
+
template <typename T, int N>
|
| 630 |
+
inline Jet<T, N> asin(const Jet<T, N>& f) {
|
| 631 |
+
const T tmp = T(1.0) / sqrt(T(1.0) - f.a * f.a);
|
| 632 |
+
return Jet<T, N>(asin(f.a), tmp * f.v);
|
| 633 |
+
}
|
| 634 |
+
|
| 635 |
+
// tan(a + h) ~= tan(a) + (1 + tan(a)^2) h
|
| 636 |
+
template <typename T, int N>
|
| 637 |
+
inline Jet<T, N> tan(const Jet<T, N>& f) {
|
| 638 |
+
const T tan_a = tan(f.a);
|
| 639 |
+
const T tmp = T(1.0) + tan_a * tan_a;
|
| 640 |
+
return Jet<T, N>(tan_a, tmp * f.v);
|
| 641 |
+
}
|
| 642 |
+
|
| 643 |
+
// atan(a + h) ~= atan(a) + 1 / (1 + a^2) h
|
| 644 |
+
template <typename T, int N>
|
| 645 |
+
inline Jet<T, N> atan(const Jet<T, N>& f) {
|
| 646 |
+
const T tmp = T(1.0) / (T(1.0) + f.a * f.a);
|
| 647 |
+
return Jet<T, N>(atan(f.a), tmp * f.v);
|
| 648 |
+
}
|
| 649 |
+
|
| 650 |
+
// sinh(a + h) ~= sinh(a) + cosh(a) h
|
| 651 |
+
template <typename T, int N>
|
| 652 |
+
inline Jet<T, N> sinh(const Jet<T, N>& f) {
|
| 653 |
+
return Jet<T, N>(sinh(f.a), cosh(f.a) * f.v);
|
| 654 |
+
}
|
| 655 |
+
|
| 656 |
+
// cosh(a + h) ~= cosh(a) + sinh(a) h
|
| 657 |
+
template <typename T, int N>
|
| 658 |
+
inline Jet<T, N> cosh(const Jet<T, N>& f) {
|
| 659 |
+
return Jet<T, N>(cosh(f.a), sinh(f.a) * f.v);
|
| 660 |
+
}
|
| 661 |
+
|
| 662 |
+
// tanh(a + h) ~= tanh(a) + (1 - tanh(a)^2) h
|
| 663 |
+
template <typename T, int N>
|
| 664 |
+
inline Jet<T, N> tanh(const Jet<T, N>& f) {
|
| 665 |
+
const T tanh_a = tanh(f.a);
|
| 666 |
+
const T tmp = T(1.0) - tanh_a * tanh_a;
|
| 667 |
+
return Jet<T, N>(tanh_a, tmp * f.v);
|
| 668 |
+
}
|
| 669 |
+
|
| 670 |
+
// The floor function should be used with extreme care as this operation will
|
| 671 |
+
// result in a zero derivative which provides no information to the solver.
|
| 672 |
+
//
|
| 673 |
+
// floor(a + h) ~= floor(a) + 0
|
| 674 |
+
template <typename T, int N>
|
| 675 |
+
inline Jet<T, N> floor(const Jet<T, N>& f) {
|
| 676 |
+
return Jet<T, N>(floor(f.a));
|
| 677 |
+
}
|
| 678 |
+
|
| 679 |
+
// The ceil function should be used with extreme care as this operation will
|
| 680 |
+
// result in a zero derivative which provides no information to the solver.
|
| 681 |
+
//
|
| 682 |
+
// ceil(a + h) ~= ceil(a) + 0
|
| 683 |
+
template <typename T, int N>
|
| 684 |
+
inline Jet<T, N> ceil(const Jet<T, N>& f) {
|
| 685 |
+
return Jet<T, N>(ceil(f.a));
|
| 686 |
+
}
|
| 687 |
+
|
| 688 |
+
// Some new additions to C++11:
|
| 689 |
+
|
| 690 |
+
// cbrt(a + h) ~= cbrt(a) + h / (3 a ^ (2/3))
|
| 691 |
+
template <typename T, int N>
|
| 692 |
+
inline Jet<T, N> cbrt(const Jet<T, N>& f) {
|
| 693 |
+
const T derivative = T(1.0) / (T(3.0) * cbrt(f.a * f.a));
|
| 694 |
+
return Jet<T, N>(cbrt(f.a), f.v * derivative);
|
| 695 |
+
}
|
| 696 |
+
|
| 697 |
+
// exp2(x + h) = 2^(x+h) ~= 2^x + h*2^x*log(2)
|
| 698 |
+
template <typename T, int N>
|
| 699 |
+
inline Jet<T, N> exp2(const Jet<T, N>& f) {
|
| 700 |
+
const T tmp = exp2(f.a);
|
| 701 |
+
const T derivative = tmp * log(T(2));
|
| 702 |
+
return Jet<T, N>(tmp, f.v * derivative);
|
| 703 |
+
}
|
| 704 |
+
|
| 705 |
+
// log2(x + h) ~= log2(x) + h / (x * log(2))
|
| 706 |
+
template <typename T, int N>
|
| 707 |
+
inline Jet<T, N> log2(const Jet<T, N>& f) {
|
| 708 |
+
const T derivative = T(1.0) / (f.a * log(T(2)));
|
| 709 |
+
return Jet<T, N>(log2(f.a), f.v * derivative);
|
| 710 |
+
}
|
| 711 |
+
|
| 712 |
+
// Like sqrt(x^2 + y^2),
|
| 713 |
+
// but acts to prevent underflow/overflow for small/large x/y.
|
| 714 |
+
// Note that the function is non-smooth at x=y=0,
|
| 715 |
+
// so the derivative is undefined there.
|
| 716 |
+
template <typename T, int N>
|
| 717 |
+
inline Jet<T, N> hypot(const Jet<T, N>& x, const Jet<T, N>& y) {
|
| 718 |
+
// d/da sqrt(a) = 0.5 / sqrt(a)
|
| 719 |
+
// d/dx x^2 + y^2 = 2x
|
| 720 |
+
// So by the chain rule:
|
| 721 |
+
// d/dx sqrt(x^2 + y^2) = 0.5 / sqrt(x^2 + y^2) * 2x = x / sqrt(x^2 + y^2)
|
| 722 |
+
// d/dy sqrt(x^2 + y^2) = y / sqrt(x^2 + y^2)
|
| 723 |
+
const T tmp = hypot(x.a, y.a);
|
| 724 |
+
return Jet<T, N>(tmp, x.a / tmp * x.v + y.a / tmp * y.v);
|
| 725 |
+
}
|
| 726 |
+
|
| 727 |
+
#ifdef CERES_HAS_CPP17
|
| 728 |
+
// Like sqrt(x^2 + y^2 + z^2),
|
| 729 |
+
// but acts to prevent underflow/overflow for small/large x/y/z.
|
| 730 |
+
// Note that the function is non-smooth at x=y=z=0,
|
| 731 |
+
// so the derivative is undefined there.
|
| 732 |
+
template <typename T, int N>
|
| 733 |
+
inline Jet<T, N> hypot(const Jet<T, N>& x,
|
| 734 |
+
const Jet<T, N>& y,
|
| 735 |
+
const Jet<T, N>& z) {
|
| 736 |
+
// d/da sqrt(a) = 0.5 / sqrt(a)
|
| 737 |
+
// d/dx x^2 + y^2 + z^2 = 2x
|
| 738 |
+
// So by the chain rule:
|
| 739 |
+
// d/dx sqrt(x^2 + y^2 + z^2)
|
| 740 |
+
// = 0.5 / sqrt(x^2 + y^2 + z^2) * 2x
|
| 741 |
+
// = x / sqrt(x^2 + y^2 + z^2)
|
| 742 |
+
// d/dy sqrt(x^2 + y^2 + z^2) = y / sqrt(x^2 + y^2 + z^2)
|
| 743 |
+
// d/dz sqrt(x^2 + y^2 + z^2) = z / sqrt(x^2 + y^2 + z^2)
|
| 744 |
+
const T tmp = hypot(x.a, y.a, z.a);
|
| 745 |
+
return Jet<T, N>(tmp, x.a / tmp * x.v + y.a / tmp * y.v + z.a / tmp * z.v);
|
| 746 |
+
}
|
| 747 |
+
#endif // defined(CERES_HAS_CPP17)
|
| 748 |
+
|
| 749 |
+
// Like x * y + z but rounded only once.
|
| 750 |
+
template <typename T, int N>
|
| 751 |
+
inline Jet<T, N> fma(const Jet<T, N>& x,
|
| 752 |
+
const Jet<T, N>& y,
|
| 753 |
+
const Jet<T, N>& z) {
|
| 754 |
+
// d/dx fma(x, y, z) = y
|
| 755 |
+
// d/dy fma(x, y, z) = x
|
| 756 |
+
// d/dz fma(x, y, z) = 1
|
| 757 |
+
return Jet<T, N>(fma(x.a, y.a, z.a), y.a * x.v + x.a * y.v + z.v);
|
| 758 |
+
}
|
| 759 |
+
|
| 760 |
+
// Returns the larger of the two arguments. NaNs are treated as missing data.
|
| 761 |
+
//
|
| 762 |
+
// NOTE: This function is NOT subject to any of the error conditions specified
|
| 763 |
+
// in `math_errhandling`.
|
| 764 |
+
template <typename Lhs,
|
| 765 |
+
typename Rhs,
|
| 766 |
+
std::enable_if_t<CompatibleJetOperands_v<Lhs, Rhs>>* = nullptr>
|
| 767 |
+
inline decltype(auto) fmax(const Lhs& f, const Rhs& g) {
|
| 768 |
+
using J = std::common_type_t<Lhs, Rhs>;
|
| 769 |
+
return (isnan(g) || isgreater(f, g)) ? J{f} : J{g};
|
| 770 |
+
}
|
| 771 |
+
|
| 772 |
+
// Returns the smaller of the two arguments. NaNs are treated as missing data.
|
| 773 |
+
//
|
| 774 |
+
// NOTE: This function is NOT subject to any of the error conditions specified
|
| 775 |
+
// in `math_errhandling`.
|
| 776 |
+
template <typename Lhs,
|
| 777 |
+
typename Rhs,
|
| 778 |
+
std::enable_if_t<CompatibleJetOperands_v<Lhs, Rhs>>* = nullptr>
|
| 779 |
+
inline decltype(auto) fmin(const Lhs& f, const Rhs& g) {
|
| 780 |
+
using J = std::common_type_t<Lhs, Rhs>;
|
| 781 |
+
return (isnan(f) || isless(g, f)) ? J{g} : J{f};
|
| 782 |
+
}
|
| 783 |
+
|
| 784 |
+
// Returns the positive difference (f - g) of two arguments and zero if f <= g.
|
| 785 |
+
// If at least one argument is NaN, a NaN is return.
|
| 786 |
+
//
|
| 787 |
+
// NOTE At least one of the argument types must be a Jet, the other one can be a
|
| 788 |
+
// scalar. In case both arguments are Jets, their dimensionality must match.
|
| 789 |
+
template <typename Lhs,
|
| 790 |
+
typename Rhs,
|
| 791 |
+
std::enable_if_t<CompatibleJetOperands_v<Lhs, Rhs>>* = nullptr>
|
| 792 |
+
inline decltype(auto) fdim(const Lhs& f, const Rhs& g) {
|
| 793 |
+
using J = std::common_type_t<Lhs, Rhs>;
|
| 794 |
+
if (isnan(f) || isnan(g)) {
|
| 795 |
+
return std::numeric_limits<J>::quiet_NaN();
|
| 796 |
+
}
|
| 797 |
+
return isgreater(f, g) ? J{f - g} : J{};
|
| 798 |
+
}
|
| 799 |
+
|
| 800 |
+
// erf is defined as an integral that cannot be expressed analytically
|
| 801 |
+
// however, the derivative is trivial to compute
|
| 802 |
+
// erf(x + h) = erf(x) + h * 2*exp(-x^2)/sqrt(pi)
|
| 803 |
+
template <typename T, int N>
|
| 804 |
+
inline Jet<T, N> erf(const Jet<T, N>& x) {
|
| 805 |
+
// We evaluate the constant as follows:
|
| 806 |
+
// 2 / sqrt(pi) = 1 / sqrt(atan(1.))
|
| 807 |
+
// On POSIX sytems it is defined as M_2_SQRTPI, but this is not
|
| 808 |
+
// portable and the type may not be T. The above expression
|
| 809 |
+
// evaluates to full precision with IEEE arithmetic and, since it's
|
| 810 |
+
// constant, the compiler can generate exactly the same code. gcc
|
| 811 |
+
// does so even at -O0.
|
| 812 |
+
return Jet<T, N>(erf(x.a), x.v * exp(-x.a * x.a) * (T(1) / sqrt(atan(T(1)))));
|
| 813 |
+
}
|
| 814 |
+
|
| 815 |
+
// erfc(x) = 1-erf(x)
|
| 816 |
+
// erfc(x + h) = erfc(x) + h * (-2*exp(-x^2)/sqrt(pi))
|
| 817 |
+
template <typename T, int N>
|
| 818 |
+
inline Jet<T, N> erfc(const Jet<T, N>& x) {
|
| 819 |
+
// See in erf() above for the evaluation of the constant in the derivative.
|
| 820 |
+
return Jet<T, N>(erfc(x.a),
|
| 821 |
+
-x.v * exp(-x.a * x.a) * (T(1) / sqrt(atan(T(1)))));
|
| 822 |
+
}
|
| 823 |
+
|
| 824 |
+
// Bessel functions of the first kind with integer order equal to 0, 1, n.
|
| 825 |
+
//
|
| 826 |
+
// Microsoft has deprecated the j[0,1,n]() POSIX Bessel functions in favour of
|
| 827 |
+
// _j[0,1,n](). Where available on MSVC, use _j[0,1,n]() to avoid deprecated
|
| 828 |
+
// function errors in client code (the specific warning is suppressed when
|
| 829 |
+
// Ceres itself is built).
|
| 830 |
+
inline double BesselJ0(double x) {
|
| 831 |
+
#if defined(CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
|
| 832 |
+
return _j0(x);
|
| 833 |
+
#else
|
| 834 |
+
return j0(x);
|
| 835 |
+
#endif
|
| 836 |
+
}
|
| 837 |
+
inline double BesselJ1(double x) {
|
| 838 |
+
#if defined(CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
|
| 839 |
+
return _j1(x);
|
| 840 |
+
#else
|
| 841 |
+
return j1(x);
|
| 842 |
+
#endif
|
| 843 |
+
}
|
| 844 |
+
inline double BesselJn(int n, double x) {
|
| 845 |
+
#if defined(CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
|
| 846 |
+
return _jn(n, x);
|
| 847 |
+
#else
|
| 848 |
+
return jn(n, x);
|
| 849 |
+
#endif
|
| 850 |
+
}
|
| 851 |
+
|
| 852 |
+
// For the formulae of the derivatives of the Bessel functions see the book:
|
| 853 |
+
// Olver, Lozier, Boisvert, Clark, NIST Handbook of Mathematical Functions,
|
| 854 |
+
// Cambridge University Press 2010.
|
| 855 |
+
//
|
| 856 |
+
// Formulae are also available at http://dlmf.nist.gov
|
| 857 |
+
|
| 858 |
+
// See formula http://dlmf.nist.gov/10.6#E3
|
| 859 |
+
// j0(a + h) ~= j0(a) - j1(a) h
|
| 860 |
+
template <typename T, int N>
|
| 861 |
+
inline Jet<T, N> BesselJ0(const Jet<T, N>& f) {
|
| 862 |
+
return Jet<T, N>(BesselJ0(f.a), -BesselJ1(f.a) * f.v);
|
| 863 |
+
}
|
| 864 |
+
|
| 865 |
+
// See formula http://dlmf.nist.gov/10.6#E1
|
| 866 |
+
// j1(a + h) ~= j1(a) + 0.5 ( j0(a) - j2(a) ) h
|
| 867 |
+
template <typename T, int N>
|
| 868 |
+
inline Jet<T, N> BesselJ1(const Jet<T, N>& f) {
|
| 869 |
+
return Jet<T, N>(BesselJ1(f.a),
|
| 870 |
+
T(0.5) * (BesselJ0(f.a) - BesselJn(2, f.a)) * f.v);
|
| 871 |
+
}
|
| 872 |
+
|
| 873 |
+
// See formula http://dlmf.nist.gov/10.6#E1
|
| 874 |
+
// j_n(a + h) ~= j_n(a) + 0.5 ( j_{n-1}(a) - j_{n+1}(a) ) h
|
| 875 |
+
template <typename T, int N>
|
| 876 |
+
inline Jet<T, N> BesselJn(int n, const Jet<T, N>& f) {
|
| 877 |
+
return Jet<T, N>(
|
| 878 |
+
BesselJn(n, f.a),
|
| 879 |
+
T(0.5) * (BesselJn(n - 1, f.a) - BesselJn(n + 1, f.a)) * f.v);
|
| 880 |
+
}
|
| 881 |
+
|
| 882 |
+
// Classification and comparison functionality referencing only the scalar part
|
| 883 |
+
// of a Jet. To classify the derivatives (e.g., for sanity checks), the dual
|
| 884 |
+
// part should be referenced explicitly. For instance, to check whether the
|
| 885 |
+
// derivatives of a Jet 'f' are reasonable, one can use
|
| 886 |
+
//
|
| 887 |
+
// isfinite(f.v.array()).all()
|
| 888 |
+
// !isnan(f.v.array()).any()
|
| 889 |
+
//
|
| 890 |
+
// etc., depending on the desired semantics.
|
| 891 |
+
//
|
| 892 |
+
// NOTE: Floating-point classification and comparison functions and operators
|
| 893 |
+
// should be used with care as no derivatives can be propagated by such
|
| 894 |
+
// functions directly but only by expressions resulting from corresponding
|
| 895 |
+
// conditional statements. At the same time, conditional statements can possibly
|
| 896 |
+
// introduce a discontinuity in the cost function making it impossible to
|
| 897 |
+
// evaluate its derivative and thus the optimization problem intractable.
|
| 898 |
+
|
| 899 |
+
// Determines whether the scalar part of the Jet is finite.
|
| 900 |
+
template <typename T, int N>
|
| 901 |
+
inline bool isfinite(const Jet<T, N>& f) {
|
| 902 |
+
return isfinite(f.a);
|
| 903 |
+
}
|
| 904 |
+
|
| 905 |
+
// Determines whether the scalar part of the Jet is infinite.
|
| 906 |
+
template <typename T, int N>
|
| 907 |
+
inline bool isinf(const Jet<T, N>& f) {
|
| 908 |
+
return isinf(f.a);
|
| 909 |
+
}
|
| 910 |
+
|
| 911 |
+
// Determines whether the scalar part of the Jet is NaN.
|
| 912 |
+
template <typename T, int N>
|
| 913 |
+
inline bool isnan(const Jet<T, N>& f) {
|
| 914 |
+
return isnan(f.a);
|
| 915 |
+
}
|
| 916 |
+
|
| 917 |
+
// Determines whether the scalar part of the Jet is neither zero, subnormal,
|
| 918 |
+
// infinite, nor NaN.
|
| 919 |
+
template <typename T, int N>
|
| 920 |
+
inline bool isnormal(const Jet<T, N>& f) {
|
| 921 |
+
return isnormal(f.a);
|
| 922 |
+
}
|
| 923 |
+
|
| 924 |
+
// Determines whether the scalar part of the Jet f is less than the scalar
|
| 925 |
+
// part of g.
|
| 926 |
+
//
|
| 927 |
+
// NOTE: This function does NOT set any floating-point exceptions.
|
| 928 |
+
template <typename Lhs,
|
| 929 |
+
typename Rhs,
|
| 930 |
+
std::enable_if_t<CompatibleJetOperands_v<Lhs, Rhs>>* = nullptr>
|
| 931 |
+
inline bool isless(const Lhs& f, const Rhs& g) {
|
| 932 |
+
using internal::AsScalar;
|
| 933 |
+
return isless(AsScalar(f), AsScalar(g));
|
| 934 |
+
}
|
| 935 |
+
|
| 936 |
+
// Determines whether the scalar part of the Jet f is greater than the scalar
|
| 937 |
+
// part of g.
|
| 938 |
+
//
|
| 939 |
+
// NOTE: This function does NOT set any floating-point exceptions.
|
| 940 |
+
template <typename Lhs,
|
| 941 |
+
typename Rhs,
|
| 942 |
+
std::enable_if_t<CompatibleJetOperands_v<Lhs, Rhs>>* = nullptr>
|
| 943 |
+
inline bool isgreater(const Lhs& f, const Rhs& g) {
|
| 944 |
+
using internal::AsScalar;
|
| 945 |
+
return isgreater(AsScalar(f), AsScalar(g));
|
| 946 |
+
}
|
| 947 |
+
|
| 948 |
+
// Determines whether the scalar part of the Jet f is less than or equal to the
|
| 949 |
+
// scalar part of g.
|
| 950 |
+
//
|
| 951 |
+
// NOTE: This function does NOT set any floating-point exceptions.
|
| 952 |
+
template <typename Lhs,
|
| 953 |
+
typename Rhs,
|
| 954 |
+
std::enable_if_t<CompatibleJetOperands_v<Lhs, Rhs>>* = nullptr>
|
| 955 |
+
inline bool islessequal(const Lhs& f, const Rhs& g) {
|
| 956 |
+
using internal::AsScalar;
|
| 957 |
+
return islessequal(AsScalar(f), AsScalar(g));
|
| 958 |
+
}
|
| 959 |
+
|
| 960 |
+
// Determines whether the scalar part of the Jet f is less than or greater than
|
| 961 |
+
// (f < g || f > g) the scalar part of g.
|
| 962 |
+
//
|
| 963 |
+
// NOTE: This function does NOT set any floating-point exceptions.
|
| 964 |
+
template <typename Lhs,
|
| 965 |
+
typename Rhs,
|
| 966 |
+
std::enable_if_t<CompatibleJetOperands_v<Lhs, Rhs>>* = nullptr>
|
| 967 |
+
inline bool islessgreater(const Lhs& f, const Rhs& g) {
|
| 968 |
+
using internal::AsScalar;
|
| 969 |
+
return islessgreater(AsScalar(f), AsScalar(g));
|
| 970 |
+
}
|
| 971 |
+
|
| 972 |
+
// Determines whether the scalar part of the Jet f is greater than or equal to
|
| 973 |
+
// the scalar part of g.
|
| 974 |
+
//
|
| 975 |
+
// NOTE: This function does NOT set any floating-point exceptions.
|
| 976 |
+
template <typename Lhs,
|
| 977 |
+
typename Rhs,
|
| 978 |
+
std::enable_if_t<CompatibleJetOperands_v<Lhs, Rhs>>* = nullptr>
|
| 979 |
+
inline bool isgreaterequal(const Lhs& f, const Rhs& g) {
|
| 980 |
+
using internal::AsScalar;
|
| 981 |
+
return isgreaterequal(AsScalar(f), AsScalar(g));
|
| 982 |
+
}
|
| 983 |
+
|
| 984 |
+
// Determines if either of the scalar parts of the arguments are NaN and
|
| 985 |
+
// thus cannot be ordered with respect to each other.
|
| 986 |
+
template <typename Lhs,
|
| 987 |
+
typename Rhs,
|
| 988 |
+
std::enable_if_t<CompatibleJetOperands_v<Lhs, Rhs>>* = nullptr>
|
| 989 |
+
inline bool isunordered(const Lhs& f, const Rhs& g) {
|
| 990 |
+
using internal::AsScalar;
|
| 991 |
+
return isunordered(AsScalar(f), AsScalar(g));
|
| 992 |
+
}
|
| 993 |
+
|
| 994 |
+
// Categorize scalar part as zero, subnormal, normal, infinite, NaN, or
|
| 995 |
+
// implementation-defined.
|
| 996 |
+
template <typename T, int N>
|
| 997 |
+
inline int fpclassify(const Jet<T, N>& f) {
|
| 998 |
+
return fpclassify(f.a);
|
| 999 |
+
}
|
| 1000 |
+
|
| 1001 |
+
// Determines whether the scalar part of the argument is negative.
|
| 1002 |
+
template <typename T, int N>
|
| 1003 |
+
inline bool signbit(const Jet<T, N>& f) {
|
| 1004 |
+
return signbit(f.a);
|
| 1005 |
+
}
|
| 1006 |
+
|
| 1007 |
+
// Legacy functions from the pre-C++11 days.
|
| 1008 |
+
template <typename T, int N>
|
| 1009 |
+
CERES_DEPRECATED_WITH_MSG(
|
| 1010 |
+
"ceres::IsFinite will be removed in a future Ceres Solver release. Please "
|
| 1011 |
+
"use ceres::isfinite.")
|
| 1012 |
+
inline bool IsFinite(const Jet<T, N>& f) {
|
| 1013 |
+
return isfinite(f);
|
| 1014 |
+
}
|
| 1015 |
+
|
| 1016 |
+
template <typename T, int N>
|
| 1017 |
+
CERES_DEPRECATED_WITH_MSG(
|
| 1018 |
+
"ceres::IsNaN will be removed in a future Ceres Solver release. Please use "
|
| 1019 |
+
"ceres::isnan.")
|
| 1020 |
+
inline bool IsNaN(const Jet<T, N>& f) {
|
| 1021 |
+
return isnan(f);
|
| 1022 |
+
}
|
| 1023 |
+
|
| 1024 |
+
template <typename T, int N>
|
| 1025 |
+
CERES_DEPRECATED_WITH_MSG(
|
| 1026 |
+
"ceres::IsNormal will be removed in a future Ceres Solver release. Please "
|
| 1027 |
+
"use ceres::isnormal.")
|
| 1028 |
+
inline bool IsNormal(const Jet<T, N>& f) {
|
| 1029 |
+
return isnormal(f);
|
| 1030 |
+
}
|
| 1031 |
+
|
| 1032 |
+
// The jet is infinite if any part of the jet is infinite.
|
| 1033 |
+
template <typename T, int N>
|
| 1034 |
+
CERES_DEPRECATED_WITH_MSG(
|
| 1035 |
+
"ceres::IsInfinite will be removed in a future Ceres Solver release. "
|
| 1036 |
+
"Please use ceres::isinf.")
|
| 1037 |
+
inline bool IsInfinite(const Jet<T, N>& f) {
|
| 1038 |
+
return isinf(f);
|
| 1039 |
+
}
|
| 1040 |
+
|
| 1041 |
+
#ifdef CERES_HAS_CPP20
|
| 1042 |
+
// Computes the linear interpolation a + t(b - a) between a and b at the value
|
| 1043 |
+
// t. For arguments outside of the range 0 <= t <= 1, the values are
|
| 1044 |
+
// extrapolated.
|
| 1045 |
+
//
|
| 1046 |
+
// Differentiating lerp(a, b, t) with respect to a, b, and t gives:
|
| 1047 |
+
//
|
| 1048 |
+
// d/da lerp(a, b, t) = 1 - t
|
| 1049 |
+
// d/db lerp(a, b, t) = t
|
| 1050 |
+
// d/dt lerp(a, b, t) = b - a
|
| 1051 |
+
//
|
| 1052 |
+
// with the dual representation given by
|
| 1053 |
+
//
|
| 1054 |
+
// lerp(a + da, b + db, t + dt)
|
| 1055 |
+
// ~= lerp(a, b, t) + (1 - t) da + t db + (b - a) dt .
|
| 1056 |
+
template <typename T, int N>
|
| 1057 |
+
inline Jet<T, N> lerp(const Jet<T, N>& a,
|
| 1058 |
+
const Jet<T, N>& b,
|
| 1059 |
+
const Jet<T, N>& t) {
|
| 1060 |
+
return Jet<T, N>{lerp(a.a, b.a, t.a),
|
| 1061 |
+
(T(1) - t.a) * a.v + t.a * b.v + (b.a - a.a) * t.v};
|
| 1062 |
+
}
|
| 1063 |
+
|
| 1064 |
+
// Computes the midpoint a + (b - a) / 2.
|
| 1065 |
+
//
|
| 1066 |
+
// Differentiating midpoint(a, b) with respect to a and b gives:
|
| 1067 |
+
//
|
| 1068 |
+
// d/da midpoint(a, b) = 1/2
|
| 1069 |
+
// d/db midpoint(a, b) = 1/2
|
| 1070 |
+
//
|
| 1071 |
+
// with the dual representation given by
|
| 1072 |
+
//
|
| 1073 |
+
// midpoint(a + da, b + db) ~= midpoint(a, b) + (da + db) / 2 .
|
| 1074 |
+
template <typename T, int N>
|
| 1075 |
+
inline Jet<T, N> midpoint(const Jet<T, N>& a, const Jet<T, N>& b) {
|
| 1076 |
+
Jet<T, N> result{midpoint(a.a, b.a)};
|
| 1077 |
+
// To avoid overflow in the differential, compute
|
| 1078 |
+
// (da + db) / 2 using midpoint.
|
| 1079 |
+
for (int i = 0; i < N; ++i) {
|
| 1080 |
+
result.v[i] = midpoint(a.v[i], b.v[i]);
|
| 1081 |
+
}
|
| 1082 |
+
return result;
|
| 1083 |
+
}
|
| 1084 |
+
#endif // defined(CERES_HAS_CPP20)
|
| 1085 |
+
|
| 1086 |
+
// atan2(b + db, a + da) ~= atan2(b, a) + (- b da + a db) / (a^2 + b^2)
|
| 1087 |
+
//
|
| 1088 |
+
// In words: the rate of change of theta is 1/r times the rate of
|
| 1089 |
+
// change of (x, y) in the positive angular direction.
|
| 1090 |
+
template <typename T, int N>
|
| 1091 |
+
inline Jet<T, N> atan2(const Jet<T, N>& g, const Jet<T, N>& f) {
|
| 1092 |
+
// Note order of arguments:
|
| 1093 |
+
//
|
| 1094 |
+
// f = a + da
|
| 1095 |
+
// g = b + db
|
| 1096 |
+
|
| 1097 |
+
T const tmp = T(1.0) / (f.a * f.a + g.a * g.a);
|
| 1098 |
+
return Jet<T, N>(atan2(g.a, f.a), tmp * (-g.a * f.v + f.a * g.v));
|
| 1099 |
+
}
|
| 1100 |
+
|
| 1101 |
+
// Computes the square x^2 of a real number x (not the Euclidean L^2 norm as
|
| 1102 |
+
// the name might suggest).
|
| 1103 |
+
//
|
| 1104 |
+
// NOTE: While std::norm is primarily intended for computing the squared
|
| 1105 |
+
// magnitude of a std::complex<> number, the current Jet implementation does not
|
| 1106 |
+
// support mixing a scalar T in its real part and std::complex<T> and in the
|
| 1107 |
+
// infinitesimal. Mixed Jet support is necessary for the type decay from
|
| 1108 |
+
// std::complex<T> to T (the squared magnitude of a complex number is always
|
| 1109 |
+
// real) performed by std::norm.
|
| 1110 |
+
//
|
| 1111 |
+
// norm(x + h) ~= norm(x) + 2x h
|
| 1112 |
+
template <typename T, int N>
|
| 1113 |
+
inline Jet<T, N> norm(const Jet<T, N>& f) {
|
| 1114 |
+
return Jet<T, N>(norm(f.a), T(2) * f.a * f.v);
|
| 1115 |
+
}
|
| 1116 |
+
|
| 1117 |
+
// pow -- base is a differentiable function, exponent is a constant.
|
| 1118 |
+
// (a+da)^p ~= a^p + p*a^(p-1) da
|
| 1119 |
+
template <typename T, int N>
|
| 1120 |
+
inline Jet<T, N> pow(const Jet<T, N>& f, double g) {
|
| 1121 |
+
T const tmp = g * pow(f.a, g - T(1.0));
|
| 1122 |
+
return Jet<T, N>(pow(f.a, g), tmp * f.v);
|
| 1123 |
+
}
|
| 1124 |
+
|
| 1125 |
+
// pow -- base is a constant, exponent is a differentiable function.
|
| 1126 |
+
// We have various special cases, see the comment for pow(Jet, Jet) for
|
| 1127 |
+
// analysis:
|
| 1128 |
+
//
|
| 1129 |
+
// 1. For f > 0 we have: (f)^(g + dg) ~= f^g + f^g log(f) dg
|
| 1130 |
+
//
|
| 1131 |
+
// 2. For f == 0 and g > 0 we have: (f)^(g + dg) ~= f^g
|
| 1132 |
+
//
|
| 1133 |
+
// 3. For f < 0 and integer g we have: (f)^(g + dg) ~= f^g but if dg
|
| 1134 |
+
// != 0, the derivatives are not defined and we return NaN.
|
| 1135 |
+
|
| 1136 |
+
template <typename T, int N>
|
| 1137 |
+
inline Jet<T, N> pow(T f, const Jet<T, N>& g) {
|
| 1138 |
+
Jet<T, N> result;
|
| 1139 |
+
|
| 1140 |
+
if (fpclassify(f) == FP_ZERO && g > 0) {
|
| 1141 |
+
// Handle case 2.
|
| 1142 |
+
result = Jet<T, N>(T(0.0));
|
| 1143 |
+
} else {
|
| 1144 |
+
if (f < 0 && g == floor(g.a)) { // Handle case 3.
|
| 1145 |
+
result = Jet<T, N>(pow(f, g.a));
|
| 1146 |
+
for (int i = 0; i < N; i++) {
|
| 1147 |
+
if (fpclassify(g.v[i]) != FP_ZERO) {
|
| 1148 |
+
// Return a NaN when g.v != 0.
|
| 1149 |
+
result.v[i] = std::numeric_limits<T>::quiet_NaN();
|
| 1150 |
+
}
|
| 1151 |
+
}
|
| 1152 |
+
} else {
|
| 1153 |
+
// Handle case 1.
|
| 1154 |
+
T const tmp = pow(f, g.a);
|
| 1155 |
+
result = Jet<T, N>(tmp, log(f) * tmp * g.v);
|
| 1156 |
+
}
|
| 1157 |
+
}
|
| 1158 |
+
|
| 1159 |
+
return result;
|
| 1160 |
+
}
|
| 1161 |
+
|
| 1162 |
+
// pow -- both base and exponent are differentiable functions. This has a
|
| 1163 |
+
// variety of special cases that require careful handling.
|
| 1164 |
+
//
|
| 1165 |
+
// 1. For f > 0:
|
| 1166 |
+
// (f + df)^(g + dg) ~= f^g + f^(g - 1) * (g * df + f * log(f) * dg)
|
| 1167 |
+
// The numerical evaluation of f * log(f) for f > 0 is well behaved, even for
|
| 1168 |
+
// extremely small values (e.g. 1e-99).
|
| 1169 |
+
//
|
| 1170 |
+
// 2. For f == 0 and g > 1: (f + df)^(g + dg) ~= 0
|
| 1171 |
+
// This cases is needed because log(0) can not be evaluated in the f > 0
|
| 1172 |
+
// expression. However the function f*log(f) is well behaved around f == 0
|
| 1173 |
+
// and its limit as f-->0 is zero.
|
| 1174 |
+
//
|
| 1175 |
+
// 3. For f == 0 and g == 1: (f + df)^(g + dg) ~= 0 + df
|
| 1176 |
+
//
|
| 1177 |
+
// 4. For f == 0 and 0 < g < 1: The value is finite but the derivatives are not.
|
| 1178 |
+
//
|
| 1179 |
+
// 5. For f == 0 and g < 0: The value and derivatives of f^g are not finite.
|
| 1180 |
+
//
|
| 1181 |
+
// 6. For f == 0 and g == 0: The C standard incorrectly defines 0^0 to be 1
|
| 1182 |
+
// "because there are applications that can exploit this definition". We
|
| 1183 |
+
// (arbitrarily) decree that derivatives here will be nonfinite, since that
|
| 1184 |
+
// is consistent with the behavior for f == 0, g < 0 and 0 < g < 1.
|
| 1185 |
+
// Practically any definition could have been justified because mathematical
|
| 1186 |
+
// consistency has been lost at this point.
|
| 1187 |
+
//
|
| 1188 |
+
// 7. For f < 0, g integer, dg == 0: (f + df)^(g + dg) ~= f^g + g * f^(g - 1) df
|
| 1189 |
+
// This is equivalent to the case where f is a differentiable function and g
|
| 1190 |
+
// is a constant (to first order).
|
| 1191 |
+
//
|
| 1192 |
+
// 8. For f < 0, g integer, dg != 0: The value is finite but the derivatives are
|
| 1193 |
+
// not, because any change in the value of g moves us away from the point
|
| 1194 |
+
// with a real-valued answer into the region with complex-valued answers.
|
| 1195 |
+
//
|
| 1196 |
+
// 9. For f < 0, g noninteger: The value and derivatives of f^g are not finite.
|
| 1197 |
+
|
| 1198 |
+
template <typename T, int N>
|
| 1199 |
+
inline Jet<T, N> pow(const Jet<T, N>& f, const Jet<T, N>& g) {
|
| 1200 |
+
Jet<T, N> result;
|
| 1201 |
+
|
| 1202 |
+
if (fpclassify(f) == FP_ZERO && g >= 1) {
|
| 1203 |
+
// Handle cases 2 and 3.
|
| 1204 |
+
if (g > 1) {
|
| 1205 |
+
result = Jet<T, N>(T(0.0));
|
| 1206 |
+
} else {
|
| 1207 |
+
result = f;
|
| 1208 |
+
}
|
| 1209 |
+
|
| 1210 |
+
} else {
|
| 1211 |
+
if (f < 0 && g == floor(g.a)) {
|
| 1212 |
+
// Handle cases 7 and 8.
|
| 1213 |
+
T const tmp = g.a * pow(f.a, g.a - T(1.0));
|
| 1214 |
+
result = Jet<T, N>(pow(f.a, g.a), tmp * f.v);
|
| 1215 |
+
for (int i = 0; i < N; i++) {
|
| 1216 |
+
if (fpclassify(g.v[i]) != FP_ZERO) {
|
| 1217 |
+
// Return a NaN when g.v != 0.
|
| 1218 |
+
result.v[i] = T(std::numeric_limits<double>::quiet_NaN());
|
| 1219 |
+
}
|
| 1220 |
+
}
|
| 1221 |
+
} else {
|
| 1222 |
+
// Handle the remaining cases. For cases 4,5,6,9 we allow the log()
|
| 1223 |
+
// function to generate -HUGE_VAL or NaN, since those cases result in a
|
| 1224 |
+
// nonfinite derivative.
|
| 1225 |
+
T const tmp1 = pow(f.a, g.a);
|
| 1226 |
+
T const tmp2 = g.a * pow(f.a, g.a - T(1.0));
|
| 1227 |
+
T const tmp3 = tmp1 * log(f.a);
|
| 1228 |
+
result = Jet<T, N>(tmp1, tmp2 * f.v + tmp3 * g.v);
|
| 1229 |
+
}
|
| 1230 |
+
}
|
| 1231 |
+
|
| 1232 |
+
return result;
|
| 1233 |
+
}
|
| 1234 |
+
|
| 1235 |
+
// Note: This has to be in the ceres namespace for argument dependent lookup to
|
| 1236 |
+
// function correctly. Otherwise statements like CHECK_LE(x, 2.0) fail with
|
| 1237 |
+
// strange compile errors.
|
| 1238 |
+
template <typename T, int N>
|
| 1239 |
+
inline std::ostream& operator<<(std::ostream& s, const Jet<T, N>& z) {
|
| 1240 |
+
s << "[" << z.a << " ; ";
|
| 1241 |
+
for (int i = 0; i < N; ++i) {
|
| 1242 |
+
s << z.v[i];
|
| 1243 |
+
if (i != N - 1) {
|
| 1244 |
+
s << ", ";
|
| 1245 |
+
}
|
| 1246 |
+
}
|
| 1247 |
+
s << "]";
|
| 1248 |
+
return s;
|
| 1249 |
+
}
|
| 1250 |
+
} // namespace ceres
|
| 1251 |
+
|
| 1252 |
+
namespace std {
|
| 1253 |
+
template <typename T, int N>
|
| 1254 |
+
struct numeric_limits<ceres::Jet<T, N>> {
|
| 1255 |
+
static constexpr bool is_specialized = true;
|
| 1256 |
+
static constexpr bool is_signed = std::numeric_limits<T>::is_signed;
|
| 1257 |
+
static constexpr bool is_integer = std::numeric_limits<T>::is_integer;
|
| 1258 |
+
static constexpr bool is_exact = std::numeric_limits<T>::is_exact;
|
| 1259 |
+
static constexpr bool has_infinity = std::numeric_limits<T>::has_infinity;
|
| 1260 |
+
static constexpr bool has_quiet_NaN = std::numeric_limits<T>::has_quiet_NaN;
|
| 1261 |
+
static constexpr bool has_signaling_NaN =
|
| 1262 |
+
std::numeric_limits<T>::has_signaling_NaN;
|
| 1263 |
+
static constexpr bool is_iec559 = std::numeric_limits<T>::is_iec559;
|
| 1264 |
+
static constexpr bool is_bounded = std::numeric_limits<T>::is_bounded;
|
| 1265 |
+
static constexpr bool is_modulo = std::numeric_limits<T>::is_modulo;
|
| 1266 |
+
|
| 1267 |
+
static constexpr std::float_denorm_style has_denorm =
|
| 1268 |
+
std::numeric_limits<T>::has_denorm;
|
| 1269 |
+
static constexpr std::float_round_style round_style =
|
| 1270 |
+
std::numeric_limits<T>::round_style;
|
| 1271 |
+
|
| 1272 |
+
static constexpr int digits = std::numeric_limits<T>::digits;
|
| 1273 |
+
static constexpr int digits10 = std::numeric_limits<T>::digits10;
|
| 1274 |
+
static constexpr int max_digits10 = std::numeric_limits<T>::max_digits10;
|
| 1275 |
+
static constexpr int radix = std::numeric_limits<T>::radix;
|
| 1276 |
+
static constexpr int min_exponent = std::numeric_limits<T>::min_exponent;
|
| 1277 |
+
static constexpr int min_exponent10 = std::numeric_limits<T>::max_exponent10;
|
| 1278 |
+
static constexpr int max_exponent = std::numeric_limits<T>::max_exponent;
|
| 1279 |
+
static constexpr int max_exponent10 = std::numeric_limits<T>::max_exponent10;
|
| 1280 |
+
static constexpr bool traps = std::numeric_limits<T>::traps;
|
| 1281 |
+
static constexpr bool tinyness_before =
|
| 1282 |
+
std::numeric_limits<T>::tinyness_before;
|
| 1283 |
+
|
| 1284 |
+
static constexpr ceres::Jet<T, N> min
|
| 1285 |
+
CERES_PREVENT_MACRO_SUBSTITUTION() noexcept {
|
| 1286 |
+
return ceres::Jet<T, N>((std::numeric_limits<T>::min)());
|
| 1287 |
+
}
|
| 1288 |
+
static constexpr ceres::Jet<T, N> lowest() noexcept {
|
| 1289 |
+
return ceres::Jet<T, N>(std::numeric_limits<T>::lowest());
|
| 1290 |
+
}
|
| 1291 |
+
static constexpr ceres::Jet<T, N> epsilon() noexcept {
|
| 1292 |
+
return ceres::Jet<T, N>(std::numeric_limits<T>::epsilon());
|
| 1293 |
+
}
|
| 1294 |
+
static constexpr ceres::Jet<T, N> round_error() noexcept {
|
| 1295 |
+
return ceres::Jet<T, N>(std::numeric_limits<T>::round_error());
|
| 1296 |
+
}
|
| 1297 |
+
static constexpr ceres::Jet<T, N> infinity() noexcept {
|
| 1298 |
+
return ceres::Jet<T, N>(std::numeric_limits<T>::infinity());
|
| 1299 |
+
}
|
| 1300 |
+
static constexpr ceres::Jet<T, N> quiet_NaN() noexcept {
|
| 1301 |
+
return ceres::Jet<T, N>(std::numeric_limits<T>::quiet_NaN());
|
| 1302 |
+
}
|
| 1303 |
+
static constexpr ceres::Jet<T, N> signaling_NaN() noexcept {
|
| 1304 |
+
return ceres::Jet<T, N>(std::numeric_limits<T>::signaling_NaN());
|
| 1305 |
+
}
|
| 1306 |
+
static constexpr ceres::Jet<T, N> denorm_min() noexcept {
|
| 1307 |
+
return ceres::Jet<T, N>(std::numeric_limits<T>::denorm_min());
|
| 1308 |
+
}
|
| 1309 |
+
|
| 1310 |
+
static constexpr ceres::Jet<T, N> max
|
| 1311 |
+
CERES_PREVENT_MACRO_SUBSTITUTION() noexcept {
|
| 1312 |
+
return ceres::Jet<T, N>((std::numeric_limits<T>::max)());
|
| 1313 |
+
}
|
| 1314 |
+
};
|
| 1315 |
+
|
| 1316 |
+
} // namespace std
|
| 1317 |
+
|
| 1318 |
+
namespace Eigen {
|
| 1319 |
+
|
| 1320 |
+
// Creating a specialization of NumTraits enables placing Jet objects inside
|
| 1321 |
+
// Eigen arrays, getting all the goodness of Eigen combined with autodiff.
|
| 1322 |
+
template <typename T, int N>
|
| 1323 |
+
struct NumTraits<ceres::Jet<T, N>> {
|
| 1324 |
+
using Real = ceres::Jet<T, N>;
|
| 1325 |
+
using NonInteger = ceres::Jet<T, N>;
|
| 1326 |
+
using Nested = ceres::Jet<T, N>;
|
| 1327 |
+
using Literal = ceres::Jet<T, N>;
|
| 1328 |
+
|
| 1329 |
+
static typename ceres::Jet<T, N> dummy_precision() {
|
| 1330 |
+
return ceres::Jet<T, N>(1e-12);
|
| 1331 |
+
}
|
| 1332 |
+
|
| 1333 |
+
static inline Real epsilon() {
|
| 1334 |
+
return Real(std::numeric_limits<T>::epsilon());
|
| 1335 |
+
}
|
| 1336 |
+
|
| 1337 |
+
static inline int digits10() { return NumTraits<T>::digits10(); }
|
| 1338 |
+
|
| 1339 |
+
enum {
|
| 1340 |
+
IsComplex = 0,
|
| 1341 |
+
IsInteger = 0,
|
| 1342 |
+
IsSigned,
|
| 1343 |
+
ReadCost = 1,
|
| 1344 |
+
AddCost = 1,
|
| 1345 |
+
// For Jet types, multiplication is more expensive than addition.
|
| 1346 |
+
MulCost = 3,
|
| 1347 |
+
HasFloatingPoint = 1,
|
| 1348 |
+
RequireInitialization = 1
|
| 1349 |
+
};
|
| 1350 |
+
|
| 1351 |
+
template <bool Vectorized>
|
| 1352 |
+
struct Div {
|
| 1353 |
+
enum {
|
| 1354 |
+
#if defined(EIGEN_VECTORIZE_AVX)
|
| 1355 |
+
AVX = true,
|
| 1356 |
+
#else
|
| 1357 |
+
AVX = false,
|
| 1358 |
+
#endif
|
| 1359 |
+
|
| 1360 |
+
// Assuming that for Jets, division is as expensive as
|
| 1361 |
+
// multiplication.
|
| 1362 |
+
Cost = 3
|
| 1363 |
+
};
|
| 1364 |
+
};
|
| 1365 |
+
|
| 1366 |
+
static inline Real highest() { return Real((std::numeric_limits<T>::max)()); }
|
| 1367 |
+
static inline Real lowest() { return Real(-(std::numeric_limits<T>::max)()); }
|
| 1368 |
+
};
|
| 1369 |
+
|
| 1370 |
+
// Specifying the return type of binary operations between Jets and scalar types
|
| 1371 |
+
// allows you to perform matrix/array operations with Eigen matrices and arrays
|
| 1372 |
+
// such as addition, subtraction, multiplication, and division where one Eigen
|
| 1373 |
+
// matrix/array is of type Jet and the other is a scalar type. This improves
|
| 1374 |
+
// performance by using the optimized scalar-to-Jet binary operations but
|
| 1375 |
+
// is only available on Eigen versions >= 3.3
|
| 1376 |
+
template <typename BinaryOp, typename T, int N>
|
| 1377 |
+
struct ScalarBinaryOpTraits<ceres::Jet<T, N>, T, BinaryOp> {
|
| 1378 |
+
using ReturnType = ceres::Jet<T, N>;
|
| 1379 |
+
};
|
| 1380 |
+
template <typename BinaryOp, typename T, int N>
|
| 1381 |
+
struct ScalarBinaryOpTraits<T, ceres::Jet<T, N>, BinaryOp> {
|
| 1382 |
+
using ReturnType = ceres::Jet<T, N>;
|
| 1383 |
+
};
|
| 1384 |
+
|
| 1385 |
+
} // namespace Eigen
|
| 1386 |
+
|
| 1387 |
+
#endif // CERES_PUBLIC_JET_H_
|
ceres-v2/include/jet_fwd.h
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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: sergiu.deitsch@gmail.com (Sergiu Deitsch)
|
| 30 |
+
//
|
| 31 |
+
|
| 32 |
+
#ifndef CERES_PUBLIC_JET_FWD_H_
|
| 33 |
+
#define CERES_PUBLIC_JET_FWD_H_
|
| 34 |
+
|
| 35 |
+
namespace ceres {
|
| 36 |
+
|
| 37 |
+
// Jet forward declaration necessary for the following partial specialization of
|
| 38 |
+
// std::common_type and type traits.
|
| 39 |
+
template <typename T, int N>
|
| 40 |
+
struct Jet;
|
| 41 |
+
|
| 42 |
+
} // namespace ceres
|
| 43 |
+
|
| 44 |
+
#endif // CERES_PUBLIC_JET_FWD_H_
|
ceres-v2/include/line_manifold.h
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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: jodebo_beck@gmx.de (Johannes Beck)
|
| 30 |
+
//
|
| 31 |
+
|
| 32 |
+
#ifndef CERES_PUBLIC_LINE_MANIFOLD_H_
|
| 33 |
+
#define CERES_PUBLIC_LINE_MANIFOLD_H_
|
| 34 |
+
|
| 35 |
+
#include <Eigen/Core>
|
| 36 |
+
#include <algorithm>
|
| 37 |
+
#include <array>
|
| 38 |
+
#include <memory>
|
| 39 |
+
#include <vector>
|
| 40 |
+
|
| 41 |
+
#include "ceres/internal/disable_warnings.h"
|
| 42 |
+
#include "ceres/internal/export.h"
|
| 43 |
+
#include "ceres/internal/householder_vector.h"
|
| 44 |
+
#include "ceres/internal/sphere_manifold_functions.h"
|
| 45 |
+
#include "ceres/manifold.h"
|
| 46 |
+
#include "ceres/types.h"
|
| 47 |
+
#include "glog/logging.h"
|
| 48 |
+
|
| 49 |
+
namespace ceres {
|
| 50 |
+
// This provides a manifold for lines, where the line is
|
| 51 |
+
// over-parameterized by an origin point and a direction vector. So the
|
| 52 |
+
// parameter vector size needs to be two times the ambient space dimension,
|
| 53 |
+
// where the first half is interpreted as the origin point and the second half
|
| 54 |
+
// as the direction.
|
| 55 |
+
//
|
| 56 |
+
// The plus operator for the line direction is the same as for the
|
| 57 |
+
// SphereManifold. The update of the origin point is
|
| 58 |
+
// perpendicular to the line direction before the update.
|
| 59 |
+
//
|
| 60 |
+
// This manifold is a special case of the affine Grassmannian
|
| 61 |
+
// manifold (see https://en.wikipedia.org/wiki/Affine_Grassmannian_(manifold))
|
| 62 |
+
// for the case Graff_1(R^n).
|
| 63 |
+
//
|
| 64 |
+
// The class works with dynamic and static ambient space dimensions. If the
|
| 65 |
+
// ambient space dimensions is known at compile time use
|
| 66 |
+
//
|
| 67 |
+
// LineManifold<3> manifold;
|
| 68 |
+
//
|
| 69 |
+
// If the ambient space dimensions is not known at compile time the template
|
| 70 |
+
// parameter needs to be set to ceres::DYNAMIC and the actual dimension needs
|
| 71 |
+
// to be provided as a constructor argument:
|
| 72 |
+
//
|
| 73 |
+
// LineManifold<ceres::DYNAMIC> manifold(ambient_dim);
|
| 74 |
+
//
|
| 75 |
+
template <int AmbientSpaceDimension>
|
| 76 |
+
class LineManifold final : public Manifold {
|
| 77 |
+
public:
|
| 78 |
+
static_assert(AmbientSpaceDimension == DYNAMIC || AmbientSpaceDimension >= 2,
|
| 79 |
+
"The ambient space must be at least 2.");
|
| 80 |
+
static_assert(ceres::DYNAMIC == Eigen::Dynamic,
|
| 81 |
+
"ceres::DYNAMIC needs to be the same as Eigen::Dynamic.");
|
| 82 |
+
|
| 83 |
+
LineManifold();
|
| 84 |
+
explicit LineManifold(int size);
|
| 85 |
+
|
| 86 |
+
int AmbientSize() const override { return 2 * size_; }
|
| 87 |
+
int TangentSize() const override { return 2 * (size_ - 1); }
|
| 88 |
+
bool Plus(const double* x,
|
| 89 |
+
const double* delta,
|
| 90 |
+
double* x_plus_delta) const override;
|
| 91 |
+
bool PlusJacobian(const double* x, double* jacobian) const override;
|
| 92 |
+
bool Minus(const double* y,
|
| 93 |
+
const double* x,
|
| 94 |
+
double* y_minus_x) const override;
|
| 95 |
+
bool MinusJacobian(const double* x, double* jacobian) const override;
|
| 96 |
+
|
| 97 |
+
private:
|
| 98 |
+
static constexpr bool IsDynamic = (AmbientSpaceDimension == ceres::DYNAMIC);
|
| 99 |
+
static constexpr int TangentSpaceDimension =
|
| 100 |
+
IsDynamic ? ceres::DYNAMIC : AmbientSpaceDimension - 1;
|
| 101 |
+
|
| 102 |
+
static constexpr int DAmbientSpaceDimension =
|
| 103 |
+
IsDynamic ? ceres::DYNAMIC : 2 * AmbientSpaceDimension;
|
| 104 |
+
static constexpr int DTangentSpaceDimension =
|
| 105 |
+
IsDynamic ? ceres::DYNAMIC : 2 * TangentSpaceDimension;
|
| 106 |
+
|
| 107 |
+
using AmbientVector = Eigen::Matrix<double, AmbientSpaceDimension, 1>;
|
| 108 |
+
using TangentVector = Eigen::Matrix<double, TangentSpaceDimension, 1>;
|
| 109 |
+
using MatrixPlusJacobian = Eigen::Matrix<double,
|
| 110 |
+
DAmbientSpaceDimension,
|
| 111 |
+
DTangentSpaceDimension,
|
| 112 |
+
Eigen::RowMajor>;
|
| 113 |
+
using MatrixMinusJacobian = Eigen::Matrix<double,
|
| 114 |
+
DTangentSpaceDimension,
|
| 115 |
+
DAmbientSpaceDimension,
|
| 116 |
+
Eigen::RowMajor>;
|
| 117 |
+
|
| 118 |
+
const int size_{AmbientSpaceDimension};
|
| 119 |
+
};
|
| 120 |
+
|
| 121 |
+
template <int AmbientSpaceDimension>
|
| 122 |
+
LineManifold<AmbientSpaceDimension>::LineManifold()
|
| 123 |
+
: size_{AmbientSpaceDimension} {
|
| 124 |
+
static_assert(
|
| 125 |
+
AmbientSpaceDimension != Eigen::Dynamic,
|
| 126 |
+
"The size is set to dynamic. Please call the constructor with a size.");
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
template <int AmbientSpaceDimension>
|
| 130 |
+
LineManifold<AmbientSpaceDimension>::LineManifold(int size) : size_{size} {
|
| 131 |
+
if (AmbientSpaceDimension != Eigen::Dynamic) {
|
| 132 |
+
CHECK_EQ(AmbientSpaceDimension, size)
|
| 133 |
+
<< "Specified size by template parameter differs from the supplied "
|
| 134 |
+
"one.";
|
| 135 |
+
} else {
|
| 136 |
+
CHECK_GT(size_, 1)
|
| 137 |
+
<< "The size of the manifold needs to be greater than 1.";
|
| 138 |
+
}
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
template <int AmbientSpaceDimension>
|
| 142 |
+
bool LineManifold<AmbientSpaceDimension>::Plus(const double* x_ptr,
|
| 143 |
+
const double* delta_ptr,
|
| 144 |
+
double* x_plus_delta_ptr) const {
|
| 145 |
+
// We seek a box plus operator of the form
|
| 146 |
+
//
|
| 147 |
+
// [o*, d*] = Plus([o, d], [delta_o, delta_d])
|
| 148 |
+
//
|
| 149 |
+
// where o is the origin point, d is the direction vector, delta_o is
|
| 150 |
+
// the delta of the origin point and delta_d the delta of the direction and
|
| 151 |
+
// o* and d* is the updated origin point and direction.
|
| 152 |
+
//
|
| 153 |
+
// We separate the Plus operator into the origin point and directional part
|
| 154 |
+
// d* = Plus_d(d, delta_d)
|
| 155 |
+
// o* = Plus_o(o, d, delta_o)
|
| 156 |
+
//
|
| 157 |
+
// The direction update function Plus_d is the same as as the SphereManifold:
|
| 158 |
+
//
|
| 159 |
+
// d* = H_{v(d)} [0.5 sinc(0.5 |delta_d|) delta_d, cos(0.5 |delta_d|)]^T
|
| 160 |
+
//
|
| 161 |
+
// where H is the householder matrix
|
| 162 |
+
// H_{v} = I - (2 / |v|^2) v v^T
|
| 163 |
+
// and
|
| 164 |
+
// v(d) = d - sign(d_n) |d| e_n.
|
| 165 |
+
//
|
| 166 |
+
// The origin point update function Plus_o is defined as
|
| 167 |
+
//
|
| 168 |
+
// o* = o + H_{v(d)} [0.5 delta_o, 0]^T.
|
| 169 |
+
|
| 170 |
+
Eigen::Map<const AmbientVector> o(x_ptr, size_);
|
| 171 |
+
Eigen::Map<const AmbientVector> d(x_ptr + size_, size_);
|
| 172 |
+
|
| 173 |
+
Eigen::Map<const TangentVector> delta_o(delta_ptr, size_ - 1);
|
| 174 |
+
Eigen::Map<const TangentVector> delta_d(delta_ptr + size_ - 1, size_ - 1);
|
| 175 |
+
Eigen::Map<AmbientVector> o_plus_delta(x_plus_delta_ptr, size_);
|
| 176 |
+
Eigen::Map<AmbientVector> d_plus_delta(x_plus_delta_ptr + size_, size_);
|
| 177 |
+
|
| 178 |
+
const double norm_delta_d = delta_d.norm();
|
| 179 |
+
|
| 180 |
+
o_plus_delta = o;
|
| 181 |
+
|
| 182 |
+
// Shortcut for zero delta direction.
|
| 183 |
+
if (norm_delta_d == 0.0) {
|
| 184 |
+
d_plus_delta = d;
|
| 185 |
+
|
| 186 |
+
if (delta_o.isZero(0.0)) {
|
| 187 |
+
return true;
|
| 188 |
+
}
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
// Calculate the householder transformation which is needed for f_d and f_o.
|
| 192 |
+
AmbientVector v(size_);
|
| 193 |
+
double beta;
|
| 194 |
+
|
| 195 |
+
// NOTE: The explicit template arguments are needed here because
|
| 196 |
+
// ComputeHouseholderVector is templated and some versions of MSVC
|
| 197 |
+
// have trouble deducing the type of v automatically.
|
| 198 |
+
internal::ComputeHouseholderVector<Eigen::Map<const AmbientVector>,
|
| 199 |
+
double,
|
| 200 |
+
AmbientSpaceDimension>(d, &v, &beta);
|
| 201 |
+
|
| 202 |
+
if (norm_delta_d != 0.0) {
|
| 203 |
+
internal::ComputeSphereManifoldPlus(
|
| 204 |
+
v, beta, d, delta_d, norm_delta_d, &d_plus_delta);
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
// The null space is in the direction of the line, so the tangent space is
|
| 208 |
+
// perpendicular to the line direction. This is achieved by using the
|
| 209 |
+
// householder matrix of the direction and allow only movements
|
| 210 |
+
// perpendicular to e_n.
|
| 211 |
+
//
|
| 212 |
+
// The factor of 0.5 is used to be consistent with the line direction
|
| 213 |
+
// update.
|
| 214 |
+
AmbientVector y(size_);
|
| 215 |
+
y << 0.5 * delta_o, 0;
|
| 216 |
+
o_plus_delta += internal::ApplyHouseholderVector(y, v, beta);
|
| 217 |
+
|
| 218 |
+
return true;
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
template <int AmbientSpaceDimension>
|
| 222 |
+
bool LineManifold<AmbientSpaceDimension>::PlusJacobian(
|
| 223 |
+
const double* x_ptr, double* jacobian_ptr) const {
|
| 224 |
+
Eigen::Map<const AmbientVector> d(x_ptr + size_, size_);
|
| 225 |
+
Eigen::Map<MatrixPlusJacobian> jacobian(
|
| 226 |
+
jacobian_ptr, 2 * size_, 2 * (size_ - 1));
|
| 227 |
+
|
| 228 |
+
// Clear the Jacobian as only half of the matrix is not zero.
|
| 229 |
+
jacobian.setZero();
|
| 230 |
+
|
| 231 |
+
auto jacobian_d =
|
| 232 |
+
jacobian
|
| 233 |
+
.template topLeftCorner<AmbientSpaceDimension, TangentSpaceDimension>(
|
| 234 |
+
size_, size_ - 1);
|
| 235 |
+
auto jacobian_o = jacobian.template bottomRightCorner<AmbientSpaceDimension,
|
| 236 |
+
TangentSpaceDimension>(
|
| 237 |
+
size_, size_ - 1);
|
| 238 |
+
internal::ComputeSphereManifoldPlusJacobian(d, &jacobian_d);
|
| 239 |
+
jacobian_o = jacobian_d;
|
| 240 |
+
return true;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
template <int AmbientSpaceDimension>
|
| 244 |
+
bool LineManifold<AmbientSpaceDimension>::Minus(const double* y_ptr,
|
| 245 |
+
const double* x_ptr,
|
| 246 |
+
double* y_minus_x) const {
|
| 247 |
+
Eigen::Map<const AmbientVector> y_o(y_ptr, size_);
|
| 248 |
+
Eigen::Map<const AmbientVector> y_d(y_ptr + size_, size_);
|
| 249 |
+
Eigen::Map<const AmbientVector> x_o(x_ptr, size_);
|
| 250 |
+
Eigen::Map<const AmbientVector> x_d(x_ptr + size_, size_);
|
| 251 |
+
|
| 252 |
+
Eigen::Map<TangentVector> y_minus_x_o(y_minus_x, size_ - 1);
|
| 253 |
+
Eigen::Map<TangentVector> y_minus_x_d(y_minus_x + size_ - 1, size_ - 1);
|
| 254 |
+
|
| 255 |
+
AmbientVector v(size_);
|
| 256 |
+
double beta;
|
| 257 |
+
|
| 258 |
+
// NOTE: The explicit template arguments are needed here because
|
| 259 |
+
// ComputeHouseholderVector is templated and some versions of MSVC
|
| 260 |
+
// have trouble deducing the type of v automatically.
|
| 261 |
+
internal::ComputeHouseholderVector<Eigen::Map<const AmbientVector>,
|
| 262 |
+
double,
|
| 263 |
+
AmbientSpaceDimension>(x_d, &v, &beta);
|
| 264 |
+
|
| 265 |
+
internal::ComputeSphereManifoldMinus(v, beta, x_d, y_d, &y_minus_x_d);
|
| 266 |
+
|
| 267 |
+
AmbientVector delta_o = y_o - x_o;
|
| 268 |
+
const AmbientVector h_delta_o =
|
| 269 |
+
2.0 * internal::ApplyHouseholderVector(delta_o, v, beta);
|
| 270 |
+
y_minus_x_o = h_delta_o.template head<TangentSpaceDimension>(size_ - 1);
|
| 271 |
+
|
| 272 |
+
return true;
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
template <int AmbientSpaceDimension>
|
| 276 |
+
bool LineManifold<AmbientSpaceDimension>::MinusJacobian(
|
| 277 |
+
const double* x_ptr, double* jacobian_ptr) const {
|
| 278 |
+
Eigen::Map<const AmbientVector> d(x_ptr + size_, size_);
|
| 279 |
+
Eigen::Map<MatrixMinusJacobian> jacobian(
|
| 280 |
+
jacobian_ptr, 2 * (size_ - 1), 2 * size_);
|
| 281 |
+
|
| 282 |
+
// Clear the Jacobian as only half of the matrix is not zero.
|
| 283 |
+
jacobian.setZero();
|
| 284 |
+
|
| 285 |
+
auto jacobian_d =
|
| 286 |
+
jacobian
|
| 287 |
+
.template topLeftCorner<TangentSpaceDimension, AmbientSpaceDimension>(
|
| 288 |
+
size_ - 1, size_);
|
| 289 |
+
auto jacobian_o = jacobian.template bottomRightCorner<TangentSpaceDimension,
|
| 290 |
+
AmbientSpaceDimension>(
|
| 291 |
+
size_ - 1, size_);
|
| 292 |
+
internal::ComputeSphereManifoldMinusJacobian(d, &jacobian_d);
|
| 293 |
+
jacobian_o = jacobian_d;
|
| 294 |
+
|
| 295 |
+
return true;
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
} // namespace ceres
|
| 299 |
+
|
| 300 |
+
// clang-format off
|
| 301 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 302 |
+
// clang-format on
|
| 303 |
+
|
| 304 |
+
#endif // CERES_PUBLIC_LINE_MANIFOLD_H_
|
ceres-v2/include/local_parameterization.h
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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: keir@google.com (Keir Mierle)
|
| 30 |
+
// sameeragarwal@google.com (Sameer Agarwal)
|
| 31 |
+
|
| 32 |
+
#ifndef CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
|
| 33 |
+
#define CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
|
| 34 |
+
|
| 35 |
+
#include <array>
|
| 36 |
+
#include <memory>
|
| 37 |
+
#include <vector>
|
| 38 |
+
|
| 39 |
+
#include "ceres/internal/disable_warnings.h"
|
| 40 |
+
#include "ceres/internal/export.h"
|
| 41 |
+
#include "ceres/internal/port.h"
|
| 42 |
+
|
| 43 |
+
namespace ceres {
|
| 44 |
+
|
| 45 |
+
// WARNING: LocalParameterizations are deprecated. They will be removed from
|
| 46 |
+
// Ceres Solver in version 2.2.0. Please use Manifolds instead.
|
| 47 |
+
|
| 48 |
+
// Purpose: Sometimes parameter blocks x can overparameterize a problem
|
| 49 |
+
//
|
| 50 |
+
// min f(x)
|
| 51 |
+
// x
|
| 52 |
+
//
|
| 53 |
+
// In that case it is desirable to choose a parameterization for the
|
| 54 |
+
// block itself to remove the null directions of the cost. More
|
| 55 |
+
// generally, if x lies on a manifold of a smaller dimension than the
|
| 56 |
+
// ambient space that it is embedded in, then it is numerically and
|
| 57 |
+
// computationally more effective to optimize it using a
|
| 58 |
+
// parameterization that lives in the tangent space of that manifold
|
| 59 |
+
// at each point.
|
| 60 |
+
//
|
| 61 |
+
// For example, a sphere in three dimensions is a 2 dimensional
|
| 62 |
+
// manifold, embedded in a three dimensional space. At each point on
|
| 63 |
+
// the sphere, the plane tangent to it defines a two dimensional
|
| 64 |
+
// tangent space. For a cost function defined on this sphere, given a
|
| 65 |
+
// point x, moving in the direction normal to the sphere at that point
|
| 66 |
+
// is not useful. Thus a better way to do a local optimization is to
|
| 67 |
+
// optimize over two dimensional vector delta in the tangent space at
|
| 68 |
+
// that point and then "move" to the point x + delta, where the move
|
| 69 |
+
// operation involves projecting back onto the sphere. Doing so
|
| 70 |
+
// removes a redundant dimension from the optimization, making it
|
| 71 |
+
// numerically more robust and efficient.
|
| 72 |
+
//
|
| 73 |
+
// More generally we can define a function
|
| 74 |
+
//
|
| 75 |
+
// x_plus_delta = Plus(x, delta),
|
| 76 |
+
//
|
| 77 |
+
// where x_plus_delta has the same size as x, and delta is of size
|
| 78 |
+
// less than or equal to x. The function Plus, generalizes the
|
| 79 |
+
// definition of vector addition. Thus it satisfies the identify
|
| 80 |
+
//
|
| 81 |
+
// Plus(x, 0) = x, for all x.
|
| 82 |
+
//
|
| 83 |
+
// A trivial version of Plus is when delta is of the same size as x
|
| 84 |
+
// and
|
| 85 |
+
//
|
| 86 |
+
// Plus(x, delta) = x + delta
|
| 87 |
+
//
|
| 88 |
+
// A more interesting case if x is two dimensional vector, and the
|
| 89 |
+
// user wishes to hold the first coordinate constant. Then, delta is a
|
| 90 |
+
// scalar and Plus is defined as
|
| 91 |
+
//
|
| 92 |
+
// Plus(x, delta) = x + [0] * delta
|
| 93 |
+
// [1]
|
| 94 |
+
//
|
| 95 |
+
// An example that occurs commonly in Structure from Motion problems
|
| 96 |
+
// is when camera rotations are parameterized using Quaternion. There,
|
| 97 |
+
// it is useful to only make updates orthogonal to that 4-vector
|
| 98 |
+
// defining the quaternion. One way to do this is to let delta be a 3
|
| 99 |
+
// dimensional vector and define Plus to be
|
| 100 |
+
//
|
| 101 |
+
// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x
|
| 102 |
+
//
|
| 103 |
+
// The multiplication between the two 4-vectors on the RHS is the
|
| 104 |
+
// standard quaternion product.
|
| 105 |
+
//
|
| 106 |
+
// Given f and a point x, optimizing f can now be restated as
|
| 107 |
+
//
|
| 108 |
+
// min f(Plus(x, delta))
|
| 109 |
+
// delta
|
| 110 |
+
//
|
| 111 |
+
// Given a solution delta to this problem, the optimal value is then
|
| 112 |
+
// given by
|
| 113 |
+
//
|
| 114 |
+
// x* = Plus(x, delta)
|
| 115 |
+
//
|
| 116 |
+
// The class LocalParameterization defines the function Plus and its
|
| 117 |
+
// Jacobian which is needed to compute the Jacobian of f w.r.t delta.
|
| 118 |
+
class CERES_DEPRECATED_WITH_MSG(
|
| 119 |
+
"LocalParameterizations will be removed from the Ceres Solver API in "
|
| 120 |
+
"version 2.2.0. Use Manifolds instead.")
|
| 121 |
+
CERES_EXPORT LocalParameterization {
|
| 122 |
+
public:
|
| 123 |
+
virtual ~LocalParameterization();
|
| 124 |
+
|
| 125 |
+
// Generalization of the addition operation,
|
| 126 |
+
//
|
| 127 |
+
// x_plus_delta = Plus(x, delta)
|
| 128 |
+
//
|
| 129 |
+
// with the condition that Plus(x, 0) = x.
|
| 130 |
+
//
|
| 131 |
+
virtual bool Plus(const double* x,
|
| 132 |
+
const double* delta,
|
| 133 |
+
double* x_plus_delta) const = 0;
|
| 134 |
+
|
| 135 |
+
// The jacobian of Plus(x, delta) w.r.t delta at delta = 0.
|
| 136 |
+
//
|
| 137 |
+
// jacobian is a row-major GlobalSize() x LocalSize() matrix.
|
| 138 |
+
virtual bool ComputeJacobian(const double* x, double* jacobian) const = 0;
|
| 139 |
+
|
| 140 |
+
// local_matrix = global_matrix * jacobian
|
| 141 |
+
//
|
| 142 |
+
// global_matrix is a num_rows x GlobalSize row major matrix.
|
| 143 |
+
// local_matrix is a num_rows x LocalSize row major matrix.
|
| 144 |
+
// jacobian(x) is the matrix returned by ComputeJacobian at x.
|
| 145 |
+
//
|
| 146 |
+
// This is only used by GradientProblem. For most normal uses, it is
|
| 147 |
+
// okay to use the default implementation.
|
| 148 |
+
virtual bool MultiplyByJacobian(const double* x,
|
| 149 |
+
const int num_rows,
|
| 150 |
+
const double* global_matrix,
|
| 151 |
+
double* local_matrix) const;
|
| 152 |
+
|
| 153 |
+
// Size of x.
|
| 154 |
+
virtual int GlobalSize() const = 0;
|
| 155 |
+
|
| 156 |
+
// Size of delta.
|
| 157 |
+
virtual int LocalSize() const = 0;
|
| 158 |
+
};
|
| 159 |
+
|
| 160 |
+
// Some basic parameterizations
|
| 161 |
+
|
| 162 |
+
// Identity Parameterization: Plus(x, delta) = x + delta
|
| 163 |
+
class CERES_DEPRECATED_WITH_MSG("Use EuclideanManifold instead.")
|
| 164 |
+
CERES_EXPORT IdentityParameterization : public LocalParameterization {
|
| 165 |
+
public:
|
| 166 |
+
explicit IdentityParameterization(int size);
|
| 167 |
+
bool Plus(const double* x,
|
| 168 |
+
const double* delta,
|
| 169 |
+
double* x_plus_delta) const override;
|
| 170 |
+
bool ComputeJacobian(const double* x, double* jacobian) const override;
|
| 171 |
+
bool MultiplyByJacobian(const double* x,
|
| 172 |
+
const int num_cols,
|
| 173 |
+
const double* global_matrix,
|
| 174 |
+
double* local_matrix) const override;
|
| 175 |
+
int GlobalSize() const override { return size_; }
|
| 176 |
+
int LocalSize() const override { return size_; }
|
| 177 |
+
|
| 178 |
+
private:
|
| 179 |
+
const int size_;
|
| 180 |
+
};
|
| 181 |
+
|
| 182 |
+
// Hold a subset of the parameters inside a parameter block constant.
|
| 183 |
+
class CERES_DEPRECATED_WITH_MSG("Use SubsetManifold instead.")
|
| 184 |
+
CERES_EXPORT SubsetParameterization : public LocalParameterization {
|
| 185 |
+
public:
|
| 186 |
+
explicit SubsetParameterization(int size,
|
| 187 |
+
const std::vector<int>& constant_parameters);
|
| 188 |
+
bool Plus(const double* x,
|
| 189 |
+
const double* delta,
|
| 190 |
+
double* x_plus_delta) const override;
|
| 191 |
+
bool ComputeJacobian(const double* x, double* jacobian) const override;
|
| 192 |
+
bool MultiplyByJacobian(const double* x,
|
| 193 |
+
const int num_cols,
|
| 194 |
+
const double* global_matrix,
|
| 195 |
+
double* local_matrix) const override;
|
| 196 |
+
int GlobalSize() const override {
|
| 197 |
+
return static_cast<int>(constancy_mask_.size());
|
| 198 |
+
}
|
| 199 |
+
int LocalSize() const override { return local_size_; }
|
| 200 |
+
|
| 201 |
+
private:
|
| 202 |
+
const int local_size_;
|
| 203 |
+
std::vector<char> constancy_mask_;
|
| 204 |
+
};
|
| 205 |
+
|
| 206 |
+
// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x
|
| 207 |
+
// with * being the quaternion multiplication operator. Here we assume
|
| 208 |
+
// that the first element of the quaternion vector is the real (cos
|
| 209 |
+
// theta) part.
|
| 210 |
+
class CERES_DEPRECATED_WITH_MSG("Use QuaternionManifold instead.")
|
| 211 |
+
CERES_EXPORT QuaternionParameterization : public LocalParameterization {
|
| 212 |
+
public:
|
| 213 |
+
bool Plus(const double* x,
|
| 214 |
+
const double* delta,
|
| 215 |
+
double* x_plus_delta) const override;
|
| 216 |
+
bool ComputeJacobian(const double* x, double* jacobian) const override;
|
| 217 |
+
int GlobalSize() const override { return 4; }
|
| 218 |
+
int LocalSize() const override { return 3; }
|
| 219 |
+
};
|
| 220 |
+
|
| 221 |
+
// Implements the quaternion local parameterization for Eigen's representation
|
| 222 |
+
// of the quaternion. Eigen uses a different internal memory layout for the
|
| 223 |
+
// elements of the quaternion than what is commonly used. Specifically, Eigen
|
| 224 |
+
// stores the elements in memory as [x, y, z, w] where the real part is last
|
| 225 |
+
// whereas it is typically stored first. Note, when creating an Eigen quaternion
|
| 226 |
+
// through the constructor the elements are accepted in w, x, y, z order. Since
|
| 227 |
+
// Ceres operates on parameter blocks which are raw double pointers this
|
| 228 |
+
// difference is important and requires a different parameterization.
|
| 229 |
+
//
|
| 230 |
+
// Plus(x, delta) = [sin(|delta|) delta / |delta|, cos(|delta|)] * x
|
| 231 |
+
// with * being the quaternion multiplication operator.
|
| 232 |
+
class CERES_DEPRECATED_WITH_MSG("Use EigenQuaternionManifold instead.")
|
| 233 |
+
CERES_EXPORT EigenQuaternionParameterization
|
| 234 |
+
: public ceres::LocalParameterization {
|
| 235 |
+
public:
|
| 236 |
+
bool Plus(const double* x,
|
| 237 |
+
const double* delta,
|
| 238 |
+
double* x_plus_delta) const override;
|
| 239 |
+
bool ComputeJacobian(const double* x, double* jacobian) const override;
|
| 240 |
+
int GlobalSize() const override { return 4; }
|
| 241 |
+
int LocalSize() const override { return 3; }
|
| 242 |
+
};
|
| 243 |
+
|
| 244 |
+
// This provides a parameterization for homogeneous vectors which are commonly
|
| 245 |
+
// used in Structure from Motion problems. One example where they are used is
|
| 246 |
+
// in representing points whose triangulation is ill-conditioned. Here it is
|
| 247 |
+
// advantageous to use an over-parameterization since homogeneous vectors can
|
| 248 |
+
// represent points at infinity.
|
| 249 |
+
//
|
| 250 |
+
// The plus operator is defined as
|
| 251 |
+
// Plus(x, delta) =
|
| 252 |
+
// [sin(0.5 * |delta|) * delta / |delta|, cos(0.5 * |delta|)] * x
|
| 253 |
+
//
|
| 254 |
+
// with * defined as an operator which applies the update orthogonal to x to
|
| 255 |
+
// remain on the sphere. We assume that the last element of x is the scalar
|
| 256 |
+
// component. The size of the homogeneous vector is required to be greater than
|
| 257 |
+
// 1.
|
| 258 |
+
class CERES_DEPRECATED_WITH_MSG("Use SphereManifold instead.") CERES_EXPORT
|
| 259 |
+
HomogeneousVectorParameterization : public LocalParameterization {
|
| 260 |
+
public:
|
| 261 |
+
explicit HomogeneousVectorParameterization(int size);
|
| 262 |
+
bool Plus(const double* x,
|
| 263 |
+
const double* delta,
|
| 264 |
+
double* x_plus_delta) const override;
|
| 265 |
+
bool ComputeJacobian(const double* x, double* jacobian) const override;
|
| 266 |
+
int GlobalSize() const override { return size_; }
|
| 267 |
+
int LocalSize() const override { return size_ - 1; }
|
| 268 |
+
|
| 269 |
+
private:
|
| 270 |
+
const int size_;
|
| 271 |
+
};
|
| 272 |
+
|
| 273 |
+
// This provides a parameterization for lines, where the line is
|
| 274 |
+
// over-parameterized by an origin point and a direction vector. So the
|
| 275 |
+
// parameter vector size needs to be two times the ambient space dimension,
|
| 276 |
+
// where the first half is interpreted as the origin point and the second half
|
| 277 |
+
// as the direction.
|
| 278 |
+
//
|
| 279 |
+
// The plus operator for the line direction is the same as for the
|
| 280 |
+
// HomogeneousVectorParameterization. The update of the origin point is
|
| 281 |
+
// perpendicular to the line direction before the update.
|
| 282 |
+
//
|
| 283 |
+
// This local parameterization is a special case of the affine Grassmannian
|
| 284 |
+
// manifold (see https://en.wikipedia.org/wiki/Affine_Grassmannian_(manifold))
|
| 285 |
+
// for the case Graff_1(R^n).
|
| 286 |
+
template <int AmbientSpaceDimension>
|
| 287 |
+
class CERES_DEPRECATED_WITH_MSG("Use LineManifold instead.")
|
| 288 |
+
LineParameterization : public LocalParameterization {
|
| 289 |
+
public:
|
| 290 |
+
static_assert(AmbientSpaceDimension >= 2,
|
| 291 |
+
"The ambient space must be at least 2");
|
| 292 |
+
|
| 293 |
+
bool Plus(const double* x,
|
| 294 |
+
const double* delta,
|
| 295 |
+
double* x_plus_delta) const override;
|
| 296 |
+
bool ComputeJacobian(const double* x, double* jacobian) const override;
|
| 297 |
+
int GlobalSize() const override { return 2 * AmbientSpaceDimension; }
|
| 298 |
+
int LocalSize() const override { return 2 * (AmbientSpaceDimension - 1); }
|
| 299 |
+
};
|
| 300 |
+
|
| 301 |
+
// Construct a local parameterization by taking the Cartesian product
|
| 302 |
+
// of a number of other local parameterizations. This is useful, when
|
| 303 |
+
// a parameter block is the cartesian product of two or more
|
| 304 |
+
// manifolds. For example the parameters of a camera consist of a
|
| 305 |
+
// rotation and a translation, i.e., SO(3) x R^3.
|
| 306 |
+
//
|
| 307 |
+
// Example usage:
|
| 308 |
+
//
|
| 309 |
+
// ProductParameterization product_param(new QuaterionionParameterization(),
|
| 310 |
+
// new IdentityParameterization(3));
|
| 311 |
+
//
|
| 312 |
+
// is the local parameterization for a rigid transformation, where the
|
| 313 |
+
// rotation is represented using a quaternion.
|
| 314 |
+
//
|
| 315 |
+
class CERES_DEPRECATED_WITH_MSG("Use ProductManifold instead.")
|
| 316 |
+
CERES_EXPORT ProductParameterization : public LocalParameterization {
|
| 317 |
+
public:
|
| 318 |
+
ProductParameterization(const ProductParameterization&) = delete;
|
| 319 |
+
ProductParameterization& operator=(const ProductParameterization&) = delete;
|
| 320 |
+
//
|
| 321 |
+
// NOTE: The constructor takes ownership of the input local
|
| 322 |
+
// parameterizations.
|
| 323 |
+
//
|
| 324 |
+
template <typename... LocalParams>
|
| 325 |
+
explicit ProductParameterization(LocalParams*... local_params)
|
| 326 |
+
: local_params_(sizeof...(LocalParams)) {
|
| 327 |
+
constexpr int kNumLocalParams = sizeof...(LocalParams);
|
| 328 |
+
static_assert(kNumLocalParams >= 2,
|
| 329 |
+
"At least two local parameterizations must be specified.");
|
| 330 |
+
|
| 331 |
+
using LocalParameterizationPtr = std::unique_ptr<LocalParameterization>;
|
| 332 |
+
|
| 333 |
+
// Wrap all raw pointers into std::unique_ptr for exception safety.
|
| 334 |
+
std::array<LocalParameterizationPtr, kNumLocalParams> local_params_array{
|
| 335 |
+
LocalParameterizationPtr(local_params)...};
|
| 336 |
+
|
| 337 |
+
// Initialize internal state.
|
| 338 |
+
for (int i = 0; i < kNumLocalParams; ++i) {
|
| 339 |
+
LocalParameterizationPtr& param = local_params_[i];
|
| 340 |
+
param = std::move(local_params_array[i]);
|
| 341 |
+
|
| 342 |
+
buffer_size_ =
|
| 343 |
+
std::max(buffer_size_, param->LocalSize() * param->GlobalSize());
|
| 344 |
+
global_size_ += param->GlobalSize();
|
| 345 |
+
local_size_ += param->LocalSize();
|
| 346 |
+
}
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
bool Plus(const double* x,
|
| 350 |
+
const double* delta,
|
| 351 |
+
double* x_plus_delta) const override;
|
| 352 |
+
bool ComputeJacobian(const double* x, double* jacobian) const override;
|
| 353 |
+
int GlobalSize() const override { return global_size_; }
|
| 354 |
+
int LocalSize() const override { return local_size_; }
|
| 355 |
+
|
| 356 |
+
private:
|
| 357 |
+
std::vector<std::unique_ptr<LocalParameterization>> local_params_;
|
| 358 |
+
int local_size_{0};
|
| 359 |
+
int global_size_{0};
|
| 360 |
+
int buffer_size_{0};
|
| 361 |
+
};
|
| 362 |
+
|
| 363 |
+
} // namespace ceres
|
| 364 |
+
|
| 365 |
+
// clang-format off
|
| 366 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 367 |
+
// clang-format on
|
| 368 |
+
|
| 369 |
+
#include "ceres/internal/line_parameterization.h"
|
| 370 |
+
|
| 371 |
+
#endif // CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
|
ceres-v2/include/loss_function.h
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
//
|
| 31 |
+
// The LossFunction interface is the way users describe how residuals
|
| 32 |
+
// are converted to cost terms for the overall problem cost function.
|
| 33 |
+
// For the exact manner in which loss functions are converted to the
|
| 34 |
+
// overall cost for a problem, see problem.h.
|
| 35 |
+
//
|
| 36 |
+
// For least squares problem where there are no outliers and standard
|
| 37 |
+
// squared loss is expected, it is not necessary to create a loss
|
| 38 |
+
// function; instead passing a nullptr to the problem when adding
|
| 39 |
+
// residuals implies a standard squared loss.
|
| 40 |
+
//
|
| 41 |
+
// For least squares problems where the minimization may encounter
|
| 42 |
+
// input terms that contain outliers, that is, completely bogus
|
| 43 |
+
// measurements, it is important to use a loss function that reduces
|
| 44 |
+
// their associated penalty.
|
| 45 |
+
//
|
| 46 |
+
// Consider a structure from motion problem. The unknowns are 3D
|
| 47 |
+
// points and camera parameters, and the measurements are image
|
| 48 |
+
// coordinates describing the expected reprojected position for a
|
| 49 |
+
// point in a camera. For example, we want to model the geometry of a
|
| 50 |
+
// street scene with fire hydrants and cars, observed by a moving
|
| 51 |
+
// camera with unknown parameters, and the only 3D points we care
|
| 52 |
+
// about are the pointy tippy-tops of the fire hydrants. Our magic
|
| 53 |
+
// image processing algorithm, which is responsible for producing the
|
| 54 |
+
// measurements that are input to Ceres, has found and matched all
|
| 55 |
+
// such tippy-tops in all image frames, except that in one of the
|
| 56 |
+
// frame it mistook a car's headlight for a hydrant. If we didn't do
|
| 57 |
+
// anything special (i.e. if we used a basic quadratic loss), the
|
| 58 |
+
// residual for the erroneous measurement will result in extreme error
|
| 59 |
+
// due to the quadratic nature of squared loss. This results in the
|
| 60 |
+
// entire solution getting pulled away from the optimum to reduce
|
| 61 |
+
// the large error that would otherwise be attributed to the wrong
|
| 62 |
+
// measurement.
|
| 63 |
+
//
|
| 64 |
+
// Using a robust loss function, the cost for large residuals is
|
| 65 |
+
// reduced. In the example above, this leads to outlier terms getting
|
| 66 |
+
// downweighted so they do not overly influence the final solution.
|
| 67 |
+
//
|
| 68 |
+
// What cost function is best?
|
| 69 |
+
//
|
| 70 |
+
// In general, there isn't a principled way to select a robust loss
|
| 71 |
+
// function. The authors suggest starting with a non-robust cost, then
|
| 72 |
+
// only experimenting with robust loss functions if standard squared
|
| 73 |
+
// loss doesn't work.
|
| 74 |
+
|
| 75 |
+
#ifndef CERES_PUBLIC_LOSS_FUNCTION_H_
|
| 76 |
+
#define CERES_PUBLIC_LOSS_FUNCTION_H_
|
| 77 |
+
|
| 78 |
+
#include <memory>
|
| 79 |
+
|
| 80 |
+
#include "ceres/internal/disable_warnings.h"
|
| 81 |
+
#include "ceres/internal/export.h"
|
| 82 |
+
#include "ceres/types.h"
|
| 83 |
+
#include "glog/logging.h"
|
| 84 |
+
|
| 85 |
+
namespace ceres {
|
| 86 |
+
|
| 87 |
+
class CERES_EXPORT LossFunction {
|
| 88 |
+
public:
|
| 89 |
+
virtual ~LossFunction();
|
| 90 |
+
|
| 91 |
+
// For a residual vector with squared 2-norm 'sq_norm', this method
|
| 92 |
+
// is required to fill in the value and derivatives of the loss
|
| 93 |
+
// function (rho in this example):
|
| 94 |
+
//
|
| 95 |
+
// out[0] = rho(sq_norm),
|
| 96 |
+
// out[1] = rho'(sq_norm),
|
| 97 |
+
// out[2] = rho''(sq_norm),
|
| 98 |
+
//
|
| 99 |
+
// Here the convention is that the contribution of a term to the
|
| 100 |
+
// cost function is given by 1/2 rho(s), where
|
| 101 |
+
//
|
| 102 |
+
// s = ||residuals||^2.
|
| 103 |
+
//
|
| 104 |
+
// Calling the method with a negative value of 's' is an error and
|
| 105 |
+
// the implementations are not required to handle that case.
|
| 106 |
+
//
|
| 107 |
+
// Most sane choices of rho() satisfy:
|
| 108 |
+
//
|
| 109 |
+
// rho(0) = 0,
|
| 110 |
+
// rho'(0) = 1,
|
| 111 |
+
// rho'(s) < 1 in outlier region,
|
| 112 |
+
// rho''(s) < 0 in outlier region,
|
| 113 |
+
//
|
| 114 |
+
// so that they mimic the least squares cost for small residuals.
|
| 115 |
+
virtual void Evaluate(double sq_norm, double out[3]) const = 0;
|
| 116 |
+
};
|
| 117 |
+
|
| 118 |
+
// Some common implementations follow below.
|
| 119 |
+
//
|
| 120 |
+
// Note: in the region of interest (i.e. s < 3) we have:
|
| 121 |
+
// TrivialLoss >= HuberLoss >= SoftLOneLoss >= CauchyLoss
|
| 122 |
+
|
| 123 |
+
// This corresponds to no robustification.
|
| 124 |
+
//
|
| 125 |
+
// rho(s) = s
|
| 126 |
+
//
|
| 127 |
+
// At s = 0: rho = [0, 1, 0].
|
| 128 |
+
//
|
| 129 |
+
// It is not normally necessary to use this, as passing nullptr for the
|
| 130 |
+
// loss function when building the problem accomplishes the same
|
| 131 |
+
// thing.
|
| 132 |
+
class CERES_EXPORT TrivialLoss final : public LossFunction {
|
| 133 |
+
public:
|
| 134 |
+
void Evaluate(double, double*) const override;
|
| 135 |
+
};
|
| 136 |
+
|
| 137 |
+
// Scaling
|
| 138 |
+
// -------
|
| 139 |
+
// Given one robustifier
|
| 140 |
+
// s -> rho(s)
|
| 141 |
+
// one can change the length scale at which robustification takes
|
| 142 |
+
// place, by adding a scale factor 'a' as follows:
|
| 143 |
+
//
|
| 144 |
+
// s -> a^2 rho(s / a^2).
|
| 145 |
+
//
|
| 146 |
+
// The first and second derivatives are:
|
| 147 |
+
//
|
| 148 |
+
// s -> rho'(s / a^2),
|
| 149 |
+
// s -> (1 / a^2) rho''(s / a^2),
|
| 150 |
+
//
|
| 151 |
+
// but the behaviour near s = 0 is the same as the original function,
|
| 152 |
+
// i.e.
|
| 153 |
+
//
|
| 154 |
+
// rho(s) = s + higher order terms,
|
| 155 |
+
// a^2 rho(s / a^2) = s + higher order terms.
|
| 156 |
+
//
|
| 157 |
+
// The scalar 'a' should be positive.
|
| 158 |
+
//
|
| 159 |
+
// The reason for the appearance of squaring is that 'a' is in the
|
| 160 |
+
// units of the residual vector norm whereas 's' is a squared
|
| 161 |
+
// norm. For applications it is more convenient to specify 'a' than
|
| 162 |
+
// its square. The commonly used robustifiers below are described in
|
| 163 |
+
// un-scaled format (a = 1) but their implementations work for any
|
| 164 |
+
// non-zero value of 'a'.
|
| 165 |
+
|
| 166 |
+
// Huber.
|
| 167 |
+
//
|
| 168 |
+
// rho(s) = s for s <= 1,
|
| 169 |
+
// rho(s) = 2 sqrt(s) - 1 for s >= 1.
|
| 170 |
+
//
|
| 171 |
+
// At s = 0: rho = [0, 1, 0].
|
| 172 |
+
//
|
| 173 |
+
// The scaling parameter 'a' corresponds to 'delta' on this page:
|
| 174 |
+
// http://en.wikipedia.org/wiki/Huber_Loss_Function
|
| 175 |
+
class CERES_EXPORT HuberLoss final : public LossFunction {
|
| 176 |
+
public:
|
| 177 |
+
explicit HuberLoss(double a) : a_(a), b_(a * a) {}
|
| 178 |
+
void Evaluate(double, double*) const override;
|
| 179 |
+
|
| 180 |
+
private:
|
| 181 |
+
const double a_;
|
| 182 |
+
// b = a^2.
|
| 183 |
+
const double b_;
|
| 184 |
+
};
|
| 185 |
+
|
| 186 |
+
// Soft L1, similar to Huber but smooth.
|
| 187 |
+
//
|
| 188 |
+
// rho(s) = 2 (sqrt(1 + s) - 1).
|
| 189 |
+
//
|
| 190 |
+
// At s = 0: rho = [0, 1, -1 / (2 * a^2)].
|
| 191 |
+
class CERES_EXPORT SoftLOneLoss final : public LossFunction {
|
| 192 |
+
public:
|
| 193 |
+
explicit SoftLOneLoss(double a) : b_(a * a), c_(1 / b_) {}
|
| 194 |
+
void Evaluate(double, double*) const override;
|
| 195 |
+
|
| 196 |
+
private:
|
| 197 |
+
// b = a^2.
|
| 198 |
+
const double b_;
|
| 199 |
+
// c = 1 / a^2.
|
| 200 |
+
const double c_;
|
| 201 |
+
};
|
| 202 |
+
|
| 203 |
+
// Inspired by the Cauchy distribution
|
| 204 |
+
//
|
| 205 |
+
// rho(s) = log(1 + s).
|
| 206 |
+
//
|
| 207 |
+
// At s = 0: rho = [0, 1, -1 / a^2].
|
| 208 |
+
class CERES_EXPORT CauchyLoss final : public LossFunction {
|
| 209 |
+
public:
|
| 210 |
+
explicit CauchyLoss(double a) : b_(a * a), c_(1 / b_) {}
|
| 211 |
+
void Evaluate(double, double*) const override;
|
| 212 |
+
|
| 213 |
+
private:
|
| 214 |
+
// b = a^2.
|
| 215 |
+
const double b_;
|
| 216 |
+
// c = 1 / a^2.
|
| 217 |
+
const double c_;
|
| 218 |
+
};
|
| 219 |
+
|
| 220 |
+
// Loss that is capped beyond a certain level using the arc-tangent function.
|
| 221 |
+
// The scaling parameter 'a' determines the level where falloff occurs.
|
| 222 |
+
// For costs much smaller than 'a', the loss function is linear and behaves like
|
| 223 |
+
// TrivialLoss, and for values much larger than 'a' the value asymptotically
|
| 224 |
+
// approaches the constant value of a * PI / 2.
|
| 225 |
+
//
|
| 226 |
+
// rho(s) = a atan(s / a).
|
| 227 |
+
//
|
| 228 |
+
// At s = 0: rho = [0, 1, 0].
|
| 229 |
+
class CERES_EXPORT ArctanLoss final : public LossFunction {
|
| 230 |
+
public:
|
| 231 |
+
explicit ArctanLoss(double a) : a_(a), b_(1 / (a * a)) {}
|
| 232 |
+
void Evaluate(double, double*) const override;
|
| 233 |
+
|
| 234 |
+
private:
|
| 235 |
+
const double a_;
|
| 236 |
+
// b = 1 / a^2.
|
| 237 |
+
const double b_;
|
| 238 |
+
};
|
| 239 |
+
|
| 240 |
+
// Loss function that maps to approximately zero cost in a range around the
|
| 241 |
+
// origin, and reverts to linear in error (quadratic in cost) beyond this range.
|
| 242 |
+
// The tolerance parameter 'a' sets the nominal point at which the
|
| 243 |
+
// transition occurs, and the transition size parameter 'b' sets the nominal
|
| 244 |
+
// distance over which most of the transition occurs. Both a and b must be
|
| 245 |
+
// greater than zero, and typically b will be set to a fraction of a.
|
| 246 |
+
// The slope rho'[s] varies smoothly from about 0 at s <= a - b to
|
| 247 |
+
// about 1 at s >= a + b.
|
| 248 |
+
//
|
| 249 |
+
// The term is computed as:
|
| 250 |
+
//
|
| 251 |
+
// rho(s) = b log(1 + exp((s - a) / b)) - c0.
|
| 252 |
+
//
|
| 253 |
+
// where c0 is chosen so that rho(0) == 0
|
| 254 |
+
//
|
| 255 |
+
// c0 = b log(1 + exp(-a / b)
|
| 256 |
+
//
|
| 257 |
+
// This has the following useful properties:
|
| 258 |
+
//
|
| 259 |
+
// rho(s) == 0 for s = 0
|
| 260 |
+
// rho'(s) ~= 0 for s << a - b
|
| 261 |
+
// rho'(s) ~= 1 for s >> a + b
|
| 262 |
+
// rho''(s) > 0 for all s
|
| 263 |
+
//
|
| 264 |
+
// In addition, all derivatives are continuous, and the curvature is
|
| 265 |
+
// concentrated in the range a - b to a + b.
|
| 266 |
+
//
|
| 267 |
+
// At s = 0: rho = [0, ~0, ~0].
|
| 268 |
+
class CERES_EXPORT TolerantLoss final : public LossFunction {
|
| 269 |
+
public:
|
| 270 |
+
explicit TolerantLoss(double a, double b);
|
| 271 |
+
void Evaluate(double, double*) const override;
|
| 272 |
+
|
| 273 |
+
private:
|
| 274 |
+
const double a_, b_, c_;
|
| 275 |
+
};
|
| 276 |
+
|
| 277 |
+
// This is the Tukey biweight loss function which aggressively
|
| 278 |
+
// attempts to suppress large errors.
|
| 279 |
+
//
|
| 280 |
+
// The term is computed as follows where the equations are scaled by a
|
| 281 |
+
// factor of 2 because the cost function is given by 1/2 rho(s):
|
| 282 |
+
//
|
| 283 |
+
// rho(s) = a^2 / 3 * (1 - (1 - s / a^2)^3 ) for s <= a^2,
|
| 284 |
+
// rho(s) = a^2 / 3 for s > a^2.
|
| 285 |
+
//
|
| 286 |
+
// At s = 0: rho = [0, 1, -2 / a^2]
|
| 287 |
+
class CERES_EXPORT TukeyLoss final : public ceres::LossFunction {
|
| 288 |
+
public:
|
| 289 |
+
explicit TukeyLoss(double a) : a_squared_(a * a) {}
|
| 290 |
+
void Evaluate(double, double*) const override;
|
| 291 |
+
|
| 292 |
+
private:
|
| 293 |
+
const double a_squared_;
|
| 294 |
+
};
|
| 295 |
+
|
| 296 |
+
// Composition of two loss functions. The error is the result of first
|
| 297 |
+
// evaluating g followed by f to yield the composition f(g(s)).
|
| 298 |
+
// The loss functions must not be nullptr.
|
| 299 |
+
class CERES_EXPORT ComposedLoss final : public LossFunction {
|
| 300 |
+
public:
|
| 301 |
+
explicit ComposedLoss(const LossFunction* f,
|
| 302 |
+
Ownership ownership_f,
|
| 303 |
+
const LossFunction* g,
|
| 304 |
+
Ownership ownership_g);
|
| 305 |
+
~ComposedLoss() override;
|
| 306 |
+
void Evaluate(double, double*) const override;
|
| 307 |
+
|
| 308 |
+
private:
|
| 309 |
+
std::unique_ptr<const LossFunction> f_, g_;
|
| 310 |
+
const Ownership ownership_f_, ownership_g_;
|
| 311 |
+
};
|
| 312 |
+
|
| 313 |
+
// The discussion above has to do with length scaling: it affects the space
|
| 314 |
+
// in which s is measured. Sometimes you want to simply scale the output
|
| 315 |
+
// value of the robustifier. For example, you might want to weight
|
| 316 |
+
// different error terms differently (e.g., weight pixel reprojection
|
| 317 |
+
// errors differently from terrain errors).
|
| 318 |
+
//
|
| 319 |
+
// If rho is the wrapped robustifier, then this simply outputs
|
| 320 |
+
// s -> a * rho(s)
|
| 321 |
+
//
|
| 322 |
+
// The first and second derivatives are, not surprisingly
|
| 323 |
+
// s -> a * rho'(s)
|
| 324 |
+
// s -> a * rho''(s)
|
| 325 |
+
//
|
| 326 |
+
// Since we treat the a nullptr Loss function as the Identity loss
|
| 327 |
+
// function, rho = nullptr is a valid input and will result in the input
|
| 328 |
+
// being scaled by a. This provides a simple way of implementing a
|
| 329 |
+
// scaled ResidualBlock.
|
| 330 |
+
class CERES_EXPORT ScaledLoss final : public LossFunction {
|
| 331 |
+
public:
|
| 332 |
+
// Constructs a ScaledLoss wrapping another loss function. Takes
|
| 333 |
+
// ownership of the wrapped loss function or not depending on the
|
| 334 |
+
// ownership parameter.
|
| 335 |
+
ScaledLoss(const LossFunction* rho, double a, Ownership ownership)
|
| 336 |
+
: rho_(rho), a_(a), ownership_(ownership) {}
|
| 337 |
+
ScaledLoss(const ScaledLoss&) = delete;
|
| 338 |
+
void operator=(const ScaledLoss&) = delete;
|
| 339 |
+
|
| 340 |
+
~ScaledLoss() override {
|
| 341 |
+
if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
|
| 342 |
+
rho_.release();
|
| 343 |
+
}
|
| 344 |
+
}
|
| 345 |
+
void Evaluate(double, double*) const override;
|
| 346 |
+
|
| 347 |
+
private:
|
| 348 |
+
std::unique_ptr<const LossFunction> rho_;
|
| 349 |
+
const double a_;
|
| 350 |
+
const Ownership ownership_;
|
| 351 |
+
};
|
| 352 |
+
|
| 353 |
+
// Sometimes after the optimization problem has been constructed, we
|
| 354 |
+
// wish to mutate the scale of the loss function. For example, when
|
| 355 |
+
// performing estimation from data which has substantial outliers,
|
| 356 |
+
// convergence can be improved by starting out with a large scale,
|
| 357 |
+
// optimizing the problem and then reducing the scale. This can have
|
| 358 |
+
// better convergence behaviour than just using a loss function with a
|
| 359 |
+
// small scale.
|
| 360 |
+
//
|
| 361 |
+
// This templated class allows the user to implement a loss function
|
| 362 |
+
// whose scale can be mutated after an optimization problem has been
|
| 363 |
+
// constructed.
|
| 364 |
+
//
|
| 365 |
+
// Since we treat the a nullptr Loss function as the Identity loss
|
| 366 |
+
// function, rho = nullptr is a valid input.
|
| 367 |
+
//
|
| 368 |
+
// Example usage
|
| 369 |
+
//
|
| 370 |
+
// Problem problem;
|
| 371 |
+
//
|
| 372 |
+
// // Add parameter blocks
|
| 373 |
+
//
|
| 374 |
+
// CostFunction* cost_function =
|
| 375 |
+
// new AutoDiffCostFunction < UW_Camera_Mapper, 2, 9, 3>(
|
| 376 |
+
// new UW_Camera_Mapper(feature_x, feature_y));
|
| 377 |
+
//
|
| 378 |
+
// LossFunctionWrapper* loss_function = new LossFunctionWrapper(
|
| 379 |
+
// new HuberLoss(1.0), TAKE_OWNERSHIP);
|
| 380 |
+
//
|
| 381 |
+
// problem.AddResidualBlock(cost_function, loss_function, parameters);
|
| 382 |
+
//
|
| 383 |
+
// Solver::Options options;
|
| 384 |
+
// Solger::Summary summary;
|
| 385 |
+
//
|
| 386 |
+
// Solve(options, &problem, &summary)
|
| 387 |
+
//
|
| 388 |
+
// loss_function->Reset(new HuberLoss(1.0), TAKE_OWNERSHIP);
|
| 389 |
+
//
|
| 390 |
+
// Solve(options, &problem, &summary)
|
| 391 |
+
//
|
| 392 |
+
class CERES_EXPORT LossFunctionWrapper final : public LossFunction {
|
| 393 |
+
public:
|
| 394 |
+
LossFunctionWrapper(LossFunction* rho, Ownership ownership)
|
| 395 |
+
: rho_(rho), ownership_(ownership) {}
|
| 396 |
+
|
| 397 |
+
LossFunctionWrapper(const LossFunctionWrapper&) = delete;
|
| 398 |
+
void operator=(const LossFunctionWrapper&) = delete;
|
| 399 |
+
|
| 400 |
+
~LossFunctionWrapper() override {
|
| 401 |
+
if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
|
| 402 |
+
rho_.release();
|
| 403 |
+
}
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
void Evaluate(double sq_norm, double out[3]) const override {
|
| 407 |
+
if (rho_.get() == nullptr) {
|
| 408 |
+
out[0] = sq_norm;
|
| 409 |
+
out[1] = 1.0;
|
| 410 |
+
out[2] = 0.0;
|
| 411 |
+
} else {
|
| 412 |
+
rho_->Evaluate(sq_norm, out);
|
| 413 |
+
}
|
| 414 |
+
}
|
| 415 |
+
|
| 416 |
+
void Reset(LossFunction* rho, Ownership ownership) {
|
| 417 |
+
if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
|
| 418 |
+
rho_.release();
|
| 419 |
+
}
|
| 420 |
+
rho_.reset(rho);
|
| 421 |
+
ownership_ = ownership;
|
| 422 |
+
}
|
| 423 |
+
|
| 424 |
+
private:
|
| 425 |
+
std::unique_ptr<const LossFunction> rho_;
|
| 426 |
+
Ownership ownership_;
|
| 427 |
+
};
|
| 428 |
+
|
| 429 |
+
} // namespace ceres
|
| 430 |
+
|
| 431 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 432 |
+
|
| 433 |
+
#endif // CERES_PUBLIC_LOSS_FUNCTION_H_
|
ceres-v2/include/manifold.h
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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 |
+
|
| 31 |
+
#ifndef CERES_PUBLIC_MANIFOLD_H_
|
| 32 |
+
#define CERES_PUBLIC_MANIFOLD_H_
|
| 33 |
+
|
| 34 |
+
#include <Eigen/Core>
|
| 35 |
+
#include <algorithm>
|
| 36 |
+
#include <array>
|
| 37 |
+
#include <memory>
|
| 38 |
+
#include <utility>
|
| 39 |
+
#include <vector>
|
| 40 |
+
|
| 41 |
+
#include "ceres/internal/disable_warnings.h"
|
| 42 |
+
#include "ceres/internal/export.h"
|
| 43 |
+
#include "ceres/types.h"
|
| 44 |
+
#include "glog/logging.h"
|
| 45 |
+
|
| 46 |
+
namespace ceres {
|
| 47 |
+
|
| 48 |
+
// In sensor fusion problems, often we have to model quantities that live in
|
| 49 |
+
// spaces known as Manifolds, for example the rotation/orientation of a sensor
|
| 50 |
+
// that is represented by a quaternion.
|
| 51 |
+
//
|
| 52 |
+
// Manifolds are spaces which locally look like Euclidean spaces. More
|
| 53 |
+
// precisely, at each point on the manifold there is a linear space that is
|
| 54 |
+
// tangent to the manifold. It has dimension equal to the intrinsic dimension of
|
| 55 |
+
// the manifold itself, which is less than or equal to the ambient space in
|
| 56 |
+
// which the manifold is embedded.
|
| 57 |
+
//
|
| 58 |
+
// For example, the tangent space to a point on a sphere in three dimensions is
|
| 59 |
+
// the two dimensional plane that is tangent to the sphere at that point. There
|
| 60 |
+
// are two reasons tangent spaces are interesting:
|
| 61 |
+
//
|
| 62 |
+
// 1. They are Eucliean spaces so the usual vector space operations apply there,
|
| 63 |
+
// which makes numerical operations easy.
|
| 64 |
+
// 2. Movement in the tangent space translate into movements along the manifold.
|
| 65 |
+
// Movements perpendicular to the tangent space do not translate into
|
| 66 |
+
// movements on the manifold.
|
| 67 |
+
//
|
| 68 |
+
// Returning to our sphere example, moving in the 2 dimensional plane
|
| 69 |
+
// tangent to the sphere and projecting back onto the sphere will move you away
|
| 70 |
+
// from the point you started from but moving along the normal at the same point
|
| 71 |
+
// and the projecting back onto the sphere brings you back to the point.
|
| 72 |
+
//
|
| 73 |
+
// The Manifold interface defines two operations (and their derivatives)
|
| 74 |
+
// involving the tangent space, allowing filtering and optimization to be
|
| 75 |
+
// performed on said manifold:
|
| 76 |
+
//
|
| 77 |
+
// 1. x_plus_delta = Plus(x, delta)
|
| 78 |
+
// 2. delta = Minus(x_plus_delta, x)
|
| 79 |
+
//
|
| 80 |
+
// "Plus" computes the result of moving along delta in the tangent space at x,
|
| 81 |
+
// and then projecting back onto the manifold that x belongs to. In Differential
|
| 82 |
+
// Geometry this is known as a "Retraction". It is a generalization of vector
|
| 83 |
+
// addition in Euclidean spaces.
|
| 84 |
+
//
|
| 85 |
+
// Given two points on the manifold, "Minus" computes the change delta to x in
|
| 86 |
+
// the tangent space at x, that will take it to x_plus_delta.
|
| 87 |
+
//
|
| 88 |
+
// Let us now consider two examples.
|
| 89 |
+
//
|
| 90 |
+
// The Euclidean space R^n is the simplest example of a manifold. It has
|
| 91 |
+
// dimension n (and so does its tangent space) and Plus and Minus are the
|
| 92 |
+
// familiar vector sum and difference operations.
|
| 93 |
+
//
|
| 94 |
+
// Plus(x, delta) = x + delta = y,
|
| 95 |
+
// Minus(y, x) = y - x = delta.
|
| 96 |
+
//
|
| 97 |
+
// A more interesting case is SO(3), the special orthogonal group in three
|
| 98 |
+
// dimensions - the space of 3x3 rotation matrices. SO(3) is a three dimensional
|
| 99 |
+
// manifold embedded in R^9 or R^(3x3). So points on SO(3) are represented using
|
| 100 |
+
// 9 dimensional vectors or 3x3 matrices, and points in its tangent spaces are
|
| 101 |
+
// represented by 3 dimensional vectors.
|
| 102 |
+
//
|
| 103 |
+
// Defining Plus and Minus are defined in terms of the matrix Exp and Log
|
| 104 |
+
// operations as follows:
|
| 105 |
+
//
|
| 106 |
+
// Let Exp(p, q, r) = [cos(theta) + cp^2, -sr + cpq , sq + cpr ]
|
| 107 |
+
// [sr + cpq , cos(theta) + cq^2, -sp + cqr ]
|
| 108 |
+
// [-sq + cpr , sp + cqr , cos(theta) + cr^2]
|
| 109 |
+
//
|
| 110 |
+
// where: theta = sqrt(p^2 + q^2 + r^2)
|
| 111 |
+
// s = sinc(theta)
|
| 112 |
+
// c = (1 - cos(theta))/theta^2
|
| 113 |
+
//
|
| 114 |
+
// and Log(x) = 1/(2 sinc(theta))[x_32 - x_23, x_13 - x_31, x_21 - x_12]
|
| 115 |
+
//
|
| 116 |
+
// where: theta = acos((Trace(x) - 1)/2)
|
| 117 |
+
//
|
| 118 |
+
// Then,
|
| 119 |
+
//
|
| 120 |
+
// Plus(x, delta) = x Exp(delta)
|
| 121 |
+
// Minus(y, x) = Log(x^T y)
|
| 122 |
+
//
|
| 123 |
+
// For Plus and Minus to be mathematically consistent, the following identities
|
| 124 |
+
// must be satisfied at all points x on the manifold:
|
| 125 |
+
//
|
| 126 |
+
// 1. Plus(x, 0) = x.
|
| 127 |
+
// 2. For all y, Plus(x, Minus(y, x)) = y.
|
| 128 |
+
// 3. For all delta, Minus(Plus(x, delta), x) = delta.
|
| 129 |
+
// 4. For all delta_1, delta_2
|
| 130 |
+
// |Minus(Plus(x, delta_1), Plus(x, delta_2)) <= |delta_1 - delta_2|
|
| 131 |
+
//
|
| 132 |
+
// Briefly:
|
| 133 |
+
// (1) Ensures that the tangent space is "centered" at x, and the zero vector is
|
| 134 |
+
// the identity element.
|
| 135 |
+
// (2) Ensures that any y can be reached from x.
|
| 136 |
+
// (3) Ensures that Plus is an injective (one-to-one) map.
|
| 137 |
+
// (4) Allows us to define a metric on the manifold.
|
| 138 |
+
//
|
| 139 |
+
// Additionally we require that Plus and Minus be sufficiently smooth. In
|
| 140 |
+
// particular they need to be differentiable everywhere on the manifold.
|
| 141 |
+
//
|
| 142 |
+
// For more details, please see
|
| 143 |
+
//
|
| 144 |
+
// "Integrating Generic Sensor Fusion Algorithms with Sound State
|
| 145 |
+
// Representations through Encapsulation of Manifolds"
|
| 146 |
+
// By C. Hertzberg, R. Wagner, U. Frese and L. Schroder
|
| 147 |
+
// https://arxiv.org/pdf/1107.1119.pdf
|
| 148 |
+
class CERES_EXPORT Manifold {
|
| 149 |
+
public:
|
| 150 |
+
virtual ~Manifold();
|
| 151 |
+
|
| 152 |
+
// Dimension of the ambient space in which the manifold is embedded.
|
| 153 |
+
virtual int AmbientSize() const = 0;
|
| 154 |
+
|
| 155 |
+
// Dimension of the manifold/tangent space.
|
| 156 |
+
virtual int TangentSize() const = 0;
|
| 157 |
+
|
| 158 |
+
// x_plus_delta = Plus(x, delta),
|
| 159 |
+
//
|
| 160 |
+
// A generalization of vector addition in Euclidean space, Plus computes the
|
| 161 |
+
// result of moving along delta in the tangent space at x, and then projecting
|
| 162 |
+
// back onto the manifold that x belongs to.
|
| 163 |
+
//
|
| 164 |
+
// x and x_plus_delta are AmbientSize() vectors.
|
| 165 |
+
// delta is a TangentSize() vector.
|
| 166 |
+
//
|
| 167 |
+
// Return value indicates if the operation was successful or not.
|
| 168 |
+
virtual bool Plus(const double* x,
|
| 169 |
+
const double* delta,
|
| 170 |
+
double* x_plus_delta) const = 0;
|
| 171 |
+
|
| 172 |
+
// Compute the derivative of Plus(x, delta) w.r.t delta at delta = 0, i.e.
|
| 173 |
+
//
|
| 174 |
+
// (D_2 Plus)(x, 0)
|
| 175 |
+
//
|
| 176 |
+
// jacobian is a row-major AmbientSize() x TangentSize() matrix.
|
| 177 |
+
//
|
| 178 |
+
// Return value indicates whether the operation was successful or not.
|
| 179 |
+
virtual bool PlusJacobian(const double* x, double* jacobian) const = 0;
|
| 180 |
+
|
| 181 |
+
// tangent_matrix = ambient_matrix * (D_2 Plus)(x, 0)
|
| 182 |
+
//
|
| 183 |
+
// ambient_matrix is a row-major num_rows x AmbientSize() matrix.
|
| 184 |
+
// tangent_matrix is a row-major num_rows x TangentSize() matrix.
|
| 185 |
+
//
|
| 186 |
+
// Return value indicates whether the operation was successful or not.
|
| 187 |
+
//
|
| 188 |
+
// This function is only used by the GradientProblemSolver, where the
|
| 189 |
+
// dimension of the parameter block can be large and it may be more efficient
|
| 190 |
+
// to compute this product directly rather than first evaluating the Jacobian
|
| 191 |
+
// into a matrix and then doing a matrix vector product.
|
| 192 |
+
//
|
| 193 |
+
// Because this is not an often used function, we provide a default
|
| 194 |
+
// implementation for convenience. If performance becomes an issue then the
|
| 195 |
+
// user should consider implementing a specialization.
|
| 196 |
+
virtual bool RightMultiplyByPlusJacobian(const double* x,
|
| 197 |
+
const int num_rows,
|
| 198 |
+
const double* ambient_matrix,
|
| 199 |
+
double* tangent_matrix) const;
|
| 200 |
+
|
| 201 |
+
// y_minus_x = Minus(y, x)
|
| 202 |
+
//
|
| 203 |
+
// Given two points on the manifold, Minus computes the change to x in the
|
| 204 |
+
// tangent space at x, that will take it to y.
|
| 205 |
+
//
|
| 206 |
+
// x and y are AmbientSize() vectors.
|
| 207 |
+
// y_minus_x is a TangentSize() vector.
|
| 208 |
+
//
|
| 209 |
+
// Return value indicates if the operation was successful or not.
|
| 210 |
+
virtual bool Minus(const double* y,
|
| 211 |
+
const double* x,
|
| 212 |
+
double* y_minus_x) const = 0;
|
| 213 |
+
|
| 214 |
+
// Compute the derivative of Minus(y, x) w.r.t y at y = x, i.e
|
| 215 |
+
//
|
| 216 |
+
// (D_1 Minus) (x, x)
|
| 217 |
+
//
|
| 218 |
+
// Jacobian is a row-major TangentSize() x AmbientSize() matrix.
|
| 219 |
+
//
|
| 220 |
+
// Return value indicates whether the operation was successful or not.
|
| 221 |
+
virtual bool MinusJacobian(const double* x, double* jacobian) const = 0;
|
| 222 |
+
};
|
| 223 |
+
|
| 224 |
+
// The Euclidean manifold is another name for the ordinary vector space R^size,
|
| 225 |
+
// where the plus and minus operations are the usual vector addition and
|
| 226 |
+
// subtraction:
|
| 227 |
+
// Plus(x, delta) = x + delta
|
| 228 |
+
// Minus(y, x) = y - x.
|
| 229 |
+
//
|
| 230 |
+
// The class works with dynamic and static ambient space dimensions. If the
|
| 231 |
+
// ambient space dimensions is know at compile time use
|
| 232 |
+
//
|
| 233 |
+
// EuclideanManifold<3> manifold;
|
| 234 |
+
//
|
| 235 |
+
// If the ambient space dimensions is not known at compile time the template
|
| 236 |
+
// parameter needs to be set to ceres::DYNAMIC and the actual dimension needs
|
| 237 |
+
// to be provided as a constructor argument:
|
| 238 |
+
//
|
| 239 |
+
// EuclideanManifold<ceres::DYNAMIC> manifold(ambient_dim);
|
| 240 |
+
template <int Size>
|
| 241 |
+
class EuclideanManifold final : public Manifold {
|
| 242 |
+
public:
|
| 243 |
+
static_assert(Size == ceres::DYNAMIC || Size >= 0,
|
| 244 |
+
"The size of the manifold needs to be non-negative.");
|
| 245 |
+
static_assert(ceres::DYNAMIC == Eigen::Dynamic,
|
| 246 |
+
"ceres::DYNAMIC needs to be the same as Eigen::Dynamic.");
|
| 247 |
+
|
| 248 |
+
EuclideanManifold() : size_{Size} {
|
| 249 |
+
static_assert(
|
| 250 |
+
Size != ceres::DYNAMIC,
|
| 251 |
+
"The size is set to dynamic. Please call the constructor with a size.");
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
explicit EuclideanManifold(int size) : size_(size) {
|
| 255 |
+
if (Size != ceres::DYNAMIC) {
|
| 256 |
+
CHECK_EQ(Size, size)
|
| 257 |
+
<< "Specified size by template parameter differs from the supplied "
|
| 258 |
+
"one.";
|
| 259 |
+
} else {
|
| 260 |
+
CHECK_GE(size_, 0)
|
| 261 |
+
<< "The size of the manifold needs to be non-negative.";
|
| 262 |
+
}
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
int AmbientSize() const override { return size_; }
|
| 266 |
+
int TangentSize() const override { return size_; }
|
| 267 |
+
|
| 268 |
+
bool Plus(const double* x_ptr,
|
| 269 |
+
const double* delta_ptr,
|
| 270 |
+
double* x_plus_delta_ptr) const override {
|
| 271 |
+
Eigen::Map<const AmbientVector> x(x_ptr, size_);
|
| 272 |
+
Eigen::Map<const AmbientVector> delta(delta_ptr, size_);
|
| 273 |
+
Eigen::Map<AmbientVector> x_plus_delta(x_plus_delta_ptr, size_);
|
| 274 |
+
x_plus_delta = x + delta;
|
| 275 |
+
return true;
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
bool PlusJacobian(const double* x_ptr, double* jacobian_ptr) const override {
|
| 279 |
+
Eigen::Map<MatrixJacobian> jacobian(jacobian_ptr, size_, size_);
|
| 280 |
+
jacobian.setIdentity();
|
| 281 |
+
return true;
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
bool RightMultiplyByPlusJacobian(const double* x,
|
| 285 |
+
const int num_rows,
|
| 286 |
+
const double* ambient_matrix,
|
| 287 |
+
double* tangent_matrix) const override {
|
| 288 |
+
std::copy_n(ambient_matrix, num_rows * size_, tangent_matrix);
|
| 289 |
+
return true;
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
bool Minus(const double* y_ptr,
|
| 293 |
+
const double* x_ptr,
|
| 294 |
+
double* y_minus_x_ptr) const override {
|
| 295 |
+
Eigen::Map<const AmbientVector> x(x_ptr, size_);
|
| 296 |
+
Eigen::Map<const AmbientVector> y(y_ptr, size_);
|
| 297 |
+
Eigen::Map<AmbientVector> y_minus_x(y_minus_x_ptr, size_);
|
| 298 |
+
y_minus_x = y - x;
|
| 299 |
+
return true;
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
bool MinusJacobian(const double* x_ptr, double* jacobian_ptr) const override {
|
| 303 |
+
Eigen::Map<MatrixJacobian> jacobian(jacobian_ptr, size_, size_);
|
| 304 |
+
jacobian.setIdentity();
|
| 305 |
+
return true;
|
| 306 |
+
}
|
| 307 |
+
|
| 308 |
+
private:
|
| 309 |
+
static constexpr bool IsDynamic = (Size == ceres::DYNAMIC);
|
| 310 |
+
using AmbientVector = Eigen::Matrix<double, Size, 1>;
|
| 311 |
+
using MatrixJacobian = Eigen::Matrix<double, Size, Size, Eigen::RowMajor>;
|
| 312 |
+
|
| 313 |
+
int size_{};
|
| 314 |
+
};
|
| 315 |
+
|
| 316 |
+
// Hold a subset of the parameters inside a parameter block constant.
|
| 317 |
+
class CERES_EXPORT SubsetManifold final : public Manifold {
|
| 318 |
+
public:
|
| 319 |
+
SubsetManifold(int size, const std::vector<int>& constant_parameters);
|
| 320 |
+
int AmbientSize() const override;
|
| 321 |
+
int TangentSize() const override;
|
| 322 |
+
|
| 323 |
+
bool Plus(const double* x,
|
| 324 |
+
const double* delta,
|
| 325 |
+
double* x_plus_delta) const override;
|
| 326 |
+
bool PlusJacobian(const double* x, double* jacobian) const override;
|
| 327 |
+
bool RightMultiplyByPlusJacobian(const double* x,
|
| 328 |
+
const int num_rows,
|
| 329 |
+
const double* ambient_matrix,
|
| 330 |
+
double* tangent_matrix) const override;
|
| 331 |
+
bool Minus(const double* y,
|
| 332 |
+
const double* x,
|
| 333 |
+
double* y_minus_x) const override;
|
| 334 |
+
bool MinusJacobian(const double* x, double* jacobian) const override;
|
| 335 |
+
|
| 336 |
+
private:
|
| 337 |
+
const int tangent_size_ = 0;
|
| 338 |
+
std::vector<bool> constancy_mask_;
|
| 339 |
+
};
|
| 340 |
+
|
| 341 |
+
// Implements the manifold for a Hamilton quaternion as defined in
|
| 342 |
+
// https://en.wikipedia.org/wiki/Quaternion. Quaternions are represented as
|
| 343 |
+
// unit norm 4-vectors, i.e.
|
| 344 |
+
//
|
| 345 |
+
// q = [q0; q1; q2; q3], |q| = 1
|
| 346 |
+
//
|
| 347 |
+
// is the ambient space representation.
|
| 348 |
+
//
|
| 349 |
+
// q0 scalar part.
|
| 350 |
+
// q1 coefficient of i.
|
| 351 |
+
// q2 coefficient of j.
|
| 352 |
+
// q3 coefficient of k.
|
| 353 |
+
//
|
| 354 |
+
// where: i*i = j*j = k*k = -1 and i*j = k, j*k = i, k*i = j.
|
| 355 |
+
//
|
| 356 |
+
// The tangent space is R^3, which relates to the ambient space through the
|
| 357 |
+
// Plus and Minus operations defined as:
|
| 358 |
+
//
|
| 359 |
+
// Plus(x, delta) = [cos(|delta|); sin(|delta|) * delta / |delta|] * x
|
| 360 |
+
// Minus(y, x) = to_delta(y * x^{-1})
|
| 361 |
+
//
|
| 362 |
+
// where "*" is the quaternion product and because q is a unit quaternion
|
| 363 |
+
// (|q|=1), q^-1 = [q0; -q1; -q2; -q3]
|
| 364 |
+
//
|
| 365 |
+
// and to_delta( [q0; u_{3x1}] ) = u / |u| * atan2(|u|, q0)
|
| 366 |
+
class CERES_EXPORT QuaternionManifold final : public Manifold {
|
| 367 |
+
public:
|
| 368 |
+
int AmbientSize() const override { return 4; }
|
| 369 |
+
int TangentSize() const override { return 3; }
|
| 370 |
+
|
| 371 |
+
bool Plus(const double* x,
|
| 372 |
+
const double* delta,
|
| 373 |
+
double* x_plus_delta) const override;
|
| 374 |
+
bool PlusJacobian(const double* x, double* jacobian) const override;
|
| 375 |
+
bool Minus(const double* y,
|
| 376 |
+
const double* x,
|
| 377 |
+
double* y_minus_x) const override;
|
| 378 |
+
bool MinusJacobian(const double* x, double* jacobian) const override;
|
| 379 |
+
};
|
| 380 |
+
|
| 381 |
+
// Implements the quaternion manifold for Eigen's representation of the
|
| 382 |
+
// Hamilton quaternion. Geometrically it is exactly the same as the
|
| 383 |
+
// QuaternionManifold defined above. However, Eigen uses a different internal
|
| 384 |
+
// memory layout for the elements of the quaternion than what is commonly
|
| 385 |
+
// used. It stores the quaternion in memory as [q1, q2, q3, q0] or
|
| 386 |
+
// [x, y, z, w] where the real (scalar) part is last.
|
| 387 |
+
//
|
| 388 |
+
// Since Ceres operates on parameter blocks which are raw double pointers this
|
| 389 |
+
// difference is important and requires a different manifold.
|
| 390 |
+
class CERES_EXPORT EigenQuaternionManifold final : public Manifold {
|
| 391 |
+
public:
|
| 392 |
+
int AmbientSize() const override { return 4; }
|
| 393 |
+
int TangentSize() const override { return 3; }
|
| 394 |
+
|
| 395 |
+
bool Plus(const double* x,
|
| 396 |
+
const double* delta,
|
| 397 |
+
double* x_plus_delta) const override;
|
| 398 |
+
bool PlusJacobian(const double* x, double* jacobian) const override;
|
| 399 |
+
bool Minus(const double* y,
|
| 400 |
+
const double* x,
|
| 401 |
+
double* y_minus_x) const override;
|
| 402 |
+
bool MinusJacobian(const double* x, double* jacobian) const override;
|
| 403 |
+
};
|
| 404 |
+
|
| 405 |
+
} // namespace ceres
|
| 406 |
+
|
| 407 |
+
// clang-format off
|
| 408 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 409 |
+
// clang-format on
|
| 410 |
+
|
| 411 |
+
#endif // CERES_PUBLIC_MANIFOLD_H_
|
ceres-v2/include/manifold_test_utils.h
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Ceres Solver - A fast non-linear least squares minimizer
|
| 2 |
+
// Copyright 2022 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 |
+
|
| 31 |
+
#include <cmath>
|
| 32 |
+
#include <limits>
|
| 33 |
+
#include <memory>
|
| 34 |
+
|
| 35 |
+
#include "ceres/dynamic_numeric_diff_cost_function.h"
|
| 36 |
+
#include "ceres/internal/eigen.h"
|
| 37 |
+
#include "ceres/manifold.h"
|
| 38 |
+
#include "ceres/numeric_diff_options.h"
|
| 39 |
+
#include "ceres/types.h"
|
| 40 |
+
#include "gmock/gmock.h"
|
| 41 |
+
#include "gtest/gtest.h"
|
| 42 |
+
|
| 43 |
+
namespace ceres {
|
| 44 |
+
|
| 45 |
+
// Matchers and macros for help with testing Manifold objects.
|
| 46 |
+
//
|
| 47 |
+
// Testing a Manifold has two parts.
|
| 48 |
+
//
|
| 49 |
+
// 1. Checking that Manifold::Plus is correctly defined. This requires per
|
| 50 |
+
// manifold tests.
|
| 51 |
+
//
|
| 52 |
+
// 2. The other methods of the manifold have mathematical properties that make
|
| 53 |
+
// it compatible with Plus, as described in:
|
| 54 |
+
//
|
| 55 |
+
// "Integrating Generic Sensor Fusion Algorithms with Sound State
|
| 56 |
+
// Representations through Encapsulation of Manifolds"
|
| 57 |
+
// By C. Hertzberg, R. Wagner, U. Frese and L. Schroder
|
| 58 |
+
// https://arxiv.org/pdf/1107.1119.pdf
|
| 59 |
+
//
|
| 60 |
+
// These tests are implemented using generic matchers defined below which can
|
| 61 |
+
// all be called by the macro EXPECT_THAT_MANIFOLD_INVARIANTS_HOLD(manifold, x,
|
| 62 |
+
// delta, y, tolerance). See manifold_test.cc for example usage.
|
| 63 |
+
|
| 64 |
+
// Checks that the invariant Plus(x, 0) == x holds.
|
| 65 |
+
MATCHER_P2(XPlusZeroIsXAt, x, tolerance, "") {
|
| 66 |
+
const int ambient_size = arg.AmbientSize();
|
| 67 |
+
const int tangent_size = arg.TangentSize();
|
| 68 |
+
|
| 69 |
+
Vector actual = Vector::Zero(ambient_size);
|
| 70 |
+
Vector zero = Vector::Zero(tangent_size);
|
| 71 |
+
EXPECT_TRUE(arg.Plus(x.data(), zero.data(), actual.data()));
|
| 72 |
+
const double n = (actual - x).norm();
|
| 73 |
+
const double d = x.norm();
|
| 74 |
+
const double diffnorm = (d == 0.0) ? n : (n / d);
|
| 75 |
+
if (diffnorm > tolerance) {
|
| 76 |
+
*result_listener << "\nexpected (x): " << x.transpose()
|
| 77 |
+
<< "\nactual: " << actual.transpose()
|
| 78 |
+
<< "\ndiffnorm: " << diffnorm;
|
| 79 |
+
return false;
|
| 80 |
+
}
|
| 81 |
+
return true;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
// Checks that the invariant Minus(x, x) == 0 holds.
|
| 85 |
+
MATCHER_P2(XMinusXIsZeroAt, x, tolerance, "") {
|
| 86 |
+
const int tangent_size = arg.TangentSize();
|
| 87 |
+
Vector actual = Vector::Zero(tangent_size);
|
| 88 |
+
EXPECT_TRUE(arg.Minus(x.data(), x.data(), actual.data()));
|
| 89 |
+
const double diffnorm = actual.norm();
|
| 90 |
+
if (diffnorm > tolerance) {
|
| 91 |
+
*result_listener << "\nx: " << x.transpose() //
|
| 92 |
+
<< "\nexpected: 0 0 0"
|
| 93 |
+
<< "\nactual: " << actual.transpose()
|
| 94 |
+
<< "\ndiffnorm: " << diffnorm;
|
| 95 |
+
return false;
|
| 96 |
+
}
|
| 97 |
+
return true;
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
// Helper struct to curry Plus(x, .) so that it can be numerically
|
| 101 |
+
// differentiated.
|
| 102 |
+
struct PlusFunctor {
|
| 103 |
+
PlusFunctor(const Manifold& manifold, const double* x)
|
| 104 |
+
: manifold(manifold), x(x) {}
|
| 105 |
+
bool operator()(double const* const* parameters, double* x_plus_delta) const {
|
| 106 |
+
return manifold.Plus(x, parameters[0], x_plus_delta);
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
const Manifold& manifold;
|
| 110 |
+
const double* x;
|
| 111 |
+
};
|
| 112 |
+
|
| 113 |
+
// Checks that the output of PlusJacobian matches the one obtained by
|
| 114 |
+
// numerically evaluating D_2 Plus(x,0).
|
| 115 |
+
MATCHER_P2(HasCorrectPlusJacobianAt, x, tolerance, "") {
|
| 116 |
+
const int ambient_size = arg.AmbientSize();
|
| 117 |
+
const int tangent_size = arg.TangentSize();
|
| 118 |
+
|
| 119 |
+
NumericDiffOptions options;
|
| 120 |
+
options.ridders_relative_initial_step_size = 1e-4;
|
| 121 |
+
|
| 122 |
+
DynamicNumericDiffCostFunction<PlusFunctor, RIDDERS> cost_function(
|
| 123 |
+
new PlusFunctor(arg, x.data()), TAKE_OWNERSHIP, options);
|
| 124 |
+
cost_function.AddParameterBlock(tangent_size);
|
| 125 |
+
cost_function.SetNumResiduals(ambient_size);
|
| 126 |
+
|
| 127 |
+
Vector zero = Vector::Zero(tangent_size);
|
| 128 |
+
double* parameters[1] = {zero.data()};
|
| 129 |
+
|
| 130 |
+
Vector x_plus_zero = Vector::Zero(ambient_size);
|
| 131 |
+
Matrix expected = Matrix::Zero(ambient_size, tangent_size);
|
| 132 |
+
double* jacobians[1] = {expected.data()};
|
| 133 |
+
|
| 134 |
+
EXPECT_TRUE(
|
| 135 |
+
cost_function.Evaluate(parameters, x_plus_zero.data(), jacobians));
|
| 136 |
+
|
| 137 |
+
Matrix actual = Matrix::Random(ambient_size, tangent_size);
|
| 138 |
+
EXPECT_TRUE(arg.PlusJacobian(x.data(), actual.data()));
|
| 139 |
+
|
| 140 |
+
const double n = (actual - expected).norm();
|
| 141 |
+
const double d = expected.norm();
|
| 142 |
+
const double diffnorm = (d == 0.0) ? n : n / d;
|
| 143 |
+
if (diffnorm > tolerance) {
|
| 144 |
+
*result_listener << "\nx: " << x.transpose() << "\nexpected: \n"
|
| 145 |
+
<< expected << "\nactual:\n"
|
| 146 |
+
<< actual << "\ndiff:\n"
|
| 147 |
+
<< expected - actual << "\ndiffnorm : " << diffnorm;
|
| 148 |
+
return false;
|
| 149 |
+
}
|
| 150 |
+
return true;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
// Checks that the invariant Minus(Plus(x, delta), x) == delta holds.
|
| 154 |
+
MATCHER_P3(MinusPlusIsIdentityAt, x, delta, tolerance, "") {
|
| 155 |
+
const int ambient_size = arg.AmbientSize();
|
| 156 |
+
const int tangent_size = arg.TangentSize();
|
| 157 |
+
Vector x_plus_delta = Vector::Zero(ambient_size);
|
| 158 |
+
EXPECT_TRUE(arg.Plus(x.data(), delta.data(), x_plus_delta.data()));
|
| 159 |
+
Vector actual = Vector::Zero(tangent_size);
|
| 160 |
+
EXPECT_TRUE(arg.Minus(x_plus_delta.data(), x.data(), actual.data()));
|
| 161 |
+
|
| 162 |
+
const double n = (actual - delta).norm();
|
| 163 |
+
const double d = delta.norm();
|
| 164 |
+
const double diffnorm = (d == 0.0) ? n : (n / d);
|
| 165 |
+
if (diffnorm > tolerance) {
|
| 166 |
+
*result_listener << "\nx: " << x.transpose()
|
| 167 |
+
<< "\nexpected: " << delta.transpose()
|
| 168 |
+
<< "\nactual:" << actual.transpose()
|
| 169 |
+
<< "\ndiff:" << (delta - actual).transpose()
|
| 170 |
+
<< "\ndiffnorm: " << diffnorm;
|
| 171 |
+
return false;
|
| 172 |
+
}
|
| 173 |
+
return true;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
// Checks that the invariant Plus(Minus(y, x), x) == y holds.
|
| 177 |
+
MATCHER_P3(PlusMinusIsIdentityAt, x, y, tolerance, "") {
|
| 178 |
+
const int ambient_size = arg.AmbientSize();
|
| 179 |
+
const int tangent_size = arg.TangentSize();
|
| 180 |
+
|
| 181 |
+
Vector y_minus_x = Vector::Zero(tangent_size);
|
| 182 |
+
EXPECT_TRUE(arg.Minus(y.data(), x.data(), y_minus_x.data()));
|
| 183 |
+
|
| 184 |
+
Vector actual = Vector::Zero(ambient_size);
|
| 185 |
+
EXPECT_TRUE(arg.Plus(x.data(), y_minus_x.data(), actual.data()));
|
| 186 |
+
|
| 187 |
+
const double n = (actual - y).norm();
|
| 188 |
+
const double d = y.norm();
|
| 189 |
+
const double diffnorm = (d == 0.0) ? n : (n / d);
|
| 190 |
+
if (diffnorm > tolerance) {
|
| 191 |
+
*result_listener << "\nx: " << x.transpose()
|
| 192 |
+
<< "\nexpected: " << y.transpose()
|
| 193 |
+
<< "\nactual:" << actual.transpose()
|
| 194 |
+
<< "\ndiff:" << (y - actual).transpose()
|
| 195 |
+
<< "\ndiffnorm: " << diffnorm;
|
| 196 |
+
return false;
|
| 197 |
+
}
|
| 198 |
+
return true;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
// Helper struct to curry Minus(., x) so that it can be numerically
|
| 202 |
+
// differentiated.
|
| 203 |
+
struct MinusFunctor {
|
| 204 |
+
MinusFunctor(const Manifold& manifold, const double* x)
|
| 205 |
+
: manifold(manifold), x(x) {}
|
| 206 |
+
bool operator()(double const* const* parameters, double* y_minus_x) const {
|
| 207 |
+
return manifold.Minus(parameters[0], x, y_minus_x);
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
const Manifold& manifold;
|
| 211 |
+
const double* x;
|
| 212 |
+
};
|
| 213 |
+
|
| 214 |
+
// Checks that the output of MinusJacobian matches the one obtained by
|
| 215 |
+
// numerically evaluating D_1 Minus(x,x).
|
| 216 |
+
MATCHER_P2(HasCorrectMinusJacobianAt, x, tolerance, "") {
|
| 217 |
+
const int ambient_size = arg.AmbientSize();
|
| 218 |
+
const int tangent_size = arg.TangentSize();
|
| 219 |
+
|
| 220 |
+
Vector y = x;
|
| 221 |
+
Vector y_minus_x = Vector::Zero(tangent_size);
|
| 222 |
+
|
| 223 |
+
NumericDiffOptions options;
|
| 224 |
+
options.ridders_relative_initial_step_size = 1e-4;
|
| 225 |
+
DynamicNumericDiffCostFunction<MinusFunctor, RIDDERS> cost_function(
|
| 226 |
+
new MinusFunctor(arg, x.data()), TAKE_OWNERSHIP, options);
|
| 227 |
+
cost_function.AddParameterBlock(ambient_size);
|
| 228 |
+
cost_function.SetNumResiduals(tangent_size);
|
| 229 |
+
|
| 230 |
+
double* parameters[1] = {y.data()};
|
| 231 |
+
|
| 232 |
+
Matrix expected = Matrix::Zero(tangent_size, ambient_size);
|
| 233 |
+
double* jacobians[1] = {expected.data()};
|
| 234 |
+
|
| 235 |
+
EXPECT_TRUE(cost_function.Evaluate(parameters, y_minus_x.data(), jacobians));
|
| 236 |
+
|
| 237 |
+
Matrix actual = Matrix::Random(tangent_size, ambient_size);
|
| 238 |
+
EXPECT_TRUE(arg.MinusJacobian(x.data(), actual.data()));
|
| 239 |
+
|
| 240 |
+
const double n = (actual - expected).norm();
|
| 241 |
+
const double d = expected.norm();
|
| 242 |
+
const double diffnorm = (d == 0.0) ? n : (n / d);
|
| 243 |
+
if (diffnorm > tolerance) {
|
| 244 |
+
*result_listener << "\nx: " << x.transpose() << "\nexpected: \n"
|
| 245 |
+
<< expected << "\nactual:\n"
|
| 246 |
+
<< actual << "\ndiff:\n"
|
| 247 |
+
<< expected - actual << "\ndiffnorm: " << diffnorm;
|
| 248 |
+
return false;
|
| 249 |
+
}
|
| 250 |
+
return true;
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
// Checks that D_delta Minus(Plus(x, delta), x) at delta = 0 is an identity
|
| 254 |
+
// matrix.
|
| 255 |
+
MATCHER_P2(MinusPlusJacobianIsIdentityAt, x, tolerance, "") {
|
| 256 |
+
const int ambient_size = arg.AmbientSize();
|
| 257 |
+
const int tangent_size = arg.TangentSize();
|
| 258 |
+
|
| 259 |
+
Matrix plus_jacobian(ambient_size, tangent_size);
|
| 260 |
+
EXPECT_TRUE(arg.PlusJacobian(x.data(), plus_jacobian.data()));
|
| 261 |
+
Matrix minus_jacobian(tangent_size, ambient_size);
|
| 262 |
+
EXPECT_TRUE(arg.MinusJacobian(x.data(), minus_jacobian.data()));
|
| 263 |
+
|
| 264 |
+
const Matrix actual = minus_jacobian * plus_jacobian;
|
| 265 |
+
const Matrix expected = Matrix::Identity(tangent_size, tangent_size);
|
| 266 |
+
|
| 267 |
+
const double n = (actual - expected).norm();
|
| 268 |
+
const double d = expected.norm();
|
| 269 |
+
const double diffnorm = n / d;
|
| 270 |
+
if (diffnorm > tolerance) {
|
| 271 |
+
*result_listener << "\nx: " << x.transpose() << "\nexpected: \n"
|
| 272 |
+
<< expected << "\nactual:\n"
|
| 273 |
+
<< actual << "\ndiff:\n"
|
| 274 |
+
<< expected - actual << "\ndiffnorm: " << diffnorm;
|
| 275 |
+
|
| 276 |
+
return false;
|
| 277 |
+
}
|
| 278 |
+
return true;
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
+
// Verify that the output of RightMultiplyByPlusJacobian is ambient_matrix *
|
| 282 |
+
// plus_jacobian.
|
| 283 |
+
MATCHER_P2(HasCorrectRightMultiplyByPlusJacobianAt, x, tolerance, "") {
|
| 284 |
+
const int ambient_size = arg.AmbientSize();
|
| 285 |
+
const int tangent_size = arg.TangentSize();
|
| 286 |
+
|
| 287 |
+
constexpr int kMinNumRows = 0;
|
| 288 |
+
constexpr int kMaxNumRows = 3;
|
| 289 |
+
for (int num_rows = kMinNumRows; num_rows <= kMaxNumRows; ++num_rows) {
|
| 290 |
+
Matrix plus_jacobian = Matrix::Random(ambient_size, tangent_size);
|
| 291 |
+
EXPECT_TRUE(arg.PlusJacobian(x.data(), plus_jacobian.data()));
|
| 292 |
+
|
| 293 |
+
Matrix ambient_matrix = Matrix::Random(num_rows, ambient_size);
|
| 294 |
+
Matrix expected = ambient_matrix * plus_jacobian;
|
| 295 |
+
|
| 296 |
+
Matrix actual = Matrix::Random(num_rows, tangent_size);
|
| 297 |
+
EXPECT_TRUE(arg.RightMultiplyByPlusJacobian(
|
| 298 |
+
x.data(), num_rows, ambient_matrix.data(), actual.data()));
|
| 299 |
+
const double n = (actual - expected).norm();
|
| 300 |
+
const double d = expected.norm();
|
| 301 |
+
const double diffnorm = (d == 0.0) ? n : (n / d);
|
| 302 |
+
if (diffnorm > tolerance) {
|
| 303 |
+
*result_listener << "\nx: " << x.transpose() << "\nambient_matrix : \n"
|
| 304 |
+
<< ambient_matrix << "\nplus_jacobian : \n"
|
| 305 |
+
<< plus_jacobian << "\nexpected: \n"
|
| 306 |
+
<< expected << "\nactual:\n"
|
| 307 |
+
<< actual << "\ndiff:\n"
|
| 308 |
+
<< expected - actual << "\ndiffnorm : " << diffnorm;
|
| 309 |
+
return false;
|
| 310 |
+
}
|
| 311 |
+
}
|
| 312 |
+
return true;
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
#define EXPECT_THAT_MANIFOLD_INVARIANTS_HOLD(manifold, x, delta, y, tolerance) \
|
| 316 |
+
Vector zero_tangent = Vector::Zero(manifold.TangentSize()); \
|
| 317 |
+
EXPECT_THAT(manifold, XPlusZeroIsXAt(x, tolerance)); \
|
| 318 |
+
EXPECT_THAT(manifold, XMinusXIsZeroAt(x, tolerance)); \
|
| 319 |
+
EXPECT_THAT(manifold, MinusPlusIsIdentityAt(x, delta, tolerance)); \
|
| 320 |
+
EXPECT_THAT(manifold, MinusPlusIsIdentityAt(x, zero_tangent, tolerance)); \
|
| 321 |
+
EXPECT_THAT(manifold, PlusMinusIsIdentityAt(x, x, tolerance)); \
|
| 322 |
+
EXPECT_THAT(manifold, PlusMinusIsIdentityAt(x, y, tolerance)); \
|
| 323 |
+
EXPECT_THAT(manifold, HasCorrectPlusJacobianAt(x, tolerance)); \
|
| 324 |
+
EXPECT_THAT(manifold, HasCorrectMinusJacobianAt(x, tolerance)); \
|
| 325 |
+
EXPECT_THAT(manifold, MinusPlusJacobianIsIdentityAt(x, tolerance)); \
|
| 326 |
+
EXPECT_THAT(manifold, HasCorrectRightMultiplyByPlusJacobianAt(x, tolerance));
|
| 327 |
+
|
| 328 |
+
} // namespace ceres
|
ceres-v2/include/normal_prior.h
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
//
|
| 31 |
+
// Cost term that implements a prior on a parameter block using a
|
| 32 |
+
// normal distribution.
|
| 33 |
+
|
| 34 |
+
#ifndef CERES_PUBLIC_NORMAL_PRIOR_H_
|
| 35 |
+
#define CERES_PUBLIC_NORMAL_PRIOR_H_
|
| 36 |
+
|
| 37 |
+
#include "ceres/cost_function.h"
|
| 38 |
+
#include "ceres/internal/disable_warnings.h"
|
| 39 |
+
#include "ceres/internal/eigen.h"
|
| 40 |
+
|
| 41 |
+
namespace ceres {
|
| 42 |
+
|
| 43 |
+
// Implements a cost function of the form
|
| 44 |
+
//
|
| 45 |
+
// cost(x) = ||A(x - b)||^2
|
| 46 |
+
//
|
| 47 |
+
// where, the matrix A and the vector b are fixed and x is the
|
| 48 |
+
// variable. In case the user is interested in implementing a cost
|
| 49 |
+
// function of the form
|
| 50 |
+
//
|
| 51 |
+
// cost(x) = (x - mu)^T S^{-1} (x - mu)
|
| 52 |
+
//
|
| 53 |
+
// where, mu is a vector and S is a covariance matrix, then, A =
|
| 54 |
+
// S^{-1/2}, i.e the matrix A is the square root of the inverse of the
|
| 55 |
+
// covariance, also known as the stiffness matrix. There are however
|
| 56 |
+
// no restrictions on the shape of A. It is free to be rectangular,
|
| 57 |
+
// which would be the case if the covariance matrix S is rank
|
| 58 |
+
// deficient.
|
| 59 |
+
|
| 60 |
+
class CERES_EXPORT NormalPrior final : public CostFunction {
|
| 61 |
+
public:
|
| 62 |
+
// Check that the number of rows in the vector b are the same as the
|
| 63 |
+
// number of columns in the matrix A, crash otherwise.
|
| 64 |
+
NormalPrior(const Matrix& A, const Vector& b);
|
| 65 |
+
bool Evaluate(double const* const* parameters,
|
| 66 |
+
double* residuals,
|
| 67 |
+
double** jacobians) const override;
|
| 68 |
+
|
| 69 |
+
private:
|
| 70 |
+
Matrix A_;
|
| 71 |
+
Vector b_;
|
| 72 |
+
};
|
| 73 |
+
|
| 74 |
+
} // namespace ceres
|
| 75 |
+
|
| 76 |
+
#include "ceres/internal/reenable_warnings.h"
|
| 77 |
+
|
| 78 |
+
#endif // CERES_PUBLIC_NORMAL_PRIOR_H_
|