1. Refactor the python code that generates the template specializations
to remove code duplication.
2. Improved the logic for template specialization selection where
Eigen::Dynamic now serves as a wildcard.
3. Added schur_templates.h/cc which allows querying the set of available
template specializations without instantiating a linear solver.
4. Added Solver::Summary::schur_structre_given and
Solver::Summary::schur_structure_used and expose them in
Solver::Summary::FullReport for better performance debugging.
5. Updated the templates with newer dates and some minor comments cleanup
which lead to the the template specializations to be re-generated.
Change-Id: Iaf3c6f714353597899916c300465da01f151c3de
- ScalarBinaryOpTraits was introduced in Eigen 3.3, and thus breaks
compilation of Ceres for Eigen versions < 3.3.
- Reported as issue #252 by AustinDeric:
https://github.com/ceres-solver/ceres-solver/issues/252
Change-Id: Ie9b7dace17709c348b18b297f2d5306b054ce4b0
This commit extends the use of Jets with Eigen matrices and arrays
by enabling the use of binary operators (such as scalar addition,
multiplication, as well as matrix multiplication) when one Eigen
matrix/array is of type Jet and the other is a scalar type. This
should increase performance since Jet types have optimized
scalar-to-jet binary operations.
Change-Id: Ia756064845d845cefcf0abb16d366331d2824b52
Below fixes are required to compile Ceres as a dynamic library using
MSVC.
1. Added CERES_EXPORT to EigenQuaternionParameterization.
2. Removed CERES_EXPORT from CubicInterpolator and BicubicInterpolator.
EigenQuaternionParameterization has its source embedded in ceres.dll
whereas Cubic+BicubicInterpolators are defined in the header file and
therefore do not require __declspec(dllimport).
Change-Id: Idd1f387890c36aab51a1a4177ea7c06933b96f39
- MSVC deprecated the standard POSIX names for Bessel functions in
favour of underscore prefixed versions.
- Previously we were checking for the presence of the newer underscore
functions via a macro, which fails as the functions are not defined
as macros.
- Now we check via a check_cxx_source_compiles() if the newer underscore
prefixed versions exist when compiling on MSVC and use a new Ceres
configuration #define to switch on their presence in jet.h
Change-Id: I430880bde2981d12f4d03dbc94d903b9842e887e
ResidualBlock evaluation has logic to ensure that CostFunction
should always fill out the residual and jacobian arrays completely
by using a special value to pre-populate these arrays.
This works for CostFunctions with analytical Jacobians but not for
AutoDiffCostFunction and NumericDiffCostFunction Jacobians.
There is no way to fix this for NumericDiffCostFunctions without
introducing significant performance penalties but the residual
evaluation fails, which should be enough to catch such errors.
For AutoDiffCostFunction the way the Jets are default initialized
was sidestepping this check. So now, the Jet that is used to
capture the output residuals is now initialized with
kImpossibleValue, which will ensure that if the user forgets
to fill all output fields, it triggers an evaluation error.
This change required that ceres::internal::kImpossibleValue be moved
out of array_utils.h/cc to types.h.
Change-Id: I35bb0946cf0785a5d43c7b5459a2272848fb2a9b
- Eigen versions < 3.3 only supported SIMD instructions that required
16-byte alignment (SSE), whereas Eigen >= 3.3 also supports AVX
instructions which require 32+-byte alignment.
- Previously we only ever requested 16-byte alignment for Jets (if >=
C++11 was enabled) which resulted in Eigen assertions being triggered
on some compilers as reported as Issue #251:
https://github.com/ceres-solver/ceres-solver/issues/251.
- Now we use Eigen’s EIGEN_MAX_ALIGN_BYTES macro, defined in Eigen >=
3.3 to specify the byte alignment for Jets when C++11 is enabled for
Eigen >= 3.3. For Eigen versions < 3.3, we maintain the previous
behaviour of 16.
Change-Id: I749af7a70ae794e0c2a59301128db781e338422c
- alignas(0) should be ignored, however it results in a build error on
GCC, so instead default to the alignment of double in Jets if
we cannot align to 16-byte boundaries on the platform, but are
compiling with C++11.
Change-Id: I2e54c69516ea2e1447a8bdc138b2dd70050c6dad
- As per Andrew Hunter’s comments in the commit which added Jet
alignment when using C++11 here:
https://ceres-solver-review.googlesource.com/#/c/7100, there is wide
lattitude in the standard about what the maximum supported alignment
can be.
- Previously, we were forcing the alignment to 1, if the value of
alignof(std::max_align_t), which we use as a proxy for the maximum
supported alignment on the platform, was < 16.
- An alignment of 1 is not valid for Jets, as it would weaken the
natural alignment of the types within a Jet, which would typically be
4 (32-bit systems) or 8 (64-bit systems), thus resulting in a compiler
error.
- This was reported as issue 235 for Clang 3.8 on i386:
https://github.com/ceres-solver/ceres-solver/issues/235.
Change-Id: Ie39e5499c64f9231f29ebf4392992b5c9ce2e385
In the process also move some documentation from the file header to
just above the class declaration.
This change is in response to https://github.com/ceres-solver/ceres-solver/issues/233
Change-Id: I08cff1a94c57b67dd2bd8be4dba8c3fce46b68ab
Support for parameter tolerance was added to the line search
minimizer was added a while ago, and calling Solve on a
non-linear least squares problem supported it but for some reason
the GradientProblemSolver::Options struct was missing this
option even though the documentation suggested that it was present!
Thanks to Noah Snavely for reporting this bug.
Change-Id: I57cf4ab396bc822c19fa298529e113b89664a349
They were present as debugging checks but were causing problems
with the build on 32bit i386 due to numerical cancellation issues,
where x ~ -epsilon.
Removing these checks only changes the behaviour in Debug mode.
We are already handling such small negative numbers in production
if they occur. All that this change does is to remove the crash.
https://github.com/ceres-solver/ceres-solver/issues/212
Thanks to @NeroBurner and @debalance for reporting this.
Change-Id: I66480e86d4fa0a4b621204f2ff44cc3ff8d01c04
Solver::Options::numeric_derivative_relative_step_size to
Solver::Options::gradient_check_numeric_derivative_relative_step_size
Change-Id: Ib89ae3f87e588d4aba2a75361770d2cec26f07aa
1. Use AVX if EIGEN_VECTORIZE_AVX is defined.
2. Make the cost of division same as the cost of multiplication.
These are updates to the original numtraits update needed for eigen 3.3
that Shaheen Gandhi sent out.
Change-Id: Ic1e3ed7d05a659c7badc79a894679b2dd61c51b9
Change the Ceres gradient checking API to make is useful for
unit testing, clean up code duplication and fix interaction between
gradient checking and local parameterizations.
There were two gradient checking implementations, one being used
when using the check_gradients flag in the Solver, the other
being a standalone class. The standalone version was restricted
to cost functions with fixed parameter sizes at compile time, which
is being lifted here. This enables it to be used inside the
GradientCheckingCostFunction as well.
In addition, this installs new hooks in the Solver to ensure
that Solve will fail if any incorrect gradients are detected. This
way, you can set the check_gradient flags to true and detect
errors in an automated way, instead of just printing error information
to the log. The error log is now also returned in the Solver summary
instead of being printed directly. The user can then decide what to
do with it. The existing hooks for user callbacks are used for
this purpose to keep the internal API changes minimal and non-invasive.
The last and biggest change is the way the the interaction between
local parameterizations and the gradient checker works. Before,
local parameterizations would be ignored by the checker. However,
if a cost function does not compute its Jacobian along the null
space of the local parameterization, this wil not have any effect
on the solver, but would result in a gradient checker error.
With this change, the Jacobians are multiplied by the Jacobians
of the respective local parameterization and thus being compared
in the tangent space only.
The typical use case for this are quaternion parameters, where
a cost function will typically assume that the quaternion is
always normalized, skipping the correct computation of the Jacobian
along the normal to save computation cost.
Change-Id: I5e1bb97b8a899436cea25101efe5011b0bb13282
- Microsoft deprecated the POSIX Bessel functions: j[0,1,n]() in favour
of _j[0,1,n](), it appears since at least MSVC 2005:
https://msdn.microsoft.com/en-us/library/ms235384(v=vs.100).aspx.
- As this occurs in jet.h (templated public header), although Ceres
suppresses the warning when it itself is built (to suppress a warning
about the insecurity of using std::copy), it will crop up again in
client code (without this fix) unless it is explicitly suppressed
there also.
- Raised as Issue #190:
https://github.com/ceres-solver/ceres-solver/issues/190.
Change-Id: If7ac5dbb856748f9900be93ec0452a40c0b00524
1. Break up the monolithic loop in TrustRegionMinimizer::Minimize
into a number of more easily described and analyzed subfunctions.
2. Break out the logic for evaluating the quality of a Trust Region
step into its own object - TrustRegionStepEvaluator.
Change-Id: I08580ecac074cfd74c096cb8e4880cbda3d48296
Computing the covariance matrix for a number of parameter blocks
previously required adding all parameter blocks to the computation and
subsequently assembling the matrix by concatenating all the blocks.
This patch adds the computation of the covariance matrix for a vector
of parameter blocks. All covariance block pairs are added automatically
and the resulting covariance matrix is assembled in the order the
parameter blocks appear.
Change-Id: I3b70c63f16862adc23a1d7fb7a21dde4e68abe9a
I169b637a1e2a106956b536c41d6a514a266e7cc0 marked Jets (in C++11) as
aligned to 16 bytes, and enabled Eigen vectorization. However, to
implement this, we added Eigen includes to port.h.
Turns out this broke some other tricks Ceres uses (redefining Eigen
constants for better performance), so we don't want to do that. Move
most of the implementation to jet.h where it is safe.
Change-Id: I47c6fc4180db1ff674bc660723dd5a2b84254e0d
We currently don't align the infinitesimal part of a Jet to a 16-byte
boundary (and thus force Eigen to avoid using SSE ops)--as a member of a
larger struct, we couldn't guarantee Jets would be allocated on
appropriately-aligned boundaries. However, C++11 adds better support
for requesting alignment: we can use it to guarantee the members will be
properly aligned, and tell Eigen to vectorize.
There is a significant gotcha here: the standard gives wide latitude to
implementations as to which alignments they choose to support. If we
ask for 16 and the system only supports 8, we may have misaligned
Jets. So we test (using alignof(std::max_align_t)) that the current
system supports 16-byte aligned values; if not, we fall back to the
current solution.
Two other small notes:
- This is obviously gated on C++11 support, and
thus we put the logic in port.h and export some useful #defines.
- GCC 4.8.x has a
bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56019) that has
max_align_t in the wrong namespace. This will not be a problem with a
modern GCC, but add a small workaround since many systems still ship 4.8.
This results (on a x86 workstation) in a 60% speedup in Jacobian
evaluation on bin/simple_bundle_adjuster problem-16-22106-pre.txt.
Change-Id: I169b637a1e2a106956b536c41d6a514a266e7cc0
Accumulate the number of steps of the line search algorithm
and report it as part of Summary::FullReport.
Change-Id: I1de12784009a3e08f2a2c2aff5085d57a3c73828
1. Add answers to a number of FAQs.
2. Add a note to the documentation for NumericDiffCostFunction that
NumericDiffOptions needs to be documented and mentioned.
3. Update the docs for Solver::Options::numeric_derivative_relative_step_size
to indicate that this setting only applies to the gradient checker.
4. Remove deprecated constructors from NumericDiffCostFunction and
DynamicNumericDiffCostFunction.
Change-Id: If8fc011b2a5996dbc2c51268aa477550ed014a1c
This method numerically computes function derivatives in different
scales, extrapolating between intermediate results to conserve function
evaluations. Adaptive differentiation is essential to produce accurate
results for functions with noisy derivatives.
Full changelist:
-Created a new type of NumericDiffMethod (RIDDERS).
-Implemented EvaluateRiddersJacobianColumn in NumericDiff.
-Created unit tests with f(x) = x^2 + [random noise] and
f(x) = exp(x).
Change-Id: I2d6e924d7ff686650272f29a8c981351e6f72091
1. Push the boundary handling logic into the underlying array
object. This has two very significant impacts:
a. The interpolation code becomes extremely simple to write
and to test.
b. The user has more flexibility in implementing how out of bounds
values are handled. We provide one default implementation.
Change-Id: Ic2f6cf9257ce7110c62e492688e5a6c8be1e7df2
Often a parameter block is the Cartesian product of a number of
manifolds. For example, a rigid transformation SE(3) = SO(3) x R^3
In such cases, where you have the local parameterization
of the individual manifolds available,
ProductParameterization can be used to construct a local
parameterization of the cartesian product.
Change-Id: I4b5bcbd2407a38739c7725b129789db5c3d65a20
This adds a new wrapper class called DynamicCostFunctionToFunctor
that closes a gap in the current API: the existing
CostFunctionToFunctor can only be used with a SizedCostFunction, where
the number and sizes of all parameter vectors are known at compile-time.
The DynamicCostFunctionToFunctor allows you to wrap a generic
CostFunction into a templated functor which can then be used in a
DynamicAutoDiffCostFunction.
Also updates the existing CostFunctionToFunctor class to internally use
DynamicCostFunctionToFunctor.
Change-Id: I088adc3271c58d2519126c27037c3576965a36d6
Before this change, the default step size
for a function F(x) at x was
step_size = |x| * relative_step_size
if step_size was exactly zero, then to prevent
division by zero we would fall back to relative_step_size.
This however is not good enough, as values of x say 1e-64
would lead to step sizes ~ 1e-70 and dividing by such numbers
leads to inaccurate results. For even smaller numbers, like
1e-300, which I have observed can occur as the optimization
algorithm makes progress, this leads to NaNs.
The key change in this CL is to change the fallback mechanism
to be
step_size = max(|x| * relative_step_size, min_step_size)
where
min_step_size = sqrt(DBL_EPSILON)
This is the recommended minimum value for the step size
for double precision arithmetic on the interwebs.
This results in a small loss of precision in the transcendental
functions test, but that is unavoidable as we are not taking
sufficiently small steps anymore.
On the whole though this will improve the numerical performance
of the algorithm.
To validate this approach, one of the parameter values for the
EasyFunctorTest has been set to 1e-64, which causes the test
to start failing without the corrected fallback logic.
This change should also address some if not all of
https://github.com/ceres-solver/ceres-solver/issues/121
Change-Id: I4a9013ef358626c1ba7b8abad60b3904163d63f6