camenduru commited on
Commit
2b5a2b6
·
1 Parent(s): 559549f

ceres-solver and colmap

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +9 -0
  2. bin/colmap +3 -0
  3. cmake/Ceres/CeresConfig.cmake +340 -0
  4. cmake/Ceres/CeresConfigVersion.cmake +70 -0
  5. cmake/Ceres/CeresTargets-release.cmake +19 -0
  6. cmake/Ceres/CeresTargets.cmake +100 -0
  7. cmake/Ceres/FindCXSparse.cmake +240 -0
  8. cmake/Ceres/FindGlog.cmake +379 -0
  9. cmake/Ceres/FindMETIS.cmake +110 -0
  10. cmake/Ceres/FindSuiteSparse.cmake +488 -0
  11. include/ceres/autodiff_cost_function.h +228 -0
  12. include/ceres/autodiff_first_order_function.h +151 -0
  13. include/ceres/autodiff_local_parameterization.h +158 -0
  14. include/ceres/autodiff_manifold.h +259 -0
  15. include/ceres/c_api.h +148 -0
  16. include/ceres/ceres.h +74 -0
  17. include/ceres/conditioned_cost_function.h +101 -0
  18. include/ceres/context.h +58 -0
  19. include/ceres/cost_function.h +144 -0
  20. include/ceres/cost_function_to_functor.h +171 -0
  21. include/ceres/covariance.h +459 -0
  22. include/ceres/crs_matrix.h +87 -0
  23. include/ceres/cubic_interpolation.h +436 -0
  24. include/ceres/dynamic_autodiff_cost_function.h +274 -0
  25. include/ceres/dynamic_cost_function.h +57 -0
  26. include/ceres/dynamic_cost_function_to_functor.h +194 -0
  27. include/ceres/dynamic_numeric_diff_cost_function.h +164 -0
  28. include/ceres/evaluation_callback.h +80 -0
  29. include/ceres/first_order_function.h +54 -0
  30. include/ceres/gradient_checker.h +189 -0
  31. include/ceres/gradient_problem.h +185 -0
  32. include/ceres/gradient_problem_solver.h +357 -0
  33. include/ceres/internal/array_selector.h +97 -0
  34. include/ceres/internal/autodiff.h +365 -0
  35. include/ceres/internal/config.h +123 -0
  36. include/ceres/internal/disable_warnings.h +44 -0
  37. include/ceres/internal/eigen.h +75 -0
  38. include/ceres/internal/export.h +42 -0
  39. include/ceres/internal/fixed_array.h +467 -0
  40. include/ceres/internal/householder_vector.h +96 -0
  41. include/ceres/internal/integer_sequence_algorithm.h +291 -0
  42. include/ceres/internal/jet_traits.h +223 -0
  43. include/ceres/internal/line_parameterization.h +183 -0
  44. include/ceres/internal/memory.h +90 -0
  45. include/ceres/internal/numeric_diff.h +508 -0
  46. include/ceres/internal/parameter_dims.h +124 -0
  47. include/ceres/internal/port.h +88 -0
  48. include/ceres/internal/reenable_warnings.h +38 -0
  49. include/ceres/internal/sphere_manifold_functions.h +162 -0
  50. include/ceres/internal/variadic_evaluate.h +113 -0
.gitattributes CHANGED
@@ -32,3 +32,12 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
35
+ bin/colmap filter=lfs diff=lfs merge=lfs -text
36
+ lib/libceres.a filter=lfs diff=lfs merge=lfs -text
37
+ lib/colmap/libcolmap_cuda.a filter=lfs diff=lfs merge=lfs -text
38
+ lib/colmap/libflann.a filter=lfs diff=lfs merge=lfs -text
39
+ lib/colmap/libpoisson_recon.a filter=lfs diff=lfs merge=lfs -text
40
+ lib/colmap/libcolmap.a filter=lfs diff=lfs merge=lfs -text
41
+ lib/colmap/libpba.a filter=lfs diff=lfs merge=lfs -text
42
+ lib/colmap/libsqlite3.a filter=lfs diff=lfs merge=lfs -text
43
+ lib/colmap/libsift_gpu.a filter=lfs diff=lfs merge=lfs -text
bin/colmap ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5256130472c6f6e7e82c04b2bcd08ca11628cc8da83f65e011f5a5c3ff260796
3
+ size 30940856
cmake/Ceres/CeresConfig.cmake ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ceres Solver - A fast non-linear least squares minimizer
2
+ # Copyright 2015 Google Inc. All rights reserved.
3
+ # http://ceres-solver.org/
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of Google Inc. nor the names of its contributors may be
14
+ # used to endorse or promote products derived from this software without
15
+ # specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ #
29
+ # Authors: pablo.speciale@gmail.com (Pablo Speciale)
30
+ # alexs.mac@gmail.com (Alex Stewart)
31
+ #
32
+
33
+ # Config file for Ceres Solver - Find Ceres & dependencies.
34
+ #
35
+ # This file is used by CMake when find_package(Ceres) is invoked and either
36
+ # the directory containing this file either is present in CMAKE_MODULE_PATH
37
+ # (if Ceres was installed), or exists in the local CMake package registry if
38
+ # the Ceres build directory was exported.
39
+ #
40
+ # This module defines the following variables:
41
+ #
42
+ # Ceres_FOUND / CERES_FOUND: True if Ceres has been successfully
43
+ # found. Both variables are set as although
44
+ # FindPackage() only references Ceres_FOUND
45
+ # in Config mode, given the conventions for
46
+ # <package>_FOUND when FindPackage() is
47
+ # called in Module mode, users could
48
+ # reasonably expect to use CERES_FOUND
49
+ # instead.
50
+ #
51
+ # CERES_VERSION: Version of Ceres found.
52
+ #
53
+ # CERES_LIBRARIES: Libraries for Ceres and all
54
+ # dependencies against which Ceres was
55
+ # compiled. This will not include any optional
56
+ # dependencies that were disabled when Ceres was
57
+ # compiled.
58
+ #
59
+ # NOTE: There is no equivalent of CERES_INCLUDE_DIRS as the exported
60
+ # CMake target already includes the definition of its public
61
+ # include directories.
62
+
63
+ include(CMakeFindDependencyMacro)
64
+
65
+ # Called if we failed to find Ceres or any of its required dependencies,
66
+ # unsets all public (designed to be used externally) variables and reports
67
+ # error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
68
+ macro(CERES_REPORT_NOT_FOUND REASON_MSG)
69
+ # FindPackage() only references Ceres_FOUND, and requires it to be
70
+ # explicitly set FALSE to denote not found (not merely undefined).
71
+ set(Ceres_FOUND FALSE)
72
+ set(CERES_FOUND FALSE)
73
+ unset(CERES_INCLUDE_DIR)
74
+ unset(CERES_INCLUDE_DIRS)
75
+ unset(CERES_LIBRARIES)
76
+
77
+ # Reset the CMake module path to its state when this script was called.
78
+ set(CMAKE_MODULE_PATH ${CALLERS_CMAKE_MODULE_PATH})
79
+
80
+ # Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by
81
+ # FindPackage() use the camelcase library name, not uppercase.
82
+ if (Ceres_FIND_QUIETLY)
83
+ message(STATUS "Failed to find Ceres - " ${REASON_MSG} ${ARGN})
84
+ elseif (Ceres_FIND_REQUIRED)
85
+ message(FATAL_ERROR "Failed to find Ceres - " ${REASON_MSG} ${ARGN})
86
+ else()
87
+ # Neither QUIETLY nor REQUIRED, use SEND_ERROR which emits an error
88
+ # that prevents generation, but continues configuration.
89
+ message(SEND_ERROR "Failed to find Ceres - " ${REASON_MSG} ${ARGN})
90
+ endif ()
91
+ return()
92
+ endmacro(CERES_REPORT_NOT_FOUND)
93
+
94
+
95
+ # ceres_message([mode] "message text")
96
+ #
97
+ # Wraps the standard cmake 'message' command, but suppresses output
98
+ # if the QUIET flag was passed to the find_package(Ceres ...) call.
99
+ function(ceres_message)
100
+ if (NOT Ceres_FIND_QUIETLY)
101
+ message(${ARGN})
102
+ endif()
103
+ endfunction()
104
+
105
+
106
+ # ceres_pretty_print_cmake_list( OUTPUT_VAR [item1 [item2 ... ]] )
107
+ #
108
+ # Sets ${OUTPUT_VAR} in the caller's scope to a human-readable string
109
+ # representation of the list passed as the remaining arguments formed
110
+ # as: "[item1, item2, ..., itemN]".
111
+ function(ceres_pretty_print_cmake_list OUTPUT_VAR)
112
+ string(REPLACE ";" ", " PRETTY_LIST_STRING "[${ARGN}]")
113
+ set(${OUTPUT_VAR} "${PRETTY_LIST_STRING}" PARENT_SCOPE)
114
+ endfunction()
115
+
116
+ # The list of (optional) components this version of Ceres was compiled with.
117
+ set(CERES_COMPILED_COMPONENTS "EigenSparse;SparseLinearAlgebraLibrary;LAPACK;SuiteSparse;CXSparse;SchurSpecializations;Multithreading")
118
+
119
+ # If Ceres was not installed, then by definition it was exported
120
+ # from a build directory.
121
+ set(CERES_WAS_INSTALLED TRUE)
122
+
123
+ # Record the state of the CMake module path when this script was
124
+ # called so that we can ensure that we leave it in the same state on
125
+ # exit as it was on entry, but modify it locally.
126
+ set(CALLERS_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH})
127
+
128
+ # Get the (current, i.e. installed) directory containing this file.
129
+ get_filename_component(CERES_CURRENT_CONFIG_DIR
130
+ "${CMAKE_CURRENT_LIST_FILE}" PATH)
131
+
132
+ if (CERES_WAS_INSTALLED)
133
+ # Reset CMake module path to the installation directory of this
134
+ # script, thus we will use the FindPackage() scripts shipped with
135
+ # Ceres to find Ceres' dependencies, even if the user has equivalently
136
+ # named FindPackage() scripts in their project.
137
+ set(CMAKE_MODULE_PATH ${CERES_CURRENT_CONFIG_DIR})
138
+
139
+ # Build the absolute root install directory as a relative path
140
+ # (determined when Ceres was configured & built) from the current
141
+ # install directory for this this file. This allows for the install
142
+ # tree to be relocated, after Ceres was built, outside of CMake.
143
+ get_filename_component(CURRENT_ROOT_INSTALL_DIR
144
+ "${CERES_CURRENT_CONFIG_DIR}/../../../"
145
+ ABSOLUTE)
146
+ if (NOT EXISTS ${CURRENT_ROOT_INSTALL_DIR})
147
+ ceres_report_not_found(
148
+ "Ceres install root: ${CURRENT_ROOT_INSTALL_DIR}, "
149
+ "determined from relative path from CeresConfig.cmake install location: "
150
+ "${CERES_CURRENT_CONFIG_DIR}, does not exist. Either the install "
151
+ "directory was deleted, or the install tree was only partially relocated "
152
+ "outside of CMake after Ceres was built.")
153
+ endif (NOT EXISTS ${CURRENT_ROOT_INSTALL_DIR})
154
+
155
+ else(CERES_WAS_INSTALLED)
156
+ # Ceres was exported from the build tree.
157
+ set(CERES_EXPORTED_BUILD_DIR ${CERES_CURRENT_CONFIG_DIR})
158
+ get_filename_component(CERES_EXPORTED_SOURCE_DIR
159
+ "${CERES_EXPORTED_BUILD_DIR}/../../../"
160
+ ABSOLUTE)
161
+ if (NOT EXISTS ${CERES_EXPORTED_SOURCE_DIR})
162
+ ceres_report_not_found(
163
+ "Ceres exported source directory: ${CERES_EXPORTED_SOURCE_DIR}, "
164
+ "determined from relative path from CeresConfig.cmake exported build "
165
+ "directory: ${CERES_EXPORTED_BUILD_DIR} does not exist.")
166
+ endif()
167
+
168
+ # Reset CMake module path to the cmake directory in the Ceres source
169
+ # tree which was exported, thus we will use the FindPackage() scripts shipped
170
+ # with Ceres to find Ceres' dependencies, even if the user has equivalently
171
+ # named FindPackage() scripts in their project.
172
+ set(CMAKE_MODULE_PATH ${CERES_EXPORTED_SOURCE_DIR}/cmake)
173
+ endif(CERES_WAS_INSTALLED)
174
+
175
+ # Set the version.
176
+ set(CERES_VERSION 2.1.0)
177
+
178
+ include(CMakeFindDependencyMacro)
179
+ find_dependency(Threads)
180
+
181
+ # Optional dependencies
182
+ find_dependency(CXSparse 3.1.9)
183
+ find_dependency(SuiteSparse 5.1.2)
184
+
185
+ # As imported CMake targets are not re-exported when a dependent target is
186
+ # exported, we must invoke find_package(XXX) here to reload the definition
187
+ # of their targets. Without this, the dependency target names (e.g.
188
+ # 'gflags-shared') which will be present in the ceres target would not be
189
+ # defined, and so CMake will assume that they refer to a library name and
190
+ # fail to link correctly.
191
+
192
+ # Eigen.
193
+ # Flag set during configuration and build of Ceres.
194
+ set(CERES_EIGEN_VERSION 3.3.4)
195
+ # Search quietly to control the timing of the error message if not found. The
196
+ # search should be for an exact match, but for usability reasons do a soft
197
+ # match and reject with an explanation below.
198
+ find_package(Eigen3 ${CERES_EIGEN_VERSION} QUIET)
199
+ if (Eigen3_FOUND)
200
+ if (NOT Eigen3_VERSION VERSION_EQUAL CERES_EIGEN_VERSION)
201
+ # CMake's VERSION check in FIND_PACKAGE() will accept any version >= the
202
+ # specified version. However, only version = is supported. Improve
203
+ # usability by explaining why we don't accept non-exact version matching.
204
+ ceres_report_not_found("Found Eigen dependency, but the version of Eigen "
205
+ "found (${Eigen3_VERSION}) does not exactly match the version of Eigen "
206
+ "Ceres was compiled with (${CERES_EIGEN_VERSION}). This can cause subtle "
207
+ "bugs by triggering violations of the One Definition Rule. See the "
208
+ "Wikipedia article http://en.wikipedia.org/wiki/One_Definition_Rule "
209
+ "for more details")
210
+ endif ()
211
+ ceres_message(STATUS "Found required Ceres dependency: "
212
+ "Eigen version ${CERES_EIGEN_VERSION} in ${Eigen3_DIR}")
213
+ else (Eigen3_FOUND)
214
+ ceres_report_not_found("Missing required Ceres "
215
+ "dependency: Eigen version ${CERES_EIGEN_VERSION}, please set "
216
+ "Eigen3_DIR.")
217
+ endif (Eigen3_FOUND)
218
+
219
+ # glog (and maybe gflags).
220
+ #
221
+ # Flags set during configuration and build of Ceres.
222
+ set(CERES_USES_MINIGLOG OFF)
223
+ set(CERES_GLOG_VERSION )
224
+ set(CERES_GLOG_WAS_BUILT_WITH_CMAKE 0)
225
+
226
+ set(CERES_USES_GFLAGS ON)
227
+ set(CERES_GFLAGS_VERSION 2.2.1)
228
+
229
+ if (CERES_USES_MINIGLOG)
230
+ # Output message at standard log level (not the lower STATUS) so that
231
+ # the message is output in GUI during configuration to warn user.
232
+ ceres_message("-- Found Ceres compiled with miniglog substitute "
233
+ "for glog, beware this will likely cause problems if glog is later linked.")
234
+ else(CERES_USES_MINIGLOG)
235
+ if (CERES_GLOG_WAS_BUILT_WITH_CMAKE)
236
+ find_package(glog ${CERES_GLOG_VERSION} CONFIG QUIET)
237
+ set(GLOG_FOUND ${glog_FOUND})
238
+ else()
239
+ # Version of glog against which Ceres was built was not built with CMake,
240
+ # use the exported glog find_package() module from Ceres to find it again.
241
+ # Append the locations of glog when Ceres was built to the search path hints.
242
+ list(APPEND GLOG_INCLUDE_DIR_HINTS "/usr/include")
243
+ get_filename_component(CERES_BUILD_GLOG_LIBRARY_DIR "/usr/lib/x86_64-linux-gnu/libglog.so" PATH)
244
+ list(APPEND GLOG_LIBRARY_DIR_HINTS ${CERES_BUILD_GLOG_LIBRARY_DIR})
245
+
246
+ # Search quietly s/t we control the timing of the error message if not found.
247
+ find_package(Glog QUIET)
248
+ endif()
249
+
250
+ if (GLOG_FOUND)
251
+ ceres_message(STATUS "Found required Ceres dependency: glog")
252
+ else()
253
+ ceres_report_not_found("Missing required Ceres dependency: glog.")
254
+ endif()
255
+
256
+ # gflags is only a public dependency of Ceres via glog, thus is not required
257
+ # if Ceres was built with MINIGLOG.
258
+ if (CERES_USES_GFLAGS)
259
+ # Search quietly s/t we control the timing of the error message if not found.
260
+ find_package(gflags ${CERES_GFLAGS_VERSION} QUIET)
261
+ if (gflags_FOUND AND TARGET gflags)
262
+ ceres_message(STATUS "Found required Ceres dependency: gflags")
263
+ else()
264
+ ceres_report_not_found("Missing required Ceres "
265
+ "dependency: gflags (not found, or not found as exported CMake target).")
266
+ endif()
267
+ endif()
268
+ endif(CERES_USES_MINIGLOG)
269
+
270
+ # Import exported Ceres targets, if they have not already been imported.
271
+ if (NOT TARGET ceres AND NOT Ceres_BINARY_DIR)
272
+ include(${CERES_CURRENT_CONFIG_DIR}/CeresTargets.cmake)
273
+ endif (NOT TARGET ceres AND NOT Ceres_BINARY_DIR)
274
+ # Set the expected XX_LIBRARIES variable for FindPackage().
275
+ set(CERES_LIBRARIES Ceres::ceres)
276
+
277
+ # Reset CMake module path to its state when this script was called.
278
+ set(CMAKE_MODULE_PATH ${CALLERS_CMAKE_MODULE_PATH})
279
+
280
+ # Build the detected Ceres version string to correctly capture whether it
281
+ # was installed, or exported.
282
+ ceres_pretty_print_cmake_list(CERES_COMPILED_COMPONENTS_STRING
283
+ ${CERES_COMPILED_COMPONENTS})
284
+ if (CERES_WAS_INSTALLED)
285
+ set(CERES_DETECTED_VERSION_STRING "Ceres version: ${CERES_VERSION} "
286
+ "installed in: ${CURRENT_ROOT_INSTALL_DIR} with components: "
287
+ "${CERES_COMPILED_COMPONENTS_STRING}")
288
+ else (CERES_WAS_INSTALLED)
289
+ set(CERES_DETECTED_VERSION_STRING "Ceres version: ${CERES_VERSION} "
290
+ "exported from build directory: ${CERES_EXPORTED_BUILD_DIR} with "
291
+ "components: ${CERES_COMPILED_COMPONENTS_STRING}")
292
+ endif()
293
+
294
+ # If the user called this script through find_package() whilst specifying
295
+ # particular Ceres components that should be found via:
296
+ # find_package(Ceres COMPONENTS XXX YYY), check the requested components against
297
+ # those with which Ceres was compiled. In this case, we should only report
298
+ # Ceres as found if all the requested components have been found.
299
+ if (Ceres_FIND_COMPONENTS)
300
+ foreach (REQUESTED_COMPONENT ${Ceres_FIND_COMPONENTS})
301
+ list(FIND CERES_COMPILED_COMPONENTS ${REQUESTED_COMPONENT} HAVE_REQUESTED_COMPONENT)
302
+ # list(FIND ..) returns -1 if the element was not in the list, but CMake
303
+ # interprets if (VAR) to be true if VAR is any non-zero number, even
304
+ # negative ones, hence we have to explicitly check for >= 0.
305
+ if (HAVE_REQUESTED_COMPONENT EQUAL -1)
306
+ # Check for the presence of all requested components before reporting
307
+ # not found, such that we report all of the missing components rather
308
+ # than just the first.
309
+ list(APPEND MISSING_CERES_COMPONENTS ${REQUESTED_COMPONENT})
310
+ endif()
311
+ endforeach()
312
+ if (MISSING_CERES_COMPONENTS)
313
+ ceres_pretty_print_cmake_list(REQUESTED_CERES_COMPONENTS_STRING
314
+ ${Ceres_FIND_COMPONENTS})
315
+ ceres_pretty_print_cmake_list(MISSING_CERES_COMPONENTS_STRING
316
+ ${MISSING_CERES_COMPONENTS})
317
+ ceres_report_not_found("Missing requested Ceres components: "
318
+ "${MISSING_CERES_COMPONENTS_STRING} (components requested: "
319
+ "${REQUESTED_CERES_COMPONENTS_STRING}). Detected "
320
+ "${CERES_DETECTED_VERSION_STRING}.")
321
+ endif()
322
+ endif()
323
+
324
+ # As we use CERES_REPORT_NOT_FOUND() to abort, if we reach this point we have
325
+ # found Ceres and all required dependencies.
326
+ ceres_message(STATUS "Found " ${CERES_DETECTED_VERSION_STRING})
327
+
328
+ # Set CERES_FOUND to be equivalent to Ceres_FOUND, which is set to
329
+ # TRUE by FindPackage() if this file is found and run, and after which
330
+ # Ceres_FOUND is not (explicitly, i.e. undefined does not count) set
331
+ # to FALSE.
332
+ set(CERES_FOUND TRUE)
333
+
334
+ if (NOT TARGET ceres)
335
+ # For backwards compatibility, create a local 'alias' target with the
336
+ # non-namespace-qualified Ceres target name. Note that this is not a
337
+ # true ALIAS library in CMake terms as they cannot point to imported targets.
338
+ add_library(ceres INTERFACE IMPORTED)
339
+ set_target_properties(ceres PROPERTIES INTERFACE_LINK_LIBRARIES Ceres::ceres)
340
+ endif()
cmake/Ceres/CeresConfigVersion.cmake ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This is a basic version file for the Config-mode of find_package().
2
+ # It is used by write_basic_package_version_file() as input file for configure_file()
3
+ # to create a version-file which can be installed along a config.cmake file.
4
+ #
5
+ # The created file sets PACKAGE_VERSION_EXACT if the current version string and
6
+ # the requested version string are exactly the same and it sets
7
+ # PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version,
8
+ # but only if the requested major version is the same as the current one.
9
+ # The variable CVF_VERSION must be set before calling configure_file().
10
+
11
+
12
+ set(PACKAGE_VERSION "2.1.0")
13
+
14
+ if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
15
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
16
+ else()
17
+
18
+ if("2.1.0" MATCHES "^([0-9]+)\\.")
19
+ set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
20
+ if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0)
21
+ string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}")
22
+ endif()
23
+ else()
24
+ set(CVF_VERSION_MAJOR "2.1.0")
25
+ endif()
26
+
27
+ if(PACKAGE_FIND_VERSION_RANGE)
28
+ # both endpoints of the range must have the expected major version
29
+ math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1")
30
+ if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR
31
+ OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR)
32
+ OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT)))
33
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
34
+ elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR
35
+ AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX)
36
+ OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX)))
37
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
38
+ else()
39
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
40
+ endif()
41
+ else()
42
+ if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR)
43
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
44
+ else()
45
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
46
+ endif()
47
+
48
+ if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
49
+ set(PACKAGE_VERSION_EXACT TRUE)
50
+ endif()
51
+ endif()
52
+ endif()
53
+
54
+
55
+ # if the installed project requested no architecture check, don't perform the check
56
+ if("FALSE")
57
+ return()
58
+ endif()
59
+
60
+ # if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
61
+ if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "")
62
+ return()
63
+ endif()
64
+
65
+ # check that the installed version has the same 32/64bit-ness as the one which is currently searching:
66
+ if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8")
67
+ math(EXPR installedBits "8 * 8")
68
+ set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
69
+ set(PACKAGE_VERSION_UNSUITABLE TRUE)
70
+ endif()
cmake/Ceres/CeresTargets-release.cmake ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #----------------------------------------------------------------
2
+ # Generated CMake target import file for configuration "Release".
3
+ #----------------------------------------------------------------
4
+
5
+ # Commands may need to know the format version.
6
+ set(CMAKE_IMPORT_FILE_VERSION 1)
7
+
8
+ # Import target "Ceres::ceres" for configuration "Release"
9
+ set_property(TARGET Ceres::ceres APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
10
+ set_target_properties(Ceres::ceres PROPERTIES
11
+ IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
12
+ IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libceres.a"
13
+ )
14
+
15
+ list(APPEND _IMPORT_CHECK_TARGETS Ceres::ceres )
16
+ list(APPEND _IMPORT_CHECK_FILES_FOR_Ceres::ceres "${_IMPORT_PREFIX}/lib/libceres.a" )
17
+
18
+ # Commands beyond this point should not need to know the version.
19
+ set(CMAKE_IMPORT_FILE_VERSION)
cmake/Ceres/CeresTargets.cmake ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by CMake
2
+
3
+ if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6)
4
+ message(FATAL_ERROR "CMake >= 2.6.0 required")
5
+ endif()
6
+ cmake_policy(PUSH)
7
+ cmake_policy(VERSION 2.6...3.20)
8
+ #----------------------------------------------------------------
9
+ # Generated CMake target import file.
10
+ #----------------------------------------------------------------
11
+
12
+ # Commands may need to know the format version.
13
+ set(CMAKE_IMPORT_FILE_VERSION 1)
14
+
15
+ # Protect against multiple inclusion, which would fail when already imported targets are added once more.
16
+ set(_targetsDefined)
17
+ set(_targetsNotDefined)
18
+ set(_expectedTargets)
19
+ foreach(_expectedTarget Ceres::ceres)
20
+ list(APPEND _expectedTargets ${_expectedTarget})
21
+ if(NOT TARGET ${_expectedTarget})
22
+ list(APPEND _targetsNotDefined ${_expectedTarget})
23
+ endif()
24
+ if(TARGET ${_expectedTarget})
25
+ list(APPEND _targetsDefined ${_expectedTarget})
26
+ endif()
27
+ endforeach()
28
+ if("${_targetsDefined}" STREQUAL "${_expectedTargets}")
29
+ unset(_targetsDefined)
30
+ unset(_targetsNotDefined)
31
+ unset(_expectedTargets)
32
+ set(CMAKE_IMPORT_FILE_VERSION)
33
+ cmake_policy(POP)
34
+ return()
35
+ endif()
36
+ if(NOT "${_targetsDefined}" STREQUAL "")
37
+ message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n")
38
+ endif()
39
+ unset(_targetsDefined)
40
+ unset(_targetsNotDefined)
41
+ unset(_expectedTargets)
42
+
43
+
44
+ # Compute the installation prefix relative to this file.
45
+ get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
46
+ get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
47
+ get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
48
+ get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
49
+ if(_IMPORT_PREFIX STREQUAL "/")
50
+ set(_IMPORT_PREFIX "")
51
+ endif()
52
+
53
+ # Create imported target Ceres::ceres
54
+ add_library(Ceres::ceres STATIC IMPORTED)
55
+
56
+ set_target_properties(Ceres::ceres PROPERTIES
57
+ INTERFACE_COMPILE_FEATURES "cxx_std_14"
58
+ INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;/usr/include"
59
+ INTERFACE_LINK_LIBRARIES "Threads::Threads;/usr/lib/x86_64-linux-gnu/libglog.so;gflags;\$<LINK_ONLY:SuiteSparse::CHOLMOD>;\$<LINK_ONLY:SuiteSparse::SPQR>;\$<LINK_ONLY:CXSparse::CXSparse>;/usr/local/cuda/lib64/libcudart_static.a;\$<LINK_ONLY:Threads::Threads>;\$<LINK_ONLY:dl>;/usr/lib/x86_64-linux-gnu/librt.so;/usr/local/cuda/lib64/libcublas.so;/usr/local/cuda/lib64/libcusolver.so;/usr/local/cuda/lib64/libcusparse.so;/usr/local/lib/libmkl_intel_lp64.so;/usr/local/lib/libmkl_intel_thread.so;/usr/local/lib/libmkl_core.so;/usr/local/lib/libiomp5.so;\$<LINK_ONLY:-lpthread>;\$<LINK_ONLY:-lm>;\$<LINK_ONLY:-ldl>;\$<LINK_ONLY:-lpthread>;\$<LINK_ONLY:-lm>;\$<LINK_ONLY:-ldl>;Eigen3::Eigen"
60
+ )
61
+
62
+ if(CMAKE_VERSION VERSION_LESS 2.8.12)
63
+ message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.")
64
+ endif()
65
+
66
+ # Load information for each installed configuration.
67
+ get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
68
+ file(GLOB CONFIG_FILES "${_DIR}/CeresTargets-*.cmake")
69
+ foreach(f ${CONFIG_FILES})
70
+ include(${f})
71
+ endforeach()
72
+
73
+ # Cleanup temporary variables.
74
+ set(_IMPORT_PREFIX)
75
+
76
+ # Loop over all imported files and verify that they actually exist
77
+ foreach(target ${_IMPORT_CHECK_TARGETS} )
78
+ foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )
79
+ if(NOT EXISTS "${file}" )
80
+ message(FATAL_ERROR "The imported target \"${target}\" references the file
81
+ \"${file}\"
82
+ but this file does not exist. Possible reasons include:
83
+ * The file was deleted, renamed, or moved to another location.
84
+ * An install or uninstall procedure did not complete successfully.
85
+ * The installation package was faulty and contained
86
+ \"${CMAKE_CURRENT_LIST_FILE}\"
87
+ but not all the files it references.
88
+ ")
89
+ endif()
90
+ endforeach()
91
+ unset(_IMPORT_CHECK_FILES_FOR_${target})
92
+ endforeach()
93
+ unset(_IMPORT_CHECK_TARGETS)
94
+
95
+ # This file does not depend on other imported targets which have
96
+ # been exported from the same project but in a separate export set.
97
+
98
+ # Commands beyond this point should not need to know the version.
99
+ set(CMAKE_IMPORT_FILE_VERSION)
100
+ cmake_policy(POP)
cmake/Ceres/FindCXSparse.cmake ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ceres Solver - A fast non-linear least squares minimizer
2
+ # Copyright 2022 Google Inc. All rights reserved.
3
+ # http://ceres-solver.org/
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of Google Inc. nor the names of its contributors may be
14
+ # used to endorse or promote products derived from this software without
15
+ # specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ #
29
+ # Author: alexs.mac@gmail.com (Alex Stewart)
30
+ #
31
+
32
+ #[=======================================================================[.rst:
33
+ FindCXSparse
34
+ ============
35
+
36
+ Find CXSparse and its dependencies.
37
+
38
+ This module defines the following variables which should be referenced by the
39
+ caller to use the library.
40
+
41
+ ``CXSparse_FOUND``
42
+ ``TRUE`` iff CXSparse and all dependencies have been found.
43
+
44
+ ``CXSparse_VERSION``
45
+ Extracted from ``cs.h``.
46
+
47
+ ``CXSparse_VERSION_MAJOR``
48
+ Equal to 3 if ``CXSparse_VERSION`` = 3.1.2
49
+
50
+ ``CXSparse_VERSION_MINOR``
51
+ Equal to 1 if ``CXSparse_VERSION`` = 3.1.2
52
+
53
+ ``CXSparse_VERSION_PATCH``
54
+ Equal to 2 if ``CXSparse_VERSION`` = 3.1.2
55
+
56
+ The following variables control the behaviour of this module:
57
+
58
+ ``CXSparse_NO_CMAKE``
59
+ Do not attempt to use the native CXSparse CMake package configuration.
60
+
61
+ Targets
62
+ -------
63
+
64
+ The following target defines CXSparse.
65
+
66
+ ``CXSparse::CXSparse``
67
+ The main CXSparse to be linked against.
68
+
69
+ The following variables are also defined by this module, but in line with CMake
70
+ recommended ``find_package`` module style should NOT be referenced directly by
71
+ callers (use the plural variables detailed above instead). These variables do
72
+ however affect the behaviour of the module via ``find_[path/library]()`` which
73
+ are NOT re-called (i.e., search for library is not repeated) if these variables
74
+ are set with valid values *in the CMake cache*. This means that if these
75
+ variables are set directly in the cache, either by the user in the CMake GUI, or
76
+ by the user passing ``-DVAR=VALUE`` directives to CMake when called (which
77
+ explicitly defines a cache variable), then they will be used verbatim, bypassing
78
+ the ``HINTS`` variables and other hard-coded search locations.
79
+
80
+ ``CXSparse_INCLUDE_DIR``
81
+ Include directory for CXSparse, not including the include directory of any
82
+ dependencies.
83
+
84
+ ``CXSparse_LIBRARY``
85
+ CXSparse library, not including the libraries of any dependencies.
86
+ ]=======================================================================]
87
+
88
+ if (NOT CXSparse_NO_CMAKE)
89
+ find_package (CXSparse NO_MODULE QUIET)
90
+ endif (NOT CXSparse_NO_CMAKE)
91
+
92
+ if (CXSparse_FOUND)
93
+ return ()
94
+ endif (CXSparse_FOUND)
95
+
96
+ # Reset CALLERS_CMAKE_FIND_LIBRARY_PREFIXES to its value when
97
+ # FindCXSparse was invoked.
98
+ macro(CXSparse_RESET_FIND_LIBRARY_PREFIX)
99
+ if (MSVC)
100
+ set(CMAKE_FIND_LIBRARY_PREFIXES "${CALLERS_CMAKE_FIND_LIBRARY_PREFIXES}")
101
+ endif (MSVC)
102
+ endmacro(CXSparse_RESET_FIND_LIBRARY_PREFIX)
103
+
104
+ # Called if we failed to find CXSparse or any of it's required dependencies,
105
+ # unsets all public (designed to be used externally) variables and reports
106
+ # error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
107
+ macro(CXSparse_REPORT_NOT_FOUND REASON_MSG)
108
+ # Make results of search visible in the CMake GUI if CXSparse has not
109
+ # been found so that user does not have to toggle to advanced view.
110
+ mark_as_advanced(CLEAR CXSparse_INCLUDE_DIR
111
+ CXSparse_LIBRARY)
112
+
113
+ cxsparse_reset_find_library_prefix()
114
+
115
+ # Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
116
+ # use the camelcase library name, not uppercase.
117
+ if (CXSparse_FIND_QUIETLY)
118
+ message(STATUS "Failed to find CXSparse - " ${REASON_MSG} ${ARGN})
119
+ elseif (CXSparse_FIND_REQUIRED)
120
+ message(FATAL_ERROR "Failed to find CXSparse - " ${REASON_MSG} ${ARGN})
121
+ else()
122
+ # Neither QUIETLY nor REQUIRED, use no priority which emits a message
123
+ # but continues configuration and allows generation.
124
+ message("-- Failed to find CXSparse - " ${REASON_MSG} ${ARGN})
125
+ endif ()
126
+ return()
127
+ endmacro(CXSparse_REPORT_NOT_FOUND)
128
+
129
+ # Handle possible presence of lib prefix for libraries on MSVC, see
130
+ # also CXSparse_RESET_FIND_LIBRARY_PREFIX().
131
+ if (MSVC)
132
+ # Preserve the caller's original values for CMAKE_FIND_LIBRARY_PREFIXES
133
+ # s/t we can set it back before returning.
134
+ set(CALLERS_CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
135
+ # The empty string in this list is important, it represents the case when
136
+ # the libraries have no prefix (shared libraries / DLLs).
137
+ set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "" "${CMAKE_FIND_LIBRARY_PREFIXES}")
138
+ endif (MSVC)
139
+
140
+ # Additional suffixes to try appending to each search path.
141
+ list(APPEND CXSparse_CHECK_PATH_SUFFIXES
142
+ suitesparse) # Linux/Windows
143
+
144
+ # Search supplied hint directories first if supplied.
145
+ find_path(CXSparse_INCLUDE_DIR
146
+ NAMES cs.h
147
+ PATH_SUFFIXES ${CXSparse_CHECK_PATH_SUFFIXES})
148
+ if (NOT CXSparse_INCLUDE_DIR OR
149
+ NOT EXISTS ${CXSparse_INCLUDE_DIR})
150
+ cxsparse_report_not_found(
151
+ "Could not find CXSparse include directory, set CXSparse_INCLUDE_DIR "
152
+ "to directory containing cs.h")
153
+ endif (NOT CXSparse_INCLUDE_DIR OR
154
+ NOT EXISTS ${CXSparse_INCLUDE_DIR})
155
+
156
+ find_library(CXSparse_LIBRARY NAMES cxsparse
157
+ PATH_SUFFIXES ${CXSparse_CHECK_PATH_SUFFIXES})
158
+
159
+ if (NOT CXSparse_LIBRARY OR
160
+ NOT EXISTS ${CXSparse_LIBRARY})
161
+ cxsparse_report_not_found(
162
+ "Could not find CXSparse library, set CXSparse_LIBRARY "
163
+ "to full path to libcxsparse.")
164
+ endif (NOT CXSparse_LIBRARY OR
165
+ NOT EXISTS ${CXSparse_LIBRARY})
166
+
167
+ # Mark internally as found, then verify. CXSparse_REPORT_NOT_FOUND() unsets
168
+ # if called.
169
+ set(CXSparse_FOUND TRUE)
170
+
171
+ # Extract CXSparse version from cs.h
172
+ if (CXSparse_INCLUDE_DIR)
173
+ set(CXSparse_VERSION_FILE ${CXSparse_INCLUDE_DIR}/cs.h)
174
+ if (NOT EXISTS ${CXSparse_VERSION_FILE})
175
+ cxsparse_report_not_found(
176
+ "Could not find file: ${CXSparse_VERSION_FILE} "
177
+ "containing version information in CXSparse install located at: "
178
+ "${CXSparse_INCLUDE_DIR}.")
179
+ else (NOT EXISTS ${CXSparse_VERSION_FILE})
180
+ file(READ ${CXSparse_INCLUDE_DIR}/cs.h CXSparse_VERSION_FILE_CONTENTS)
181
+
182
+ string(REGEX MATCH "#define CS_VER [0-9]+"
183
+ CXSparse_VERSION_MAJOR "${CXSparse_VERSION_FILE_CONTENTS}")
184
+ string(REGEX REPLACE "#define CS_VER ([0-9]+)" "\\1"
185
+ CXSparse_VERSION_MAJOR "${CXSparse_VERSION_MAJOR}")
186
+
187
+ string(REGEX MATCH "#define CS_SUBVER [0-9]+"
188
+ CXSparse_VERSION_MINOR "${CXSparse_VERSION_FILE_CONTENTS}")
189
+ string(REGEX REPLACE "#define CS_SUBVER ([0-9]+)" "\\1"
190
+ CXSparse_VERSION_MINOR "${CXSparse_VERSION_MINOR}")
191
+
192
+ string(REGEX MATCH "#define CS_SUBSUB [0-9]+"
193
+ CXSparse_VERSION_PATCH "${CXSparse_VERSION_FILE_CONTENTS}")
194
+ string(REGEX REPLACE "#define CS_SUBSUB ([0-9]+)" "\\1"
195
+ CXSparse_VERSION_PATCH "${CXSparse_VERSION_PATCH}")
196
+
197
+ # This is on a single line s/t CMake does not interpret it as a list of
198
+ # elements and insert ';' separators which would result in 3.;1.;2 nonsense.
199
+ set(CXSparse_VERSION "${CXSparse_VERSION_MAJOR}.${CXSparse_VERSION_MINOR}.${CXSparse_VERSION_PATCH}")
200
+ set(CXSparse_VERSION_COMPONENTS 3)
201
+ endif (NOT EXISTS ${CXSparse_VERSION_FILE})
202
+ endif (CXSparse_INCLUDE_DIR)
203
+
204
+ # Catch the case when the caller has set CXSparse_LIBRARY in the cache / GUI and
205
+ # thus FIND_LIBRARY was not called, but specified library is invalid, otherwise
206
+ # we would report CXSparse as found.
207
+ # TODO: This regex for CXSparse library is pretty primitive, we use lowercase
208
+ # for comparison to handle Windows using CamelCase library names, could
209
+ # this check be better?
210
+ string(TOLOWER "${CXSparse_LIBRARY}" LOWERCASE_CXSparse_LIBRARY)
211
+ if (CXSparse_LIBRARY AND
212
+ EXISTS ${CXSparse_LIBRARY} AND
213
+ NOT "${LOWERCASE_CXSparse_LIBRARY}" MATCHES ".*cxsparse[^/]*")
214
+ cxsparse_report_not_found(
215
+ "Caller defined CXSparse_LIBRARY: "
216
+ "${CXSparse_LIBRARY} does not match CXSparse.")
217
+ endif (CXSparse_LIBRARY AND
218
+ EXISTS ${CXSparse_LIBRARY} AND
219
+ NOT "${LOWERCASE_CXSparse_LIBRARY}" MATCHES ".*cxsparse[^/]*")
220
+
221
+ cxsparse_reset_find_library_prefix()
222
+
223
+ mark_as_advanced(CXSparse_INCLUDE_DIR CXSparse_LIBRARY)
224
+
225
+ # Handle REQUIRED / QUIET optional arguments and version.
226
+ include(FindPackageHandleStandardArgs)
227
+ find_package_handle_standard_args(CXSparse
228
+ REQUIRED_VARS CXSparse_INCLUDE_DIR CXSparse_LIBRARY
229
+ VERSION_VAR CXSparse_VERSION)
230
+
231
+ if (CXSparse_INCLUDE_DIR AND CXSparse_LIBRARY)
232
+ if (NOT TARGET CXSparse::CXSparse)
233
+ add_library (CXSparse::CXSparse IMPORTED UNKNOWN)
234
+ endif (NOT TARGET CXSparse::CXSparse)
235
+
236
+ set_property (TARGET CXSparse::CXSparse PROPERTY
237
+ IMPORTED_LOCATION ${CXSparse_LIBRARY})
238
+ set_property (TARGET CXSparse::CXSparse PROPERTY
239
+ INTERFACE_INCLUDE_DIRECTORIES ${CXSparse_INCLUDE_DIR})
240
+ endif (CXSparse_INCLUDE_DIR AND CXSparse_LIBRARY)
cmake/Ceres/FindGlog.cmake ADDED
@@ -0,0 +1,379 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ceres Solver - A fast non-linear least squares minimizer
2
+ # Copyright 2015 Google Inc. All rights reserved.
3
+ # http://ceres-solver.org/
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of Google Inc. nor the names of its contributors may be
14
+ # used to endorse or promote products derived from this software without
15
+ # specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ #
29
+ # Author: alexs.mac@gmail.com (Alex Stewart)
30
+ #
31
+
32
+ # FindGlog.cmake - Find Google glog logging library.
33
+ #
34
+ # This module defines the following variables:
35
+ #
36
+ # GLOG_FOUND: TRUE iff glog is found.
37
+ # GLOG_INCLUDE_DIRS: Include directories for glog.
38
+ # GLOG_LIBRARIES: Libraries required to link glog.
39
+ # FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION: True iff the version of glog found
40
+ # was built & installed / exported
41
+ # as a CMake package.
42
+ #
43
+ # The following variables control the behaviour of this module:
44
+ #
45
+ # GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION: TRUE/FALSE, iff TRUE then
46
+ # then prefer using an exported CMake configuration
47
+ # generated by glog > 0.3.4 over searching for the
48
+ # glog components manually. Otherwise (FALSE)
49
+ # ignore any exported glog CMake configurations and
50
+ # always perform a manual search for the components.
51
+ # Default: TRUE iff user does not define this variable
52
+ # before we are called, and does NOT specify either
53
+ # GLOG_INCLUDE_DIR_HINTS or GLOG_LIBRARY_DIR_HINTS
54
+ # otherwise FALSE.
55
+ # GLOG_INCLUDE_DIR_HINTS: List of additional directories in which to
56
+ # search for glog includes, e.g: /timbuktu/include.
57
+ # GLOG_LIBRARY_DIR_HINTS: List of additional directories in which to
58
+ # search for glog libraries, e.g: /timbuktu/lib.
59
+ #
60
+ # The following variables are also defined by this module, but in line with
61
+ # CMake recommended FindPackage() module style should NOT be referenced directly
62
+ # by callers (use the plural variables detailed above instead). These variables
63
+ # do however affect the behaviour of the module via FIND_[PATH/LIBRARY]() which
64
+ # are NOT re-called (i.e. search for library is not repeated) if these variables
65
+ # are set with valid values _in the CMake cache_. This means that if these
66
+ # variables are set directly in the cache, either by the user in the CMake GUI,
67
+ # or by the user passing -DVAR=VALUE directives to CMake when called (which
68
+ # explicitly defines a cache variable), then they will be used verbatim,
69
+ # bypassing the HINTS variables and other hard-coded search locations.
70
+ #
71
+ # GLOG_INCLUDE_DIR: Include directory for glog, not including the
72
+ # include directory of any dependencies.
73
+ # GLOG_LIBRARY: glog library, not including the libraries of any
74
+ # dependencies.
75
+
76
+ # Reset CALLERS_CMAKE_FIND_LIBRARY_PREFIXES to its value when
77
+ # FindGlog was invoked.
78
+ macro(GLOG_RESET_FIND_LIBRARY_PREFIX)
79
+ if (MSVC AND CALLERS_CMAKE_FIND_LIBRARY_PREFIXES)
80
+ set(CMAKE_FIND_LIBRARY_PREFIXES "${CALLERS_CMAKE_FIND_LIBRARY_PREFIXES}")
81
+ endif()
82
+ endmacro(GLOG_RESET_FIND_LIBRARY_PREFIX)
83
+
84
+ # Called if we failed to find glog or any of it's required dependencies,
85
+ # unsets all public (designed to be used externally) variables and reports
86
+ # error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
87
+ macro(GLOG_REPORT_NOT_FOUND REASON_MSG)
88
+ unset(GLOG_FOUND)
89
+ unset(GLOG_INCLUDE_DIRS)
90
+ unset(GLOG_LIBRARIES)
91
+ # Make results of search visible in the CMake GUI if glog has not
92
+ # been found so that user does not have to toggle to advanced view.
93
+ mark_as_advanced(CLEAR GLOG_INCLUDE_DIR
94
+ GLOG_LIBRARY)
95
+
96
+ glog_reset_find_library_prefix()
97
+
98
+ # Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
99
+ # use the camelcase library name, not uppercase.
100
+ if (Glog_FIND_QUIETLY)
101
+ message(STATUS "Failed to find glog - " ${REASON_MSG} ${ARGN})
102
+ elseif (Glog_FIND_REQUIRED)
103
+ message(FATAL_ERROR "Failed to find glog - " ${REASON_MSG} ${ARGN})
104
+ else()
105
+ # Neither QUIETLY nor REQUIRED, use no priority which emits a message
106
+ # but continues configuration and allows generation.
107
+ message("-- Failed to find glog - " ${REASON_MSG} ${ARGN})
108
+ endif ()
109
+ return()
110
+ endmacro(GLOG_REPORT_NOT_FOUND)
111
+
112
+ # glog_message([mode] "message text")
113
+ #
114
+ # Wraps the standard cmake 'message' command, but suppresses output
115
+ # if the QUIET flag was passed to the find_package(Glog ...) call.
116
+ function(GLOG_MESSAGE)
117
+ if (NOT Glog_FIND_QUIETLY)
118
+ message(${ARGN})
119
+ endif()
120
+ endfunction()
121
+
122
+ # Protect against any alternative find_package scripts for this library having
123
+ # been called previously (in a client project) which set GLOG_FOUND, but not
124
+ # the other variables we require / set here which could cause the search logic
125
+ # here to fail.
126
+ unset(GLOG_FOUND)
127
+
128
+ # -----------------------------------------------------------------
129
+ # By default, if the user has expressed no preference for using an exported
130
+ # glog CMake configuration over performing a search for the installed
131
+ # components, and has not specified any hints for the search locations, then
132
+ # prefer a glog exported configuration if available.
133
+ if (NOT DEFINED GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION
134
+ AND NOT GLOG_INCLUDE_DIR_HINTS
135
+ AND NOT GLOG_LIBRARY_DIR_HINTS)
136
+ glog_message(STATUS "No preference for use of exported glog CMake "
137
+ "configuration set, and no hints for include/library directories provided. "
138
+ "Defaulting to preferring an installed/exported glog CMake configuration "
139
+ "if available.")
140
+ set(GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION TRUE)
141
+ endif()
142
+
143
+ # On macOS, add the Homebrew prefix (with appropriate suffixes) to the
144
+ # respective HINTS directories (after any user-specified locations). This
145
+ # handles Homebrew installations into non-standard locations (not /usr/local).
146
+ # We do not use CMAKE_PREFIX_PATH for this as given the search ordering of
147
+ # find_xxx(), doing so would override any user-specified HINTS locations with
148
+ # the Homebrew version if it exists.
149
+ if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
150
+ find_program(HOMEBREW_EXECUTABLE brew)
151
+ mark_as_advanced(FORCE HOMEBREW_EXECUTABLE)
152
+ if (HOMEBREW_EXECUTABLE)
153
+ # Detected a Homebrew install, query for its install prefix.
154
+ execute_process(COMMAND ${HOMEBREW_EXECUTABLE} --prefix
155
+ OUTPUT_VARIABLE HOMEBREW_INSTALL_PREFIX
156
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
157
+ glog_message(STATUS "Detected Homebrew with install prefix: "
158
+ "${HOMEBREW_INSTALL_PREFIX}, adding to CMake search paths.")
159
+ list(APPEND GLOG_INCLUDE_DIR_HINTS "${HOMEBREW_INSTALL_PREFIX}/include")
160
+ list(APPEND GLOG_LIBRARY_DIR_HINTS "${HOMEBREW_INSTALL_PREFIX}/lib")
161
+ endif()
162
+ endif()
163
+
164
+ if (GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION)
165
+ # Try to find an exported CMake configuration for glog, as generated by
166
+ # glog versions > 0.3.4
167
+ #
168
+ # We search twice, s/t we can invert the ordering of precedence used by
169
+ # find_package() for exported package build directories, and installed
170
+ # packages (found via CMAKE_SYSTEM_PREFIX_PATH), listed as items 6) and 7)
171
+ # respectively in [1].
172
+ #
173
+ # By default, exported build directories are (in theory) detected first, and
174
+ # this is usually the case on Windows. However, on OS X & Linux, the install
175
+ # path (/usr/local) is typically present in the PATH environment variable
176
+ # which is checked in item 4) in [1] (i.e. before both of the above, unless
177
+ # NO_SYSTEM_ENVIRONMENT_PATH is passed). As such on those OSs installed
178
+ # packages are usually detected in preference to exported package build
179
+ # directories.
180
+ #
181
+ # To ensure a more consistent response across all OSs, and as users usually
182
+ # want to prefer an installed version of a package over a locally built one
183
+ # where both exist (esp. as the exported build directory might be removed
184
+ # after installation), we first search with NO_CMAKE_PACKAGE_REGISTRY which
185
+ # means any build directories exported by the user are ignored, and thus
186
+ # installed directories are preferred. If this fails to find the package
187
+ # we then research again, but without NO_CMAKE_PACKAGE_REGISTRY, so any
188
+ # exported build directories will now be detected.
189
+ #
190
+ # To prevent confusion on Windows, we also pass NO_CMAKE_BUILDS_PATH (which
191
+ # is item 5) in [1]), to not preferentially use projects that were built
192
+ # recently with the CMake GUI to ensure that we always prefer an installed
193
+ # version if available.
194
+ #
195
+ # NOTE: We use the NAMES option as glog erroneously uses 'google-glog' as its
196
+ # project name when built with CMake, but exports itself as just 'glog'.
197
+ # On Linux/OS X this does not break detection as the project name is
198
+ # not used as part of the install path for the CMake package files,
199
+ # e.g. /usr/local/lib/cmake/glog, where the <glog> suffix is hardcoded
200
+ # in glog's CMakeLists. However, on Windows the project name *is*
201
+ # part of the install prefix: C:/Program Files/google-glog/[include,lib].
202
+ # However, by default CMake checks:
203
+ # C:/Program Files/<FIND_PACKAGE_ARGUMENT_NAME='glog'> which does not
204
+ # exist and thus detection fails. Thus we use the NAMES to force the
205
+ # search to use both google-glog & glog.
206
+ #
207
+ # [1] http://www.cmake.org/cmake/help/v2.8.11/cmake.html#command:find_package
208
+ find_package(glog QUIET
209
+ NAMES google-glog glog
210
+ HINTS ${glog_DIR} ${HOMEBREW_INSTALL_PREFIX}
211
+ NO_MODULE
212
+ NO_CMAKE_PACKAGE_REGISTRY
213
+ NO_CMAKE_BUILDS_PATH)
214
+ if (glog_FOUND)
215
+ glog_message(STATUS "Found installed version of glog: ${glog_DIR}")
216
+ else()
217
+ # Failed to find an installed version of glog, repeat search allowing
218
+ # exported build directories.
219
+ glog_message(STATUS "Failed to find installed glog CMake configuration, "
220
+ "searching for glog build directories exported with CMake.")
221
+ # Again pass NO_CMAKE_BUILDS_PATH, as we know that glog is exported and
222
+ # do not want to treat projects built with the CMake GUI preferentially.
223
+ find_package(glog QUIET
224
+ NAMES google-glog glog
225
+ NO_MODULE
226
+ NO_CMAKE_BUILDS_PATH)
227
+ if (glog_FOUND)
228
+ glog_message(STATUS "Found exported glog build directory: ${glog_DIR}")
229
+ endif(glog_FOUND)
230
+ endif(glog_FOUND)
231
+
232
+ set(FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION ${glog_FOUND})
233
+
234
+ if (FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION)
235
+ glog_message(STATUS "Detected glog version: ${glog_VERSION}")
236
+ set(GLOG_FOUND ${glog_FOUND})
237
+ # glog wraps the include directories into the exported glog::glog target.
238
+ set(GLOG_INCLUDE_DIR "")
239
+ set(GLOG_LIBRARY glog::glog)
240
+ else (FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION)
241
+ glog_message(STATUS "Failed to find an installed/exported CMake "
242
+ "configuration for glog, will perform search for installed glog "
243
+ "components.")
244
+ endif (FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION)
245
+ endif(GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION)
246
+
247
+ if (NOT GLOG_FOUND)
248
+ # Either failed to find an exported glog CMake configuration, or user
249
+ # told us not to use one. Perform a manual search for all glog components.
250
+
251
+ # Handle possible presence of lib prefix for libraries on MSVC, see
252
+ # also GLOG_RESET_FIND_LIBRARY_PREFIX().
253
+ if (MSVC)
254
+ # Preserve the caller's original values for CMAKE_FIND_LIBRARY_PREFIXES
255
+ # s/t we can set it back before returning.
256
+ set(CALLERS_CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
257
+ # The empty string in this list is important, it represents the case when
258
+ # the libraries have no prefix (shared libraries / DLLs).
259
+ set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "" "${CMAKE_FIND_LIBRARY_PREFIXES}")
260
+ endif (MSVC)
261
+
262
+ # Search user-installed locations first, so that we prefer user installs
263
+ # to system installs where both exist.
264
+ list(APPEND GLOG_CHECK_INCLUDE_DIRS
265
+ /usr/local/include
266
+ /usr/local/homebrew/include # Mac OS X
267
+ /opt/local/var/macports/software # Mac OS X.
268
+ /opt/local/include
269
+ /usr/include)
270
+ # Windows (for C:/Program Files prefix).
271
+ list(APPEND GLOG_CHECK_PATH_SUFFIXES
272
+ glog/include
273
+ glog/Include
274
+ Glog/include
275
+ Glog/Include
276
+ google-glog/include # CMake installs with project name prefix.
277
+ google-glog/Include)
278
+
279
+ list(APPEND GLOG_CHECK_LIBRARY_DIRS
280
+ /usr/local/lib
281
+ /usr/local/homebrew/lib # Mac OS X.
282
+ /opt/local/lib
283
+ /usr/lib)
284
+ # Windows (for C:/Program Files prefix).
285
+ list(APPEND GLOG_CHECK_LIBRARY_SUFFIXES
286
+ glog/lib
287
+ glog/Lib
288
+ Glog/lib
289
+ Glog/Lib
290
+ google-glog/lib # CMake installs with project name prefix.
291
+ google-glog/Lib)
292
+
293
+ # Search supplied hint directories first if supplied.
294
+ find_path(GLOG_INCLUDE_DIR
295
+ NAMES glog/logging.h
296
+ HINTS ${GLOG_INCLUDE_DIR_HINTS}
297
+ PATHS ${GLOG_CHECK_INCLUDE_DIRS}
298
+ PATH_SUFFIXES ${GLOG_CHECK_PATH_SUFFIXES})
299
+ if (NOT GLOG_INCLUDE_DIR OR
300
+ NOT EXISTS ${GLOG_INCLUDE_DIR})
301
+ glog_report_not_found(
302
+ "Could not find glog include directory, set GLOG_INCLUDE_DIR "
303
+ "to directory containing glog/logging.h")
304
+ endif (NOT GLOG_INCLUDE_DIR OR
305
+ NOT EXISTS ${GLOG_INCLUDE_DIR})
306
+
307
+ find_library(GLOG_LIBRARY NAMES glog
308
+ HINTS ${GLOG_LIBRARY_DIR_HINTS}
309
+ PATHS ${GLOG_CHECK_LIBRARY_DIRS}
310
+ PATH_SUFFIXES ${GLOG_CHECK_LIBRARY_SUFFIXES})
311
+ if (NOT GLOG_LIBRARY OR
312
+ NOT EXISTS ${GLOG_LIBRARY})
313
+ glog_report_not_found(
314
+ "Could not find glog library, set GLOG_LIBRARY "
315
+ "to full path to libglog.")
316
+ endif (NOT GLOG_LIBRARY OR
317
+ NOT EXISTS ${GLOG_LIBRARY})
318
+
319
+ # Mark internally as found, then verify. GLOG_REPORT_NOT_FOUND() unsets
320
+ # if called.
321
+ set(GLOG_FOUND TRUE)
322
+
323
+ # Glog does not seem to provide any record of the version in its
324
+ # source tree, thus cannot extract version.
325
+
326
+ # Catch case when caller has set GLOG_INCLUDE_DIR in the cache / GUI and
327
+ # thus FIND_[PATH/LIBRARY] are not called, but specified locations are
328
+ # invalid, otherwise we would report the library as found.
329
+ if (GLOG_INCLUDE_DIR AND
330
+ NOT EXISTS ${GLOG_INCLUDE_DIR}/glog/logging.h)
331
+ glog_report_not_found(
332
+ "Caller defined GLOG_INCLUDE_DIR:"
333
+ " ${GLOG_INCLUDE_DIR} does not contain glog/logging.h header.")
334
+ endif (GLOG_INCLUDE_DIR AND
335
+ NOT EXISTS ${GLOG_INCLUDE_DIR}/glog/logging.h)
336
+ # TODO: This regex for glog library is pretty primitive, we use lowercase
337
+ # for comparison to handle Windows using CamelCase library names, could
338
+ # this check be better?
339
+ string(TOLOWER "${GLOG_LIBRARY}" LOWERCASE_GLOG_LIBRARY)
340
+ if (GLOG_LIBRARY AND
341
+ NOT "${LOWERCASE_GLOG_LIBRARY}" MATCHES ".*glog[^/]*")
342
+ glog_report_not_found(
343
+ "Caller defined GLOG_LIBRARY: "
344
+ "${GLOG_LIBRARY} does not match glog.")
345
+ endif (GLOG_LIBRARY AND
346
+ NOT "${LOWERCASE_GLOG_LIBRARY}" MATCHES ".*glog[^/]*")
347
+
348
+ glog_reset_find_library_prefix()
349
+
350
+ endif(NOT GLOG_FOUND)
351
+
352
+ # Set standard CMake FindPackage variables if found.
353
+ if (GLOG_FOUND)
354
+ set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR})
355
+ set(GLOG_LIBRARIES ${GLOG_LIBRARY})
356
+ endif (GLOG_FOUND)
357
+
358
+ # If we are using an exported CMake glog target, the include directories are
359
+ # wrapped into the target itself, and do not have to be (and are not)
360
+ # separately specified. In which case, we should not add GLOG_INCLUDE_DIRS
361
+ # to the list of required variables in order that glog be reported as found.
362
+ if (FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION)
363
+ set(GLOG_REQUIRED_VARIABLES GLOG_LIBRARIES)
364
+ else()
365
+ set(GLOG_REQUIRED_VARIABLES GLOG_INCLUDE_DIRS GLOG_LIBRARIES)
366
+ endif()
367
+
368
+ # Handle REQUIRED / QUIET optional arguments.
369
+ include(FindPackageHandleStandardArgs)
370
+ find_package_handle_standard_args(Glog DEFAULT_MSG
371
+ ${GLOG_REQUIRED_VARIABLES})
372
+
373
+ # Only mark internal variables as advanced if we found glog, otherwise
374
+ # leave them visible in the standard GUI for the user to set manually.
375
+ if (GLOG_FOUND)
376
+ mark_as_advanced(FORCE GLOG_INCLUDE_DIR
377
+ GLOG_LIBRARY
378
+ glog_DIR) # Autogenerated by find_package(glog)
379
+ endif (GLOG_FOUND)
cmake/Ceres/FindMETIS.cmake ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (c) 2022 Sergiu Deitsch
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTMETISLAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ # SOFTWARE.
21
+ #
22
+ #[=======================================================================[.rst:
23
+ Module for locating METIS
24
+ =========================
25
+
26
+ Read-only variables:
27
+
28
+ ``METIS_FOUND``
29
+ Indicates whether the library has been found.
30
+
31
+ ``METIS_VERSION``
32
+ Indicates library version.
33
+
34
+ Targets
35
+ -------
36
+
37
+ ``METIS::METIS``
38
+ Specifies targets that should be passed to target_link_libararies.
39
+ ]=======================================================================]
40
+
41
+ include (FindPackageHandleStandardArgs)
42
+
43
+ find_path (METIS_INCLUDE_DIR NAMES metis.h
44
+ PATH_SUFFIXES include
45
+ DOC "METIS include directory")
46
+ find_library (METIS_LIBRARY_DEBUG NAMES metis
47
+ PATH_SUFFIXES Debug
48
+ DOC "METIS debug library")
49
+ find_library (METIS_LIBRARY_RELEASE NAMES metis
50
+ PATH_SUFFIXES Release
51
+ DOC "METIS release library")
52
+
53
+ if (METIS_LIBRARY_RELEASE)
54
+ if (METIS_LIBRARY_DEBUG)
55
+ set (METIS_LIBRARY debug ${METIS_LIBRARY_DEBUG} optimized
56
+ ${METIS_LIBRARY_RELEASE} CACHE STRING "METIS library")
57
+ else (METIS_LIBRARY_DEBUG)
58
+ set (METIS_LIBRARY ${METIS_LIBRARY_RELEASE} CACHE FILEPATH "METIS library")
59
+ endif (METIS_LIBRARY_DEBUG)
60
+ elseif (METIS_LIBRARY_DEBUG)
61
+ set (METIS_LIBRARY ${METIS_LIBRARY_DEBUG} CACHE FILEPATH "METIS library")
62
+ endif (METIS_LIBRARY_RELEASE)
63
+
64
+ set (_METIS_VERSION_HEADER ${METIS_INCLUDE_DIR}/metis.h)
65
+
66
+ if (EXISTS ${_METIS_VERSION_HEADER})
67
+ file (READ ${_METIS_VERSION_HEADER} _METIS_VERSION_CONTENTS)
68
+
69
+ string (REGEX REPLACE ".*#define METIS_VER_MAJOR[ \t]+([0-9]+).*" "\\1"
70
+ METIS_VERSION_MAJOR "${_METIS_VERSION_CONTENTS}")
71
+ string (REGEX REPLACE ".*#define METIS_VER_MINOR[ \t]+([0-9]+).*" "\\1"
72
+ METIS_VERSION_MINOR "${_METIS_VERSION_CONTENTS}")
73
+ string (REGEX REPLACE ".*#define METIS_VER_SUBMINOR[ \t]+([0-9]+).*" "\\1"
74
+ METIS_VERSION_PATCH "${_METIS_VERSION_CONTENTS}")
75
+
76
+ set (METIS_VERSION
77
+ ${METIS_VERSION_MAJOR}.${METIS_VERSION_MINOR}.${METIS_VERSION_PATCH})
78
+ set (METIS_VERSION_COMPONENTS 3)
79
+ endif (EXISTS ${_METIS_VERSION_HEADER})
80
+
81
+ mark_as_advanced (METIS_INCLUDE_DIR METIS_LIBRARY_DEBUG METIS_LIBRARY_RELEASE
82
+ METIS_LIBRARY)
83
+
84
+ if (NOT TARGET METIS::METIS)
85
+ if (METIS_INCLUDE_DIR OR METIS_LIBRARY)
86
+ add_library (METIS::METIS IMPORTED UNKNOWN)
87
+ endif (METIS_INCLUDE_DIR OR METIS_LIBRARY)
88
+ endif (NOT TARGET METIS::METIS)
89
+
90
+ if (METIS_INCLUDE_DIR)
91
+ set_property (TARGET METIS::METIS PROPERTY INTERFACE_INCLUDE_DIRECTORIES
92
+ ${METIS_INCLUDE_DIR})
93
+ endif (METIS_INCLUDE_DIR)
94
+
95
+ if (METIS_LIBRARY_RELEASE)
96
+ set_property (TARGET METIS::METIS PROPERTY IMPORTED_LOCATION_RELEASE
97
+ ${METIS_LIBRARY_RELEASE})
98
+ set_property (TARGET METIS::METIS APPEND PROPERTY IMPORTED_CONFIGURATIONS
99
+ RELEASE)
100
+ endif (METIS_LIBRARY_RELEASE)
101
+
102
+ if (METIS_LIBRARY_DEBUG)
103
+ set_property (TARGET METIS::METIS PROPERTY IMPORTED_LOCATION_DEBUG
104
+ ${METIS_LIBRARY_DEBUG})
105
+ set_property (TARGET METIS::METIS APPEND PROPERTY IMPORTED_CONFIGURATIONS
106
+ DEBUG)
107
+ endif (METIS_LIBRARY_DEBUG)
108
+
109
+ find_package_handle_standard_args (METIS REQUIRED_VARS
110
+ METIS_INCLUDE_DIR METIS_LIBRARY VERSION_VAR METIS_VERSION)
cmake/Ceres/FindSuiteSparse.cmake ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ceres Solver - A fast non-linear least squares minimizer
2
+ # Copyright 2022 Google Inc. All rights reserved.
3
+ # http://ceres-solver.org/
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of Google Inc. nor the names of its contributors may be
14
+ # used to endorse or promote products derived from this software without
15
+ # specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ #
29
+ # Author: alexs.mac@gmail.com (Alex Stewart)
30
+ #
31
+
32
+ #[=======================================================================[.rst:
33
+ FindSuiteSparse
34
+ ===============
35
+
36
+ Module for locating SuiteSparse libraries and its dependencies.
37
+
38
+ This module defines the following variables:
39
+
40
+ ``SuiteSparse_FOUND``
41
+ ``TRUE`` iff SuiteSparse and all dependencies have been found.
42
+
43
+ ``SuiteSparse_VERSION``
44
+ Extracted from ``SuiteSparse_config.h`` (>= v4).
45
+
46
+ ``SuiteSparse_VERSION_MAJOR``
47
+ Equal to 4 if ``SuiteSparse_VERSION`` = 4.2.1
48
+
49
+ ``SuiteSparse_VERSION_MINOR``
50
+ Equal to 2 if ``SuiteSparse_VERSION`` = 4.2.1
51
+
52
+ ``SuiteSparse_VERSION_PATCH``
53
+ Equal to 1 if ``SuiteSparse_VERSION`` = 4.2.1
54
+
55
+ The following variables control the behaviour of this module:
56
+
57
+ ``SuiteSparse_NO_CMAKE``
58
+ Do not attempt to use the native SuiteSparse CMake package configuration.
59
+
60
+
61
+ Targets
62
+ -------
63
+
64
+ The following targets define the SuiteSparse components searched for.
65
+
66
+ ``SuiteSparse::AMD``
67
+ Symmetric Approximate Minimum Degree (AMD)
68
+
69
+ ``SuiteSparse::CAMD``
70
+ Constrained Approximate Minimum Degree (CAMD)
71
+
72
+ ``SuiteSparse::COLAMD``
73
+ Column Approximate Minimum Degree (COLAMD)
74
+
75
+ ``SuiteSparse::CCOLAMD``
76
+ Constrained Column Approximate Minimum Degree (CCOLAMD)
77
+
78
+ ``SuiteSparse::CHOLMOD``
79
+ Sparse Supernodal Cholesky Factorization and Update/Downdate (CHOLMOD)
80
+
81
+ ``SuiteSparse::SPQR``
82
+ Multifrontal Sparse QR (SuiteSparseQR)
83
+
84
+ ``SuiteSparse::Config``
85
+ Common configuration for all but CSparse (SuiteSparse version >= 4).
86
+
87
+ Optional SuiteSparse dependencies:
88
+
89
+ ``METIS::METIS``
90
+ Serial Graph Partitioning and Fill-reducing Matrix Ordering (METIS)
91
+ ]=======================================================================]
92
+
93
+ if (NOT SuiteSparse_NO_CMAKE)
94
+ find_package (SuiteSparse NO_MODULE QUIET)
95
+ endif (NOT SuiteSparse_NO_CMAKE)
96
+
97
+ if (SuiteSparse_FOUND)
98
+ return ()
99
+ endif (SuiteSparse_FOUND)
100
+
101
+ # Push CMP0057 to enable support for IN_LIST, when cmake_minimum_required is
102
+ # set to <3.3.
103
+ cmake_policy (PUSH)
104
+ cmake_policy (SET CMP0057 NEW)
105
+
106
+ if (NOT SuiteSparse_FIND_COMPONENTS)
107
+ set (SuiteSparse_FIND_COMPONENTS
108
+ AMD
109
+ CAMD
110
+ CCOLAMD
111
+ CHOLMOD
112
+ COLAMD
113
+ SPQR
114
+ )
115
+
116
+ foreach (component IN LISTS SuiteSparse_FIND_COMPONENTS)
117
+ set (SuiteSparse_FIND_REQUIRED_${component} TRUE)
118
+ endforeach (component IN LISTS SuiteSparse_FIND_COMPONENTS)
119
+ endif (NOT SuiteSparse_FIND_COMPONENTS)
120
+
121
+ # Assume SuiteSparse was found and set it to false only if third-party
122
+ # dependencies could not be located. SuiteSparse components are handled by
123
+ # FindPackageHandleStandardArgs HANDLE_COMPONENTS option.
124
+ set (SuiteSparse_FOUND TRUE)
125
+
126
+ include (CheckLibraryExists)
127
+
128
+ # Config is a base component and thus always required
129
+ set (SuiteSparse_IMPLICIT_COMPONENTS Config)
130
+
131
+ # CHOLMOD depends on AMD, CAMD, CCOLAMD, and COLAMD.
132
+ if (CHOLMOD IN_LIST SuiteSparse_FIND_COMPONENTS)
133
+ list (APPEND SuiteSparse_IMPLICIT_COMPONENTS AMD CAMD CCOLAMD COLAMD)
134
+ endif (CHOLMOD IN_LIST SuiteSparse_FIND_COMPONENTS)
135
+
136
+ # SPQR depends on CHOLMOD.
137
+ if (SPQR IN_LIST SuiteSparse_FIND_COMPONENTS)
138
+ list (APPEND SuiteSparse_IMPLICIT_COMPONENTS CHOLMOD)
139
+ endif (SPQR IN_LIST SuiteSparse_FIND_COMPONENTS)
140
+
141
+ # Implicit components are always required
142
+ foreach (component IN LISTS SuiteSparse_IMPLICIT_COMPONENTS)
143
+ set (SuiteSparse_FIND_REQUIRED_${component} TRUE)
144
+ endforeach (component IN LISTS SuiteSparse_IMPLICIT_COMPONENTS)
145
+
146
+ list (APPEND SuiteSparse_FIND_COMPONENTS ${SuiteSparse_IMPLICIT_COMPONENTS})
147
+
148
+ # Do not list components multiple times.
149
+ list (REMOVE_DUPLICATES SuiteSparse_FIND_COMPONENTS)
150
+
151
+ # Reset CALLERS_CMAKE_FIND_LIBRARY_PREFIXES to its value when
152
+ # FindSuiteSparse was invoked.
153
+ macro(SuiteSparse_RESET_FIND_LIBRARY_PREFIX)
154
+ if (MSVC)
155
+ set(CMAKE_FIND_LIBRARY_PREFIXES "${CALLERS_CMAKE_FIND_LIBRARY_PREFIXES}")
156
+ endif (MSVC)
157
+ endmacro(SuiteSparse_RESET_FIND_LIBRARY_PREFIX)
158
+
159
+ # Called if we failed to find SuiteSparse or any of it's required dependencies,
160
+ # unsets all public (designed to be used externally) variables and reports
161
+ # error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
162
+ macro(SuiteSparse_REPORT_NOT_FOUND REASON_MSG)
163
+ # Will be set to FALSE by find_package_handle_standard_args
164
+ unset (SuiteSparse_FOUND)
165
+
166
+ # Do NOT unset SuiteSparse_REQUIRED_VARS here, as it is used by
167
+ # FindPackageHandleStandardArgs() to generate the automatic error message on
168
+ # failure which highlights which components are missing.
169
+
170
+ suitesparse_reset_find_library_prefix()
171
+
172
+ # Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
173
+ # use the camelcase library name, not uppercase.
174
+ if (SuiteSparse_FIND_QUIETLY)
175
+ message(STATUS "Failed to find SuiteSparse - " ${REASON_MSG} ${ARGN})
176
+ elseif (SuiteSparse_FIND_REQUIRED)
177
+ message(FATAL_ERROR "Failed to find SuiteSparse - " ${REASON_MSG} ${ARGN})
178
+ else()
179
+ # Neither QUIETLY nor REQUIRED, use no priority which emits a message
180
+ # but continues configuration and allows generation.
181
+ message("-- Failed to find SuiteSparse - " ${REASON_MSG} ${ARGN})
182
+ endif (SuiteSparse_FIND_QUIETLY)
183
+
184
+ # Do not call return(), s/t we keep processing if not called with REQUIRED
185
+ # and report all missing components, rather than bailing after failing to find
186
+ # the first.
187
+ endmacro(SuiteSparse_REPORT_NOT_FOUND)
188
+
189
+ # Handle possible presence of lib prefix for libraries on MSVC, see
190
+ # also SuiteSparse_RESET_FIND_LIBRARY_PREFIX().
191
+ if (MSVC)
192
+ # Preserve the caller's original values for CMAKE_FIND_LIBRARY_PREFIXES
193
+ # s/t we can set it back before returning.
194
+ set(CALLERS_CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
195
+ # The empty string in this list is important, it represents the case when
196
+ # the libraries have no prefix (shared libraries / DLLs).
197
+ set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "" "${CMAKE_FIND_LIBRARY_PREFIXES}")
198
+ endif (MSVC)
199
+
200
+ # Additional suffixes to try appending to each search path.
201
+ list(APPEND SuiteSparse_CHECK_PATH_SUFFIXES
202
+ suitesparse) # Windows/Ubuntu
203
+
204
+ # Wrappers to find_path/library that pass the SuiteSparse search hints/paths.
205
+ #
206
+ # suitesparse_find_component(<component> [FILES name1 [name2 ...]]
207
+ # [LIBRARIES name1 [name2 ...]])
208
+ macro(suitesparse_find_component COMPONENT)
209
+ include(CMakeParseArguments)
210
+ set(MULTI_VALUE_ARGS FILES LIBRARIES)
211
+ cmake_parse_arguments(SuiteSparse_FIND_COMPONENT_${COMPONENT}
212
+ "" "" "${MULTI_VALUE_ARGS}" ${ARGN})
213
+
214
+ set(SuiteSparse_${COMPONENT}_FOUND TRUE)
215
+ if (SuiteSparse_FIND_COMPONENT_${COMPONENT}_FILES)
216
+ find_path(SuiteSparse_${COMPONENT}_INCLUDE_DIR
217
+ NAMES ${SuiteSparse_FIND_COMPONENT_${COMPONENT}_FILES}
218
+ PATH_SUFFIXES ${SuiteSparse_CHECK_PATH_SUFFIXES})
219
+ if (SuiteSparse_${COMPONENT}_INCLUDE_DIR)
220
+ message(STATUS "Found ${COMPONENT} headers in: "
221
+ "${SuiteSparse_${COMPONENT}_INCLUDE_DIR}")
222
+ mark_as_advanced(SuiteSparse_${COMPONENT}_INCLUDE_DIR)
223
+ else()
224
+ # Specified headers not found.
225
+ set(SuiteSparse_${COMPONENT}_FOUND FALSE)
226
+ if (SuiteSparse_FIND_REQUIRED_${COMPONENT})
227
+ suitesparse_report_not_found(
228
+ "Did not find ${COMPONENT} header (required SuiteSparse component).")
229
+ else()
230
+ message(STATUS "Did not find ${COMPONENT} header (optional "
231
+ "SuiteSparse component).")
232
+ # Hide optional vars from CMake GUI even if not found.
233
+ mark_as_advanced(SuiteSparse_${COMPONENT}_INCLUDE_DIR)
234
+ endif()
235
+ endif()
236
+ endif()
237
+
238
+ if (SuiteSparse_FIND_COMPONENT_${COMPONENT}_LIBRARIES)
239
+ find_library(SuiteSparse_${COMPONENT}_LIBRARY
240
+ NAMES ${SuiteSparse_FIND_COMPONENT_${COMPONENT}_LIBRARIES}
241
+ PATH_SUFFIXES ${SuiteSparse_CHECK_PATH_SUFFIXES})
242
+ if (SuiteSparse_${COMPONENT}_LIBRARY)
243
+ message(STATUS "Found ${COMPONENT} library: ${SuiteSparse_${COMPONENT}_LIBRARY}")
244
+ mark_as_advanced(SuiteSparse_${COMPONENT}_LIBRARY)
245
+ else ()
246
+ # Specified libraries not found.
247
+ set(SuiteSparse_${COMPONENT}_FOUND FALSE)
248
+ if (SuiteSparse_FIND_REQUIRED_${COMPONENT})
249
+ suitesparse_report_not_found(
250
+ "Did not find ${COMPONENT} library (required SuiteSparse component).")
251
+ else()
252
+ message(STATUS "Did not find ${COMPONENT} library (optional SuiteSparse "
253
+ "dependency)")
254
+ # Hide optional vars from CMake GUI even if not found.
255
+ mark_as_advanced(SuiteSparse_${COMPONENT}_LIBRARY)
256
+ endif()
257
+ endif()
258
+ endif()
259
+
260
+ # A component can be optional (given to OPTIONAL_COMPONENTS). However, if the
261
+ # component is implicit (must be always present, such as the Config component)
262
+ # assume it be required as well.
263
+ if (SuiteSparse_FIND_REQUIRED_${COMPONENT})
264
+ list (APPEND SuiteSparse_REQUIRED_VARS SuiteSparse_${COMPONENT}_INCLUDE_DIR)
265
+ list (APPEND SuiteSparse_REQUIRED_VARS SuiteSparse_${COMPONENT}_LIBRARY)
266
+ endif (SuiteSparse_FIND_REQUIRED_${COMPONENT})
267
+
268
+ # Define the target only if the include directory and the library were found
269
+ if (SuiteSparse_${COMPONENT}_INCLUDE_DIR AND SuiteSparse_${COMPONENT}_LIBRARY)
270
+ if (NOT TARGET SuiteSparse::${COMPONENT})
271
+ add_library(SuiteSparse::${COMPONENT} IMPORTED UNKNOWN)
272
+ endif (NOT TARGET SuiteSparse::${COMPONENT})
273
+
274
+ set_property(TARGET SuiteSparse::${COMPONENT} PROPERTY
275
+ INTERFACE_INCLUDE_DIRECTORIES ${SuiteSparse_${COMPONENT}_INCLUDE_DIR})
276
+ set_property(TARGET SuiteSparse::${COMPONENT} PROPERTY
277
+ IMPORTED_LOCATION ${SuiteSparse_${COMPONENT}_LIBRARY})
278
+ endif (SuiteSparse_${COMPONENT}_INCLUDE_DIR AND SuiteSparse_${COMPONENT}_LIBRARY)
279
+ endmacro()
280
+
281
+ # Given the number of components of SuiteSparse, and to ensure that the
282
+ # automatic failure message generated by FindPackageHandleStandardArgs()
283
+ # when not all required components are found is helpful, we maintain a list
284
+ # of all variables that must be defined for SuiteSparse to be considered found.
285
+ unset(SuiteSparse_REQUIRED_VARS)
286
+
287
+ # BLAS.
288
+ find_package(BLAS QUIET)
289
+ if (NOT BLAS_FOUND)
290
+ suitesparse_report_not_found(
291
+ "Did not find BLAS library (required for SuiteSparse).")
292
+ endif (NOT BLAS_FOUND)
293
+
294
+ # LAPACK.
295
+ find_package(LAPACK QUIET)
296
+ if (NOT LAPACK_FOUND)
297
+ suitesparse_report_not_found(
298
+ "Did not find LAPACK library (required for SuiteSparse).")
299
+ endif (NOT LAPACK_FOUND)
300
+
301
+ foreach (component IN LISTS SuiteSparse_FIND_COMPONENTS)
302
+ string (TOLOWER ${component} component_library)
303
+
304
+ if (component STREQUAL "Config")
305
+ set (component_header SuiteSparse_config.h)
306
+ set (component_library suitesparseconfig)
307
+ elseif (component STREQUAL "SPQR")
308
+ set (component_header SuiteSparseQR.hpp)
309
+ else (component STREQUAL "SPQR")
310
+ set (component_header ${component_library}.h)
311
+ endif (component STREQUAL "Config")
312
+
313
+ suitesparse_find_component(${component}
314
+ FILES ${component_header}
315
+ LIBRARIES ${component_library})
316
+ endforeach (component IN LISTS SuiteSparse_FIND_COMPONENTS)
317
+
318
+ if (TARGET SuiteSparse::SPQR)
319
+ # SuiteSparseQR may be compiled with Intel Threading Building Blocks,
320
+ # we assume that if TBB is installed, SuiteSparseQR was compiled with
321
+ # support for it, this will do no harm if it wasn't.
322
+ find_package(TBB QUIET)
323
+ if (TBB_FOUND)
324
+ message(STATUS "Found Intel Thread Building Blocks (TBB) library "
325
+ "(${TBB_VERSION_MAJOR}.${TBB_VERSION_MINOR} / ${TBB_INTERFACE_VERSION}) "
326
+ "include location: ${TBB_INCLUDE_DIRS}. Assuming SuiteSparseQR was "
327
+ "compiled with TBB.")
328
+ # Add the TBB libraries to the SuiteSparseQR libraries (the only
329
+ # libraries to optionally depend on TBB).
330
+ if (TARGET TBB::tbb)
331
+ # Native TBB package configuration provides an imported target. Use it if
332
+ # available.
333
+ set_property (TARGET SuiteSparse::SPQR APPEND PROPERTY
334
+ INTERFACE_LINK_LIBRARIES TBB::tbb)
335
+ else (TARGET TBB::tbb)
336
+ set_property (TARGET SuiteSparse::SPQR APPEND PROPERTY
337
+ INTERFACE_INCLUDE_DIRECTORIES ${TBB_INCLUDE_DIRS})
338
+ set_property (TARGET SuiteSparse::SPQR APPEND PROPERTY
339
+ INTERFACE_LINK_LIBRARIES ${TBB_LIBRARIES})
340
+ endif (TARGET TBB::tbb)
341
+ else (TBB_FOUND)
342
+ message(STATUS "Did not find Intel TBB library, assuming SuiteSparseQR was "
343
+ "not compiled with TBB.")
344
+ endif (TBB_FOUND)
345
+ endif (TARGET SuiteSparse::SPQR)
346
+
347
+ check_library_exists(rt shm_open "" HAVE_LIBRT)
348
+
349
+ if (TARGET SuiteSparse::Config)
350
+ # SuiteSparse_config (SuiteSparse version >= 4) requires librt library for
351
+ # timing by default when compiled on Linux or Unix, but not on OSX (which
352
+ # does not have librt).
353
+ if (HAVE_LIBRT)
354
+ message(STATUS "Adding librt to "
355
+ "SuiteSparse_config libraries (required on Linux & Unix [not OSX] if "
356
+ "SuiteSparse is compiled with timing).")
357
+ set_property (TARGET SuiteSparse::Config APPEND PROPERTY
358
+ INTERFACE_LINK_LIBRARIES $<LINK_ONLY:rt>)
359
+ else (HAVE_LIBRT)
360
+ message(STATUS "Could not find librt, but found SuiteSparse_config, "
361
+ "assuming that SuiteSparse was compiled without timing.")
362
+ endif (HAVE_LIBRT)
363
+
364
+ # Add BLAS and LAPACK as dependencies of SuiteSparse::Config for convenience
365
+ # given that all components depend on it.
366
+ if (BLAS_FOUND)
367
+ if (TARGET BLAS::BLAS)
368
+ set_property (TARGET SuiteSparse::Config APPEND PROPERTY
369
+ INTERFACE_LINK_LIBRARIES $<LINK_ONLY:BLAS::BLAS>)
370
+ else (TARGET BLAS::BLAS)
371
+ set_property (TARGET SuiteSparse::Config APPEND PROPERTY
372
+ INTERFACE_LINK_LIBRARIES ${BLAS_LIBRARIES})
373
+ endif (TARGET BLAS::BLAS)
374
+ endif (BLAS_FOUND)
375
+
376
+ if (LAPACK_FOUND)
377
+ if (TARGET LAPACK::LAPACK)
378
+ set_property (TARGET SuiteSparse::Config APPEND PROPERTY
379
+ INTERFACE_LINK_LIBRARIES $<LINK_ONLY:LAPACK::LAPACK>)
380
+ else (TARGET LAPACK::LAPACK)
381
+ set_property (TARGET SuiteSparse::Config APPEND PROPERTY
382
+ INTERFACE_LINK_LIBRARIES ${LAPACK_LIBRARIES})
383
+ endif (TARGET LAPACK::LAPACK)
384
+ endif (LAPACK_FOUND)
385
+
386
+ # SuiteSparse version >= 4.
387
+ set(SuiteSparse_VERSION_FILE
388
+ ${SuiteSparse_Config_INCLUDE_DIR}/SuiteSparse_config.h)
389
+ if (NOT EXISTS ${SuiteSparse_VERSION_FILE})
390
+ suitesparse_report_not_found(
391
+ "Could not find file: ${SuiteSparse_VERSION_FILE} containing version "
392
+ "information for >= v4 SuiteSparse installs, but SuiteSparse_config was "
393
+ "found (only present in >= v4 installs).")
394
+ else (NOT EXISTS ${SuiteSparse_VERSION_FILE})
395
+ file(READ ${SuiteSparse_VERSION_FILE} Config_CONTENTS)
396
+
397
+ string(REGEX MATCH "#define SUITESPARSE_MAIN_VERSION [0-9]+"
398
+ SuiteSparse_VERSION_MAJOR "${Config_CONTENTS}")
399
+ string(REGEX REPLACE "#define SUITESPARSE_MAIN_VERSION ([0-9]+)" "\\1"
400
+ SuiteSparse_VERSION_MAJOR "${SuiteSparse_VERSION_MAJOR}")
401
+
402
+ string(REGEX MATCH "#define SUITESPARSE_SUB_VERSION [0-9]+"
403
+ SuiteSparse_VERSION_MINOR "${Config_CONTENTS}")
404
+ string(REGEX REPLACE "#define SUITESPARSE_SUB_VERSION ([0-9]+)" "\\1"
405
+ SuiteSparse_VERSION_MINOR "${SuiteSparse_VERSION_MINOR}")
406
+
407
+ string(REGEX MATCH "#define SUITESPARSE_SUBSUB_VERSION [0-9]+"
408
+ SuiteSparse_VERSION_PATCH "${Config_CONTENTS}")
409
+ string(REGEX REPLACE "#define SUITESPARSE_SUBSUB_VERSION ([0-9]+)" "\\1"
410
+ SuiteSparse_VERSION_PATCH "${SuiteSparse_VERSION_PATCH}")
411
+
412
+ # This is on a single line s/t CMake does not interpret it as a list of
413
+ # elements and insert ';' separators which would result in 4.;2.;1 nonsense.
414
+ set(SuiteSparse_VERSION
415
+ "${SuiteSparse_VERSION_MAJOR}.${SuiteSparse_VERSION_MINOR}.${SuiteSparse_VERSION_PATCH}")
416
+ set(SuiteSparse_VERSION_COMPONENTS 3)
417
+ endif (NOT EXISTS ${SuiteSparse_VERSION_FILE})
418
+ endif (TARGET SuiteSparse::Config)
419
+
420
+ # METIS (Optional dependency).
421
+ find_package (METIS)
422
+
423
+ # CHOLMOD requires AMD CAMD CCOLAMD COLAMD
424
+ if (TARGET SuiteSparse::CHOLMOD)
425
+ # METIS is optional
426
+ if (TARGET METIS::METIS)
427
+ set_property (TARGET SuiteSparse::CHOLMOD APPEND PROPERTY
428
+ INTERFACE_LINK_LIBRARIES METIS::METIS)
429
+ endif (TARGET METIS::METIS)
430
+
431
+ foreach (component IN ITEMS AMD CAMD CCOLAMD COLAMD)
432
+ if (TARGET SuiteSparse::${component})
433
+ set_property (TARGET SuiteSparse::CHOLMOD APPEND PROPERTY
434
+ INTERFACE_LINK_LIBRARIES SuiteSparse::${component})
435
+ else (TARGET SuiteSparse::${component})
436
+ # Consider CHOLMOD not found if COLAMD cannot be found
437
+ set (SuiteSparse_CHOLMOD_FOUND FALSE)
438
+ endif (TARGET SuiteSparse::${component})
439
+ endforeach (component IN ITEMS AMD CAMD CCOLAMD COLAMD)
440
+ endif (TARGET SuiteSparse::CHOLMOD)
441
+
442
+ # SPQR requires CHOLMOD
443
+ if (TARGET SuiteSparse::SPQR)
444
+ if (TARGET SuiteSparse::CHOLMOD)
445
+ set_property (TARGET SuiteSparse::SPQR APPEND PROPERTY
446
+ INTERFACE_LINK_LIBRARIES SuiteSparse::CHOLMOD)
447
+ else (TARGET SuiteSparse::CHOLMOD)
448
+ # Consider SPQR not found if CHOLMOD cannot be found
449
+ set (SuiteSparse_SQPR_FOUND FALSE)
450
+ endif (TARGET SuiteSparse::CHOLMOD)
451
+ endif (TARGET SuiteSparse::SPQR)
452
+
453
+ # Add SuiteSparse::Config as dependency to all components
454
+ if (TARGET SuiteSparse::Config)
455
+ foreach (component IN LISTS SuiteSparse_FIND_COMPONENTS)
456
+ if (component STREQUAL Config)
457
+ continue ()
458
+ endif (component STREQUAL Config)
459
+
460
+ if (TARGET SuiteSparse::${component})
461
+ set_property (TARGET SuiteSparse::${component} APPEND PROPERTY
462
+ INTERFACE_LINK_LIBRARIES SuiteSparse::Config)
463
+ endif (TARGET SuiteSparse::${component})
464
+ endforeach (component IN LISTS SuiteSparse_FIND_COMPONENTS)
465
+ endif (TARGET SuiteSparse::Config)
466
+
467
+ suitesparse_reset_find_library_prefix()
468
+
469
+ # Handle REQUIRED and QUIET arguments to FIND_PACKAGE
470
+ include(FindPackageHandleStandardArgs)
471
+ if (SuiteSparse_FOUND)
472
+ find_package_handle_standard_args(SuiteSparse
473
+ REQUIRED_VARS ${SuiteSparse_REQUIRED_VARS}
474
+ VERSION_VAR SuiteSparse_VERSION
475
+ FAIL_MESSAGE "Failed to find some/all required components of SuiteSparse."
476
+ HANDLE_COMPONENTS)
477
+ else (SuiteSparse_FOUND)
478
+ # Do not pass VERSION_VAR to FindPackageHandleStandardArgs() if we failed to
479
+ # find SuiteSparse to avoid a confusing autogenerated failure message
480
+ # that states 'not found (missing: FOO) (found version: x.y.z)'.
481
+ find_package_handle_standard_args(SuiteSparse
482
+ REQUIRED_VARS ${SuiteSparse_REQUIRED_VARS}
483
+ FAIL_MESSAGE "Failed to find some/all required components of SuiteSparse."
484
+ HANDLE_COMPONENTS)
485
+ endif (SuiteSparse_FOUND)
486
+
487
+ # Pop CMP0057.
488
+ cmake_policy (POP)
include/ceres/autodiff_cost_function.h ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+ //
31
+ // Create CostFunctions as needed by the least squares framework, with
32
+ // Jacobians computed via automatic differentiation. For more
33
+ // information on automatic differentiation, see the wikipedia article
34
+ // at http://en.wikipedia.org/wiki/Automatic_differentiation
35
+ //
36
+ // To get an auto differentiated cost function, you must define a class with a
37
+ // templated operator() (a functor) that computes the cost function in terms of
38
+ // the template parameter T. The autodiff framework substitutes appropriate
39
+ // "jet" objects for T in order to compute the derivative when necessary, but
40
+ // this is hidden, and you should write the function as if T were a scalar type
41
+ // (e.g. a double-precision floating point number).
42
+ //
43
+ // The function must write the computed value in the last argument
44
+ // (the only non-const one) and return true to indicate
45
+ // success. Please see cost_function.h for details on how the return
46
+ // value maybe used to impose simple constraints on the parameter
47
+ // block.
48
+ //
49
+ // For example, consider a scalar error e = k - x'y, where both x and y are
50
+ // two-dimensional column vector parameters, the prime sign indicates
51
+ // transposition, and k is a constant. The form of this error, which is the
52
+ // difference between a constant and an expression, is a common pattern in least
53
+ // squares problems. For example, the value x'y might be the model expectation
54
+ // for a series of measurements, where there is an instance of the cost function
55
+ // for each measurement k.
56
+ //
57
+ // The actual cost added to the total problem is e^2, or (k - x'y)^2; however,
58
+ // the squaring is implicitly done by the optimization framework.
59
+ //
60
+ // To write an auto-differentiable cost function for the above model, first
61
+ // define the object
62
+ //
63
+ // class MyScalarCostFunctor {
64
+ // MyScalarCostFunctor(double k): k_(k) {}
65
+ //
66
+ // template <typename T>
67
+ // bool operator()(const T* const x , const T* const y, T* e) const {
68
+ // e[0] = T(k_) - x[0] * y[0] + x[1] * y[1];
69
+ // return true;
70
+ // }
71
+ //
72
+ // private:
73
+ // double k_;
74
+ // };
75
+ //
76
+ // Note that in the declaration of operator() the input parameters x and y come
77
+ // first, and are passed as const pointers to arrays of T. If there were three
78
+ // input parameters, then the third input parameter would come after y. The
79
+ // output is always the last parameter, and is also a pointer to an array. In
80
+ // the example above, e is a scalar, so only e[0] is set.
81
+ //
82
+ // Then given this class definition, the auto differentiated cost function for
83
+ // it can be constructed as follows.
84
+ //
85
+ // CostFunction* cost_function
86
+ // = new AutoDiffCostFunction<MyScalarCostFunctor, 1, 2, 2>(
87
+ // new MyScalarCostFunctor(1.0)); ^ ^ ^
88
+ // | | |
89
+ // Dimension of residual -----+ | |
90
+ // Dimension of x ---------------+ |
91
+ // Dimension of y ------------------+
92
+ //
93
+ // In this example, there is usually an instance for each measurement of k.
94
+ //
95
+ // In the instantiation above, the template parameters following
96
+ // "MyScalarCostFunctor", "1, 2, 2", describe the functor as computing a
97
+ // 1-dimensional output from two arguments, both 2-dimensional.
98
+ //
99
+ // AutoDiffCostFunction also supports cost functions with a
100
+ // runtime-determined number of residuals. For example:
101
+ //
102
+ // CostFunction* cost_function
103
+ // = new AutoDiffCostFunction<MyScalarCostFunctor, DYNAMIC, 2, 2>(
104
+ // new CostFunctorWithDynamicNumResiduals(1.0), ^ ^ ^
105
+ // runtime_number_of_residuals); <----+ | | |
106
+ // | | | |
107
+ // | | | |
108
+ // Actual number of residuals ------+ | | |
109
+ // Indicate dynamic number of residuals --------+ | |
110
+ // Dimension of x ------------------------------------+ |
111
+ // Dimension of y ---------------------------------------+
112
+ //
113
+ // WARNING #1: Since the functor will get instantiated with different types for
114
+ // T, you must convert from other numeric types to T before mixing
115
+ // computations with other variables of type T. In the example above, this is
116
+ // seen where instead of using k_ directly, k_ is wrapped with T(k_).
117
+ //
118
+ // WARNING #2: A common beginner's error when first using autodiff cost
119
+ // functions is to get the sizing wrong. In particular, there is a tendency to
120
+ // set the template parameters to (dimension of residual, number of parameters)
121
+ // instead of passing a dimension parameter for *every parameter*. In the
122
+ // example above, that would be <MyScalarCostFunctor, 1, 2>, which is missing
123
+ // the last '2' argument. Please be careful when setting the size parameters.
124
+
125
+ #ifndef CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
126
+ #define CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
127
+
128
+ #include <memory>
129
+
130
+ #include "ceres/internal/autodiff.h"
131
+ #include "ceres/sized_cost_function.h"
132
+ #include "ceres/types.h"
133
+ #include "glog/logging.h"
134
+
135
+ namespace ceres {
136
+
137
+ // A cost function which computes the derivative of the cost with respect to
138
+ // the parameters (a.k.a. the jacobian) using an auto differentiation framework.
139
+ // The first template argument is the functor object, described in the header
140
+ // comment. The second argument is the dimension of the residual (or
141
+ // ceres::DYNAMIC to indicate it will be set at runtime), and subsequent
142
+ // arguments describe the size of the Nth parameter, one per parameter.
143
+ //
144
+ // The constructors take ownership of the cost functor.
145
+ //
146
+ // If the number of residuals (argument kNumResiduals below) is
147
+ // ceres::DYNAMIC, then the two-argument constructor must be used. The
148
+ // second constructor takes a number of residuals (in addition to the
149
+ // templated number of residuals). This allows for varying the number
150
+ // of residuals for a single autodiff cost function at runtime.
151
+ template <typename CostFunctor,
152
+ int kNumResiduals, // Number of residuals, or ceres::DYNAMIC.
153
+ int... Ns> // Number of parameters in each parameter block.
154
+ class AutoDiffCostFunction final
155
+ : public SizedCostFunction<kNumResiduals, Ns...> {
156
+ public:
157
+ // Takes ownership of functor by default. Uses the template-provided
158
+ // value for the number of residuals ("kNumResiduals").
159
+ explicit AutoDiffCostFunction(CostFunctor* functor,
160
+ Ownership ownership = TAKE_OWNERSHIP)
161
+ : functor_(functor), ownership_(ownership) {
162
+ static_assert(kNumResiduals != DYNAMIC,
163
+ "Can't run the fixed-size constructor if the number of "
164
+ "residuals is set to ceres::DYNAMIC.");
165
+ }
166
+
167
+ // Takes ownership of functor by default. Ignores the template-provided
168
+ // kNumResiduals in favor of the "num_residuals" argument provided.
169
+ //
170
+ // This allows for having autodiff cost functions which return varying
171
+ // numbers of residuals at runtime.
172
+ AutoDiffCostFunction(CostFunctor* functor,
173
+ int num_residuals,
174
+ Ownership ownership = TAKE_OWNERSHIP)
175
+ : functor_(functor), ownership_(ownership) {
176
+ static_assert(kNumResiduals == DYNAMIC,
177
+ "Can't run the dynamic-size constructor if the number of "
178
+ "residuals is not ceres::DYNAMIC.");
179
+ SizedCostFunction<kNumResiduals, Ns...>::set_num_residuals(num_residuals);
180
+ }
181
+
182
+ AutoDiffCostFunction(AutoDiffCostFunction&& other)
183
+ : functor_(std::move(other.functor_)), ownership_(other.ownership_) {}
184
+
185
+ virtual ~AutoDiffCostFunction() {
186
+ // Manually release pointer if configured to not take ownership rather than
187
+ // deleting only if ownership is taken.
188
+ // This is to stay maximally compatible to old user code which may have
189
+ // forgotten to implement a virtual destructor, from when the
190
+ // AutoDiffCostFunction always took ownership.
191
+ if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
192
+ functor_.release();
193
+ }
194
+ }
195
+
196
+ // Implementation details follow; clients of the autodiff cost function should
197
+ // not have to examine below here.
198
+ //
199
+ // To handle variadic cost functions, some template magic is needed. It's
200
+ // mostly hidden inside autodiff.h.
201
+ bool Evaluate(double const* const* parameters,
202
+ double* residuals,
203
+ double** jacobians) const override {
204
+ using ParameterDims =
205
+ typename SizedCostFunction<kNumResiduals, Ns...>::ParameterDims;
206
+
207
+ if (!jacobians) {
208
+ return internal::VariadicEvaluate<ParameterDims>(
209
+ *functor_, parameters, residuals);
210
+ }
211
+ return internal::AutoDifferentiate<kNumResiduals, ParameterDims>(
212
+ *functor_,
213
+ parameters,
214
+ SizedCostFunction<kNumResiduals, Ns...>::num_residuals(),
215
+ residuals,
216
+ jacobians);
217
+ };
218
+
219
+ const CostFunctor& functor() const { return *functor_; }
220
+
221
+ private:
222
+ std::unique_ptr<CostFunctor> functor_;
223
+ Ownership ownership_;
224
+ };
225
+
226
+ } // namespace ceres
227
+
228
+ #endif // CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
include/ceres/autodiff_first_order_function.h ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+
31
+ #ifndef CERES_PUBLIC_AUTODIFF_FIRST_ORDER_FUNCTION_H_
32
+ #define CERES_PUBLIC_AUTODIFF_FIRST_ORDER_FUNCTION_H_
33
+
34
+ #include <memory>
35
+
36
+ #include "ceres/first_order_function.h"
37
+ #include "ceres/internal/eigen.h"
38
+ #include "ceres/internal/fixed_array.h"
39
+ #include "ceres/jet.h"
40
+ #include "ceres/types.h"
41
+
42
+ namespace ceres {
43
+
44
+ // Create FirstOrderFunctions as needed by the GradientProblem
45
+ // framework, with gradients computed via automatic
46
+ // differentiation. For more information on automatic differentiation,
47
+ // see the wikipedia article at
48
+ // http://en.wikipedia.org/wiki/Automatic_differentiation
49
+ //
50
+ // To get an auto differentiated function, you must define a class
51
+ // with a templated operator() (a functor) that computes the cost
52
+ // function in terms of the template parameter T. The autodiff
53
+ // framework substitutes appropriate "jet" objects for T in order to
54
+ // compute the derivative when necessary, but this is hidden, and you
55
+ // should write the function as if T were a scalar type (e.g. a
56
+ // double-precision floating point number).
57
+ //
58
+ // The function must write the computed value in the last argument
59
+ // (the only non-const one) and return true to indicate
60
+ // success.
61
+ //
62
+ // For example, consider a scalar error e = x'y - a, where both x and y are
63
+ // two-dimensional column vector parameters, the prime sign indicates
64
+ // transposition, and a is a constant.
65
+ //
66
+ // To write an auto-differentiable FirstOrderFunction for the above model, first
67
+ // define the object
68
+ //
69
+ // class QuadraticCostFunctor {
70
+ // public:
71
+ // explicit QuadraticCostFunctor(double a) : a_(a) {}
72
+ // template <typename T>
73
+ // bool operator()(const T* const xy, T* cost) const {
74
+ // const T* const x = xy;
75
+ // const T* const y = xy + 2;
76
+ // *cost = x[0] * y[0] + x[1] * y[1] - T(a_);
77
+ // return true;
78
+ // }
79
+ //
80
+ // private:
81
+ // double a_;
82
+ // };
83
+ //
84
+ // Note that in the declaration of operator() the input parameters xy come
85
+ // first, and are passed as const pointers to arrays of T. The
86
+ // output is the last parameter.
87
+ //
88
+ // Then given this class definition, the auto differentiated FirstOrderFunction
89
+ // for it can be constructed as follows.
90
+ //
91
+ // FirstOrderFunction* function =
92
+ // new AutoDiffFirstOrderFunction<QuadraticCostFunctor, 4>(
93
+ // new QuadraticCostFunctor(1.0)));
94
+ //
95
+ // In the instantiation above, the template parameters following
96
+ // "QuadraticCostFunctor", "4", describe the functor as computing a
97
+ // 1-dimensional output from a four dimensional vector.
98
+ //
99
+ // WARNING: Since the functor will get instantiated with different types for
100
+ // T, you must convert from other numeric types to T before mixing
101
+ // computations with other variables of type T. In the example above, this is
102
+ // seen where instead of using a_ directly, a_ is wrapped with T(a_).
103
+
104
+ template <typename FirstOrderFunctor, int kNumParameters>
105
+ class AutoDiffFirstOrderFunction final : public FirstOrderFunction {
106
+ public:
107
+ // Takes ownership of functor.
108
+ explicit AutoDiffFirstOrderFunction(FirstOrderFunctor* functor)
109
+ : functor_(functor) {
110
+ static_assert(kNumParameters > 0, "kNumParameters must be positive");
111
+ }
112
+
113
+ bool Evaluate(const double* const parameters,
114
+ double* cost,
115
+ double* gradient) const override {
116
+ if (gradient == nullptr) {
117
+ return (*functor_)(parameters, cost);
118
+ }
119
+
120
+ using JetT = Jet<double, kNumParameters>;
121
+ internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(kNumParameters);
122
+ for (int i = 0; i < kNumParameters; ++i) {
123
+ x[i].a = parameters[i];
124
+ x[i].v.setZero();
125
+ x[i].v[i] = 1.0;
126
+ }
127
+
128
+ JetT output;
129
+ output.a = kImpossibleValue;
130
+ output.v.setConstant(kImpossibleValue);
131
+
132
+ if (!(*functor_)(x.data(), &output)) {
133
+ return false;
134
+ }
135
+
136
+ *cost = output.a;
137
+ VectorRef(gradient, kNumParameters) = output.v;
138
+ return true;
139
+ }
140
+
141
+ int NumParameters() const override { return kNumParameters; }
142
+
143
+ const FirstOrderFunctor& functor() const { return *functor_; }
144
+
145
+ private:
146
+ std::unique_ptr<FirstOrderFunctor> functor_;
147
+ };
148
+
149
+ } // namespace ceres
150
+
151
+ #endif // CERES_PUBLIC_AUTODIFF_FIRST_ORDER_FUNCTION_H_
include/ceres/autodiff_local_parameterization.h ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sergey.vfx@gmail.com (Sergey Sharybin)
30
+ // mierle@gmail.com (Keir Mierle)
31
+ // sameeragarwal@google.com (Sameer Agarwal)
32
+
33
+ #ifndef CERES_PUBLIC_AUTODIFF_LOCAL_PARAMETERIZATION_H_
34
+ #define CERES_PUBLIC_AUTODIFF_LOCAL_PARAMETERIZATION_H_
35
+
36
+ #include <memory>
37
+
38
+ #include "ceres/internal/autodiff.h"
39
+ #include "ceres/local_parameterization.h"
40
+
41
+ namespace ceres {
42
+
43
+ // WARNING: LocalParameterizations are deprecated, so is
44
+ // AutoDiffLocalParameterization. They will be removed from Ceres Solver in
45
+ // version 2.2.0. Please use Manifolds and AutoDiffManifold instead.
46
+
47
+ // Create local parameterization with Jacobians computed via automatic
48
+ // differentiation. For more information on local parameterizations,
49
+ // see include/ceres/local_parameterization.h
50
+ //
51
+ // To get an auto differentiated local parameterization, you must define
52
+ // a class with a templated operator() (a functor) that computes
53
+ //
54
+ // x_plus_delta = Plus(x, delta);
55
+ //
56
+ // the template parameter T. The autodiff framework substitutes appropriate
57
+ // "Jet" objects for T in order to compute the derivative when necessary, but
58
+ // this is hidden, and you should write the function as if T were a scalar type
59
+ // (e.g. a double-precision floating point number).
60
+ //
61
+ // The function must write the computed value in the last argument (the only
62
+ // non-const one) and return true to indicate success.
63
+ //
64
+ // For example, Quaternions have a three dimensional local
65
+ // parameterization. It's plus operation can be implemented as (taken
66
+ // from internal/ceres/auto_diff_local_parameterization_test.cc)
67
+ //
68
+ // struct QuaternionPlus {
69
+ // template<typename T>
70
+ // bool operator()(const T* x, const T* delta, T* x_plus_delta) const {
71
+ // const T squared_norm_delta =
72
+ // delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2];
73
+ //
74
+ // T q_delta[4];
75
+ // if (squared_norm_delta > T(0.0)) {
76
+ // T norm_delta = sqrt(squared_norm_delta);
77
+ // const T sin_delta_by_delta = sin(norm_delta) / norm_delta;
78
+ // q_delta[0] = cos(norm_delta);
79
+ // q_delta[1] = sin_delta_by_delta * delta[0];
80
+ // q_delta[2] = sin_delta_by_delta * delta[1];
81
+ // q_delta[3] = sin_delta_by_delta * delta[2];
82
+ // } else {
83
+ // // We do not just use q_delta = [1,0,0,0] here because that is a
84
+ // // constant and when used for automatic differentiation will
85
+ // // lead to a zero derivative. Instead we take a first order
86
+ // // approximation and evaluate it at zero.
87
+ // q_delta[0] = T(1.0);
88
+ // q_delta[1] = delta[0];
89
+ // q_delta[2] = delta[1];
90
+ // q_delta[3] = delta[2];
91
+ // }
92
+ //
93
+ // QuaternionProduct(q_delta, x, x_plus_delta);
94
+ // return true;
95
+ // }
96
+ // };
97
+ //
98
+ // Then given this struct, the auto differentiated local
99
+ // parameterization can now be constructed as
100
+ //
101
+ // LocalParameterization* local_parameterization =
102
+ // new AutoDiffLocalParameterization<QuaternionPlus, 4, 3>;
103
+ // | |
104
+ // Global Size ---------------+ |
105
+ // Local Size -------------------+
106
+ //
107
+ // WARNING: Since the functor will get instantiated with different types for
108
+ // T, you must to convert from other numeric types to T before mixing
109
+ // computations with other variables of type T. In the example above, this is
110
+ // seen where instead of using k_ directly, k_ is wrapped with T(k_).
111
+
112
+ template <typename Functor, int kGlobalSize, int kLocalSize>
113
+ class CERES_DEPRECATED_WITH_MSG("Use AutoDiffManifold instead.")
114
+ AutoDiffLocalParameterization : public LocalParameterization {
115
+ public:
116
+ AutoDiffLocalParameterization() : functor_(new Functor()) {}
117
+
118
+ // Takes ownership of functor.
119
+ explicit AutoDiffLocalParameterization(Functor* functor)
120
+ : functor_(functor) {}
121
+
122
+ bool Plus(const double* x,
123
+ const double* delta,
124
+ double* x_plus_delta) const override {
125
+ return (*functor_)(x, delta, x_plus_delta);
126
+ }
127
+
128
+ bool ComputeJacobian(const double* x, double* jacobian) const override {
129
+ double zero_delta[kLocalSize];
130
+ for (int i = 0; i < kLocalSize; ++i) {
131
+ zero_delta[i] = 0.0;
132
+ }
133
+
134
+ double x_plus_delta[kGlobalSize];
135
+ for (int i = 0; i < kGlobalSize; ++i) {
136
+ x_plus_delta[i] = 0.0;
137
+ }
138
+
139
+ const double* parameter_ptrs[2] = {x, zero_delta};
140
+ double* jacobian_ptrs[2] = {nullptr, jacobian};
141
+ return internal::AutoDifferentiate<
142
+ kGlobalSize,
143
+ internal::StaticParameterDims<kGlobalSize, kLocalSize>>(
144
+ *functor_, parameter_ptrs, kGlobalSize, x_plus_delta, jacobian_ptrs);
145
+ }
146
+
147
+ int GlobalSize() const override { return kGlobalSize; }
148
+ int LocalSize() const override { return kLocalSize; }
149
+
150
+ const Functor& functor() const { return *functor_; }
151
+
152
+ private:
153
+ std::unique_ptr<Functor> functor_;
154
+ };
155
+
156
+ } // namespace ceres
157
+
158
+ #endif // CERES_PUBLIC_AUTODIFF_LOCAL_PARAMETERIZATION_H_
include/ceres/autodiff_manifold.h ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2022 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+
31
+ #ifndef CERES_PUBLIC_AUTODIFF_MANIFOLD_H_
32
+ #define CERES_PUBLIC_AUTODIFF_MANIFOLD_H_
33
+
34
+ #include <memory>
35
+
36
+ #include "ceres/internal/autodiff.h"
37
+ #include "ceres/manifold.h"
38
+
39
+ namespace ceres {
40
+
41
+ // Create a Manifold with Jacobians computed via automatic differentiation. For
42
+ // more information on manifolds, see include/ceres/manifold.h
43
+ //
44
+ // To get an auto differentiated manifold, you must define a class/struct with
45
+ // templated Plus and Minus functions that compute
46
+ //
47
+ // x_plus_delta = Plus(x, delta);
48
+ // y_minus_x = Minus(y, x);
49
+ //
50
+ // Where, x, y and x_plus_y are vectors on the manifold in the ambient space (so
51
+ // they are kAmbientSize vectors) and delta, y_minus_x are vectors in the
52
+ // tangent space (so they are kTangentSize vectors).
53
+ //
54
+ // The Functor should have the signature:
55
+ //
56
+ // struct Functor {
57
+ // template <typename T>
58
+ // bool Plus(const T* x, const T* delta, T* x_plus_delta) const;
59
+ //
60
+ // template <typename T>
61
+ // bool Minus(const T* y, const T* x, T* y_minus_x) const;
62
+ // };
63
+ //
64
+ // Observe that the Plus and Minus operations are templated on the parameter T.
65
+ // The autodiff framework substitutes appropriate "Jet" objects for T in order
66
+ // to compute the derivative when necessary. This is the same mechanism that is
67
+ // used to compute derivatives when using AutoDiffCostFunction.
68
+ //
69
+ // Plus and Minus should return true if the computation is successful and false
70
+ // otherwise, in which case the result will not be used.
71
+ //
72
+ // Given this Functor, the corresponding Manifold can be constructed as:
73
+ //
74
+ // AutoDiffManifold<Functor, kAmbientSize, kTangentSize> manifold;
75
+ //
76
+ // As a concrete example consider the case of Quaternions. Quaternions form a
77
+ // three dimensional manifold embedded in R^4, i.e. they have an ambient
78
+ // dimension of 4 and their tangent space has dimension 3. The following Functor
79
+ // (taken from autodiff_manifold_test.cc) defines the Plus and Minus operations
80
+ // on the Quaternion manifold:
81
+ //
82
+ // NOTE: The following is only used for illustration purposes. Ceres Solver
83
+ // ships with optimized production grade QuaternionManifold implementation. See
84
+ // manifold.h.
85
+ //
86
+ // This functor assumes that the quaternions are laid out as [w,x,y,z] in
87
+ // memory, i.e. the real or scalar part is the first coordinate.
88
+ //
89
+ // struct QuaternionFunctor {
90
+ // template <typename T>
91
+ // bool Plus(const T* x, const T* delta, T* x_plus_delta) const {
92
+ // const T squared_norm_delta =
93
+ // delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2];
94
+ //
95
+ // T q_delta[4];
96
+ // if (squared_norm_delta > T(0.0)) {
97
+ // T norm_delta = sqrt(squared_norm_delta);
98
+ // const T sin_delta_by_delta = sin(norm_delta) / norm_delta;
99
+ // q_delta[0] = cos(norm_delta);
100
+ // q_delta[1] = sin_delta_by_delta * delta[0];
101
+ // q_delta[2] = sin_delta_by_delta * delta[1];
102
+ // q_delta[3] = sin_delta_by_delta * delta[2];
103
+ // } else {
104
+ // // We do not just use q_delta = [1,0,0,0] here because that is a
105
+ // // constant and when used for automatic differentiation will
106
+ // // lead to a zero derivative. Instead we take a first order
107
+ // // approximation and evaluate it at zero.
108
+ // q_delta[0] = T(1.0);
109
+ // q_delta[1] = delta[0];
110
+ // q_delta[2] = delta[1];
111
+ // q_delta[3] = delta[2];
112
+ // }
113
+ //
114
+ // QuaternionProduct(q_delta, x, x_plus_delta);
115
+ // return true;
116
+ // }
117
+ //
118
+ // template <typename T>
119
+ // bool Minus(const T* y, const T* x, T* y_minus_x) const {
120
+ // T minus_x[4] = {x[0], -x[1], -x[2], -x[3]};
121
+ // T ambient_y_minus_x[4];
122
+ // QuaternionProduct(y, minus_x, ambient_y_minus_x);
123
+ // T u_norm = sqrt(ambient_y_minus_x[1] * ambient_y_minus_x[1] +
124
+ // ambient_y_minus_x[2] * ambient_y_minus_x[2] +
125
+ // ambient_y_minus_x[3] * ambient_y_minus_x[3]);
126
+ // if (u_norm > 0.0) {
127
+ // T theta = atan2(u_norm, ambient_y_minus_x[0]);
128
+ // y_minus_x[0] = theta * ambient_y_minus_x[1] / u_norm;
129
+ // y_minus_x[1] = theta * ambient_y_minus_x[2] / u_norm;
130
+ // y_minus_x[2] = theta * ambient_y_minus_x[3] / u_norm;
131
+ // } else {
132
+ // // We do not use [0,0,0] here because even though the value part is
133
+ // // a constant, the derivative part is not.
134
+ // y_minus_x[0] = ambient_y_minus_x[1];
135
+ // y_minus_x[1] = ambient_y_minus_x[2];
136
+ // y_minus_x[2] = ambient_y_minus_x[3];
137
+ // }
138
+ // return true;
139
+ // }
140
+ // };
141
+ //
142
+ // Then given this struct, the auto differentiated Quaternion Manifold can now
143
+ // be constructed as
144
+ //
145
+ // Manifold* manifold = new AutoDiffManifold<QuaternionFunctor, 4, 3>;
146
+
147
+ template <typename Functor, int kAmbientSize, int kTangentSize>
148
+ class AutoDiffManifold final : public Manifold {
149
+ public:
150
+ AutoDiffManifold() : functor_(std::make_unique<Functor>()) {}
151
+
152
+ // Takes ownership of functor.
153
+ explicit AutoDiffManifold(Functor* functor) : functor_(functor) {}
154
+
155
+ int AmbientSize() const override { return kAmbientSize; }
156
+ int TangentSize() const override { return kTangentSize; }
157
+
158
+ bool Plus(const double* x,
159
+ const double* delta,
160
+ double* x_plus_delta) const override {
161
+ return functor_->Plus(x, delta, x_plus_delta);
162
+ }
163
+
164
+ bool PlusJacobian(const double* x, double* jacobian) const override;
165
+
166
+ bool Minus(const double* y,
167
+ const double* x,
168
+ double* y_minus_x) const override {
169
+ return functor_->Minus(y, x, y_minus_x);
170
+ }
171
+
172
+ bool MinusJacobian(const double* x, double* jacobian) const override;
173
+
174
+ const Functor& functor() const { return *functor_; }
175
+
176
+ private:
177
+ std::unique_ptr<Functor> functor_;
178
+ };
179
+
180
+ namespace internal {
181
+
182
+ // The following two helper structs are needed to interface the Plus and Minus
183
+ // methods of the ManifoldFunctor with the automatic differentiation which
184
+ // expects a Functor with operator().
185
+ template <typename Functor>
186
+ struct PlusWrapper {
187
+ explicit PlusWrapper(const Functor& functor) : functor(functor) {}
188
+ template <typename T>
189
+ bool operator()(const T* x, const T* delta, T* x_plus_delta) const {
190
+ return functor.Plus(x, delta, x_plus_delta);
191
+ }
192
+ const Functor& functor;
193
+ };
194
+
195
+ template <typename Functor>
196
+ struct MinusWrapper {
197
+ explicit MinusWrapper(const Functor& functor) : functor(functor) {}
198
+ template <typename T>
199
+ bool operator()(const T* y, const T* x, T* y_minus_x) const {
200
+ return functor.Minus(y, x, y_minus_x);
201
+ }
202
+ const Functor& functor;
203
+ };
204
+ } // namespace internal
205
+
206
+ template <typename Functor, int kAmbientSize, int kTangentSize>
207
+ bool AutoDiffManifold<Functor, kAmbientSize, kTangentSize>::PlusJacobian(
208
+ const double* x, double* jacobian) const {
209
+ double zero_delta[kTangentSize];
210
+ for (int i = 0; i < kTangentSize; ++i) {
211
+ zero_delta[i] = 0.0;
212
+ }
213
+
214
+ double x_plus_delta[kAmbientSize];
215
+ for (int i = 0; i < kAmbientSize; ++i) {
216
+ x_plus_delta[i] = 0.0;
217
+ }
218
+
219
+ const double* parameter_ptrs[2] = {x, zero_delta};
220
+
221
+ // PlusJacobian is D_2 Plus(x,0) so we only need to compute the Jacobian
222
+ // w.r.t. the second argument.
223
+ double* jacobian_ptrs[2] = {nullptr, jacobian};
224
+ return internal::AutoDifferentiate<
225
+ kAmbientSize,
226
+ internal::StaticParameterDims<kAmbientSize, kTangentSize>>(
227
+ internal::PlusWrapper<Functor>(*functor_),
228
+ parameter_ptrs,
229
+ kAmbientSize,
230
+ x_plus_delta,
231
+ jacobian_ptrs);
232
+ }
233
+
234
+ template <typename Functor, int kAmbientSize, int kTangentSize>
235
+ bool AutoDiffManifold<Functor, kAmbientSize, kTangentSize>::MinusJacobian(
236
+ const double* x, double* jacobian) const {
237
+ double y_minus_x[kTangentSize];
238
+ for (int i = 0; i < kTangentSize; ++i) {
239
+ y_minus_x[i] = 0.0;
240
+ }
241
+
242
+ const double* parameter_ptrs[2] = {x, x};
243
+
244
+ // MinusJacobian is D_1 Minus(x,x), so we only need to compute the Jacobian
245
+ // w.r.t. the first argument.
246
+ double* jacobian_ptrs[2] = {jacobian, nullptr};
247
+ return internal::AutoDifferentiate<
248
+ kTangentSize,
249
+ internal::StaticParameterDims<kAmbientSize, kAmbientSize>>(
250
+ internal::MinusWrapper<Functor>(*functor_),
251
+ parameter_ptrs,
252
+ kTangentSize,
253
+ y_minus_x,
254
+ jacobian_ptrs);
255
+ }
256
+
257
+ } // namespace ceres
258
+
259
+ #endif // CERES_PUBLIC_AUTODIFF_MANIFOLD_H_
include/ceres/c_api.h ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Ceres Solver - A fast non-linear least squares minimizer
2
+ * Copyright 2019 Google Inc. All rights reserved.
3
+ * http://ceres-solver.org/
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * - Redistributions of source code must retain the above copyright notice,
9
+ * this list of conditions and the following disclaimer.
10
+ * - Redistributions in binary form must reproduce the above copyright notice,
11
+ * this list of conditions and the following disclaimer in the documentation
12
+ * and/or other materials provided with the distribution.
13
+ * - Neither the name of Google Inc. nor the names of its contributors may be
14
+ * used to endorse or promote products derived from this software without
15
+ * specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ * POSSIBILITY OF SUCH DAMAGE.
28
+ *
29
+ * Author: mierle@gmail.com (Keir Mierle)
30
+ *
31
+ * A minimal C API for Ceres. Not all functionality is included. This API is
32
+ * not intended for clients of Ceres, but is instead intended for easing the
33
+ * process of binding Ceres to other languages.
34
+ *
35
+ * Currently this is a work in progress.
36
+ */
37
+
38
+ #ifndef CERES_PUBLIC_C_API_H_
39
+ #define CERES_PUBLIC_C_API_H_
40
+
41
+ // clang-format off
42
+ #include "ceres/internal/export.h"
43
+ #include "ceres/internal/disable_warnings.h"
44
+ // clang-format on
45
+
46
+ #ifdef __cplusplus
47
+ extern "C" {
48
+ #endif
49
+
50
+ /* Init the Ceres private data. Must be called before anything else. */
51
+ CERES_EXPORT void ceres_init();
52
+
53
+ /* Equivalent to CostFunction::Evaluate() in the C++ API.
54
+ *
55
+ * The user may keep private information inside the opaque user_data object.
56
+ * The pointer here is the same one passed in the ceres_add_residual_block().
57
+ */
58
+ typedef int (*ceres_cost_function_t)(void* user_data,
59
+ double** parameters,
60
+ double* residuals,
61
+ double** jacobians);
62
+
63
+ /* Equivalent to LossFunction::Evaluate() from the C++ API. */
64
+ typedef void (*ceres_loss_function_t)(void* user_data,
65
+ double squared_norm,
66
+ double out[3]);
67
+
68
+ /* Create callback data for Ceres' stock loss functions.
69
+ *
70
+ * Ceres has several loss functions available by default, and these functions
71
+ * expose those to the C API. To use the stock loss functions, call
72
+ * ceres_create_*_loss_data(), which internally creates an instance of one of
73
+ * the stock loss functions (for example ceres::CauchyLoss), and pass the
74
+ * returned "loss_function_data" along with the ceres_stock_loss_function to
75
+ * ceres_add_residual_block().
76
+ *
77
+ * For example:
78
+ *
79
+ * void* cauchy_loss_function_data =
80
+ * ceres_create_cauchy_loss_function_data(1.2, 0.0);
81
+ * ceres_problem_add_residual_block(
82
+ * problem,
83
+ * my_cost_function,
84
+ * my_cost_function_data,
85
+ * ceres_stock_loss_function,
86
+ * cauchy_loss_function_data,
87
+ * 1,
88
+ * 2,
89
+ * parameter_sizes,
90
+ * parameter_pointers);
91
+ * ...
92
+ * ceres_free_stock_loss_function_data(cauchy_loss_function_data);
93
+ *
94
+ * See loss_function.h for the details of each loss function.
95
+ */
96
+ CERES_EXPORT void* ceres_create_huber_loss_function_data(double a);
97
+ CERES_EXPORT void* ceres_create_softl1_loss_function_data(double a);
98
+ CERES_EXPORT void* ceres_create_cauchy_loss_function_data(double a);
99
+ CERES_EXPORT void* ceres_create_arctan_loss_function_data(double a);
100
+ CERES_EXPORT void* ceres_create_tolerant_loss_function_data(double a, double b);
101
+
102
+ /* Free the given stock loss function data. */
103
+ CERES_EXPORT void ceres_free_stock_loss_function_data(void* loss_function_data);
104
+
105
+ /* This is an implementation of ceres_loss_function_t contained within Ceres
106
+ * itself, intended as a way to access the various stock Ceres loss functions
107
+ * from the C API. This should be passed to ceres_add_residual() below, in
108
+ * combination with a user_data pointer generated by
109
+ * ceres_create_stock_loss_function() above. */
110
+ CERES_EXPORT void ceres_stock_loss_function(void* user_data,
111
+ double squared_norm,
112
+ double out[3]);
113
+
114
+ /* Equivalent to Problem from the C++ API. */
115
+ struct ceres_problem_s;
116
+ typedef struct ceres_problem_s ceres_problem_t;
117
+
118
+ struct ceres_residual_block_id_s;
119
+ typedef struct ceres_residual_block_id_s ceres_residual_block_id_t;
120
+
121
+ /* Create and destroy a problem */
122
+ /* TODO(keir): Add options for the problem. */
123
+ CERES_EXPORT ceres_problem_t* ceres_create_problem();
124
+ CERES_EXPORT void ceres_free_problem(ceres_problem_t* problem);
125
+
126
+ /* Add a residual block. */
127
+ CERES_EXPORT ceres_residual_block_id_t* ceres_problem_add_residual_block(
128
+ ceres_problem_t* problem,
129
+ ceres_cost_function_t cost_function,
130
+ void* cost_function_data,
131
+ ceres_loss_function_t loss_function,
132
+ void* loss_function_data,
133
+ int num_residuals,
134
+ int num_parameter_blocks,
135
+ int* parameter_block_sizes,
136
+ double** parameters);
137
+
138
+ CERES_EXPORT void ceres_solve(ceres_problem_t* problem);
139
+
140
+ /* TODO(keir): Figure out a way to pass a config in. */
141
+
142
+ #ifdef __cplusplus
143
+ }
144
+ #endif
145
+
146
+ #include "ceres/internal/reenable_warnings.h"
147
+
148
+ #endif /* CERES_PUBLIC_C_API_H_ */
include/ceres/ceres.h ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2022 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: keir@google.com (Keir Mierle)
30
+ //
31
+ // This is a forwarding header containing the public symbols exported from
32
+ // Ceres. Anything in the "ceres" namespace is available for use.
33
+
34
+ #ifndef CERES_PUBLIC_CERES_H_
35
+ #define CERES_PUBLIC_CERES_H_
36
+
37
+ #include "ceres/autodiff_cost_function.h"
38
+ #include "ceres/autodiff_first_order_function.h"
39
+ #include "ceres/autodiff_local_parameterization.h"
40
+ #include "ceres/autodiff_manifold.h"
41
+ #include "ceres/conditioned_cost_function.h"
42
+ #include "ceres/context.h"
43
+ #include "ceres/cost_function.h"
44
+ #include "ceres/cost_function_to_functor.h"
45
+ #include "ceres/covariance.h"
46
+ #include "ceres/crs_matrix.h"
47
+ #include "ceres/dynamic_autodiff_cost_function.h"
48
+ #include "ceres/dynamic_cost_function.h"
49
+ #include "ceres/dynamic_cost_function_to_functor.h"
50
+ #include "ceres/dynamic_numeric_diff_cost_function.h"
51
+ #include "ceres/evaluation_callback.h"
52
+ #include "ceres/first_order_function.h"
53
+ #include "ceres/gradient_checker.h"
54
+ #include "ceres/gradient_problem.h"
55
+ #include "ceres/gradient_problem_solver.h"
56
+ #include "ceres/iteration_callback.h"
57
+ #include "ceres/jet.h"
58
+ #include "ceres/line_manifold.h"
59
+ #include "ceres/local_parameterization.h"
60
+ #include "ceres/loss_function.h"
61
+ #include "ceres/manifold.h"
62
+ #include "ceres/numeric_diff_cost_function.h"
63
+ #include "ceres/numeric_diff_first_order_function.h"
64
+ #include "ceres/numeric_diff_options.h"
65
+ #include "ceres/ordered_groups.h"
66
+ #include "ceres/problem.h"
67
+ #include "ceres/product_manifold.h"
68
+ #include "ceres/sized_cost_function.h"
69
+ #include "ceres/solver.h"
70
+ #include "ceres/sphere_manifold.h"
71
+ #include "ceres/types.h"
72
+ #include "ceres/version.h"
73
+
74
+ #endif // CERES_PUBLIC_CERES_H_
include/ceres/conditioned_cost_function.h ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: wjr@google.com (William Rucklidge)
30
+ //
31
+ // This file contains a cost function that can apply a transformation to
32
+ // each residual value before they are square-summed.
33
+
34
+ #ifndef CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_
35
+ #define CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_
36
+
37
+ #include <memory>
38
+ #include <vector>
39
+
40
+ #include "ceres/cost_function.h"
41
+ #include "ceres/internal/disable_warnings.h"
42
+ #include "ceres/types.h"
43
+
44
+ namespace ceres {
45
+
46
+ // This class allows you to apply different conditioning to the residual
47
+ // values of a wrapped cost function. An example where this is useful is
48
+ // where you have an existing cost function that produces N values, but you
49
+ // want the total cost to be something other than just the sum of these
50
+ // squared values - maybe you want to apply a different scaling to some
51
+ // values, to change their contribution to the cost.
52
+ //
53
+ // Usage:
54
+ //
55
+ // // my_cost_function produces N residuals
56
+ // CostFunction* my_cost_function = ...
57
+ // CHECK_EQ(N, my_cost_function->num_residuals());
58
+ // vector<CostFunction*> conditioners;
59
+ //
60
+ // // Make N 1x1 cost functions (1 parameter, 1 residual)
61
+ // CostFunction* f_1 = ...
62
+ // conditioners.push_back(f_1);
63
+ // ...
64
+ // CostFunction* f_N = ...
65
+ // conditioners.push_back(f_N);
66
+ // ConditionedCostFunction* ccf =
67
+ // new ConditionedCostFunction(my_cost_function, conditioners);
68
+ //
69
+ // Now ccf's residual i (i=0..N-1) will be passed though the i'th conditioner.
70
+ //
71
+ // ccf_residual[i] = f_i(my_cost_function_residual[i])
72
+ //
73
+ // and the Jacobian will be affected appropriately.
74
+ class CERES_EXPORT ConditionedCostFunction final : public CostFunction {
75
+ public:
76
+ // Builds a cost function based on a wrapped cost function, and a
77
+ // per-residual conditioner. Takes ownership of all of the wrapped cost
78
+ // functions, or not, depending on the ownership parameter. Conditioners
79
+ // may be nullptr, in which case the corresponding residual is not modified.
80
+ //
81
+ // The conditioners can repeat.
82
+ ConditionedCostFunction(CostFunction* wrapped_cost_function,
83
+ const std::vector<CostFunction*>& conditioners,
84
+ Ownership ownership);
85
+ ~ConditionedCostFunction() override;
86
+
87
+ bool Evaluate(double const* const* parameters,
88
+ double* residuals,
89
+ double** jacobians) const override;
90
+
91
+ private:
92
+ std::unique_ptr<CostFunction> wrapped_cost_function_;
93
+ std::vector<CostFunction*> conditioners_;
94
+ Ownership ownership_;
95
+ };
96
+
97
+ } // namespace ceres
98
+
99
+ #include "ceres/internal/reenable_warnings.h"
100
+
101
+ #endif // CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_
include/ceres/context.h ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: vitus@google.com (Michael Vitus)
30
+
31
+ #ifndef CERES_PUBLIC_CONTEXT_H_
32
+ #define CERES_PUBLIC_CONTEXT_H_
33
+
34
+ #include "ceres/internal/export.h"
35
+
36
+ namespace ceres {
37
+
38
+ // A global context for processing data in Ceres. This provides a mechanism to
39
+ // allow Ceres to reuse items that are expensive to create between multiple
40
+ // calls; for example, thread pools. The same Context can be used on multiple
41
+ // Problems, either serially or in parallel. When using it with multiple
42
+ // Problems at the same time, they may end up contending for resources
43
+ // (e.g. threads) managed by the Context.
44
+ class CERES_EXPORT Context {
45
+ public:
46
+ Context();
47
+ Context(const Context&) = delete;
48
+ void operator=(const Context&) = delete;
49
+
50
+ virtual ~Context();
51
+
52
+ // Creates a context object and the caller takes ownership.
53
+ static Context* Create();
54
+ };
55
+
56
+ } // namespace ceres
57
+
58
+ #endif // CERES_PUBLIC_CONTEXT_H_
include/ceres/cost_function.h ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+ // keir@google.m (Keir Mierle)
31
+ //
32
+ // This is the interface through which the least squares solver accesses the
33
+ // residual and Jacobian of the least squares problem. Users are expected to
34
+ // subclass CostFunction to define their own terms in the least squares problem.
35
+ //
36
+ // It is recommended that users define templated residual functors for use as
37
+ // arguments for AutoDiffCostFunction (see autodiff_cost_function.h), instead of
38
+ // directly implementing the CostFunction interface. This often results in both
39
+ // shorter code and faster execution than hand-coded derivatives. However,
40
+ // specialized cases may demand direct implementation of the lower-level
41
+ // CostFunction interface; for example, this is true when calling legacy code
42
+ // which is not templated on numeric types.
43
+
44
+ #ifndef CERES_PUBLIC_COST_FUNCTION_H_
45
+ #define CERES_PUBLIC_COST_FUNCTION_H_
46
+
47
+ #include <cstdint>
48
+ #include <vector>
49
+
50
+ #include "ceres/internal/disable_warnings.h"
51
+ #include "ceres/internal/export.h"
52
+
53
+ namespace ceres {
54
+
55
+ // This class implements the computation of the cost (a.k.a. residual) terms as
56
+ // a function of the input (control) variables, and is the interface for users
57
+ // to describe their least squares problem to Ceres. In other words, this is the
58
+ // modeling layer between users and the Ceres optimizer. The signature of the
59
+ // function (number and sizes of input parameter blocks and number of outputs)
60
+ // is stored in parameter_block_sizes_ and num_residuals_ respectively. User
61
+ // code inheriting from this class is expected to set these two members with the
62
+ // corresponding accessors. This information will be verified by the Problem
63
+ // when added with AddResidualBlock().
64
+ class CERES_EXPORT CostFunction {
65
+ public:
66
+ CostFunction();
67
+ CostFunction(const CostFunction&) = delete;
68
+ void operator=(const CostFunction&) = delete;
69
+
70
+ virtual ~CostFunction();
71
+
72
+ // Inputs:
73
+ //
74
+ // parameters is an array of pointers to arrays containing the
75
+ // various parameter blocks. parameters has the same number of
76
+ // elements as parameter_block_sizes_. Parameter blocks are in the
77
+ // same order as parameter_block_sizes_.i.e.,
78
+ //
79
+ // parameters_[i] = double[parameter_block_sizes_[i]]
80
+ //
81
+ // Outputs:
82
+ //
83
+ // residuals is an array of size num_residuals_.
84
+ //
85
+ // jacobians is an array of size parameter_block_sizes_ containing
86
+ // pointers to storage for jacobian blocks corresponding to each
87
+ // parameter block. Jacobian blocks are in the same order as
88
+ // parameter_block_sizes, i.e. jacobians[i], is an
89
+ // array that contains num_residuals_* parameter_block_sizes_[i]
90
+ // elements. Each jacobian block is stored in row-major order, i.e.,
91
+ //
92
+ // jacobians[i][r*parameter_block_size_[i] + c] =
93
+ // d residual[r] / d parameters[i][c]
94
+ //
95
+ // If jacobians is nullptr, then no derivatives are returned; this is
96
+ // the case when computing cost only. If jacobians[i] is nullptr, then
97
+ // the jacobian block corresponding to the i'th parameter block must
98
+ // not to be returned.
99
+ //
100
+ // The return value indicates whether the computation of the
101
+ // residuals and/or jacobians was successful or not.
102
+ //
103
+ // This can be used to communicate numerical failures in jacobian
104
+ // computations for instance.
105
+ //
106
+ // A more interesting and common use is to impose constraints on the
107
+ // parameters. If the initial values of the parameter blocks satisfy
108
+ // the constraints, then returning false whenever the constraints
109
+ // are not satisfied will prevent the solver from moving into the
110
+ // infeasible region. This is not a very sophisticated mechanism for
111
+ // enforcing constraints, but is often good enough.
112
+ //
113
+ // Note that it is important that the initial values of the
114
+ // parameter block must be feasible, otherwise the solver will
115
+ // declare a numerical problem at iteration 0.
116
+ virtual bool Evaluate(double const* const* parameters,
117
+ double* residuals,
118
+ double** jacobians) const = 0;
119
+
120
+ const std::vector<int32_t>& parameter_block_sizes() const {
121
+ return parameter_block_sizes_;
122
+ }
123
+
124
+ int num_residuals() const { return num_residuals_; }
125
+
126
+ protected:
127
+ std::vector<int32_t>* mutable_parameter_block_sizes() {
128
+ return &parameter_block_sizes_;
129
+ }
130
+
131
+ void set_num_residuals(int num_residuals) { num_residuals_ = num_residuals; }
132
+
133
+ private:
134
+ // Cost function signature metadata: number of inputs & their sizes,
135
+ // number of outputs (residuals).
136
+ std::vector<int32_t> parameter_block_sizes_;
137
+ int num_residuals_;
138
+ };
139
+
140
+ } // namespace ceres
141
+
142
+ #include "ceres/internal/reenable_warnings.h"
143
+
144
+ #endif // CERES_PUBLIC_COST_FUNCTION_H_
include/ceres/cost_function_to_functor.h ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+ //
31
+ // CostFunctionToFunctor is an adapter class that allows users to use
32
+ // SizedCostFunction objects in templated functors which are to be used for
33
+ // automatic differentiation. This allows the user to seamlessly mix
34
+ // analytic, numeric and automatic differentiation.
35
+ //
36
+ // For example, let us assume that
37
+ //
38
+ // class IntrinsicProjection : public SizedCostFunction<2, 5, 3> {
39
+ // public:
40
+ // IntrinsicProjection(const double* observation);
41
+ // bool Evaluate(double const* const* parameters,
42
+ // double* residuals,
43
+ // double** jacobians) const override;
44
+ // };
45
+ //
46
+ // is a cost function that implements the projection of a point in its
47
+ // local coordinate system onto its image plane and subtracts it from
48
+ // the observed point projection. It can compute its residual and
49
+ // jacobians either via analytic or numerical differentiation.
50
+ //
51
+ // Now we would like to compose the action of this CostFunction with
52
+ // the action of camera extrinsics, i.e., rotation and
53
+ // translation. Say we have a templated function
54
+ //
55
+ // template<typename T>
56
+ // void RotateAndTranslatePoint(const T* rotation,
57
+ // const T* translation,
58
+ // const T* point,
59
+ // T* result);
60
+ //
61
+ // Then we can now do the following,
62
+ //
63
+ // struct CameraProjection {
64
+ // CameraProjection(const double* observation)
65
+ // : intrinsic_projection_(new IntrinsicProjection(observation)) {
66
+ // }
67
+ // template <typename T>
68
+ // bool operator()(const T* rotation,
69
+ // const T* translation,
70
+ // const T* intrinsics,
71
+ // const T* point,
72
+ // T* residual) const {
73
+ // T transformed_point[3];
74
+ // RotateAndTranslatePoint(rotation, translation, point, transformed_point);
75
+ //
76
+ // // Note that we call intrinsic_projection_, just like it was
77
+ // // any other templated functor.
78
+ //
79
+ // return intrinsic_projection_(intrinsics, transformed_point, residual);
80
+ // }
81
+ //
82
+ // private:
83
+ // CostFunctionToFunctor<2,5,3> intrinsic_projection_;
84
+ // };
85
+
86
+ #ifndef CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
87
+ #define CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
88
+
89
+ #include <cstdint>
90
+ #include <numeric>
91
+ #include <tuple>
92
+ #include <utility>
93
+ #include <vector>
94
+
95
+ #include "ceres/cost_function.h"
96
+ #include "ceres/dynamic_cost_function_to_functor.h"
97
+ #include "ceres/internal/export.h"
98
+ #include "ceres/internal/fixed_array.h"
99
+ #include "ceres/internal/parameter_dims.h"
100
+ #include "ceres/types.h"
101
+ #include "glog/logging.h"
102
+
103
+ namespace ceres {
104
+
105
+ template <int kNumResiduals, int... Ns>
106
+ class CostFunctionToFunctor {
107
+ public:
108
+ // Takes ownership of cost_function.
109
+ explicit CostFunctionToFunctor(CostFunction* cost_function)
110
+ : cost_functor_(cost_function) {
111
+ CHECK(cost_function != nullptr);
112
+ CHECK(kNumResiduals > 0 || kNumResiduals == DYNAMIC);
113
+
114
+ const std::vector<int32_t>& parameter_block_sizes =
115
+ cost_function->parameter_block_sizes();
116
+ const int num_parameter_blocks = ParameterDims::kNumParameterBlocks;
117
+ CHECK_EQ(static_cast<int>(parameter_block_sizes.size()),
118
+ num_parameter_blocks);
119
+
120
+ if (parameter_block_sizes.size() == num_parameter_blocks) {
121
+ for (int block = 0; block < num_parameter_blocks; ++block) {
122
+ CHECK_EQ(ParameterDims::GetDim(block), parameter_block_sizes[block])
123
+ << "Parameter block size missmatch. The specified static parameter "
124
+ "block dimension does not match the one from the cost function.";
125
+ }
126
+ }
127
+
128
+ CHECK_EQ(accumulate(
129
+ parameter_block_sizes.begin(), parameter_block_sizes.end(), 0),
130
+ ParameterDims::kNumParameters);
131
+ }
132
+
133
+ template <typename T, typename... Ts>
134
+ bool operator()(const T* p1, Ts*... ps) const {
135
+ // Add one because of residual block.
136
+ static_assert(sizeof...(Ts) + 1 == ParameterDims::kNumParameterBlocks + 1,
137
+ "Invalid number of parameter blocks specified.");
138
+
139
+ auto params = std::make_tuple(p1, ps...);
140
+
141
+ // Extract residual pointer from params. The residual pointer is the
142
+ // last pointer.
143
+ constexpr int kResidualIndex = ParameterDims::kNumParameterBlocks;
144
+ T* residuals = std::get<kResidualIndex>(params);
145
+
146
+ // Extract parameter block pointers from params.
147
+ using Indices =
148
+ std::make_integer_sequence<int, ParameterDims::kNumParameterBlocks>;
149
+ std::array<const T*, ParameterDims::kNumParameterBlocks> parameter_blocks =
150
+ GetParameterPointers<T>(params, Indices());
151
+
152
+ return cost_functor_(parameter_blocks.data(), residuals);
153
+ }
154
+
155
+ private:
156
+ using ParameterDims = internal::StaticParameterDims<Ns...>;
157
+
158
+ template <typename T, typename Tuple, int... Indices>
159
+ static std::array<const T*, ParameterDims::kNumParameterBlocks>
160
+ GetParameterPointers(const Tuple& paramPointers,
161
+ std::integer_sequence<int, Indices...>) {
162
+ return std::array<const T*, ParameterDims::kNumParameterBlocks>{
163
+ {std::get<Indices>(paramPointers)...}};
164
+ }
165
+
166
+ DynamicCostFunctionToFunctor cost_functor_;
167
+ };
168
+
169
+ } // namespace ceres
170
+
171
+ #endif // CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
include/ceres/covariance.h ADDED
@@ -0,0 +1,459 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+
31
+ #ifndef CERES_PUBLIC_COVARIANCE_H_
32
+ #define CERES_PUBLIC_COVARIANCE_H_
33
+
34
+ #include <memory>
35
+ #include <utility>
36
+ #include <vector>
37
+
38
+ #include "ceres/internal/config.h"
39
+ #include "ceres/internal/disable_warnings.h"
40
+ #include "ceres/internal/export.h"
41
+ #include "ceres/types.h"
42
+
43
+ namespace ceres {
44
+
45
+ class Problem;
46
+
47
+ namespace internal {
48
+ class CovarianceImpl;
49
+ } // namespace internal
50
+
51
+ // WARNING
52
+ // =======
53
+ // It is very easy to use this class incorrectly without understanding
54
+ // the underlying mathematics. Please read and understand the
55
+ // documentation completely before attempting to use it.
56
+ //
57
+ //
58
+ // This class allows the user to evaluate the covariance for a
59
+ // non-linear least squares problem and provides random access to its
60
+ // blocks
61
+ //
62
+ // Background
63
+ // ==========
64
+ // One way to assess the quality of the solution returned by a
65
+ // non-linear least squares solver is to analyze the covariance of the
66
+ // solution.
67
+ //
68
+ // Let us consider the non-linear regression problem
69
+ //
70
+ // y = f(x) + N(0, I)
71
+ //
72
+ // i.e., the observation y is a random non-linear function of the
73
+ // independent variable x with mean f(x) and identity covariance. Then
74
+ // the maximum likelihood estimate of x given observations y is the
75
+ // solution to the non-linear least squares problem:
76
+ //
77
+ // x* = arg min_x |f(x) - y|^2
78
+ //
79
+ // And the covariance of x* is given by
80
+ //
81
+ // C(x*) = inverse[J'(x*)J(x*)]
82
+ //
83
+ // Here J(x*) is the Jacobian of f at x*. The above formula assumes
84
+ // that J(x*) has full column rank.
85
+ //
86
+ // If J(x*) is rank deficient, then the covariance matrix C(x*) is
87
+ // also rank deficient and is given by
88
+ //
89
+ // C(x*) = pseudoinverse[J'(x*)J(x*)]
90
+ //
91
+ // Note that in the above, we assumed that the covariance
92
+ // matrix for y was identity. This is an important assumption. If this
93
+ // is not the case and we have
94
+ //
95
+ // y = f(x) + N(0, S)
96
+ //
97
+ // Where S is a positive semi-definite matrix denoting the covariance
98
+ // of y, then the maximum likelihood problem to be solved is
99
+ //
100
+ // x* = arg min_x f'(x) inverse[S] f(x)
101
+ //
102
+ // and the corresponding covariance estimate of x* is given by
103
+ //
104
+ // C(x*) = inverse[J'(x*) inverse[S] J(x*)]
105
+ //
106
+ // So, if it is the case that the observations being fitted to have a
107
+ // covariance matrix not equal to identity, then it is the user's
108
+ // responsibility that the corresponding cost functions are correctly
109
+ // scaled, e.g. in the above case the cost function for this problem
110
+ // should evaluate S^{-1/2} f(x) instead of just f(x), where S^{-1/2}
111
+ // is the inverse square root of the covariance matrix S.
112
+ //
113
+ // This class allows the user to evaluate the covariance for a
114
+ // non-linear least squares problem and provides random access to its
115
+ // blocks. The computation assumes that the CostFunctions compute
116
+ // residuals such that their covariance is identity.
117
+ //
118
+ // Since the computation of the covariance matrix requires computing
119
+ // the inverse of a potentially large matrix, this can involve a
120
+ // rather large amount of time and memory. However, it is usually the
121
+ // case that the user is only interested in a small part of the
122
+ // covariance matrix. Quite often just the block diagonal. This class
123
+ // allows the user to specify the parts of the covariance matrix that
124
+ // she is interested in and then uses this information to only compute
125
+ // and store those parts of the covariance matrix.
126
+ //
127
+ // Rank of the Jacobian
128
+ // --------------------
129
+ // As we noted above, if the jacobian is rank deficient, then the
130
+ // inverse of J'J is not defined and instead a pseudo inverse needs to
131
+ // be computed.
132
+ //
133
+ // The rank deficiency in J can be structural -- columns which are
134
+ // always known to be zero or numerical -- depending on the exact
135
+ // values in the Jacobian.
136
+ //
137
+ // Structural rank deficiency occurs when the problem contains
138
+ // parameter blocks that are constant. This class correctly handles
139
+ // structural rank deficiency like that.
140
+ //
141
+ // Numerical rank deficiency, where the rank of the matrix cannot be
142
+ // predicted by its sparsity structure and requires looking at its
143
+ // numerical values is more complicated. Here again there are two
144
+ // cases.
145
+ //
146
+ // a. The rank deficiency arises from overparameterization. e.g., a
147
+ // four dimensional quaternion used to parameterize SO(3), which is
148
+ // a three dimensional manifold. In cases like this, the user should
149
+ // use an appropriate LocalParameterization/Manifold. Not only will this lead
150
+ // to better numerical behaviour of the Solver, it will also expose
151
+ // the rank deficiency to the Covariance object so that it can
152
+ // handle it correctly.
153
+ //
154
+ // b. More general numerical rank deficiency in the Jacobian
155
+ // requires the computation of the so called Singular Value
156
+ // Decomposition (SVD) of J'J. We do not know how to do this for
157
+ // large sparse matrices efficiently. For small and moderate sized
158
+ // problems this is done using dense linear algebra.
159
+ //
160
+ // Gauge Invariance
161
+ // ----------------
162
+ // In structure from motion (3D reconstruction) problems, the
163
+ // reconstruction is ambiguous up to a similarity transform. This is
164
+ // known as a Gauge Ambiguity. Handling Gauges correctly requires the
165
+ // use of SVD or custom inversion algorithms. For small problems the
166
+ // user can use the dense algorithm. For more details see
167
+ //
168
+ // Ken-ichi Kanatani, Daniel D. Morris: Gauges and gauge
169
+ // transformations for uncertainty description of geometric structure
170
+ // with indeterminacy. IEEE Transactions on Information Theory 47(5):
171
+ // 2017-2028 (2001)
172
+ //
173
+ // Example Usage
174
+ // =============
175
+ //
176
+ // double x[3];
177
+ // double y[2];
178
+ //
179
+ // Problem problem;
180
+ // problem.AddParameterBlock(x, 3);
181
+ // problem.AddParameterBlock(y, 2);
182
+ // <Build Problem>
183
+ // <Solve Problem>
184
+ //
185
+ // Covariance::Options options;
186
+ // Covariance covariance(options);
187
+ //
188
+ // std::vector<std::pair<const double*, const double*>> covariance_blocks;
189
+ // covariance_blocks.push_back(make_pair(x, x));
190
+ // covariance_blocks.push_back(make_pair(y, y));
191
+ // covariance_blocks.push_back(make_pair(x, y));
192
+ //
193
+ // CHECK(covariance.Compute(covariance_blocks, &problem));
194
+ //
195
+ // double covariance_xx[3 * 3];
196
+ // double covariance_yy[2 * 2];
197
+ // double covariance_xy[3 * 2];
198
+ // covariance.GetCovarianceBlock(x, x, covariance_xx)
199
+ // covariance.GetCovarianceBlock(y, y, covariance_yy)
200
+ // covariance.GetCovarianceBlock(x, y, covariance_xy)
201
+ //
202
+ class CERES_EXPORT Covariance {
203
+ public:
204
+ struct CERES_EXPORT Options {
205
+ // Sparse linear algebra library to use when a sparse matrix
206
+ // factorization is being used to compute the covariance matrix.
207
+ //
208
+ // Currently this only applies to SPARSE_QR.
209
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type =
210
+ #if !defined(CERES_NO_SUITESPARSE)
211
+ SUITE_SPARSE;
212
+ #else
213
+ // Eigen's QR factorization is always available.
214
+ EIGEN_SPARSE;
215
+ #endif
216
+
217
+ // Ceres supports two different algorithms for covariance
218
+ // estimation, which represent different tradeoffs in speed,
219
+ // accuracy and reliability.
220
+ //
221
+ // 1. DENSE_SVD uses Eigen's JacobiSVD to perform the
222
+ // computations. It computes the singular value decomposition
223
+ //
224
+ // U * D * V' = J
225
+ //
226
+ // and then uses it to compute the pseudo inverse of J'J as
227
+ //
228
+ // pseudoinverse[J'J] = V * pseudoinverse[D^2] * V'
229
+ //
230
+ // It is an accurate but slow method and should only be used
231
+ // for small to moderate sized problems. It can handle
232
+ // full-rank as well as rank deficient Jacobians.
233
+ //
234
+ // 2. SPARSE_QR uses the sparse QR factorization algorithm
235
+ // to compute the decomposition
236
+ //
237
+ // Q * R = J
238
+ //
239
+ // [J'J]^-1 = [R'*R]^-1
240
+ //
241
+ // SPARSE_QR is not capable of computing the covariance if the
242
+ // Jacobian is rank deficient. Depending on the value of
243
+ // Covariance::Options::sparse_linear_algebra_library_type, either
244
+ // Eigen's Sparse QR factorization algorithm will be used or
245
+ // SuiteSparse's high performance SuiteSparseQR algorithm will be
246
+ // used.
247
+ CovarianceAlgorithmType algorithm_type = SPARSE_QR;
248
+
249
+ // If the Jacobian matrix is near singular, then inverting J'J
250
+ // will result in unreliable results, e.g, if
251
+ //
252
+ // J = [1.0 1.0 ]
253
+ // [1.0 1.0000001 ]
254
+ //
255
+ // which is essentially a rank deficient matrix, we have
256
+ //
257
+ // inv(J'J) = [ 2.0471e+14 -2.0471e+14]
258
+ // [-2.0471e+14 2.0471e+14]
259
+ //
260
+ // This is not a useful result. Therefore, by default
261
+ // Covariance::Compute will return false if a rank deficient
262
+ // Jacobian is encountered. How rank deficiency is detected
263
+ // depends on the algorithm being used.
264
+ //
265
+ // 1. DENSE_SVD
266
+ //
267
+ // min_sigma / max_sigma < sqrt(min_reciprocal_condition_number)
268
+ //
269
+ // where min_sigma and max_sigma are the minimum and maxiumum
270
+ // singular values of J respectively.
271
+ //
272
+ // 2. SPARSE_QR
273
+ //
274
+ // rank(J) < num_col(J)
275
+ //
276
+ // Here rank(J) is the estimate of the rank of J returned by the
277
+ // sparse QR factorization algorithm. It is a fairly reliable
278
+ // indication of rank deficiency.
279
+ //
280
+ double min_reciprocal_condition_number = 1e-14;
281
+
282
+ // When using DENSE_SVD, the user has more control in dealing with
283
+ // singular and near singular covariance matrices.
284
+ //
285
+ // As mentioned above, when the covariance matrix is near
286
+ // singular, instead of computing the inverse of J'J, the
287
+ // Moore-Penrose pseudoinverse of J'J should be computed.
288
+ //
289
+ // If J'J has the eigen decomposition (lambda_i, e_i), where
290
+ // lambda_i is the i^th eigenvalue and e_i is the corresponding
291
+ // eigenvector, then the inverse of J'J is
292
+ //
293
+ // inverse[J'J] = sum_i e_i e_i' / lambda_i
294
+ //
295
+ // and computing the pseudo inverse involves dropping terms from
296
+ // this sum that correspond to small eigenvalues.
297
+ //
298
+ // How terms are dropped is controlled by
299
+ // min_reciprocal_condition_number and null_space_rank.
300
+ //
301
+ // If null_space_rank is non-negative, then the smallest
302
+ // null_space_rank eigenvalue/eigenvectors are dropped
303
+ // irrespective of the magnitude of lambda_i. If the ratio of the
304
+ // smallest non-zero eigenvalue to the largest eigenvalue in the
305
+ // truncated matrix is still below
306
+ // min_reciprocal_condition_number, then the Covariance::Compute()
307
+ // will fail and return false.
308
+ //
309
+ // Setting null_space_rank = -1 drops all terms for which
310
+ //
311
+ // lambda_i / lambda_max < min_reciprocal_condition_number.
312
+ //
313
+ // This option has no effect on the SUITE_SPARSE_QR and
314
+ // EIGEN_SPARSE_QR algorithms.
315
+ int null_space_rank = 0;
316
+
317
+ int num_threads = 1;
318
+
319
+ // Even though the residual blocks in the problem may contain loss
320
+ // functions, setting apply_loss_function to false will turn off
321
+ // the application of the loss function to the output of the cost
322
+ // function and in turn its effect on the covariance.
323
+ //
324
+ // TODO(sameergaarwal): Expand this based on Jim's experiments.
325
+ bool apply_loss_function = true;
326
+ };
327
+
328
+ explicit Covariance(const Options& options);
329
+ ~Covariance();
330
+
331
+ // Compute a part of the covariance matrix.
332
+ //
333
+ // The vector covariance_blocks, indexes into the covariance matrix
334
+ // block-wise using pairs of parameter blocks. This allows the
335
+ // covariance estimation algorithm to only compute and store these
336
+ // blocks.
337
+ //
338
+ // Since the covariance matrix is symmetric, if the user passes
339
+ // (block1, block2), then GetCovarianceBlock can be called with
340
+ // block1, block2 as well as block2, block1.
341
+ //
342
+ // covariance_blocks cannot contain duplicates. Bad things will
343
+ // happen if they do.
344
+ //
345
+ // Note that the list of covariance_blocks is only used to determine
346
+ // what parts of the covariance matrix are computed. The full
347
+ // Jacobian is used to do the computation, i.e. they do not have an
348
+ // impact on what part of the Jacobian is used for computation.
349
+ //
350
+ // The return value indicates the success or failure of the
351
+ // covariance computation. Please see the documentation for
352
+ // Covariance::Options for more on the conditions under which this
353
+ // function returns false.
354
+ bool Compute(const std::vector<std::pair<const double*, const double*>>&
355
+ covariance_blocks,
356
+ Problem* problem);
357
+
358
+ // Compute a part of the covariance matrix.
359
+ //
360
+ // The vector parameter_blocks contains the parameter blocks that
361
+ // are used for computing the covariance matrix. From this vector
362
+ // all covariance pairs are generated. This allows the covariance
363
+ // estimation algorithm to only compute and store these blocks.
364
+ //
365
+ // parameter_blocks cannot contain duplicates. Bad things will
366
+ // happen if they do.
367
+ //
368
+ // Note that the list of covariance_blocks is only used to determine
369
+ // what parts of the covariance matrix are computed. The full
370
+ // Jacobian is used to do the computation, i.e. they do not have an
371
+ // impact on what part of the Jacobian is used for computation.
372
+ //
373
+ // The return value indicates the success or failure of the
374
+ // covariance computation. Please see the documentation for
375
+ // Covariance::Options for more on the conditions under which this
376
+ // function returns false.
377
+ bool Compute(const std::vector<const double*>& parameter_blocks,
378
+ Problem* problem);
379
+
380
+ // Return the block of the cross-covariance matrix corresponding to
381
+ // parameter_block1 and parameter_block2.
382
+ //
383
+ // Compute must be called before the first call to
384
+ // GetCovarianceBlock and the pair <parameter_block1,
385
+ // parameter_block2> OR the pair <parameter_block2,
386
+ // parameter_block1> must have been present in the vector
387
+ // covariance_blocks when Compute was called. Otherwise
388
+ // GetCovarianceBlock will return false.
389
+ //
390
+ // covariance_block must point to a memory location that can store a
391
+ // parameter_block1_size x parameter_block2_size matrix. The
392
+ // returned covariance will be a row-major matrix.
393
+ bool GetCovarianceBlock(const double* parameter_block1,
394
+ const double* parameter_block2,
395
+ double* covariance_block) const;
396
+
397
+ // Return the block of the cross-covariance matrix corresponding to
398
+ // parameter_block1 and parameter_block2.
399
+ // Returns cross-covariance in the tangent space if a local
400
+ // parameterization is associated with either parameter block;
401
+ // else returns cross-covariance in the ambient space.
402
+ //
403
+ // Compute must be called before the first call to
404
+ // GetCovarianceBlock and the pair <parameter_block1,
405
+ // parameter_block2> OR the pair <parameter_block2,
406
+ // parameter_block1> must have been present in the vector
407
+ // covariance_blocks when Compute was called. Otherwise
408
+ // GetCovarianceBlock will return false.
409
+ //
410
+ // covariance_block must point to a memory location that can store a
411
+ // parameter_block1_local_size x parameter_block2_local_size matrix. The
412
+ // returned covariance will be a row-major matrix.
413
+ bool GetCovarianceBlockInTangentSpace(const double* parameter_block1,
414
+ const double* parameter_block2,
415
+ double* covariance_block) const;
416
+
417
+ // Return the covariance matrix corresponding to all parameter_blocks.
418
+ //
419
+ // Compute must be called before calling GetCovarianceMatrix and all
420
+ // parameter_blocks must have been present in the vector
421
+ // parameter_blocks when Compute was called. Otherwise
422
+ // GetCovarianceMatrix returns false.
423
+ //
424
+ // covariance_matrix must point to a memory location that can store
425
+ // the size of the covariance matrix. The covariance matrix will be
426
+ // a square matrix whose row and column count is equal to the sum of
427
+ // the sizes of the individual parameter blocks. The covariance
428
+ // matrix will be a row-major matrix.
429
+ bool GetCovarianceMatrix(const std::vector<const double*>& parameter_blocks,
430
+ double* covariance_matrix) const;
431
+
432
+ // Return the covariance matrix corresponding to parameter_blocks
433
+ // in the tangent space if a local parameterization is associated
434
+ // with one of the parameter blocks else returns the covariance
435
+ // matrix in the ambient space.
436
+ //
437
+ // Compute must be called before calling GetCovarianceMatrix and all
438
+ // parameter_blocks must have been present in the vector
439
+ // parameters_blocks when Compute was called. Otherwise
440
+ // GetCovarianceMatrix returns false.
441
+ //
442
+ // covariance_matrix must point to a memory location that can store
443
+ // the size of the covariance matrix. The covariance matrix will be
444
+ // a square matrix whose row and column count is equal to the sum of
445
+ // the sizes of the tangent spaces of the individual parameter
446
+ // blocks. The covariance matrix will be a row-major matrix.
447
+ bool GetCovarianceMatrixInTangentSpace(
448
+ const std::vector<const double*>& parameter_blocks,
449
+ double* covariance_matrix) const;
450
+
451
+ private:
452
+ std::unique_ptr<internal::CovarianceImpl> impl_;
453
+ };
454
+
455
+ } // namespace ceres
456
+
457
+ #include "ceres/internal/reenable_warnings.h"
458
+
459
+ #endif // CERES_PUBLIC_COVARIANCE_H_
include/ceres/crs_matrix.h ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+
31
+ #ifndef CERES_PUBLIC_CRS_MATRIX_H_
32
+ #define CERES_PUBLIC_CRS_MATRIX_H_
33
+
34
+ #include <vector>
35
+
36
+ #include "ceres/internal/disable_warnings.h"
37
+ #include "ceres/internal/export.h"
38
+
39
+ namespace ceres {
40
+
41
+ // A compressed row sparse matrix used primarily for communicating the
42
+ // Jacobian matrix to the user.
43
+ struct CERES_EXPORT CRSMatrix {
44
+ CRSMatrix() = default;
45
+
46
+ int num_rows{0};
47
+ int num_cols{0};
48
+
49
+ // A compressed row matrix stores its contents in three arrays,
50
+ // rows, cols and values.
51
+ //
52
+ // rows is a num_rows + 1 sized array that points into the cols and
53
+ // values array. For each row i:
54
+ //
55
+ // cols[rows[i]] ... cols[rows[i + 1] - 1] are the indices of the
56
+ // non-zero columns of row i.
57
+ //
58
+ // values[rows[i]] .. values[rows[i + 1] - 1] are the values of the
59
+ // corresponding entries.
60
+ //
61
+ // cols and values contain as many entries as there are non-zeros in
62
+ // the matrix.
63
+ //
64
+ // e.g, consider the 3x4 sparse matrix
65
+ //
66
+ // [ 0 10 0 4 ]
67
+ // [ 0 2 -3 2 ]
68
+ // [ 1 2 0 0 ]
69
+ //
70
+ // The three arrays will be:
71
+ //
72
+ //
73
+ // -row0- ---row1--- -row2-
74
+ // rows = [ 0, 2, 5, 7]
75
+ // cols = [ 1, 3, 1, 2, 3, 0, 1]
76
+ // values = [10, 4, 2, -3, 2, 1, 2]
77
+
78
+ std::vector<int> cols;
79
+ std::vector<int> rows;
80
+ std::vector<double> values;
81
+ };
82
+
83
+ } // namespace ceres
84
+
85
+ #include "ceres/internal/reenable_warnings.h"
86
+
87
+ #endif // CERES_PUBLIC_CRS_MATRIX_H_
include/ceres/cubic_interpolation.h ADDED
@@ -0,0 +1,436 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+
31
+ #ifndef CERES_PUBLIC_CUBIC_INTERPOLATION_H_
32
+ #define CERES_PUBLIC_CUBIC_INTERPOLATION_H_
33
+
34
+ #include "Eigen/Core"
35
+ #include "ceres/internal/export.h"
36
+ #include "glog/logging.h"
37
+
38
+ namespace ceres {
39
+
40
+ // Given samples from a function sampled at four equally spaced points,
41
+ //
42
+ // p0 = f(-1)
43
+ // p1 = f(0)
44
+ // p2 = f(1)
45
+ // p3 = f(2)
46
+ //
47
+ // Evaluate the cubic Hermite spline (also known as the Catmull-Rom
48
+ // spline) at a point x that lies in the interval [0, 1].
49
+ //
50
+ // This is also the interpolation kernel (for the case of a = 0.5) as
51
+ // proposed by R. Keys, in:
52
+ //
53
+ // "Cubic convolution interpolation for digital image processing".
54
+ // IEEE Transactions on Acoustics, Speech, and Signal Processing
55
+ // 29 (6): 1153-1160.
56
+ //
57
+ // For more details see
58
+ //
59
+ // http://en.wikipedia.org/wiki/Cubic_Hermite_spline
60
+ // http://en.wikipedia.org/wiki/Bicubic_interpolation
61
+ //
62
+ // f if not nullptr will contain the interpolated function values.
63
+ // dfdx if not nullptr will contain the interpolated derivative values.
64
+ template <int kDataDimension>
65
+ void CubicHermiteSpline(const Eigen::Matrix<double, kDataDimension, 1>& p0,
66
+ const Eigen::Matrix<double, kDataDimension, 1>& p1,
67
+ const Eigen::Matrix<double, kDataDimension, 1>& p2,
68
+ const Eigen::Matrix<double, kDataDimension, 1>& p3,
69
+ const double x,
70
+ double* f,
71
+ double* dfdx) {
72
+ using VType = Eigen::Matrix<double, kDataDimension, 1>;
73
+ const VType a = 0.5 * (-p0 + 3.0 * p1 - 3.0 * p2 + p3);
74
+ const VType b = 0.5 * (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3);
75
+ const VType c = 0.5 * (-p0 + p2);
76
+ const VType d = p1;
77
+
78
+ // Use Horner's rule to evaluate the function value and its
79
+ // derivative.
80
+
81
+ // f = ax^3 + bx^2 + cx + d
82
+ if (f != nullptr) {
83
+ Eigen::Map<VType>(f, kDataDimension) = d + x * (c + x * (b + x * a));
84
+ }
85
+
86
+ // dfdx = 3ax^2 + 2bx + c
87
+ if (dfdx != nullptr) {
88
+ Eigen::Map<VType>(dfdx, kDataDimension) = c + x * (2.0 * b + 3.0 * a * x);
89
+ }
90
+ }
91
+
92
+ // Given as input an infinite one dimensional grid, which provides the
93
+ // following interface.
94
+ //
95
+ // class Grid {
96
+ // public:
97
+ // enum { DATA_DIMENSION = 2; };
98
+ // void GetValue(int n, double* f) const;
99
+ // };
100
+ //
101
+ // Here, GetValue gives the value of a function f (possibly vector
102
+ // valued) for any integer n.
103
+ //
104
+ // The enum DATA_DIMENSION indicates the dimensionality of the
105
+ // function being interpolated. For example if you are interpolating
106
+ // rotations in axis-angle format over time, then DATA_DIMENSION = 3.
107
+ //
108
+ // CubicInterpolator uses cubic Hermite splines to produce a smooth
109
+ // approximation to it that can be used to evaluate the f(x) and f'(x)
110
+ // at any point on the real number line.
111
+ //
112
+ // For more details on cubic interpolation see
113
+ //
114
+ // http://en.wikipedia.org/wiki/Cubic_Hermite_spline
115
+ //
116
+ // Example usage:
117
+ //
118
+ // const double data[] = {1.0, 2.0, 5.0, 6.0};
119
+ // Grid1D<double, 1> grid(data, 0, 4);
120
+ // CubicInterpolator<Grid1D<double, 1>> interpolator(grid);
121
+ // double f, dfdx;
122
+ // interpolator.Evaluator(1.5, &f, &dfdx);
123
+ template <typename Grid>
124
+ class CubicInterpolator {
125
+ public:
126
+ explicit CubicInterpolator(const Grid& grid) : grid_(grid) {
127
+ // The + casts the enum into an int before doing the
128
+ // comparison. It is needed to prevent
129
+ // "-Wunnamed-type-template-args" related errors.
130
+ CHECK_GE(+Grid::DATA_DIMENSION, 1);
131
+ }
132
+
133
+ void Evaluate(double x, double* f, double* dfdx) const {
134
+ const int n = std::floor(x);
135
+ Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> p0, p1, p2, p3;
136
+ grid_.GetValue(n - 1, p0.data());
137
+ grid_.GetValue(n, p1.data());
138
+ grid_.GetValue(n + 1, p2.data());
139
+ grid_.GetValue(n + 2, p3.data());
140
+ CubicHermiteSpline<Grid::DATA_DIMENSION>(p0, p1, p2, p3, x - n, f, dfdx);
141
+ }
142
+
143
+ // The following two Evaluate overloads are needed for interfacing
144
+ // with automatic differentiation. The first is for when a scalar
145
+ // evaluation is done, and the second one is for when Jets are used.
146
+ void Evaluate(const double& x, double* f) const { Evaluate(x, f, nullptr); }
147
+
148
+ template <typename JetT>
149
+ void Evaluate(const JetT& x, JetT* f) const {
150
+ double fx[Grid::DATA_DIMENSION], dfdx[Grid::DATA_DIMENSION];
151
+ Evaluate(x.a, fx, dfdx);
152
+ for (int i = 0; i < Grid::DATA_DIMENSION; ++i) {
153
+ f[i].a = fx[i];
154
+ f[i].v = dfdx[i] * x.v;
155
+ }
156
+ }
157
+
158
+ private:
159
+ const Grid& grid_;
160
+ };
161
+
162
+ // An object that implements an infinite one dimensional grid needed
163
+ // by the CubicInterpolator where the source of the function values is
164
+ // an array of type T on the interval
165
+ //
166
+ // [begin, ..., end - 1]
167
+ //
168
+ // Since the input array is finite and the grid is infinite, values
169
+ // outside this interval needs to be computed. Grid1D uses the value
170
+ // from the nearest edge.
171
+ //
172
+ // The function being provided can be vector valued, in which case
173
+ // kDataDimension > 1. The dimensional slices of the function maybe
174
+ // interleaved, or they maybe stacked, i.e, if the function has
175
+ // kDataDimension = 2, if kInterleaved = true, then it is stored as
176
+ //
177
+ // f01, f02, f11, f12 ....
178
+ //
179
+ // and if kInterleaved = false, then it is stored as
180
+ //
181
+ // f01, f11, .. fn1, f02, f12, .. , fn2
182
+ //
183
+ template <typename T, int kDataDimension = 1, bool kInterleaved = true>
184
+ struct Grid1D {
185
+ public:
186
+ enum { DATA_DIMENSION = kDataDimension };
187
+
188
+ Grid1D(const T* data, const int begin, const int end)
189
+ : data_(data), begin_(begin), end_(end), num_values_(end - begin) {
190
+ CHECK_LT(begin, end);
191
+ }
192
+
193
+ EIGEN_STRONG_INLINE void GetValue(const int n, double* f) const {
194
+ const int idx = (std::min)((std::max)(begin_, n), end_ - 1) - begin_;
195
+ if (kInterleaved) {
196
+ for (int i = 0; i < kDataDimension; ++i) {
197
+ f[i] = static_cast<double>(data_[kDataDimension * idx + i]);
198
+ }
199
+ } else {
200
+ for (int i = 0; i < kDataDimension; ++i) {
201
+ f[i] = static_cast<double>(data_[i * num_values_ + idx]);
202
+ }
203
+ }
204
+ }
205
+
206
+ private:
207
+ const T* data_;
208
+ const int begin_;
209
+ const int end_;
210
+ const int num_values_;
211
+ };
212
+
213
+ // Given as input an infinite two dimensional grid like object, which
214
+ // provides the following interface:
215
+ //
216
+ // struct Grid {
217
+ // enum { DATA_DIMENSION = 1 };
218
+ // void GetValue(int row, int col, double* f) const;
219
+ // };
220
+ //
221
+ // Where, GetValue gives us the value of a function f (possibly vector
222
+ // valued) for any pairs of integers (row, col), and the enum
223
+ // DATA_DIMENSION indicates the dimensionality of the function being
224
+ // interpolated. For example if you are interpolating a color image
225
+ // with three channels (Red, Green & Blue), then DATA_DIMENSION = 3.
226
+ //
227
+ // BiCubicInterpolator uses the cubic convolution interpolation
228
+ // algorithm of R. Keys, to produce a smooth approximation to it that
229
+ // can be used to evaluate the f(r,c), df(r, c)/dr and df(r,c)/dc at
230
+ // any point in the real plane.
231
+ //
232
+ // For more details on the algorithm used here see:
233
+ //
234
+ // "Cubic convolution interpolation for digital image processing".
235
+ // Robert G. Keys, IEEE Trans. on Acoustics, Speech, and Signal
236
+ // Processing 29 (6): 1153-1160, 1981.
237
+ //
238
+ // http://en.wikipedia.org/wiki/Cubic_Hermite_spline
239
+ // http://en.wikipedia.org/wiki/Bicubic_interpolation
240
+ //
241
+ // Example usage:
242
+ //
243
+ // const double data[] = {1.0, 3.0, -1.0, 4.0,
244
+ // 3.6, 2.1, 4.2, 2.0,
245
+ // 2.0, 1.0, 3.1, 5.2};
246
+ // Grid2D<double, 1> grid(data, 3, 4);
247
+ // BiCubicInterpolator<Grid2D<double, 1>> interpolator(grid);
248
+ // double f, dfdr, dfdc;
249
+ // interpolator.Evaluate(1.2, 2.5, &f, &dfdr, &dfdc);
250
+
251
+ template <typename Grid>
252
+ class BiCubicInterpolator {
253
+ public:
254
+ explicit BiCubicInterpolator(const Grid& grid) : grid_(grid) {
255
+ // The + casts the enum into an int before doing the
256
+ // comparison. It is needed to prevent
257
+ // "-Wunnamed-type-template-args" related errors.
258
+ CHECK_GE(+Grid::DATA_DIMENSION, 1);
259
+ }
260
+
261
+ // Evaluate the interpolated function value and/or its
262
+ // derivative. Uses the nearest point on the grid boundary if r or
263
+ // c is out of bounds.
264
+ void Evaluate(
265
+ double r, double c, double* f, double* dfdr, double* dfdc) const {
266
+ // BiCubic interpolation requires 16 values around the point being
267
+ // evaluated. We will use pij, to indicate the elements of the
268
+ // 4x4 grid of values.
269
+ //
270
+ // col
271
+ // p00 p01 p02 p03
272
+ // row p10 p11 p12 p13
273
+ // p20 p21 p22 p23
274
+ // p30 p31 p32 p33
275
+ //
276
+ // The point (r,c) being evaluated is assumed to lie in the square
277
+ // defined by p11, p12, p22 and p21.
278
+
279
+ const int row = std::floor(r);
280
+ const int col = std::floor(c);
281
+
282
+ Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> p0, p1, p2, p3;
283
+
284
+ // Interpolate along each of the four rows, evaluating the function
285
+ // value and the horizontal derivative in each row.
286
+ Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> f0, f1, f2, f3;
287
+ Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> df0dc, df1dc, df2dc, df3dc;
288
+
289
+ grid_.GetValue(row - 1, col - 1, p0.data());
290
+ grid_.GetValue(row - 1, col, p1.data());
291
+ grid_.GetValue(row - 1, col + 1, p2.data());
292
+ grid_.GetValue(row - 1, col + 2, p3.data());
293
+ CubicHermiteSpline<Grid::DATA_DIMENSION>(
294
+ p0, p1, p2, p3, c - col, f0.data(), df0dc.data());
295
+
296
+ grid_.GetValue(row, col - 1, p0.data());
297
+ grid_.GetValue(row, col, p1.data());
298
+ grid_.GetValue(row, col + 1, p2.data());
299
+ grid_.GetValue(row, col + 2, p3.data());
300
+ CubicHermiteSpline<Grid::DATA_DIMENSION>(
301
+ p0, p1, p2, p3, c - col, f1.data(), df1dc.data());
302
+
303
+ grid_.GetValue(row + 1, col - 1, p0.data());
304
+ grid_.GetValue(row + 1, col, p1.data());
305
+ grid_.GetValue(row + 1, col + 1, p2.data());
306
+ grid_.GetValue(row + 1, col + 2, p3.data());
307
+ CubicHermiteSpline<Grid::DATA_DIMENSION>(
308
+ p0, p1, p2, p3, c - col, f2.data(), df2dc.data());
309
+
310
+ grid_.GetValue(row + 2, col - 1, p0.data());
311
+ grid_.GetValue(row + 2, col, p1.data());
312
+ grid_.GetValue(row + 2, col + 1, p2.data());
313
+ grid_.GetValue(row + 2, col + 2, p3.data());
314
+ CubicHermiteSpline<Grid::DATA_DIMENSION>(
315
+ p0, p1, p2, p3, c - col, f3.data(), df3dc.data());
316
+
317
+ // Interpolate vertically the interpolated value from each row and
318
+ // compute the derivative along the columns.
319
+ CubicHermiteSpline<Grid::DATA_DIMENSION>(f0, f1, f2, f3, r - row, f, dfdr);
320
+ if (dfdc != nullptr) {
321
+ // Interpolate vertically the derivative along the columns.
322
+ CubicHermiteSpline<Grid::DATA_DIMENSION>(
323
+ df0dc, df1dc, df2dc, df3dc, r - row, dfdc, nullptr);
324
+ }
325
+ }
326
+
327
+ // The following two Evaluate overloads are needed for interfacing
328
+ // with automatic differentiation. The first is for when a scalar
329
+ // evaluation is done, and the second one is for when Jets are used.
330
+ void Evaluate(const double& r, const double& c, double* f) const {
331
+ Evaluate(r, c, f, nullptr, nullptr);
332
+ }
333
+
334
+ template <typename JetT>
335
+ void Evaluate(const JetT& r, const JetT& c, JetT* f) const {
336
+ double frc[Grid::DATA_DIMENSION];
337
+ double dfdr[Grid::DATA_DIMENSION];
338
+ double dfdc[Grid::DATA_DIMENSION];
339
+ Evaluate(r.a, c.a, frc, dfdr, dfdc);
340
+ for (int i = 0; i < Grid::DATA_DIMENSION; ++i) {
341
+ f[i].a = frc[i];
342
+ f[i].v = dfdr[i] * r.v + dfdc[i] * c.v;
343
+ }
344
+ }
345
+
346
+ private:
347
+ const Grid& grid_;
348
+ };
349
+
350
+ // An object that implements an infinite two dimensional grid needed
351
+ // by the BiCubicInterpolator where the source of the function values
352
+ // is an grid of type T on the grid
353
+ //
354
+ // [(row_start, col_start), ..., (row_start, col_end - 1)]
355
+ // [ ... ]
356
+ // [(row_end - 1, col_start), ..., (row_end - 1, col_end - 1)]
357
+ //
358
+ // Since the input grid is finite and the grid is infinite, values
359
+ // outside this interval needs to be computed. Grid2D uses the value
360
+ // from the nearest edge.
361
+ //
362
+ // The function being provided can be vector valued, in which case
363
+ // kDataDimension > 1. The data maybe stored in row or column major
364
+ // format and the various dimensional slices of the function maybe
365
+ // interleaved, or they maybe stacked, i.e, if the function has
366
+ // kDataDimension = 2, is stored in row-major format and if
367
+ // kInterleaved = true, then it is stored as
368
+ //
369
+ // f001, f002, f011, f012, ...
370
+ //
371
+ // A commonly occuring example are color images (RGB) where the three
372
+ // channels are stored interleaved.
373
+ //
374
+ // If kInterleaved = false, then it is stored as
375
+ //
376
+ // f001, f011, ..., fnm1, f002, f012, ...
377
+ template <typename T,
378
+ int kDataDimension = 1,
379
+ bool kRowMajor = true,
380
+ bool kInterleaved = true>
381
+ struct Grid2D {
382
+ public:
383
+ enum { DATA_DIMENSION = kDataDimension };
384
+
385
+ Grid2D(const T* data,
386
+ const int row_begin,
387
+ const int row_end,
388
+ const int col_begin,
389
+ const int col_end)
390
+ : data_(data),
391
+ row_begin_(row_begin),
392
+ row_end_(row_end),
393
+ col_begin_(col_begin),
394
+ col_end_(col_end),
395
+ num_rows_(row_end - row_begin),
396
+ num_cols_(col_end - col_begin),
397
+ num_values_(num_rows_ * num_cols_) {
398
+ CHECK_GE(kDataDimension, 1);
399
+ CHECK_LT(row_begin, row_end);
400
+ CHECK_LT(col_begin, col_end);
401
+ }
402
+
403
+ EIGEN_STRONG_INLINE void GetValue(const int r, const int c, double* f) const {
404
+ const int row_idx =
405
+ (std::min)((std::max)(row_begin_, r), row_end_ - 1) - row_begin_;
406
+ const int col_idx =
407
+ (std::min)((std::max)(col_begin_, c), col_end_ - 1) - col_begin_;
408
+
409
+ const int n = (kRowMajor) ? num_cols_ * row_idx + col_idx
410
+ : num_rows_ * col_idx + row_idx;
411
+
412
+ if (kInterleaved) {
413
+ for (int i = 0; i < kDataDimension; ++i) {
414
+ f[i] = static_cast<double>(data_[kDataDimension * n + i]);
415
+ }
416
+ } else {
417
+ for (int i = 0; i < kDataDimension; ++i) {
418
+ f[i] = static_cast<double>(data_[i * num_values_ + n]);
419
+ }
420
+ }
421
+ }
422
+
423
+ private:
424
+ const T* data_;
425
+ const int row_begin_;
426
+ const int row_end_;
427
+ const int col_begin_;
428
+ const int col_end_;
429
+ const int num_rows_;
430
+ const int num_cols_;
431
+ const int num_values_;
432
+ };
433
+
434
+ } // namespace ceres
435
+
436
+ #endif // CERES_PUBLIC_CUBIC_INTERPOLATOR_H_
include/ceres/dynamic_autodiff_cost_function.h ADDED
@@ -0,0 +1,274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+ // mierle@gmail.com (Keir Mierle)
31
+
32
+ #ifndef CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
33
+ #define CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
34
+
35
+ #include <cmath>
36
+ #include <memory>
37
+ #include <numeric>
38
+ #include <vector>
39
+
40
+ #include "ceres/dynamic_cost_function.h"
41
+ #include "ceres/internal/fixed_array.h"
42
+ #include "ceres/jet.h"
43
+ #include "ceres/types.h"
44
+ #include "glog/logging.h"
45
+
46
+ namespace ceres {
47
+
48
+ // This autodiff implementation differs from the one found in
49
+ // autodiff_cost_function.h by supporting autodiff on cost functions
50
+ // with variable numbers of parameters with variable sizes. With the
51
+ // other implementation, all the sizes (both the number of parameter
52
+ // blocks and the size of each block) must be fixed at compile time.
53
+ //
54
+ // The functor API differs slightly from the API for fixed size
55
+ // autodiff; the expected interface for the cost functors is:
56
+ //
57
+ // struct MyCostFunctor {
58
+ // template<typename T>
59
+ // bool operator()(T const* const* parameters, T* residuals) const {
60
+ // // Use parameters[i] to access the i'th parameter block.
61
+ // }
62
+ // };
63
+ //
64
+ // Since the sizing of the parameters is done at runtime, you must
65
+ // also specify the sizes after creating the dynamic autodiff cost
66
+ // function. For example:
67
+ //
68
+ // DynamicAutoDiffCostFunction<MyCostFunctor, 3> cost_function(
69
+ // new MyCostFunctor());
70
+ // cost_function.AddParameterBlock(5);
71
+ // cost_function.AddParameterBlock(10);
72
+ // cost_function.SetNumResiduals(21);
73
+ //
74
+ // Under the hood, the implementation evaluates the cost function
75
+ // multiple times, computing a small set of the derivatives (four by
76
+ // default, controlled by the Stride template parameter) with each
77
+ // pass. There is a tradeoff with the size of the passes; you may want
78
+ // to experiment with the stride.
79
+ template <typename CostFunctor, int Stride = 4>
80
+ class DynamicAutoDiffCostFunction final : public DynamicCostFunction {
81
+ public:
82
+ // Takes ownership by default.
83
+ explicit DynamicAutoDiffCostFunction(CostFunctor* functor,
84
+ Ownership ownership = TAKE_OWNERSHIP)
85
+ : functor_(functor), ownership_(ownership) {}
86
+
87
+ DynamicAutoDiffCostFunction(DynamicAutoDiffCostFunction&& other)
88
+ : functor_(std::move(other.functor_)), ownership_(other.ownership_) {}
89
+
90
+ ~DynamicAutoDiffCostFunction() override {
91
+ // Manually release pointer if configured to not take ownership
92
+ // rather than deleting only if ownership is taken. This is to
93
+ // stay maximally compatible to old user code which may have
94
+ // forgotten to implement a virtual destructor, from when the
95
+ // AutoDiffCostFunction always took ownership.
96
+ if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
97
+ functor_.release();
98
+ }
99
+ }
100
+
101
+ bool Evaluate(double const* const* parameters,
102
+ double* residuals,
103
+ double** jacobians) const override {
104
+ CHECK_GT(num_residuals(), 0)
105
+ << "You must call DynamicAutoDiffCostFunction::SetNumResiduals() "
106
+ << "before DynamicAutoDiffCostFunction::Evaluate().";
107
+
108
+ if (jacobians == nullptr) {
109
+ return (*functor_)(parameters, residuals);
110
+ }
111
+
112
+ // The difficulty with Jets, as implemented in Ceres, is that they were
113
+ // originally designed for strictly compile-sized use. At this point, there
114
+ // is a large body of code that assumes inside a cost functor it is
115
+ // acceptable to do e.g. T(1.5) and get an appropriately sized jet back.
116
+ //
117
+ // Unfortunately, it is impossible to communicate the expected size of a
118
+ // dynamically sized jet to the static instantiations that existing code
119
+ // depends on.
120
+ //
121
+ // To work around this issue, the solution here is to evaluate the
122
+ // jacobians in a series of passes, each one computing Stride *
123
+ // num_residuals() derivatives. This is done with small, fixed-size jets.
124
+ const int num_parameter_blocks =
125
+ static_cast<int>(parameter_block_sizes().size());
126
+ const int num_parameters = std::accumulate(
127
+ parameter_block_sizes().begin(), parameter_block_sizes().end(), 0);
128
+
129
+ // Allocate scratch space for the strided evaluation.
130
+ using JetT = Jet<double, Stride>;
131
+ internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> input_jets(
132
+ num_parameters);
133
+ internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> output_jets(
134
+ num_residuals());
135
+
136
+ // Make the parameter pack that is sent to the functor (reused).
137
+ internal::FixedArray<Jet<double, Stride>*> jet_parameters(
138
+ num_parameter_blocks, nullptr);
139
+ int num_active_parameters = 0;
140
+
141
+ // To handle constant parameters between non-constant parameter blocks, the
142
+ // start position --- a raw parameter index --- of each contiguous block of
143
+ // non-constant parameters is recorded in start_derivative_section.
144
+ std::vector<int> start_derivative_section;
145
+ bool in_derivative_section = false;
146
+ int parameter_cursor = 0;
147
+
148
+ // Discover the derivative sections and set the parameter values.
149
+ for (int i = 0; i < num_parameter_blocks; ++i) {
150
+ jet_parameters[i] = &input_jets[parameter_cursor];
151
+
152
+ const int parameter_block_size = parameter_block_sizes()[i];
153
+ if (jacobians[i] != nullptr) {
154
+ if (!in_derivative_section) {
155
+ start_derivative_section.push_back(parameter_cursor);
156
+ in_derivative_section = true;
157
+ }
158
+
159
+ num_active_parameters += parameter_block_size;
160
+ } else {
161
+ in_derivative_section = false;
162
+ }
163
+
164
+ for (int j = 0; j < parameter_block_size; ++j, parameter_cursor++) {
165
+ input_jets[parameter_cursor].a = parameters[i][j];
166
+ }
167
+ }
168
+
169
+ if (num_active_parameters == 0) {
170
+ return (*functor_)(parameters, residuals);
171
+ }
172
+ // When `num_active_parameters % Stride != 0` then it can be the case
173
+ // that `active_parameter_count < Stride` while parameter_cursor is less
174
+ // than the total number of parameters and with no remaining non-constant
175
+ // parameter blocks. Pushing parameter_cursor (the total number of
176
+ // parameters) as a final entry to start_derivative_section is required
177
+ // because if a constant parameter block is encountered after the
178
+ // last non-constant block then current_derivative_section is incremented
179
+ // and would otherwise index an invalid position in
180
+ // start_derivative_section. Setting the final element to the total number
181
+ // of parameters means that this can only happen at most once in the loop
182
+ // below.
183
+ start_derivative_section.push_back(parameter_cursor);
184
+
185
+ // Evaluate all of the strides. Each stride is a chunk of the derivative to
186
+ // evaluate, typically some size proportional to the size of the SIMD
187
+ // registers of the CPU.
188
+ int num_strides = static_cast<int>(
189
+ ceil(num_active_parameters / static_cast<float>(Stride)));
190
+
191
+ int current_derivative_section = 0;
192
+ int current_derivative_section_cursor = 0;
193
+
194
+ for (int pass = 0; pass < num_strides; ++pass) {
195
+ // Set most of the jet components to zero, except for
196
+ // non-constant #Stride parameters.
197
+ const int initial_derivative_section = current_derivative_section;
198
+ const int initial_derivative_section_cursor =
199
+ current_derivative_section_cursor;
200
+
201
+ int active_parameter_count = 0;
202
+ parameter_cursor = 0;
203
+
204
+ for (int i = 0; i < num_parameter_blocks; ++i) {
205
+ for (int j = 0; j < parameter_block_sizes()[i];
206
+ ++j, parameter_cursor++) {
207
+ input_jets[parameter_cursor].v.setZero();
208
+ if (active_parameter_count < Stride &&
209
+ parameter_cursor >=
210
+ (start_derivative_section[current_derivative_section] +
211
+ current_derivative_section_cursor)) {
212
+ if (jacobians[i] != nullptr) {
213
+ input_jets[parameter_cursor].v[active_parameter_count] = 1.0;
214
+ ++active_parameter_count;
215
+ ++current_derivative_section_cursor;
216
+ } else {
217
+ ++current_derivative_section;
218
+ current_derivative_section_cursor = 0;
219
+ }
220
+ }
221
+ }
222
+ }
223
+
224
+ if (!(*functor_)(&jet_parameters[0], &output_jets[0])) {
225
+ return false;
226
+ }
227
+
228
+ // Copy the pieces of the jacobians into their final place.
229
+ active_parameter_count = 0;
230
+
231
+ current_derivative_section = initial_derivative_section;
232
+ current_derivative_section_cursor = initial_derivative_section_cursor;
233
+
234
+ for (int i = 0, parameter_cursor = 0; i < num_parameter_blocks; ++i) {
235
+ for (int j = 0; j < parameter_block_sizes()[i];
236
+ ++j, parameter_cursor++) {
237
+ if (active_parameter_count < Stride &&
238
+ parameter_cursor >=
239
+ (start_derivative_section[current_derivative_section] +
240
+ current_derivative_section_cursor)) {
241
+ if (jacobians[i] != nullptr) {
242
+ for (int k = 0; k < num_residuals(); ++k) {
243
+ jacobians[i][k * parameter_block_sizes()[i] + j] =
244
+ output_jets[k].v[active_parameter_count];
245
+ }
246
+ ++active_parameter_count;
247
+ ++current_derivative_section_cursor;
248
+ } else {
249
+ ++current_derivative_section;
250
+ current_derivative_section_cursor = 0;
251
+ }
252
+ }
253
+ }
254
+ }
255
+
256
+ // Only copy the residuals over once (even though we compute them on
257
+ // every loop).
258
+ if (pass == num_strides - 1) {
259
+ for (int k = 0; k < num_residuals(); ++k) {
260
+ residuals[k] = output_jets[k].a;
261
+ }
262
+ }
263
+ }
264
+ return true;
265
+ }
266
+
267
+ private:
268
+ std::unique_ptr<CostFunctor> functor_;
269
+ Ownership ownership_;
270
+ };
271
+
272
+ } // namespace ceres
273
+
274
+ #endif // CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
include/ceres/dynamic_cost_function.h ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+
31
+ #ifndef CERES_PUBLIC_DYNAMIC_COST_FUNCTION_H_
32
+ #define CERES_PUBLIC_DYNAMIC_COST_FUNCTION_H_
33
+
34
+ #include "ceres/cost_function.h"
35
+ #include "ceres/internal/disable_warnings.h"
36
+
37
+ namespace ceres {
38
+
39
+ // A common base class for DynamicAutoDiffCostFunction and
40
+ // DynamicNumericDiffCostFunction which depend on methods that can add
41
+ // parameter blocks and set the number of residuals at run time.
42
+ class CERES_EXPORT DynamicCostFunction : public CostFunction {
43
+ public:
44
+ virtual void AddParameterBlock(int size) {
45
+ mutable_parameter_block_sizes()->push_back(size);
46
+ }
47
+
48
+ virtual void SetNumResiduals(int num_residuals) {
49
+ set_num_residuals(num_residuals);
50
+ }
51
+ };
52
+
53
+ } // namespace ceres
54
+
55
+ #include "ceres/internal/reenable_warnings.h"
56
+
57
+ #endif // CERES_PUBLIC_DYNAMIC_COST_FUNCTION_H_
include/ceres/dynamic_cost_function_to_functor.h ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+ // dgossow@google.com (David Gossow)
31
+
32
+ #ifndef CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
33
+ #define CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
34
+
35
+ #include <memory>
36
+ #include <numeric>
37
+ #include <vector>
38
+
39
+ #include "ceres/dynamic_cost_function.h"
40
+ #include "ceres/internal/disable_warnings.h"
41
+ #include "ceres/internal/export.h"
42
+ #include "ceres/internal/fixed_array.h"
43
+ #include "glog/logging.h"
44
+
45
+ namespace ceres {
46
+
47
+ // DynamicCostFunctionToFunctor allows users to use CostFunction
48
+ // objects in templated functors which are to be used for automatic
49
+ // differentiation. It works similar to CostFunctionToFunctor, with the
50
+ // difference that it allows you to wrap a cost function with dynamic numbers
51
+ // of parameters and residuals.
52
+ //
53
+ // For example, let us assume that
54
+ //
55
+ // class IntrinsicProjection : public CostFunction {
56
+ // public:
57
+ // IntrinsicProjection(const double* observation);
58
+ // bool Evaluate(double const* const* parameters,
59
+ // double* residuals,
60
+ // double** jacobians) const override;
61
+ // };
62
+ //
63
+ // is a cost function that implements the projection of a point in its
64
+ // local coordinate system onto its image plane and subtracts it from
65
+ // the observed point projection. It can compute its residual and
66
+ // either via analytic or numerical differentiation can compute its
67
+ // jacobians. The intrinsics are passed in as parameters[0] and the point as
68
+ // parameters[1].
69
+ //
70
+ // Now we would like to compose the action of this CostFunction with
71
+ // the action of camera extrinsics, i.e., rotation and
72
+ // translation. Say we have a templated function
73
+ //
74
+ // template<typename T>
75
+ // void RotateAndTranslatePoint(double const* const* parameters,
76
+ // double* residuals);
77
+ //
78
+ // Then we can now do the following,
79
+ //
80
+ // struct CameraProjection {
81
+ // CameraProjection(const double* observation)
82
+ // : intrinsic_projection_.(new IntrinsicProjection(observation)) {
83
+ // }
84
+ // template <typename T>
85
+ // bool operator()(T const* const* parameters,
86
+ // T* residual) const {
87
+ // const T* rotation = parameters[0];
88
+ // const T* translation = parameters[1];
89
+ // const T* intrinsics = parameters[2];
90
+ // const T* point = parameters[3];
91
+ // T transformed_point[3];
92
+ // RotateAndTranslatePoint(rotation, translation, point, transformed_point);
93
+ //
94
+ // // Note that we call intrinsic_projection_, just like it was
95
+ // // any other templated functor.
96
+ // const T* projection_parameters[2];
97
+ // projection_parameters[0] = intrinsics;
98
+ // projection_parameters[1] = transformed_point;
99
+ // return intrinsic_projection_(projection_parameters, residual);
100
+ // }
101
+ //
102
+ // private:
103
+ // DynamicCostFunctionToFunctor intrinsic_projection_;
104
+ // };
105
+ class CERES_EXPORT DynamicCostFunctionToFunctor {
106
+ public:
107
+ // Takes ownership of cost_function.
108
+ explicit DynamicCostFunctionToFunctor(CostFunction* cost_function)
109
+ : cost_function_(cost_function) {
110
+ CHECK(cost_function != nullptr);
111
+ }
112
+
113
+ bool operator()(double const* const* parameters, double* residuals) const {
114
+ return cost_function_->Evaluate(parameters, residuals, nullptr);
115
+ }
116
+
117
+ template <typename JetT>
118
+ bool operator()(JetT const* const* inputs, JetT* output) const {
119
+ const std::vector<int32_t>& parameter_block_sizes =
120
+ cost_function_->parameter_block_sizes();
121
+ const int num_parameter_blocks =
122
+ static_cast<int>(parameter_block_sizes.size());
123
+ const int num_residuals = cost_function_->num_residuals();
124
+ const int num_parameters = std::accumulate(
125
+ parameter_block_sizes.begin(), parameter_block_sizes.end(), 0);
126
+
127
+ internal::FixedArray<double> parameters(num_parameters);
128
+ internal::FixedArray<double*> parameter_blocks(num_parameter_blocks);
129
+ internal::FixedArray<double> jacobians(num_residuals * num_parameters);
130
+ internal::FixedArray<double*> jacobian_blocks(num_parameter_blocks);
131
+ internal::FixedArray<double> residuals(num_residuals);
132
+
133
+ // Build a set of arrays to get the residuals and jacobians from
134
+ // the CostFunction wrapped by this functor.
135
+ double* parameter_ptr = parameters.data();
136
+ double* jacobian_ptr = jacobians.data();
137
+ for (int i = 0; i < num_parameter_blocks; ++i) {
138
+ parameter_blocks[i] = parameter_ptr;
139
+ jacobian_blocks[i] = jacobian_ptr;
140
+ for (int j = 0; j < parameter_block_sizes[i]; ++j) {
141
+ *parameter_ptr++ = inputs[i][j].a;
142
+ }
143
+ jacobian_ptr += num_residuals * parameter_block_sizes[i];
144
+ }
145
+
146
+ if (!cost_function_->Evaluate(parameter_blocks.data(),
147
+ residuals.data(),
148
+ jacobian_blocks.data())) {
149
+ return false;
150
+ }
151
+
152
+ // Now that we have the incoming Jets, which are carrying the
153
+ // partial derivatives of each of the inputs w.r.t to some other
154
+ // underlying parameters. The derivative of the outputs of the
155
+ // cost function w.r.t to the same underlying parameters can now
156
+ // be computed by applying the chain rule.
157
+ //
158
+ // d output[i] d output[i] d input[j]
159
+ // -------------- = sum_j ----------- * ------------
160
+ // d parameter[k] d input[j] d parameter[k]
161
+ //
162
+ // d input[j]
163
+ // -------------- = inputs[j], so
164
+ // d parameter[k]
165
+ //
166
+ // outputJet[i] = sum_k jacobian[i][k] * inputJet[k]
167
+ //
168
+ // The following loop, iterates over the residuals, computing one
169
+ // output jet at a time.
170
+ for (int i = 0; i < num_residuals; ++i) {
171
+ output[i].a = residuals[i];
172
+ output[i].v.setZero();
173
+
174
+ for (int j = 0; j < num_parameter_blocks; ++j) {
175
+ const int32_t block_size = parameter_block_sizes[j];
176
+ for (int k = 0; k < parameter_block_sizes[j]; ++k) {
177
+ output[i].v +=
178
+ jacobian_blocks[j][i * block_size + k] * inputs[j][k].v;
179
+ }
180
+ }
181
+ }
182
+
183
+ return true;
184
+ }
185
+
186
+ private:
187
+ std::unique_ptr<CostFunction> cost_function_;
188
+ };
189
+
190
+ } // namespace ceres
191
+
192
+ #include "ceres/internal/reenable_warnings.h"
193
+
194
+ #endif // CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
include/ceres/dynamic_numeric_diff_cost_function.h ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: mierle@gmail.com (Keir Mierle)
30
+ // sameeragarwal@google.com (Sameer Agarwal)
31
+ // thadh@gmail.com (Thad Hughes)
32
+ // tbennun@gmail.com (Tal Ben-Nun)
33
+
34
+ #ifndef CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_
35
+ #define CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_
36
+
37
+ #include <cmath>
38
+ #include <memory>
39
+ #include <numeric>
40
+ #include <vector>
41
+
42
+ #include "ceres/dynamic_cost_function.h"
43
+ #include "ceres/internal/eigen.h"
44
+ #include "ceres/internal/numeric_diff.h"
45
+ #include "ceres/internal/parameter_dims.h"
46
+ #include "ceres/numeric_diff_options.h"
47
+ #include "ceres/types.h"
48
+ #include "glog/logging.h"
49
+
50
+ namespace ceres {
51
+
52
+ // This numeric diff implementation differs from the one found in
53
+ // numeric_diff_cost_function.h by supporting numericdiff on cost
54
+ // functions with variable numbers of parameters with variable
55
+ // sizes. With the other implementation, all the sizes (both the
56
+ // number of parameter blocks and the size of each block) must be
57
+ // fixed at compile time.
58
+ //
59
+ // The functor API differs slightly from the API for fixed size
60
+ // numeric diff; the expected interface for the cost functors is:
61
+ //
62
+ // struct MyCostFunctor {
63
+ // bool operator()(double const*
64
+ // const* parameters,
65
+ // double* residuals) const {
66
+ // // Use parameters[i] to access the i'th parameter block.
67
+ // }
68
+ // }
69
+ //
70
+ // Since the sizing of the parameters is done at runtime, you must
71
+ // also specify the sizes after creating the
72
+ // DynamicNumericDiffCostFunction. For example:
73
+ //
74
+ // DynamicAutoDiffCostFunction<MyCostFunctor, CENTRAL> cost_function(
75
+ // new MyCostFunctor());
76
+ // cost_function.AddParameterBlock(5);
77
+ // cost_function.AddParameterBlock(10);
78
+ // cost_function.SetNumResiduals(21);
79
+ template <typename CostFunctor, NumericDiffMethodType method = CENTRAL>
80
+ class DynamicNumericDiffCostFunction final : public DynamicCostFunction {
81
+ public:
82
+ explicit DynamicNumericDiffCostFunction(
83
+ const CostFunctor* functor,
84
+ Ownership ownership = TAKE_OWNERSHIP,
85
+ const NumericDiffOptions& options = NumericDiffOptions())
86
+ : functor_(functor), ownership_(ownership), options_(options) {}
87
+
88
+ DynamicNumericDiffCostFunction(DynamicNumericDiffCostFunction&& other)
89
+ : functor_(std::move(other.functor_)), ownership_(other.ownership_) {}
90
+
91
+ ~DynamicNumericDiffCostFunction() override {
92
+ if (ownership_ != TAKE_OWNERSHIP) {
93
+ functor_.release();
94
+ }
95
+ }
96
+
97
+ bool Evaluate(double const* const* parameters,
98
+ double* residuals,
99
+ double** jacobians) const override {
100
+ using internal::NumericDiff;
101
+ CHECK_GT(num_residuals(), 0)
102
+ << "You must call DynamicNumericDiffCostFunction::SetNumResiduals() "
103
+ << "before DynamicNumericDiffCostFunction::Evaluate().";
104
+
105
+ const std::vector<int32_t>& block_sizes = parameter_block_sizes();
106
+ CHECK(!block_sizes.empty())
107
+ << "You must call DynamicNumericDiffCostFunction::AddParameterBlock() "
108
+ << "before DynamicNumericDiffCostFunction::Evaluate().";
109
+
110
+ const bool status =
111
+ internal::VariadicEvaluate<internal::DynamicParameterDims>(
112
+ *functor_.get(), parameters, residuals);
113
+ if (jacobians == nullptr || !status) {
114
+ return status;
115
+ }
116
+
117
+ // Create local space for a copy of the parameters which will get mutated.
118
+ int parameters_size = accumulate(block_sizes.begin(), block_sizes.end(), 0);
119
+ std::vector<double> parameters_copy(parameters_size);
120
+ std::vector<double*> parameters_references_copy(block_sizes.size());
121
+ parameters_references_copy[0] = &parameters_copy[0];
122
+ for (size_t block = 1; block < block_sizes.size(); ++block) {
123
+ parameters_references_copy[block] =
124
+ parameters_references_copy[block - 1] + block_sizes[block - 1];
125
+ }
126
+
127
+ // Copy the parameters into the local temp space.
128
+ for (size_t block = 0; block < block_sizes.size(); ++block) {
129
+ memcpy(parameters_references_copy[block],
130
+ parameters[block],
131
+ block_sizes[block] * sizeof(*parameters[block]));
132
+ }
133
+
134
+ for (size_t block = 0; block < block_sizes.size(); ++block) {
135
+ if (jacobians[block] != nullptr &&
136
+ !NumericDiff<CostFunctor,
137
+ method,
138
+ ceres::DYNAMIC,
139
+ internal::DynamicParameterDims,
140
+ ceres::DYNAMIC,
141
+ ceres::DYNAMIC>::
142
+ EvaluateJacobianForParameterBlock(functor_.get(),
143
+ residuals,
144
+ options_,
145
+ this->num_residuals(),
146
+ block,
147
+ block_sizes[block],
148
+ &parameters_references_copy[0],
149
+ jacobians[block])) {
150
+ return false;
151
+ }
152
+ }
153
+ return true;
154
+ }
155
+
156
+ private:
157
+ std::unique_ptr<const CostFunctor> functor_;
158
+ Ownership ownership_;
159
+ NumericDiffOptions options_;
160
+ };
161
+
162
+ } // namespace ceres
163
+
164
+ #endif // CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
include/ceres/evaluation_callback.h ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: mierle@gmail.com (Keir Mierle)
30
+
31
+ #ifndef CERES_PUBLIC_EVALUATION_CALLBACK_H_
32
+ #define CERES_PUBLIC_EVALUATION_CALLBACK_H_
33
+
34
+ #include "ceres/internal/export.h"
35
+
36
+ namespace ceres {
37
+
38
+ // Using this callback interface, Ceres can notify you when it is
39
+ // about to evaluate the residuals or jacobians. With the callback,
40
+ // you can share computation between residual blocks by doing the
41
+ // shared computation in PrepareForEvaluation() before Ceres calls
42
+ // CostFunction::Evaluate(). It also enables caching results between a
43
+ // pure residual evaluation and a residual & jacobian evaluation, via
44
+ // the new_evaluation_point argument.
45
+ //
46
+ // One use case for this callback is if the cost function compute is
47
+ // moved to the GPU. In that case, the prepare call does the actual
48
+ // cost function evaluation, and subsequent calls from Ceres to the
49
+ // actual cost functions merely copy the results from the GPU onto the
50
+ // corresponding blocks for Ceres to plug into the solver.
51
+ //
52
+ // NOTE: Ceres provides no mechanism to share data other than the
53
+ // notification from the callback. Users must provide access to
54
+ // pre-computed shared data to their cost functions behind the scenes;
55
+ // this all happens without Ceres knowing.
56
+ //
57
+ // One approach is to put a pointer to the shared data in each cost
58
+ // function (recommended) or to use a global shared variable
59
+ // (discouraged; bug-prone). As far as Ceres is concerned, it is
60
+ // evaluating cost functions like any other; it just so happens that
61
+ // behind the scenes the cost functions reuse pre-computed data to
62
+ // execute faster.
63
+ class CERES_EXPORT EvaluationCallback {
64
+ public:
65
+ virtual ~EvaluationCallback();
66
+
67
+ // Called before Ceres requests residuals or jacobians for a given setting of
68
+ // the parameters. User parameters (the double* values provided to the cost
69
+ // functions) are fixed until the next call to PrepareForEvaluation(). If
70
+ // new_evaluation_point == true, then this is a new point that is different
71
+ // from the last evaluated point. Otherwise, it is the same point that was
72
+ // evaluated previously (either jacobian or residual) and the user can use
73
+ // cached results from previous evaluations.
74
+ virtual void PrepareForEvaluation(bool evaluate_jacobians,
75
+ bool new_evaluation_point) = 0;
76
+ };
77
+
78
+ } // namespace ceres
79
+
80
+ #endif // CERES_PUBLIC_EVALUATION_CALLBACK_H_
include/ceres/first_order_function.h ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+
31
+ #ifndef CERES_PUBLIC_FIRST_ORDER_FUNCTION_H_
32
+ #define CERES_PUBLIC_FIRST_ORDER_FUNCTION_H_
33
+
34
+ #include "ceres/internal/export.h"
35
+
36
+ namespace ceres {
37
+
38
+ // A FirstOrderFunction object implements the evaluation of a function
39
+ // and its gradient.
40
+ class CERES_EXPORT FirstOrderFunction {
41
+ public:
42
+ virtual ~FirstOrderFunction();
43
+
44
+ // cost is never null. gradient may be null. The return value
45
+ // indicates whether the evaluation was successful or not.
46
+ virtual bool Evaluate(const double* const parameters,
47
+ double* cost,
48
+ double* gradient) const = 0;
49
+ virtual int NumParameters() const = 0;
50
+ };
51
+
52
+ } // namespace ceres
53
+
54
+ #endif // CERES_PUBLIC_FIRST_ORDER_FUNCTION_H_
include/ceres/gradient_checker.h ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ // Copyright 2007 Google Inc. All Rights Reserved.
29
+ //
30
+ // Authors: wjr@google.com (William Rucklidge),
31
+ // keir@google.com (Keir Mierle),
32
+ // dgossow@google.com (David Gossow)
33
+
34
+ #ifndef CERES_PUBLIC_GRADIENT_CHECKER_H_
35
+ #define CERES_PUBLIC_GRADIENT_CHECKER_H_
36
+
37
+ #include <memory>
38
+ #include <string>
39
+ #include <vector>
40
+
41
+ #include "ceres/cost_function.h"
42
+ #include "ceres/dynamic_numeric_diff_cost_function.h"
43
+ #include "ceres/internal/disable_warnings.h"
44
+ #include "ceres/internal/eigen.h"
45
+ #include "ceres/internal/export.h"
46
+ #include "ceres/internal/fixed_array.h"
47
+ #include "ceres/local_parameterization.h"
48
+ #include "ceres/manifold.h"
49
+ #include "glog/logging.h"
50
+
51
+ namespace ceres {
52
+
53
+ // GradientChecker compares the Jacobians returned by a cost function against
54
+ // derivatives estimated using finite differencing.
55
+ //
56
+ // The condition enforced is that
57
+ //
58
+ // (J_actual(i, j) - J_numeric(i, j))
59
+ // ------------------------------------ < relative_precision
60
+ // max(J_actual(i, j), J_numeric(i, j))
61
+ //
62
+ // where J_actual(i, j) is the jacobian as computed by the supplied cost
63
+ // function (by the user) multiplied by the local parameterization Jacobian
64
+ // and J_numeric is the jacobian as computed by finite differences, multiplied
65
+ // by the local parameterization Jacobian as well.
66
+ //
67
+ // How to use: Fill in an array of pointers to parameter blocks for your
68
+ // CostFunction, and then call Probe(). Check that the return value is 'true'.
69
+ class CERES_EXPORT GradientChecker {
70
+ public:
71
+ // This constructor will not take ownership of the cost function or local
72
+ // parameterizations.
73
+ //
74
+ // function: The cost function to probe.
75
+ //
76
+ // local_parameterizations: A vector of local parameterizations, one for each
77
+ // parameter block. May be nullptr or contain nullptrs to indicate that the
78
+ // respective parameter does not have a local parameterization.
79
+ //
80
+ // options: Options to use for numerical differentiation.
81
+ //
82
+ // NOTE: This constructor is deprecated and will be removed in the next public
83
+ // release of Ceres Solver. Please transition to using the Manifold based
84
+ // version.
85
+ CERES_DEPRECATED_WITH_MSG(
86
+ "Local Parameterizations are deprecated. Use the constructor that uses "
87
+ "Manifolds instead.")
88
+ GradientChecker(
89
+ const CostFunction* function,
90
+ const std::vector<const LocalParameterization*>* local_parameterizations,
91
+ const NumericDiffOptions& options);
92
+
93
+ // This will not take ownership of the cost function or manifolds.
94
+ //
95
+ // function: The cost function to probe.
96
+ //
97
+ // manifolds: A vector of manifolds for each parameter. May be nullptr or
98
+ // contain nullptrs to indicate that the respective parameter blocks are
99
+ // Euclidean.
100
+ //
101
+ // options: Options to use for numerical differentiation.
102
+ GradientChecker(const CostFunction* function,
103
+ const std::vector<const Manifold*>* manifolds,
104
+ const NumericDiffOptions& options);
105
+ ~GradientChecker();
106
+
107
+ // Contains results from a call to Probe for later inspection.
108
+ struct CERES_EXPORT ProbeResults {
109
+ // The return value of the cost function.
110
+ bool return_value;
111
+
112
+ // Computed residual vector.
113
+ Vector residuals;
114
+
115
+ // The sizes of the Jacobians below are dictated by the cost function's
116
+ // parameter block size and residual block sizes. If a parameter block has a
117
+ // manifold associated with it, the size of the "local" Jacobian will be
118
+ // determined by the dimension of the manifold (which is the same as the
119
+ // dimension of the tangent space) and residual block size, otherwise it
120
+ // will be identical to the regular Jacobian.
121
+
122
+ // Derivatives as computed by the cost function.
123
+ std::vector<Matrix> jacobians;
124
+
125
+ // Derivatives as computed by the cost function in local space.
126
+ std::vector<Matrix> local_jacobians;
127
+
128
+ // Derivatives as computed by numerical differentiation in local space.
129
+ std::vector<Matrix> numeric_jacobians;
130
+
131
+ // Derivatives as computed by numerical differentiation in local space.
132
+ std::vector<Matrix> local_numeric_jacobians;
133
+
134
+ // Contains the maximum relative error found in the local Jacobians.
135
+ double maximum_relative_error;
136
+
137
+ // If an error was detected, this will contain a detailed description of
138
+ // that error.
139
+ std::string error_log;
140
+ };
141
+
142
+ // Call the cost function, compute alternative Jacobians using finite
143
+ // differencing and compare results. If manifolds are given, the Jacobians
144
+ // will be multiplied by the manifold Jacobians before performing the check,
145
+ // which effectively means that all errors along the null space of the
146
+ // manifold will be ignored. Returns false if the Jacobians don't match, the
147
+ // cost function return false, or if a cost function returns a different
148
+ // residual when called with a Jacobian output argument vs. calling it
149
+ // without. Otherwise returns true.
150
+ //
151
+ // parameters: The parameter values at which to probe.
152
+ // relative_precision: A threshold for the relative difference between the
153
+ // Jacobians. If the Jacobians differ by more than this amount, then the
154
+ // probe fails.
155
+ // results: On return, the Jacobians (and other information) will be stored
156
+ // here. May be nullptr.
157
+ //
158
+ // Returns true if no problems are detected and the difference between the
159
+ // Jacobians is less than error_tolerance.
160
+ bool Probe(double const* const* parameters,
161
+ double relative_precision,
162
+ ProbeResults* results) const;
163
+
164
+ private:
165
+ GradientChecker() = delete;
166
+ GradientChecker(const GradientChecker&) = delete;
167
+ void operator=(const GradientChecker&) = delete;
168
+
169
+ // This bool is used to determine whether the constructor with the
170
+ // LocalParameterizations is called or the one with Manifolds is called. If
171
+ // the former, then the vector of manifolds is a vector of ManifoldAdapter
172
+ // objects which we own and should be deleted. If the latter then they are
173
+ // real Manifold objects owned by the caller and will not be deleted.
174
+ //
175
+ // This bool is only needed during the LocalParameterization to Manifold
176
+ // transition, once this transition is complete the LocalParameterization
177
+ // based constructor and this bool will be removed.
178
+ const bool delete_manifolds_ = false;
179
+
180
+ std::vector<const Manifold*> manifolds_;
181
+ const CostFunction* function_;
182
+ std::unique_ptr<CostFunction> finite_diff_cost_function_;
183
+ };
184
+
185
+ } // namespace ceres
186
+
187
+ #include "ceres/internal/reenable_warnings.h"
188
+
189
+ #endif // CERES_PUBLIC_GRADIENT_CHECKER_H_
include/ceres/gradient_problem.h ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+
31
+ #ifndef CERES_PUBLIC_GRADIENT_PROBLEM_H_
32
+ #define CERES_PUBLIC_GRADIENT_PROBLEM_H_
33
+
34
+ #include <memory>
35
+
36
+ #include "ceres/first_order_function.h"
37
+ #include "ceres/internal/disable_warnings.h"
38
+ #include "ceres/internal/export.h"
39
+ #include "ceres/local_parameterization.h"
40
+ #include "ceres/manifold.h"
41
+
42
+ namespace ceres {
43
+
44
+ class FirstOrderFunction;
45
+
46
+ // Instances of GradientProblem represent general non-linear
47
+ // optimization problems that must be solved using just the value of
48
+ // the objective function and its gradient.
49
+
50
+ // Unlike the Problem class, which can only be used to model non-linear least
51
+ // squares problems, instances of GradientProblem are not restricted in the form
52
+ // of the objective function.
53
+ //
54
+ // Structurally GradientProblem is a composition of a FirstOrderFunction and
55
+ // optionally a Manifold.
56
+ //
57
+ // The FirstOrderFunction is responsible for evaluating the cost and gradient of
58
+ // the objective function.
59
+ //
60
+ // The Manifold is responsible for going back and forth between the ambient
61
+ // space and the local tangent space. (See manifold.h for more details). When a
62
+ // Manifold is not provided, then the tangent space is assumed to coincide with
63
+ // the ambient Euclidean space that the gradient vector lives in.
64
+ //
65
+ // Example usage:
66
+ //
67
+ // The following demonstrate the problem construction for Rosenbrock's function
68
+ //
69
+ // f(x,y) = (1-x)^2 + 100(y - x^2)^2;
70
+ //
71
+ // class Rosenbrock : public ceres::FirstOrderFunction {
72
+ // public:
73
+ // virtual ~Rosenbrock() {}
74
+ //
75
+ // virtual bool Evaluate(const double* parameters,
76
+ // double* cost,
77
+ // double* gradient) const {
78
+ // const double x = parameters[0];
79
+ // const double y = parameters[1];
80
+ //
81
+ // cost[0] = (1.0 - x) * (1.0 - x) + 100.0 * (y - x * x) * (y - x * x);
82
+ // if (gradient != nullptr) {
83
+ // gradient[0] = -2.0 * (1.0 - x) - 200.0 * (y - x * x) * 2.0 * x;
84
+ // gradient[1] = 200.0 * (y - x * x);
85
+ // }
86
+ // return true;
87
+ // };
88
+ //
89
+ // virtual int NumParameters() const { return 2; };
90
+ // };
91
+ //
92
+ // ceres::GradientProblem problem(new Rosenbrock());
93
+ //
94
+ // NOTE: We are currently in the process of transitioning from
95
+ // LocalParameterization to Manifolds in the Ceres API. During this period,
96
+ // GradientProblem will support using both Manifold and LocalParameterization
97
+ // objects interchangably. For methods in the API affected by this change, see
98
+ // their documentation below.
99
+ class CERES_EXPORT GradientProblem {
100
+ public:
101
+ // Takes ownership of the function.
102
+ explicit GradientProblem(FirstOrderFunction* function);
103
+
104
+ // Takes ownership of the function and the parameterization.
105
+ //
106
+ // NOTE: This constructor is deprecated and will be removed in the next public
107
+ // release of Ceres Solver. Please move to using the Manifold based
108
+ // constructor.
109
+ CERES_DEPRECATED_WITH_MSG(
110
+ "LocalParameterizations are deprecated. Please use the constructor that "
111
+ "uses Manifold instead.")
112
+ GradientProblem(FirstOrderFunction* function,
113
+ LocalParameterization* parameterization);
114
+
115
+ // Takes ownership of the function and the manifold.
116
+ GradientProblem(FirstOrderFunction* function, Manifold* manifold);
117
+
118
+ int NumParameters() const;
119
+
120
+ // Dimension of the manifold (and its tangent space).
121
+ //
122
+ // During the transition from LocalParameterization to Manifold, this method
123
+ // reports the LocalSize of the LocalParameterization or the TangentSize of
124
+ // the Manifold object associated with this problem.
125
+ int NumTangentParameters() const;
126
+
127
+ // Dimension of the manifold (and its tangent space).
128
+ //
129
+ // NOTE: This method is deprecated and will be removed in the next public
130
+ // release of Ceres Solver. Please move to using NumTangentParameters()
131
+ // instead.
132
+ int NumLocalParameters() const { return NumTangentParameters(); }
133
+
134
+ // This call is not thread safe.
135
+ bool Evaluate(const double* parameters, double* cost, double* gradient) const;
136
+ bool Plus(const double* x, const double* delta, double* x_plus_delta) const;
137
+
138
+ const FirstOrderFunction* function() const { return function_.get(); }
139
+ FirstOrderFunction* mutable_function() { return function_.get(); }
140
+
141
+ // NOTE: During the transition from LocalParameterization to Manifold we need
142
+ // to support both The LocalParameterization and Manifold based constructors.
143
+ //
144
+ // When the user uses the LocalParameterization, internally the solver will
145
+ // wrap it in a ManifoldAdapter object and return it when manifold or
146
+ // mutable_manifold are called.
147
+ //
148
+ // As a result this method will return a non-nullptr result if a Manifold or a
149
+ // LocalParameterization was used when constructing the GradientProblem.
150
+ const Manifold* manifold() const { return manifold_.get(); }
151
+ Manifold* mutable_manifold() { return manifold_.get(); }
152
+
153
+ // If the problem is constructed without a LocalParameterization or with a
154
+ // Manifold this method will return a nullptr.
155
+ //
156
+ // NOTE: This method is deprecated and will be removed in the next public
157
+ // release of Ceres Solver.
158
+ CERES_DEPRECATED_WITH_MSG("Use Manifolds instead.")
159
+ const LocalParameterization* parameterization() const {
160
+ return parameterization_.get();
161
+ }
162
+
163
+ // If the problem is constructed without a LocalParameterization or with a
164
+ // Manifold this method will return a nullptr.
165
+ //
166
+ // NOTE: This method is deprecated and will be removed in the next public
167
+ // release of Ceres Solver.
168
+ CERES_DEPRECATED_WITH_MSG("Use Manifolds instead.")
169
+ LocalParameterization* mutable_parameterization() {
170
+ return parameterization_.get();
171
+ }
172
+
173
+ private:
174
+ std::unique_ptr<FirstOrderFunction> function_;
175
+ CERES_DEPRECATED_WITH_MSG("")
176
+ std::unique_ptr<LocalParameterization> parameterization_;
177
+ std::unique_ptr<Manifold> manifold_;
178
+ std::unique_ptr<double[]> scratch_;
179
+ };
180
+
181
+ } // namespace ceres
182
+
183
+ #include "ceres/internal/reenable_warnings.h"
184
+
185
+ #endif // CERES_PUBLIC_GRADIENT_PROBLEM_H_
include/ceres/gradient_problem_solver.h ADDED
@@ -0,0 +1,357 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+
31
+ #ifndef CERES_PUBLIC_GRADIENT_PROBLEM_SOLVER_H_
32
+ #define CERES_PUBLIC_GRADIENT_PROBLEM_SOLVER_H_
33
+
34
+ #include <cmath>
35
+ #include <string>
36
+ #include <vector>
37
+
38
+ #include "ceres/internal/disable_warnings.h"
39
+ #include "ceres/internal/export.h"
40
+ #include "ceres/internal/port.h"
41
+ #include "ceres/iteration_callback.h"
42
+ #include "ceres/types.h"
43
+
44
+ namespace ceres {
45
+
46
+ class GradientProblem;
47
+
48
+ class CERES_EXPORT GradientProblemSolver {
49
+ public:
50
+ virtual ~GradientProblemSolver();
51
+
52
+ // The options structure contains, not surprisingly, options that control how
53
+ // the solver operates. The defaults should be suitable for a wide range of
54
+ // problems; however, better performance is often obtainable with tweaking.
55
+ //
56
+ // The constants are defined inside types.h
57
+ struct CERES_EXPORT Options {
58
+ // Returns true if the options struct has a valid
59
+ // configuration. Returns false otherwise, and fills in *error
60
+ // with a message describing the problem.
61
+ bool IsValid(std::string* error) const;
62
+
63
+ // Minimizer options ----------------------------------------
64
+ LineSearchDirectionType line_search_direction_type = LBFGS;
65
+ LineSearchType line_search_type = WOLFE;
66
+ NonlinearConjugateGradientType nonlinear_conjugate_gradient_type =
67
+ FLETCHER_REEVES;
68
+
69
+ // The LBFGS hessian approximation is a low rank approximation to
70
+ // the inverse of the Hessian matrix. The rank of the
71
+ // approximation determines (linearly) the space and time
72
+ // complexity of using the approximation. Higher the rank, the
73
+ // better is the quality of the approximation. The increase in
74
+ // quality is however is bounded for a number of reasons.
75
+ //
76
+ // 1. The method only uses secant information and not actual
77
+ // derivatives.
78
+ //
79
+ // 2. The Hessian approximation is constrained to be positive
80
+ // definite.
81
+ //
82
+ // So increasing this rank to a large number will cost time and
83
+ // space complexity without the corresponding increase in solution
84
+ // quality. There are no hard and fast rules for choosing the
85
+ // maximum rank. The best choice usually requires some problem
86
+ // specific experimentation.
87
+ //
88
+ // For more theoretical and implementation details of the LBFGS
89
+ // method, please see:
90
+ //
91
+ // Nocedal, J. (1980). "Updating Quasi-Newton Matrices with
92
+ // Limited Storage". Mathematics of Computation 35 (151): 773-782.
93
+ int max_lbfgs_rank = 20;
94
+
95
+ // As part of the (L)BFGS update step (BFGS) / right-multiply step (L-BFGS),
96
+ // the initial inverse Hessian approximation is taken to be the Identity.
97
+ // However, Oren showed that using instead I * \gamma, where \gamma is
98
+ // chosen to approximate an eigenvalue of the true inverse Hessian can
99
+ // result in improved convergence in a wide variety of cases. Setting
100
+ // use_approximate_eigenvalue_bfgs_scaling to true enables this scaling.
101
+ //
102
+ // It is important to note that approximate eigenvalue scaling does not
103
+ // always improve convergence, and that it can in fact significantly degrade
104
+ // performance for certain classes of problem, which is why it is disabled
105
+ // by default. In particular it can degrade performance when the
106
+ // sensitivity of the problem to different parameters varies significantly,
107
+ // as in this case a single scalar factor fails to capture this variation
108
+ // and detrimentally downscales parts of the jacobian approximation which
109
+ // correspond to low-sensitivity parameters. It can also reduce the
110
+ // robustness of the solution to errors in the jacobians.
111
+ //
112
+ // Oren S.S., Self-scaling variable metric (SSVM) algorithms
113
+ // Part II: Implementation and experiments, Management Science,
114
+ // 20(5), 863-874, 1974.
115
+ bool use_approximate_eigenvalue_bfgs_scaling = false;
116
+
117
+ // Degree of the polynomial used to approximate the objective
118
+ // function. Valid values are BISECTION, QUADRATIC and CUBIC.
119
+ //
120
+ // BISECTION corresponds to pure backtracking search with no
121
+ // interpolation.
122
+ LineSearchInterpolationType line_search_interpolation_type = CUBIC;
123
+
124
+ // If during the line search, the step_size falls below this
125
+ // value, it is truncated to zero.
126
+ double min_line_search_step_size = 1e-9;
127
+
128
+ // Line search parameters.
129
+
130
+ // Solving the line search problem exactly is computationally
131
+ // prohibitive. Fortunately, line search based optimization
132
+ // algorithms can still guarantee convergence if instead of an
133
+ // exact solution, the line search algorithm returns a solution
134
+ // which decreases the value of the objective function
135
+ // sufficiently. More precisely, we are looking for a step_size
136
+ // s.t.
137
+ //
138
+ // f(step_size) <= f(0) + sufficient_decrease * f'(0) * step_size
139
+ //
140
+ double line_search_sufficient_function_decrease = 1e-4;
141
+
142
+ // In each iteration of the line search,
143
+ //
144
+ // new_step_size >= max_line_search_step_contraction * step_size
145
+ //
146
+ // Note that by definition, for contraction:
147
+ //
148
+ // 0 < max_step_contraction < min_step_contraction < 1
149
+ //
150
+ double max_line_search_step_contraction = 1e-3;
151
+
152
+ // In each iteration of the line search,
153
+ //
154
+ // new_step_size <= min_line_search_step_contraction * step_size
155
+ //
156
+ // Note that by definition, for contraction:
157
+ //
158
+ // 0 < max_step_contraction < min_step_contraction < 1
159
+ //
160
+ double min_line_search_step_contraction = 0.6;
161
+
162
+ // Maximum number of trial step size iterations during each line search,
163
+ // if a step size satisfying the search conditions cannot be found within
164
+ // this number of trials, the line search will terminate.
165
+ int max_num_line_search_step_size_iterations = 20;
166
+
167
+ // Maximum number of restarts of the line search direction algorithm before
168
+ // terminating the optimization. Restarts of the line search direction
169
+ // algorithm occur when the current algorithm fails to produce a new descent
170
+ // direction. This typically indicates a numerical failure, or a breakdown
171
+ // in the validity of the approximations used.
172
+ int max_num_line_search_direction_restarts = 5;
173
+
174
+ // The strong Wolfe conditions consist of the Armijo sufficient
175
+ // decrease condition, and an additional requirement that the
176
+ // step-size be chosen s.t. the _magnitude_ ('strong' Wolfe
177
+ // conditions) of the gradient along the search direction
178
+ // decreases sufficiently. Precisely, this second condition
179
+ // is that we seek a step_size s.t.
180
+ //
181
+ // |f'(step_size)| <= sufficient_curvature_decrease * |f'(0)|
182
+ //
183
+ // Where f() is the line search objective and f'() is the derivative
184
+ // of f w.r.t step_size (d f / d step_size).
185
+ double line_search_sufficient_curvature_decrease = 0.9;
186
+
187
+ // During the bracketing phase of the Wolfe search, the step size is
188
+ // increased until either a point satisfying the Wolfe conditions is
189
+ // found, or an upper bound for a bracket containing a point satisfying
190
+ // the conditions is found. Precisely, at each iteration of the
191
+ // expansion:
192
+ //
193
+ // new_step_size <= max_step_expansion * step_size.
194
+ //
195
+ // By definition for expansion, max_step_expansion > 1.0.
196
+ double max_line_search_step_expansion = 10.0;
197
+
198
+ // Maximum number of iterations for the minimizer to run for.
199
+ int max_num_iterations = 50;
200
+
201
+ // Maximum time for which the minimizer should run for.
202
+ double max_solver_time_in_seconds = 1e9;
203
+
204
+ // Minimizer terminates when
205
+ //
206
+ // (new_cost - old_cost) < function_tolerance * old_cost;
207
+ //
208
+ double function_tolerance = 1e-6;
209
+
210
+ // Minimizer terminates when
211
+ //
212
+ // max_i |x - Project(Plus(x, -g(x))| < gradient_tolerance
213
+ //
214
+ // This value should typically be 1e-4 * function_tolerance.
215
+ double gradient_tolerance = 1e-10;
216
+
217
+ // Minimizer terminates when
218
+ //
219
+ // |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance)
220
+ //
221
+ double parameter_tolerance = 1e-8;
222
+
223
+ // Logging options ---------------------------------------------------------
224
+
225
+ LoggingType logging_type = PER_MINIMIZER_ITERATION;
226
+
227
+ // By default the Minimizer progress is logged to VLOG(1), which
228
+ // is sent to STDERR depending on the vlog level. If this flag is
229
+ // set to true, and logging_type is not SILENT, the logging output
230
+ // is sent to STDOUT.
231
+ bool minimizer_progress_to_stdout = false;
232
+
233
+ // If true, the user's parameter blocks are updated at the end of
234
+ // every Minimizer iteration, otherwise they are updated when the
235
+ // Minimizer terminates. This is useful if, for example, the user
236
+ // wishes to visualize the state of the optimization every
237
+ // iteration.
238
+ bool update_state_every_iteration = false;
239
+
240
+ // Callbacks that are executed at the end of each iteration of the
241
+ // Minimizer. An iteration may terminate midway, either due to
242
+ // numerical failures or because one of the convergence tests has
243
+ // been satisfied. In this case none of the callbacks are
244
+ // executed.
245
+
246
+ // Callbacks are executed in the order that they are specified in
247
+ // this vector. By default, parameter blocks are updated only at
248
+ // the end of the optimization, i.e when the Minimizer
249
+ // terminates. This behaviour is controlled by
250
+ // update_state_every_variable. If the user wishes to have access
251
+ // to the update parameter blocks when his/her callbacks are
252
+ // executed, then set update_state_every_iteration to true.
253
+ //
254
+ // The solver does NOT take ownership of these pointers.
255
+ std::vector<IterationCallback*> callbacks;
256
+ };
257
+
258
+ struct CERES_EXPORT Summary {
259
+ // A brief one line description of the state of the solver after
260
+ // termination.
261
+ std::string BriefReport() const;
262
+
263
+ // A full multiline description of the state of the solver after
264
+ // termination.
265
+ std::string FullReport() const;
266
+
267
+ bool IsSolutionUsable() const;
268
+
269
+ // Minimizer summary -------------------------------------------------
270
+ TerminationType termination_type = FAILURE;
271
+
272
+ // Reason why the solver terminated.
273
+ std::string message = "ceres::GradientProblemSolve was not called.";
274
+
275
+ // Cost of the problem (value of the objective function) before
276
+ // the optimization.
277
+ double initial_cost = -1.0;
278
+
279
+ // Cost of the problem (value of the objective function) after the
280
+ // optimization.
281
+ double final_cost = -1.0;
282
+
283
+ // IterationSummary for each minimizer iteration in order.
284
+ std::vector<IterationSummary> iterations;
285
+
286
+ // Number of times the cost (and not the gradient) was evaluated.
287
+ int num_cost_evaluations = -1;
288
+
289
+ // Number of times the gradient (and the cost) were evaluated.
290
+ int num_gradient_evaluations = -1;
291
+
292
+ // Sum total of all time spent inside Ceres when Solve is called.
293
+ double total_time_in_seconds = -1.0;
294
+
295
+ // Time (in seconds) spent evaluating the cost.
296
+ double cost_evaluation_time_in_seconds = -1.0;
297
+
298
+ // Time (in seconds) spent evaluating the gradient.
299
+ double gradient_evaluation_time_in_seconds = -1.0;
300
+
301
+ // Time (in seconds) spent minimizing the interpolating polynomial
302
+ // to compute the next candidate step size as part of a line search.
303
+ double line_search_polynomial_minimization_time_in_seconds = -1.0;
304
+
305
+ // Number of parameters in the problem.
306
+ int num_parameters = -1;
307
+
308
+ // Dimension of the tangent space of the problem.
309
+ CERES_DEPRECATED_WITH_MSG("Use num_tangent_parameters.")
310
+ int num_local_parameters = -1;
311
+
312
+ // Dimension of the tangent space of the problem.
313
+ int num_tangent_parameters = -1;
314
+
315
+ // Type of line search direction used.
316
+ LineSearchDirectionType line_search_direction_type = LBFGS;
317
+
318
+ // Type of the line search algorithm used.
319
+ LineSearchType line_search_type = WOLFE;
320
+
321
+ // When performing line search, the degree of the polynomial used
322
+ // to approximate the objective function.
323
+ LineSearchInterpolationType line_search_interpolation_type = CUBIC;
324
+
325
+ // If the line search direction is NONLINEAR_CONJUGATE_GRADIENT,
326
+ // then this indicates the particular variant of non-linear
327
+ // conjugate gradient used.
328
+ NonlinearConjugateGradientType nonlinear_conjugate_gradient_type =
329
+ FLETCHER_REEVES;
330
+
331
+ // If the type of the line search direction is LBFGS, then this
332
+ // indicates the rank of the Hessian approximation.
333
+ int max_lbfgs_rank = -1;
334
+ };
335
+
336
+ // Once a least squares problem has been built, this function takes
337
+ // the problem and optimizes it based on the values of the options
338
+ // parameters. Upon return, a detailed summary of the work performed
339
+ // by the preprocessor, the non-linear minimizer and the linear
340
+ // solver are reported in the summary object.
341
+ virtual void Solve(const GradientProblemSolver::Options& options,
342
+ const GradientProblem& problem,
343
+ double* parameters,
344
+ GradientProblemSolver::Summary* summary);
345
+ };
346
+
347
+ // Helper function which avoids going through the interface.
348
+ CERES_EXPORT void Solve(const GradientProblemSolver::Options& options,
349
+ const GradientProblem& problem,
350
+ double* parameters,
351
+ GradientProblemSolver::Summary* summary);
352
+
353
+ } // namespace ceres
354
+
355
+ #include "ceres/internal/reenable_warnings.h"
356
+
357
+ #endif // CERES_PUBLIC_GRADIENT_PROBLEM_SOLVER_H_
include/ceres/internal/array_selector.h ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2020 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: darius.rueckert@fau.de (Darius Rueckert)
30
+ //
31
+
32
+ #ifndef CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
33
+ #define CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
34
+
35
+ #include <array>
36
+ #include <vector>
37
+
38
+ #include "ceres/internal/fixed_array.h"
39
+ #include "ceres/types.h"
40
+
41
+ namespace ceres {
42
+ namespace internal {
43
+
44
+ // StaticFixedArray selects the best array implementation based on template
45
+ // arguments. If the size is not known at compile-time, pass
46
+ // ceres::DYNAMIC as a size-template argument.
47
+ //
48
+ // Three different containers are selected in different scenarios:
49
+ //
50
+ // num_elements == DYNAMIC:
51
+ // -> ceres::internal::FixedArray<T, max_stack_size>(size)
52
+
53
+ // num_elements != DYNAMIC && num_elements <= max_stack_size
54
+ // -> std::array<T,num_elements>
55
+
56
+ // num_elements != DYNAMIC && num_elements > max_stack_size
57
+ // -> std::vector<T>(num_elements)
58
+ //
59
+ template <typename T,
60
+ int num_elements,
61
+ int max_num_elements_on_stack,
62
+ bool dynamic = (num_elements == DYNAMIC),
63
+ bool fits_on_stack = (num_elements <= max_num_elements_on_stack)>
64
+ struct ArraySelector {};
65
+
66
+ template <typename T,
67
+ int num_elements,
68
+ int max_num_elements_on_stack,
69
+ bool fits_on_stack>
70
+ struct ArraySelector<T,
71
+ num_elements,
72
+ max_num_elements_on_stack,
73
+ true,
74
+ fits_on_stack>
75
+ : ceres::internal::FixedArray<T, max_num_elements_on_stack> {
76
+ explicit ArraySelector(int s)
77
+ : ceres::internal::FixedArray<T, max_num_elements_on_stack>(s) {}
78
+ };
79
+
80
+ template <typename T, int num_elements, int max_num_elements_on_stack>
81
+ struct ArraySelector<T, num_elements, max_num_elements_on_stack, false, true>
82
+ : std::array<T, num_elements> {
83
+ explicit ArraySelector(int s) { CHECK_EQ(s, num_elements); }
84
+ };
85
+
86
+ template <typename T, int num_elements, int max_num_elements_on_stack>
87
+ struct ArraySelector<T, num_elements, max_num_elements_on_stack, false, false>
88
+ : std::vector<T> {
89
+ explicit ArraySelector(int s) : std::vector<T>(s) {
90
+ CHECK_EQ(s, num_elements);
91
+ }
92
+ };
93
+
94
+ } // namespace internal
95
+ } // namespace ceres
96
+
97
+ #endif // CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
include/ceres/internal/autodiff.h ADDED
@@ -0,0 +1,365 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2019 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: keir@google.com (Keir Mierle)
30
+ //
31
+ // Computation of the Jacobian matrix for vector-valued functions of multiple
32
+ // variables, using automatic differentiation based on the implementation of
33
+ // dual numbers in jet.h. Before reading the rest of this file, it is advisable
34
+ // to read jet.h's header comment in detail.
35
+ //
36
+ // The helper wrapper AutoDifferentiate() computes the jacobian of
37
+ // functors with templated operator() taking this form:
38
+ //
39
+ // struct F {
40
+ // template<typename T>
41
+ // bool operator()(const T *x, const T *y, ..., T *z) {
42
+ // // Compute z[] based on x[], y[], ...
43
+ // // return true if computation succeeded, false otherwise.
44
+ // }
45
+ // };
46
+ //
47
+ // All inputs and outputs may be vector-valued.
48
+ //
49
+ // To understand how jets are used to compute the jacobian, a
50
+ // picture may help. Consider a vector-valued function, F, returning 3
51
+ // dimensions and taking a vector-valued parameter of 4 dimensions:
52
+ //
53
+ // y x
54
+ // [ * ] F [ * ]
55
+ // [ * ] <--- [ * ]
56
+ // [ * ] [ * ]
57
+ // [ * ]
58
+ //
59
+ // Similar to the 2-parameter example for f described in jet.h, computing the
60
+ // jacobian dy/dx is done by substituting a suitable jet object for x and all
61
+ // intermediate steps of the computation of F. Since x is has 4 dimensions, use
62
+ // a Jet<double, 4>.
63
+ //
64
+ // Before substituting a jet object for x, the dual components are set
65
+ // appropriately for each dimension of x:
66
+ //
67
+ // y x
68
+ // [ * | * * * * ] f [ * | 1 0 0 0 ] x0
69
+ // [ * | * * * * ] <--- [ * | 0 1 0 0 ] x1
70
+ // [ * | * * * * ] [ * | 0 0 1 0 ] x2
71
+ // ---+--- [ * | 0 0 0 1 ] x3
72
+ // | ^ ^ ^ ^
73
+ // dy/dx | | | +----- infinitesimal for x3
74
+ // | | +------- infinitesimal for x2
75
+ // | +--------- infinitesimal for x1
76
+ // +----------- infinitesimal for x0
77
+ //
78
+ // The reason to set the internal 4x4 submatrix to the identity is that we wish
79
+ // to take the derivative of y separately with respect to each dimension of x.
80
+ // Each column of the 4x4 identity is therefore for a single component of the
81
+ // independent variable x.
82
+ //
83
+ // Then the jacobian of the mapping, dy/dx, is the 3x4 sub-matrix of the
84
+ // extended y vector, indicated in the above diagram.
85
+ //
86
+ // Functors with multiple parameters
87
+ // ---------------------------------
88
+ // In practice, it is often convenient to use a function f of two or more
89
+ // vector-valued parameters, for example, x[3] and z[6]. Unfortunately, the jet
90
+ // framework is designed for a single-parameter vector-valued input. The wrapper
91
+ // in this file addresses this issue adding support for functions with one or
92
+ // more parameter vectors.
93
+ //
94
+ // To support multiple parameters, all the parameter vectors are concatenated
95
+ // into one and treated as a single parameter vector, except that since the
96
+ // functor expects different inputs, we need to construct the jets as if they
97
+ // were part of a single parameter vector. The extended jets are passed
98
+ // separately for each parameter.
99
+ //
100
+ // For example, consider a functor F taking two vector parameters, p[2] and
101
+ // q[3], and producing an output y[4]:
102
+ //
103
+ // struct F {
104
+ // template<typename T>
105
+ // bool operator()(const T *p, const T *q, T *z) {
106
+ // // ...
107
+ // }
108
+ // };
109
+ //
110
+ // In this case, the necessary jet type is Jet<double, 5>. Here is a
111
+ // visualization of the jet objects in this case:
112
+ //
113
+ // Dual components for p ----+
114
+ // |
115
+ // -+-
116
+ // y [ * | 1 0 | 0 0 0 ] --- p[0]
117
+ // [ * | 0 1 | 0 0 0 ] --- p[1]
118
+ // [ * | . . | + + + ] |
119
+ // [ * | . . | + + + ] v
120
+ // [ * | . . | + + + ] <--- F(p, q)
121
+ // [ * | . . | + + + ] ^
122
+ // ^^^ ^^^^^ |
123
+ // dy/dp dy/dq [ * | 0 0 | 1 0 0 ] --- q[0]
124
+ // [ * | 0 0 | 0 1 0 ] --- q[1]
125
+ // [ * | 0 0 | 0 0 1 ] --- q[2]
126
+ // --+--
127
+ // |
128
+ // Dual components for q --------------+
129
+ //
130
+ // where the 4x2 submatrix (marked with ".") and 4x3 submatrix (marked with "+"
131
+ // of y in the above diagram are the derivatives of y with respect to p and q
132
+ // respectively. This is how autodiff works for functors taking multiple vector
133
+ // valued arguments (up to 6).
134
+ //
135
+ // Jacobian null pointers (nullptr)
136
+ // --------------------------------
137
+ // In general, the functions below will accept nullptr for all or some of the
138
+ // Jacobian parameters, meaning that those Jacobians will not be computed.
139
+
140
+ #ifndef CERES_PUBLIC_INTERNAL_AUTODIFF_H_
141
+ #define CERES_PUBLIC_INTERNAL_AUTODIFF_H_
142
+
143
+ #include <array>
144
+ #include <cstddef>
145
+ #include <utility>
146
+
147
+ #include "ceres/internal/array_selector.h"
148
+ #include "ceres/internal/eigen.h"
149
+ #include "ceres/internal/fixed_array.h"
150
+ #include "ceres/internal/parameter_dims.h"
151
+ #include "ceres/internal/variadic_evaluate.h"
152
+ #include "ceres/jet.h"
153
+ #include "ceres/types.h"
154
+ #include "glog/logging.h"
155
+
156
+ // If the number of parameters exceeds this values, the corresponding jets are
157
+ // placed on the heap. This will reduce performance by a factor of 2-5 on
158
+ // current compilers.
159
+ #ifndef CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK
160
+ #define CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK 50
161
+ #endif
162
+
163
+ #ifndef CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK
164
+ #define CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK 20
165
+ #endif
166
+
167
+ namespace ceres {
168
+ namespace internal {
169
+
170
+ // Extends src by a 1st order perturbation for every dimension and puts it in
171
+ // dst. The size of src is N. Since this is also used for perturbations in
172
+ // blocked arrays, offset is used to shift which part of the jet the
173
+ // perturbation occurs. This is used to set up the extended x augmented by an
174
+ // identity matrix. The JetT type should be a Jet type, and T should be a
175
+ // numeric type (e.g. double). For example,
176
+ //
177
+ // 0 1 2 3 4 5 6 7 8
178
+ // dst[0] [ * | . . | 1 0 0 | . . . ]
179
+ // dst[1] [ * | . . | 0 1 0 | . . . ]
180
+ // dst[2] [ * | . . | 0 0 1 | . . . ]
181
+ //
182
+ // is what would get put in dst if N was 3, offset was 3, and the jet type JetT
183
+ // was 8-dimensional.
184
+ template <int j, int N, int Offset, typename T, typename JetT>
185
+ struct Make1stOrderPerturbation {
186
+ public:
187
+ inline static void Apply(const T* src, JetT* dst) {
188
+ if (j == 0) {
189
+ DCHECK(src);
190
+ DCHECK(dst);
191
+ }
192
+ dst[j] = JetT(src[j], j + Offset);
193
+ Make1stOrderPerturbation<j + 1, N, Offset, T, JetT>::Apply(src, dst);
194
+ }
195
+ };
196
+
197
+ template <int N, int Offset, typename T, typename JetT>
198
+ struct Make1stOrderPerturbation<N, N, Offset, T, JetT> {
199
+ public:
200
+ static void Apply(const T* /* NOT USED */, JetT* /* NOT USED */) {}
201
+ };
202
+
203
+ // Calls Make1stOrderPerturbation for every parameter block.
204
+ //
205
+ // Example:
206
+ // If one having three parameter blocks with dimensions (3, 2, 4), the call
207
+ // Make1stOrderPerturbations<integer_sequence<3, 2, 4>::Apply(params, x);
208
+ // will result in the following calls to Make1stOrderPerturbation:
209
+ // Make1stOrderPerturbation<0, 3, 0>::Apply(params[0], x + 0);
210
+ // Make1stOrderPerturbation<0, 2, 3>::Apply(params[1], x + 3);
211
+ // Make1stOrderPerturbation<0, 4, 5>::Apply(params[2], x + 5);
212
+ template <typename Seq, int ParameterIdx = 0, int Offset = 0>
213
+ struct Make1stOrderPerturbations;
214
+
215
+ template <int N, int... Ns, int ParameterIdx, int Offset>
216
+ struct Make1stOrderPerturbations<std::integer_sequence<int, N, Ns...>,
217
+ ParameterIdx,
218
+ Offset> {
219
+ template <typename T, typename JetT>
220
+ inline static void Apply(T const* const* parameters, JetT* x) {
221
+ Make1stOrderPerturbation<0, N, Offset, T, JetT>::Apply(
222
+ parameters[ParameterIdx], x + Offset);
223
+ Make1stOrderPerturbations<std::integer_sequence<int, Ns...>,
224
+ ParameterIdx + 1,
225
+ Offset + N>::Apply(parameters, x);
226
+ }
227
+ };
228
+
229
+ // End of 'recursion'. Nothing more to do.
230
+ template <int ParameterIdx, int Total>
231
+ struct Make1stOrderPerturbations<std::integer_sequence<int>,
232
+ ParameterIdx,
233
+ Total> {
234
+ template <typename T, typename JetT>
235
+ static void Apply(T const* const* /* NOT USED */, JetT* /* NOT USED */) {}
236
+ };
237
+
238
+ // Takes the 0th order part of src, assumed to be a Jet type, and puts it in
239
+ // dst. This is used to pick out the "vector" part of the extended y.
240
+ template <typename JetT, typename T>
241
+ inline void Take0thOrderPart(int M, const JetT* src, T dst) {
242
+ DCHECK(src);
243
+ for (int i = 0; i < M; ++i) {
244
+ dst[i] = src[i].a;
245
+ }
246
+ }
247
+
248
+ // Takes N 1st order parts, starting at index N0, and puts them in the M x N
249
+ // matrix 'dst'. This is used to pick out the "matrix" parts of the extended y.
250
+ template <int N0, int N, typename JetT, typename T>
251
+ inline void Take1stOrderPart(const int M, const JetT* src, T* dst) {
252
+ DCHECK(src);
253
+ DCHECK(dst);
254
+ for (int i = 0; i < M; ++i) {
255
+ Eigen::Map<Eigen::Matrix<T, N, 1>>(dst + N * i, N) =
256
+ src[i].v.template segment<N>(N0);
257
+ }
258
+ }
259
+
260
+ // Calls Take1stOrderPart for every parameter block.
261
+ //
262
+ // Example:
263
+ // If one having three parameter blocks with dimensions (3, 2, 4), the call
264
+ // Take1stOrderParts<integer_sequence<3, 2, 4>::Apply(num_outputs,
265
+ // output,
266
+ // jacobians);
267
+ // will result in the following calls to Take1stOrderPart:
268
+ // if (jacobians[0]) {
269
+ // Take1stOrderPart<0, 3>(num_outputs, output, jacobians[0]);
270
+ // }
271
+ // if (jacobians[1]) {
272
+ // Take1stOrderPart<3, 2>(num_outputs, output, jacobians[1]);
273
+ // }
274
+ // if (jacobians[2]) {
275
+ // Take1stOrderPart<5, 4>(num_outputs, output, jacobians[2]);
276
+ // }
277
+ template <typename Seq, int ParameterIdx = 0, int Offset = 0>
278
+ struct Take1stOrderParts;
279
+
280
+ template <int N, int... Ns, int ParameterIdx, int Offset>
281
+ struct Take1stOrderParts<std::integer_sequence<int, N, Ns...>,
282
+ ParameterIdx,
283
+ Offset> {
284
+ template <typename JetT, typename T>
285
+ inline static void Apply(int num_outputs, JetT* output, T** jacobians) {
286
+ if (jacobians[ParameterIdx]) {
287
+ Take1stOrderPart<Offset, N>(num_outputs, output, jacobians[ParameterIdx]);
288
+ }
289
+ Take1stOrderParts<std::integer_sequence<int, Ns...>,
290
+ ParameterIdx + 1,
291
+ Offset + N>::Apply(num_outputs, output, jacobians);
292
+ }
293
+ };
294
+
295
+ // End of 'recursion'. Nothing more to do.
296
+ template <int ParameterIdx, int Offset>
297
+ struct Take1stOrderParts<std::integer_sequence<int>, ParameterIdx, Offset> {
298
+ template <typename T, typename JetT>
299
+ static void Apply(int /* NOT USED*/,
300
+ JetT* /* NOT USED*/,
301
+ T** /* NOT USED */) {}
302
+ };
303
+
304
+ template <int kNumResiduals,
305
+ typename ParameterDims,
306
+ typename Functor,
307
+ typename T>
308
+ inline bool AutoDifferentiate(const Functor& functor,
309
+ T const* const* parameters,
310
+ int dynamic_num_outputs,
311
+ T* function_value,
312
+ T** jacobians) {
313
+ using JetT = Jet<T, ParameterDims::kNumParameters>;
314
+ using Parameters = typename ParameterDims::Parameters;
315
+
316
+ if (kNumResiduals != DYNAMIC) {
317
+ DCHECK_EQ(kNumResiduals, dynamic_num_outputs);
318
+ }
319
+
320
+ ArraySelector<JetT,
321
+ ParameterDims::kNumParameters,
322
+ CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK>
323
+ parameters_as_jets(ParameterDims::kNumParameters);
324
+
325
+ // Pointers to the beginning of each parameter block
326
+ std::array<JetT*, ParameterDims::kNumParameterBlocks> unpacked_parameters =
327
+ ParameterDims::GetUnpackedParameters(parameters_as_jets.data());
328
+
329
+ // If the number of residuals is fixed, we use the template argument as the
330
+ // number of outputs. Otherwise we use the num_outputs parameter. Note: The
331
+ // ?-operator here is compile-time evaluated, therefore num_outputs is also
332
+ // a compile-time constant for functors with fixed residuals.
333
+ const int num_outputs =
334
+ kNumResiduals == DYNAMIC ? dynamic_num_outputs : kNumResiduals;
335
+ DCHECK_GT(num_outputs, 0);
336
+
337
+ ArraySelector<JetT, kNumResiduals, CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK>
338
+ residuals_as_jets(num_outputs);
339
+
340
+ // Invalidate the output Jets, so that we can detect if the user
341
+ // did not assign values to all of them.
342
+ for (int i = 0; i < num_outputs; ++i) {
343
+ residuals_as_jets[i].a = kImpossibleValue;
344
+ residuals_as_jets[i].v.setConstant(kImpossibleValue);
345
+ }
346
+
347
+ Make1stOrderPerturbations<Parameters>::Apply(parameters,
348
+ parameters_as_jets.data());
349
+
350
+ if (!VariadicEvaluate<ParameterDims>(
351
+ functor, unpacked_parameters.data(), residuals_as_jets.data())) {
352
+ return false;
353
+ }
354
+
355
+ Take0thOrderPart(num_outputs, residuals_as_jets.data(), function_value);
356
+ Take1stOrderParts<Parameters>::Apply(
357
+ num_outputs, residuals_as_jets.data(), jacobians);
358
+
359
+ return true;
360
+ }
361
+
362
+ } // namespace internal
363
+ } // namespace ceres
364
+
365
+ #endif // CERES_PUBLIC_INTERNAL_AUTODIFF_H_
include/ceres/internal/config.h ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2022 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: alexs.mac@gmail.com (Alex Stewart)
30
+
31
+ // Configuration options for Ceres.
32
+ //
33
+ // Do not edit this file, it was automatically configured by CMake when
34
+ // Ceres was compiled with the relevant configuration for the machine
35
+ // on which Ceres was compiled.
36
+ //
37
+ // Ceres Developers: All options should have the same name as their mapped
38
+ // CMake options, in the preconfigured version of this file
39
+ // all options should be enclosed in '@'.
40
+
41
+ #ifndef CERES_PUBLIC_INTERNAL_CONFIG_H_
42
+ #define CERES_PUBLIC_INTERNAL_CONFIG_H_
43
+
44
+ // If defined, use the LGPL code in Eigen.
45
+ #define CERES_USE_EIGEN_SPARSE
46
+
47
+ // If defined, Ceres was compiled without LAPACK.
48
+ // #define CERES_NO_LAPACK
49
+
50
+ // If defined, Ceres was compiled without SuiteSparse.
51
+ // #define CERES_NO_SUITESPARSE
52
+
53
+ // If defined, Ceres was compiled without CXSparse.
54
+ // #define CERES_NO_CXSPARSE
55
+
56
+ // If defined, Ceres was compiled without CUDA.
57
+ // #define CERES_NO_CUDA
58
+
59
+ // If defined, Ceres was compiled without Apple's Accelerate framework solvers.
60
+ #define CERES_NO_ACCELERATE_SPARSE
61
+
62
+ #if defined(CERES_NO_SUITESPARSE) && \
63
+ defined(CERES_NO_ACCELERATE_SPARSE) && \
64
+ defined(CERES_NO_CXSPARSE) && \
65
+ !defined(CERES_USE_EIGEN_SPARSE) // NOLINT
66
+ // If defined Ceres was compiled without any sparse linear algebra support.
67
+ #define CERES_NO_SPARSE
68
+ #endif
69
+
70
+ // If defined, Ceres was compiled without Schur specializations.
71
+ // #define CERES_RESTRICT_SCHUR_SPECIALIZATION
72
+
73
+ // If defined, Ceres was compiled to use Eigen instead of hardcoded BLAS
74
+ // routines.
75
+ // #define CERES_NO_CUSTOM_BLAS
76
+
77
+ // If defined, Ceres was compiled without multithreading support.
78
+ // #define CERES_NO_THREADS
79
+ // If defined Ceres was compiled with OpenMP multithreading.
80
+ // #define CERES_USE_OPENMP
81
+ // If defined Ceres was compiled with modern C++ multithreading.
82
+ #define CERES_USE_CXX_THREADS
83
+
84
+ // If defined, Ceres was compiled with a version MSVC >= 2005 which
85
+ // deprecated the standard POSIX names for bessel functions, replacing them
86
+ // with underscore prefixed versions (e.g. j0() -> _j0()).
87
+ // #define CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS
88
+
89
+ #if defined(CERES_USE_OPENMP)
90
+ #if defined(CERES_USE_CXX_THREADS) || defined(CERES_NO_THREADS)
91
+ #error CERES_USE_OPENMP is mutually exclusive to CERES_USE_CXX_THREADS and CERES_NO_THREADS
92
+ #endif
93
+ #elif defined(CERES_USE_CXX_THREADS)
94
+ #if defined(CERES_USE_OPENMP) || defined(CERES_NO_THREADS)
95
+ #error CERES_USE_CXX_THREADS is mutually exclusive to CERES_USE_OPENMP, CERES_USE_CXX_THREADS and CERES_NO_THREADS
96
+ #endif
97
+ #elif defined(CERES_NO_THREADS)
98
+ #if defined(CERES_USE_OPENMP) || defined(CERES_USE_CXX_THREADS)
99
+ #error CERES_NO_THREADS is mutually exclusive to CERES_USE_OPENMP and CERES_USE_CXX_THREADS
100
+ #endif
101
+ #else
102
+ # error One of CERES_USE_OPENMP, CERES_USE_CXX_THREADS or CERES_NO_THREADS must be defined.
103
+ #endif
104
+
105
+ // CERES_NO_SPARSE should be automatically defined by config.h if Ceres was
106
+ // compiled without any sparse back-end. Verify that it has not subsequently
107
+ // been inconsistently redefined.
108
+ #if defined(CERES_NO_SPARSE)
109
+ #if !defined(CERES_NO_SUITESPARSE)
110
+ #error CERES_NO_SPARSE requires CERES_NO_SUITESPARSE.
111
+ #endif
112
+ #if !defined(CERES_NO_CXSPARSE)
113
+ #error CERES_NO_SPARSE requires CERES_NO_CXSPARSE
114
+ #endif
115
+ #if !defined(CERES_NO_ACCELERATE_SPARSE)
116
+ #error CERES_NO_SPARSE requires CERES_NO_ACCELERATE_SPARSE
117
+ #endif
118
+ #if defined(CERES_USE_EIGEN_SPARSE)
119
+ #error CERES_NO_SPARSE requires !CERES_USE_EIGEN_SPARSE
120
+ #endif
121
+ #endif
122
+
123
+ #endif // CERES_PUBLIC_INTERNAL_CONFIG_H_
include/ceres/internal/disable_warnings.h ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2015 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // This file has the sole purpose to silence warnings when including Ceres.
30
+
31
+ // This is not your usual header guard. The macro CERES_WARNINGS_DISABLED
32
+ // shows up again in reenable_warnings.h.
33
+ #ifndef CERES_WARNINGS_DISABLED
34
+ #define CERES_WARNINGS_DISABLED
35
+
36
+ #ifdef _MSC_VER
37
+ #pragma warning(push)
38
+ // Disable the warning C4251 which is triggered by stl classes in
39
+ // Ceres' public interface. To quote MSDN: "C4251 can be ignored "
40
+ // "if you are deriving from a type in the Standard C++ Library"
41
+ #pragma warning(disable : 4251)
42
+ #endif
43
+
44
+ #endif // CERES_WARNINGS_DISABLED
include/ceres/internal/eigen.h ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2015 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+
31
+ #ifndef CERES_INTERNAL_EIGEN_H_
32
+ #define CERES_INTERNAL_EIGEN_H_
33
+
34
+ #include "Eigen/Core"
35
+
36
+ namespace ceres {
37
+
38
+ using Vector = Eigen::Matrix<double, Eigen::Dynamic, 1>;
39
+ using Matrix =
40
+ Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
41
+ using VectorRef = Eigen::Map<Vector>;
42
+ using MatrixRef = Eigen::Map<Matrix>;
43
+ using ConstVectorRef = Eigen::Map<const Vector>;
44
+ using ConstMatrixRef = Eigen::Map<const Matrix>;
45
+
46
+ // Column major matrices for DenseSparseMatrix/DenseQRSolver
47
+ using ColMajorMatrix =
48
+ Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
49
+
50
+ using ColMajorMatrixRef =
51
+ Eigen::Map<ColMajorMatrix, 0, Eigen::Stride<Eigen::Dynamic, 1>>;
52
+
53
+ using ConstColMajorMatrixRef =
54
+ Eigen::Map<const ColMajorMatrix, 0, Eigen::Stride<Eigen::Dynamic, 1>>;
55
+
56
+ // C++ does not support templated typdefs, thus the need for this
57
+ // struct so that we can support statically sized Matrix and Maps.
58
+ template <int num_rows = Eigen::Dynamic, int num_cols = Eigen::Dynamic>
59
+ struct EigenTypes {
60
+ using Matrix =
61
+ Eigen::Matrix<double,
62
+ num_rows,
63
+ num_cols,
64
+ num_cols == 1 ? Eigen::ColMajor : Eigen::RowMajor>;
65
+
66
+ using MatrixRef = Eigen::Map<Matrix>;
67
+ using ConstMatrixRef = Eigen::Map<const Matrix>;
68
+ using Vector = Eigen::Matrix<double, num_rows, 1>;
69
+ using VectorRef = Eigen::Map<Eigen::Matrix<double, num_rows, 1>>;
70
+ using ConstVectorRef = Eigen::Map<const Eigen::Matrix<double, num_rows, 1>>;
71
+ };
72
+
73
+ } // namespace ceres
74
+
75
+ #endif // CERES_INTERNAL_EIGEN_H_
include/ceres/internal/export.h ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #ifndef CERES_EXPORT_H
3
+ #define CERES_EXPORT_H
4
+
5
+ #ifdef CERES_STATIC_DEFINE
6
+ # define CERES_EXPORT
7
+ # define CERES_NO_EXPORT
8
+ #else
9
+ # ifndef CERES_EXPORT
10
+ # ifdef ceres_EXPORTS
11
+ /* We are building this library */
12
+ # define CERES_EXPORT
13
+ # else
14
+ /* We are using this library */
15
+ # define CERES_EXPORT
16
+ # endif
17
+ # endif
18
+
19
+ # ifndef CERES_NO_EXPORT
20
+ # define CERES_NO_EXPORT
21
+ # endif
22
+ #endif
23
+
24
+ #ifndef CERES_DEPRECATED
25
+ # define CERES_DEPRECATED __attribute__ ((__deprecated__))
26
+ #endif
27
+
28
+ #ifndef CERES_DEPRECATED_EXPORT
29
+ # define CERES_DEPRECATED_EXPORT CERES_EXPORT CERES_DEPRECATED
30
+ #endif
31
+
32
+ #ifndef CERES_DEPRECATED_NO_EXPORT
33
+ # define CERES_DEPRECATED_NO_EXPORT CERES_NO_EXPORT CERES_DEPRECATED
34
+ #endif
35
+
36
+ #if 0 /* DEFINE_NO_DEPRECATED */
37
+ # ifndef CERES_NO_DEPRECATED
38
+ # define CERES_NO_DEPRECATED
39
+ # endif
40
+ #endif
41
+
42
+ #endif /* CERES_EXPORT_H */
include/ceres/internal/fixed_array.h ADDED
@@ -0,0 +1,467 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2018 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // -----------------------------------------------------------------------------
16
+ // File: fixed_array.h
17
+ // -----------------------------------------------------------------------------
18
+ //
19
+ // A `FixedArray<T>` represents a non-resizable array of `T` where the length of
20
+ // the array can be determined at run-time. It is a good replacement for
21
+ // non-standard and deprecated uses of `alloca()` and variable length arrays
22
+ // within the GCC extension. (See
23
+ // https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html).
24
+ //
25
+ // `FixedArray` allocates small arrays inline, keeping performance fast by
26
+ // avoiding heap operations. It also helps reduce the chances of
27
+ // accidentally overflowing your stack if large input is passed to
28
+ // your function.
29
+
30
+ #ifndef CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
31
+ #define CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
32
+
33
+ #include <Eigen/Core> // For Eigen::aligned_allocator
34
+ #include <algorithm>
35
+ #include <array>
36
+ #include <cstddef>
37
+ #include <memory>
38
+ #include <tuple>
39
+ #include <type_traits>
40
+
41
+ #include "ceres/internal/memory.h"
42
+ #include "glog/logging.h"
43
+
44
+ namespace ceres {
45
+ namespace internal {
46
+
47
+ constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
48
+
49
+ // The default fixed array allocator.
50
+ //
51
+ // As one can not easily detect if a struct contains or inherits from a fixed
52
+ // size Eigen type, to be safe the Eigen::aligned_allocator is used by default.
53
+ // But trivial types can never contain Eigen types, so std::allocator is used to
54
+ // safe some heap memory.
55
+ template <typename T>
56
+ using FixedArrayDefaultAllocator =
57
+ typename std::conditional<std::is_trivial<T>::value,
58
+ std::allocator<T>,
59
+ Eigen::aligned_allocator<T>>::type;
60
+
61
+ // -----------------------------------------------------------------------------
62
+ // FixedArray
63
+ // -----------------------------------------------------------------------------
64
+ //
65
+ // A `FixedArray` provides a run-time fixed-size array, allocating a small array
66
+ // inline for efficiency.
67
+ //
68
+ // Most users should not specify an `inline_elements` argument and let
69
+ // `FixedArray` automatically determine the number of elements
70
+ // to store inline based on `sizeof(T)`. If `inline_elements` is specified, the
71
+ // `FixedArray` implementation will use inline storage for arrays with a
72
+ // length <= `inline_elements`.
73
+ //
74
+ // Note that a `FixedArray` constructed with a `size_type` argument will
75
+ // default-initialize its values by leaving trivially constructible types
76
+ // uninitialized (e.g. int, int[4], double), and others default-constructed.
77
+ // This matches the behavior of c-style arrays and `std::array`, but not
78
+ // `std::vector`.
79
+ //
80
+ // Note that `FixedArray` does not provide a public allocator; if it requires a
81
+ // heap allocation, it will do so with global `::operator new[]()` and
82
+ // `::operator delete[]()`, even if T provides class-scope overrides for these
83
+ // operators.
84
+ template <typename T,
85
+ size_t N = kFixedArrayUseDefault,
86
+ typename A = FixedArrayDefaultAllocator<T>>
87
+ class FixedArray {
88
+ static_assert(!std::is_array<T>::value || std::extent<T>::value > 0,
89
+ "Arrays with unknown bounds cannot be used with FixedArray.");
90
+
91
+ static constexpr size_t kInlineBytesDefault = 256;
92
+
93
+ using AllocatorTraits = std::allocator_traits<A>;
94
+ // std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17,
95
+ // but this seems to be mostly pedantic.
96
+ template <typename Iterator>
97
+ using EnableIfForwardIterator = typename std::enable_if<std::is_convertible<
98
+ typename std::iterator_traits<Iterator>::iterator_category,
99
+ std::forward_iterator_tag>::value>::type;
100
+ static constexpr bool DefaultConstructorIsNonTrivial() {
101
+ return !std::is_trivially_default_constructible<StorageElement>::value;
102
+ }
103
+
104
+ public:
105
+ using allocator_type = typename AllocatorTraits::allocator_type;
106
+ using value_type = typename AllocatorTraits::value_type;
107
+ using pointer = typename AllocatorTraits::pointer;
108
+ using const_pointer = typename AllocatorTraits::const_pointer;
109
+ using reference = value_type&;
110
+ using const_reference = const value_type&;
111
+ using size_type = typename AllocatorTraits::size_type;
112
+ using difference_type = typename AllocatorTraits::difference_type;
113
+ using iterator = pointer;
114
+ using const_iterator = const_pointer;
115
+ using reverse_iterator = std::reverse_iterator<iterator>;
116
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
117
+
118
+ static constexpr size_type inline_elements =
119
+ (N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type)
120
+ : static_cast<size_type>(N));
121
+
122
+ FixedArray(const FixedArray& other,
123
+ const allocator_type& a = allocator_type())
124
+ : FixedArray(other.begin(), other.end(), a) {}
125
+
126
+ FixedArray(FixedArray&& other, const allocator_type& a = allocator_type())
127
+ : FixedArray(std::make_move_iterator(other.begin()),
128
+ std::make_move_iterator(other.end()),
129
+ a) {}
130
+
131
+ // Creates an array object that can store `n` elements.
132
+ // Note that trivially constructible elements will be uninitialized.
133
+ explicit FixedArray(size_type n, const allocator_type& a = allocator_type())
134
+ : storage_(n, a) {
135
+ if (DefaultConstructorIsNonTrivial()) {
136
+ ConstructRange(storage_.alloc(), storage_.begin(), storage_.end());
137
+ }
138
+ }
139
+
140
+ // Creates an array initialized with `n` copies of `val`.
141
+ FixedArray(size_type n,
142
+ const value_type& val,
143
+ const allocator_type& a = allocator_type())
144
+ : storage_(n, a) {
145
+ ConstructRange(storage_.alloc(), storage_.begin(), storage_.end(), val);
146
+ }
147
+
148
+ // Creates an array initialized with the size and contents of `init_list`.
149
+ FixedArray(std::initializer_list<value_type> init_list,
150
+ const allocator_type& a = allocator_type())
151
+ : FixedArray(init_list.begin(), init_list.end(), a) {}
152
+
153
+ // Creates an array initialized with the elements from the input
154
+ // range. The array's size will always be `std::distance(first, last)`.
155
+ // REQUIRES: Iterator must be a forward_iterator or better.
156
+ template <typename Iterator, EnableIfForwardIterator<Iterator>* = nullptr>
157
+ FixedArray(Iterator first,
158
+ Iterator last,
159
+ const allocator_type& a = allocator_type())
160
+ : storage_(std::distance(first, last), a) {
161
+ CopyRange(storage_.alloc(), storage_.begin(), first, last);
162
+ }
163
+
164
+ ~FixedArray() noexcept {
165
+ for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) {
166
+ AllocatorTraits::destroy(storage_.alloc(), cur);
167
+ }
168
+ }
169
+
170
+ // Assignments are deleted because they break the invariant that the size of a
171
+ // `FixedArray` never changes.
172
+ void operator=(FixedArray&&) = delete;
173
+ void operator=(const FixedArray&) = delete;
174
+
175
+ // FixedArray::size()
176
+ //
177
+ // Returns the length of the fixed array.
178
+ size_type size() const { return storage_.size(); }
179
+
180
+ // FixedArray::max_size()
181
+ //
182
+ // Returns the largest possible value of `std::distance(begin(), end())` for a
183
+ // `FixedArray<T>`. This is equivalent to the most possible addressable bytes
184
+ // over the number of bytes taken by T.
185
+ constexpr size_type max_size() const {
186
+ return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
187
+ }
188
+
189
+ // FixedArray::empty()
190
+ //
191
+ // Returns whether or not the fixed array is empty.
192
+ bool empty() const { return size() == 0; }
193
+
194
+ // FixedArray::memsize()
195
+ //
196
+ // Returns the memory size of the fixed array in bytes.
197
+ size_t memsize() const { return size() * sizeof(value_type); }
198
+
199
+ // FixedArray::data()
200
+ //
201
+ // Returns a const T* pointer to elements of the `FixedArray`. This pointer
202
+ // can be used to access (but not modify) the contained elements.
203
+ const_pointer data() const { return AsValueType(storage_.begin()); }
204
+
205
+ // Overload of FixedArray::data() to return a T* pointer to elements of the
206
+ // fixed array. This pointer can be used to access and modify the contained
207
+ // elements.
208
+ pointer data() { return AsValueType(storage_.begin()); }
209
+
210
+ // FixedArray::operator[]
211
+ //
212
+ // Returns a reference the ith element of the fixed array.
213
+ // REQUIRES: 0 <= i < size()
214
+ reference operator[](size_type i) {
215
+ DCHECK_LT(i, size());
216
+ return data()[i];
217
+ }
218
+
219
+ // Overload of FixedArray::operator()[] to return a const reference to the
220
+ // ith element of the fixed array.
221
+ // REQUIRES: 0 <= i < size()
222
+ const_reference operator[](size_type i) const {
223
+ DCHECK_LT(i, size());
224
+ return data()[i];
225
+ }
226
+
227
+ // FixedArray::front()
228
+ //
229
+ // Returns a reference to the first element of the fixed array.
230
+ reference front() { return *begin(); }
231
+
232
+ // Overload of FixedArray::front() to return a reference to the first element
233
+ // of a fixed array of const values.
234
+ const_reference front() const { return *begin(); }
235
+
236
+ // FixedArray::back()
237
+ //
238
+ // Returns a reference to the last element of the fixed array.
239
+ reference back() { return *(end() - 1); }
240
+
241
+ // Overload of FixedArray::back() to return a reference to the last element
242
+ // of a fixed array of const values.
243
+ const_reference back() const { return *(end() - 1); }
244
+
245
+ // FixedArray::begin()
246
+ //
247
+ // Returns an iterator to the beginning of the fixed array.
248
+ iterator begin() { return data(); }
249
+
250
+ // Overload of FixedArray::begin() to return a const iterator to the
251
+ // beginning of the fixed array.
252
+ const_iterator begin() const { return data(); }
253
+
254
+ // FixedArray::cbegin()
255
+ //
256
+ // Returns a const iterator to the beginning of the fixed array.
257
+ const_iterator cbegin() const { return begin(); }
258
+
259
+ // FixedArray::end()
260
+ //
261
+ // Returns an iterator to the end of the fixed array.
262
+ iterator end() { return data() + size(); }
263
+
264
+ // Overload of FixedArray::end() to return a const iterator to the end of the
265
+ // fixed array.
266
+ const_iterator end() const { return data() + size(); }
267
+
268
+ // FixedArray::cend()
269
+ //
270
+ // Returns a const iterator to the end of the fixed array.
271
+ const_iterator cend() const { return end(); }
272
+
273
+ // FixedArray::rbegin()
274
+ //
275
+ // Returns a reverse iterator from the end of the fixed array.
276
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
277
+
278
+ // Overload of FixedArray::rbegin() to return a const reverse iterator from
279
+ // the end of the fixed array.
280
+ const_reverse_iterator rbegin() const {
281
+ return const_reverse_iterator(end());
282
+ }
283
+
284
+ // FixedArray::crbegin()
285
+ //
286
+ // Returns a const reverse iterator from the end of the fixed array.
287
+ const_reverse_iterator crbegin() const { return rbegin(); }
288
+
289
+ // FixedArray::rend()
290
+ //
291
+ // Returns a reverse iterator from the beginning of the fixed array.
292
+ reverse_iterator rend() { return reverse_iterator(begin()); }
293
+
294
+ // Overload of FixedArray::rend() for returning a const reverse iterator
295
+ // from the beginning of the fixed array.
296
+ const_reverse_iterator rend() const {
297
+ return const_reverse_iterator(begin());
298
+ }
299
+
300
+ // FixedArray::crend()
301
+ //
302
+ // Returns a reverse iterator from the beginning of the fixed array.
303
+ const_reverse_iterator crend() const { return rend(); }
304
+
305
+ // FixedArray::fill()
306
+ //
307
+ // Assigns the given `value` to all elements in the fixed array.
308
+ void fill(const value_type& val) { std::fill(begin(), end(), val); }
309
+
310
+ // Relational operators. Equality operators are elementwise using
311
+ // `operator==`, while order operators order FixedArrays lexicographically.
312
+ friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) {
313
+ return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
314
+ }
315
+
316
+ friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) {
317
+ return !(lhs == rhs);
318
+ }
319
+
320
+ friend bool operator<(const FixedArray& lhs, const FixedArray& rhs) {
321
+ return std::lexicographical_compare(
322
+ lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
323
+ }
324
+
325
+ friend bool operator>(const FixedArray& lhs, const FixedArray& rhs) {
326
+ return rhs < lhs;
327
+ }
328
+
329
+ friend bool operator<=(const FixedArray& lhs, const FixedArray& rhs) {
330
+ return !(rhs < lhs);
331
+ }
332
+
333
+ friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) {
334
+ return !(lhs < rhs);
335
+ }
336
+
337
+ private:
338
+ // StorageElement
339
+ //
340
+ // For FixedArrays with a C-style-array value_type, StorageElement is a POD
341
+ // wrapper struct called StorageElementWrapper that holds the value_type
342
+ // instance inside. This is needed for construction and destruction of the
343
+ // entire array regardless of how many dimensions it has. For all other cases,
344
+ // StorageElement is just an alias of value_type.
345
+ //
346
+ // Maintainer's Note: The simpler solution would be to simply wrap value_type
347
+ // in a struct whether it's an array or not. That causes some paranoid
348
+ // diagnostics to misfire, believing that 'data()' returns a pointer to a
349
+ // single element, rather than the packed array that it really is.
350
+ // e.g.:
351
+ //
352
+ // FixedArray<char> buf(1);
353
+ // sprintf(buf.data(), "foo");
354
+ //
355
+ // error: call to int __builtin___sprintf_chk(etc...)
356
+ // will always overflow destination buffer [-Werror]
357
+ //
358
+ template <typename OuterT,
359
+ typename InnerT = typename std::remove_extent<OuterT>::type,
360
+ size_t InnerN = std::extent<OuterT>::value>
361
+ struct StorageElementWrapper {
362
+ InnerT array[InnerN];
363
+ };
364
+
365
+ using StorageElement =
366
+ typename std::conditional<std::is_array<value_type>::value,
367
+ StorageElementWrapper<value_type>,
368
+ value_type>::type;
369
+
370
+ static pointer AsValueType(pointer ptr) { return ptr; }
371
+ static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
372
+ return std::addressof(ptr->array);
373
+ }
374
+
375
+ static_assert(sizeof(StorageElement) == sizeof(value_type), "");
376
+ static_assert(alignof(StorageElement) == alignof(value_type), "");
377
+
378
+ class NonEmptyInlinedStorage {
379
+ public:
380
+ StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }
381
+ void AnnotateConstruct(size_type) {}
382
+ void AnnotateDestruct(size_type) {}
383
+
384
+ // #ifdef ADDRESS_SANITIZER
385
+ // void* RedzoneBegin() { return &redzone_begin_; }
386
+ // void* RedzoneEnd() { return &redzone_end_ + 1; }
387
+ // #endif // ADDRESS_SANITIZER
388
+
389
+ private:
390
+ // ADDRESS_SANITIZER_REDZONE(redzone_begin_);
391
+ alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
392
+ // ADDRESS_SANITIZER_REDZONE(redzone_end_);
393
+ };
394
+
395
+ class EmptyInlinedStorage {
396
+ public:
397
+ StorageElement* data() { return nullptr; }
398
+ void AnnotateConstruct(size_type) {}
399
+ void AnnotateDestruct(size_type) {}
400
+ };
401
+
402
+ using InlinedStorage =
403
+ typename std::conditional<inline_elements == 0,
404
+ EmptyInlinedStorage,
405
+ NonEmptyInlinedStorage>::type;
406
+
407
+ // Storage
408
+ //
409
+ // An instance of Storage manages the inline and out-of-line memory for
410
+ // instances of FixedArray. This guarantees that even when construction of
411
+ // individual elements fails in the FixedArray constructor body, the
412
+ // destructor for Storage will still be called and out-of-line memory will be
413
+ // properly deallocated.
414
+ //
415
+ class Storage : public InlinedStorage {
416
+ public:
417
+ Storage(size_type n, const allocator_type& a)
418
+ : size_alloc_(n, a), data_(InitializeData()) {}
419
+
420
+ ~Storage() noexcept {
421
+ if (UsingInlinedStorage(size())) {
422
+ InlinedStorage::AnnotateDestruct(size());
423
+ } else {
424
+ AllocatorTraits::deallocate(alloc(), AsValueType(begin()), size());
425
+ }
426
+ }
427
+
428
+ size_type size() const { return std::get<0>(size_alloc_); }
429
+ StorageElement* begin() const { return data_; }
430
+ StorageElement* end() const { return begin() + size(); }
431
+ allocator_type& alloc() { return std::get<1>(size_alloc_); }
432
+
433
+ private:
434
+ static bool UsingInlinedStorage(size_type n) {
435
+ return n <= inline_elements;
436
+ }
437
+
438
+ StorageElement* InitializeData() {
439
+ if (UsingInlinedStorage(size())) {
440
+ InlinedStorage::AnnotateConstruct(size());
441
+ return InlinedStorage::data();
442
+ } else {
443
+ return reinterpret_cast<StorageElement*>(
444
+ AllocatorTraits::allocate(alloc(), size()));
445
+ }
446
+ }
447
+
448
+ // Using std::tuple and not absl::CompressedTuple, as it has a lot of
449
+ // dependencies to other absl headers.
450
+ std::tuple<size_type, allocator_type> size_alloc_;
451
+ StorageElement* data_;
452
+ };
453
+
454
+ Storage storage_;
455
+ };
456
+
457
+ template <typename T, size_t N, typename A>
458
+ constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault;
459
+
460
+ template <typename T, size_t N, typename A>
461
+ constexpr typename FixedArray<T, N, A>::size_type
462
+ FixedArray<T, N, A>::inline_elements;
463
+
464
+ } // namespace internal
465
+ } // namespace ceres
466
+
467
+ #endif // CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
include/ceres/internal/householder_vector.h ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2015 Google Inc. All rights reserved.
3
+ // http://code.google.com/p/ceres-solver/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: vitus@google.com (Michael Vitus)
30
+
31
+ #ifndef CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
32
+ #define CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
33
+
34
+ #include "Eigen/Core"
35
+ #include "glog/logging.h"
36
+
37
+ namespace ceres {
38
+ namespace internal {
39
+
40
+ // Algorithm 5.1.1 from 'Matrix Computations' by Golub et al. (Johns Hopkins
41
+ // Studies in Mathematical Sciences) but using the nth element of the input
42
+ // vector as pivot instead of first. This computes the vector v with v(n) = 1
43
+ // and beta such that H = I - beta * v * v^T is orthogonal and
44
+ // H * x = ||x||_2 * e_n.
45
+ //
46
+ // NOTE: Some versions of MSVC have trouble deducing the type of v if
47
+ // you do not specify all the template arguments explicitly.
48
+ template <typename XVectorType, typename Scalar, int N>
49
+ void ComputeHouseholderVector(const XVectorType& x,
50
+ Eigen::Matrix<Scalar, N, 1>* v,
51
+ Scalar* beta) {
52
+ CHECK(beta != nullptr);
53
+ CHECK(v != nullptr);
54
+ CHECK_GT(x.rows(), 1);
55
+ CHECK_EQ(x.rows(), v->rows());
56
+
57
+ Scalar sigma = x.head(x.rows() - 1).squaredNorm();
58
+ *v = x;
59
+ (*v)(v->rows() - 1) = Scalar(1.0);
60
+
61
+ *beta = Scalar(0.0);
62
+ const Scalar& x_pivot = x(x.rows() - 1);
63
+
64
+ if (sigma <= Scalar(std::numeric_limits<double>::epsilon())) {
65
+ if (x_pivot < Scalar(0.0)) {
66
+ *beta = Scalar(2.0);
67
+ }
68
+ return;
69
+ }
70
+
71
+ const Scalar mu = sqrt(x_pivot * x_pivot + sigma);
72
+ Scalar v_pivot = Scalar(1.0);
73
+
74
+ if (x_pivot <= Scalar(0.0)) {
75
+ v_pivot = x_pivot - mu;
76
+ } else {
77
+ v_pivot = -sigma / (x_pivot + mu);
78
+ }
79
+
80
+ *beta = Scalar(2.0) * v_pivot * v_pivot / (sigma + v_pivot * v_pivot);
81
+
82
+ v->head(v->rows() - 1) /= v_pivot;
83
+ }
84
+
85
+ template <typename XVectorType, typename Derived>
86
+ typename Derived::PlainObject ApplyHouseholderVector(
87
+ const XVectorType& y,
88
+ const Eigen::MatrixBase<Derived>& v,
89
+ const typename Derived::Scalar& beta) {
90
+ return (y - v * (beta * (v.transpose() * y)));
91
+ }
92
+
93
+ } // namespace internal
94
+ } // namespace ceres
95
+
96
+ #endif // CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
include/ceres/internal/integer_sequence_algorithm.h ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2022 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: jodebo_beck@gmx.de (Johannes Beck)
30
+ // sergiu.deitsch@gmail.com (Sergiu Deitsch)
31
+ //
32
+ // Algorithms to be used together with integer_sequence, like computing the sum
33
+ // or the exclusive scan (sometimes called exclusive prefix sum) at compile
34
+ // time.
35
+
36
+ #ifndef CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
37
+ #define CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
38
+
39
+ #include <utility>
40
+
41
+ #include "ceres/jet_fwd.h"
42
+
43
+ namespace ceres {
44
+ namespace internal {
45
+
46
+ // Implementation of calculating the sum of an integer sequence.
47
+ // Recursively instantiate SumImpl and calculate the sum of the N first
48
+ // numbers. This reduces the number of instantiations and speeds up
49
+ // compilation.
50
+ //
51
+ // Examples:
52
+ // 1) integer_sequence<int, 5>:
53
+ // Value = 5
54
+ //
55
+ // 2) integer_sequence<int, 4, 2>:
56
+ // Value = 4 + 2 + SumImpl<integer_sequence<int>>::Value
57
+ // Value = 4 + 2 + 0
58
+ //
59
+ // 3) integer_sequence<int, 2, 1, 4>:
60
+ // Value = 2 + 1 + SumImpl<integer_sequence<int, 4>>::Value
61
+ // Value = 2 + 1 + 4
62
+ template <typename Seq>
63
+ struct SumImpl;
64
+
65
+ // Strip of and sum the first number.
66
+ template <typename T, T N, T... Ns>
67
+ struct SumImpl<std::integer_sequence<T, N, Ns...>> {
68
+ static constexpr T Value =
69
+ N + SumImpl<std::integer_sequence<T, Ns...>>::Value;
70
+ };
71
+
72
+ // Strip of and sum the first two numbers.
73
+ template <typename T, T N1, T N2, T... Ns>
74
+ struct SumImpl<std::integer_sequence<T, N1, N2, Ns...>> {
75
+ static constexpr T Value =
76
+ N1 + N2 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
77
+ };
78
+
79
+ // Strip of and sum the first four numbers.
80
+ template <typename T, T N1, T N2, T N3, T N4, T... Ns>
81
+ struct SumImpl<std::integer_sequence<T, N1, N2, N3, N4, Ns...>> {
82
+ static constexpr T Value =
83
+ N1 + N2 + N3 + N4 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
84
+ };
85
+
86
+ // Only one number is left. 'Value' is just that number ('recursion' ends).
87
+ template <typename T, T N>
88
+ struct SumImpl<std::integer_sequence<T, N>> {
89
+ static constexpr T Value = N;
90
+ };
91
+
92
+ // No number is left. 'Value' is the identity element (for sum this is zero).
93
+ template <typename T>
94
+ struct SumImpl<std::integer_sequence<T>> {
95
+ static constexpr T Value = T(0);
96
+ };
97
+
98
+ // Calculate the sum of an integer sequence. The resulting sum will be stored in
99
+ // 'Value'.
100
+ template <typename Seq>
101
+ class Sum {
102
+ using T = typename Seq::value_type;
103
+
104
+ public:
105
+ static constexpr T Value = SumImpl<Seq>::Value;
106
+ };
107
+
108
+ // Implementation of calculating an exclusive scan (exclusive prefix sum) of an
109
+ // integer sequence. Exclusive means that the i-th input element is not included
110
+ // in the i-th sum. Calculating the exclusive scan for an input array I results
111
+ // in the following output R:
112
+ //
113
+ // R[0] = 0
114
+ // R[1] = I[0];
115
+ // R[2] = I[0] + I[1];
116
+ // R[3] = I[0] + I[1] + I[2];
117
+ // ...
118
+ //
119
+ // In C++17 std::exclusive_scan does the same operation at runtime (but
120
+ // cannot be used to calculate the prefix sum at compile time). See
121
+ // https://en.cppreference.com/w/cpp/algorithm/exclusive_scan for a more
122
+ // detailed description.
123
+ //
124
+ // Example for integer_sequence<int, 1, 4, 3> (seq := integer_sequence):
125
+ // T , Sum, Ns... , Rs...
126
+ // ExclusiveScanImpl<int, 0, seq<int, 1, 4, 3>, seq<int >>
127
+ // ExclusiveScanImpl<int, 1, seq<int, 4, 3>, seq<int, 0 >>
128
+ // ExclusiveScanImpl<int, 5, seq<int, 3>, seq<int, 0, 1 >>
129
+ // ExclusiveScanImpl<int, 8, seq<int >, seq<int, 0, 1, 5>>
130
+ // ^^^^^^^^^^^^^^^^^
131
+ // resulting sequence
132
+ template <typename T, T Sum, typename SeqIn, typename SeqOut>
133
+ struct ExclusiveScanImpl;
134
+
135
+ template <typename T, T Sum, T N, T... Ns, T... Rs>
136
+ struct ExclusiveScanImpl<T,
137
+ Sum,
138
+ std::integer_sequence<T, N, Ns...>,
139
+ std::integer_sequence<T, Rs...>> {
140
+ using Type =
141
+ typename ExclusiveScanImpl<T,
142
+ Sum + N,
143
+ std::integer_sequence<T, Ns...>,
144
+ std::integer_sequence<T, Rs..., Sum>>::Type;
145
+ };
146
+
147
+ // End of 'recursion'. The resulting type is SeqOut.
148
+ template <typename T, T Sum, typename SeqOut>
149
+ struct ExclusiveScanImpl<T, Sum, std::integer_sequence<T>, SeqOut> {
150
+ using Type = SeqOut;
151
+ };
152
+
153
+ // Calculates the exclusive scan of the specified integer sequence. The last
154
+ // element (the total) is not included in the resulting sequence so they have
155
+ // same length. This means the exclusive scan of integer_sequence<int, 1, 2, 3>
156
+ // will be integer_sequence<int, 0, 1, 3>.
157
+ template <typename Seq>
158
+ class ExclusiveScanT {
159
+ using T = typename Seq::value_type;
160
+
161
+ public:
162
+ using Type =
163
+ typename ExclusiveScanImpl<T, T(0), Seq, std::integer_sequence<T>>::Type;
164
+ };
165
+
166
+ // Helper to use exclusive scan without typename.
167
+ template <typename Seq>
168
+ using ExclusiveScan = typename ExclusiveScanT<Seq>::Type;
169
+
170
+ // Removes all elements from a integer sequence corresponding to specified
171
+ // ValueToRemove.
172
+ //
173
+ // This type should not be used directly but instead RemoveValue.
174
+ template <typename T, T ValueToRemove, typename... Sequence>
175
+ struct RemoveValueImpl;
176
+
177
+ // Final filtered sequence
178
+ template <typename T, T ValueToRemove, T... Values>
179
+ struct RemoveValueImpl<T,
180
+ ValueToRemove,
181
+ std::integer_sequence<T, Values...>,
182
+ std::integer_sequence<T>> {
183
+ using type = std::integer_sequence<T, Values...>;
184
+ };
185
+
186
+ // Found a matching value
187
+ template <typename T, T ValueToRemove, T... Head, T... Tail>
188
+ struct RemoveValueImpl<T,
189
+ ValueToRemove,
190
+ std::integer_sequence<T, Head...>,
191
+ std::integer_sequence<T, ValueToRemove, Tail...>>
192
+ : RemoveValueImpl<T,
193
+ ValueToRemove,
194
+ std::integer_sequence<T, Head...>,
195
+ std::integer_sequence<T, Tail...>> {};
196
+
197
+ // Move one element from the tail to the head
198
+ template <typename T, T ValueToRemove, T... Head, T MiddleValue, T... Tail>
199
+ struct RemoveValueImpl<T,
200
+ ValueToRemove,
201
+ std::integer_sequence<T, Head...>,
202
+ std::integer_sequence<T, MiddleValue, Tail...>>
203
+ : RemoveValueImpl<T,
204
+ ValueToRemove,
205
+ std::integer_sequence<T, Head..., MiddleValue>,
206
+ std::integer_sequence<T, Tail...>> {};
207
+
208
+ // Start recursion by splitting the integer sequence into two separate ones
209
+ template <typename T, T ValueToRemove, T... Tail>
210
+ struct RemoveValueImpl<T, ValueToRemove, std::integer_sequence<T, Tail...>>
211
+ : RemoveValueImpl<T,
212
+ ValueToRemove,
213
+ std::integer_sequence<T>,
214
+ std::integer_sequence<T, Tail...>> {};
215
+
216
+ // RemoveValue takes an integer Sequence of arbitrary type and removes all
217
+ // elements matching ValueToRemove.
218
+ //
219
+ // In contrast to RemoveValueImpl, this implementation deduces the value type
220
+ // eliminating the need to specify it explicitly.
221
+ //
222
+ // As an example, RemoveValue<std::integer_sequence<int, 1, 2, 3>, 4>::type will
223
+ // not transform the type of the original sequence. However,
224
+ // RemoveValue<std::integer_sequence<int, 0, 0, 2>, 2>::type will generate a new
225
+ // sequence of type std::integer_sequence<int, 0, 0> by removing the value 2.
226
+ template <typename Sequence, typename Sequence::value_type ValueToRemove>
227
+ struct RemoveValue
228
+ : RemoveValueImpl<typename Sequence::value_type, ValueToRemove, Sequence> {
229
+ };
230
+
231
+ // Convenience template alias for RemoveValue.
232
+ template <typename Sequence, typename Sequence::value_type ValueToRemove>
233
+ using RemoveValue_t = typename RemoveValue<Sequence, ValueToRemove>::type;
234
+
235
+ // Determines whether the values of an integer sequence are all the same.
236
+ //
237
+ // The integer sequence must contain at least one value. The predicate is
238
+ // undefined for empty sequences. The evaluation result of the predicate for a
239
+ // sequence containing only one value is defined to be true.
240
+ template <typename... Sequence>
241
+ struct AreAllEqual;
242
+
243
+ // The predicate result for a sequence containing one element is defined to be
244
+ // true.
245
+ template <typename T, T Value>
246
+ struct AreAllEqual<std::integer_sequence<T, Value>> : std::true_type {};
247
+
248
+ // Recursion end.
249
+ template <typename T, T Value1, T Value2>
250
+ struct AreAllEqual<std::integer_sequence<T, Value1, Value2>>
251
+ : std::integral_constant<bool, Value1 == Value2> {};
252
+
253
+ // Recursion for sequences containing at least two elements.
254
+ template <typename T, T Value1, T Value2, T... Values>
255
+ // clang-format off
256
+ struct AreAllEqual<std::integer_sequence<T, Value1, Value2, Values...> >
257
+ : std::integral_constant
258
+ <
259
+ bool,
260
+ AreAllEqual<std::integer_sequence<T, Value1, Value2> >::value &&
261
+ AreAllEqual<std::integer_sequence<T, Value2, Values...> >::value
262
+ >
263
+ // clang-format on
264
+ {};
265
+
266
+ // Convenience variable template for AreAllEqual.
267
+ template <class Sequence>
268
+ constexpr bool AreAllEqual_v = AreAllEqual<Sequence>::value;
269
+
270
+ // Predicate determining whether an integer sequence is either empty or all
271
+ // values are equal.
272
+ template <typename Sequence>
273
+ struct IsEmptyOrAreAllEqual;
274
+
275
+ // Empty case.
276
+ template <typename T>
277
+ struct IsEmptyOrAreAllEqual<std::integer_sequence<T>> : std::true_type {};
278
+
279
+ // General case for sequences containing at least one value.
280
+ template <typename T, T HeadValue, T... Values>
281
+ struct IsEmptyOrAreAllEqual<std::integer_sequence<T, HeadValue, Values...>>
282
+ : AreAllEqual<std::integer_sequence<T, HeadValue, Values...>> {};
283
+
284
+ // Convenience variable template for IsEmptyOrAreAllEqual.
285
+ template <class Sequence>
286
+ constexpr bool IsEmptyOrAreAllEqual_v = IsEmptyOrAreAllEqual<Sequence>::value;
287
+
288
+ } // namespace internal
289
+ } // namespace ceres
290
+
291
+ #endif // CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
include/ceres/internal/jet_traits.h ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2022 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sergiu.deitsch@gmail.com (Sergiu Deitsch)
30
+ //
31
+
32
+ #ifndef CERES_PUBLIC_INTERNAL_JET_TRAITS_H_
33
+ #define CERES_PUBLIC_INTERNAL_JET_TRAITS_H_
34
+
35
+ #include <tuple>
36
+ #include <type_traits>
37
+ #include <utility>
38
+
39
+ #include "ceres/internal/integer_sequence_algorithm.h"
40
+ #include "ceres/jet_fwd.h"
41
+
42
+ namespace ceres {
43
+ namespace internal {
44
+
45
+ // Predicate that determines whether T is a Jet.
46
+ template <typename T, typename E = void>
47
+ struct IsJet : std::false_type {};
48
+
49
+ template <typename T, int N>
50
+ struct IsJet<Jet<T, N>> : std::true_type {};
51
+
52
+ // Convenience variable template for IsJet.
53
+ template <typename T>
54
+ constexpr bool IsJet_v = IsJet<T>::value;
55
+
56
+ // Predicate that determines whether any of the Types is a Jet.
57
+ template <typename... Types>
58
+ struct AreAnyJet : std::false_type {};
59
+
60
+ template <typename T, typename... Types>
61
+ struct AreAnyJet<T, Types...> : AreAnyJet<Types...> {};
62
+
63
+ template <typename T, int N, typename... Types>
64
+ struct AreAnyJet<Jet<T, N>, Types...> : std::true_type {};
65
+
66
+ // Convenience variable template for AreAnyJet.
67
+ template <typename... Types>
68
+ constexpr bool AreAnyJet_v = AreAnyJet<Types...>::value;
69
+
70
+ // Extracts the underlying floating-point from a type T.
71
+ template <typename T, typename E = void>
72
+ struct UnderlyingScalar {
73
+ using type = T;
74
+ };
75
+
76
+ template <typename T, int N>
77
+ struct UnderlyingScalar<Jet<T, N>> : UnderlyingScalar<T> {};
78
+
79
+ // Convenience template alias for UnderlyingScalar type trait.
80
+ template <typename T>
81
+ using UnderlyingScalar_t = typename UnderlyingScalar<T>::type;
82
+
83
+ // Predicate determining whether all Types in the pack are the same.
84
+ //
85
+ // Specifically, the predicate applies std::is_same recursively to pairs of
86
+ // Types in the pack.
87
+ //
88
+ // The predicate is defined only for template packs containing at least two
89
+ // types.
90
+ template <typename T1, typename T2, typename... Types>
91
+ // clang-format off
92
+ struct AreAllSame : std::integral_constant
93
+ <
94
+ bool,
95
+ AreAllSame<T1, T2>::value &&
96
+ AreAllSame<T2, Types...>::value
97
+ >
98
+ // clang-format on
99
+ {};
100
+
101
+ // AreAllSame pairwise test.
102
+ template <typename T1, typename T2>
103
+ struct AreAllSame<T1, T2> : std::is_same<T1, T2> {};
104
+
105
+ // Convenience variable template for AreAllSame.
106
+ template <typename... Types>
107
+ constexpr bool AreAllSame_v = AreAllSame<Types...>::value;
108
+
109
+ // Determines the rank of a type. This allows to ensure that types passed as
110
+ // arguments are compatible to each other. The rank of Jet is determined by the
111
+ // dimensions of the dual part. The rank of a scalar is always 0.
112
+ // Non-specialized types default to a rank of -1.
113
+ template <typename T, typename E = void>
114
+ struct Rank : std::integral_constant<int, -1> {};
115
+
116
+ // The rank of a scalar is 0.
117
+ template <typename T>
118
+ struct Rank<T, std::enable_if_t<std::is_scalar<T>::value>>
119
+ : std::integral_constant<int, 0> {};
120
+
121
+ // The rank of a Jet is given by its dimensionality.
122
+ template <typename T, int N>
123
+ struct Rank<Jet<T, N>> : std::integral_constant<int, N> {};
124
+
125
+ // Convenience variable template for Rank.
126
+ template <typename T>
127
+ constexpr int Rank_v = Rank<T>::value;
128
+
129
+ // Constructs an integer sequence of ranks for each of the Types in the pack.
130
+ template <typename... Types>
131
+ using Ranks_t = std::integer_sequence<int, Rank_v<Types>...>;
132
+
133
+ // Returns the scalar part of a type. This overload acts as an identity.
134
+ template <typename T>
135
+ constexpr decltype(auto) AsScalar(T&& value) noexcept {
136
+ return std::forward<T>(value);
137
+ }
138
+
139
+ // Recursively unwraps the scalar part of a Jet until a non-Jet scalar type is
140
+ // encountered.
141
+ template <typename T, int N>
142
+ constexpr decltype(auto) AsScalar(const Jet<T, N>& value) noexcept(
143
+ noexcept(AsScalar(value.a))) {
144
+ return AsScalar(value.a);
145
+ }
146
+
147
+ } // namespace internal
148
+
149
+ // Type trait ensuring at least one of the types is a Jet,
150
+ // the underlying scalar types are the same and Jet dimensions match.
151
+ //
152
+ // The type trait can be further specialized if necessary.
153
+ //
154
+ // This trait is a candidate for a concept definition once C++20 features can
155
+ // be used.
156
+ template <typename... Types>
157
+ // clang-format off
158
+ struct CompatibleJetOperands : std::integral_constant
159
+ <
160
+ bool,
161
+ // At least one of the types is a Jet
162
+ internal::AreAnyJet_v<Types...> &&
163
+ // The underlying floating-point types are exactly the same
164
+ internal::AreAllSame_v<internal::UnderlyingScalar_t<Types>...> &&
165
+ // Non-zero ranks of types are equal
166
+ internal::IsEmptyOrAreAllEqual_v<internal::RemoveValue_t<internal::Ranks_t<Types...>, 0>>
167
+ >
168
+ // clang-format on
169
+ {};
170
+
171
+ // Single Jet operand is always compatible.
172
+ template <typename T, int N>
173
+ struct CompatibleJetOperands<Jet<T, N>> : std::true_type {};
174
+
175
+ // Single non-Jet operand is always incompatible.
176
+ template <typename T>
177
+ struct CompatibleJetOperands<T> : std::false_type {};
178
+
179
+ // Empty operands are always incompatible.
180
+ template <>
181
+ struct CompatibleJetOperands<> : std::false_type {};
182
+
183
+ // Convenience variable template ensuring at least one of the types is a Jet,
184
+ // the underlying scalar types are the same and Jet dimensions match.
185
+ //
186
+ // This trait is a candidate for a concept definition once C++20 features can
187
+ // be used.
188
+ template <typename... Types>
189
+ constexpr bool CompatibleJetOperands_v = CompatibleJetOperands<Types...>::value;
190
+
191
+ // Type trait ensuring at least one of the types is a Jet,
192
+ // the underlying scalar types are compatible among each other and Jet
193
+ // dimensions match.
194
+ //
195
+ // The type trait can be further specialized if necessary.
196
+ //
197
+ // This trait is a candidate for a concept definition once C++20 features can
198
+ // be used.
199
+ template <typename... Types>
200
+ // clang-format off
201
+ struct PromotableJetOperands : std::integral_constant
202
+ <
203
+ bool,
204
+ // Types can be compatible among each other
205
+ internal::AreAnyJet_v<Types...> &&
206
+ // Non-zero ranks of types are equal
207
+ internal::IsEmptyOrAreAllEqual_v<internal::RemoveValue_t<internal::Ranks_t<Types...>, 0>>
208
+ >
209
+ // clang-format on
210
+ {};
211
+
212
+ // Convenience variable template ensuring at least one of the types is a Jet,
213
+ // the underlying scalar types are compatible among each other and Jet
214
+ // dimensions match.
215
+ //
216
+ // This trait is a candidate for a concept definition once C++20 features can
217
+ // be used.
218
+ template <typename... Types>
219
+ constexpr bool PromotableJetOperands_v = PromotableJetOperands<Types...>::value;
220
+
221
+ } // namespace ceres
222
+
223
+ #endif // CERES_PUBLIC_INTERNAL_JET_TRAITS_H_
include/ceres/internal/line_parameterization.h ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2020 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: jodebo_beck@gmx.de (Johannes Beck)
30
+ //
31
+
32
+ #ifndef CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
33
+ #define CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
34
+
35
+ #include "householder_vector.h"
36
+
37
+ namespace ceres {
38
+
39
+ template <int AmbientSpaceDimension>
40
+ bool LineParameterization<AmbientSpaceDimension>::Plus(
41
+ const double* x_ptr,
42
+ const double* delta_ptr,
43
+ double* x_plus_delta_ptr) const {
44
+ // We seek a box plus operator of the form
45
+ //
46
+ // [o*, d*] = Plus([o, d], [delta_o, delta_d])
47
+ //
48
+ // where o is the origin point, d is the direction vector, delta_o is
49
+ // the delta of the origin point and delta_d the delta of the direction and
50
+ // o* and d* is the updated origin point and direction.
51
+ //
52
+ // We separate the Plus operator into the origin point and directional part
53
+ // d* = Plus_d(d, delta_d)
54
+ // o* = Plus_o(o, d, delta_o)
55
+ //
56
+ // The direction update function Plus_d is the same as for the homogeneous
57
+ // vector parameterization:
58
+ //
59
+ // d* = H_{v(d)} [0.5 sinc(0.5 |delta_d|) delta_d, cos(0.5 |delta_d|)]^T
60
+ //
61
+ // where H is the householder matrix
62
+ // H_{v} = I - (2 / |v|^2) v v^T
63
+ // and
64
+ // v(d) = d - sign(d_n) |d| e_n.
65
+ //
66
+ // The origin point update function Plus_o is defined as
67
+ //
68
+ // o* = o + H_{v(d)} [0.5 delta_o, 0]^T.
69
+
70
+ static constexpr int kDim = AmbientSpaceDimension;
71
+ using AmbientVector = Eigen::Matrix<double, kDim, 1>;
72
+ using AmbientVectorRef = Eigen::Map<Eigen::Matrix<double, kDim, 1>>;
73
+ using ConstAmbientVectorRef =
74
+ Eigen::Map<const Eigen::Matrix<double, kDim, 1>>;
75
+ using ConstTangentVectorRef =
76
+ Eigen::Map<const Eigen::Matrix<double, kDim - 1, 1>>;
77
+
78
+ ConstAmbientVectorRef o(x_ptr);
79
+ ConstAmbientVectorRef d(x_ptr + kDim);
80
+
81
+ ConstTangentVectorRef delta_o(delta_ptr);
82
+ ConstTangentVectorRef delta_d(delta_ptr + kDim - 1);
83
+ AmbientVectorRef o_plus_delta(x_plus_delta_ptr);
84
+ AmbientVectorRef d_plus_delta(x_plus_delta_ptr + kDim);
85
+
86
+ const double norm_delta_d = delta_d.norm();
87
+
88
+ o_plus_delta = o;
89
+
90
+ // Shortcut for zero delta direction.
91
+ if (norm_delta_d == 0.0) {
92
+ d_plus_delta = d;
93
+
94
+ if (delta_o.isZero(0.0)) {
95
+ return true;
96
+ }
97
+ }
98
+
99
+ // Calculate the householder transformation which is needed for f_d and f_o.
100
+ AmbientVector v;
101
+ double beta;
102
+
103
+ // NOTE: The explicit template arguments are needed here because
104
+ // ComputeHouseholderVector is templated and some versions of MSVC
105
+ // have trouble deducing the type of v automatically.
106
+ internal::ComputeHouseholderVector<ConstAmbientVectorRef, double, kDim>(
107
+ d, &v, &beta);
108
+
109
+ if (norm_delta_d != 0.0) {
110
+ // Map the delta from the minimum representation to the over parameterized
111
+ // homogeneous vector. See section A6.9.2 on page 624 of Hartley & Zisserman
112
+ // (2nd Edition) for a detailed description. Note there is a typo on Page
113
+ // 625, line 4 so check the book errata.
114
+ const double norm_delta_div_2 = 0.5 * norm_delta_d;
115
+ const double sin_delta_by_delta =
116
+ std::sin(norm_delta_div_2) / norm_delta_div_2;
117
+
118
+ // Apply the delta update to remain on the unit sphere. See section A6.9.3
119
+ // on page 625 of Hartley & Zisserman (2nd Edition) for a detailed
120
+ // description.
121
+ AmbientVector y;
122
+ y.template head<kDim - 1>() = 0.5 * sin_delta_by_delta * delta_d;
123
+ y[kDim - 1] = std::cos(norm_delta_div_2);
124
+
125
+ d_plus_delta = d.norm() * (y - v * (beta * (v.transpose() * y)));
126
+ }
127
+
128
+ // The null space is in the direction of the line, so the tangent space is
129
+ // perpendicular to the line direction. This is achieved by using the
130
+ // householder matrix of the direction and allow only movements
131
+ // perpendicular to e_n.
132
+ //
133
+ // The factor of 0.5 is used to be consistent with the line direction
134
+ // update.
135
+ AmbientVector y;
136
+ y << 0.5 * delta_o, 0;
137
+ o_plus_delta += y - v * (beta * (v.transpose() * y));
138
+
139
+ return true;
140
+ }
141
+
142
+ template <int AmbientSpaceDimension>
143
+ bool LineParameterization<AmbientSpaceDimension>::ComputeJacobian(
144
+ const double* x_ptr, double* jacobian_ptr) const {
145
+ static constexpr int kDim = AmbientSpaceDimension;
146
+ using AmbientVector = Eigen::Matrix<double, kDim, 1>;
147
+ using ConstAmbientVectorRef =
148
+ Eigen::Map<const Eigen::Matrix<double, kDim, 1>>;
149
+ using MatrixRef = Eigen::Map<
150
+ Eigen::Matrix<double, 2 * kDim, 2 * (kDim - 1), Eigen::RowMajor>>;
151
+
152
+ ConstAmbientVectorRef d(x_ptr + kDim);
153
+ MatrixRef jacobian(jacobian_ptr);
154
+
155
+ // Clear the Jacobian as only half of the matrix is not zero.
156
+ jacobian.setZero();
157
+
158
+ AmbientVector v;
159
+ double beta;
160
+
161
+ // NOTE: The explicit template arguments are needed here because
162
+ // ComputeHouseholderVector is templated and some versions of MSVC
163
+ // have trouble deducing the type of v automatically.
164
+ internal::ComputeHouseholderVector<ConstAmbientVectorRef, double, kDim>(
165
+ d, &v, &beta);
166
+
167
+ // The Jacobian is equal to J = 0.5 * H.leftCols(kDim - 1) where H is
168
+ // the Householder matrix (H = I - beta * v * v') for the origin point. For
169
+ // the line direction part the Jacobian is scaled by the norm of the
170
+ // direction.
171
+ for (int i = 0; i < kDim - 1; ++i) {
172
+ jacobian.block(0, i, kDim, 1) = -0.5 * beta * v(i) * v;
173
+ jacobian.col(i)(i) += 0.5;
174
+ }
175
+
176
+ jacobian.template block<kDim, kDim - 1>(kDim, kDim - 1) =
177
+ jacobian.template block<kDim, kDim - 1>(0, 0) * d.norm();
178
+ return true;
179
+ }
180
+
181
+ } // namespace ceres
182
+
183
+ #endif // CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
include/ceres/internal/memory.h ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2017 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // -----------------------------------------------------------------------------
16
+ // File: memory.h
17
+ // -----------------------------------------------------------------------------
18
+ //
19
+ // This header file contains utility functions for managing the creation and
20
+ // conversion of smart pointers. This file is an extension to the C++
21
+ // standard <memory> library header file.
22
+
23
+ #ifndef CERES_PUBLIC_INTERNAL_MEMORY_H_
24
+ #define CERES_PUBLIC_INTERNAL_MEMORY_H_
25
+
26
+ #include <memory>
27
+
28
+ #ifdef CERES_HAVE_EXCEPTIONS
29
+ #define CERES_INTERNAL_TRY try
30
+ #define CERES_INTERNAL_CATCH_ANY catch (...)
31
+ #define CERES_INTERNAL_RETHROW \
32
+ do { \
33
+ throw; \
34
+ } while (false)
35
+ #else // CERES_HAVE_EXCEPTIONS
36
+ #define CERES_INTERNAL_TRY if (true)
37
+ #define CERES_INTERNAL_CATCH_ANY else if (false)
38
+ #define CERES_INTERNAL_RETHROW \
39
+ do { \
40
+ } while (false)
41
+ #endif // CERES_HAVE_EXCEPTIONS
42
+
43
+ namespace ceres {
44
+ namespace internal {
45
+
46
+ template <typename Allocator, typename Iterator, typename... Args>
47
+ void ConstructRange(Allocator& alloc,
48
+ Iterator first,
49
+ Iterator last,
50
+ const Args&... args) {
51
+ for (Iterator cur = first; cur != last; ++cur) {
52
+ CERES_INTERNAL_TRY {
53
+ std::allocator_traits<Allocator>::construct(
54
+ alloc, std::addressof(*cur), args...);
55
+ }
56
+ CERES_INTERNAL_CATCH_ANY {
57
+ while (cur != first) {
58
+ --cur;
59
+ std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
60
+ }
61
+ CERES_INTERNAL_RETHROW;
62
+ }
63
+ }
64
+ }
65
+
66
+ template <typename Allocator, typename Iterator, typename InputIterator>
67
+ void CopyRange(Allocator& alloc,
68
+ Iterator destination,
69
+ InputIterator first,
70
+ InputIterator last) {
71
+ for (Iterator cur = destination; first != last;
72
+ static_cast<void>(++cur), static_cast<void>(++first)) {
73
+ CERES_INTERNAL_TRY {
74
+ std::allocator_traits<Allocator>::construct(
75
+ alloc, std::addressof(*cur), *first);
76
+ }
77
+ CERES_INTERNAL_CATCH_ANY {
78
+ while (cur != destination) {
79
+ --cur;
80
+ std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
81
+ }
82
+ CERES_INTERNAL_RETHROW;
83
+ }
84
+ }
85
+ }
86
+
87
+ } // namespace internal
88
+ } // namespace ceres
89
+
90
+ #endif // CERES_PUBLIC_INTERNAL_MEMORY_H_
include/ceres/internal/numeric_diff.h ADDED
@@ -0,0 +1,508 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2015 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+ // mierle@gmail.com (Keir Mierle)
31
+ // tbennun@gmail.com (Tal Ben-Nun)
32
+ //
33
+ // Finite differencing routines used by NumericDiffCostFunction.
34
+
35
+ #ifndef CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
36
+ #define CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
37
+
38
+ #include <cstring>
39
+ #include <utility>
40
+
41
+ #include "Eigen/Dense"
42
+ #include "Eigen/StdVector"
43
+ #include "ceres/cost_function.h"
44
+ #include "ceres/internal/fixed_array.h"
45
+ #include "ceres/internal/variadic_evaluate.h"
46
+ #include "ceres/numeric_diff_options.h"
47
+ #include "ceres/types.h"
48
+ #include "glog/logging.h"
49
+
50
+ namespace ceres {
51
+ namespace internal {
52
+
53
+ // This is split from the main class because C++ doesn't allow partial template
54
+ // specializations for member functions. The alternative is to repeat the main
55
+ // class for differing numbers of parameters, which is also unfortunate.
56
+ template <typename CostFunctor,
57
+ NumericDiffMethodType kMethod,
58
+ int kNumResiduals,
59
+ typename ParameterDims,
60
+ int kParameterBlock,
61
+ int kParameterBlockSize>
62
+ struct NumericDiff {
63
+ // Mutates parameters but must restore them before return.
64
+ static bool EvaluateJacobianForParameterBlock(
65
+ const CostFunctor* functor,
66
+ const double* residuals_at_eval_point,
67
+ const NumericDiffOptions& options,
68
+ int num_residuals,
69
+ int parameter_block_index,
70
+ int parameter_block_size,
71
+ double** parameters,
72
+ double* jacobian) {
73
+ using Eigen::ColMajor;
74
+ using Eigen::Map;
75
+ using Eigen::Matrix;
76
+ using Eigen::RowMajor;
77
+
78
+ DCHECK(jacobian);
79
+
80
+ const int num_residuals_internal =
81
+ (kNumResiduals != ceres::DYNAMIC ? kNumResiduals : num_residuals);
82
+ const int parameter_block_index_internal =
83
+ (kParameterBlock != ceres::DYNAMIC ? kParameterBlock
84
+ : parameter_block_index);
85
+ const int parameter_block_size_internal =
86
+ (kParameterBlockSize != ceres::DYNAMIC ? kParameterBlockSize
87
+ : parameter_block_size);
88
+
89
+ using ResidualVector = Matrix<double, kNumResiduals, 1>;
90
+ using ParameterVector = Matrix<double, kParameterBlockSize, 1>;
91
+
92
+ // The convoluted reasoning for choosing the Row/Column major
93
+ // ordering of the matrix is an artifact of the restrictions in
94
+ // Eigen that prevent it from creating RowMajor matrices with a
95
+ // single column. In these cases, we ask for a ColMajor matrix.
96
+ using JacobianMatrix =
97
+ Matrix<double,
98
+ kNumResiduals,
99
+ kParameterBlockSize,
100
+ (kParameterBlockSize == 1) ? ColMajor : RowMajor>;
101
+
102
+ Map<JacobianMatrix> parameter_jacobian(
103
+ jacobian, num_residuals_internal, parameter_block_size_internal);
104
+
105
+ Map<ParameterVector> x_plus_delta(
106
+ parameters[parameter_block_index_internal],
107
+ parameter_block_size_internal);
108
+ ParameterVector x(x_plus_delta);
109
+ ParameterVector step_size =
110
+ x.array().abs() * ((kMethod == RIDDERS)
111
+ ? options.ridders_relative_initial_step_size
112
+ : options.relative_step_size);
113
+
114
+ // It is not a good idea to make the step size arbitrarily
115
+ // small. This will lead to problems with round off and numerical
116
+ // instability when dividing by the step size. The general
117
+ // recommendation is to not go down below sqrt(epsilon).
118
+ double min_step_size = std::sqrt(std::numeric_limits<double>::epsilon());
119
+
120
+ // For Ridders' method, the initial step size is required to be large,
121
+ // thus ridders_relative_initial_step_size is used.
122
+ if (kMethod == RIDDERS) {
123
+ min_step_size =
124
+ (std::max)(min_step_size, options.ridders_relative_initial_step_size);
125
+ }
126
+
127
+ // For each parameter in the parameter block, use finite differences to
128
+ // compute the derivative for that parameter.
129
+ FixedArray<double> temp_residual_array(num_residuals_internal);
130
+ FixedArray<double> residual_array(num_residuals_internal);
131
+ Map<ResidualVector> residuals(residual_array.data(),
132
+ num_residuals_internal);
133
+
134
+ for (int j = 0; j < parameter_block_size_internal; ++j) {
135
+ const double delta = (std::max)(min_step_size, step_size(j));
136
+
137
+ if (kMethod == RIDDERS) {
138
+ if (!EvaluateRiddersJacobianColumn(functor,
139
+ j,
140
+ delta,
141
+ options,
142
+ num_residuals_internal,
143
+ parameter_block_size_internal,
144
+ x.data(),
145
+ residuals_at_eval_point,
146
+ parameters,
147
+ x_plus_delta.data(),
148
+ temp_residual_array.data(),
149
+ residual_array.data())) {
150
+ return false;
151
+ }
152
+ } else {
153
+ if (!EvaluateJacobianColumn(functor,
154
+ j,
155
+ delta,
156
+ num_residuals_internal,
157
+ parameter_block_size_internal,
158
+ x.data(),
159
+ residuals_at_eval_point,
160
+ parameters,
161
+ x_plus_delta.data(),
162
+ temp_residual_array.data(),
163
+ residual_array.data())) {
164
+ return false;
165
+ }
166
+ }
167
+
168
+ parameter_jacobian.col(j).matrix() = residuals;
169
+ }
170
+ return true;
171
+ }
172
+
173
+ static bool EvaluateJacobianColumn(const CostFunctor* functor,
174
+ int parameter_index,
175
+ double delta,
176
+ int num_residuals,
177
+ int parameter_block_size,
178
+ const double* x_ptr,
179
+ const double* residuals_at_eval_point,
180
+ double** parameters,
181
+ double* x_plus_delta_ptr,
182
+ double* temp_residuals_ptr,
183
+ double* residuals_ptr) {
184
+ using Eigen::Map;
185
+ using Eigen::Matrix;
186
+
187
+ using ResidualVector = Matrix<double, kNumResiduals, 1>;
188
+ using ParameterVector = Matrix<double, kParameterBlockSize, 1>;
189
+
190
+ Map<const ParameterVector> x(x_ptr, parameter_block_size);
191
+ Map<ParameterVector> x_plus_delta(x_plus_delta_ptr, parameter_block_size);
192
+
193
+ Map<ResidualVector> residuals(residuals_ptr, num_residuals);
194
+ Map<ResidualVector> temp_residuals(temp_residuals_ptr, num_residuals);
195
+
196
+ // Mutate 1 element at a time and then restore.
197
+ x_plus_delta(parameter_index) = x(parameter_index) + delta;
198
+
199
+ if (!VariadicEvaluate<ParameterDims>(
200
+ *functor, parameters, residuals.data())) {
201
+ return false;
202
+ }
203
+
204
+ // Compute this column of the jacobian in 3 steps:
205
+ // 1. Store residuals for the forward part.
206
+ // 2. Subtract residuals for the backward (or 0) part.
207
+ // 3. Divide out the run.
208
+ double one_over_delta = 1.0 / delta;
209
+ if (kMethod == CENTRAL || kMethod == RIDDERS) {
210
+ // Compute the function on the other side of x(parameter_index).
211
+ x_plus_delta(parameter_index) = x(parameter_index) - delta;
212
+
213
+ if (!VariadicEvaluate<ParameterDims>(
214
+ *functor, parameters, temp_residuals.data())) {
215
+ return false;
216
+ }
217
+
218
+ residuals -= temp_residuals;
219
+ one_over_delta /= 2;
220
+ } else {
221
+ // Forward difference only; reuse existing residuals evaluation.
222
+ residuals -=
223
+ Map<const ResidualVector>(residuals_at_eval_point, num_residuals);
224
+ }
225
+
226
+ // Restore x_plus_delta.
227
+ x_plus_delta(parameter_index) = x(parameter_index);
228
+
229
+ // Divide out the run to get slope.
230
+ residuals *= one_over_delta;
231
+
232
+ return true;
233
+ }
234
+
235
+ // This numeric difference implementation uses adaptive differentiation
236
+ // on the parameters to obtain the Jacobian matrix. The adaptive algorithm
237
+ // is based on Ridders' method for adaptive differentiation, which creates
238
+ // a Romberg tableau from varying step sizes and extrapolates the
239
+ // intermediate results to obtain the current computational error.
240
+ //
241
+ // References:
242
+ // C.J.F. Ridders, Accurate computation of F'(x) and F'(x) F"(x), Advances
243
+ // in Engineering Software (1978), Volume 4, Issue 2, April 1982,
244
+ // Pages 75-76, ISSN 0141-1195,
245
+ // http://dx.doi.org/10.1016/S0141-1195(82)80057-0.
246
+ static bool EvaluateRiddersJacobianColumn(
247
+ const CostFunctor* functor,
248
+ int parameter_index,
249
+ double delta,
250
+ const NumericDiffOptions& options,
251
+ int num_residuals,
252
+ int parameter_block_size,
253
+ const double* x_ptr,
254
+ const double* residuals_at_eval_point,
255
+ double** parameters,
256
+ double* x_plus_delta_ptr,
257
+ double* temp_residuals_ptr,
258
+ double* residuals_ptr) {
259
+ using Eigen::aligned_allocator;
260
+ using Eigen::Map;
261
+ using Eigen::Matrix;
262
+
263
+ using ResidualVector = Matrix<double, kNumResiduals, 1>;
264
+ using ResidualCandidateMatrix =
265
+ Matrix<double, kNumResiduals, Eigen::Dynamic>;
266
+ using ParameterVector = Matrix<double, kParameterBlockSize, 1>;
267
+
268
+ Map<const ParameterVector> x(x_ptr, parameter_block_size);
269
+ Map<ParameterVector> x_plus_delta(x_plus_delta_ptr, parameter_block_size);
270
+
271
+ Map<ResidualVector> residuals(residuals_ptr, num_residuals);
272
+ Map<ResidualVector> temp_residuals(temp_residuals_ptr, num_residuals);
273
+
274
+ // In order for the algorithm to converge, the step size should be
275
+ // initialized to a value that is large enough to produce a significant
276
+ // change in the function.
277
+ // As the derivative is estimated, the step size decreases.
278
+ // By default, the step sizes are chosen so that the middle column
279
+ // of the Romberg tableau uses the input delta.
280
+ double current_step_size =
281
+ delta * pow(options.ridders_step_shrink_factor,
282
+ options.max_num_ridders_extrapolations / 2);
283
+
284
+ // Double-buffering temporary differential candidate vectors
285
+ // from previous step size.
286
+ ResidualCandidateMatrix stepsize_candidates_a(
287
+ num_residuals, options.max_num_ridders_extrapolations);
288
+ ResidualCandidateMatrix stepsize_candidates_b(
289
+ num_residuals, options.max_num_ridders_extrapolations);
290
+ ResidualCandidateMatrix* current_candidates = &stepsize_candidates_a;
291
+ ResidualCandidateMatrix* previous_candidates = &stepsize_candidates_b;
292
+
293
+ // Represents the computational error of the derivative. This variable is
294
+ // initially set to a large value, and is set to the difference between
295
+ // current and previous finite difference extrapolations.
296
+ // norm_error is supposed to decrease as the finite difference tableau
297
+ // generation progresses, serving both as an estimate for differentiation
298
+ // error and as a measure of differentiation numerical stability.
299
+ double norm_error = (std::numeric_limits<double>::max)();
300
+
301
+ // Loop over decreasing step sizes until:
302
+ // 1. Error is smaller than a given value (ridders_epsilon),
303
+ // 2. Maximal order of extrapolation reached, or
304
+ // 3. Extrapolation becomes numerically unstable.
305
+ for (int i = 0; i < options.max_num_ridders_extrapolations; ++i) {
306
+ // Compute the numerical derivative at this step size.
307
+ if (!EvaluateJacobianColumn(functor,
308
+ parameter_index,
309
+ current_step_size,
310
+ num_residuals,
311
+ parameter_block_size,
312
+ x.data(),
313
+ residuals_at_eval_point,
314
+ parameters,
315
+ x_plus_delta.data(),
316
+ temp_residuals.data(),
317
+ current_candidates->col(0).data())) {
318
+ // Something went wrong; bail.
319
+ return false;
320
+ }
321
+
322
+ // Store initial results.
323
+ if (i == 0) {
324
+ residuals = current_candidates->col(0);
325
+ }
326
+
327
+ // Shrink differentiation step size.
328
+ current_step_size /= options.ridders_step_shrink_factor;
329
+
330
+ // Extrapolation factor for Richardson acceleration method (see below).
331
+ double richardson_factor = options.ridders_step_shrink_factor *
332
+ options.ridders_step_shrink_factor;
333
+ for (int k = 1; k <= i; ++k) {
334
+ // Extrapolate the various orders of finite differences using
335
+ // the Richardson acceleration method.
336
+ current_candidates->col(k) =
337
+ (richardson_factor * current_candidates->col(k - 1) -
338
+ previous_candidates->col(k - 1)) /
339
+ (richardson_factor - 1.0);
340
+
341
+ richardson_factor *= options.ridders_step_shrink_factor *
342
+ options.ridders_step_shrink_factor;
343
+
344
+ // Compute the difference between the previous value and the current.
345
+ double candidate_error = (std::max)(
346
+ (current_candidates->col(k) - current_candidates->col(k - 1))
347
+ .norm(),
348
+ (current_candidates->col(k) - previous_candidates->col(k - 1))
349
+ .norm());
350
+
351
+ // If the error has decreased, update results.
352
+ if (candidate_error <= norm_error) {
353
+ norm_error = candidate_error;
354
+ residuals = current_candidates->col(k);
355
+
356
+ // If the error is small enough, stop.
357
+ if (norm_error < options.ridders_epsilon) {
358
+ break;
359
+ }
360
+ }
361
+ }
362
+
363
+ // After breaking out of the inner loop, declare convergence.
364
+ if (norm_error < options.ridders_epsilon) {
365
+ break;
366
+ }
367
+
368
+ // Check to see if the current gradient estimate is numerically unstable.
369
+ // If so, bail out and return the last stable result.
370
+ if (i > 0) {
371
+ double tableau_error =
372
+ (current_candidates->col(i) - previous_candidates->col(i - 1))
373
+ .norm();
374
+
375
+ // Compare current error to the chosen candidate's error.
376
+ if (tableau_error >= 2 * norm_error) {
377
+ break;
378
+ }
379
+ }
380
+
381
+ std::swap(current_candidates, previous_candidates);
382
+ }
383
+ return true;
384
+ }
385
+ };
386
+
387
+ // This function calls NumericDiff<...>::EvaluateJacobianForParameterBlock for
388
+ // each parameter block.
389
+ //
390
+ // Example:
391
+ // A call to
392
+ // EvaluateJacobianForParameterBlocks<StaticParameterDims<2, 3>>(
393
+ // functor,
394
+ // residuals_at_eval_point,
395
+ // options,
396
+ // num_residuals,
397
+ // parameters,
398
+ // jacobians);
399
+ // will result in the following calls to
400
+ // NumericDiff<...>::EvaluateJacobianForParameterBlock:
401
+ //
402
+ // if (jacobians[0] != nullptr) {
403
+ // if (!NumericDiff<
404
+ // CostFunctor,
405
+ // method,
406
+ // kNumResiduals,
407
+ // StaticParameterDims<2, 3>,
408
+ // 0,
409
+ // 2>::EvaluateJacobianForParameterBlock(functor,
410
+ // residuals_at_eval_point,
411
+ // options,
412
+ // num_residuals,
413
+ // 0,
414
+ // 2,
415
+ // parameters,
416
+ // jacobians[0])) {
417
+ // return false;
418
+ // }
419
+ // }
420
+ // if (jacobians[1] != nullptr) {
421
+ // if (!NumericDiff<
422
+ // CostFunctor,
423
+ // method,
424
+ // kNumResiduals,
425
+ // StaticParameterDims<2, 3>,
426
+ // 1,
427
+ // 3>::EvaluateJacobianForParameterBlock(functor,
428
+ // residuals_at_eval_point,
429
+ // options,
430
+ // num_residuals,
431
+ // 1,
432
+ // 3,
433
+ // parameters,
434
+ // jacobians[1])) {
435
+ // return false;
436
+ // }
437
+ // }
438
+ template <typename ParameterDims,
439
+ typename Parameters = typename ParameterDims::Parameters,
440
+ int ParameterIdx = 0>
441
+ struct EvaluateJacobianForParameterBlocks;
442
+
443
+ template <typename ParameterDims, int N, int... Ns, int ParameterIdx>
444
+ struct EvaluateJacobianForParameterBlocks<ParameterDims,
445
+ std::integer_sequence<int, N, Ns...>,
446
+ ParameterIdx> {
447
+ template <NumericDiffMethodType method,
448
+ int kNumResiduals,
449
+ typename CostFunctor>
450
+ static bool Apply(const CostFunctor* functor,
451
+ const double* residuals_at_eval_point,
452
+ const NumericDiffOptions& options,
453
+ int num_residuals,
454
+ double** parameters,
455
+ double** jacobians) {
456
+ if (jacobians[ParameterIdx] != nullptr) {
457
+ if (!NumericDiff<
458
+ CostFunctor,
459
+ method,
460
+ kNumResiduals,
461
+ ParameterDims,
462
+ ParameterIdx,
463
+ N>::EvaluateJacobianForParameterBlock(functor,
464
+ residuals_at_eval_point,
465
+ options,
466
+ num_residuals,
467
+ ParameterIdx,
468
+ N,
469
+ parameters,
470
+ jacobians[ParameterIdx])) {
471
+ return false;
472
+ }
473
+ }
474
+
475
+ return EvaluateJacobianForParameterBlocks<ParameterDims,
476
+ std::integer_sequence<int, Ns...>,
477
+ ParameterIdx + 1>::
478
+ template Apply<method, kNumResiduals>(functor,
479
+ residuals_at_eval_point,
480
+ options,
481
+ num_residuals,
482
+ parameters,
483
+ jacobians);
484
+ }
485
+ };
486
+
487
+ // End of 'recursion'. Nothing more to do.
488
+ template <typename ParameterDims, int ParameterIdx>
489
+ struct EvaluateJacobianForParameterBlocks<ParameterDims,
490
+ std::integer_sequence<int>,
491
+ ParameterIdx> {
492
+ template <NumericDiffMethodType method,
493
+ int kNumResiduals,
494
+ typename CostFunctor>
495
+ static bool Apply(const CostFunctor* /* NOT USED*/,
496
+ const double* /* NOT USED*/,
497
+ const NumericDiffOptions& /* NOT USED*/,
498
+ int /* NOT USED*/,
499
+ double** /* NOT USED*/,
500
+ double** /* NOT USED*/) {
501
+ return true;
502
+ }
503
+ };
504
+
505
+ } // namespace internal
506
+ } // namespace ceres
507
+
508
+ #endif // CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
include/ceres/internal/parameter_dims.h ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2018 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: jodebo_beck@gmx.de (Johannes Beck)
30
+
31
+ #ifndef CERES_PUBLIC_INTERNAL_PARAMETER_DIMS_H_
32
+ #define CERES_PUBLIC_INTERNAL_PARAMETER_DIMS_H_
33
+
34
+ #include <array>
35
+ #include <utility>
36
+
37
+ #include "ceres/internal/integer_sequence_algorithm.h"
38
+
39
+ namespace ceres {
40
+ namespace internal {
41
+
42
+ // Checks, whether the given parameter block sizes are valid. Valid means every
43
+ // dimension is bigger than zero.
44
+ constexpr bool IsValidParameterDimensionSequence(std::integer_sequence<int>) {
45
+ return true;
46
+ }
47
+
48
+ template <int N, int... Ts>
49
+ constexpr bool IsValidParameterDimensionSequence(
50
+ std::integer_sequence<int, N, Ts...>) {
51
+ return (N <= 0) ? false
52
+ : IsValidParameterDimensionSequence(
53
+ std::integer_sequence<int, Ts...>());
54
+ }
55
+
56
+ // Helper class that represents the parameter dimensions. The parameter
57
+ // dimensions are either dynamic or the sizes are known at compile time. It is
58
+ // used to pass parameter block dimensions around (e.g. between functions or
59
+ // classes).
60
+ //
61
+ // As an example if one have three parameter blocks with dimensions (2, 4, 1),
62
+ // one would use 'StaticParameterDims<2, 4, 1>' which is a synonym for
63
+ // 'ParameterDims<false, 2, 4, 1>'.
64
+ // For dynamic parameter dims, one would just use 'DynamicParameterDims', which
65
+ // is a synonym for 'ParameterDims<true>'.
66
+ template <bool IsDynamic, int... Ns>
67
+ class ParameterDims {
68
+ public:
69
+ using Parameters = std::integer_sequence<int, Ns...>;
70
+
71
+ // The parameter dimensions are only valid if all parameter block dimensions
72
+ // are greater than zero.
73
+ static constexpr bool kIsValid =
74
+ IsValidParameterDimensionSequence(Parameters());
75
+ static_assert(kIsValid,
76
+ "Invalid parameter block dimension detected. Each parameter "
77
+ "block dimension must be bigger than zero.");
78
+
79
+ static constexpr bool kIsDynamic = IsDynamic;
80
+ static constexpr int kNumParameterBlocks = sizeof...(Ns);
81
+ static_assert(kIsDynamic || kNumParameterBlocks > 0,
82
+ "At least one parameter block must be specified.");
83
+
84
+ static constexpr int kNumParameters =
85
+ Sum<std::integer_sequence<int, Ns...>>::Value;
86
+
87
+ static constexpr int GetDim(int dim) { return params_[dim]; }
88
+
89
+ // If one has all parameters packed into a single array this function unpacks
90
+ // the parameters.
91
+ template <typename T>
92
+ static inline std::array<T*, kNumParameterBlocks> GetUnpackedParameters(
93
+ T* ptr) {
94
+ using Offsets = ExclusiveScan<Parameters>;
95
+ return GetUnpackedParameters(ptr, Offsets());
96
+ }
97
+
98
+ private:
99
+ template <typename T, int... Indices>
100
+ static inline std::array<T*, kNumParameterBlocks> GetUnpackedParameters(
101
+ T* ptr, std::integer_sequence<int, Indices...>) {
102
+ return std::array<T*, kNumParameterBlocks>{{ptr + Indices...}};
103
+ }
104
+
105
+ static constexpr std::array<int, kNumParameterBlocks> params_{Ns...};
106
+ };
107
+
108
+ // Even static constexpr member variables needs to be defined (not only
109
+ // declared). As the ParameterDims class is tempalted this definition must
110
+ // be in the header file.
111
+ template <bool IsDynamic, int... Ns>
112
+ constexpr std::array<int, ParameterDims<IsDynamic, Ns...>::kNumParameterBlocks>
113
+ ParameterDims<IsDynamic, Ns...>::params_;
114
+
115
+ // Using declarations for static and dynamic parameter dims. This makes client
116
+ // code easier to read.
117
+ template <int... Ns>
118
+ using StaticParameterDims = ParameterDims<false, Ns...>;
119
+ using DynamicParameterDims = ParameterDims<true>;
120
+
121
+ } // namespace internal
122
+ } // namespace ceres
123
+
124
+ #endif // CERES_PUBLIC_INTERNAL_PARAMETER_DIMS_H_
include/ceres/internal/port.h ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2022 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: keir@google.com (Keir Mierle)
30
+
31
+ #ifndef CERES_PUBLIC_INTERNAL_PORT_H_
32
+ #define CERES_PUBLIC_INTERNAL_PORT_H_
33
+
34
+ // A macro to mark a function/variable/class as deprecated.
35
+ // We use compiler specific attributes rather than the c++
36
+ // attribute because they do not mix well with each other.
37
+ #if defined(_MSC_VER)
38
+ #define CERES_DEPRECATED_WITH_MSG(message) __declspec(deprecated(message))
39
+ #elif defined(__GNUC__)
40
+ #define CERES_DEPRECATED_WITH_MSG(message) __attribute__((deprecated(message)))
41
+ #else
42
+ // In the worst case fall back to c++ attribute.
43
+ #define CERES_DEPRECATED_WITH_MSG(message) [[deprecated(message)]]
44
+ #endif
45
+
46
+ #ifndef CERES_GET_FLAG
47
+ #define CERES_GET_FLAG(X) X
48
+ #endif
49
+
50
+ // Indicates whether C++17 is currently active
51
+ #ifndef CERES_HAS_CPP17
52
+ #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
53
+ #define CERES_HAS_CPP17
54
+ #endif // __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >=
55
+ // 201703L)
56
+ #endif // !defined(CERES_HAS_CPP17)
57
+
58
+ // Indicates whether C++20 is currently active
59
+ #ifndef CERES_HAS_CPP20
60
+ #if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
61
+ #define CERES_HAS_CPP20
62
+ #endif // __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >=
63
+ // 202002L)
64
+ #endif // !defined(CERES_HAS_CPP20)
65
+
66
+ // Prevents symbols from being substituted by the corresponding macro definition
67
+ // under the same name. For instance, min and max are defined as macros on
68
+ // Windows (unless NOMINMAX is defined) which causes compilation errors when
69
+ // defining or referencing symbols under the same name.
70
+ //
71
+ // To be robust in all cases particularly when NOMINMAX cannot be used, use this
72
+ // macro to annotate min/max declarations/definitions. Examples:
73
+ //
74
+ // int max CERES_PREVENT_MACRO_SUBSTITUTION();
75
+ // min CERES_PREVENT_MACRO_SUBSTITUTION(a, b);
76
+ // max CERES_PREVENT_MACRO_SUBSTITUTION(a, b);
77
+ //
78
+ // NOTE: In case the symbols for which the substitution must be prevented are
79
+ // used within another macro, the substitution must be inhibited using parens as
80
+ //
81
+ // (std::numerical_limits<double>::max)()
82
+ //
83
+ // since the helper macro will not work here. Do not use this technique in
84
+ // general case, because it will prevent argument-dependent lookup (ADL).
85
+ //
86
+ #define CERES_PREVENT_MACRO_SUBSTITUTION // Yes, it's empty
87
+
88
+ #endif // CERES_PUBLIC_INTERNAL_PORT_H_
include/ceres/internal/reenable_warnings.h ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2015 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+
30
+ // This is not your usual header guard. See disable_warnings.h
31
+ #ifdef CERES_WARNINGS_DISABLED
32
+ #undef CERES_WARNINGS_DISABLED
33
+
34
+ #ifdef _MSC_VER
35
+ #pragma warning(pop)
36
+ #endif
37
+
38
+ #endif // CERES_WARNINGS_DISABLED
include/ceres/internal/sphere_manifold_functions.h ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2022 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: vitus@google.com (Mike Vitus)
30
+ // jodebo_beck@gmx.de (Johannes Beck)
31
+
32
+ #ifndef CERES_PUBLIC_INTERNAL_SPHERE_MANIFOLD_HELPERS_H_
33
+ #define CERES_PUBLIC_INTERNAL_SPHERE_MANIFOLD_HELPERS_H_
34
+
35
+ #include "ceres/internal/householder_vector.h"
36
+
37
+ // This module contains functions to compute the SphereManifold plus and minus
38
+ // operator and their Jacobians.
39
+ //
40
+ // As the parameters to these functions are shared between them, they are
41
+ // described here: The following variable names are used:
42
+ // Plus(x, delta) = x + delta = x_plus_delta,
43
+ // Minus(y, x) = y - x = y_minus_x.
44
+ //
45
+ // The remaining ones are v and beta which describe the Householder
46
+ // transformation of x, and norm_delta which is the norm of delta.
47
+ //
48
+ // The types of x, y, x_plus_delta and y_minus_x need to be equivalent to
49
+ // Eigen::Matrix<double, AmbientSpaceDimension, 1> and the type of delta needs
50
+ // to be equivalent to Eigen::Matrix<double, TangentSpaceDimension, 1>.
51
+ //
52
+ // The type of Jacobian plus needs to be equivalent to Eigen::Matrix<double,
53
+ // AmbientSpaceDimension, TangentSpaceDimension, Eigen::RowMajor> and for
54
+ // Jacobian minus Eigen::Matrix<double, TangentSpaceDimension,
55
+ // AmbientSpaceDimension, Eigen::RowMajor>.
56
+ //
57
+ // For all vector / matrix inputs and outputs, template parameters are
58
+ // used in order to allow also Eigen::Ref and Eigen block expressions to
59
+ // be passed to the function.
60
+
61
+ namespace ceres {
62
+ namespace internal {
63
+
64
+ template <typename VT, typename XT, typename DeltaT, typename XPlusDeltaT>
65
+ inline void ComputeSphereManifoldPlus(const VT& v,
66
+ double beta,
67
+ const XT& x,
68
+ const DeltaT& delta,
69
+ double norm_delta,
70
+ XPlusDeltaT* x_plus_delta) {
71
+ constexpr int AmbientDim = VT::RowsAtCompileTime;
72
+
73
+ // Map the delta from the minimum representation to the over parameterized
74
+ // homogeneous vector. See B.2 p.25 equation (106) - (107) for more details.
75
+ const double norm_delta_div_2 = 0.5 * norm_delta;
76
+ const double sin_delta_by_delta =
77
+ std::sin(norm_delta_div_2) / norm_delta_div_2;
78
+
79
+ Eigen::Matrix<double, AmbientDim, 1> y(v.size());
80
+ y << 0.5 * sin_delta_by_delta * delta, std::cos(norm_delta_div_2);
81
+
82
+ // Apply the delta update to remain on the sphere.
83
+ *x_plus_delta = x.norm() * ApplyHouseholderVector(y, v, beta);
84
+ }
85
+
86
+ template <typename VT, typename JacobianT>
87
+ inline void ComputeSphereManifoldPlusJacobian(const VT& x,
88
+ JacobianT* jacobian) {
89
+ constexpr int AmbientSpaceDim = VT::RowsAtCompileTime;
90
+ using AmbientVector = Eigen::Matrix<double, AmbientSpaceDim, 1>;
91
+ const int ambient_size = x.size();
92
+ const int tangent_size = x.size() - 1;
93
+
94
+ AmbientVector v(ambient_size);
95
+ double beta;
96
+
97
+ // NOTE: The explicit template arguments are needed here because
98
+ // ComputeHouseholderVector is templated and some versions of MSVC
99
+ // have trouble deducing the type of v automatically.
100
+ ComputeHouseholderVector<VT, double, AmbientSpaceDim>(x, &v, &beta);
101
+
102
+ // The Jacobian is equal to J = 0.5 * H.leftCols(size_ - 1) where H is the
103
+ // Householder matrix (H = I - beta * v * v').
104
+ for (int i = 0; i < tangent_size; ++i) {
105
+ (*jacobian).col(i) = -0.5 * beta * v(i) * v;
106
+ (*jacobian)(i, i) += 0.5;
107
+ }
108
+ (*jacobian) *= x.norm();
109
+ }
110
+
111
+ template <typename VT, typename XT, typename YT, typename YMinusXT>
112
+ inline void ComputeSphereManifoldMinus(
113
+ const VT& v, double beta, const XT& x, const YT& y, YMinusXT* y_minus_x) {
114
+ constexpr int AmbientSpaceDim = VT::RowsAtCompileTime;
115
+ constexpr int TangentSpaceDim =
116
+ AmbientSpaceDim == Eigen::Dynamic ? Eigen::Dynamic : AmbientSpaceDim - 1;
117
+ using AmbientVector = Eigen::Matrix<double, AmbientSpaceDim, 1>;
118
+
119
+ const int tanget_size = v.size() - 1;
120
+
121
+ const AmbientVector hy = ApplyHouseholderVector(y, v, beta) / x.norm();
122
+
123
+ // Calculate y - x. See B.2 p.25 equation (108).
124
+ double y_last = hy[tanget_size];
125
+ double hy_norm = hy.template head<TangentSpaceDim>(tanget_size).norm();
126
+ if (hy_norm == 0.0) {
127
+ y_minus_x->setZero();
128
+ } else {
129
+ *y_minus_x = 2.0 * std::atan2(hy_norm, y_last) / hy_norm *
130
+ hy.template head<TangentSpaceDim>(tanget_size);
131
+ }
132
+ }
133
+
134
+ template <typename VT, typename JacobianT>
135
+ inline void ComputeSphereManifoldMinusJacobian(const VT& x,
136
+ JacobianT* jacobian) {
137
+ constexpr int AmbientSpaceDim = VT::RowsAtCompileTime;
138
+ using AmbientVector = Eigen::Matrix<double, AmbientSpaceDim, 1>;
139
+ const int ambient_size = x.size();
140
+ const int tangent_size = x.size() - 1;
141
+
142
+ AmbientVector v(ambient_size);
143
+ double beta;
144
+
145
+ // NOTE: The explicit template arguments are needed here because
146
+ // ComputeHouseholderVector is templated and some versions of MSVC
147
+ // have trouble deducing the type of v automatically.
148
+ ComputeHouseholderVector<VT, double, AmbientSpaceDim>(x, &v, &beta);
149
+
150
+ // The Jacobian is equal to J = 2.0 * H.leftCols(size_ - 1) where H is the
151
+ // Householder matrix (H = I - beta * v * v').
152
+ for (int i = 0; i < tangent_size; ++i) {
153
+ (*jacobian).row(i) = -2.0 * beta * v(i) * v;
154
+ (*jacobian)(i, i) += 2.0;
155
+ }
156
+ (*jacobian) /= x.norm();
157
+ }
158
+
159
+ } // namespace internal
160
+ } // namespace ceres
161
+
162
+ #endif
include/ceres/internal/variadic_evaluate.h ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Ceres Solver - A fast non-linear least squares minimizer
2
+ // Copyright 2015 Google Inc. All rights reserved.
3
+ // http://ceres-solver.org/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright notice,
9
+ // this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above copyright notice,
11
+ // this list of conditions and the following disclaimer in the documentation
12
+ // and/or other materials provided with the distribution.
13
+ // * Neither the name of Google Inc. nor the names of its contributors may be
14
+ // used to endorse or promote products derived from this software without
15
+ // specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ // POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Author: sameeragarwal@google.com (Sameer Agarwal)
30
+ // mierle@gmail.com (Keir Mierle)
31
+ // jodebo_beck@gmx.de (Johannes Beck)
32
+
33
+ #ifndef CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
34
+ #define CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
35
+
36
+ #include <cstddef>
37
+ #include <type_traits>
38
+ #include <utility>
39
+
40
+ #include "ceres/cost_function.h"
41
+ #include "ceres/internal/parameter_dims.h"
42
+
43
+ namespace ceres {
44
+ namespace internal {
45
+
46
+ // For fixed size cost functors
47
+ template <typename Functor, typename T, int... Indices>
48
+ inline bool VariadicEvaluateImpl(const Functor& functor,
49
+ T const* const* input,
50
+ T* output,
51
+ std::false_type /*is_dynamic*/,
52
+ std::integer_sequence<int, Indices...>) {
53
+ static_assert(sizeof...(Indices),
54
+ "Invalid number of parameter blocks. At least one parameter "
55
+ "block must be specified.");
56
+ return functor(input[Indices]..., output);
57
+ }
58
+
59
+ // For dynamic sized cost functors
60
+ template <typename Functor, typename T>
61
+ inline bool VariadicEvaluateImpl(const Functor& functor,
62
+ T const* const* input,
63
+ T* output,
64
+ std::true_type /*is_dynamic*/,
65
+ std::integer_sequence<int>) {
66
+ return functor(input, output);
67
+ }
68
+
69
+ // For ceres cost functors (not ceres::CostFunction)
70
+ template <typename ParameterDims, typename Functor, typename T>
71
+ inline bool VariadicEvaluateImpl(const Functor& functor,
72
+ T const* const* input,
73
+ T* output,
74
+ const void* /* NOT USED */) {
75
+ using ParameterBlockIndices =
76
+ std::make_integer_sequence<int, ParameterDims::kNumParameterBlocks>;
77
+ using IsDynamic = std::integral_constant<bool, ParameterDims::kIsDynamic>;
78
+ return VariadicEvaluateImpl(
79
+ functor, input, output, IsDynamic(), ParameterBlockIndices());
80
+ }
81
+
82
+ // For ceres::CostFunction
83
+ template <typename ParameterDims, typename Functor, typename T>
84
+ inline bool VariadicEvaluateImpl(const Functor& functor,
85
+ T const* const* input,
86
+ T* output,
87
+ const CostFunction* /* NOT USED */) {
88
+ return functor.Evaluate(input, output, nullptr);
89
+ }
90
+
91
+ // Variadic evaluate is a helper function to evaluate ceres cost function or
92
+ // functors using an input, output and the parameter dimensions. There are
93
+ // several ways different possibilities:
94
+ // 1) If the passed functor is a 'ceres::CostFunction' its evaluate method is
95
+ // called.
96
+ // 2) If the functor is not a 'ceres::CostFunction' and the specified parameter
97
+ // dims is dynamic, the functor must have the following signature
98
+ // 'bool(T const* const* input, T* output)'.
99
+ // 3) If the functor is not a 'ceres::CostFunction' and the specified parameter
100
+ // dims is not dynamic, the input is expanded by using the number of parameter
101
+ // blocks. The signature of the functor must have the following signature
102
+ // 'bool()(const T* i_1, const T* i_2, ... const T* i_n, T* output)'.
103
+ template <typename ParameterDims, typename Functor, typename T>
104
+ inline bool VariadicEvaluate(const Functor& functor,
105
+ T const* const* input,
106
+ T* output) {
107
+ return VariadicEvaluateImpl<ParameterDims>(functor, input, output, &functor);
108
+ }
109
+
110
+ } // namespace internal
111
+ } // namespace ceres
112
+
113
+ #endif // CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_