Merge branch 'hybrid/error' into hybrid/tests
						commit
						5bfce89b65
					
				|  | @ -101,8 +101,6 @@ if(GTSAM_BUILD_PYTHON OR GTSAM_INSTALL_MATLAB_TOOLBOX) | ||||||
|     # Copy matlab.h to the correct folder. |     # Copy matlab.h to the correct folder. | ||||||
|     configure_file(${PROJECT_SOURCE_DIR}/wrap/matlab.h |     configure_file(${PROJECT_SOURCE_DIR}/wrap/matlab.h | ||||||
|                ${PROJECT_BINARY_DIR}/wrap/matlab.h COPYONLY) |                ${PROJECT_BINARY_DIR}/wrap/matlab.h COPYONLY) | ||||||
|     # Add the include directories so that matlab.h can be found |  | ||||||
|     include_directories("${PROJECT_BINARY_DIR}" "${GTSAM_EIGEN_INCLUDE_FOR_BUILD}") |  | ||||||
| 
 | 
 | ||||||
|     add_subdirectory(wrap) |     add_subdirectory(wrap) | ||||||
|     list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/wrap/cmake") |     list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/wrap/cmake") | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ will run up to 10x faster in Release mode! See the end of this document for | ||||||
| additional debugging tips. | additional debugging tips. | ||||||
| 
 | 
 | ||||||
| 3. GTSAM has Doxygen documentation. To generate, run 'make doc' from your | 3. GTSAM has Doxygen documentation. To generate, run 'make doc' from your | ||||||
| build directory. | build directory after setting the `GTSAM_BUILD_DOCS` and `GTSAM_BUILD_[HTML|LATEX]` cmake flags. | ||||||
| 
 | 
 | ||||||
| 4. The instructions below install the library to the default system install path and | 4. The instructions below install the library to the default system install path and | ||||||
| build all components. From a terminal, starting in the root library folder, | build all components. From a terminal, starting in the root library folder, | ||||||
|  |  | ||||||
|  | @ -21,6 +21,10 @@ else() | ||||||
| find_dependency(Boost @BOOST_FIND_MINIMUM_VERSION@ COMPONENTS @BOOST_FIND_MINIMUM_COMPONENTS@) | find_dependency(Boost @BOOST_FIND_MINIMUM_VERSION@ COMPONENTS @BOOST_FIND_MINIMUM_COMPONENTS@) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
|  | if(@GTSAM_USE_SYSTEM_EIGEN@) | ||||||
|  | find_dependency(Eigen3 REQUIRED) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| # Load exports | # Load exports | ||||||
| include(${OUR_CMAKE_DIR}/@PACKAGE_NAME@-exports.cmake) | include(${OUR_CMAKE_DIR}/@PACKAGE_NAME@-exports.cmake) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,81 +0,0 @@ | ||||||
| # - Try to find Eigen3 lib |  | ||||||
| # |  | ||||||
| # This module supports requiring a minimum version, e.g. you can do |  | ||||||
| #   find_package(Eigen3 3.1.2) |  | ||||||
| # to require version 3.1.2 or newer of Eigen3. |  | ||||||
| # |  | ||||||
| # Once done this will define |  | ||||||
| # |  | ||||||
| #  EIGEN3_FOUND - system has eigen lib with correct version |  | ||||||
| #  EIGEN3_INCLUDE_DIR - the eigen include directory |  | ||||||
| #  EIGEN3_VERSION - eigen version |  | ||||||
| 
 |  | ||||||
| # Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org> |  | ||||||
| # Copyright (c) 2008, 2009 Gael Guennebaud, <g.gael@free.fr> |  | ||||||
| # Copyright (c) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> |  | ||||||
| # Redistribution and use is allowed according to the terms of the 2-clause BSD license. |  | ||||||
| 
 |  | ||||||
| if(NOT Eigen3_FIND_VERSION) |  | ||||||
|   if(NOT Eigen3_FIND_VERSION_MAJOR) |  | ||||||
|     set(Eigen3_FIND_VERSION_MAJOR 2) |  | ||||||
|   endif(NOT Eigen3_FIND_VERSION_MAJOR) |  | ||||||
|   if(NOT Eigen3_FIND_VERSION_MINOR) |  | ||||||
|     set(Eigen3_FIND_VERSION_MINOR 91) |  | ||||||
|   endif(NOT Eigen3_FIND_VERSION_MINOR) |  | ||||||
|   if(NOT Eigen3_FIND_VERSION_PATCH) |  | ||||||
|     set(Eigen3_FIND_VERSION_PATCH 0) |  | ||||||
|   endif(NOT Eigen3_FIND_VERSION_PATCH) |  | ||||||
| 
 |  | ||||||
|   set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}") |  | ||||||
| endif(NOT Eigen3_FIND_VERSION) |  | ||||||
| 
 |  | ||||||
| macro(_eigen3_check_version) |  | ||||||
|   file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header) |  | ||||||
| 
 |  | ||||||
|   string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}") |  | ||||||
|   set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}") |  | ||||||
|   string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}") |  | ||||||
|   set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}") |  | ||||||
|   string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}") |  | ||||||
|   set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}") |  | ||||||
| 
 |  | ||||||
|   set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION}) |  | ||||||
|   if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) |  | ||||||
|     set(EIGEN3_VERSION_OK FALSE) |  | ||||||
|   else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) |  | ||||||
|     set(EIGEN3_VERSION_OK TRUE) |  | ||||||
|   endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) |  | ||||||
| 
 |  | ||||||
|   if(NOT EIGEN3_VERSION_OK) |  | ||||||
| 
 |  | ||||||
|     message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, " |  | ||||||
|                    "but at least version ${Eigen3_FIND_VERSION} is required") |  | ||||||
|   endif(NOT EIGEN3_VERSION_OK) |  | ||||||
| endmacro(_eigen3_check_version) |  | ||||||
| 
 |  | ||||||
| if (EIGEN3_INCLUDE_DIR) |  | ||||||
| 
 |  | ||||||
|   # in cache already |  | ||||||
|   _eigen3_check_version() |  | ||||||
|   set(EIGEN3_FOUND ${EIGEN3_VERSION_OK}) |  | ||||||
| 
 |  | ||||||
| else (EIGEN3_INCLUDE_DIR) |  | ||||||
| 
 |  | ||||||
|   find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library |  | ||||||
|       PATHS |  | ||||||
|       ${CMAKE_INSTALL_PREFIX}/include |  | ||||||
|       ${KDE4_INCLUDE_DIR} |  | ||||||
|       PATH_SUFFIXES eigen3 eigen |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|   if(EIGEN3_INCLUDE_DIR) |  | ||||||
|     _eigen3_check_version() |  | ||||||
|   endif(EIGEN3_INCLUDE_DIR) |  | ||||||
| 
 |  | ||||||
|   include(FindPackageHandleStandardArgs) |  | ||||||
|   find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK) |  | ||||||
| 
 |  | ||||||
|   mark_as_advanced(EIGEN3_INCLUDE_DIR) |  | ||||||
| 
 |  | ||||||
| endif(EIGEN3_INCLUDE_DIR) |  | ||||||
| 
 |  | ||||||
|  | @ -1,10 +1,6 @@ | ||||||
| ############################################################################### | ############################################################################### | ||||||
| # Option for using system Eigen or GTSAM-bundled Eigen | # Option for using system Eigen or GTSAM-bundled Eigen | ||||||
| # Default: Use system's Eigen if found automatically: | option(GTSAM_USE_SYSTEM_EIGEN "Find and use system-installed Eigen. If 'off', use the one bundled with GTSAM" OFF) | ||||||
| find_package(Eigen3 QUIET) |  | ||||||
| set(USE_SYSTEM_EIGEN_INITIAL_VALUE ${Eigen3_FOUND}) |  | ||||||
| option(GTSAM_USE_SYSTEM_EIGEN "Find and use system-installed Eigen. If 'off', use the one bundled with GTSAM" ${USE_SYSTEM_EIGEN_INITIAL_VALUE}) |  | ||||||
| unset(USE_SYSTEM_EIGEN_INITIAL_VALUE) |  | ||||||
| 
 | 
 | ||||||
| if(NOT GTSAM_USE_SYSTEM_EIGEN) | if(NOT GTSAM_USE_SYSTEM_EIGEN) | ||||||
|   # This option only makes sense if using the embedded copy of Eigen, it is |   # This option only makes sense if using the embedded copy of Eigen, it is | ||||||
|  | @ -14,10 +10,14 @@ endif() | ||||||
| 
 | 
 | ||||||
| # Switch for using system Eigen or GTSAM-bundled Eigen | # Switch for using system Eigen or GTSAM-bundled Eigen | ||||||
| if(GTSAM_USE_SYSTEM_EIGEN) | if(GTSAM_USE_SYSTEM_EIGEN) | ||||||
|     find_package(Eigen3 REQUIRED) # need to find again as REQUIRED |     # Since Eigen 3.3.0 a Eigen3Config.cmake is available so use it. | ||||||
|  |     find_package(Eigen3 CONFIG REQUIRED) # need to find again as REQUIRED | ||||||
| 
 | 
 | ||||||
|     # Use generic Eigen include paths e.g. <Eigen/Core> |     # The actual include directory (for BUILD cmake target interface): | ||||||
|     set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "${EIGEN3_INCLUDE_DIR}") |     # Note: EIGEN3_INCLUDE_DIR points to some random location on some eigen | ||||||
|  |     # versions.  So here I use the target itself to get the proper include | ||||||
|  |     # directory (it is generated by cmake, thus has the correct path) | ||||||
|  |     get_target_property(GTSAM_EIGEN_INCLUDE_FOR_BUILD Eigen3::Eigen INTERFACE_INCLUDE_DIRECTORIES) | ||||||
| 
 | 
 | ||||||
|     # check if MKL is also enabled - can have one or the other, but not both! |     # check if MKL is also enabled - can have one or the other, but not both! | ||||||
|     # Note: Eigen >= v3.2.5 includes our patches |     # Note: Eigen >= v3.2.5 includes our patches | ||||||
|  | @ -30,9 +30,6 @@ if(GTSAM_USE_SYSTEM_EIGEN) | ||||||
|     if(EIGEN_USE_MKL_ALL AND (EIGEN3_VERSION VERSION_EQUAL 3.3.4)) |     if(EIGEN_USE_MKL_ALL AND (EIGEN3_VERSION VERSION_EQUAL 3.3.4)) | ||||||
|         message(FATAL_ERROR "MKL does not work with Eigen 3.3.4 because of a bug in Eigen. See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1527. Disable GTSAM_USE_SYSTEM_EIGEN to use GTSAM's copy of Eigen, disable GTSAM_WITH_EIGEN_MKL, or upgrade/patch your installation of Eigen.") |         message(FATAL_ERROR "MKL does not work with Eigen 3.3.4 because of a bug in Eigen. See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1527. Disable GTSAM_USE_SYSTEM_EIGEN to use GTSAM's copy of Eigen, disable GTSAM_WITH_EIGEN_MKL, or upgrade/patch your installation of Eigen.") | ||||||
|     endif() |     endif() | ||||||
| 
 |  | ||||||
|     # The actual include directory (for BUILD cmake target interface): |  | ||||||
|     set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${EIGEN3_INCLUDE_DIR}") |  | ||||||
| else() | else() | ||||||
|     # Use bundled Eigen include path. |     # Use bundled Eigen include path. | ||||||
|     # Clear any variables set by FindEigen3 |     # Clear any variables set by FindEigen3 | ||||||
|  | @ -45,7 +42,20 @@ else() | ||||||
|     set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "include/gtsam/3rdparty/Eigen/") |     set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "include/gtsam/3rdparty/Eigen/") | ||||||
| 
 | 
 | ||||||
|     # The actual include directory (for BUILD cmake target interface): |     # The actual include directory (for BUILD cmake target interface): | ||||||
|     set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${GTSAM_SOURCE_DIR}/gtsam/3rdparty/Eigen/") |     set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${GTSAM_SOURCE_DIR}/gtsam/3rdparty/Eigen") | ||||||
|  | 
 | ||||||
|  |     add_library(gtsam_eigen3 INTERFACE) | ||||||
|  | 
 | ||||||
|  |     target_include_directories(gtsam_eigen3 INTERFACE | ||||||
|  |       $<BUILD_INTERFACE:${GTSAM_EIGEN_INCLUDE_FOR_BUILD}> | ||||||
|  |       $<INSTALL_INTERFACE:${GTSAM_EIGEN_INCLUDE_FOR_INSTALL}> | ||||||
|  |     ) | ||||||
|  |     add_library(Eigen3::Eigen ALIAS gtsam_eigen3) | ||||||
|  | 
 | ||||||
|  |     install(TARGETS gtsam_eigen3 EXPORT GTSAM-exports PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) | ||||||
|  | 
 | ||||||
|  |     list(APPEND GTSAM_EXPORTED_TARGETS gtsam_eigen3) | ||||||
|  |     set(GTSAM_EXPORTED_TARGETS "${GTSAM_EXPORTED_TARGETS}") | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| # Detect Eigen version: | # Detect Eigen version: | ||||||
|  |  | ||||||
|  | @ -26,6 +26,7 @@ if (GTSAM_BUILD_DOCS) | ||||||
|         gtsam/basis  |         gtsam/basis  | ||||||
|         gtsam/discrete |         gtsam/discrete | ||||||
|         gtsam/geometry |         gtsam/geometry | ||||||
|  |         gtsam/hybrid | ||||||
|         gtsam/inference |         gtsam/inference | ||||||
|         gtsam/linear |         gtsam/linear | ||||||
|         gtsam/navigation |         gtsam/navigation | ||||||
|  | @ -33,7 +34,6 @@ if (GTSAM_BUILD_DOCS) | ||||||
|         gtsam/sam |         gtsam/sam | ||||||
|         gtsam/sfm |         gtsam/sfm | ||||||
|         gtsam/slam |         gtsam/slam | ||||||
|         gtsam/smart |  | ||||||
|         gtsam/symbolic |         gtsam/symbolic | ||||||
|         gtsam |         gtsam | ||||||
|     ) |     ) | ||||||
|  | @ -42,10 +42,12 @@ if (GTSAM_BUILD_DOCS) | ||||||
|     set(gtsam_unstable_doc_subdirs |     set(gtsam_unstable_doc_subdirs | ||||||
|         gtsam_unstable/base |         gtsam_unstable/base | ||||||
|         gtsam_unstable/discrete |         gtsam_unstable/discrete | ||||||
|  |         gtsam_unstable/dynamics | ||||||
|  |         gtsam_unstable/geometry | ||||||
|         gtsam_unstable/linear |         gtsam_unstable/linear | ||||||
|         gtsam_unstable/nonlinear  |         gtsam_unstable/nonlinear | ||||||
|         gtsam_unstable/slam  |         gtsam_unstable/partition | ||||||
|         gtsam_unstable/dynamics  |         gtsam_unstable/slam | ||||||
|         gtsam_unstable |         gtsam_unstable | ||||||
|     ) |     ) | ||||||
|      |      | ||||||
|  |  | ||||||
							
								
								
									
										2973
									
								
								doc/Doxyfile.in
								
								
								
								
							
							
						
						
									
										2973
									
								
								doc/Doxyfile.in
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -18,7 +18,6 @@ | ||||||
|       <tab type="files" visible="yes" title="" intro=""/> |       <tab type="files" visible="yes" title="" intro=""/> | ||||||
|       <tab type="globals" visible="yes" title="" intro=""/> |       <tab type="globals" visible="yes" title="" intro=""/> | ||||||
|     </tab> |     </tab> | ||||||
|     <tab type="dirs" visible="yes" title="" intro=""/> |  | ||||||
|     <tab type="examples" visible="yes" title="" intro=""/>   |     <tab type="examples" visible="yes" title="" intro=""/>   | ||||||
|   </navindex> |   </navindex> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -117,12 +117,10 @@ set_target_properties(gtsam PROPERTIES | ||||||
|     VERSION             ${gtsam_version} |     VERSION             ${gtsam_version} | ||||||
|     SOVERSION           ${gtsam_soversion}) |     SOVERSION           ${gtsam_soversion}) | ||||||
| 
 | 
 | ||||||
| # Append Eigen include path, set in top-level CMakeLists.txt to either | # Append Eigen include path to either | ||||||
| # system-eigen, or GTSAM eigen path | # system-eigen, or GTSAM eigen path | ||||||
| target_include_directories(gtsam PUBLIC | target_link_libraries(gtsam PUBLIC Eigen3::Eigen) | ||||||
|   $<BUILD_INTERFACE:${GTSAM_EIGEN_INCLUDE_FOR_BUILD}> | 
 | ||||||
|   $<INSTALL_INTERFACE:${GTSAM_EIGEN_INCLUDE_FOR_INSTALL}> |  | ||||||
| ) |  | ||||||
| # MKL include dir: | # MKL include dir: | ||||||
| if (GTSAM_USE_EIGEN_MKL) | if (GTSAM_USE_EIGEN_MKL) | ||||||
|   target_include_directories(gtsam PUBLIC ${MKL_INCLUDE_DIR}) |   target_include_directories(gtsam PUBLIC ${MKL_INCLUDE_DIR}) | ||||||
|  |  | ||||||
|  | @ -62,7 +62,7 @@ namespace gtsam { | ||||||
|  * convenience to avoid having lengthy types in the code.  Through timing, |  * convenience to avoid having lengthy types in the code.  Through timing, | ||||||
|  * we've seen that the fast_pool_allocator can lead to speedups of several |  * we've seen that the fast_pool_allocator can lead to speedups of several | ||||||
|  * percent. |  * percent. | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| template<typename KEY, typename VALUE> | template<typename KEY, typename VALUE> | ||||||
| class ConcurrentMap : public ConcurrentMapBase<KEY,VALUE> { | class ConcurrentMap : public ConcurrentMapBase<KEY,VALUE> { | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ namespace gtsam { | ||||||
| /**
 | /**
 | ||||||
|  * Disjoint set forest using an STL map data structure underneath |  * Disjoint set forest using an STL map data structure underneath | ||||||
|  * Uses rank compression and union by rank, iterator version |  * Uses rank compression and union by rank, iterator version | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| template <class KEY> | template <class KEY> | ||||||
| class DSFMap { | class DSFMap { | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ namespace gtsam { | ||||||
|  * A fast implementation of disjoint set forests that uses vector as underly data structure. |  * A fast implementation of disjoint set forests that uses vector as underly data structure. | ||||||
|  * This is the absolute minimal DSF data structure, and only allows size_t keys |  * This is the absolute minimal DSF data structure, and only allows size_t keys | ||||||
|  * Uses rank compression but not union by rank :-( |  * Uses rank compression but not union by rank :-( | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DSFBase { | class GTSAM_EXPORT DSFBase { | ||||||
| 
 | 
 | ||||||
|  | @ -59,7 +59,7 @@ public: | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * DSFVector additionally keeps a vector of keys to support more expensive operations |  * DSFVector additionally keeps a vector of keys to support more expensive operations | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DSFVector: public DSFBase { | class GTSAM_EXPORT DSFVector: public DSFBase { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ namespace gtsam { | ||||||
|  * convenience to avoid having lengthy types in the code.  Through timing, |  * convenience to avoid having lengthy types in the code.  Through timing, | ||||||
|  * we've seen that the fast_pool_allocator can lead to speedups of several |  * we've seen that the fast_pool_allocator can lead to speedups of several | ||||||
|  * percent. |  * percent. | ||||||
|    * @addtogroup base |    * @ingroup base | ||||||
|  */ |  */ | ||||||
| template<typename VALUE> | template<typename VALUE> | ||||||
| class FastList: public std::list<VALUE, typename internal::FastDefaultAllocator<VALUE>::type> { | class FastList: public std::list<VALUE, typename internal::FastDefaultAllocator<VALUE>::type> { | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ namespace gtsam { | ||||||
|  * convenience to avoid having lengthy types in the code.  Through timing, |  * convenience to avoid having lengthy types in the code.  Through timing, | ||||||
|  * we've seen that the fast_pool_allocator can lead to speedups of several |  * we've seen that the fast_pool_allocator can lead to speedups of several | ||||||
|  * percent. |  * percent. | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| template<typename KEY, typename VALUE> | template<typename KEY, typename VALUE> | ||||||
| class FastMap : public std::map<KEY, VALUE, std::less<KEY>, | class FastMap : public std::map<KEY, VALUE, std::less<KEY>, | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ namespace gtsam { | ||||||
|  * fast_pool_allocator instead of the default STL allocator.  This is just a |  * fast_pool_allocator instead of the default STL allocator.  This is just a | ||||||
|  * convenience to avoid having lengthy types in the code.  Through timing, |  * convenience to avoid having lengthy types in the code.  Through timing, | ||||||
|  * we've seen that the fast_pool_allocator can lead to speedups of several %. |  * we've seen that the fast_pool_allocator can lead to speedups of several %. | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| template<typename VALUE> | template<typename VALUE> | ||||||
| class FastSet: public std::set<VALUE, std::less<VALUE>, | class FastSet: public std::set<VALUE, std::less<VALUE>, | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ namespace gtsam { | ||||||
| /**
 | /**
 | ||||||
|  * FastVector is a type alias to a std::vector with a custom memory allocator. |  * FastVector is a type alias to a std::vector with a custom memory allocator. | ||||||
|  * The particular allocator depends on GTSAM's cmake configuration. |  * The particular allocator depends on GTSAM's cmake configuration. | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| template <typename T> | template <typename T> | ||||||
| using FastVector = | using FastVector = | ||||||
|  |  | ||||||
|  | @ -47,7 +47,7 @@ namespace gtsam { | ||||||
|   * matrix view.  firstBlock() determines the block that appears to have index 0 for all operations |   * matrix view.  firstBlock() determines the block that appears to have index 0 for all operations | ||||||
|   * (except re-setting firstBlock()). |   * (except re-setting firstBlock()). | ||||||
|   * |   * | ||||||
|   * @addtogroup base */ |   * @ingroup base */ | ||||||
|   class GTSAM_EXPORT SymmetricBlockMatrix |   class GTSAM_EXPORT SymmetricBlockMatrix | ||||||
|   { |   { | ||||||
|   public: |   public: | ||||||
|  |  | ||||||
|  | @ -51,7 +51,7 @@ namespace gtsam { | ||||||
|    * tests and in generic algorithms. |    * tests and in generic algorithms. | ||||||
|    * |    * | ||||||
|    * See macros for details on using this structure |    * See macros for details on using this structure | ||||||
|    * @addtogroup base |    * @ingroup base | ||||||
|    * @tparam T is the objectype this constrains to be testable - assumes print() and equals() |    * @tparam T is the objectype this constrains to be testable - assumes print() and equals() | ||||||
|    */ |    */ | ||||||
|   template <class T> |   template <class T> | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ | ||||||
|  * @brief    Base exception type that uses tbb_allocator if GTSAM is compiled with TBB |  * @brief    Base exception type that uses tbb_allocator if GTSAM is compiled with TBB | ||||||
|  * @author   Richard Roberts |  * @author   Richard Roberts | ||||||
|  * @date     Aug 21, 2010 |  * @date     Aug 21, 2010 | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ namespace gtsam { | ||||||
|    * row for all operations.  To include all rows, rowEnd() should be set to the number of rows in |    * row for all operations.  To include all rows, rowEnd() should be set to the number of rows in | ||||||
|    * the matrix (i.e. one after the last true row index). |    * the matrix (i.e. one after the last true row index). | ||||||
|    * |    * | ||||||
|    * @addtogroup base */ |    * @ingroup base */ | ||||||
|   class GTSAM_EXPORT VerticalBlockMatrix |   class GTSAM_EXPORT VerticalBlockMatrix | ||||||
|   { |   { | ||||||
|   public: |   public: | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ | ||||||
| #include <type_traits> | #include <type_traits> | ||||||
| 
 | 
 | ||||||
| namespace gtsam { | namespace gtsam { | ||||||
|   /// An shorthand alias for accessing the ::type inside std::enable_if that can be used in a template directly
 |   /// An shorthand alias for accessing the \::type inside std::enable_if that can be used in a template directly
 | ||||||
|   template<bool B, class T = void> |   template<bool B, class T = void> | ||||||
|   using enable_if_t = typename std::enable_if<B, T>::type; |   using enable_if_t = typename std::enable_if<B, T>::type; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -147,7 +147,7 @@ namespace gtsam { | ||||||
|       size_t id_; |       size_t id_; | ||||||
|       size_t t_; |       size_t t_; | ||||||
|       size_t tWall_; |       size_t tWall_; | ||||||
|       double t2_ ; ///< cache the \sum t_i^2
 |       double t2_ ; ///< cache the \f$ \sum t_i^2 \f$
 | ||||||
|       size_t tIt_; |       size_t tIt_; | ||||||
|       size_t tMax_; |       size_t tMax_; | ||||||
|       size_t tMin_; |       size_t tMin_; | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ | ||||||
|  * @brief    Functions for handling type information |  * @brief    Functions for handling type information | ||||||
|  * @author   Varun Agrawal |  * @author   Varun Agrawal | ||||||
|  * @date     May 18, 2020 |  * @date     May 18, 2020 | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <gtsam/base/types.h> | #include <gtsam/base/types.h> | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ | ||||||
|  * @brief    Typedefs for easier changing of types |  * @brief    Typedefs for easier changing of types | ||||||
|  * @author   Richard Roberts |  * @author   Richard Roberts | ||||||
|  * @date     Aug 21, 2010 |  * @date     Aug 21, 2010 | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | @ -78,6 +78,8 @@ using Weights = Eigen::Matrix<double, 1, -1>; /* 1xN vector */ | ||||||
|  * @tparam M Size of the identity matrix. |  * @tparam M Size of the identity matrix. | ||||||
|  * @param w The weights of the polynomial. |  * @param w The weights of the polynomial. | ||||||
|  * @return Mx(M*N) kronecker product [w(0)*I, w(1)*I, ..., w(N-1)*I] |  * @return Mx(M*N) kronecker product [w(0)*I, w(1)*I, ..., w(N-1)*I] | ||||||
|  |  * | ||||||
|  |  * @ingroup basis | ||||||
|  */ |  */ | ||||||
| template <size_t M> | template <size_t M> | ||||||
| Matrix kroneckerProductIdentity(const Weights& w) { | Matrix kroneckerProductIdentity(const Weights& w) { | ||||||
|  | @ -90,7 +92,10 @@ Matrix kroneckerProductIdentity(const Weights& w) { | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// CRTP Base class for function bases
 | /**
 | ||||||
|  |  * CRTP Base class for function bases | ||||||
|  |  *  @ingroup basis | ||||||
|  |  */ | ||||||
| template <typename DERIVED> | template <typename DERIVED> | ||||||
| class Basis { | class Basis { | ||||||
|  public: |  public: | ||||||
|  |  | ||||||
|  | @ -32,6 +32,8 @@ namespace gtsam { | ||||||
|  * |  * | ||||||
|  * Example, degree 8 Chebyshev polynomial measured at x=0.5: |  * Example, degree 8 Chebyshev polynomial measured at x=0.5: | ||||||
|  *  EvaluationFactor<Chebyshev2> factor(key, measured, model, 8, 0.5); |  *  EvaluationFactor<Chebyshev2> factor(key, measured, model, 8, 0.5); | ||||||
|  |  * | ||||||
|  |  * @ingroup basis | ||||||
|  */ |  */ | ||||||
| template <class BASIS> | template <class BASIS> | ||||||
| class EvaluationFactor : public FunctorizedFactor<double, Vector> { | class EvaluationFactor : public FunctorizedFactor<double, Vector> { | ||||||
|  | @ -86,6 +88,8 @@ class EvaluationFactor : public FunctorizedFactor<double, Vector> { | ||||||
|  * |  * | ||||||
|  * @param BASIS: The basis class to use e.g. Chebyshev2 |  * @param BASIS: The basis class to use e.g. Chebyshev2 | ||||||
|  * @param M: Size of the evaluated state vector. |  * @param M: Size of the evaluated state vector. | ||||||
|  |  * | ||||||
|  |  * @ingroup basis | ||||||
|  */ |  */ | ||||||
| template <class BASIS, int M> | template <class BASIS, int M> | ||||||
| class VectorEvaluationFactor | class VectorEvaluationFactor | ||||||
|  | @ -149,6 +153,8 @@ class VectorEvaluationFactor | ||||||
|  *  VectorComponentFactor<BASIS, P> controlPrior(key, measured, model, |  *  VectorComponentFactor<BASIS, P> controlPrior(key, measured, model, | ||||||
|  *                                               N, i, t, a, b); |  *                                               N, i, t, a, b); | ||||||
|  *  where N is the degree and i is the component index. |  *  where N is the degree and i is the component index. | ||||||
|  |  * | ||||||
|  |  * @ingroup basis | ||||||
|  */ |  */ | ||||||
| template <class BASIS, size_t P> | template <class BASIS, size_t P> | ||||||
| class VectorComponentFactor | class VectorComponentFactor | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ | ||||||
|  * -------------------------------------------------------------------------- */ |  * -------------------------------------------------------------------------- */ | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @file ParamaterMatrix.h |  * @file ParameterMatrix.h | ||||||
|  * @brief Define ParameterMatrix class which is used to store values at |  * @brief Define ParameterMatrix class which is used to store values at | ||||||
|  * interpolation points. |  * interpolation points. | ||||||
|  * @author Varun Agrawal, Frank Dellaert |  * @author Varun Agrawal, Frank Dellaert | ||||||
|  |  | ||||||
|  | @ -31,6 +31,8 @@ namespace gtsam { | ||||||
|    * Algebraic Decision Trees fix the range to double |    * Algebraic Decision Trees fix the range to double | ||||||
|    * Just has some nice constructors and some syntactic sugar |    * Just has some nice constructors and some syntactic sugar | ||||||
|    * TODO: consider eliminating this class altogether? |    * TODO: consider eliminating this class altogether? | ||||||
|  |    * | ||||||
|  |    * @ingroup discrete | ||||||
|    */ |    */ | ||||||
|   template <typename L> |   template <typename L> | ||||||
|   class GTSAM_EXPORT AlgebraicDecisionTree : public DecisionTree<L, double> { |   class GTSAM_EXPORT AlgebraicDecisionTree : public DecisionTree<L, double> { | ||||||
|  | @ -156,9 +158,9 @@ namespace gtsam { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// print method customized to value type `double`.
 |     /// print method customized to value type `double`.
 | ||||||
|     void print(const std::string& s, |     void print(const std::string& s = "", | ||||||
|               const typename Base::LabelFormatter& labelFormatter = |                const typename Base::LabelFormatter& labelFormatter = | ||||||
|                   &DefaultFormatter) const { |                    &DefaultFormatter) const { | ||||||
|       auto valueFormatter = [](const double& v) { |       auto valueFormatter = [](const double& v) { | ||||||
|         return (boost::format("%4.8g") % v).str(); |         return (boost::format("%4.8g") % v).str(); | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ namespace gtsam { | ||||||
|  * An assignment from labels to value index (size_t). |  * An assignment from labels to value index (size_t). | ||||||
|  * Assigns to each label a value. Implemented as a simple map. |  * Assigns to each label a value. Implemented as a simple map. | ||||||
|  * A discrete factor takes an Assignment and returns a value. |  * A discrete factor takes an Assignment and returns a value. | ||||||
|  |  * @ingroup discrete | ||||||
|  */ |  */ | ||||||
| template <class L> | template <class L> | ||||||
| class Assignment : public std::map<L, size_t> { | class Assignment : public std::map<L, size_t> { | ||||||
|  |  | ||||||
|  | @ -38,6 +38,8 @@ namespace gtsam { | ||||||
|    * Decision Tree |    * Decision Tree | ||||||
|    * L = label for variables |    * L = label for variables | ||||||
|    * Y = function range (any algebra), e.g., bool, int, double |    * Y = function range (any algebra), e.g., bool, int, double | ||||||
|  |    * | ||||||
|  |    * @ingroup discrete | ||||||
|    */ |    */ | ||||||
|   template<typename L, typename Y> |   template<typename L, typename Y> | ||||||
|   class DecisionTree { |   class DecisionTree { | ||||||
|  |  | ||||||
|  | @ -36,7 +36,9 @@ namespace gtsam { | ||||||
|   class DiscreteConditional; |   class DiscreteConditional; | ||||||
| 
 | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * A discrete probabilistic factor |    * A discrete probabilistic factor. | ||||||
|  |    * | ||||||
|  |    * @ingroup discrete | ||||||
|    */ |    */ | ||||||
|   class GTSAM_EXPORT DecisionTreeFactor : public DiscreteFactor, |   class GTSAM_EXPORT DecisionTreeFactor : public DiscreteFactor, | ||||||
|                                           public AlgebraicDecisionTree<Key> { |                                           public AlgebraicDecisionTree<Key> { | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /** 
 | /** 
 | ||||||
|  * A Bayes net made from discrete conditional distributions.  |  * A Bayes net made from discrete conditional distributions.  | ||||||
|  * @addtogroup discrete |  * @ingroup discrete | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DiscreteBayesNet: public BayesNet<DiscreteConditional> { | class GTSAM_EXPORT DiscreteBayesNet: public BayesNet<DiscreteConditional> { | ||||||
|  public: |  public: | ||||||
|  |  | ||||||
|  | @ -62,7 +62,10 @@ class GTSAM_EXPORT DiscreteBayesTreeClique | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| /** A Bayes tree representing a Discrete density */ | /**
 | ||||||
|  |  * @brief A Bayes tree representing a Discrete density. | ||||||
|  |  * @ingroup discrete | ||||||
|  |  */ | ||||||
| class GTSAM_EXPORT DiscreteBayesTree | class GTSAM_EXPORT DiscreteBayesTree | ||||||
|     : public BayesTree<DiscreteBayesTreeClique> { |     : public BayesTree<DiscreteBayesTreeClique> { | ||||||
|  private: |  private: | ||||||
|  |  | ||||||
|  | @ -32,6 +32,8 @@ namespace gtsam { | ||||||
| /**
 | /**
 | ||||||
|  * Discrete Conditional Density |  * Discrete Conditional Density | ||||||
|  * Derives from DecisionTreeFactor |  * Derives from DecisionTreeFactor | ||||||
|  |  * | ||||||
|  |  * @ingroup discrete | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DiscreteConditional | class GTSAM_EXPORT DiscreteConditional | ||||||
|     : public DecisionTreeFactor, |     : public DecisionTreeFactor, | ||||||
|  |  | ||||||
|  | @ -27,6 +27,8 @@ namespace gtsam { | ||||||
| /**
 | /**
 | ||||||
|  * A prior probability on a set of discrete variables. |  * A prior probability on a set of discrete variables. | ||||||
|  * Derives from DiscreteConditional |  * Derives from DiscreteConditional | ||||||
|  |  * | ||||||
|  |  * @ingroup discrete | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DiscreteDistribution : public DiscreteConditional { | class GTSAM_EXPORT DiscreteDistribution : public DiscreteConditional { | ||||||
|  public: |  public: | ||||||
|  |  | ||||||
|  | @ -24,6 +24,10 @@ | ||||||
| 
 | 
 | ||||||
| namespace gtsam { | namespace gtsam { | ||||||
| 
 | 
 | ||||||
|  |   /**
 | ||||||
|  |    * @brief Elimination tree for discrete factors. | ||||||
|  |    * @ingroup discrete | ||||||
|  |    */ | ||||||
|   class GTSAM_EXPORT DiscreteEliminationTree : |   class GTSAM_EXPORT DiscreteEliminationTree : | ||||||
|     public EliminationTree<DiscreteBayesNet, DiscreteFactorGraph> |     public EliminationTree<DiscreteBayesNet, DiscreteFactorGraph> | ||||||
|   { |   { | ||||||
|  |  | ||||||
|  | @ -31,6 +31,8 @@ class DiscreteConditional; | ||||||
| /**
 | /**
 | ||||||
|  * Base class for discrete probabilistic factors |  * Base class for discrete probabilistic factors | ||||||
|  * The most general one is the derived DecisionTreeFactor |  * The most general one is the derived DecisionTreeFactor | ||||||
|  |  * | ||||||
|  |  * @ingroup discrete | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DiscreteFactor: public Factor { | class GTSAM_EXPORT DiscreteFactor: public Factor { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -40,7 +40,14 @@ class DiscreteEliminationTree; | ||||||
| class DiscreteBayesTree; | class DiscreteBayesTree; | ||||||
| class DiscreteJunctionTree; | class DiscreteJunctionTree; | ||||||
| 
 | 
 | ||||||
| /** Main elimination function for DiscreteFactorGraph */ | /**
 | ||||||
|  |  * @brief Main elimination function for DiscreteFactorGraph. | ||||||
|  |  *  | ||||||
|  |  * @param factors  | ||||||
|  |  * @param keys  | ||||||
|  |  * @return GTSAM_EXPORT | ||||||
|  |  * @ingroup discrete | ||||||
|  |  */ | ||||||
| GTSAM_EXPORT std::pair<boost::shared_ptr<DiscreteConditional>, DecisionTreeFactor::shared_ptr> | GTSAM_EXPORT std::pair<boost::shared_ptr<DiscreteConditional>, DecisionTreeFactor::shared_ptr> | ||||||
| EliminateDiscrete(const DiscreteFactorGraph& factors, const Ordering& keys); | EliminateDiscrete(const DiscreteFactorGraph& factors, const Ordering& keys); | ||||||
| 
 | 
 | ||||||
|  | @ -64,6 +71,7 @@ template<> struct EliminationTraits<DiscreteFactorGraph> | ||||||
| /**
 | /**
 | ||||||
|  * A Discrete Factor Graph is a factor graph where all factors are Discrete, i.e. |  * A Discrete Factor Graph is a factor graph where all factors are Discrete, i.e. | ||||||
|  *   Factor == DiscreteFactor |  *   Factor == DiscreteFactor | ||||||
|  |  * @ingroup discrete | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DiscreteFactorGraph | class GTSAM_EXPORT DiscreteFactorGraph | ||||||
|     : public FactorGraph<DiscreteFactor>, |     : public FactorGraph<DiscreteFactor>, | ||||||
|  |  | ||||||
|  | @ -44,7 +44,8 @@ namespace gtsam { | ||||||
|    * The tree structure and elimination method are exactly analogous to the EliminationTree, |    * The tree structure and elimination method are exactly analogous to the EliminationTree, | ||||||
|    * except that in the JunctionTree, at each node multiple variables are eliminated at a time. |    * except that in the JunctionTree, at each node multiple variables are eliminated at a time. | ||||||
|    * |    * | ||||||
|    * \addtogroup Multifrontal |    * \ingroup Multifrontal | ||||||
|  |    * @ingroup discrete | ||||||
|    * \nosubgrouping |    * \nosubgrouping | ||||||
|    */ |    */ | ||||||
|   class GTSAM_EXPORT DiscreteJunctionTree : |   class GTSAM_EXPORT DiscreteJunctionTree : | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ namespace gtsam { | ||||||
|   /**
 |   /**
 | ||||||
|    * Key type for discrete variables. |    * Key type for discrete variables. | ||||||
|    * Includes Key and cardinality. |    * Includes Key and cardinality. | ||||||
|  |    * @ingroup discrete | ||||||
|    */ |    */ | ||||||
|   using DiscreteKey = std::pair<Key,size_t>; |   using DiscreteKey = std::pair<Key,size_t>; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ class DiscreteBayesNet; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief DiscreteLookupTable table for max-product |  * @brief DiscreteLookupTable table for max-product | ||||||
|  |  * @ingroup discrete | ||||||
|  * |  * | ||||||
|  * Inherits from discrete conditional for convenience, but is not normalized. |  * Inherits from discrete conditional for convenience, but is not normalized. | ||||||
|  * Is used in the max-product algorithm. |  * Is used in the max-product algorithm. | ||||||
|  |  | ||||||
|  | @ -28,6 +28,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * A class for computing marginals of variables in a DiscreteFactorGraph |    * A class for computing marginals of variables in a DiscreteFactorGraph | ||||||
|  |    * @ingroup discrete | ||||||
|    */ |    */ | ||||||
| class DiscreteMarginals { | class DiscreteMarginals { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ namespace gtsam { | ||||||
|  * Another good thing is we don't need to have the special DiscreteKey which |  * Another good thing is we don't need to have the special DiscreteKey which | ||||||
|  * stores cardinality of a Discrete variable. It should be handled naturally in |  * stores cardinality of a Discrete variable. It should be handled naturally in | ||||||
|  * the new class DiscreteValue, as the variable's type (domain) |  * the new class DiscreteValue, as the variable's type (domain) | ||||||
|  |  * @ingroup discrete | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DiscreteValues : public Assignment<Key> { | class GTSAM_EXPORT DiscreteValues : public Assignment<Key> { | ||||||
|  public: |  public: | ||||||
|  |  | ||||||
|  | @ -48,6 +48,8 @@ namespace gtsam { | ||||||
|    *   (E|T,L) = "F F F 1" |    *   (E|T,L) = "F F F 1" | ||||||
|    *   X|E = "95/5 2/98" |    *   X|E = "95/5 2/98" | ||||||
|    *   (D|E,B) = "9/1 2/8 3/7 1/9" |    *   (D|E,B) = "9/1 2/8 3/7 1/9" | ||||||
|  |    * | ||||||
|  |    * @ingroup discrete | ||||||
|    */ |    */ | ||||||
|   class GTSAM_EXPORT Signature { |   class GTSAM_EXPORT Signature { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
|  | @ -63,7 +63,7 @@ void calibrateJacobians(const Cal& calibration, const Point2& pn, | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Common base class for all calibration models. |  * @brief Common base class for all calibration models. | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT Cal3 { | class GTSAM_EXPORT Cal3 { | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Calibration used by Bundler |  * @brief Calibration used by Bundler | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT Cal3Bundler : public Cal3 { | class GTSAM_EXPORT Cal3Bundler : public Cal3 { | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ namespace gtsam { | ||||||
|  * @brief Calibration of a camera with radial distortion that also supports |  * @brief Calibration of a camera with radial distortion that also supports | ||||||
|  * Lie-group behaviors for optimization. |  * Lie-group behaviors for optimization. | ||||||
|  * \sa Cal3DS2_Base |  * \sa Cal3DS2_Base | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT Cal3DS2 : public Cal3DS2_Base { | class GTSAM_EXPORT Cal3DS2 : public Cal3DS2_Base { | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Calibration of a camera with radial distortion |  * @brief Calibration of a camera with radial distortion | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  * |  * | ||||||
|  * Uses same distortionmodel as OpenCV, with |  * Uses same distortionmodel as OpenCV, with | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Calibration of a fisheye camera |  * @brief Calibration of a fisheye camera | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  * |  * | ||||||
|  * Uses same distortionmodel as OpenCV, with |  * Uses same distortionmodel as OpenCV, with | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
|  | @ -30,7 +30,7 @@ namespace gtsam { | ||||||
| /**
 | /**
 | ||||||
|  * @brief Calibration of a omni-directional camera with mirror + lens radial |  * @brief Calibration of a omni-directional camera with mirror + lens radial | ||||||
|  * distortion |  * distortion | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  * |  * | ||||||
|  * Similar to Cal3DS2, does distortion but has additional mirror parameter xi |  * Similar to Cal3DS2, does distortion but has additional mirror parameter xi | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
|  | @ -28,7 +28,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief The most common 5DOF 3D->2D calibration |  * @brief The most common 5DOF 3D->2D calibration | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT Cal3_S2 : public Cal3 { | class GTSAM_EXPORT Cal3_S2 : public Cal3 { | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief The most common 5DOF 3D->2D calibration, stereo version |  * @brief The most common 5DOF 3D->2D calibration, stereo version | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT Cal3_S2Stereo : public Cal3_S2 { | class GTSAM_EXPORT Cal3_S2Stereo : public Cal3_S2 { | ||||||
|  | @ -38,7 +38,7 @@ class GTSAM_EXPORT Cal3_S2Stereo : public Cal3_S2 { | ||||||
|   using shared_ptr = boost::shared_ptr<Cal3_S2Stereo>; |   using shared_ptr = boost::shared_ptr<Cal3_S2Stereo>; | ||||||
| 
 | 
 | ||||||
|   /// @name Standard Constructors
 |   /// @name Standard Constructors
 | ||||||
|   /// @
 |   /// @{
 | ||||||
| 
 | 
 | ||||||
|   /// default calibration leaves coordinates unchanged
 |   /// default calibration leaves coordinates unchanged
 | ||||||
|   Cal3_S2Stereo() = default; |   Cal3_S2Stereo() = default; | ||||||
|  | @ -55,6 +55,8 @@ class GTSAM_EXPORT Cal3_S2Stereo : public Cal3_S2 { | ||||||
|   Cal3_S2Stereo(double fov, int w, int h, double b) |   Cal3_S2Stereo(double fov, int w, int h, double b) | ||||||
|       : Cal3_S2(fov, w, h), b_(b) {} |       : Cal3_S2(fov, w, h), b_(b) {} | ||||||
| 
 | 
 | ||||||
|  |   /// @}
 | ||||||
|  | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * Convert intrinsic coordinates xy to image coordinates uv, fixed derivaitves |    * Convert intrinsic coordinates xy to image coordinates uv, fixed derivaitves | ||||||
|    * @param p point in intrinsic coordinates |    * @param p point in intrinsic coordinates | ||||||
|  | @ -82,7 +84,6 @@ class GTSAM_EXPORT Cal3_S2Stereo : public Cal3_S2 { | ||||||
|    */ |    */ | ||||||
|   Vector3 calibrate(const Vector3& p) const { return Cal3_S2::calibrate(p); } |   Vector3 calibrate(const Vector3& p) const { return Cal3_S2::calibrate(p); } | ||||||
| 
 | 
 | ||||||
|   /// @}
 |  | ||||||
|   /// @name Testable
 |   /// @name Testable
 | ||||||
|   /// @{
 |   /// @{
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ private: | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * A pinhole camera class that has a Pose3, functions as base class for all pinhole cameras |  * A pinhole camera class that has a Pose3, functions as base class for all pinhole cameras | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT PinholeBase { | class GTSAM_EXPORT PinholeBase { | ||||||
|  | @ -241,7 +241,7 @@ private: | ||||||
|  * A Calibrated camera class [R|-R't], calibration K=I. |  * A Calibrated camera class [R|-R't], calibration K=I. | ||||||
|  * If calibration is known, it is more computationally efficient |  * If calibration is known, it is more computationally efficient | ||||||
|  * to calibrate the measurements rather than try to predict in pixels. |  * to calibrate the measurements rather than try to predict in pixels. | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT CalibratedCamera: public PinholeBase { | class GTSAM_EXPORT CalibratedCamera: public PinholeBase { | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ GTSAM_EXPORT Line3 transformTo(const Pose3 &wTc, const Line3 &wL, | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * A 3D line (R,a,b) : (Rot3,Scalar,Scalar) |  * A 3D line (R,a,b) : (Rot3,Scalar,Scalar) | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT Line3 { | class GTSAM_EXPORT Line3 { | ||||||
|  |  | ||||||
|  | @ -133,8 +133,6 @@ public: | ||||||
|   inline double distance() const { |   inline double distance() const { | ||||||
|     return d_; |     return d_; | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   /// @}
 |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template<> struct traits<OrientedPlane3> : public internal::Manifold< | template<> struct traits<OrientedPlane3> : public internal::Manifold< | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ namespace gtsam { | ||||||
| /**
 | /**
 | ||||||
|  * A pinhole camera class that has a Pose3 and a Calibration. |  * A pinhole camera class that has a Pose3 and a Calibration. | ||||||
|  * Use PinholePose if you will not be optimizing for Calibration |  * Use PinholePose if you will not be optimizing for Calibration | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| template<typename Calibration> | template<typename Calibration> | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * A pinhole camera class that has a Pose3 and a *fixed* Calibration. |  * A pinhole camera class that has a Pose3 and a *fixed* Calibration. | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| template<typename CALIBRATION> | template<typename CALIBRATION> | ||||||
|  | @ -236,7 +236,7 @@ public: | ||||||
|  * A pinhole camera class that has a Pose3 and a *fixed* Calibration. |  * A pinhole camera class that has a Pose3 and a *fixed* Calibration. | ||||||
|  * Instead of using this class, one might consider calibrating the measurements |  * Instead of using this class, one might consider calibrating the measurements | ||||||
|  * and using CalibratedCamera, which would then be faster. |  * and using CalibratedCamera, which would then be faster. | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| template<typename CALIBRATION> | template<typename CALIBRATION> | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * A 2D pose (Point2,Rot2) |  * A 2D pose (Point2,Rot2) | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class Pose2: public LieGroup<Pose2, 3> { | class Pose2: public LieGroup<Pose2, 3> { | ||||||
|  |  | ||||||
|  | @ -27,7 +27,6 @@ | ||||||
| namespace gtsam { | namespace gtsam { | ||||||
| 
 | 
 | ||||||
| using std::vector; | using std::vector; | ||||||
| using Point3Pairs = vector<Point3Pair>; |  | ||||||
| 
 | 
 | ||||||
| /** instantiate concept checks */ | /** instantiate concept checks */ | ||||||
| GTSAM_CONCEPT_POSE_INST(Pose3) | GTSAM_CONCEPT_POSE_INST(Pose3) | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ class Pose2; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * A 3D pose (R,t) : (Rot3,Point3) |  * A 3D pose (R,t) : (Rot3,Point3) | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT Pose3: public LieGroup<Pose3, 6> { | class GTSAM_EXPORT Pose3: public LieGroup<Pose3, 6> { | ||||||
|  | @ -83,7 +83,7 @@ public: | ||||||
|    *  A pose aTb is estimated between pairs (a_point, b_point) such that a_point = aTb * b_point |    *  A pose aTb is estimated between pairs (a_point, b_point) such that a_point = aTb * b_point | ||||||
|    *  Note this allows for noise on the points but in that case the mapping will not be exact. |    *  Note this allows for noise on the points but in that case the mapping will not be exact. | ||||||
|    */ |    */ | ||||||
|   static boost::optional<Pose3> Align(const std::vector<Point3Pair>& abPointPairs); |   static boost::optional<Pose3> Align(const Point3Pairs& abPointPairs); | ||||||
| 
 | 
 | ||||||
|   // Version of Pose3::Align that takes 2 matrices.
 |   // Version of Pose3::Align that takes 2 matrices.
 | ||||||
|   static boost::optional<Pose3> Align(const Matrix& a, const Matrix& b); |   static boost::optional<Pose3> Align(const Matrix& a, const Matrix& b); | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ namespace gtsam { | ||||||
|   /**
 |   /**
 | ||||||
|    * Rotation matrix |    * Rotation matrix | ||||||
|    * NOTE: the angle theta is in radians unless explicitly stated |    * NOTE: the angle theta is in radians unless explicitly stated | ||||||
|    * @addtogroup geometry |    * @ingroup geometry | ||||||
|    * \nosubgrouping |    * \nosubgrouping | ||||||
|    */ |    */ | ||||||
|   class GTSAM_EXPORT Rot2 : public LieGroup<Rot2, 1> { |   class GTSAM_EXPORT Rot2 : public LieGroup<Rot2, 1> { | ||||||
|  | @ -86,7 +86,7 @@ namespace gtsam { | ||||||
|     static Rot2 atan2(double y, double x); |     static Rot2 atan2(double y, double x); | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Random, generates random angle \in [-p,pi] |      * Random, generates random angle \f$\in\f$ [-pi,pi] | ||||||
|      * Example: |      * Example: | ||||||
|      *   std::mt19937 engine(42); |      *   std::mt19937 engine(42); | ||||||
|      *   Unit3 unit = Unit3::Random(engine); |      *   Unit3 unit = Unit3::Random(engine); | ||||||
|  |  | ||||||
|  | @ -53,7 +53,7 @@ namespace gtsam { | ||||||
|  * @brief Rot3 is a 3D rotation represented as a rotation matrix if the |  * @brief Rot3 is a 3D rotation represented as a rotation matrix if the | ||||||
|  * preprocessor symbol GTSAM_USE_QUATERNIONS is not defined, or as a quaternion |  * preprocessor symbol GTSAM_USE_QUATERNIONS is not defined, or as a quaternion | ||||||
|  * if it is defined. |  * if it is defined. | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT Rot3 : public LieGroup<Rot3, 3> { | class GTSAM_EXPORT Rot3 : public LieGroup<Rot3, 3> { | ||||||
|  private: |  private: | ||||||
|  | @ -129,7 +129,7 @@ class GTSAM_EXPORT Rot3 : public LieGroup<Rot3, 3> { | ||||||
|     Rot3(double w, double x, double y, double z) : Rot3(Quaternion(w, x, y, z)) {} |     Rot3(double w, double x, double y, double z) : Rot3(Quaternion(w, x, y, z)) {} | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Random, generates a random axis, then random angle \in [-p,pi] |      * Random, generates a random axis, then random angle \f$\in\f$ [-pi,pi] | ||||||
|      * Example: |      * Example: | ||||||
|      *   std::mt19937 engine(42); |      *   std::mt19937 engine(42); | ||||||
|      *   Unit3 unit = Unit3::Random(engine); |      *   Unit3 unit = Unit3::Random(engine); | ||||||
|  |  | ||||||
|  | @ -74,7 +74,7 @@ GTSAM_EXPORT Matrix3 topLeft(const SO4 &Q, OptionalJacobian<9, 6> H = boost::non | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Project to Stiefel manifold of 4*3 orthonormal 3-frames in R^4, i.e., pi(Q) |  * Project to Stiefel manifold of 4*3 orthonormal 3-frames in R^4, i.e., pi(Q) | ||||||
|  * -> S \in St(3,4). |  * -> \f$ S \in St(3,4) \f$. | ||||||
|  */ |  */ | ||||||
| GTSAM_EXPORT Matrix43 stiefel(const SO4 &Q, OptionalJacobian<12, 6> H = boost::none); | GTSAM_EXPORT Matrix43 stiefel(const SO4 &Q, OptionalJacobian<12, 6> H = boost::none); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -121,7 +121,8 @@ class SO : public LieGroup<SO<N>, internal::DimensionSO(N)> { | ||||||
|   /// currently only defined for SO3.
 |   /// currently only defined for SO3.
 | ||||||
|   static SO ClosestTo(const MatrixNN& M); |   static SO ClosestTo(const MatrixNN& M); | ||||||
| 
 | 
 | ||||||
|   /// Named constructor that finds chordal mean = argmin_R \sum sqr(|R-R_i|_F),
 |   /// Named constructor that finds chordal mean
 | ||||||
|  |   /// \f$ mu = argmin_R \sum sqr(|R-R_i|_F) \f$,
 | ||||||
|   /// currently only defined for SO3.
 |   /// currently only defined for SO3.
 | ||||||
|   static SO ChordalMean(const std::vector<SO>& rotations); |   static SO ChordalMean(const std::vector<SO>& rotations); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -132,7 +132,7 @@ class GTSAM_EXPORT Similarity2 : public LieGroup<Similarity2, 4> { | ||||||
|    * using the algorithm described here: |    * using the algorithm described here: | ||||||
|    * http://www5.informatik.uni-erlangen.de/Forschung/Publikationen/2005/Zinsser05-PSR.pdf
 |    * http://www5.informatik.uni-erlangen.de/Forschung/Publikationen/2005/Zinsser05-PSR.pdf
 | ||||||
|    */ |    */ | ||||||
|   static Similarity2 Align(const std::vector<Pose2Pair>& abPosePairs); |   static Similarity2 Align(const Pose2Pairs& abPosePairs); | ||||||
| 
 | 
 | ||||||
|   /// @}
 |   /// @}
 | ||||||
|   /// @name Lie Group
 |   /// @name Lie Group
 | ||||||
|  |  | ||||||
|  | @ -120,7 +120,7 @@ class GTSAM_EXPORT Similarity3 : public LieGroup<Similarity3, 7> { | ||||||
|   /**
 |   /**
 | ||||||
|    *  Create Similarity3 by aligning at least three point pairs |    *  Create Similarity3 by aligning at least three point pairs | ||||||
|    */ |    */ | ||||||
|   static Similarity3 Align(const std::vector<Point3Pair>& abPointPairs); |   static Similarity3 Align(const Point3Pairs& abPointPairs); | ||||||
| 
 | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * Create the Similarity3 object that aligns at least two pose pairs. |    * Create the Similarity3 object that aligns at least two pose pairs. | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ namespace gtsam { | ||||||
|  * Empty calibration. Only needed to play well with other cameras |  * Empty calibration. Only needed to play well with other cameras | ||||||
|  * (e.g., when templating functions wrt cameras), since other cameras |  * (e.g., when templating functions wrt cameras), since other cameras | ||||||
|  * have constuctors in the form ‘camera(pose,calibration)’ |  * have constuctors in the form ‘camera(pose,calibration)’ | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT EmptyCal { | class GTSAM_EXPORT EmptyCal { | ||||||
|  | @ -64,7 +64,7 @@ class GTSAM_EXPORT EmptyCal { | ||||||
| /**
 | /**
 | ||||||
|  * A spherical camera class that has a Pose3 and measures bearing vectors. |  * A spherical camera class that has a Pose3 and measures bearing vectors. | ||||||
|  * The camera has an ‘Empty’ calibration and the only 6 dof are the pose |  * The camera has an ‘Empty’ calibration and the only 6 dof are the pose | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT SphericalCamera { | class GTSAM_EXPORT SphericalCamera { | ||||||
|  | @ -82,7 +82,6 @@ class GTSAM_EXPORT SphericalCamera { | ||||||
|   EmptyCal::shared_ptr emptyCal_; |   EmptyCal::shared_ptr emptyCal_; | ||||||
| 
 | 
 | ||||||
|  public: |  public: | ||||||
|   /// @}
 |  | ||||||
|   /// @name Standard Constructors
 |   /// @name Standard Constructors
 | ||||||
|   /// @{
 |   /// @{
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ private: | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * A stereo camera class, parameterize by left camera pose and stereo calibration |  * A stereo camera class, parameterize by left camera pose and stereo calibration | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT StereoCamera { | class GTSAM_EXPORT StereoCamera { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * A 2D stereo point, v will be same for rectified images |  * A 2D stereo point, v will be same for rectified images | ||||||
|  * @addtogroup geometry |  * @ingroup geometry | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT StereoPoint2 { | class GTSAM_EXPORT StereoPoint2 { | ||||||
|  |  | ||||||
|  | @ -1123,7 +1123,7 @@ class StereoCamera { | ||||||
| #include <gtsam/geometry/triangulation.h> | #include <gtsam/geometry/triangulation.h> | ||||||
| class TriangulationResult { | class TriangulationResult { | ||||||
|   enum Status { VALID, DEGENERATE, BEHIND_CAMERA, OUTLIER, FAR_POINT }; |   enum Status { VALID, DEGENERATE, BEHIND_CAMERA, OUTLIER, FAR_POINT }; | ||||||
|   Status status; |   gtsam::TriangulationResult::Status status; | ||||||
|   TriangulationResult(const gtsam::Point3& p); |   TriangulationResult(const gtsam::Point3& p); | ||||||
|   const gtsam::Point3& get() const; |   const gtsam::Point3& get() const; | ||||||
|   static gtsam::TriangulationResult Degenerate(); |   static gtsam::TriangulationResult Degenerate(); | ||||||
|  | @ -1142,7 +1142,7 @@ class TriangulationParameters { | ||||||
|   bool enableEPI; |   bool enableEPI; | ||||||
|   double landmarkDistanceThreshold; |   double landmarkDistanceThreshold; | ||||||
|   double dynamicOutlierRejectionThreshold; |   double dynamicOutlierRejectionThreshold; | ||||||
|   SharedNoiseModel noiseModel; |   gtsam::SharedNoiseModel noiseModel; | ||||||
|   TriangulationParameters(const double rankTolerance = 1.0, |   TriangulationParameters(const double rankTolerance = 1.0, | ||||||
|                           const bool enableEPI = false, |                           const bool enableEPI = false, | ||||||
|                           double landmarkDistanceThreshold = -1, |                           double landmarkDistanceThreshold = -1, | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ | ||||||
|  * @file     global_includes.h |  * @file     global_includes.h | ||||||
|  * @brief    Included from all GTSAM files |  * @brief    Included from all GTSAM files | ||||||
|  * @author   Richard Roberts |  * @author   Richard Roberts | ||||||
|  * @addtogroup base |  * @ingroup base | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| /** | /** | ||||||
| 
 | 
 | ||||||
| \defgroup LinearSolving Solving of sparse linear systems with least-squares | \defgroup LinearSolving Solving of sparse linear systems with least-squares | ||||||
| @{ | @{ @} | ||||||
| 
 | 
 | ||||||
| \defgroup Multifrontal Solving by multifrontal variable elimination (QR and Cholesky) | \defgroup Multifrontal Solving by multifrontal variable elimination (QR and Cholesky) | ||||||
| @{ @} | @{ @} | ||||||
|  | @ -9,9 +9,48 @@ | ||||||
| \defgroup Sequential Solving by sequential variable elimination (QR and Cholesky) | \defgroup Sequential Solving by sequential variable elimination (QR and Cholesky) | ||||||
| @{ @} | @{ @} | ||||||
| 
 | 
 | ||||||
| @} | \defgroup base Base | ||||||
| 
 |  | ||||||
| \defgroup SLAM Useful SLAM components |  | ||||||
| @{ @} | @{ @} | ||||||
| 
 | 
 | ||||||
| */ | \defgroup basis Basis | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | \defgroup discrete Discrete | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | \defgroup geometry Geometry | ||||||
|  | @{ | ||||||
|  |   Geometric primitives. | ||||||
|  | @} | ||||||
|  | 
 | ||||||
|  | \defgroup hybrid Hybrid | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | \defgroup inference Inference | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | \defgroup linear Linear | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | \defgroup navigation Navigation | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | \defgroup nonlinear Nonlinear | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | \defgroup sam SAM | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | \defgroup sfm SFM | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | \defgroup slam SLAM | ||||||
|  | @{ Useful SLAM components @} | ||||||
|  | 
 | ||||||
|  | \defgroup symbolic Symbolic | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | \defgroup isam2 ISAM2 | ||||||
|  | @{ @} | ||||||
|  | 
 | ||||||
|  | */  | ||||||
|  |  | ||||||
|  | @ -207,4 +207,28 @@ void GaussianMixture::prune(const DecisionTreeFactor &decisionTree) { | ||||||
|   conditionals_.root_ = pruned_conditionals.root_; |   conditionals_.root_ = pruned_conditionals.root_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* *******************************************************************************/ | ||||||
|  | AlgebraicDecisionTree<Key> GaussianMixture::error( | ||||||
|  |     const VectorValues &continuousVals) const { | ||||||
|  |   // functor to convert from GaussianConditional to double error value.
 | ||||||
|  |   auto errorFunc = | ||||||
|  |       [continuousVals](const GaussianConditional::shared_ptr &conditional) { | ||||||
|  |         if (conditional) { | ||||||
|  |           return conditional->error(continuousVals); | ||||||
|  |         } else { | ||||||
|  |           // return arbitrarily large error
 | ||||||
|  |           return 1e50; | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  |   DecisionTree<Key, double> errorTree(conditionals_, errorFunc); | ||||||
|  |   return errorTree; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* *******************************************************************************/ | ||||||
|  | double GaussianMixture::error(const VectorValues &continuousVals, | ||||||
|  |                               const DiscreteValues &discreteValues) const { | ||||||
|  |   auto conditional = conditionals_(discreteValues); | ||||||
|  |   return conditional->error(continuousVals); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| }  // namespace gtsam
 | }  // namespace gtsam
 | ||||||
|  |  | ||||||
|  | @ -45,6 +45,7 @@ namespace gtsam { | ||||||
|  * where i indexes the components and k_i is a component-wise normalization |  * where i indexes the components and k_i is a component-wise normalization | ||||||
|  * constant. |  * constant. | ||||||
|  * |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT GaussianMixture | class GTSAM_EXPORT GaussianMixture | ||||||
|     : public HybridFactor, |     : public HybridFactor, | ||||||
|  | @ -143,6 +144,26 @@ class GTSAM_EXPORT GaussianMixture | ||||||
|   /// Getter for the underlying Conditionals DecisionTree
 |   /// Getter for the underlying Conditionals DecisionTree
 | ||||||
|   const Conditionals &conditionals(); |   const Conditionals &conditionals(); | ||||||
| 
 | 
 | ||||||
|  |   /**
 | ||||||
|  |    * @brief Compute error of the GaussianMixture as a tree. | ||||||
|  |    * | ||||||
|  |    * @param continuousVals The continuous VectorValues. | ||||||
|  |    * @return AlgebraicDecisionTree<Key> A decision tree with corresponding keys | ||||||
|  |    * as the factor but leaf values as the error. | ||||||
|  |    */ | ||||||
|  |   AlgebraicDecisionTree<Key> error(const VectorValues &continuousVals) const; | ||||||
|  | 
 | ||||||
|  |   /**
 | ||||||
|  |    * @brief Compute the error of this Gaussian Mixture given the continuous | ||||||
|  |    * values and a discrete assignment. | ||||||
|  |    * | ||||||
|  |    * @param continuousVals The continuous values at which to compute the error. | ||||||
|  |    * @param discreteValues The discrete assignment for a specific mode sequence. | ||||||
|  |    * @return double | ||||||
|  |    */ | ||||||
|  |   double error(const VectorValues &continuousVals, | ||||||
|  |                const DiscreteValues &discreteValues) const; | ||||||
|  | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * @brief Prune the decision tree of Gaussian factors as per the discrete |    * @brief Prune the decision tree of Gaussian factors as per the discrete | ||||||
|    * `decisionTree`. |    * `decisionTree`. | ||||||
|  |  | ||||||
|  | @ -95,4 +95,24 @@ GaussianMixtureFactor::Sum GaussianMixtureFactor::asGaussianFactorGraphTree() | ||||||
|   }; |   }; | ||||||
|   return {factors_, wrap}; |   return {factors_, wrap}; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /* *******************************************************************************/ | ||||||
|  | AlgebraicDecisionTree<Key> GaussianMixtureFactor::error( | ||||||
|  |     const VectorValues &continuousVals) const { | ||||||
|  |   // functor to convert from sharedFactor to double error value.
 | ||||||
|  |   auto errorFunc = [continuousVals](const GaussianFactor::shared_ptr &factor) { | ||||||
|  |     return factor->error(continuousVals); | ||||||
|  |   }; | ||||||
|  |   DecisionTree<Key, double> errorTree(factors_, errorFunc); | ||||||
|  |   return errorTree; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* *******************************************************************************/ | ||||||
|  | double GaussianMixtureFactor::error( | ||||||
|  |     const VectorValues &continuousVals, | ||||||
|  |     const DiscreteValues &discreteValues) const { | ||||||
|  |   auto factor = factors_(discreteValues); | ||||||
|  |   return factor->error(continuousVals); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| }  // namespace gtsam
 | }  // namespace gtsam
 | ||||||
|  |  | ||||||
|  | @ -20,15 +20,19 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <gtsam/discrete/AlgebraicDecisionTree.h> | ||||||
| #include <gtsam/discrete/DecisionTree.h> | #include <gtsam/discrete/DecisionTree.h> | ||||||
| #include <gtsam/discrete/DiscreteKey.h> | #include <gtsam/discrete/DiscreteKey.h> | ||||||
|  | #include <gtsam/discrete/DiscreteValues.h> | ||||||
| #include <gtsam/hybrid/HybridGaussianFactor.h> | #include <gtsam/hybrid/HybridGaussianFactor.h> | ||||||
| #include <gtsam/linear/GaussianFactor.h> | #include <gtsam/linear/GaussianFactor.h> | ||||||
|  | #include <gtsam/linear/VectorValues.h> | ||||||
| 
 | 
 | ||||||
| namespace gtsam { | namespace gtsam { | ||||||
| 
 | 
 | ||||||
| class GaussianFactorGraph; | class GaussianFactorGraph; | ||||||
| 
 | 
 | ||||||
|  | // Needed for wrapper.
 | ||||||
| using GaussianFactorVector = std::vector<gtsam::GaussianFactor::shared_ptr>; | using GaussianFactorVector = std::vector<gtsam::GaussianFactor::shared_ptr>; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -40,6 +44,7 @@ using GaussianFactorVector = std::vector<gtsam::GaussianFactor::shared_ptr>; | ||||||
|  * Represents the underlying Gaussian Mixture as a Decision Tree, where the set |  * Represents the underlying Gaussian Mixture as a Decision Tree, where the set | ||||||
|  * of discrete variables indexes to the continuous gaussian distribution. |  * of discrete variables indexes to the continuous gaussian distribution. | ||||||
|  * |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT GaussianMixtureFactor : public HybridFactor { | class GTSAM_EXPORT GaussianMixtureFactor : public HybridFactor { | ||||||
|  public: |  public: | ||||||
|  | @ -125,6 +130,26 @@ class GTSAM_EXPORT GaussianMixtureFactor : public HybridFactor { | ||||||
|    */ |    */ | ||||||
|   Sum add(const Sum &sum) const; |   Sum add(const Sum &sum) const; | ||||||
| 
 | 
 | ||||||
|  |   /**
 | ||||||
|  |    * @brief Compute error of the GaussianMixtureFactor as a tree. | ||||||
|  |    * | ||||||
|  |    * @param continuousVals The continuous VectorValues. | ||||||
|  |    * @return AlgebraicDecisionTree<Key> A decision tree with corresponding keys | ||||||
|  |    * as the factor but leaf values as the error. | ||||||
|  |    */ | ||||||
|  |   AlgebraicDecisionTree<Key> error(const VectorValues &continuousVals) const; | ||||||
|  | 
 | ||||||
|  |   /**
 | ||||||
|  |    * @brief Compute the error of this Gaussian Mixture given the continuous | ||||||
|  |    * values and a discrete assignment. | ||||||
|  |    * | ||||||
|  |    * @param continuousVals The continuous values at which to compute the error. | ||||||
|  |    * @param discreteValues The discrete assignment for a specific mode sequence. | ||||||
|  |    * @return double | ||||||
|  |    */ | ||||||
|  |   double error(const VectorValues &continuousVals, | ||||||
|  |                const DiscreteValues &discreteValues) const; | ||||||
|  | 
 | ||||||
|   /// Add MixtureFactor to a Sum, syntactic sugar.
 |   /// Add MixtureFactor to a Sum, syntactic sugar.
 | ||||||
|   friend Sum &operator+=(Sum &sum, const GaussianMixtureFactor &factor) { |   friend Sum &operator+=(Sum &sum, const GaussianMixtureFactor &factor) { | ||||||
|     sum = factor.add(sum); |     sum = factor.add(sum); | ||||||
|  |  | ||||||
|  | @ -232,4 +232,45 @@ VectorValues HybridBayesNet::optimize(const DiscreteValues &assignment) const { | ||||||
|   return gbn.optimize(); |   return gbn.optimize(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | double HybridBayesNet::error(const VectorValues &continuousValues, | ||||||
|  |                              const DiscreteValues &discreteValues) const { | ||||||
|  |   GaussianBayesNet gbn = this->choose(discreteValues); | ||||||
|  |   return gbn.error(continuousValues); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | AlgebraicDecisionTree<Key> HybridBayesNet::error( | ||||||
|  |     const VectorValues &continuousValues) const { | ||||||
|  |   AlgebraicDecisionTree<Key> error_tree; | ||||||
|  | 
 | ||||||
|  |   for (size_t idx = 0; idx < size(); idx++) { | ||||||
|  |     AlgebraicDecisionTree<Key> conditional_error; | ||||||
|  |     if (factors_.at(idx)->isHybrid()) { | ||||||
|  |       // If factor is hybrid, select based on assignment.
 | ||||||
|  |       GaussianMixture::shared_ptr gm = this->atMixture(idx); | ||||||
|  |       conditional_error = gm->error(continuousValues); | ||||||
|  | 
 | ||||||
|  |       if (idx == 0) { | ||||||
|  |         error_tree = conditional_error; | ||||||
|  |       } else { | ||||||
|  |         error_tree = error_tree + conditional_error; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |     } else if (factors_.at(idx)->isContinuous()) { | ||||||
|  |       // If continuous only, get the (double) error
 | ||||||
|  |       // and add it to the error_tree
 | ||||||
|  |       double error = this->atGaussian(idx)->error(continuousValues); | ||||||
|  |       error_tree = error_tree.apply( | ||||||
|  |           [error](double leaf_value) { return leaf_value + error; }); | ||||||
|  | 
 | ||||||
|  |     } else if (factors_.at(idx)->isDiscrete()) { | ||||||
|  |       // If factor at `idx` is discrete-only, we skip.
 | ||||||
|  |       continue; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return error_tree; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| }  // namespace gtsam
 | }  // namespace gtsam
 | ||||||
|  |  | ||||||
|  | @ -29,6 +29,8 @@ namespace gtsam { | ||||||
| /**
 | /**
 | ||||||
|  * A hybrid Bayes net is a collection of HybridConditionals, which can have |  * A hybrid Bayes net is a collection of HybridConditionals, which can have | ||||||
|  * discrete conditionals, Gaussian mixtures, or pure Gaussian conditionals. |  * discrete conditionals, Gaussian mixtures, or pure Gaussian conditionals. | ||||||
|  |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT HybridBayesNet : public BayesNet<HybridConditional> { | class GTSAM_EXPORT HybridBayesNet : public BayesNet<HybridConditional> { | ||||||
|  public: |  public: | ||||||
|  | @ -122,6 +124,26 @@ class GTSAM_EXPORT HybridBayesNet : public BayesNet<HybridConditional> { | ||||||
|   /// Prune the Hybrid Bayes Net such that we have at most maxNrLeaves leaves.
 |   /// Prune the Hybrid Bayes Net such that we have at most maxNrLeaves leaves.
 | ||||||
|   HybridBayesNet prune(size_t maxNrLeaves); |   HybridBayesNet prune(size_t maxNrLeaves); | ||||||
| 
 | 
 | ||||||
|  |   /**
 | ||||||
|  |    * @brief 0.5 * sum of squared Mahalanobis distances | ||||||
|  |    * for a specific discrete assignment. | ||||||
|  |    * | ||||||
|  |    * @param continuousValues Continuous values at which to compute the error. | ||||||
|  |    * @param discreteValues Discrete assignment for a specific mode sequence. | ||||||
|  |    * @return double | ||||||
|  |    */ | ||||||
|  |   double error(const VectorValues &continuousValues, | ||||||
|  |                const DiscreteValues &discreteValues) const; | ||||||
|  | 
 | ||||||
|  |   /**
 | ||||||
|  |    * @brief Compute conditional error for each discrete assignment, | ||||||
|  |    * and return as a tree. | ||||||
|  |    * | ||||||
|  |    * @param continuousValues Continuous values at which to compute the error. | ||||||
|  |    * @return AlgebraicDecisionTree<Key> | ||||||
|  |    */ | ||||||
|  |   AlgebraicDecisionTree<Key> error(const VectorValues &continuousValues) const; | ||||||
|  | 
 | ||||||
|   /// @}
 |   /// @}
 | ||||||
| 
 | 
 | ||||||
|  private: |  private: | ||||||
|  |  | ||||||
|  | @ -34,8 +34,11 @@ class HybridConditional; | ||||||
| class VectorValues; | class VectorValues; | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| /** A clique in a HybridBayesTree
 | /**
 | ||||||
|  |  * @brief A clique in a HybridBayesTree | ||||||
|  * which is a HybridConditional internally. |  * which is a HybridConditional internally. | ||||||
|  |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT HybridBayesTreeClique | class GTSAM_EXPORT HybridBayesTreeClique | ||||||
|     : public BayesTreeCliqueBase<HybridBayesTreeClique, |     : public BayesTreeCliqueBase<HybridBayesTreeClique, | ||||||
|  |  | ||||||
|  | @ -54,6 +54,8 @@ namespace gtsam { | ||||||
|  * |  * | ||||||
|  * A great reference to the type-erasure pattern is Eduaado Madrid's CppCon |  * A great reference to the type-erasure pattern is Eduaado Madrid's CppCon | ||||||
|  * talk (https://www.youtube.com/watch?v=s082Qmd_nHs).
 |  * talk (https://www.youtube.com/watch?v=s082Qmd_nHs).
 | ||||||
|  |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT HybridConditional | class GTSAM_EXPORT HybridConditional | ||||||
|     : public HybridFactor, |     : public HybridFactor, | ||||||
|  |  | ||||||
|  | @ -28,6 +28,8 @@ namespace gtsam { | ||||||
|  * A HybridDiscreteFactor is a thin container for DiscreteFactor, which allows |  * A HybridDiscreteFactor is a thin container for DiscreteFactor, which allows | ||||||
|  * us to hide the implementation of DiscreteFactor and thus avoid diamond |  * us to hide the implementation of DiscreteFactor and thus avoid diamond | ||||||
|  * inheritance. |  * inheritance. | ||||||
|  |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT HybridDiscreteFactor : public HybridFactor { | class GTSAM_EXPORT HybridDiscreteFactor : public HybridFactor { | ||||||
|  private: |  private: | ||||||
|  |  | ||||||
|  | @ -25,6 +25,8 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Elimination Tree type for Hybrid |  * Elimination Tree type for Hybrid | ||||||
|  |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT HybridEliminationTree | class GTSAM_EXPORT HybridEliminationTree | ||||||
|     : public EliminationTree<HybridBayesNet, HybridGaussianFactorGraph> { |     : public EliminationTree<HybridBayesNet, HybridGaussianFactorGraph> { | ||||||
|  |  | ||||||
|  | @ -40,6 +40,8 @@ DiscreteKeys CollectDiscreteKeys(const DiscreteKeys &key1, | ||||||
|  *  - HybridDiscreteFactor |  *  - HybridDiscreteFactor | ||||||
|  *  - GaussianMixtureFactor |  *  - GaussianMixtureFactor | ||||||
|  *  - GaussianMixture |  *  - GaussianMixture | ||||||
|  |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT HybridFactor : public Factor { | class GTSAM_EXPORT HybridFactor : public Factor { | ||||||
|  private: |  private: | ||||||
|  |  | ||||||
|  | @ -27,6 +27,8 @@ namespace gtsam { | ||||||
|  * A HybridGaussianFactor is a layer over GaussianFactor so that we do not have |  * A HybridGaussianFactor is a layer over GaussianFactor so that we do not have | ||||||
|  * a diamond inheritance i.e. an extra factor type that inherits from both |  * a diamond inheritance i.e. an extra factor type that inherits from both | ||||||
|  * HybridFactor and GaussianFactor. |  * HybridFactor and GaussianFactor. | ||||||
|  |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT HybridGaussianFactor : public HybridFactor { | class GTSAM_EXPORT HybridGaussianFactor : public HybridFactor { | ||||||
|  private: |  private: | ||||||
|  |  | ||||||
|  | @ -39,7 +39,14 @@ class DecisionTreeFactor; | ||||||
| 
 | 
 | ||||||
| class JacobianFactor; | class JacobianFactor; | ||||||
| 
 | 
 | ||||||
| /** Main elimination function for HybridGaussianFactorGraph */ | /**
 | ||||||
|  |  * @brief Main elimination function for HybridGaussianFactorGraph. | ||||||
|  |  *  | ||||||
|  |  * @param factors The factor graph to eliminate. | ||||||
|  |  * @param keys The elimination ordering. | ||||||
|  |  * @return The conditional on the ordering keys and the remaining factors. | ||||||
|  |  * @ingroup hybrid | ||||||
|  |  */ | ||||||
| GTSAM_EXPORT | GTSAM_EXPORT | ||||||
| std::pair<boost::shared_ptr<HybridConditional>, HybridFactor::shared_ptr> | std::pair<boost::shared_ptr<HybridConditional>, HybridFactor::shared_ptr> | ||||||
| EliminateHybrid(const HybridGaussianFactorGraph& factors, const Ordering& keys); | EliminateHybrid(const HybridGaussianFactorGraph& factors, const Ordering& keys); | ||||||
|  | @ -68,10 +75,12 @@ struct EliminationTraits<HybridGaussianFactorGraph> { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Gaussian Hybrid Factor Graph |  * Hybrid Gaussian Factor Graph | ||||||
|  * ----------------------- |  * ----------------------- | ||||||
|  * This is the linearized version of a hybrid factor graph. |  * This is the linearized version of a hybrid factor graph. | ||||||
|  * Everything inside needs to be hybrid factor or hybrid conditional. |  * Everything inside needs to be hybrid factor or hybrid conditional. | ||||||
|  |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT HybridGaussianFactorGraph | class GTSAM_EXPORT HybridGaussianFactorGraph | ||||||
|     : public HybridFactorGraph, |     : public HybridFactorGraph, | ||||||
|  | @ -120,13 +129,13 @@ class GTSAM_EXPORT HybridGaussianFactorGraph | ||||||
|   void add(JacobianFactor&& factor); |   void add(JacobianFactor&& factor); | ||||||
| 
 | 
 | ||||||
|   /// Add a Jacobian factor as a shared ptr.
 |   /// Add a Jacobian factor as a shared ptr.
 | ||||||
|   void add(boost::shared_ptr<JacobianFactor> factor); |   void add(JacobianFactor::shared_ptr factor); | ||||||
| 
 | 
 | ||||||
|   /// Add a DecisionTreeFactor to the factor graph.
 |   /// Add a DecisionTreeFactor to the factor graph.
 | ||||||
|   void add(DecisionTreeFactor&& factor); |   void add(DecisionTreeFactor&& factor); | ||||||
| 
 | 
 | ||||||
|   /// Add a DecisionTreeFactor as a shared ptr.
 |   /// Add a DecisionTreeFactor as a shared ptr.
 | ||||||
|   void add(boost::shared_ptr<DecisionTreeFactor> factor); |   void add(DecisionTreeFactor::shared_ptr factor); | ||||||
| 
 | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * Add a gaussian factor *pointer* to the internal gaussian factor graph |    * Add a gaussian factor *pointer* to the internal gaussian factor graph | ||||||
|  |  | ||||||
|  | @ -38,6 +38,35 @@ HybridGaussianISAM::HybridGaussianISAM() {} | ||||||
| HybridGaussianISAM::HybridGaussianISAM(const HybridBayesTree& bayesTree) | HybridGaussianISAM::HybridGaussianISAM(const HybridBayesTree& bayesTree) | ||||||
|     : Base(bayesTree) {} |     : Base(bayesTree) {} | ||||||
| 
 | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | Ordering HybridGaussianISAM::GetOrdering( | ||||||
|  |     HybridGaussianFactorGraph& factors, | ||||||
|  |     const HybridGaussianFactorGraph& newFactors) { | ||||||
|  |   // Get all the discrete keys from the factors
 | ||||||
|  |   KeySet allDiscrete = factors.discreteKeys(); | ||||||
|  | 
 | ||||||
|  |   // Create KeyVector with continuous keys followed by discrete keys.
 | ||||||
|  |   KeyVector newKeysDiscreteLast; | ||||||
|  |   const KeySet newFactorKeys = newFactors.keys(); | ||||||
|  |   // Insert continuous keys first.
 | ||||||
|  |   for (auto& k : newFactorKeys) { | ||||||
|  |     if (!allDiscrete.exists(k)) { | ||||||
|  |       newKeysDiscreteLast.push_back(k); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   // Insert discrete keys at the end
 | ||||||
|  |   std::copy(allDiscrete.begin(), allDiscrete.end(), | ||||||
|  |             std::back_inserter(newKeysDiscreteLast)); | ||||||
|  | 
 | ||||||
|  |   const VariableIndex index(factors); | ||||||
|  | 
 | ||||||
|  |   // Get an ordering where the new keys are eliminated last
 | ||||||
|  |   Ordering ordering = Ordering::ColamdConstrainedLast( | ||||||
|  |       index, KeyVector(newKeysDiscreteLast.begin(), newKeysDiscreteLast.end()), | ||||||
|  |       true); | ||||||
|  |   return ordering; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| void HybridGaussianISAM::updateInternal( | void HybridGaussianISAM::updateInternal( | ||||||
|     const HybridGaussianFactorGraph& newFactors, |     const HybridGaussianFactorGraph& newFactors, | ||||||
|  | @ -54,7 +83,7 @@ void HybridGaussianISAM::updateInternal( | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Add the removed top and the new factors
 |   // Add the removed top and the new factors
 | ||||||
|   FactorGraphType factors; |   HybridGaussianFactorGraph factors; | ||||||
|   factors += bn; |   factors += bn; | ||||||
|   factors += newFactors; |   factors += newFactors; | ||||||
| 
 | 
 | ||||||
|  | @ -63,32 +92,12 @@ void HybridGaussianISAM::updateInternal( | ||||||
|     factors += boost::make_shared<BayesTreeOrphanWrapper<Node>>(orphan); |     factors += boost::make_shared<BayesTreeOrphanWrapper<Node>>(orphan); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Get all the discrete keys from the factors
 |  | ||||||
|   KeySet allDiscrete = factors.discreteKeys(); |  | ||||||
| 
 |  | ||||||
|   // Create KeyVector with continuous keys followed by discrete keys.
 |  | ||||||
|   KeyVector newKeysDiscreteLast; |  | ||||||
|   // Insert continuous keys first.
 |  | ||||||
|   for (auto& k : newFactorKeys) { |  | ||||||
|     if (!allDiscrete.exists(k)) { |  | ||||||
|       newKeysDiscreteLast.push_back(k); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   // Insert discrete keys at the end
 |  | ||||||
|   std::copy(allDiscrete.begin(), allDiscrete.end(), |  | ||||||
|             std::back_inserter(newKeysDiscreteLast)); |  | ||||||
| 
 |  | ||||||
|   // Get an ordering where the new keys are eliminated last
 |  | ||||||
|   const VariableIndex index(factors); |   const VariableIndex index(factors); | ||||||
| 
 |  | ||||||
|   Ordering elimination_ordering; |   Ordering elimination_ordering; | ||||||
|   if (ordering) { |   if (ordering) { | ||||||
|     elimination_ordering = *ordering; |     elimination_ordering = *ordering; | ||||||
|   } else { |   } else { | ||||||
|     elimination_ordering = Ordering::ColamdConstrainedLast( |     elimination_ordering = GetOrdering(factors, newFactors); | ||||||
|         index, |  | ||||||
|         KeyVector(newKeysDiscreteLast.begin(), newKeysDiscreteLast.end()), |  | ||||||
|         true); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // eliminate all factors (top, added, orphans) into a new Bayes tree
 |   // eliminate all factors (top, added, orphans) into a new Bayes tree
 | ||||||
|  |  | ||||||
|  | @ -26,6 +26,11 @@ | ||||||
| 
 | 
 | ||||||
| namespace gtsam { | namespace gtsam { | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief  | ||||||
|  |  * | ||||||
|  |  * @ingroup hybrid | ||||||
|  |  */ | ||||||
| class GTSAM_EXPORT HybridGaussianISAM : public ISAM<HybridBayesTree> { | class GTSAM_EXPORT HybridGaussianISAM : public ISAM<HybridBayesTree> { | ||||||
|  public: |  public: | ||||||
|   typedef ISAM<HybridBayesTree> Base; |   typedef ISAM<HybridBayesTree> Base; | ||||||
|  | @ -67,6 +72,17 @@ class GTSAM_EXPORT HybridGaussianISAM : public ISAM<HybridBayesTree> { | ||||||
|               const boost::optional<Ordering>& ordering = boost::none, |               const boost::optional<Ordering>& ordering = boost::none, | ||||||
|               const HybridBayesTree::Eliminate& function = |               const HybridBayesTree::Eliminate& function = | ||||||
|                   HybridBayesTree::EliminationTraitsType::DefaultEliminate); |                   HybridBayesTree::EliminationTraitsType::DefaultEliminate); | ||||||
|  | 
 | ||||||
|  |   /**
 | ||||||
|  |    * @brief Helper method to get an ordering given the existing factors and any | ||||||
|  |    * new factors added. | ||||||
|  |    * | ||||||
|  |    * @param factors The existing factors in the BayesTree. | ||||||
|  |    * @param newFactors New factors added during the update step. | ||||||
|  |    * @return Ordering | ||||||
|  |    */ | ||||||
|  |   static Ordering GetOrdering(HybridGaussianFactorGraph& factors, | ||||||
|  |                               const HybridGaussianFactorGraph& newFactors); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// traits
 | /// traits
 | ||||||
|  |  | ||||||
|  | @ -45,7 +45,8 @@ class HybridEliminationTree; | ||||||
|  * EliminationTree, except that in the JunctionTree, at each node multiple |  * EliminationTree, except that in the JunctionTree, at each node multiple | ||||||
|  * variables are eliminated at a time. |  * variables are eliminated at a time. | ||||||
|  * |  * | ||||||
|  * \addtogroup Multifrontal |  * \ingroup Multifrontal | ||||||
|  |  * \ingroup hybrid | ||||||
|  * \nosubgrouping |  * \nosubgrouping | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT HybridJunctionTree | class GTSAM_EXPORT HybridJunctionTree | ||||||
|  |  | ||||||
|  | @ -107,8 +107,12 @@ class MixtureFactor : public HybridFactor { | ||||||
|       std::copy(f->keys().begin(), f->keys().end(), |       std::copy(f->keys().begin(), f->keys().end(), | ||||||
|                 std::inserter(factor_keys_set, factor_keys_set.end())); |                 std::inserter(factor_keys_set, factor_keys_set.end())); | ||||||
| 
 | 
 | ||||||
|       nonlinear_factors.push_back( |       if (auto nf = boost::dynamic_pointer_cast<NonlinearFactor>(f)) { | ||||||
|           boost::dynamic_pointer_cast<NonlinearFactor>(f)); |         nonlinear_factors.push_back(nf); | ||||||
|  |       } else { | ||||||
|  |         throw std::runtime_error( | ||||||
|  |             "Factors passed into MixtureFactor need to be nonlinear!"); | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|     factors_ = Factors(discreteKeys, nonlinear_factors); |     factors_ = Factors(discreteKeys, nonlinear_factors); | ||||||
| 
 | 
 | ||||||
|  | @ -121,6 +125,22 @@ class MixtureFactor : public HybridFactor { | ||||||
| 
 | 
 | ||||||
|   ~MixtureFactor() = default; |   ~MixtureFactor() = default; | ||||||
| 
 | 
 | ||||||
|  |   /**
 | ||||||
|  |    * @brief Compute error of the MixtureFactor as a tree. | ||||||
|  |    * | ||||||
|  |    * @param continuousVals The continuous values for which to compute the error. | ||||||
|  |    * @return AlgebraicDecisionTree<Key> A decision tree with corresponding keys | ||||||
|  |    * as the factor but leaf values as the error. | ||||||
|  |    */ | ||||||
|  |   AlgebraicDecisionTree<Key> error(const Values& continuousVals) const { | ||||||
|  |     // functor to convert from sharedFactor to double error value.
 | ||||||
|  |     auto errorFunc = [continuousVals](const sharedFactor& factor) { | ||||||
|  |       return factor->error(continuousVals); | ||||||
|  |     }; | ||||||
|  |     DecisionTree<Key, double> errorTree(factors_, errorFunc); | ||||||
|  |     return errorTree; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * @brief Compute error of factor given both continuous and discrete values. |    * @brief Compute error of factor given both continuous and discrete values. | ||||||
|    * |    * | ||||||
|  | @ -149,7 +169,7 @@ class MixtureFactor : public HybridFactor { | ||||||
| 
 | 
 | ||||||
|   /// print to stdout
 |   /// print to stdout
 | ||||||
|   void print( |   void print( | ||||||
|       const std::string& s = "MixtureFactor", |       const std::string& s = "", | ||||||
|       const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override { |       const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override { | ||||||
|     std::cout << (s.empty() ? "" : s + " "); |     std::cout << (s.empty() ? "" : s + " "); | ||||||
|     Base::print("", keyFormatter); |     Base::print("", keyFormatter); | ||||||
|  |  | ||||||
|  | @ -78,15 +78,51 @@ TEST(GaussianMixture, Equals) { | ||||||
|   GaussianMixture::Conditionals conditionals( |   GaussianMixture::Conditionals conditionals( | ||||||
|       {m1}, |       {m1}, | ||||||
|       vector<GaussianConditional::shared_ptr>{conditional0, conditional1}); |       vector<GaussianConditional::shared_ptr>{conditional0, conditional1}); | ||||||
|   GaussianMixture mixtureFactor({X(1)}, {X(2)}, {m1}, conditionals); |   GaussianMixture mixture({X(1)}, {X(2)}, {m1}, conditionals); | ||||||
| 
 | 
 | ||||||
|   // Let's check that this worked:
 |   // Let's check that this worked:
 | ||||||
|   DiscreteValues mode; |   DiscreteValues mode; | ||||||
|   mode[m1.first] = 1; |   mode[m1.first] = 1; | ||||||
|   auto actual = mixtureFactor(mode); |   auto actual = mixture(mode); | ||||||
|   EXPECT(actual == conditional1); |   EXPECT(actual == conditional1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | /// Test error method of GaussianMixture.
 | ||||||
|  | TEST(GaussianMixture, Error) { | ||||||
|  |   Matrix22 S1 = Matrix22::Identity(); | ||||||
|  |   Matrix22 S2 = Matrix22::Identity() * 2; | ||||||
|  |   Matrix22 R1 = Matrix22::Ones(); | ||||||
|  |   Matrix22 R2 = Matrix22::Ones(); | ||||||
|  |   Vector2 d1(1, 2), d2(2, 1); | ||||||
|  | 
 | ||||||
|  |   SharedDiagonal model = noiseModel::Diagonal::Sigmas(Vector2(1.0, 0.34)); | ||||||
|  | 
 | ||||||
|  |   auto conditional0 = boost::make_shared<GaussianConditional>(X(1), d1, R1, | ||||||
|  |                                                               X(2), S1, model), | ||||||
|  |        conditional1 = boost::make_shared<GaussianConditional>(X(1), d2, R2, | ||||||
|  |                                                               X(2), S2, model); | ||||||
|  | 
 | ||||||
|  |   // Create decision tree
 | ||||||
|  |   DiscreteKey m1(1, 2); | ||||||
|  |   GaussianMixture::Conditionals conditionals( | ||||||
|  |       {m1}, | ||||||
|  |       vector<GaussianConditional::shared_ptr>{conditional0, conditional1}); | ||||||
|  |   GaussianMixture mixture({X(1)}, {X(2)}, {m1}, conditionals); | ||||||
|  | 
 | ||||||
|  |   VectorValues values; | ||||||
|  |   values.insert(X(1), Vector2::Ones()); | ||||||
|  |   values.insert(X(2), Vector2::Zero()); | ||||||
|  |   auto error_tree = mixture.error(values); | ||||||
|  | 
 | ||||||
|  |   std::vector<DiscreteKey> discrete_keys = {m1}; | ||||||
|  |   std::vector<double> leaves = {0.5, 4.3252595}; | ||||||
|  |   AlgebraicDecisionTree<Key> expected_error(discrete_keys, leaves); | ||||||
|  | 
 | ||||||
|  |   // regression
 | ||||||
|  |   EXPECT(assert_equal(expected_error, error_tree, 1e-6)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| int main() { | int main() { | ||||||
|   TestResult tr; |   TestResult tr; | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ | ||||||
|  * -------------------------------------------------------------------------- */ |  * -------------------------------------------------------------------------- */ | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @file    GaussianMixtureFactor.cpp |  * @file    testGaussianMixtureFactor.cpp | ||||||
|  * @brief   Unit tests for GaussianMixtureFactor |  * @brief   Unit tests for GaussianMixtureFactor | ||||||
|  * @author  Varun Agrawal |  * @author  Varun Agrawal | ||||||
|  * @author  Fan Jiang |  * @author  Fan Jiang | ||||||
|  | @ -135,7 +135,7 @@ TEST(GaussianMixtureFactor, Printing) { | ||||||
|   EXPECT(assert_print_equal(expected, mixtureFactor)); |   EXPECT(assert_print_equal(expected, mixtureFactor)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_UNSAFE(GaussianMixtureFactor, GaussianMixture) { | TEST(GaussianMixtureFactor, GaussianMixture) { | ||||||
|   KeyVector keys; |   KeyVector keys; | ||||||
|   keys.push_back(X(0)); |   keys.push_back(X(0)); | ||||||
|   keys.push_back(X(1)); |   keys.push_back(X(1)); | ||||||
|  | @ -151,6 +151,45 @@ TEST_UNSAFE(GaussianMixtureFactor, GaussianMixture) { | ||||||
|   EXPECT_LONGS_EQUAL(2, gm.discreteKeys().size()); |   EXPECT_LONGS_EQUAL(2, gm.discreteKeys().size()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | // Test the error of the GaussianMixtureFactor
 | ||||||
|  | TEST(GaussianMixtureFactor, Error) { | ||||||
|  |   DiscreteKey m1(1, 2); | ||||||
|  | 
 | ||||||
|  |   auto A01 = Matrix2::Identity(); | ||||||
|  |   auto A02 = Matrix2::Identity(); | ||||||
|  | 
 | ||||||
|  |   auto A11 = Matrix2::Identity(); | ||||||
|  |   auto A12 = Matrix2::Identity() * 2; | ||||||
|  | 
 | ||||||
|  |   auto b = Vector2::Zero(); | ||||||
|  | 
 | ||||||
|  |   auto f0 = boost::make_shared<JacobianFactor>(X(1), A01, X(2), A02, b); | ||||||
|  |   auto f1 = boost::make_shared<JacobianFactor>(X(1), A11, X(2), A12, b); | ||||||
|  |   std::vector<GaussianFactor::shared_ptr> factors{f0, f1}; | ||||||
|  | 
 | ||||||
|  |   GaussianMixtureFactor mixtureFactor({X(1), X(2)}, {m1}, factors); | ||||||
|  | 
 | ||||||
|  |   VectorValues continuousVals; | ||||||
|  |   continuousVals.insert(X(1), Vector2(0, 0)); | ||||||
|  |   continuousVals.insert(X(2), Vector2(1, 1)); | ||||||
|  | 
 | ||||||
|  |   // error should return a tree of errors, with nodes for each discrete value.
 | ||||||
|  |   AlgebraicDecisionTree<Key> error_tree = mixtureFactor.error(continuousVals); | ||||||
|  | 
 | ||||||
|  |   std::vector<DiscreteKey> discrete_keys = {m1}; | ||||||
|  |   std::vector<double> errors = {1, 4}; | ||||||
|  |   AlgebraicDecisionTree<Key> expected_error(discrete_keys, errors); | ||||||
|  | 
 | ||||||
|  |   EXPECT(assert_equal(expected_error, error_tree)); | ||||||
|  | 
 | ||||||
|  |   // Test for single leaf given discrete assignment P(X|M,Z).
 | ||||||
|  |   DiscreteValues discreteVals; | ||||||
|  |   discreteVals[m1.first] = 1; | ||||||
|  |   EXPECT_DOUBLES_EQUAL(4.0, mixtureFactor.error(continuousVals, discreteVals), | ||||||
|  |                        1e-9); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| int main() { | int main() { | ||||||
|   TestResult tr; |   TestResult tr; | ||||||
|  |  | ||||||
|  | @ -183,6 +183,61 @@ TEST(HybridBayesNet, OptimizeMultifrontal) { | ||||||
|   EXPECT(assert_equal(expectedValues, delta.continuous(), 1e-5)); |   EXPECT(assert_equal(expectedValues, delta.continuous(), 1e-5)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* ****************************************************************************/ | ||||||
|  | // Test bayes net error
 | ||||||
|  | TEST(HybridBayesNet, Error) { | ||||||
|  |   Switching s(3); | ||||||
|  | 
 | ||||||
|  |   Ordering hybridOrdering = s.linearizedFactorGraph.getHybridOrdering(); | ||||||
|  |   HybridBayesNet::shared_ptr hybridBayesNet = | ||||||
|  |       s.linearizedFactorGraph.eliminateSequential(hybridOrdering); | ||||||
|  | 
 | ||||||
|  |   HybridValues delta = hybridBayesNet->optimize(); | ||||||
|  |   auto error_tree = hybridBayesNet->error(delta.continuous()); | ||||||
|  | 
 | ||||||
|  |   std::vector<DiscreteKey> discrete_keys = {{M(0), 2}, {M(1), 2}}; | ||||||
|  |   std::vector<double> leaves = {0.0097568009, 3.3973404e-31, 0.029126214, | ||||||
|  |                                 0.0097568009}; | ||||||
|  |   AlgebraicDecisionTree<Key> expected_error(discrete_keys, leaves); | ||||||
|  | 
 | ||||||
|  |   // regression
 | ||||||
|  |   EXPECT(assert_equal(expected_error, error_tree, 1e-9)); | ||||||
|  | 
 | ||||||
|  |   // Error on pruned bayes net
 | ||||||
|  |   auto prunedBayesNet = hybridBayesNet->prune(2); | ||||||
|  |   auto pruned_error_tree = prunedBayesNet.error(delta.continuous()); | ||||||
|  | 
 | ||||||
|  |   std::vector<double> pruned_leaves = {2e50, 3.3973404e-31, 2e50, 0.0097568009}; | ||||||
|  |   AlgebraicDecisionTree<Key> expected_pruned_error(discrete_keys, | ||||||
|  |                                                    pruned_leaves); | ||||||
|  | 
 | ||||||
|  |   // regression
 | ||||||
|  |   EXPECT(assert_equal(expected_pruned_error, pruned_error_tree, 1e-9)); | ||||||
|  | 
 | ||||||
|  |   // Verify error computation and check for specific error value
 | ||||||
|  |   DiscreteValues discrete_values; | ||||||
|  |   discrete_values[M(0)] = 1; | ||||||
|  |   discrete_values[M(1)] = 1; | ||||||
|  | 
 | ||||||
|  |   double total_error = 0; | ||||||
|  |   for (size_t idx = 0; idx < hybridBayesNet->size(); idx++) { | ||||||
|  |     if (hybridBayesNet->at(idx)->isHybrid()) { | ||||||
|  |       double error = hybridBayesNet->atMixture(idx)->error(delta.continuous(), | ||||||
|  |                                                            discrete_values); | ||||||
|  |       total_error += error; | ||||||
|  |     } else if (hybridBayesNet->at(idx)->isContinuous()) { | ||||||
|  |       double error = hybridBayesNet->atGaussian(idx)->error(delta.continuous()); | ||||||
|  |       total_error += error; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   EXPECT_DOUBLES_EQUAL( | ||||||
|  |       total_error, hybridBayesNet->error(delta.continuous(), discrete_values), | ||||||
|  |       1e-9); | ||||||
|  |   EXPECT_DOUBLES_EQUAL(total_error, error_tree(discrete_values), 1e-9); | ||||||
|  |   EXPECT_DOUBLES_EQUAL(total_error, pruned_error_tree(discrete_values), 1e-9); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* ****************************************************************************/ | /* ****************************************************************************/ | ||||||
| // Test bayes net pruning
 | // Test bayes net pruning
 | ||||||
| TEST(HybridBayesNet, Prune) { | TEST(HybridBayesNet, Prune) { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,108 @@ | ||||||
|  | /* ----------------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation, | ||||||
|  |  * Atlanta, Georgia 30332-0415 | ||||||
|  |  * All Rights Reserved | ||||||
|  |  * Authors: Frank Dellaert, et al. (see THANKS for the full author list) | ||||||
|  | 
 | ||||||
|  |  * See LICENSE for the license information | ||||||
|  | 
 | ||||||
|  |  * -------------------------------------------------------------------------- */ | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @file    testMixtureFactor.cpp | ||||||
|  |  * @brief   Unit tests for MixtureFactor | ||||||
|  |  * @author  Varun Agrawal | ||||||
|  |  * @date    October 2022 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <gtsam/base/TestableAssertions.h> | ||||||
|  | #include <gtsam/discrete/DiscreteValues.h> | ||||||
|  | #include <gtsam/hybrid/MixtureFactor.h> | ||||||
|  | #include <gtsam/inference/Symbol.h> | ||||||
|  | #include <gtsam/slam/BetweenFactor.h> | ||||||
|  | 
 | ||||||
|  | // Include for test suite
 | ||||||
|  | #include <CppUnitLite/TestHarness.h> | ||||||
|  | 
 | ||||||
|  | using namespace std; | ||||||
|  | using namespace gtsam; | ||||||
|  | using noiseModel::Isotropic; | ||||||
|  | using symbol_shorthand::M; | ||||||
|  | using symbol_shorthand::X; | ||||||
|  | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | // Check iterators of empty mixture.
 | ||||||
|  | TEST(MixtureFactor, Constructor) { | ||||||
|  |   MixtureFactor factor; | ||||||
|  |   MixtureFactor::const_iterator const_it = factor.begin(); | ||||||
|  |   CHECK(const_it == factor.end()); | ||||||
|  |   MixtureFactor::iterator it = factor.begin(); | ||||||
|  |   CHECK(it == factor.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | TEST(MixtureFactor, Printing) { | ||||||
|  |   DiscreteKey m1(1, 2); | ||||||
|  |   double between0 = 0.0; | ||||||
|  |   double between1 = 1.0; | ||||||
|  | 
 | ||||||
|  |   Vector1 sigmas = Vector1(1.0); | ||||||
|  |   auto model = noiseModel::Diagonal::Sigmas(sigmas, false); | ||||||
|  | 
 | ||||||
|  |   auto f0 = | ||||||
|  |       boost::make_shared<BetweenFactor<double>>(X(1), X(2), between0, model); | ||||||
|  |   auto f1 = | ||||||
|  |       boost::make_shared<BetweenFactor<double>>(X(1), X(2), between1, model); | ||||||
|  |   std::vector<NonlinearFactor::shared_ptr> factors{f0, f1}; | ||||||
|  | 
 | ||||||
|  |   MixtureFactor mixtureFactor({X(1), X(2)}, {m1}, factors); | ||||||
|  | 
 | ||||||
|  |   std::string expected = | ||||||
|  |       R"(Hybrid [x1 x2; 1] | ||||||
|  | MixtureFactor | ||||||
|  |  Choice(1)  | ||||||
|  |  0 Leaf Nonlinear factor on 2 keys | ||||||
|  |  1 Leaf Nonlinear factor on 2 keys | ||||||
|  | )"; | ||||||
|  |   EXPECT(assert_print_equal(expected, mixtureFactor)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | // Test the error of the MixtureFactor
 | ||||||
|  | TEST(MixtureFactor, Error) { | ||||||
|  |   DiscreteKey m1(1, 2); | ||||||
|  | 
 | ||||||
|  |   double between0 = 0.0; | ||||||
|  |   double between1 = 1.0; | ||||||
|  | 
 | ||||||
|  |   Vector1 sigmas = Vector1(1.0); | ||||||
|  |   auto model = noiseModel::Diagonal::Sigmas(sigmas, false); | ||||||
|  | 
 | ||||||
|  |   auto f0 = | ||||||
|  |       boost::make_shared<BetweenFactor<double>>(X(1), X(2), between0, model); | ||||||
|  |   auto f1 = | ||||||
|  |       boost::make_shared<BetweenFactor<double>>(X(1), X(2), between1, model); | ||||||
|  |   std::vector<NonlinearFactor::shared_ptr> factors{f0, f1}; | ||||||
|  | 
 | ||||||
|  |   MixtureFactor mixtureFactor({X(1), X(2)}, {m1}, factors); | ||||||
|  | 
 | ||||||
|  |   Values continuousVals; | ||||||
|  |   continuousVals.insert<double>(X(1), 0); | ||||||
|  |   continuousVals.insert<double>(X(2), 1); | ||||||
|  | 
 | ||||||
|  |   AlgebraicDecisionTree<Key> error_tree = mixtureFactor.error(continuousVals); | ||||||
|  | 
 | ||||||
|  |   std::vector<DiscreteKey> discrete_keys = {m1}; | ||||||
|  |   std::vector<double> errors = {0.5, 0}; | ||||||
|  |   AlgebraicDecisionTree<Key> expected_error(discrete_keys, errors); | ||||||
|  | 
 | ||||||
|  |   EXPECT(assert_equal(expected_error, error_tree)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | int main() { | ||||||
|  |   TestResult tr; | ||||||
|  |   return TestRegistry::runAllTests(tr); | ||||||
|  | } | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | @ -27,7 +27,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * A BayesNet is a tree of conditionals, stored in elimination order. |  * A BayesNet is a tree of conditionals, stored in elimination order. | ||||||
|  * @addtogroup inference |  * @ingroup inference | ||||||
|  */ |  */ | ||||||
| template <class CONDITIONAL> | template <class CONDITIONAL> | ||||||
| class BayesNet : public FactorGraph<CONDITIONAL> { | class BayesNet : public FactorGraph<CONDITIONAL> { | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ | ||||||
|  * -------------------------------------------------------------------------- */ |  * -------------------------------------------------------------------------- */ | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @file    BayesTree-inl.h |  * @file    BayesTree-inst.h | ||||||
|  * @brief   Bayes Tree is a tree of cliques of a Bayes Chain |  * @brief   Bayes Tree is a tree of cliques of a Bayes Chain | ||||||
|  * @author  Frank Dellaert |  * @author  Frank Dellaert | ||||||
|  * @author  Michael Kaess |  * @author  Michael Kaess | ||||||
|  |  | ||||||
|  | @ -59,7 +59,7 @@ namespace gtsam { | ||||||
|    * @tparam CLIQUE The type of the clique data structure, defaults to BayesTreeClique, normally do not change this |    * @tparam CLIQUE The type of the clique data structure, defaults to BayesTreeClique, normally do not change this | ||||||
|    * as it is only used when developing special versions of BayesTree, e.g. for ISAM2. |    * as it is only used when developing special versions of BayesTree, e.g. for ISAM2. | ||||||
|    * |    * | ||||||
|    * \addtogroup Multifrontal |    * \ingroup Multifrontal | ||||||
|    * \nosubgrouping |    * \nosubgrouping | ||||||
|    */ |    */ | ||||||
|   template<class CLIQUE> |   template<class CLIQUE> | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| /**
 | /**
 | ||||||
|  * @file EliminatableClusterTree-inst.h |  * @file ClusterTree-inst.h | ||||||
|  * @date Oct 8, 2013 |  * @date Oct 8, 2013 | ||||||
|  * @author Kai Ni |  * @author Kai Ni | ||||||
|  * @author Richard Roberts |  * @author Richard Roberts | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| /**
 | /**
 | ||||||
|  * @file EliminatableClusterTree.h |  * @file ClusterTree.h | ||||||
|  * @date Oct 8, 2013 |  * @date Oct 8, 2013 | ||||||
|  * @author Kai Ni |  * @author Kai Ni | ||||||
|  * @author Richard Roberts |  * @author Richard Roberts | ||||||
|  | @ -139,7 +139,6 @@ class ClusterTree { | ||||||
|              const KeyFormatter& keyFormatter = DefaultKeyFormatter) const; |              const KeyFormatter& keyFormatter = DefaultKeyFormatter) const; | ||||||
| 
 | 
 | ||||||
|   /// @}
 |   /// @}
 | ||||||
| 
 |  | ||||||
|   /// @name Advanced Interface
 |   /// @name Advanced Interface
 | ||||||
|   /// @{
 |   /// @{
 | ||||||
| 
 | 
 | ||||||
|  | @ -169,6 +168,7 @@ class ClusterTree { | ||||||
| 
 | 
 | ||||||
|  protected: |  protected: | ||||||
|   /// @name Details
 |   /// @name Details
 | ||||||
|  |   /// @{
 | ||||||
| 
 | 
 | ||||||
|   /// Assignment operator - makes a deep copy of the tree structure, but only pointers to factors
 |   /// Assignment operator - makes a deep copy of the tree structure, but only pointers to factors
 | ||||||
|   /// are copied, factors are not cloned.
 |   /// are copied, factors are not cloned.
 | ||||||
|  | @ -236,6 +236,7 @@ class EliminatableClusterTree : public ClusterTree<GRAPH> { | ||||||
| 
 | 
 | ||||||
|  protected: |  protected: | ||||||
|   /// @name Details
 |   /// @name Details
 | ||||||
|  |   /// @{
 | ||||||
| 
 | 
 | ||||||
|   /// Assignment operator - makes a deep copy of the tree structure, but only pointers to factors
 |   /// Assignment operator - makes a deep copy of the tree structure, but only pointers to factors
 | ||||||
|   /// are copied, factors are not cloned.
 |   /// are copied, factors are not cloned.
 | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief DotWriter is a helper class for writing graphviz .dot files. |  * @brief DotWriter is a helper class for writing graphviz .dot files. | ||||||
|  * @addtogroup inference |  * @ingroup inference | ||||||
|  */ |  */ | ||||||
| struct GTSAM_EXPORT DotWriter { | struct GTSAM_EXPORT DotWriter { | ||||||
|   double figureWidthInches;   ///< The figure width on paper in inches
 |   double figureWidthInches;   ///< The figure width on paper in inches
 | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ | ||||||
| * -------------------------------------------------------------------------- */ | * -------------------------------------------------------------------------- */ | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| * @file    EliminationTree-inl.h | * @file    EliminationTree-inst.h | ||||||
| * @author  Frank Dellaert | * @author  Frank Dellaert | ||||||
| * @author  Richard Roberts | * @author  Richard Roberts | ||||||
| * @date    Oct 13, 2010 | * @date    Oct 13, 2010 | ||||||
|  |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue