Merge branch 'hybrid/error' into hybrid/tests

release/4.3a0
Varun Agrawal 2022-11-04 15:20:45 -04:00
commit 5bfce89b65
418 changed files with 15438 additions and 9705 deletions

View File

@ -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")

View File

@ -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,

View File

@ -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)

View File

@ -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)

View File

@ -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:

View File

@ -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/partition
gtsam_unstable/slam gtsam_unstable/slam
gtsam_unstable/dynamics
gtsam_unstable gtsam_unstable
) )

File diff suppressed because it is too large Load Diff

View File

@ -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>

View File

@ -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})

View File

@ -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> {

View File

@ -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 {

View File

@ -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 {

View File

@ -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> {

View File

@ -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>,

View File

@ -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>,

View File

@ -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 =

View File

@ -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:

View File

@ -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>

View File

@ -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

View File

@ -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:

View File

@ -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;
} }

View File

@ -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_;

View File

@ -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>

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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,7 +158,7 @@ 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) {

View File

@ -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> {

View File

@ -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 {

View File

@ -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> {

View File

@ -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:

View File

@ -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:

View File

@ -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,

View File

@ -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:

View File

@ -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>
{ {

View File

@ -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 {

View File

@ -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>,

View File

@ -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 :

View File

@ -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>;

View File

@ -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.

View File

@ -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 {

View File

@ -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:

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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
/// @{ /// @{

View File

@ -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 {

View File

@ -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 {

View File

@ -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<

View File

@ -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>

View File

@ -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>

View File

@ -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> {

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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.

View File

@ -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
/// @{ /// @{

View File

@ -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 {

View File

@ -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 {

View File

@ -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,

View File

@ -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

View File

@ -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 basis Basis
@{ @}
\defgroup discrete Discrete
@{ @}
\defgroup geometry Geometry
@{
Geometric primitives.
@} @}
\defgroup SLAM Useful SLAM components \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
@{ @} @{ @}
*/ */

View File

@ -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

View File

@ -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`.

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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:

View File

@ -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,

View File

@ -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,

View File

@ -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:

View File

@ -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> {

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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);
}
/* ************************************************************************* */

View File

@ -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> {

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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