No more Ceres dependecy, copied relevant Ceres files here (for now)
parent
f39c1d72f8
commit
e0841fb3e6
|
@ -2,8 +2,5 @@
|
||||||
file(GLOB nonlinear_headers "*.h")
|
file(GLOB nonlinear_headers "*.h")
|
||||||
install(FILES ${nonlinear_headers} DESTINATION include/gtsam_unstable/nonlinear)
|
install(FILES ${nonlinear_headers} DESTINATION include/gtsam_unstable/nonlinear)
|
||||||
|
|
||||||
FIND_PACKAGE(Ceres REQUIRED)
|
|
||||||
INCLUDE_DIRECTORIES(${CERES_INCLUDE_DIRS})
|
|
||||||
|
|
||||||
# Add all tests
|
# Add all tests
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
|
|
@ -0,0 +1,314 @@
|
||||||
|
// Ceres Solver - A fast non-linear least squares minimizer
|
||||||
|
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/ceres-solver/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: keir@google.com (Keir Mierle)
|
||||||
|
//
|
||||||
|
// Computation of the Jacobian matrix for vector-valued functions of multiple
|
||||||
|
// variables, using automatic differentiation based on the implementation of
|
||||||
|
// dual numbers in jet.h. Before reading the rest of this file, it is adivsable
|
||||||
|
// to read jet.h's header comment in detail.
|
||||||
|
//
|
||||||
|
// The helper wrapper AutoDiff::Differentiate() computes the jacobian of
|
||||||
|
// functors with templated operator() taking this form:
|
||||||
|
//
|
||||||
|
// struct F {
|
||||||
|
// template<typename T>
|
||||||
|
// bool operator()(const T *x, const T *y, ..., T *z) {
|
||||||
|
// // Compute z[] based on x[], y[], ...
|
||||||
|
// // return true if computation succeeded, false otherwise.
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// All inputs and outputs may be vector-valued.
|
||||||
|
//
|
||||||
|
// To understand how jets are used to compute the jacobian, a
|
||||||
|
// picture may help. Consider a vector-valued function, F, returning 3
|
||||||
|
// dimensions and taking a vector-valued parameter of 4 dimensions:
|
||||||
|
//
|
||||||
|
// y x
|
||||||
|
// [ * ] F [ * ]
|
||||||
|
// [ * ] <--- [ * ]
|
||||||
|
// [ * ] [ * ]
|
||||||
|
// [ * ]
|
||||||
|
//
|
||||||
|
// Similar to the 2-parameter example for f described in jet.h, computing the
|
||||||
|
// jacobian dy/dx is done by substutiting a suitable jet object for x and all
|
||||||
|
// intermediate steps of the computation of F. Since x is has 4 dimensions, use
|
||||||
|
// a Jet<double, 4>.
|
||||||
|
//
|
||||||
|
// Before substituting a jet object for x, the dual components are set
|
||||||
|
// appropriately for each dimension of x:
|
||||||
|
//
|
||||||
|
// y x
|
||||||
|
// [ * | * * * * ] f [ * | 1 0 0 0 ] x0
|
||||||
|
// [ * | * * * * ] <--- [ * | 0 1 0 0 ] x1
|
||||||
|
// [ * | * * * * ] [ * | 0 0 1 0 ] x2
|
||||||
|
// ---+--- [ * | 0 0 0 1 ] x3
|
||||||
|
// | ^ ^ ^ ^
|
||||||
|
// dy/dx | | | +----- infinitesimal for x3
|
||||||
|
// | | +------- infinitesimal for x2
|
||||||
|
// | +--------- infinitesimal for x1
|
||||||
|
// +----------- infinitesimal for x0
|
||||||
|
//
|
||||||
|
// The reason to set the internal 4x4 submatrix to the identity is that we wish
|
||||||
|
// to take the derivative of y separately with respect to each dimension of x.
|
||||||
|
// Each column of the 4x4 identity is therefore for a single component of the
|
||||||
|
// independent variable x.
|
||||||
|
//
|
||||||
|
// Then the jacobian of the mapping, dy/dx, is the 3x4 sub-matrix of the
|
||||||
|
// extended y vector, indicated in the above diagram.
|
||||||
|
//
|
||||||
|
// Functors with multiple parameters
|
||||||
|
// ---------------------------------
|
||||||
|
// In practice, it is often convenient to use a function f of two or more
|
||||||
|
// vector-valued parameters, for example, x[3] and z[6]. Unfortunately, the jet
|
||||||
|
// framework is designed for a single-parameter vector-valued input. The wrapper
|
||||||
|
// in this file addresses this issue adding support for functions with one or
|
||||||
|
// more parameter vectors.
|
||||||
|
//
|
||||||
|
// To support multiple parameters, all the parameter vectors are concatenated
|
||||||
|
// into one and treated as a single parameter vector, except that since the
|
||||||
|
// functor expects different inputs, we need to construct the jets as if they
|
||||||
|
// were part of a single parameter vector. The extended jets are passed
|
||||||
|
// separately for each parameter.
|
||||||
|
//
|
||||||
|
// For example, consider a functor F taking two vector parameters, p[2] and
|
||||||
|
// q[3], and producing an output y[4]:
|
||||||
|
//
|
||||||
|
// struct F {
|
||||||
|
// template<typename T>
|
||||||
|
// bool operator()(const T *p, const T *q, T *z) {
|
||||||
|
// // ...
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// In this case, the necessary jet type is Jet<double, 5>. Here is a
|
||||||
|
// visualization of the jet objects in this case:
|
||||||
|
//
|
||||||
|
// Dual components for p ----+
|
||||||
|
// |
|
||||||
|
// -+-
|
||||||
|
// y [ * | 1 0 | 0 0 0 ] --- p[0]
|
||||||
|
// [ * | 0 1 | 0 0 0 ] --- p[1]
|
||||||
|
// [ * | . . | + + + ] |
|
||||||
|
// [ * | . . | + + + ] v
|
||||||
|
// [ * | . . | + + + ] <--- F(p, q)
|
||||||
|
// [ * | . . | + + + ] ^
|
||||||
|
// ^^^ ^^^^^ |
|
||||||
|
// dy/dp dy/dq [ * | 0 0 | 1 0 0 ] --- q[0]
|
||||||
|
// [ * | 0 0 | 0 1 0 ] --- q[1]
|
||||||
|
// [ * | 0 0 | 0 0 1 ] --- q[2]
|
||||||
|
// --+--
|
||||||
|
// |
|
||||||
|
// Dual components for q --------------+
|
||||||
|
//
|
||||||
|
// where the 4x2 submatrix (marked with ".") and 4x3 submatrix (marked with "+"
|
||||||
|
// of y in the above diagram are the derivatives of y with respect to p and q
|
||||||
|
// respectively. This is how autodiff works for functors taking multiple vector
|
||||||
|
// valued arguments (up to 6).
|
||||||
|
//
|
||||||
|
// Jacobian NULL pointers
|
||||||
|
// ----------------------
|
||||||
|
// In general, the functions below will accept NULL pointers for all or some of
|
||||||
|
// the Jacobian parameters, meaning that those Jacobians will not be computed.
|
||||||
|
|
||||||
|
#ifndef CERES_PUBLIC_INTERNAL_AUTODIFF_H_
|
||||||
|
#define CERES_PUBLIC_INTERNAL_AUTODIFF_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <gtsam_unstable/nonlinear/ceres_jet.h>
|
||||||
|
#include <gtsam_unstable/nonlinear/ceres_eigen.h>
|
||||||
|
#include <gtsam_unstable/nonlinear/ceres_fixed_array.h>
|
||||||
|
#include <gtsam_unstable/nonlinear/ceres_variadic_evaluate.h>
|
||||||
|
#define DCHECK assert
|
||||||
|
#define DCHECK_GT(a,b) assert((a)>(b))
|
||||||
|
|
||||||
|
namespace ceres {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Extends src by a 1st order pertubation for every dimension and puts it in
|
||||||
|
// dst. The size of src is N. Since this is also used for perturbations in
|
||||||
|
// blocked arrays, offset is used to shift which part of the jet the
|
||||||
|
// perturbation occurs. This is used to set up the extended x augmented by an
|
||||||
|
// identity matrix. The JetT type should be a Jet type, and T should be a
|
||||||
|
// numeric type (e.g. double). For example,
|
||||||
|
//
|
||||||
|
// 0 1 2 3 4 5 6 7 8
|
||||||
|
// dst[0] [ * | . . | 1 0 0 | . . . ]
|
||||||
|
// dst[1] [ * | . . | 0 1 0 | . . . ]
|
||||||
|
// dst[2] [ * | . . | 0 0 1 | . . . ]
|
||||||
|
//
|
||||||
|
// is what would get put in dst if N was 3, offset was 3, and the jet type JetT
|
||||||
|
// was 8-dimensional.
|
||||||
|
template <typename JetT, typename T, int N>
|
||||||
|
inline void Make1stOrderPerturbation(int offset, const T* src, JetT* dst) {
|
||||||
|
DCHECK(src);
|
||||||
|
DCHECK(dst);
|
||||||
|
for (int j = 0; j < N; ++j) {
|
||||||
|
dst[j].a = src[j];
|
||||||
|
dst[j].v.setZero();
|
||||||
|
dst[j].v[offset + j] = T(1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes the 0th order part of src, assumed to be a Jet type, and puts it in
|
||||||
|
// dst. This is used to pick out the "vector" part of the extended y.
|
||||||
|
template <typename JetT, typename T>
|
||||||
|
inline void Take0thOrderPart(int M, const JetT *src, T dst) {
|
||||||
|
DCHECK(src);
|
||||||
|
for (int i = 0; i < M; ++i) {
|
||||||
|
dst[i] = src[i].a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes N 1st order parts, starting at index N0, and puts them in the M x N
|
||||||
|
// matrix 'dst'. This is used to pick out the "matrix" parts of the extended y.
|
||||||
|
template <typename JetT, typename T, int N0, int N>
|
||||||
|
inline void Take1stOrderPart(const int M, const JetT *src, T *dst) {
|
||||||
|
DCHECK(src);
|
||||||
|
DCHECK(dst);
|
||||||
|
for (int i = 0; i < M; ++i) {
|
||||||
|
Eigen::Map<Eigen::Matrix<T, N, 1> >(dst + N * i, N) =
|
||||||
|
src[i].v.template segment<N>(N0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is in a struct because default template parameters on a
|
||||||
|
// function are not supported in C++03 (though it is available in
|
||||||
|
// C++0x). N0 through N5 are the dimension of the input arguments to
|
||||||
|
// the user supplied functor.
|
||||||
|
template <typename Functor, typename T,
|
||||||
|
int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0,
|
||||||
|
int N5 = 0, int N6 = 0, int N7 = 0, int N8 = 0, int N9 = 0>
|
||||||
|
struct AutoDiff {
|
||||||
|
static bool Differentiate(const Functor& functor,
|
||||||
|
T const *const *parameters,
|
||||||
|
int num_outputs,
|
||||||
|
T *function_value,
|
||||||
|
T **jacobians) {
|
||||||
|
// This block breaks the 80 column rule to keep it somewhat readable.
|
||||||
|
DCHECK_GT(num_outputs, 0);
|
||||||
|
DCHECK((!N1 && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
|
||||||
|
((N1 > 0) && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
|
||||||
|
((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
|
||||||
|
((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
|
||||||
|
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5 && !N6 && !N7 && !N8 && !N9) ||
|
||||||
|
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && !N6 && !N7 && !N8 && !N9) ||
|
||||||
|
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && !N7 && !N8 && !N9) ||
|
||||||
|
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && !N8 && !N9) ||
|
||||||
|
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && !N9) ||
|
||||||
|
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && (N9 > 0)));
|
||||||
|
|
||||||
|
typedef Jet<T, N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9> JetT;
|
||||||
|
FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(
|
||||||
|
N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9 + num_outputs);
|
||||||
|
|
||||||
|
// These are the positions of the respective jets in the fixed array x.
|
||||||
|
const int jet0 = 0;
|
||||||
|
const int jet1 = N0;
|
||||||
|
const int jet2 = N0 + N1;
|
||||||
|
const int jet3 = N0 + N1 + N2;
|
||||||
|
const int jet4 = N0 + N1 + N2 + N3;
|
||||||
|
const int jet5 = N0 + N1 + N2 + N3 + N4;
|
||||||
|
const int jet6 = N0 + N1 + N2 + N3 + N4 + N5;
|
||||||
|
const int jet7 = N0 + N1 + N2 + N3 + N4 + N5 + N6;
|
||||||
|
const int jet8 = N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7;
|
||||||
|
const int jet9 = N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8;
|
||||||
|
|
||||||
|
const JetT *unpacked_parameters[10] = {
|
||||||
|
x.get() + jet0,
|
||||||
|
x.get() + jet1,
|
||||||
|
x.get() + jet2,
|
||||||
|
x.get() + jet3,
|
||||||
|
x.get() + jet4,
|
||||||
|
x.get() + jet5,
|
||||||
|
x.get() + jet6,
|
||||||
|
x.get() + jet7,
|
||||||
|
x.get() + jet8,
|
||||||
|
x.get() + jet9,
|
||||||
|
};
|
||||||
|
|
||||||
|
JetT* output = x.get() + N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9;
|
||||||
|
|
||||||
|
#define CERES_MAKE_1ST_ORDER_PERTURBATION(i) \
|
||||||
|
if (N ## i) { \
|
||||||
|
internal::Make1stOrderPerturbation<JetT, T, N ## i>( \
|
||||||
|
jet ## i, \
|
||||||
|
parameters[i], \
|
||||||
|
x.get() + jet ## i); \
|
||||||
|
}
|
||||||
|
CERES_MAKE_1ST_ORDER_PERTURBATION(0);
|
||||||
|
CERES_MAKE_1ST_ORDER_PERTURBATION(1);
|
||||||
|
CERES_MAKE_1ST_ORDER_PERTURBATION(2);
|
||||||
|
CERES_MAKE_1ST_ORDER_PERTURBATION(3);
|
||||||
|
CERES_MAKE_1ST_ORDER_PERTURBATION(4);
|
||||||
|
CERES_MAKE_1ST_ORDER_PERTURBATION(5);
|
||||||
|
CERES_MAKE_1ST_ORDER_PERTURBATION(6);
|
||||||
|
CERES_MAKE_1ST_ORDER_PERTURBATION(7);
|
||||||
|
CERES_MAKE_1ST_ORDER_PERTURBATION(8);
|
||||||
|
CERES_MAKE_1ST_ORDER_PERTURBATION(9);
|
||||||
|
#undef CERES_MAKE_1ST_ORDER_PERTURBATION
|
||||||
|
|
||||||
|
if (!VariadicEvaluate<Functor, JetT,
|
||||||
|
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Call(
|
||||||
|
functor, unpacked_parameters, output)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal::Take0thOrderPart(num_outputs, output, function_value);
|
||||||
|
|
||||||
|
#define CERES_TAKE_1ST_ORDER_PERTURBATION(i) \
|
||||||
|
if (N ## i) { \
|
||||||
|
if (jacobians[i]) { \
|
||||||
|
internal::Take1stOrderPart<JetT, T, \
|
||||||
|
jet ## i, \
|
||||||
|
N ## i>(num_outputs, \
|
||||||
|
output, \
|
||||||
|
jacobians[i]); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
CERES_TAKE_1ST_ORDER_PERTURBATION(0);
|
||||||
|
CERES_TAKE_1ST_ORDER_PERTURBATION(1);
|
||||||
|
CERES_TAKE_1ST_ORDER_PERTURBATION(2);
|
||||||
|
CERES_TAKE_1ST_ORDER_PERTURBATION(3);
|
||||||
|
CERES_TAKE_1ST_ORDER_PERTURBATION(4);
|
||||||
|
CERES_TAKE_1ST_ORDER_PERTURBATION(5);
|
||||||
|
CERES_TAKE_1ST_ORDER_PERTURBATION(6);
|
||||||
|
CERES_TAKE_1ST_ORDER_PERTURBATION(7);
|
||||||
|
CERES_TAKE_1ST_ORDER_PERTURBATION(8);
|
||||||
|
CERES_TAKE_1ST_ORDER_PERTURBATION(9);
|
||||||
|
#undef CERES_TAKE_1ST_ORDER_PERTURBATION
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace ceres
|
||||||
|
|
||||||
|
#endif // CERES_PUBLIC_INTERNAL_AUTODIFF_H_
|
|
@ -0,0 +1,93 @@
|
||||||
|
// Ceres Solver - A fast non-linear least squares minimizer
|
||||||
|
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/ceres-solver/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: sameeragarwal@google.com (Sameer Agarwal)
|
||||||
|
|
||||||
|
#ifndef CERES_INTERNAL_EIGEN_H_
|
||||||
|
#define CERES_INTERNAL_EIGEN_H_
|
||||||
|
|
||||||
|
#include <gtsam/3rdparty/gtsam_eigen_includes.h>
|
||||||
|
|
||||||
|
namespace ceres {
|
||||||
|
|
||||||
|
typedef Eigen::Matrix<double, Eigen::Dynamic, 1> Vector;
|
||||||
|
typedef Eigen::Matrix<double,
|
||||||
|
Eigen::Dynamic,
|
||||||
|
Eigen::Dynamic,
|
||||||
|
Eigen::RowMajor> Matrix;
|
||||||
|
typedef Eigen::Map<Vector> VectorRef;
|
||||||
|
typedef Eigen::Map<Matrix> MatrixRef;
|
||||||
|
typedef Eigen::Map<const Vector> ConstVectorRef;
|
||||||
|
typedef Eigen::Map<const Matrix> ConstMatrixRef;
|
||||||
|
|
||||||
|
// Column major matrices for DenseSparseMatrix/DenseQRSolver
|
||||||
|
typedef Eigen::Matrix<double,
|
||||||
|
Eigen::Dynamic,
|
||||||
|
Eigen::Dynamic,
|
||||||
|
Eigen::ColMajor> ColMajorMatrix;
|
||||||
|
|
||||||
|
typedef Eigen::Map<ColMajorMatrix, 0,
|
||||||
|
Eigen::Stride<Eigen::Dynamic, 1> > ColMajorMatrixRef;
|
||||||
|
|
||||||
|
typedef Eigen::Map<const ColMajorMatrix,
|
||||||
|
0,
|
||||||
|
Eigen::Stride<Eigen::Dynamic, 1> > ConstColMajorMatrixRef;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// C++ does not support templated typdefs, thus the need for this
|
||||||
|
// struct so that we can support statically sized Matrix and Maps.
|
||||||
|
template <int num_rows = Eigen::Dynamic, int num_cols = Eigen::Dynamic>
|
||||||
|
struct EigenTypes {
|
||||||
|
typedef Eigen::Matrix <double, num_rows, num_cols, Eigen::RowMajor>
|
||||||
|
Matrix;
|
||||||
|
|
||||||
|
typedef Eigen::Map<
|
||||||
|
Eigen::Matrix<double, num_rows, num_cols, Eigen::RowMajor> >
|
||||||
|
MatrixRef;
|
||||||
|
|
||||||
|
typedef Eigen::Matrix <double, num_rows, 1>
|
||||||
|
Vector;
|
||||||
|
|
||||||
|
typedef Eigen::Map <
|
||||||
|
Eigen::Matrix<double, num_rows, 1> >
|
||||||
|
VectorRef;
|
||||||
|
|
||||||
|
|
||||||
|
typedef Eigen::Map<
|
||||||
|
const Eigen::Matrix<double, num_rows, num_cols, Eigen::RowMajor> >
|
||||||
|
ConstMatrixRef;
|
||||||
|
|
||||||
|
typedef Eigen::Map <
|
||||||
|
const Eigen::Matrix<double, num_rows, 1> >
|
||||||
|
ConstVectorRef;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ceres
|
||||||
|
|
||||||
|
#endif // CERES_INTERNAL_EIGEN_H_
|
|
@ -0,0 +1,190 @@
|
||||||
|
// Ceres Solver - A fast non-linear least squares minimizer
|
||||||
|
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/ceres-solver/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: rennie@google.com (Jeffrey Rennie)
|
||||||
|
// Author: sanjay@google.com (Sanjay Ghemawat) -- renamed to FixedArray
|
||||||
|
|
||||||
|
#ifndef CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
|
||||||
|
#define CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <gtsam/3rdparty/gtsam_eigen_includes.h>
|
||||||
|
#include <gtsam_unstable/nonlinear/ceres_macros.h>
|
||||||
|
#include <gtsam_unstable/nonlinear/ceres_manual_constructor.h>
|
||||||
|
|
||||||
|
namespace ceres {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// A FixedArray<T> represents a non-resizable array of T where the
|
||||||
|
// length of the array does not need to be a compile time constant.
|
||||||
|
//
|
||||||
|
// FixedArray allocates small arrays inline, and large arrays on
|
||||||
|
// the heap. It is a good replacement for non-standard and deprecated
|
||||||
|
// uses of alloca() and variable length arrays (a GCC extension).
|
||||||
|
//
|
||||||
|
// FixedArray keeps performance fast for small arrays, because it
|
||||||
|
// avoids heap operations. It also helps reduce the chances of
|
||||||
|
// accidentally overflowing your stack if large input is passed to
|
||||||
|
// your function.
|
||||||
|
//
|
||||||
|
// Also, FixedArray is useful for writing portable code. Not all
|
||||||
|
// compilers support arrays of dynamic size.
|
||||||
|
|
||||||
|
// Most users should not specify an inline_elements argument and let
|
||||||
|
// FixedArray<> automatically determine the number of elements
|
||||||
|
// to store inline based on sizeof(T).
|
||||||
|
//
|
||||||
|
// If inline_elements is specified, the FixedArray<> implementation
|
||||||
|
// will store arrays of length <= inline_elements inline.
|
||||||
|
//
|
||||||
|
// Finally note that unlike vector<T> FixedArray<T> will not zero-initialize
|
||||||
|
// simple types like int, double, bool, etc.
|
||||||
|
//
|
||||||
|
// Non-POD types will be default-initialized just like regular vectors or
|
||||||
|
// arrays.
|
||||||
|
|
||||||
|
#if defined(_WIN64)
|
||||||
|
typedef __int64 ssize_t;
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
typedef __int32 ssize_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T, ssize_t inline_elements = -1>
|
||||||
|
class FixedArray {
|
||||||
|
public:
|
||||||
|
// For playing nicely with stl:
|
||||||
|
typedef T value_type;
|
||||||
|
typedef T* iterator;
|
||||||
|
typedef T const* const_iterator;
|
||||||
|
typedef T& reference;
|
||||||
|
typedef T const& const_reference;
|
||||||
|
typedef T* pointer;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
typedef size_t size_type;
|
||||||
|
|
||||||
|
// REQUIRES: n >= 0
|
||||||
|
// Creates an array object that can store "n" elements.
|
||||||
|
//
|
||||||
|
// FixedArray<T> will not zero-initialiaze POD (simple) types like int,
|
||||||
|
// double, bool, etc.
|
||||||
|
// Non-POD types will be default-initialized just like regular vectors or
|
||||||
|
// arrays.
|
||||||
|
explicit FixedArray(size_type n);
|
||||||
|
|
||||||
|
// Releases any resources.
|
||||||
|
~FixedArray();
|
||||||
|
|
||||||
|
// Returns the length of the array.
|
||||||
|
inline size_type size() const { return size_; }
|
||||||
|
|
||||||
|
// Returns the memory size of the array in bytes.
|
||||||
|
inline size_t memsize() const { return size_ * sizeof(T); }
|
||||||
|
|
||||||
|
// Returns a pointer to the underlying element array.
|
||||||
|
inline const T* get() const { return &array_[0].element; }
|
||||||
|
inline T* get() { return &array_[0].element; }
|
||||||
|
|
||||||
|
// REQUIRES: 0 <= i < size()
|
||||||
|
// Returns a reference to the "i"th element.
|
||||||
|
inline T& operator[](size_type i) {
|
||||||
|
DCHECK_LT(i, size_);
|
||||||
|
return array_[i].element;
|
||||||
|
}
|
||||||
|
|
||||||
|
// REQUIRES: 0 <= i < size()
|
||||||
|
// Returns a reference to the "i"th element.
|
||||||
|
inline const T& operator[](size_type i) const {
|
||||||
|
DCHECK_LT(i, size_);
|
||||||
|
return array_[i].element;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline iterator begin() { return &array_[0].element; }
|
||||||
|
inline iterator end() { return &array_[size_].element; }
|
||||||
|
|
||||||
|
inline const_iterator begin() const { return &array_[0].element; }
|
||||||
|
inline const_iterator end() const { return &array_[size_].element; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Container to hold elements of type T. This is necessary to handle
|
||||||
|
// the case where T is a a (C-style) array. The size of InnerContainer
|
||||||
|
// and T must be the same, otherwise callers' assumptions about use
|
||||||
|
// of this code will be broken.
|
||||||
|
struct InnerContainer {
|
||||||
|
T element;
|
||||||
|
};
|
||||||
|
|
||||||
|
// How many elements should we store inline?
|
||||||
|
// a. If not specified, use a default of 256 bytes (256 bytes
|
||||||
|
// seems small enough to not cause stack overflow or unnecessary
|
||||||
|
// stack pollution, while still allowing stack allocation for
|
||||||
|
// reasonably long character arrays.
|
||||||
|
// b. Never use 0 length arrays (not ISO C++)
|
||||||
|
static const size_type S1 = ((inline_elements < 0)
|
||||||
|
? (256/sizeof(T)) : inline_elements);
|
||||||
|
static const size_type S2 = (S1 <= 0) ? 1 : S1;
|
||||||
|
static const size_type kInlineElements = S2;
|
||||||
|
|
||||||
|
size_type const size_;
|
||||||
|
InnerContainer* const array_;
|
||||||
|
|
||||||
|
// Allocate some space, not an array of elements of type T, so that we can
|
||||||
|
// skip calling the T constructors and destructors for space we never use.
|
||||||
|
ManualConstructor<InnerContainer> inline_space_[kInlineElements];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation details follow
|
||||||
|
|
||||||
|
template <class T, ssize_t S>
|
||||||
|
inline FixedArray<T, S>::FixedArray(typename FixedArray<T, S>::size_type n)
|
||||||
|
: size_(n),
|
||||||
|
array_((n <= kInlineElements
|
||||||
|
? reinterpret_cast<InnerContainer*>(inline_space_)
|
||||||
|
: new InnerContainer[n])) {
|
||||||
|
// Construct only the elements actually used.
|
||||||
|
if (array_ == reinterpret_cast<InnerContainer*>(inline_space_)) {
|
||||||
|
for (size_t i = 0; i != size_; ++i) {
|
||||||
|
inline_space_[i].Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, ssize_t S>
|
||||||
|
inline FixedArray<T, S>::~FixedArray() {
|
||||||
|
if (array_ != reinterpret_cast<InnerContainer*>(inline_space_)) {
|
||||||
|
delete[] array_;
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i != size_; ++i) {
|
||||||
|
inline_space_[i].Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace ceres
|
||||||
|
|
||||||
|
#endif // CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
|
|
@ -0,0 +1,87 @@
|
||||||
|
// Ceres Solver - A fast non-linear least squares minimizer
|
||||||
|
// Copyright 2012 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/ceres-solver/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: keir@google.com (Keir Mierle)
|
||||||
|
//
|
||||||
|
// Portable floating point classification. The names are picked such that they
|
||||||
|
// do not collide with macros. For example, "isnan" in C99 is a macro and hence
|
||||||
|
// does not respect namespaces.
|
||||||
|
//
|
||||||
|
// TODO(keir): Finish porting!
|
||||||
|
|
||||||
|
#ifndef CERES_PUBLIC_FPCLASSIFY_H_
|
||||||
|
#define CERES_PUBLIC_FPCLASSIFY_H_
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#include <float.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace ceres {
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
|
||||||
|
inline bool IsFinite (double x) { return _finite(x) != 0; }
|
||||||
|
inline bool IsInfinite(double x) { return _finite(x) == 0 && _isnan(x) == 0; }
|
||||||
|
inline bool IsNaN (double x) { return _isnan(x) != 0; }
|
||||||
|
inline bool IsNormal (double x) {
|
||||||
|
int classification = _fpclass(x);
|
||||||
|
return classification == _FPCLASS_NN ||
|
||||||
|
classification == _FPCLASS_PN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(ANDROID) && defined(_STLPORT_VERSION)
|
||||||
|
|
||||||
|
// On Android, when using the STLPort, the C++ isnan and isnormal functions
|
||||||
|
// are defined as macros.
|
||||||
|
inline bool IsNaN (double x) { return isnan(x); }
|
||||||
|
inline bool IsNormal (double x) { return isnormal(x); }
|
||||||
|
// On Android NDK r6, when using STLPort, the isinf and isfinite functions are
|
||||||
|
// not available, so reimplement them.
|
||||||
|
inline bool IsInfinite(double x) {
|
||||||
|
return x == std::numeric_limits<double>::infinity() ||
|
||||||
|
x == -std::numeric_limits<double>::infinity();
|
||||||
|
}
|
||||||
|
inline bool IsFinite(double x) {
|
||||||
|
return !isnan(x) && !IsInfinite(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
// These definitions are for the normal Unix suspects.
|
||||||
|
inline bool IsFinite (double x) { return std::isfinite(x); }
|
||||||
|
inline bool IsInfinite(double x) { return std::isinf(x); }
|
||||||
|
inline bool IsNaN (double x) { return std::isnan(x); }
|
||||||
|
inline bool IsNormal (double x) { return std::isnormal(x); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace ceres
|
||||||
|
|
||||||
|
#endif // CERES_PUBLIC_FPCLASSIFY_H_
|
|
@ -0,0 +1,670 @@
|
||||||
|
// Ceres Solver - A fast non-linear least squares minimizer
|
||||||
|
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/ceres-solver/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: keir@google.com (Keir Mierle)
|
||||||
|
//
|
||||||
|
// A simple implementation of N-dimensional dual numbers, for automatically
|
||||||
|
// computing exact derivatives of functions.
|
||||||
|
//
|
||||||
|
// While a complete treatment of the mechanics of automatic differentation is
|
||||||
|
// beyond the scope of this header (see
|
||||||
|
// http://en.wikipedia.org/wiki/Automatic_differentiation for details), the
|
||||||
|
// basic idea is to extend normal arithmetic with an extra element, "e," often
|
||||||
|
// denoted with the greek symbol epsilon, such that e != 0 but e^2 = 0. Dual
|
||||||
|
// numbers are extensions of the real numbers analogous to complex numbers:
|
||||||
|
// whereas complex numbers augment the reals by introducing an imaginary unit i
|
||||||
|
// such that i^2 = -1, dual numbers introduce an "infinitesimal" unit e such
|
||||||
|
// that e^2 = 0. Dual numbers have two components: the "real" component and the
|
||||||
|
// "infinitesimal" component, generally written as x + y*e. Surprisingly, this
|
||||||
|
// leads to a convenient method for computing exact derivatives without needing
|
||||||
|
// to manipulate complicated symbolic expressions.
|
||||||
|
//
|
||||||
|
// For example, consider the function
|
||||||
|
//
|
||||||
|
// f(x) = x^2 ,
|
||||||
|
//
|
||||||
|
// evaluated at 10. Using normal arithmetic, f(10) = 100, and df/dx(10) = 20.
|
||||||
|
// Next, augument 10 with an infinitesimal to get:
|
||||||
|
//
|
||||||
|
// f(10 + e) = (10 + e)^2
|
||||||
|
// = 100 + 2 * 10 * e + e^2
|
||||||
|
// = 100 + 20 * e -+-
|
||||||
|
// -- |
|
||||||
|
// | +--- This is zero, since e^2 = 0
|
||||||
|
// |
|
||||||
|
// +----------------- This is df/dx!
|
||||||
|
//
|
||||||
|
// Note that the derivative of f with respect to x is simply the infinitesimal
|
||||||
|
// component of the value of f(x + e). So, in order to take the derivative of
|
||||||
|
// any function, it is only necessary to replace the numeric "object" used in
|
||||||
|
// the function with one extended with infinitesimals. The class Jet, defined in
|
||||||
|
// this header, is one such example of this, where substitution is done with
|
||||||
|
// templates.
|
||||||
|
//
|
||||||
|
// To handle derivatives of functions taking multiple arguments, different
|
||||||
|
// infinitesimals are used, one for each variable to take the derivative of. For
|
||||||
|
// example, consider a scalar function of two scalar parameters x and y:
|
||||||
|
//
|
||||||
|
// f(x, y) = x^2 + x * y
|
||||||
|
//
|
||||||
|
// Following the technique above, to compute the derivatives df/dx and df/dy for
|
||||||
|
// f(1, 3) involves doing two evaluations of f, the first time replacing x with
|
||||||
|
// x + e, the second time replacing y with y + e.
|
||||||
|
//
|
||||||
|
// For df/dx:
|
||||||
|
//
|
||||||
|
// f(1 + e, y) = (1 + e)^2 + (1 + e) * 3
|
||||||
|
// = 1 + 2 * e + 3 + 3 * e
|
||||||
|
// = 4 + 5 * e
|
||||||
|
//
|
||||||
|
// --> df/dx = 5
|
||||||
|
//
|
||||||
|
// For df/dy:
|
||||||
|
//
|
||||||
|
// f(1, 3 + e) = 1^2 + 1 * (3 + e)
|
||||||
|
// = 1 + 3 + e
|
||||||
|
// = 4 + e
|
||||||
|
//
|
||||||
|
// --> df/dy = 1
|
||||||
|
//
|
||||||
|
// To take the gradient of f with the implementation of dual numbers ("jets") in
|
||||||
|
// this file, it is necessary to create a single jet type which has components
|
||||||
|
// for the derivative in x and y, and passing them to a templated version of f:
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// T f(const T &x, const T &y) {
|
||||||
|
// return x * x + x * y;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // The "2" means there should be 2 dual number components.
|
||||||
|
// Jet<double, 2> x(0); // Pick the 0th dual number for x.
|
||||||
|
// Jet<double, 2> y(1); // Pick the 1st dual number for y.
|
||||||
|
// Jet<double, 2> z = f(x, y);
|
||||||
|
//
|
||||||
|
// LOG(INFO) << "df/dx = " << z.a[0]
|
||||||
|
// << "df/dy = " << z.a[1];
|
||||||
|
//
|
||||||
|
// Most users should not use Jet objects directly; a wrapper around Jet objects,
|
||||||
|
// which makes computing the derivative, gradient, or jacobian of templated
|
||||||
|
// functors simple, is in autodiff.h. Even autodiff.h should not be used
|
||||||
|
// directly; instead autodiff_cost_function.h is typically the file of interest.
|
||||||
|
//
|
||||||
|
// For the more mathematically inclined, this file implements first-order
|
||||||
|
// "jets". A 1st order jet is an element of the ring
|
||||||
|
//
|
||||||
|
// T[N] = T[t_1, ..., t_N] / (t_1, ..., t_N)^2
|
||||||
|
//
|
||||||
|
// which essentially means that each jet consists of a "scalar" value 'a' from T
|
||||||
|
// and a 1st order perturbation vector 'v' of length N:
|
||||||
|
//
|
||||||
|
// x = a + \sum_i v[i] t_i
|
||||||
|
//
|
||||||
|
// A shorthand is to write an element as x = a + u, where u is the pertubation.
|
||||||
|
// Then, the main point about the arithmetic of jets is that the product of
|
||||||
|
// perturbations is zero:
|
||||||
|
//
|
||||||
|
// (a + u) * (b + v) = ab + av + bu + uv
|
||||||
|
// = ab + (av + bu) + 0
|
||||||
|
//
|
||||||
|
// which is what operator* implements below. Addition is simpler:
|
||||||
|
//
|
||||||
|
// (a + u) + (b + v) = (a + b) + (u + v).
|
||||||
|
//
|
||||||
|
// The only remaining question is how to evaluate the function of a jet, for
|
||||||
|
// which we use the chain rule:
|
||||||
|
//
|
||||||
|
// f(a + u) = f(a) + f'(a) u
|
||||||
|
//
|
||||||
|
// where f'(a) is the (scalar) derivative of f at a.
|
||||||
|
//
|
||||||
|
// By pushing these things through sufficiently and suitably templated
|
||||||
|
// functions, we can do automatic differentiation. Just be sure to turn on
|
||||||
|
// function inlining and common-subexpression elimination, or it will be very
|
||||||
|
// slow!
|
||||||
|
//
|
||||||
|
// WARNING: Most Ceres users should not directly include this file or know the
|
||||||
|
// details of how jets work. Instead the suggested method for automatic
|
||||||
|
// derivatives is to use autodiff_cost_function.h, which is a wrapper around
|
||||||
|
// both jets.h and autodiff.h to make taking derivatives of cost functions for
|
||||||
|
// use in Ceres easier.
|
||||||
|
|
||||||
|
#ifndef CERES_PUBLIC_JET_H_
|
||||||
|
#define CERES_PUBLIC_JET_H_
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <iostream> // NOLINT
|
||||||
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <gtsam/3rdparty/gtsam_eigen_includes.h>
|
||||||
|
#include <gtsam_unstable/nonlinear/ceres_fpclassify.h>
|
||||||
|
|
||||||
|
namespace ceres {
|
||||||
|
|
||||||
|
template <typename T, int N>
|
||||||
|
struct Jet {
|
||||||
|
enum { DIMENSION = N };
|
||||||
|
|
||||||
|
// Default-construct "a" because otherwise this can lead to false errors about
|
||||||
|
// uninitialized uses when other classes relying on default constructed T
|
||||||
|
// (where T is a Jet<T, N>). This usually only happens in opt mode. Note that
|
||||||
|
// the C++ standard mandates that e.g. default constructed doubles are
|
||||||
|
// initialized to 0.0; see sections 8.5 of the C++03 standard.
|
||||||
|
Jet() : a() {
|
||||||
|
v.setZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor from scalar: a + 0.
|
||||||
|
explicit Jet(const T& value) {
|
||||||
|
a = value;
|
||||||
|
v.setZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor from scalar plus variable: a + t_i.
|
||||||
|
Jet(const T& value, int k) {
|
||||||
|
a = value;
|
||||||
|
v.setZero();
|
||||||
|
v[k] = T(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor from scalar and vector part
|
||||||
|
// The use of Eigen::DenseBase allows Eigen expressions
|
||||||
|
// to be passed in without being fully evaluated until
|
||||||
|
// they are assigned to v
|
||||||
|
template<typename Derived>
|
||||||
|
EIGEN_STRONG_INLINE Jet(const T& a, const Eigen::DenseBase<Derived> &v)
|
||||||
|
: a(a), v(v) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compound operators
|
||||||
|
Jet<T, N>& operator+=(const Jet<T, N> &y) {
|
||||||
|
*this = *this + y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Jet<T, N>& operator-=(const Jet<T, N> &y) {
|
||||||
|
*this = *this - y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Jet<T, N>& operator*=(const Jet<T, N> &y) {
|
||||||
|
*this = *this * y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Jet<T, N>& operator/=(const Jet<T, N> &y) {
|
||||||
|
*this = *this / y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The scalar part.
|
||||||
|
T a;
|
||||||
|
|
||||||
|
// The infinitesimal part.
|
||||||
|
//
|
||||||
|
// Note the Eigen::DontAlign bit is needed here because this object
|
||||||
|
// gets allocated on the stack and as part of other arrays and
|
||||||
|
// structs. Forcing the right alignment there is the source of much
|
||||||
|
// pain and suffering. Even if that works, passing Jets around to
|
||||||
|
// functions by value has problems because the C++ ABI does not
|
||||||
|
// guarantee alignment for function arguments.
|
||||||
|
//
|
||||||
|
// Setting the DontAlign bit prevents Eigen from using SSE for the
|
||||||
|
// various operations on Jets. This is a small performance penalty
|
||||||
|
// since the AutoDiff code will still expose much of the code as
|
||||||
|
// statically sized loops to the compiler. But given the subtle
|
||||||
|
// issues that arise due to alignment, especially when dealing with
|
||||||
|
// multiple platforms, it seems to be a trade off worth making.
|
||||||
|
Eigen::Matrix<T, N, 1, Eigen::DontAlign> v;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Unary +
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> const& operator+(const Jet<T, N>& f) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(keir): Try adding __attribute__((always_inline)) to these functions to
|
||||||
|
// see if it causes a performance increase.
|
||||||
|
|
||||||
|
// Unary -
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator-(const Jet<T, N>&f) {
|
||||||
|
return Jet<T, N>(-f.a, -f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary +
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator+(const Jet<T, N>& f,
|
||||||
|
const Jet<T, N>& g) {
|
||||||
|
return Jet<T, N>(f.a + g.a, f.v + g.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary + with a scalar: x + s
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator+(const Jet<T, N>& f, T s) {
|
||||||
|
return Jet<T, N>(f.a + s, f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary + with a scalar: s + x
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator+(T s, const Jet<T, N>& f) {
|
||||||
|
return Jet<T, N>(f.a + s, f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary -
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator-(const Jet<T, N>& f,
|
||||||
|
const Jet<T, N>& g) {
|
||||||
|
return Jet<T, N>(f.a - g.a, f.v - g.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary - with a scalar: x - s
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator-(const Jet<T, N>& f, T s) {
|
||||||
|
return Jet<T, N>(f.a - s, f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary - with a scalar: s - x
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator-(T s, const Jet<T, N>& f) {
|
||||||
|
return Jet<T, N>(s - f.a, -f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary *
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator*(const Jet<T, N>& f,
|
||||||
|
const Jet<T, N>& g) {
|
||||||
|
return Jet<T, N>(f.a * g.a, f.a * g.v + f.v * g.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary * with a scalar: x * s
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator*(const Jet<T, N>& f, T s) {
|
||||||
|
return Jet<T, N>(f.a * s, f.v * s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary * with a scalar: s * x
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator*(T s, const Jet<T, N>& f) {
|
||||||
|
return Jet<T, N>(f.a * s, f.v * s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary /
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator/(const Jet<T, N>& f,
|
||||||
|
const Jet<T, N>& g) {
|
||||||
|
// This uses:
|
||||||
|
//
|
||||||
|
// a + u (a + u)(b - v) (a + u)(b - v)
|
||||||
|
// ----- = -------------- = --------------
|
||||||
|
// b + v (b + v)(b - v) b^2
|
||||||
|
//
|
||||||
|
// which holds because v*v = 0.
|
||||||
|
const T g_a_inverse = T(1.0) / g.a;
|
||||||
|
const T f_a_by_g_a = f.a * g_a_inverse;
|
||||||
|
return Jet<T, N>(f.a * g_a_inverse, (f.v - f_a_by_g_a * g.v) * g_a_inverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary / with a scalar: s / x
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator/(T s, const Jet<T, N>& g) {
|
||||||
|
const T minus_s_g_a_inverse2 = -s / (g.a * g.a);
|
||||||
|
return Jet<T, N>(s / g.a, g.v * minus_s_g_a_inverse2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary / with a scalar: x / s
|
||||||
|
template<typename T, int N> inline
|
||||||
|
Jet<T, N> operator/(const Jet<T, N>& f, T s) {
|
||||||
|
const T s_inverse = 1.0 / s;
|
||||||
|
return Jet<T, N>(f.a * s_inverse, f.v * s_inverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary comparison operators for both scalars and jets.
|
||||||
|
#define CERES_DEFINE_JET_COMPARISON_OPERATOR(op) \
|
||||||
|
template<typename T, int N> inline \
|
||||||
|
bool operator op(const Jet<T, N>& f, const Jet<T, N>& g) { \
|
||||||
|
return f.a op g.a; \
|
||||||
|
} \
|
||||||
|
template<typename T, int N> inline \
|
||||||
|
bool operator op(const T& s, const Jet<T, N>& g) { \
|
||||||
|
return s op g.a; \
|
||||||
|
} \
|
||||||
|
template<typename T, int N> inline \
|
||||||
|
bool operator op(const Jet<T, N>& f, const T& s) { \
|
||||||
|
return f.a op s; \
|
||||||
|
}
|
||||||
|
CERES_DEFINE_JET_COMPARISON_OPERATOR( < ) // NOLINT
|
||||||
|
CERES_DEFINE_JET_COMPARISON_OPERATOR( <= ) // NOLINT
|
||||||
|
CERES_DEFINE_JET_COMPARISON_OPERATOR( > ) // NOLINT
|
||||||
|
CERES_DEFINE_JET_COMPARISON_OPERATOR( >= ) // NOLINT
|
||||||
|
CERES_DEFINE_JET_COMPARISON_OPERATOR( == ) // NOLINT
|
||||||
|
CERES_DEFINE_JET_COMPARISON_OPERATOR( != ) // NOLINT
|
||||||
|
#undef CERES_DEFINE_JET_COMPARISON_OPERATOR
|
||||||
|
|
||||||
|
// Pull some functions from namespace std.
|
||||||
|
//
|
||||||
|
// This is necessary because we want to use the same name (e.g. 'sqrt') for
|
||||||
|
// double-valued and Jet-valued functions, but we are not allowed to put
|
||||||
|
// Jet-valued functions inside namespace std.
|
||||||
|
//
|
||||||
|
// TODO(keir): Switch to "using".
|
||||||
|
inline double abs (double x) { return std::abs(x); }
|
||||||
|
inline double log (double x) { return std::log(x); }
|
||||||
|
inline double exp (double x) { return std::exp(x); }
|
||||||
|
inline double sqrt (double x) { return std::sqrt(x); }
|
||||||
|
inline double cos (double x) { return std::cos(x); }
|
||||||
|
inline double acos (double x) { return std::acos(x); }
|
||||||
|
inline double sin (double x) { return std::sin(x); }
|
||||||
|
inline double asin (double x) { return std::asin(x); }
|
||||||
|
inline double tan (double x) { return std::tan(x); }
|
||||||
|
inline double atan (double x) { return std::atan(x); }
|
||||||
|
inline double sinh (double x) { return std::sinh(x); }
|
||||||
|
inline double cosh (double x) { return std::cosh(x); }
|
||||||
|
inline double tanh (double x) { return std::tanh(x); }
|
||||||
|
inline double pow (double x, double y) { return std::pow(x, y); }
|
||||||
|
inline double atan2(double y, double x) { return std::atan2(y, x); }
|
||||||
|
|
||||||
|
// In general, f(a + h) ~= f(a) + f'(a) h, via the chain rule.
|
||||||
|
|
||||||
|
// abs(x + h) ~= x + h or -(x + h)
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> abs(const Jet<T, N>& f) {
|
||||||
|
return f.a < T(0.0) ? -f : f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// log(a + h) ~= log(a) + h / a
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> log(const Jet<T, N>& f) {
|
||||||
|
const T a_inverse = T(1.0) / f.a;
|
||||||
|
return Jet<T, N>(log(f.a), f.v * a_inverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// exp(a + h) ~= exp(a) + exp(a) h
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> exp(const Jet<T, N>& f) {
|
||||||
|
const T tmp = exp(f.a);
|
||||||
|
return Jet<T, N>(tmp, tmp * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sqrt(a + h) ~= sqrt(a) + h / (2 sqrt(a))
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> sqrt(const Jet<T, N>& f) {
|
||||||
|
const T tmp = sqrt(f.a);
|
||||||
|
const T two_a_inverse = T(1.0) / (T(2.0) * tmp);
|
||||||
|
return Jet<T, N>(tmp, f.v * two_a_inverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cos(a + h) ~= cos(a) - sin(a) h
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> cos(const Jet<T, N>& f) {
|
||||||
|
return Jet<T, N>(cos(f.a), - sin(f.a) * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// acos(a + h) ~= acos(a) - 1 / sqrt(1 - a^2) h
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> acos(const Jet<T, N>& f) {
|
||||||
|
const T tmp = - T(1.0) / sqrt(T(1.0) - f.a * f.a);
|
||||||
|
return Jet<T, N>(acos(f.a), tmp * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sin(a + h) ~= sin(a) + cos(a) h
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> sin(const Jet<T, N>& f) {
|
||||||
|
return Jet<T, N>(sin(f.a), cos(f.a) * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// asin(a + h) ~= asin(a) + 1 / sqrt(1 - a^2) h
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> asin(const Jet<T, N>& f) {
|
||||||
|
const T tmp = T(1.0) / sqrt(T(1.0) - f.a * f.a);
|
||||||
|
return Jet<T, N>(asin(f.a), tmp * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// tan(a + h) ~= tan(a) + (1 + tan(a)^2) h
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> tan(const Jet<T, N>& f) {
|
||||||
|
const T tan_a = tan(f.a);
|
||||||
|
const T tmp = T(1.0) + tan_a * tan_a;
|
||||||
|
return Jet<T, N>(tan_a, tmp * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// atan(a + h) ~= atan(a) + 1 / (1 + a^2) h
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> atan(const Jet<T, N>& f) {
|
||||||
|
const T tmp = T(1.0) / (T(1.0) + f.a * f.a);
|
||||||
|
return Jet<T, N>(atan(f.a), tmp * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sinh(a + h) ~= sinh(a) + cosh(a) h
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> sinh(const Jet<T, N>& f) {
|
||||||
|
return Jet<T, N>(sinh(f.a), cosh(f.a) * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cosh(a + h) ~= cosh(a) + sinh(a) h
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> cosh(const Jet<T, N>& f) {
|
||||||
|
return Jet<T, N>(cosh(f.a), sinh(f.a) * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// tanh(a + h) ~= tanh(a) + (1 - tanh(a)^2) h
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> tanh(const Jet<T, N>& f) {
|
||||||
|
const T tanh_a = tanh(f.a);
|
||||||
|
const T tmp = T(1.0) - tanh_a * tanh_a;
|
||||||
|
return Jet<T, N>(tanh_a, tmp * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jet Classification. It is not clear what the appropriate semantics are for
|
||||||
|
// these classifications. This picks that IsFinite and isnormal are "all"
|
||||||
|
// operations, i.e. all elements of the jet must be finite for the jet itself
|
||||||
|
// to be finite (or normal). For IsNaN and IsInfinite, the answer is less
|
||||||
|
// clear. This takes a "any" approach for IsNaN and IsInfinite such that if any
|
||||||
|
// part of a jet is nan or inf, then the entire jet is nan or inf. This leads
|
||||||
|
// to strange situations like a jet can be both IsInfinite and IsNaN, but in
|
||||||
|
// practice the "any" semantics are the most useful for e.g. checking that
|
||||||
|
// derivatives are sane.
|
||||||
|
|
||||||
|
// The jet is finite if all parts of the jet are finite.
|
||||||
|
template <typename T, int N> inline
|
||||||
|
bool IsFinite(const Jet<T, N>& f) {
|
||||||
|
if (!IsFinite(f.a)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < N; ++i) {
|
||||||
|
if (!IsFinite(f.v[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The jet is infinite if any part of the jet is infinite.
|
||||||
|
template <typename T, int N> inline
|
||||||
|
bool IsInfinite(const Jet<T, N>& f) {
|
||||||
|
if (IsInfinite(f.a)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
if (IsInfinite(f.v[i])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The jet is NaN if any part of the jet is NaN.
|
||||||
|
template <typename T, int N> inline
|
||||||
|
bool IsNaN(const Jet<T, N>& f) {
|
||||||
|
if (IsNaN(f.a)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < N; ++i) {
|
||||||
|
if (IsNaN(f.v[i])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The jet is normal if all parts of the jet are normal.
|
||||||
|
template <typename T, int N> inline
|
||||||
|
bool IsNormal(const Jet<T, N>& f) {
|
||||||
|
if (!IsNormal(f.a)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < N; ++i) {
|
||||||
|
if (!IsNormal(f.v[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// atan2(b + db, a + da) ~= atan2(b, a) + (- b da + a db) / (a^2 + b^2)
|
||||||
|
//
|
||||||
|
// In words: the rate of change of theta is 1/r times the rate of
|
||||||
|
// change of (x, y) in the positive angular direction.
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> atan2(const Jet<T, N>& g, const Jet<T, N>& f) {
|
||||||
|
// Note order of arguments:
|
||||||
|
//
|
||||||
|
// f = a + da
|
||||||
|
// g = b + db
|
||||||
|
|
||||||
|
T const tmp = T(1.0) / (f.a * f.a + g.a * g.a);
|
||||||
|
return Jet<T, N>(atan2(g.a, f.a), tmp * (- g.a * f.v + f.a * g.v));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// pow -- base is a differentiable function, exponent is a constant.
|
||||||
|
// (a+da)^p ~= a^p + p*a^(p-1) da
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> pow(const Jet<T, N>& f, double g) {
|
||||||
|
T const tmp = g * pow(f.a, g - T(1.0));
|
||||||
|
return Jet<T, N>(pow(f.a, g), tmp * f.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pow -- base is a constant, exponent is a differentiable function.
|
||||||
|
// (a)^(p+dp) ~= a^p + a^p log(a) dp
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> pow(double f, const Jet<T, N>& g) {
|
||||||
|
T const tmp = pow(f, g.a);
|
||||||
|
return Jet<T, N>(tmp, log(f) * tmp * g.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// pow -- both base and exponent are differentiable functions.
|
||||||
|
// (a+da)^(b+db) ~= a^b + b * a^(b-1) da + a^b log(a) * db
|
||||||
|
template <typename T, int N> inline
|
||||||
|
Jet<T, N> pow(const Jet<T, N>& f, const Jet<T, N>& g) {
|
||||||
|
T const tmp1 = pow(f.a, g.a);
|
||||||
|
T const tmp2 = g.a * pow(f.a, g.a - T(1.0));
|
||||||
|
T const tmp3 = tmp1 * log(f.a);
|
||||||
|
|
||||||
|
return Jet<T, N>(tmp1, tmp2 * f.v + tmp3 * g.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the helper functions Eigen needs to embed Jet types.
|
||||||
|
//
|
||||||
|
// NOTE(keir): machine_epsilon() and precision() are missing, because they don't
|
||||||
|
// work with nested template types (e.g. where the scalar is itself templated).
|
||||||
|
// Among other things, this means that decompositions of Jet's does not work,
|
||||||
|
// for example
|
||||||
|
//
|
||||||
|
// Matrix<Jet<T, N> ... > A, x, b;
|
||||||
|
// ...
|
||||||
|
// A.solve(b, &x)
|
||||||
|
//
|
||||||
|
// does not work and will fail with a strange compiler error.
|
||||||
|
//
|
||||||
|
// TODO(keir): This is an Eigen 2.0 limitation that is lifted in 3.0. When we
|
||||||
|
// switch to 3.0, also add the rest of the specialization functionality.
|
||||||
|
template<typename T, int N> inline const Jet<T, N>& ei_conj(const Jet<T, N>& x) { return x; } // NOLINT
|
||||||
|
template<typename T, int N> inline const Jet<T, N>& ei_real(const Jet<T, N>& x) { return x; } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_imag(const Jet<T, N>& ) { return Jet<T, N>(0.0); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_abs (const Jet<T, N>& x) { return fabs(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_abs2(const Jet<T, N>& x) { return x * x; } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_sqrt(const Jet<T, N>& x) { return sqrt(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_exp (const Jet<T, N>& x) { return exp(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_log (const Jet<T, N>& x) { return log(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_sin (const Jet<T, N>& x) { return sin(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_cos (const Jet<T, N>& x) { return cos(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_tan (const Jet<T, N>& x) { return tan(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_atan(const Jet<T, N>& x) { return atan(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_sinh(const Jet<T, N>& x) { return sinh(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_cosh(const Jet<T, N>& x) { return cosh(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_tanh(const Jet<T, N>& x) { return tanh(x); } // NOLINT
|
||||||
|
template<typename T, int N> inline Jet<T, N> ei_pow (const Jet<T, N>& x, Jet<T, N> y) { return pow(x, y); } // NOLINT
|
||||||
|
|
||||||
|
// Note: This has to be in the ceres namespace for argument dependent lookup to
|
||||||
|
// function correctly. Otherwise statements like CHECK_LE(x, 2.0) fail with
|
||||||
|
// strange compile errors.
|
||||||
|
template <typename T, int N>
|
||||||
|
inline std::ostream &operator<<(std::ostream &s, const Jet<T, N>& z) {
|
||||||
|
return s << "[" << z.a << " ; " << z.v.transpose() << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ceres
|
||||||
|
|
||||||
|
namespace Eigen {
|
||||||
|
|
||||||
|
// Creating a specialization of NumTraits enables placing Jet objects inside
|
||||||
|
// Eigen arrays, getting all the goodness of Eigen combined with autodiff.
|
||||||
|
template<typename T, int N>
|
||||||
|
struct NumTraits<ceres::Jet<T, N> > {
|
||||||
|
typedef ceres::Jet<T, N> Real;
|
||||||
|
typedef ceres::Jet<T, N> NonInteger;
|
||||||
|
typedef ceres::Jet<T, N> Nested;
|
||||||
|
|
||||||
|
static typename ceres::Jet<T, N> dummy_precision() {
|
||||||
|
return ceres::Jet<T, N>(1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Real epsilon() {
|
||||||
|
return Real(std::numeric_limits<T>::epsilon());
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IsComplex = 0,
|
||||||
|
IsInteger = 0,
|
||||||
|
IsSigned,
|
||||||
|
ReadCost = 1,
|
||||||
|
AddCost = 1,
|
||||||
|
// For Jet types, multiplication is more expensive than addition.
|
||||||
|
MulCost = 3,
|
||||||
|
HasFloatingPoint = 1,
|
||||||
|
RequireInitialization = 1
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Eigen
|
||||||
|
|
||||||
|
#endif // CERES_PUBLIC_JET_H_
|
|
@ -0,0 +1,170 @@
|
||||||
|
// Ceres Solver - A fast non-linear least squares minimizer
|
||||||
|
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/ceres-solver/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Various Google-specific macros.
|
||||||
|
//
|
||||||
|
// This code is compiled directly on many platforms, including client
|
||||||
|
// platforms like Windows, Mac, and embedded systems. Before making
|
||||||
|
// any changes here, make sure that you're not breaking any platforms.
|
||||||
|
|
||||||
|
#ifndef CERES_PUBLIC_INTERNAL_MACROS_H_
|
||||||
|
#define CERES_PUBLIC_INTERNAL_MACROS_H_
|
||||||
|
|
||||||
|
#include <cstddef> // For size_t.
|
||||||
|
|
||||||
|
// A macro to disallow the copy constructor and operator= functions
|
||||||
|
// This should be used in the private: declarations for a class
|
||||||
|
//
|
||||||
|
// For disallowing only assign or copy, write the code directly, but declare
|
||||||
|
// the intend in a comment, for example:
|
||||||
|
//
|
||||||
|
// void operator=(const TypeName&); // _DISALLOW_ASSIGN
|
||||||
|
|
||||||
|
// Note, that most uses of CERES_DISALLOW_ASSIGN and CERES_DISALLOW_COPY
|
||||||
|
// are broken semantically, one should either use disallow both or
|
||||||
|
// neither. Try to avoid these in new code.
|
||||||
|
#define CERES_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||||
|
TypeName(const TypeName&); \
|
||||||
|
void operator=(const TypeName&)
|
||||||
|
|
||||||
|
// A macro to disallow all the implicit constructors, namely the
|
||||||
|
// default constructor, copy constructor and operator= functions.
|
||||||
|
//
|
||||||
|
// This should be used in the private: declarations for a class
|
||||||
|
// that wants to prevent anyone from instantiating it. This is
|
||||||
|
// especially useful for classes containing only static methods.
|
||||||
|
#define CERES_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||||
|
TypeName(); \
|
||||||
|
CERES_DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||||
|
|
||||||
|
// The arraysize(arr) macro returns the # of elements in an array arr.
|
||||||
|
// The expression is a compile-time constant, and therefore can be
|
||||||
|
// used in defining new arrays, for example. If you use arraysize on
|
||||||
|
// a pointer by mistake, you will get a compile-time error.
|
||||||
|
//
|
||||||
|
// One caveat is that arraysize() doesn't accept any array of an
|
||||||
|
// anonymous type or a type defined inside a function. In these rare
|
||||||
|
// cases, you have to use the unsafe ARRAYSIZE() macro below. This is
|
||||||
|
// due to a limitation in C++'s template system. The limitation might
|
||||||
|
// eventually be removed, but it hasn't happened yet.
|
||||||
|
|
||||||
|
// This template function declaration is used in defining arraysize.
|
||||||
|
// Note that the function doesn't need an implementation, as we only
|
||||||
|
// use its type.
|
||||||
|
template <typename T, size_t N>
|
||||||
|
char (&ArraySizeHelper(T (&array)[N]))[N];
|
||||||
|
|
||||||
|
// That gcc wants both of these prototypes seems mysterious. VC, for
|
||||||
|
// its part, can't decide which to use (another mystery). Matching of
|
||||||
|
// template overloads: the final frontier.
|
||||||
|
#ifndef _WIN32
|
||||||
|
template <typename T, size_t N>
|
||||||
|
char (&ArraySizeHelper(const T (&array)[N]))[N];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
|
||||||
|
|
||||||
|
// ARRAYSIZE performs essentially the same calculation as arraysize,
|
||||||
|
// but can be used on anonymous types or types defined inside
|
||||||
|
// functions. It's less safe than arraysize as it accepts some
|
||||||
|
// (although not all) pointers. Therefore, you should use arraysize
|
||||||
|
// whenever possible.
|
||||||
|
//
|
||||||
|
// The expression ARRAYSIZE(a) is a compile-time constant of type
|
||||||
|
// size_t.
|
||||||
|
//
|
||||||
|
// ARRAYSIZE catches a few type errors. If you see a compiler error
|
||||||
|
//
|
||||||
|
// "warning: division by zero in ..."
|
||||||
|
//
|
||||||
|
// when using ARRAYSIZE, you are (wrongfully) giving it a pointer.
|
||||||
|
// You should only use ARRAYSIZE on statically allocated arrays.
|
||||||
|
//
|
||||||
|
// The following comments are on the implementation details, and can
|
||||||
|
// be ignored by the users.
|
||||||
|
//
|
||||||
|
// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
|
||||||
|
// the array) and sizeof(*(arr)) (the # of bytes in one array
|
||||||
|
// element). If the former is divisible by the latter, perhaps arr is
|
||||||
|
// indeed an array, in which case the division result is the # of
|
||||||
|
// elements in the array. Otherwise, arr cannot possibly be an array,
|
||||||
|
// and we generate a compiler error to prevent the code from
|
||||||
|
// compiling.
|
||||||
|
//
|
||||||
|
// Since the size of bool is implementation-defined, we need to cast
|
||||||
|
// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
|
||||||
|
// result has type size_t.
|
||||||
|
//
|
||||||
|
// This macro is not perfect as it wrongfully accepts certain
|
||||||
|
// pointers, namely where the pointer size is divisible by the pointee
|
||||||
|
// size. Since all our code has to go through a 32-bit compiler,
|
||||||
|
// where a pointer is 4 bytes, this means all pointers to a type whose
|
||||||
|
// size is 3 or greater than 4 will be (righteously) rejected.
|
||||||
|
//
|
||||||
|
// Kudos to Jorg Brown for this simple and elegant implementation.
|
||||||
|
//
|
||||||
|
// - wan 2005-11-16
|
||||||
|
//
|
||||||
|
// Starting with Visual C++ 2005, WinNT.h includes ARRAYSIZE. However,
|
||||||
|
// the definition comes from the over-broad windows.h header that
|
||||||
|
// introduces a macro, ERROR, that conflicts with the logging framework
|
||||||
|
// that Ceres uses. Instead, rename ARRAYSIZE to CERES_ARRAYSIZE.
|
||||||
|
#define CERES_ARRAYSIZE(a) \
|
||||||
|
((sizeof(a) / sizeof(*(a))) / \
|
||||||
|
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
|
||||||
|
|
||||||
|
// Tell the compiler to warn about unused return values for functions
|
||||||
|
// declared with this macro. The macro should be used on function
|
||||||
|
// declarations following the argument list:
|
||||||
|
//
|
||||||
|
// Sprocket* AllocateSprocket() MUST_USE_RESULT;
|
||||||
|
//
|
||||||
|
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \
|
||||||
|
&& !defined(COMPILER_ICC)
|
||||||
|
#define CERES_MUST_USE_RESULT __attribute__ ((warn_unused_result))
|
||||||
|
#else
|
||||||
|
#define CERES_MUST_USE_RESULT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Platform independent macros to get aligned memory allocations.
|
||||||
|
// For example
|
||||||
|
//
|
||||||
|
// MyFoo my_foo CERES_ALIGN_ATTRIBUTE(16);
|
||||||
|
//
|
||||||
|
// Gives us an instance of MyFoo which is aligned at a 16 byte
|
||||||
|
// boundary.
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define CERES_ALIGN_ATTRIBUTE(n) __declspec(align(n))
|
||||||
|
#define CERES_ALIGN_OF(T) __alignof(T)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define CERES_ALIGN_ATTRIBUTE(n) __attribute__((aligned(n)))
|
||||||
|
#define CERES_ALIGN_OF(T) __alignof(T)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CERES_PUBLIC_INTERNAL_MACROS_H_
|
|
@ -0,0 +1,208 @@
|
||||||
|
// Ceres Solver - A fast non-linear least squares minimizer
|
||||||
|
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/ceres-solver/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
//
|
||||||
|
// ManualConstructor statically-allocates space in which to store some
|
||||||
|
// object, but does not initialize it. You can then call the constructor
|
||||||
|
// and destructor for the object yourself as you see fit. This is useful
|
||||||
|
// for memory management optimizations, where you want to initialize and
|
||||||
|
// destroy an object multiple times but only allocate it once.
|
||||||
|
//
|
||||||
|
// (When I say ManualConstructor statically allocates space, I mean that
|
||||||
|
// the ManualConstructor object itself is forced to be the right size.)
|
||||||
|
|
||||||
|
#ifndef CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
|
||||||
|
#define CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
namespace ceres {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// ------- Define CERES_ALIGNED_CHAR_ARRAY --------------------------------
|
||||||
|
|
||||||
|
#ifndef CERES_ALIGNED_CHAR_ARRAY
|
||||||
|
|
||||||
|
// Because MSVC and older GCCs require that the argument to their alignment
|
||||||
|
// construct to be a literal constant integer, we use a template instantiated
|
||||||
|
// at all the possible powers of two.
|
||||||
|
template<int alignment, int size> struct AlignType { };
|
||||||
|
template<int size> struct AlignType<0, size> { typedef char result[size]; };
|
||||||
|
|
||||||
|
#if !defined(CERES_ALIGN_ATTRIBUTE)
|
||||||
|
#define CERES_ALIGNED_CHAR_ARRAY you_must_define_CERES_ALIGNED_CHAR_ARRAY_for_your_compiler
|
||||||
|
#else // !defined(CERES_ALIGN_ATTRIBUTE)
|
||||||
|
|
||||||
|
#define CERES_ALIGN_TYPE_TEMPLATE(X) \
|
||||||
|
template<int size> struct AlignType<X, size> { \
|
||||||
|
typedef CERES_ALIGN_ATTRIBUTE(X) char result[size]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(1);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(2);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(4);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(8);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(16);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(32);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(64);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(128);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(256);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(512);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(1024);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(2048);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(4096);
|
||||||
|
CERES_ALIGN_TYPE_TEMPLATE(8192);
|
||||||
|
// Any larger and MSVC++ will complain.
|
||||||
|
|
||||||
|
#undef CERES_ALIGN_TYPE_TEMPLATE
|
||||||
|
|
||||||
|
#define CERES_ALIGNED_CHAR_ARRAY(T, Size) \
|
||||||
|
typename AlignType<CERES_ALIGN_OF(T), sizeof(T) * Size>::result
|
||||||
|
|
||||||
|
#endif // !defined(CERES_ALIGN_ATTRIBUTE)
|
||||||
|
|
||||||
|
#endif // CERES_ALIGNED_CHAR_ARRAY
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
class ManualConstructor {
|
||||||
|
public:
|
||||||
|
// No constructor or destructor because one of the most useful uses of
|
||||||
|
// this class is as part of a union, and members of a union cannot have
|
||||||
|
// constructors or destructors. And, anyway, the whole point of this
|
||||||
|
// class is to bypass these.
|
||||||
|
|
||||||
|
inline Type* get() {
|
||||||
|
return reinterpret_cast<Type*>(space_);
|
||||||
|
}
|
||||||
|
inline const Type* get() const {
|
||||||
|
return reinterpret_cast<const Type*>(space_);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Type* operator->() { return get(); }
|
||||||
|
inline const Type* operator->() const { return get(); }
|
||||||
|
|
||||||
|
inline Type& operator*() { return *get(); }
|
||||||
|
inline const Type& operator*() const { return *get(); }
|
||||||
|
|
||||||
|
// This is needed to get around the strict aliasing warning GCC generates.
|
||||||
|
inline void* space() {
|
||||||
|
return reinterpret_cast<void*>(space_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can pass up to four constructor arguments as arguments of Init().
|
||||||
|
inline void Init() {
|
||||||
|
new(space()) Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1>
|
||||||
|
inline void Init(const T1& p1) {
|
||||||
|
new(space()) Type(p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
inline void Init(const T1& p1, const T2& p2) {
|
||||||
|
new(space()) Type(p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3>
|
||||||
|
inline void Init(const T1& p1, const T2& p2, const T3& p3) {
|
||||||
|
new(space()) Type(p1, p2, p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4>
|
||||||
|
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) {
|
||||||
|
new(space()) Type(p1, p2, p3, p4);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||||
|
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||||
|
const T5& p5) {
|
||||||
|
new(space()) Type(p1, p2, p3, p4, p5);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6>
|
||||||
|
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||||
|
const T5& p5, const T6& p6) {
|
||||||
|
new(space()) Type(p1, p2, p3, p4, p5, p6);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6, typename T7>
|
||||||
|
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||||
|
const T5& p5, const T6& p6, const T7& p7) {
|
||||||
|
new(space()) Type(p1, p2, p3, p4, p5, p6, p7);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6, typename T7, typename T8>
|
||||||
|
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||||
|
const T5& p5, const T6& p6, const T7& p7, const T8& p8) {
|
||||||
|
new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6, typename T7, typename T8, typename T9>
|
||||||
|
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||||
|
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
|
||||||
|
const T9& p9) {
|
||||||
|
new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6, typename T7, typename T8, typename T9, typename T10>
|
||||||
|
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||||
|
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
|
||||||
|
const T9& p9, const T10& p10) {
|
||||||
|
new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
|
typename T6, typename T7, typename T8, typename T9, typename T10,
|
||||||
|
typename T11>
|
||||||
|
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||||
|
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
|
||||||
|
const T9& p9, const T10& p10, const T11& p11) {
|
||||||
|
new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Destroy() {
|
||||||
|
get()->~Type();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CERES_ALIGNED_CHAR_ARRAY(Type, 1) space_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef CERES_ALIGNED_CHAR_ARRAY
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace ceres
|
||||||
|
|
||||||
|
#endif // CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
|
|
@ -0,0 +1,644 @@
|
||||||
|
// Ceres Solver - A fast non-linear least squares minimizer
|
||||||
|
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/ceres-solver/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: keir@google.com (Keir Mierle)
|
||||||
|
// sameeragarwal@google.com (Sameer Agarwal)
|
||||||
|
//
|
||||||
|
// Templated functions for manipulating rotations. The templated
|
||||||
|
// functions are useful when implementing functors for automatic
|
||||||
|
// differentiation.
|
||||||
|
//
|
||||||
|
// In the following, the Quaternions are laid out as 4-vectors, thus:
|
||||||
|
//
|
||||||
|
// q[0] scalar part.
|
||||||
|
// q[1] coefficient of i.
|
||||||
|
// q[2] coefficient of j.
|
||||||
|
// q[3] coefficient of k.
|
||||||
|
//
|
||||||
|
// where: i*i = j*j = k*k = -1 and i*j = k, j*k = i, k*i = j.
|
||||||
|
|
||||||
|
#ifndef CERES_PUBLIC_ROTATION_H_
|
||||||
|
#define CERES_PUBLIC_ROTATION_H_
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace ceres {
|
||||||
|
|
||||||
|
// Trivial wrapper to index linear arrays as matrices, given a fixed
|
||||||
|
// column and row stride. When an array "T* array" is wrapped by a
|
||||||
|
//
|
||||||
|
// (const) MatrixAdapter<T, row_stride, col_stride> M"
|
||||||
|
//
|
||||||
|
// the expression M(i, j) is equivalent to
|
||||||
|
//
|
||||||
|
// arrary[i * row_stride + j * col_stride]
|
||||||
|
//
|
||||||
|
// Conversion functions to and from rotation matrices accept
|
||||||
|
// MatrixAdapters to permit using row-major and column-major layouts,
|
||||||
|
// and rotation matrices embedded in larger matrices (such as a 3x4
|
||||||
|
// projection matrix).
|
||||||
|
template <typename T, int row_stride, int col_stride>
|
||||||
|
struct MatrixAdapter;
|
||||||
|
|
||||||
|
// Convenience functions to create a MatrixAdapter that treats the
|
||||||
|
// array pointed to by "pointer" as a 3x3 (contiguous) column-major or
|
||||||
|
// row-major matrix.
|
||||||
|
template <typename T>
|
||||||
|
MatrixAdapter<T, 1, 3> ColumnMajorAdapter3x3(T* pointer);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
MatrixAdapter<T, 3, 1> RowMajorAdapter3x3(T* pointer);
|
||||||
|
|
||||||
|
// Convert a value in combined axis-angle representation to a quaternion.
|
||||||
|
// The value angle_axis is a triple whose norm is an angle in radians,
|
||||||
|
// and whose direction is aligned with the axis of rotation,
|
||||||
|
// and quaternion is a 4-tuple that will contain the resulting quaternion.
|
||||||
|
// The implementation may be used with auto-differentiation up to the first
|
||||||
|
// derivative, higher derivatives may have unexpected results near the origin.
|
||||||
|
template<typename T>
|
||||||
|
void AngleAxisToQuaternion(const T* angle_axis, T* quaternion);
|
||||||
|
|
||||||
|
// Convert a quaternion to the equivalent combined axis-angle representation.
|
||||||
|
// The value quaternion must be a unit quaternion - it is not normalized first,
|
||||||
|
// and angle_axis will be filled with a value whose norm is the angle of
|
||||||
|
// rotation in radians, and whose direction is the axis of rotation.
|
||||||
|
// The implemention may be used with auto-differentiation up to the first
|
||||||
|
// derivative, higher derivatives may have unexpected results near the origin.
|
||||||
|
template<typename T>
|
||||||
|
void QuaternionToAngleAxis(const T* quaternion, T* angle_axis);
|
||||||
|
|
||||||
|
// Conversions between 3x3 rotation matrix (in column major order) and
|
||||||
|
// axis-angle rotation representations. Templated for use with
|
||||||
|
// autodifferentiation.
|
||||||
|
template <typename T>
|
||||||
|
void RotationMatrixToAngleAxis(const T* R, T* angle_axis);
|
||||||
|
|
||||||
|
template <typename T, int row_stride, int col_stride>
|
||||||
|
void RotationMatrixToAngleAxis(
|
||||||
|
const MatrixAdapter<const T, row_stride, col_stride>& R,
|
||||||
|
T* angle_axis);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void AngleAxisToRotationMatrix(const T* angle_axis, T* R);
|
||||||
|
|
||||||
|
template <typename T, int row_stride, int col_stride>
|
||||||
|
void AngleAxisToRotationMatrix(
|
||||||
|
const T* angle_axis,
|
||||||
|
const MatrixAdapter<T, row_stride, col_stride>& R);
|
||||||
|
|
||||||
|
// Conversions between 3x3 rotation matrix (in row major order) and
|
||||||
|
// Euler angle (in degrees) rotation representations.
|
||||||
|
//
|
||||||
|
// The {pitch,roll,yaw} Euler angles are rotations around the {x,y,z}
|
||||||
|
// axes, respectively. They are applied in that same order, so the
|
||||||
|
// total rotation R is Rz * Ry * Rx.
|
||||||
|
template <typename T>
|
||||||
|
void EulerAnglesToRotationMatrix(const T* euler, int row_stride, T* R);
|
||||||
|
|
||||||
|
template <typename T, int row_stride, int col_stride>
|
||||||
|
void EulerAnglesToRotationMatrix(
|
||||||
|
const T* euler,
|
||||||
|
const MatrixAdapter<T, row_stride, col_stride>& R);
|
||||||
|
|
||||||
|
// Convert a 4-vector to a 3x3 scaled rotation matrix.
|
||||||
|
//
|
||||||
|
// The choice of rotation is such that the quaternion [1 0 0 0] goes to an
|
||||||
|
// identity matrix and for small a, b, c the quaternion [1 a b c] goes to
|
||||||
|
// the matrix
|
||||||
|
//
|
||||||
|
// [ 0 -c b ]
|
||||||
|
// I + 2 [ c 0 -a ] + higher order terms
|
||||||
|
// [ -b a 0 ]
|
||||||
|
//
|
||||||
|
// which corresponds to a Rodrigues approximation, the last matrix being
|
||||||
|
// the cross-product matrix of [a b c]. Together with the property that
|
||||||
|
// R(q1 * q2) = R(q1) * R(q2) this uniquely defines the mapping from q to R.
|
||||||
|
//
|
||||||
|
// The rotation matrix is row-major.
|
||||||
|
//
|
||||||
|
// No normalization of the quaternion is performed, i.e.
|
||||||
|
// R = ||q||^2 * Q, where Q is an orthonormal matrix
|
||||||
|
// such that det(Q) = 1 and Q*Q' = I
|
||||||
|
template <typename T> inline
|
||||||
|
void QuaternionToScaledRotation(const T q[4], T R[3 * 3]);
|
||||||
|
|
||||||
|
template <typename T, int row_stride, int col_stride> inline
|
||||||
|
void QuaternionToScaledRotation(
|
||||||
|
const T q[4],
|
||||||
|
const MatrixAdapter<T, row_stride, col_stride>& R);
|
||||||
|
|
||||||
|
// Same as above except that the rotation matrix is normalized by the
|
||||||
|
// Frobenius norm, so that R * R' = I (and det(R) = 1).
|
||||||
|
template <typename T> inline
|
||||||
|
void QuaternionToRotation(const T q[4], T R[3 * 3]);
|
||||||
|
|
||||||
|
template <typename T, int row_stride, int col_stride> inline
|
||||||
|
void QuaternionToRotation(
|
||||||
|
const T q[4],
|
||||||
|
const MatrixAdapter<T, row_stride, col_stride>& R);
|
||||||
|
|
||||||
|
// Rotates a point pt by a quaternion q:
|
||||||
|
//
|
||||||
|
// result = R(q) * pt
|
||||||
|
//
|
||||||
|
// Assumes the quaternion is unit norm. This assumption allows us to
|
||||||
|
// write the transform as (something)*pt + pt, as is clear from the
|
||||||
|
// formula below. If you pass in a quaternion with |q|^2 = 2 then you
|
||||||
|
// WILL NOT get back 2 times the result you get for a unit quaternion.
|
||||||
|
template <typename T> inline
|
||||||
|
void UnitQuaternionRotatePoint(const T q[4], const T pt[3], T result[3]);
|
||||||
|
|
||||||
|
// With this function you do not need to assume that q has unit norm.
|
||||||
|
// It does assume that the norm is non-zero.
|
||||||
|
template <typename T> inline
|
||||||
|
void QuaternionRotatePoint(const T q[4], const T pt[3], T result[3]);
|
||||||
|
|
||||||
|
// zw = z * w, where * is the Quaternion product between 4 vectors.
|
||||||
|
template<typename T> inline
|
||||||
|
void QuaternionProduct(const T z[4], const T w[4], T zw[4]);
|
||||||
|
|
||||||
|
// xy = x cross y;
|
||||||
|
template<typename T> inline
|
||||||
|
void CrossProduct(const T x[3], const T y[3], T x_cross_y[3]);
|
||||||
|
|
||||||
|
template<typename T> inline
|
||||||
|
T DotProduct(const T x[3], const T y[3]);
|
||||||
|
|
||||||
|
// y = R(angle_axis) * x;
|
||||||
|
template<typename T> inline
|
||||||
|
void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]);
|
||||||
|
|
||||||
|
// --- IMPLEMENTATION
|
||||||
|
|
||||||
|
template<typename T, int row_stride, int col_stride>
|
||||||
|
struct MatrixAdapter {
|
||||||
|
T* pointer_;
|
||||||
|
explicit MatrixAdapter(T* pointer)
|
||||||
|
: pointer_(pointer)
|
||||||
|
{}
|
||||||
|
|
||||||
|
T& operator()(int r, int c) const {
|
||||||
|
return pointer_[r * row_stride + c * col_stride];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
MatrixAdapter<T, 1, 3> ColumnMajorAdapter3x3(T* pointer) {
|
||||||
|
return MatrixAdapter<T, 1, 3>(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
MatrixAdapter<T, 3, 1> RowMajorAdapter3x3(T* pointer) {
|
||||||
|
return MatrixAdapter<T, 3, 1>(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void AngleAxisToQuaternion(const T* angle_axis, T* quaternion) {
|
||||||
|
const T& a0 = angle_axis[0];
|
||||||
|
const T& a1 = angle_axis[1];
|
||||||
|
const T& a2 = angle_axis[2];
|
||||||
|
const T theta_squared = a0 * a0 + a1 * a1 + a2 * a2;
|
||||||
|
|
||||||
|
// For points not at the origin, the full conversion is numerically stable.
|
||||||
|
if (theta_squared > T(0.0)) {
|
||||||
|
const T theta = sqrt(theta_squared);
|
||||||
|
const T half_theta = theta * T(0.5);
|
||||||
|
const T k = sin(half_theta) / theta;
|
||||||
|
quaternion[0] = cos(half_theta);
|
||||||
|
quaternion[1] = a0 * k;
|
||||||
|
quaternion[2] = a1 * k;
|
||||||
|
quaternion[3] = a2 * k;
|
||||||
|
} else {
|
||||||
|
// At the origin, sqrt() will produce NaN in the derivative since
|
||||||
|
// the argument is zero. By approximating with a Taylor series,
|
||||||
|
// and truncating at one term, the value and first derivatives will be
|
||||||
|
// computed correctly when Jets are used.
|
||||||
|
const T k(0.5);
|
||||||
|
quaternion[0] = T(1.0);
|
||||||
|
quaternion[1] = a0 * k;
|
||||||
|
quaternion[2] = a1 * k;
|
||||||
|
quaternion[3] = a2 * k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void QuaternionToAngleAxis(const T* quaternion, T* angle_axis) {
|
||||||
|
const T& q1 = quaternion[1];
|
||||||
|
const T& q2 = quaternion[2];
|
||||||
|
const T& q3 = quaternion[3];
|
||||||
|
const T sin_squared_theta = q1 * q1 + q2 * q2 + q3 * q3;
|
||||||
|
|
||||||
|
// For quaternions representing non-zero rotation, the conversion
|
||||||
|
// is numerically stable.
|
||||||
|
if (sin_squared_theta > T(0.0)) {
|
||||||
|
const T sin_theta = sqrt(sin_squared_theta);
|
||||||
|
const T& cos_theta = quaternion[0];
|
||||||
|
|
||||||
|
// If cos_theta is negative, theta is greater than pi/2, which
|
||||||
|
// means that angle for the angle_axis vector which is 2 * theta
|
||||||
|
// would be greater than pi.
|
||||||
|
//
|
||||||
|
// While this will result in the correct rotation, it does not
|
||||||
|
// result in a normalized angle-axis vector.
|
||||||
|
//
|
||||||
|
// In that case we observe that 2 * theta ~ 2 * theta - 2 * pi,
|
||||||
|
// which is equivalent saying
|
||||||
|
//
|
||||||
|
// theta - pi = atan(sin(theta - pi), cos(theta - pi))
|
||||||
|
// = atan(-sin(theta), -cos(theta))
|
||||||
|
//
|
||||||
|
const T two_theta =
|
||||||
|
T(2.0) * ((cos_theta < 0.0)
|
||||||
|
? atan2(-sin_theta, -cos_theta)
|
||||||
|
: atan2(sin_theta, cos_theta));
|
||||||
|
const T k = two_theta / sin_theta;
|
||||||
|
angle_axis[0] = q1 * k;
|
||||||
|
angle_axis[1] = q2 * k;
|
||||||
|
angle_axis[2] = q3 * k;
|
||||||
|
} else {
|
||||||
|
// For zero rotation, sqrt() will produce NaN in the derivative since
|
||||||
|
// the argument is zero. By approximating with a Taylor series,
|
||||||
|
// and truncating at one term, the value and first derivatives will be
|
||||||
|
// computed correctly when Jets are used.
|
||||||
|
const T k(2.0);
|
||||||
|
angle_axis[0] = q1 * k;
|
||||||
|
angle_axis[1] = q2 * k;
|
||||||
|
angle_axis[2] = q3 * k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The conversion of a rotation matrix to the angle-axis form is
|
||||||
|
// numerically problematic when then rotation angle is close to zero
|
||||||
|
// or to Pi. The following implementation detects when these two cases
|
||||||
|
// occurs and deals with them by taking code paths that are guaranteed
|
||||||
|
// to not perform division by a small number.
|
||||||
|
template <typename T>
|
||||||
|
inline void RotationMatrixToAngleAxis(const T* R, T* angle_axis) {
|
||||||
|
RotationMatrixToAngleAxis(ColumnMajorAdapter3x3(R), angle_axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int row_stride, int col_stride>
|
||||||
|
void RotationMatrixToAngleAxis(
|
||||||
|
const MatrixAdapter<const T, row_stride, col_stride>& R,
|
||||||
|
T* angle_axis) {
|
||||||
|
// x = k * 2 * sin(theta), where k is the axis of rotation.
|
||||||
|
angle_axis[0] = R(2, 1) - R(1, 2);
|
||||||
|
angle_axis[1] = R(0, 2) - R(2, 0);
|
||||||
|
angle_axis[2] = R(1, 0) - R(0, 1);
|
||||||
|
|
||||||
|
static const T kOne = T(1.0);
|
||||||
|
static const T kTwo = T(2.0);
|
||||||
|
|
||||||
|
// Since the right hand side may give numbers just above 1.0 or
|
||||||
|
// below -1.0 leading to atan misbehaving, we threshold.
|
||||||
|
T costheta = std::min(std::max((R(0, 0) + R(1, 1) + R(2, 2) - kOne) / kTwo,
|
||||||
|
T(-1.0)),
|
||||||
|
kOne);
|
||||||
|
|
||||||
|
// sqrt is guaranteed to give non-negative results, so we only
|
||||||
|
// threshold above.
|
||||||
|
T sintheta = std::min(sqrt(angle_axis[0] * angle_axis[0] +
|
||||||
|
angle_axis[1] * angle_axis[1] +
|
||||||
|
angle_axis[2] * angle_axis[2]) / kTwo,
|
||||||
|
kOne);
|
||||||
|
|
||||||
|
// Use the arctan2 to get the right sign on theta
|
||||||
|
const T theta = atan2(sintheta, costheta);
|
||||||
|
|
||||||
|
// Case 1: sin(theta) is large enough, so dividing by it is not a
|
||||||
|
// problem. We do not use abs here, because while jets.h imports
|
||||||
|
// std::abs into the namespace, here in this file, abs resolves to
|
||||||
|
// the int version of the function, which returns zero always.
|
||||||
|
//
|
||||||
|
// We use a threshold much larger then the machine epsilon, because
|
||||||
|
// if sin(theta) is small, not only do we risk overflow but even if
|
||||||
|
// that does not occur, just dividing by a small number will result
|
||||||
|
// in numerical garbage. So we play it safe.
|
||||||
|
static const double kThreshold = 1e-12;
|
||||||
|
if ((sintheta > kThreshold) || (sintheta < -kThreshold)) {
|
||||||
|
const T r = theta / (kTwo * sintheta);
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
angle_axis[i] *= r;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case 2: theta ~ 0, means sin(theta) ~ theta to a good
|
||||||
|
// approximation.
|
||||||
|
if (costheta > 0.0) {
|
||||||
|
const T kHalf = T(0.5);
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
angle_axis[i] *= kHalf;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case 3: theta ~ pi, this is the hard case. Since theta is large,
|
||||||
|
// and sin(theta) is small. Dividing by theta by sin(theta) will
|
||||||
|
// either give an overflow or worse still numerically meaningless
|
||||||
|
// results. Thus we use an alternate more complicated formula
|
||||||
|
// here.
|
||||||
|
|
||||||
|
// Since cos(theta) is negative, division by (1-cos(theta)) cannot
|
||||||
|
// overflow.
|
||||||
|
const T inv_one_minus_costheta = kOne / (kOne - costheta);
|
||||||
|
|
||||||
|
// We now compute the absolute value of coordinates of the axis
|
||||||
|
// vector using the diagonal entries of R. To resolve the sign of
|
||||||
|
// these entries, we compare the sign of angle_axis[i]*sin(theta)
|
||||||
|
// with the sign of sin(theta). If they are the same, then
|
||||||
|
// angle_axis[i] should be positive, otherwise negative.
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
angle_axis[i] = theta * sqrt((R(i, i) - costheta) * inv_one_minus_costheta);
|
||||||
|
if (((sintheta < 0.0) && (angle_axis[i] > 0.0)) ||
|
||||||
|
((sintheta > 0.0) && (angle_axis[i] < 0.0))) {
|
||||||
|
angle_axis[i] = -angle_axis[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void AngleAxisToRotationMatrix(const T* angle_axis, T* R) {
|
||||||
|
AngleAxisToRotationMatrix(angle_axis, ColumnMajorAdapter3x3(R));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int row_stride, int col_stride>
|
||||||
|
void AngleAxisToRotationMatrix(
|
||||||
|
const T* angle_axis,
|
||||||
|
const MatrixAdapter<T, row_stride, col_stride>& R) {
|
||||||
|
static const T kOne = T(1.0);
|
||||||
|
const T theta2 = DotProduct(angle_axis, angle_axis);
|
||||||
|
if (theta2 > T(std::numeric_limits<double>::epsilon())) {
|
||||||
|
// We want to be careful to only evaluate the square root if the
|
||||||
|
// norm of the angle_axis vector is greater than zero. Otherwise
|
||||||
|
// we get a division by zero.
|
||||||
|
const T theta = sqrt(theta2);
|
||||||
|
const T wx = angle_axis[0] / theta;
|
||||||
|
const T wy = angle_axis[1] / theta;
|
||||||
|
const T wz = angle_axis[2] / theta;
|
||||||
|
|
||||||
|
const T costheta = cos(theta);
|
||||||
|
const T sintheta = sin(theta);
|
||||||
|
|
||||||
|
R(0, 0) = costheta + wx*wx*(kOne - costheta);
|
||||||
|
R(1, 0) = wz*sintheta + wx*wy*(kOne - costheta);
|
||||||
|
R(2, 0) = -wy*sintheta + wx*wz*(kOne - costheta);
|
||||||
|
R(0, 1) = wx*wy*(kOne - costheta) - wz*sintheta;
|
||||||
|
R(1, 1) = costheta + wy*wy*(kOne - costheta);
|
||||||
|
R(2, 1) = wx*sintheta + wy*wz*(kOne - costheta);
|
||||||
|
R(0, 2) = wy*sintheta + wx*wz*(kOne - costheta);
|
||||||
|
R(1, 2) = -wx*sintheta + wy*wz*(kOne - costheta);
|
||||||
|
R(2, 2) = costheta + wz*wz*(kOne - costheta);
|
||||||
|
} else {
|
||||||
|
// Near zero, we switch to using the first order Taylor expansion.
|
||||||
|
R(0, 0) = kOne;
|
||||||
|
R(1, 0) = angle_axis[2];
|
||||||
|
R(2, 0) = -angle_axis[1];
|
||||||
|
R(0, 1) = -angle_axis[2];
|
||||||
|
R(1, 1) = kOne;
|
||||||
|
R(2, 1) = angle_axis[0];
|
||||||
|
R(0, 2) = angle_axis[1];
|
||||||
|
R(1, 2) = -angle_axis[0];
|
||||||
|
R(2, 2) = kOne;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void EulerAnglesToRotationMatrix(const T* euler,
|
||||||
|
const int row_stride_parameter,
|
||||||
|
T* R) {
|
||||||
|
DCHECK(row_stride_parameter==3);
|
||||||
|
EulerAnglesToRotationMatrix(euler, RowMajorAdapter3x3(R));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int row_stride, int col_stride>
|
||||||
|
void EulerAnglesToRotationMatrix(
|
||||||
|
const T* euler,
|
||||||
|
const MatrixAdapter<T, row_stride, col_stride>& R) {
|
||||||
|
const double kPi = 3.14159265358979323846;
|
||||||
|
const T degrees_to_radians(kPi / 180.0);
|
||||||
|
|
||||||
|
const T pitch(euler[0] * degrees_to_radians);
|
||||||
|
const T roll(euler[1] * degrees_to_radians);
|
||||||
|
const T yaw(euler[2] * degrees_to_radians);
|
||||||
|
|
||||||
|
const T c1 = cos(yaw);
|
||||||
|
const T s1 = sin(yaw);
|
||||||
|
const T c2 = cos(roll);
|
||||||
|
const T s2 = sin(roll);
|
||||||
|
const T c3 = cos(pitch);
|
||||||
|
const T s3 = sin(pitch);
|
||||||
|
|
||||||
|
R(0, 0) = c1*c2;
|
||||||
|
R(0, 1) = -s1*c3 + c1*s2*s3;
|
||||||
|
R(0, 2) = s1*s3 + c1*s2*c3;
|
||||||
|
|
||||||
|
R(1, 0) = s1*c2;
|
||||||
|
R(1, 1) = c1*c3 + s1*s2*s3;
|
||||||
|
R(1, 2) = -c1*s3 + s1*s2*c3;
|
||||||
|
|
||||||
|
R(2, 0) = -s2;
|
||||||
|
R(2, 1) = c2*s3;
|
||||||
|
R(2, 2) = c2*c3;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline
|
||||||
|
void QuaternionToScaledRotation(const T q[4], T R[3 * 3]) {
|
||||||
|
QuaternionToScaledRotation(q, RowMajorAdapter3x3(R));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int row_stride, int col_stride> inline
|
||||||
|
void QuaternionToScaledRotation(
|
||||||
|
const T q[4],
|
||||||
|
const MatrixAdapter<T, row_stride, col_stride>& R) {
|
||||||
|
// Make convenient names for elements of q.
|
||||||
|
T a = q[0];
|
||||||
|
T b = q[1];
|
||||||
|
T c = q[2];
|
||||||
|
T d = q[3];
|
||||||
|
// This is not to eliminate common sub-expression, but to
|
||||||
|
// make the lines shorter so that they fit in 80 columns!
|
||||||
|
T aa = a * a;
|
||||||
|
T ab = a * b;
|
||||||
|
T ac = a * c;
|
||||||
|
T ad = a * d;
|
||||||
|
T bb = b * b;
|
||||||
|
T bc = b * c;
|
||||||
|
T bd = b * d;
|
||||||
|
T cc = c * c;
|
||||||
|
T cd = c * d;
|
||||||
|
T dd = d * d;
|
||||||
|
|
||||||
|
R(0, 0) = aa + bb - cc - dd; R(0, 1) = T(2) * (bc - ad); R(0, 2) = T(2) * (ac + bd); // NOLINT
|
||||||
|
R(1, 0) = T(2) * (ad + bc); R(1, 1) = aa - bb + cc - dd; R(1, 2) = T(2) * (cd - ab); // NOLINT
|
||||||
|
R(2, 0) = T(2) * (bd - ac); R(2, 1) = T(2) * (ab + cd); R(2, 2) = aa - bb - cc + dd; // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline
|
||||||
|
void QuaternionToRotation(const T q[4], T R[3 * 3]) {
|
||||||
|
QuaternionToRotation(q, RowMajorAdapter3x3(R));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int row_stride, int col_stride> inline
|
||||||
|
void QuaternionToRotation(const T q[4],
|
||||||
|
const MatrixAdapter<T, row_stride, col_stride>& R) {
|
||||||
|
QuaternionToScaledRotation(q, R);
|
||||||
|
|
||||||
|
T normalizer = q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3];
|
||||||
|
CHECK_NE(normalizer, T(0));
|
||||||
|
normalizer = T(1) / normalizer;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
for (int j = 0; j < 3; ++j) {
|
||||||
|
R(i, j) *= normalizer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline
|
||||||
|
void UnitQuaternionRotatePoint(const T q[4], const T pt[3], T result[3]) {
|
||||||
|
const T t2 = q[0] * q[1];
|
||||||
|
const T t3 = q[0] * q[2];
|
||||||
|
const T t4 = q[0] * q[3];
|
||||||
|
const T t5 = -q[1] * q[1];
|
||||||
|
const T t6 = q[1] * q[2];
|
||||||
|
const T t7 = q[1] * q[3];
|
||||||
|
const T t8 = -q[2] * q[2];
|
||||||
|
const T t9 = q[2] * q[3];
|
||||||
|
const T t1 = -q[3] * q[3];
|
||||||
|
result[0] = T(2) * ((t8 + t1) * pt[0] + (t6 - t4) * pt[1] + (t3 + t7) * pt[2]) + pt[0]; // NOLINT
|
||||||
|
result[1] = T(2) * ((t4 + t6) * pt[0] + (t5 + t1) * pt[1] + (t9 - t2) * pt[2]) + pt[1]; // NOLINT
|
||||||
|
result[2] = T(2) * ((t7 - t3) * pt[0] + (t2 + t9) * pt[1] + (t5 + t8) * pt[2]) + pt[2]; // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline
|
||||||
|
void QuaternionRotatePoint(const T q[4], const T pt[3], T result[3]) {
|
||||||
|
// 'scale' is 1 / norm(q).
|
||||||
|
const T scale = T(1) / sqrt(q[0] * q[0] +
|
||||||
|
q[1] * q[1] +
|
||||||
|
q[2] * q[2] +
|
||||||
|
q[3] * q[3]);
|
||||||
|
|
||||||
|
// Make unit-norm version of q.
|
||||||
|
const T unit[4] = {
|
||||||
|
scale * q[0],
|
||||||
|
scale * q[1],
|
||||||
|
scale * q[2],
|
||||||
|
scale * q[3],
|
||||||
|
};
|
||||||
|
|
||||||
|
UnitQuaternionRotatePoint(unit, pt, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> inline
|
||||||
|
void QuaternionProduct(const T z[4], const T w[4], T zw[4]) {
|
||||||
|
zw[0] = z[0] * w[0] - z[1] * w[1] - z[2] * w[2] - z[3] * w[3];
|
||||||
|
zw[1] = z[0] * w[1] + z[1] * w[0] + z[2] * w[3] - z[3] * w[2];
|
||||||
|
zw[2] = z[0] * w[2] - z[1] * w[3] + z[2] * w[0] + z[3] * w[1];
|
||||||
|
zw[3] = z[0] * w[3] + z[1] * w[2] - z[2] * w[1] + z[3] * w[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// xy = x cross y;
|
||||||
|
template<typename T> inline
|
||||||
|
void CrossProduct(const T x[3], const T y[3], T x_cross_y[3]) {
|
||||||
|
x_cross_y[0] = x[1] * y[2] - x[2] * y[1];
|
||||||
|
x_cross_y[1] = x[2] * y[0] - x[0] * y[2];
|
||||||
|
x_cross_y[2] = x[0] * y[1] - x[1] * y[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> inline
|
||||||
|
T DotProduct(const T x[3], const T y[3]) {
|
||||||
|
return (x[0] * y[0] + x[1] * y[1] + x[2] * y[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> inline
|
||||||
|
void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) {
|
||||||
|
const T theta2 = DotProduct(angle_axis, angle_axis);
|
||||||
|
if (theta2 > T(std::numeric_limits<double>::epsilon())) {
|
||||||
|
// Away from zero, use the rodriguez formula
|
||||||
|
//
|
||||||
|
// result = pt costheta +
|
||||||
|
// (w x pt) * sintheta +
|
||||||
|
// w (w . pt) (1 - costheta)
|
||||||
|
//
|
||||||
|
// We want to be careful to only evaluate the square root if the
|
||||||
|
// norm of the angle_axis vector is greater than zero. Otherwise
|
||||||
|
// we get a division by zero.
|
||||||
|
//
|
||||||
|
const T theta = sqrt(theta2);
|
||||||
|
const T costheta = cos(theta);
|
||||||
|
const T sintheta = sin(theta);
|
||||||
|
const T theta_inverse = 1.0 / theta;
|
||||||
|
|
||||||
|
const T w[3] = { angle_axis[0] * theta_inverse,
|
||||||
|
angle_axis[1] * theta_inverse,
|
||||||
|
angle_axis[2] * theta_inverse };
|
||||||
|
|
||||||
|
// Explicitly inlined evaluation of the cross product for
|
||||||
|
// performance reasons.
|
||||||
|
const T w_cross_pt[3] = { w[1] * pt[2] - w[2] * pt[1],
|
||||||
|
w[2] * pt[0] - w[0] * pt[2],
|
||||||
|
w[0] * pt[1] - w[1] * pt[0] };
|
||||||
|
const T tmp =
|
||||||
|
(w[0] * pt[0] + w[1] * pt[1] + w[2] * pt[2]) * (T(1.0) - costheta);
|
||||||
|
|
||||||
|
result[0] = pt[0] * costheta + w_cross_pt[0] * sintheta + w[0] * tmp;
|
||||||
|
result[1] = pt[1] * costheta + w_cross_pt[1] * sintheta + w[1] * tmp;
|
||||||
|
result[2] = pt[2] * costheta + w_cross_pt[2] * sintheta + w[2] * tmp;
|
||||||
|
} else {
|
||||||
|
// Near zero, the first order Taylor approximation of the rotation
|
||||||
|
// matrix R corresponding to a vector w and angle w is
|
||||||
|
//
|
||||||
|
// R = I + hat(w) * sin(theta)
|
||||||
|
//
|
||||||
|
// But sintheta ~ theta and theta * w = angle_axis, which gives us
|
||||||
|
//
|
||||||
|
// R = I + hat(w)
|
||||||
|
//
|
||||||
|
// and actually performing multiplication with the point pt, gives us
|
||||||
|
// R * pt = pt + w x pt.
|
||||||
|
//
|
||||||
|
// Switching to the Taylor expansion near zero provides meaningful
|
||||||
|
// derivatives when evaluated using Jets.
|
||||||
|
//
|
||||||
|
// Explicitly inlined evaluation of the cross product for
|
||||||
|
// performance reasons.
|
||||||
|
const T w_cross_pt[3] = { angle_axis[1] * pt[2] - angle_axis[2] * pt[1],
|
||||||
|
angle_axis[2] * pt[0] - angle_axis[0] * pt[2],
|
||||||
|
angle_axis[0] * pt[1] - angle_axis[1] * pt[0] };
|
||||||
|
|
||||||
|
result[0] = pt[0] + w_cross_pt[0];
|
||||||
|
result[1] = pt[1] + w_cross_pt[1];
|
||||||
|
result[2] = pt[2] + w_cross_pt[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ceres
|
||||||
|
|
||||||
|
#endif // CERES_PUBLIC_ROTATION_H_
|
|
@ -0,0 +1,181 @@
|
||||||
|
// Ceres Solver - A fast non-linear least squares minimizer
|
||||||
|
// Copyright 2013 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/ceres-solver/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: sameeragarwal@google.com (Sameer Agarwal)
|
||||||
|
// mierle@gmail.com (Keir Mierle)
|
||||||
|
|
||||||
|
#ifndef CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
|
||||||
|
#define CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <gtsam_unstable/nonlinear/ceres_jet.h>
|
||||||
|
#include <gtsam_unstable/nonlinear/ceres_eigen.h>
|
||||||
|
#include <gtsam_unstable/nonlinear/ceres_fixed_array.h>
|
||||||
|
|
||||||
|
namespace ceres {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// This block of quasi-repeated code calls the user-supplied functor, which may
|
||||||
|
// take a variable number of arguments. This is accomplished by specializing the
|
||||||
|
// struct based on the size of the trailing parameters; parameters with 0 size
|
||||||
|
// are assumed missing.
|
||||||
|
template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4,
|
||||||
|
int N5, int N6, int N7, int N8, int N9>
|
||||||
|
struct VariadicEvaluate {
|
||||||
|
static bool Call(const Functor& functor, T const *const *input, T* output) {
|
||||||
|
return functor(input[0],
|
||||||
|
input[1],
|
||||||
|
input[2],
|
||||||
|
input[3],
|
||||||
|
input[4],
|
||||||
|
input[5],
|
||||||
|
input[6],
|
||||||
|
input[7],
|
||||||
|
input[8],
|
||||||
|
input[9],
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4,
|
||||||
|
int N5, int N6, int N7, int N8>
|
||||||
|
struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, N5, N6, N7, N8, 0> {
|
||||||
|
static bool Call(const Functor& functor, T const *const *input, T* output) {
|
||||||
|
return functor(input[0],
|
||||||
|
input[1],
|
||||||
|
input[2],
|
||||||
|
input[3],
|
||||||
|
input[4],
|
||||||
|
input[5],
|
||||||
|
input[6],
|
||||||
|
input[7],
|
||||||
|
input[8],
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4,
|
||||||
|
int N5, int N6, int N7>
|
||||||
|
struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, N5, N6, N7, 0, 0> {
|
||||||
|
static bool Call(const Functor& functor, T const *const *input, T* output) {
|
||||||
|
return functor(input[0],
|
||||||
|
input[1],
|
||||||
|
input[2],
|
||||||
|
input[3],
|
||||||
|
input[4],
|
||||||
|
input[5],
|
||||||
|
input[6],
|
||||||
|
input[7],
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4,
|
||||||
|
int N5, int N6>
|
||||||
|
struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, N5, N6, 0, 0, 0> {
|
||||||
|
static bool Call(const Functor& functor, T const *const *input, T* output) {
|
||||||
|
return functor(input[0],
|
||||||
|
input[1],
|
||||||
|
input[2],
|
||||||
|
input[3],
|
||||||
|
input[4],
|
||||||
|
input[5],
|
||||||
|
input[6],
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4,
|
||||||
|
int N5>
|
||||||
|
struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, N5, 0, 0, 0, 0> {
|
||||||
|
static bool Call(const Functor& functor, T const *const *input, T* output) {
|
||||||
|
return functor(input[0],
|
||||||
|
input[1],
|
||||||
|
input[2],
|
||||||
|
input[3],
|
||||||
|
input[4],
|
||||||
|
input[5],
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4>
|
||||||
|
struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, 0, 0, 0, 0, 0> {
|
||||||
|
static bool Call(const Functor& functor, T const *const *input, T* output) {
|
||||||
|
return functor(input[0],
|
||||||
|
input[1],
|
||||||
|
input[2],
|
||||||
|
input[3],
|
||||||
|
input[4],
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Functor, typename T, int N0, int N1, int N2, int N3>
|
||||||
|
struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, 0, 0, 0, 0, 0, 0> {
|
||||||
|
static bool Call(const Functor& functor, T const *const *input, T* output) {
|
||||||
|
return functor(input[0],
|
||||||
|
input[1],
|
||||||
|
input[2],
|
||||||
|
input[3],
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Functor, typename T, int N0, int N1, int N2>
|
||||||
|
struct VariadicEvaluate<Functor, T, N0, N1, N2, 0, 0, 0, 0, 0, 0, 0> {
|
||||||
|
static bool Call(const Functor& functor, T const *const *input, T* output) {
|
||||||
|
return functor(input[0],
|
||||||
|
input[1],
|
||||||
|
input[2],
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Functor, typename T, int N0, int N1>
|
||||||
|
struct VariadicEvaluate<Functor, T, N0, N1, 0, 0, 0, 0, 0, 0, 0, 0> {
|
||||||
|
static bool Call(const Functor& functor, T const *const *input, T* output) {
|
||||||
|
return functor(input[0],
|
||||||
|
input[1],
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Functor, typename T, int N0>
|
||||||
|
struct VariadicEvaluate<Functor, T, N0, 0, 0, 0, 0, 0, 0, 0, 0, 0> {
|
||||||
|
static bool Call(const Functor& functor, T const *const *input, T* output) {
|
||||||
|
return functor(input[0],
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace ceres
|
||||||
|
|
||||||
|
#endif // CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
|
|
@ -25,8 +25,8 @@
|
||||||
#include <gtsam/base/Testable.h>
|
#include <gtsam/base/Testable.h>
|
||||||
#include <gtsam/base/LieScalar.h>
|
#include <gtsam/base/LieScalar.h>
|
||||||
|
|
||||||
#include "ceres/ceres.h"
|
#include <gtsam_unstable/nonlinear/ceres_autodiff.h>
|
||||||
#include "ceres/rotation.h"
|
#include <gtsam_unstable/nonlinear/ceres_rotation.h>
|
||||||
|
|
||||||
#undef CHECK
|
#undef CHECK
|
||||||
#include <CppUnitLite/TestHarness.h>
|
#include <CppUnitLite/TestHarness.h>
|
||||||
|
|
Loading…
Reference in New Issue