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.
|
||||
configure_file(${PROJECT_SOURCE_DIR}/wrap/matlab.h
|
||||
${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)
|
||||
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.
|
||||
|
||||
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
|
||||
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@)
|
||||
endif()
|
||||
|
||||
if(@GTSAM_USE_SYSTEM_EIGEN@)
|
||||
find_dependency(Eigen3 REQUIRED)
|
||||
endif()
|
||||
|
||||
# Load exports
|
||||
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
|
||||
# Default: Use system's Eigen if found automatically:
|
||||
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)
|
||||
option(GTSAM_USE_SYSTEM_EIGEN "Find and use system-installed Eigen. If 'off', use the one bundled with GTSAM" OFF)
|
||||
|
||||
if(NOT GTSAM_USE_SYSTEM_EIGEN)
|
||||
# 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
|
||||
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>
|
||||
set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "${EIGEN3_INCLUDE_DIR}")
|
||||
# The actual include directory (for BUILD cmake target interface):
|
||||
# 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!
|
||||
# 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))
|
||||
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()
|
||||
|
||||
# The actual include directory (for BUILD cmake target interface):
|
||||
set(GTSAM_EIGEN_INCLUDE_FOR_BUILD "${EIGEN3_INCLUDE_DIR}")
|
||||
else()
|
||||
# Use bundled Eigen include path.
|
||||
# Clear any variables set by FindEigen3
|
||||
|
@ -45,7 +42,20 @@ else()
|
|||
set(GTSAM_EIGEN_INCLUDE_FOR_INSTALL "include/gtsam/3rdparty/Eigen/")
|
||||
|
||||
# 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()
|
||||
|
||||
# Detect Eigen version:
|
||||
|
|
|
@ -26,6 +26,7 @@ if (GTSAM_BUILD_DOCS)
|
|||
gtsam/basis
|
||||
gtsam/discrete
|
||||
gtsam/geometry
|
||||
gtsam/hybrid
|
||||
gtsam/inference
|
||||
gtsam/linear
|
||||
gtsam/navigation
|
||||
|
@ -33,7 +34,6 @@ if (GTSAM_BUILD_DOCS)
|
|||
gtsam/sam
|
||||
gtsam/sfm
|
||||
gtsam/slam
|
||||
gtsam/smart
|
||||
gtsam/symbolic
|
||||
gtsam
|
||||
)
|
||||
|
@ -42,10 +42,12 @@ if (GTSAM_BUILD_DOCS)
|
|||
set(gtsam_unstable_doc_subdirs
|
||||
gtsam_unstable/base
|
||||
gtsam_unstable/discrete
|
||||
gtsam_unstable/dynamics
|
||||
gtsam_unstable/geometry
|
||||
gtsam_unstable/linear
|
||||
gtsam_unstable/nonlinear
|
||||
gtsam_unstable/slam
|
||||
gtsam_unstable/dynamics
|
||||
gtsam_unstable/nonlinear
|
||||
gtsam_unstable/partition
|
||||
gtsam_unstable/slam
|
||||
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="globals" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="dirs" visible="yes" title="" intro=""/>
|
||||
<tab type="examples" visible="yes" title="" intro=""/>
|
||||
</navindex>
|
||||
|
||||
|
|
|
@ -117,12 +117,10 @@ set_target_properties(gtsam PROPERTIES
|
|||
VERSION ${gtsam_version}
|
||||
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
|
||||
target_include_directories(gtsam PUBLIC
|
||||
$<BUILD_INTERFACE:${GTSAM_EIGEN_INCLUDE_FOR_BUILD}>
|
||||
$<INSTALL_INTERFACE:${GTSAM_EIGEN_INCLUDE_FOR_INSTALL}>
|
||||
)
|
||||
target_link_libraries(gtsam PUBLIC Eigen3::Eigen)
|
||||
|
||||
# MKL include dir:
|
||||
if (GTSAM_USE_EIGEN_MKL)
|
||||
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,
|
||||
* we've seen that the fast_pool_allocator can lead to speedups of several
|
||||
* percent.
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
template<typename KEY, typename VALUE>
|
||||
class ConcurrentMap : public ConcurrentMapBase<KEY,VALUE> {
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace gtsam {
|
|||
/**
|
||||
* Disjoint set forest using an STL map data structure underneath
|
||||
* Uses rank compression and union by rank, iterator version
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
template <class KEY>
|
||||
class DSFMap {
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace gtsam {
|
|||
* 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
|
||||
* Uses rank compression but not union by rank :-(
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
class GTSAM_EXPORT DSFBase {
|
||||
|
||||
|
@ -59,7 +59,7 @@ public:
|
|||
|
||||
/**
|
||||
* DSFVector additionally keeps a vector of keys to support more expensive operations
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
class GTSAM_EXPORT DSFVector: public DSFBase {
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace gtsam {
|
|||
* 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
|
||||
* percent.
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
template<typename VALUE>
|
||||
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,
|
||||
* we've seen that the fast_pool_allocator can lead to speedups of several
|
||||
* percent.
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
template<typename KEY, typename VALUE>
|
||||
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
|
||||
* 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 %.
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
template<typename 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.
|
||||
* The particular allocator depends on GTSAM's cmake configuration.
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
template <typename T>
|
||||
using FastVector =
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace gtsam {
|
|||
* matrix view. firstBlock() determines the block that appears to have index 0 for all operations
|
||||
* (except re-setting firstBlock()).
|
||||
*
|
||||
* @addtogroup base */
|
||||
* @ingroup base */
|
||||
class GTSAM_EXPORT SymmetricBlockMatrix
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace gtsam {
|
|||
* tests and in generic algorithms.
|
||||
*
|
||||
* 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()
|
||||
*/
|
||||
template <class T>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* @brief Base exception type that uses tbb_allocator if GTSAM is compiled with TBB
|
||||
* @author Richard Roberts
|
||||
* @date Aug 21, 2010
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
|
||||
#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
|
||||
* the matrix (i.e. one after the last true row index).
|
||||
*
|
||||
* @addtogroup base */
|
||||
* @ingroup base */
|
||||
class GTSAM_EXPORT VerticalBlockMatrix
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <type_traits>
|
||||
|
||||
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>
|
||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ namespace gtsam {
|
|||
size_t id_;
|
||||
size_t t_;
|
||||
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 tMax_;
|
||||
size_t tMin_;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* @brief Functions for handling type information
|
||||
* @author Varun Agrawal
|
||||
* @date May 18, 2020
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
|
||||
#include <gtsam/base/types.h>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* @brief Typedefs for easier changing of types
|
||||
* @author Richard Roberts
|
||||
* @date Aug 21, 2010
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
|
|
@ -78,6 +78,8 @@ using Weights = Eigen::Matrix<double, 1, -1>; /* 1xN vector */
|
|||
* @tparam M Size of the identity matrix.
|
||||
* @param w The weights of the polynomial.
|
||||
* @return Mx(M*N) kronecker product [w(0)*I, w(1)*I, ..., w(N-1)*I]
|
||||
*
|
||||
* @ingroup basis
|
||||
*/
|
||||
template <size_t M>
|
||||
Matrix kroneckerProductIdentity(const Weights& w) {
|
||||
|
@ -90,7 +92,10 @@ Matrix kroneckerProductIdentity(const Weights& w) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/// CRTP Base class for function bases
|
||||
/**
|
||||
* CRTP Base class for function bases
|
||||
* @ingroup basis
|
||||
*/
|
||||
template <typename DERIVED>
|
||||
class Basis {
|
||||
public:
|
||||
|
|
|
@ -32,6 +32,8 @@ namespace gtsam {
|
|||
*
|
||||
* Example, degree 8 Chebyshev polynomial measured at x=0.5:
|
||||
* EvaluationFactor<Chebyshev2> factor(key, measured, model, 8, 0.5);
|
||||
*
|
||||
* @ingroup basis
|
||||
*/
|
||||
template <class BASIS>
|
||||
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 M: Size of the evaluated state vector.
|
||||
*
|
||||
* @ingroup basis
|
||||
*/
|
||||
template <class BASIS, int M>
|
||||
class VectorEvaluationFactor
|
||||
|
@ -149,6 +153,8 @@ class VectorEvaluationFactor
|
|||
* VectorComponentFactor<BASIS, P> controlPrior(key, measured, model,
|
||||
* N, i, t, a, b);
|
||||
* where N is the degree and i is the component index.
|
||||
*
|
||||
* @ingroup basis
|
||||
*/
|
||||
template <class BASIS, size_t P>
|
||||
class VectorComponentFactor
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file ParamaterMatrix.h
|
||||
* @file ParameterMatrix.h
|
||||
* @brief Define ParameterMatrix class which is used to store values at
|
||||
* interpolation points.
|
||||
* @author Varun Agrawal, Frank Dellaert
|
||||
|
|
|
@ -31,6 +31,8 @@ namespace gtsam {
|
|||
* Algebraic Decision Trees fix the range to double
|
||||
* Just has some nice constructors and some syntactic sugar
|
||||
* TODO: consider eliminating this class altogether?
|
||||
*
|
||||
* @ingroup discrete
|
||||
*/
|
||||
template <typename L>
|
||||
class GTSAM_EXPORT AlgebraicDecisionTree : public DecisionTree<L, double> {
|
||||
|
@ -156,9 +158,9 @@ namespace gtsam {
|
|||
}
|
||||
|
||||
/// print method customized to value type `double`.
|
||||
void print(const std::string& s,
|
||||
const typename Base::LabelFormatter& labelFormatter =
|
||||
&DefaultFormatter) const {
|
||||
void print(const std::string& s = "",
|
||||
const typename Base::LabelFormatter& labelFormatter =
|
||||
&DefaultFormatter) const {
|
||||
auto valueFormatter = [](const double& v) {
|
||||
return (boost::format("%4.8g") % v).str();
|
||||
};
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace gtsam {
|
|||
* An assignment from labels to value index (size_t).
|
||||
* Assigns to each label a value. Implemented as a simple map.
|
||||
* A discrete factor takes an Assignment and returns a value.
|
||||
* @ingroup discrete
|
||||
*/
|
||||
template <class L>
|
||||
class Assignment : public std::map<L, size_t> {
|
||||
|
|
|
@ -38,6 +38,8 @@ namespace gtsam {
|
|||
* Decision Tree
|
||||
* L = label for variables
|
||||
* Y = function range (any algebra), e.g., bool, int, double
|
||||
*
|
||||
* @ingroup discrete
|
||||
*/
|
||||
template<typename L, typename Y>
|
||||
class DecisionTree {
|
||||
|
|
|
@ -36,7 +36,9 @@ namespace gtsam {
|
|||
class DiscreteConditional;
|
||||
|
||||
/**
|
||||
* A discrete probabilistic factor
|
||||
* A discrete probabilistic factor.
|
||||
*
|
||||
* @ingroup discrete
|
||||
*/
|
||||
class GTSAM_EXPORT DecisionTreeFactor : public DiscreteFactor,
|
||||
public AlgebraicDecisionTree<Key> {
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* A Bayes net made from discrete conditional distributions.
|
||||
* @addtogroup discrete
|
||||
* @ingroup discrete
|
||||
*/
|
||||
class GTSAM_EXPORT DiscreteBayesNet: public BayesNet<DiscreteConditional> {
|
||||
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
|
||||
: public BayesTree<DiscreteBayesTreeClique> {
|
||||
private:
|
||||
|
|
|
@ -32,6 +32,8 @@ namespace gtsam {
|
|||
/**
|
||||
* Discrete Conditional Density
|
||||
* Derives from DecisionTreeFactor
|
||||
*
|
||||
* @ingroup discrete
|
||||
*/
|
||||
class GTSAM_EXPORT DiscreteConditional
|
||||
: public DecisionTreeFactor,
|
||||
|
|
|
@ -27,6 +27,8 @@ namespace gtsam {
|
|||
/**
|
||||
* A prior probability on a set of discrete variables.
|
||||
* Derives from DiscreteConditional
|
||||
*
|
||||
* @ingroup discrete
|
||||
*/
|
||||
class GTSAM_EXPORT DiscreteDistribution : public DiscreteConditional {
|
||||
public:
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
|
||||
namespace gtsam {
|
||||
|
||||
/**
|
||||
* @brief Elimination tree for discrete factors.
|
||||
* @ingroup discrete
|
||||
*/
|
||||
class GTSAM_EXPORT DiscreteEliminationTree :
|
||||
public EliminationTree<DiscreteBayesNet, DiscreteFactorGraph>
|
||||
{
|
||||
|
|
|
@ -31,6 +31,8 @@ class DiscreteConditional;
|
|||
/**
|
||||
* Base class for discrete probabilistic factors
|
||||
* The most general one is the derived DecisionTreeFactor
|
||||
*
|
||||
* @ingroup discrete
|
||||
*/
|
||||
class GTSAM_EXPORT DiscreteFactor: public Factor {
|
||||
|
||||
|
|
|
@ -40,7 +40,14 @@ class DiscreteEliminationTree;
|
|||
class DiscreteBayesTree;
|
||||
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>
|
||||
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.
|
||||
* Factor == DiscreteFactor
|
||||
* @ingroup discrete
|
||||
*/
|
||||
class GTSAM_EXPORT DiscreteFactorGraph
|
||||
: public FactorGraph<DiscreteFactor>,
|
||||
|
|
|
@ -44,7 +44,8 @@ namespace gtsam {
|
|||
* 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.
|
||||
*
|
||||
* \addtogroup Multifrontal
|
||||
* \ingroup Multifrontal
|
||||
* @ingroup discrete
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT DiscreteJunctionTree :
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace gtsam {
|
|||
/**
|
||||
* Key type for discrete variables.
|
||||
* Includes Key and cardinality.
|
||||
* @ingroup discrete
|
||||
*/
|
||||
using DiscreteKey = std::pair<Key,size_t>;
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ class DiscreteBayesNet;
|
|||
|
||||
/**
|
||||
* @brief DiscreteLookupTable table for max-product
|
||||
* @ingroup discrete
|
||||
*
|
||||
* Inherits from discrete conditional for convenience, but is not normalized.
|
||||
* Is used in the max-product algorithm.
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* A class for computing marginals of variables in a DiscreteFactorGraph
|
||||
* @ingroup discrete
|
||||
*/
|
||||
class DiscreteMarginals {
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace gtsam {
|
|||
* 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
|
||||
* the new class DiscreteValue, as the variable's type (domain)
|
||||
* @ingroup discrete
|
||||
*/
|
||||
class GTSAM_EXPORT DiscreteValues : public Assignment<Key> {
|
||||
public:
|
||||
|
|
|
@ -48,6 +48,8 @@ namespace gtsam {
|
|||
* (E|T,L) = "F F F 1"
|
||||
* X|E = "95/5 2/98"
|
||||
* (D|E,B) = "9/1 2/8 3/7 1/9"
|
||||
*
|
||||
* @ingroup discrete
|
||||
*/
|
||||
class GTSAM_EXPORT Signature {
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -63,7 +63,7 @@ void calibrateJacobians(const Cal& calibration, const Point2& pn,
|
|||
|
||||
/**
|
||||
* @brief Common base class for all calibration models.
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT Cal3 {
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* @brief Calibration used by Bundler
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT Cal3Bundler : public Cal3 {
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace gtsam {
|
|||
* @brief Calibration of a camera with radial distortion that also supports
|
||||
* Lie-group behaviors for optimization.
|
||||
* \sa Cal3DS2_Base
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT Cal3DS2 : public Cal3DS2_Base {
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* @brief Calibration of a camera with radial distortion
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*
|
||||
* Uses same distortionmodel as OpenCV, with
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* @brief Calibration of a fisheye camera
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*
|
||||
* Uses same distortionmodel as OpenCV, with
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -30,7 +30,7 @@ namespace gtsam {
|
|||
/**
|
||||
* @brief Calibration of a omni-directional camera with mirror + lens radial
|
||||
* distortion
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*
|
||||
* Similar to Cal3DS2, does distortion but has additional mirror parameter xi
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -28,7 +28,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* @brief The most common 5DOF 3D->2D calibration
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT Cal3_S2 : public Cal3 {
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* @brief The most common 5DOF 3D->2D calibration, stereo version
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
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>;
|
||||
|
||||
/// @name Standard Constructors
|
||||
/// @
|
||||
/// @{
|
||||
|
||||
/// default calibration leaves coordinates unchanged
|
||||
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_S2(fov, w, h), b_(b) {}
|
||||
|
||||
/// @}
|
||||
|
||||
/**
|
||||
* Convert intrinsic coordinates xy to image coordinates uv, fixed derivaitves
|
||||
* @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); }
|
||||
|
||||
/// @}
|
||||
/// @name Testable
|
||||
/// @{
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ private:
|
|||
|
||||
/**
|
||||
* A pinhole camera class that has a Pose3, functions as base class for all pinhole cameras
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT PinholeBase {
|
||||
|
@ -241,7 +241,7 @@ private:
|
|||
* A Calibrated camera class [R|-R't], calibration K=I.
|
||||
* If calibration is known, it is more computationally efficient
|
||||
* to calibrate the measurements rather than try to predict in pixels.
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
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)
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT Line3 {
|
||||
|
|
|
@ -133,8 +133,6 @@ public:
|
|||
inline double distance() const {
|
||||
return d_;
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
template<> struct traits<OrientedPlane3> : public internal::Manifold<
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace gtsam {
|
|||
/**
|
||||
* A pinhole camera class that has a Pose3 and a Calibration.
|
||||
* Use PinholePose if you will not be optimizing for Calibration
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
template<typename Calibration>
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* A pinhole camera class that has a Pose3 and a *fixed* Calibration.
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
template<typename CALIBRATION>
|
||||
|
@ -236,7 +236,7 @@ public:
|
|||
* A pinhole camera class that has a Pose3 and a *fixed* Calibration.
|
||||
* Instead of using this class, one might consider calibrating the measurements
|
||||
* and using CalibratedCamera, which would then be faster.
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
template<typename CALIBRATION>
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* A 2D pose (Point2,Rot2)
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class Pose2: public LieGroup<Pose2, 3> {
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
namespace gtsam {
|
||||
|
||||
using std::vector;
|
||||
using Point3Pairs = vector<Point3Pair>;
|
||||
|
||||
/** instantiate concept checks */
|
||||
GTSAM_CONCEPT_POSE_INST(Pose3)
|
||||
|
|
|
@ -31,7 +31,7 @@ class Pose2;
|
|||
|
||||
/**
|
||||
* A 3D pose (R,t) : (Rot3,Point3)
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
static boost::optional<Pose3> Align(const Matrix& a, const Matrix& b);
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace gtsam {
|
|||
/**
|
||||
* Rotation matrix
|
||||
* NOTE: the angle theta is in radians unless explicitly stated
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT Rot2 : public LieGroup<Rot2, 1> {
|
||||
|
@ -86,7 +86,7 @@ namespace gtsam {
|
|||
static Rot2 atan2(double y, double x);
|
||||
|
||||
/**
|
||||
* Random, generates random angle \in [-p,pi]
|
||||
* Random, generates random angle \f$\in\f$ [-pi,pi]
|
||||
* Example:
|
||||
* std::mt19937 engine(42);
|
||||
* Unit3 unit = Unit3::Random(engine);
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace gtsam {
|
|||
* @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
|
||||
* if it is defined.
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
*/
|
||||
class GTSAM_EXPORT Rot3 : public LieGroup<Rot3, 3> {
|
||||
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)) {}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* std::mt19937 engine(42);
|
||||
* 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)
|
||||
* -> 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);
|
||||
|
||||
|
|
|
@ -121,7 +121,8 @@ class SO : public LieGroup<SO<N>, internal::DimensionSO(N)> {
|
|||
/// currently only defined for SO3.
|
||||
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.
|
||||
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:
|
||||
* 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
|
||||
|
|
|
@ -120,7 +120,7 @@ class GTSAM_EXPORT Similarity3 : public LieGroup<Similarity3, 7> {
|
|||
/**
|
||||
* 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.
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace gtsam {
|
|||
* Empty calibration. Only needed to play well with other cameras
|
||||
* (e.g., when templating functions wrt cameras), since other cameras
|
||||
* have constuctors in the form ‘camera(pose,calibration)’
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT EmptyCal {
|
||||
|
@ -64,7 +64,7 @@ class GTSAM_EXPORT EmptyCal {
|
|||
/**
|
||||
* 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
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT SphericalCamera {
|
||||
|
@ -82,7 +82,6 @@ class GTSAM_EXPORT SphericalCamera {
|
|||
EmptyCal::shared_ptr emptyCal_;
|
||||
|
||||
public:
|
||||
/// @}
|
||||
/// @name Standard Constructors
|
||||
/// @{
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ private:
|
|||
|
||||
/**
|
||||
* A stereo camera class, parameterize by left camera pose and stereo calibration
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
*/
|
||||
class GTSAM_EXPORT StereoCamera {
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* A 2D stereo point, v will be same for rectified images
|
||||
* @addtogroup geometry
|
||||
* @ingroup geometry
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT StereoPoint2 {
|
||||
|
|
|
@ -1123,7 +1123,7 @@ class StereoCamera {
|
|||
#include <gtsam/geometry/triangulation.h>
|
||||
class TriangulationResult {
|
||||
enum Status { VALID, DEGENERATE, BEHIND_CAMERA, OUTLIER, FAR_POINT };
|
||||
Status status;
|
||||
gtsam::TriangulationResult::Status status;
|
||||
TriangulationResult(const gtsam::Point3& p);
|
||||
const gtsam::Point3& get() const;
|
||||
static gtsam::TriangulationResult Degenerate();
|
||||
|
@ -1142,7 +1142,7 @@ class TriangulationParameters {
|
|||
bool enableEPI;
|
||||
double landmarkDistanceThreshold;
|
||||
double dynamicOutlierRejectionThreshold;
|
||||
SharedNoiseModel noiseModel;
|
||||
gtsam::SharedNoiseModel noiseModel;
|
||||
TriangulationParameters(const double rankTolerance = 1.0,
|
||||
const bool enableEPI = false,
|
||||
double landmarkDistanceThreshold = -1,
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* @file global_includes.h
|
||||
* @brief Included from all GTSAM files
|
||||
* @author Richard Roberts
|
||||
* @addtogroup base
|
||||
* @ingroup base
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
|
||||
\defgroup LinearSolving Solving of sparse linear systems with least-squares
|
||||
@{
|
||||
@{ @}
|
||||
|
||||
\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 SLAM Useful SLAM components
|
||||
\defgroup base Base
|
||||
@{ @}
|
||||
|
||||
*/
|
||||
\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_;
|
||||
}
|
||||
|
||||
/* *******************************************************************************/
|
||||
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
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace gtsam {
|
|||
* where i indexes the components and k_i is a component-wise normalization
|
||||
* constant.
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT GaussianMixture
|
||||
: public HybridFactor,
|
||||
|
@ -143,6 +144,26 @@ class GTSAM_EXPORT GaussianMixture
|
|||
/// Getter for the underlying Conditionals DecisionTree
|
||||
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
|
||||
* `decisionTree`.
|
||||
|
|
|
@ -95,4 +95,24 @@ GaussianMixtureFactor::Sum GaussianMixtureFactor::asGaussianFactorGraphTree()
|
|||
};
|
||||
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
|
||||
|
|
|
@ -20,15 +20,19 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <gtsam/discrete/AlgebraicDecisionTree.h>
|
||||
#include <gtsam/discrete/DecisionTree.h>
|
||||
#include <gtsam/discrete/DiscreteKey.h>
|
||||
#include <gtsam/discrete/DiscreteValues.h>
|
||||
#include <gtsam/hybrid/HybridGaussianFactor.h>
|
||||
#include <gtsam/linear/GaussianFactor.h>
|
||||
#include <gtsam/linear/VectorValues.h>
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
class GaussianFactorGraph;
|
||||
|
||||
// Needed for wrapper.
|
||||
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
|
||||
* of discrete variables indexes to the continuous gaussian distribution.
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT GaussianMixtureFactor : public HybridFactor {
|
||||
public:
|
||||
|
@ -125,6 +130,26 @@ class GTSAM_EXPORT GaussianMixtureFactor : public HybridFactor {
|
|||
*/
|
||||
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.
|
||||
friend Sum &operator+=(Sum &sum, const GaussianMixtureFactor &factor) {
|
||||
sum = factor.add(sum);
|
||||
|
|
|
@ -232,4 +232,45 @@ VectorValues HybridBayesNet::optimize(const DiscreteValues &assignment) const {
|
|||
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
|
||||
|
|
|
@ -29,6 +29,8 @@ namespace gtsam {
|
|||
/**
|
||||
* A hybrid Bayes net is a collection of HybridConditionals, which can have
|
||||
* discrete conditionals, Gaussian mixtures, or pure Gaussian conditionals.
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT HybridBayesNet : public BayesNet<HybridConditional> {
|
||||
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.
|
||||
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:
|
||||
|
|
|
@ -34,8 +34,11 @@ class HybridConditional;
|
|||
class VectorValues;
|
||||
|
||||
/* ************************************************************************* */
|
||||
/** A clique in a HybridBayesTree
|
||||
/**
|
||||
* @brief A clique in a HybridBayesTree
|
||||
* which is a HybridConditional internally.
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT HybridBayesTreeClique
|
||||
: public BayesTreeCliqueBase<HybridBayesTreeClique,
|
||||
|
|
|
@ -54,6 +54,8 @@ namespace gtsam {
|
|||
*
|
||||
* A great reference to the type-erasure pattern is Eduaado Madrid's CppCon
|
||||
* talk (https://www.youtube.com/watch?v=s082Qmd_nHs).
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT HybridConditional
|
||||
: public HybridFactor,
|
||||
|
|
|
@ -28,6 +28,8 @@ namespace gtsam {
|
|||
* A HybridDiscreteFactor is a thin container for DiscreteFactor, which allows
|
||||
* us to hide the implementation of DiscreteFactor and thus avoid diamond
|
||||
* inheritance.
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT HybridDiscreteFactor : public HybridFactor {
|
||||
private:
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* Elimination Tree type for Hybrid
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT HybridEliminationTree
|
||||
: public EliminationTree<HybridBayesNet, HybridGaussianFactorGraph> {
|
||||
|
|
|
@ -40,6 +40,8 @@ DiscreteKeys CollectDiscreteKeys(const DiscreteKeys &key1,
|
|||
* - HybridDiscreteFactor
|
||||
* - GaussianMixtureFactor
|
||||
* - GaussianMixture
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT HybridFactor : public Factor {
|
||||
private:
|
||||
|
|
|
@ -27,6 +27,8 @@ namespace gtsam {
|
|||
* 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
|
||||
* HybridFactor and GaussianFactor.
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT HybridGaussianFactor : public HybridFactor {
|
||||
private:
|
||||
|
|
|
@ -39,7 +39,14 @@ class DecisionTreeFactor;
|
|||
|
||||
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
|
||||
std::pair<boost::shared_ptr<HybridConditional>, HybridFactor::shared_ptr>
|
||||
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.
|
||||
* Everything inside needs to be hybrid factor or hybrid conditional.
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT HybridGaussianFactorGraph
|
||||
: public HybridFactorGraph,
|
||||
|
@ -120,13 +129,13 @@ class GTSAM_EXPORT HybridGaussianFactorGraph
|
|||
void add(JacobianFactor&& factor);
|
||||
|
||||
/// 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.
|
||||
void add(DecisionTreeFactor&& factor);
|
||||
|
||||
/// 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
|
||||
|
|
|
@ -38,6 +38,35 @@ HybridGaussianISAM::HybridGaussianISAM() {}
|
|||
HybridGaussianISAM::HybridGaussianISAM(const HybridBayesTree& 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(
|
||||
const HybridGaussianFactorGraph& newFactors,
|
||||
|
@ -54,7 +83,7 @@ void HybridGaussianISAM::updateInternal(
|
|||
}
|
||||
|
||||
// Add the removed top and the new factors
|
||||
FactorGraphType factors;
|
||||
HybridGaussianFactorGraph factors;
|
||||
factors += bn;
|
||||
factors += newFactors;
|
||||
|
||||
|
@ -63,32 +92,12 @@ void HybridGaussianISAM::updateInternal(
|
|||
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);
|
||||
|
||||
Ordering elimination_ordering;
|
||||
if (ordering) {
|
||||
elimination_ordering = *ordering;
|
||||
} else {
|
||||
elimination_ordering = Ordering::ColamdConstrainedLast(
|
||||
index,
|
||||
KeyVector(newKeysDiscreteLast.begin(), newKeysDiscreteLast.end()),
|
||||
true);
|
||||
elimination_ordering = GetOrdering(factors, newFactors);
|
||||
}
|
||||
|
||||
// eliminate all factors (top, added, orphans) into a new Bayes tree
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
|
||||
namespace gtsam {
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @ingroup hybrid
|
||||
*/
|
||||
class GTSAM_EXPORT HybridGaussianISAM : public ISAM<HybridBayesTree> {
|
||||
public:
|
||||
typedef ISAM<HybridBayesTree> Base;
|
||||
|
@ -67,6 +72,17 @@ class GTSAM_EXPORT HybridGaussianISAM : public ISAM<HybridBayesTree> {
|
|||
const boost::optional<Ordering>& ordering = boost::none,
|
||||
const HybridBayesTree::Eliminate& function =
|
||||
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
|
||||
|
|
|
@ -45,7 +45,8 @@ class HybridEliminationTree;
|
|||
* EliminationTree, except that in the JunctionTree, at each node multiple
|
||||
* variables are eliminated at a time.
|
||||
*
|
||||
* \addtogroup Multifrontal
|
||||
* \ingroup Multifrontal
|
||||
* \ingroup hybrid
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class GTSAM_EXPORT HybridJunctionTree
|
||||
|
|
|
@ -107,8 +107,12 @@ class MixtureFactor : public HybridFactor {
|
|||
std::copy(f->keys().begin(), f->keys().end(),
|
||||
std::inserter(factor_keys_set, factor_keys_set.end()));
|
||||
|
||||
nonlinear_factors.push_back(
|
||||
boost::dynamic_pointer_cast<NonlinearFactor>(f));
|
||||
if (auto nf = 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);
|
||||
|
||||
|
@ -121,6 +125,22 @@ class MixtureFactor : public HybridFactor {
|
|||
|
||||
~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.
|
||||
*
|
||||
|
@ -149,7 +169,7 @@ class MixtureFactor : public HybridFactor {
|
|||
|
||||
/// print to stdout
|
||||
void print(
|
||||
const std::string& s = "MixtureFactor",
|
||||
const std::string& s = "",
|
||||
const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
|
||||
std::cout << (s.empty() ? "" : s + " ");
|
||||
Base::print("", keyFormatter);
|
||||
|
|
|
@ -78,15 +78,51 @@ TEST(GaussianMixture, Equals) {
|
|||
GaussianMixture::Conditionals conditionals(
|
||||
{m1},
|
||||
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:
|
||||
DiscreteValues mode;
|
||||
mode[m1.first] = 1;
|
||||
auto actual = mixtureFactor(mode);
|
||||
auto actual = mixture(mode);
|
||||
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() {
|
||||
TestResult tr;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file GaussianMixtureFactor.cpp
|
||||
* @file testGaussianMixtureFactor.cpp
|
||||
* @brief Unit tests for GaussianMixtureFactor
|
||||
* @author Varun Agrawal
|
||||
* @author Fan Jiang
|
||||
|
@ -135,7 +135,7 @@ TEST(GaussianMixtureFactor, Printing) {
|
|||
EXPECT(assert_print_equal(expected, mixtureFactor));
|
||||
}
|
||||
|
||||
TEST_UNSAFE(GaussianMixtureFactor, GaussianMixture) {
|
||||
TEST(GaussianMixtureFactor, GaussianMixture) {
|
||||
KeyVector keys;
|
||||
keys.push_back(X(0));
|
||||
keys.push_back(X(1));
|
||||
|
@ -151,6 +151,45 @@ TEST_UNSAFE(GaussianMixtureFactor, GaussianMixture) {
|
|||
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() {
|
||||
TestResult tr;
|
||||
|
|
|
@ -183,6 +183,61 @@ TEST(HybridBayesNet, OptimizeMultifrontal) {
|
|||
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(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.
|
||||
* @addtogroup inference
|
||||
* @ingroup inference
|
||||
*/
|
||||
template <class 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
|
||||
* @author Frank Dellaert
|
||||
* @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
|
||||
* as it is only used when developing special versions of BayesTree, e.g. for ISAM2.
|
||||
*
|
||||
* \addtogroup Multifrontal
|
||||
* \ingroup Multifrontal
|
||||
* \nosubgrouping
|
||||
*/
|
||||
template<class CLIQUE>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* @file EliminatableClusterTree-inst.h
|
||||
* @file ClusterTree-inst.h
|
||||
* @date Oct 8, 2013
|
||||
* @author Kai Ni
|
||||
* @author Richard Roberts
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* @file EliminatableClusterTree.h
|
||||
* @file ClusterTree.h
|
||||
* @date Oct 8, 2013
|
||||
* @author Kai Ni
|
||||
* @author Richard Roberts
|
||||
|
@ -139,7 +139,6 @@ class ClusterTree {
|
|||
const KeyFormatter& keyFormatter = DefaultKeyFormatter) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Advanced Interface
|
||||
/// @{
|
||||
|
||||
|
@ -169,6 +168,7 @@ class ClusterTree {
|
|||
|
||||
protected:
|
||||
/// @name Details
|
||||
/// @{
|
||||
|
||||
/// Assignment operator - makes a deep copy of the tree structure, but only pointers to factors
|
||||
/// are copied, factors are not cloned.
|
||||
|
@ -236,6 +236,7 @@ class EliminatableClusterTree : public ClusterTree<GRAPH> {
|
|||
|
||||
protected:
|
||||
/// @name Details
|
||||
/// @{
|
||||
|
||||
/// Assignment operator - makes a deep copy of the tree structure, but only pointers to factors
|
||||
/// are copied, factors are not cloned.
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* @brief DotWriter is a helper class for writing graphviz .dot files.
|
||||
* @addtogroup inference
|
||||
* @ingroup inference
|
||||
*/
|
||||
struct GTSAM_EXPORT DotWriter {
|
||||
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 Richard Roberts
|
||||
* @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