Working on ISAM
parent
735c7a8650
commit
60d5feb5cf
|
|
@ -31,6 +31,7 @@ namespace gtsam {
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
template<class FACTOR> class FactorGraph;
|
template<class FACTOR> class FactorGraph;
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* Bayes tree
|
* Bayes tree
|
||||||
* @tparam CONDITIONAL The type of the conditional densities, i.e. the type of node in the underlying Bayes chain,
|
* @tparam CONDITIONAL The type of the conditional densities, i.e. the type of node in the underlying Bayes chain,
|
||||||
|
|
@ -256,4 +257,23 @@ namespace gtsam {
|
||||||
|
|
||||||
}; // BayesTree
|
}; // BayesTree
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class CLIQUE>
|
||||||
|
class BayesTreeOrphanWrapper : public CLIQUE::FactorType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef CLIQUE CliqueType;
|
||||||
|
typedef typename CLIQUE::FactorType Base;
|
||||||
|
|
||||||
|
boost::shared_ptr<CliqueType> clique;
|
||||||
|
|
||||||
|
BayesTreeOrphanWrapper(const boost::shared_ptr<CliqueType>& clique) :
|
||||||
|
clique(clique)
|
||||||
|
{
|
||||||
|
// Store parent keys in our base type factor so that eliminating those parent keys will pull
|
||||||
|
// this subtree into the elimination.
|
||||||
|
keys_.assign(clique->conditional()->beginParents(), clique->conditional()->endParents());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} /// namespace gtsam
|
} /// namespace gtsam
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* 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 ISAM-inl.h
|
||||||
|
* @brief Incremental update functionality (iSAM) for BayesTree.
|
||||||
|
* @author Michael Kaess
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtsam/inference/ISAM.h>
|
||||||
|
|
||||||
|
namespace gtsam {
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class BAYESTREE>
|
||||||
|
void ISAM<BAYESTREE>::update_internal(const FactorGraphType& newFactors, Cliques& orphans, const Eliminate& function)
|
||||||
|
{
|
||||||
|
// Remove the contaminated part of the Bayes tree
|
||||||
|
// Throw exception if disconnected
|
||||||
|
BayesNetType bn;
|
||||||
|
if (!this->empty()) {
|
||||||
|
const FastSet<Key> newFactorKeys = newFactors.keys();
|
||||||
|
this->removeTop(std::vector<Key>(newFactorKeys.begin(), newFactorKeys.end()), bn, orphans);
|
||||||
|
if (bn.empty())
|
||||||
|
throw std::runtime_error(
|
||||||
|
"ISAM::update_internal(): no variables in common between existing Bayes tree and incoming factors!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the removed top and the new factors
|
||||||
|
FactorGraphType factors;
|
||||||
|
factors += bn;
|
||||||
|
factors += newFactors;
|
||||||
|
|
||||||
|
// Add the orphaned subtrees
|
||||||
|
BOOST_FOREACH(const sharedClique& orphan, orphans)
|
||||||
|
factors += boost::make_shared<BayesTreeOrphanWrapper<Clique> >(orphan);
|
||||||
|
|
||||||
|
// eliminate into a Bayes net
|
||||||
|
Base bayesTree = *factors.eliminateMultifrontal(boost::none, function);
|
||||||
|
this->roots_.insert(this->roots_.end(), bayesTree.roots().begin(), bayesTree.roots().end());
|
||||||
|
this->nodes_.insert(bayesTree.nodes().begin(), bayesTree.nodes().end());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class BAYESTREE>
|
||||||
|
void ISAM<BAYESTREE>::update(const FactorGraphType& newFactors, const Eliminate& function)
|
||||||
|
{
|
||||||
|
Cliques orphans;
|
||||||
|
this->update_internal(newFactors, orphans, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/// namespace gtsam
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* 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 ISAM.h
|
||||||
|
* @brief Incremental update functionality (iSAM) for BayesTree.
|
||||||
|
* @author Michael Kaess
|
||||||
|
*/
|
||||||
|
|
||||||
|
// \callgraph
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace gtsam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Bayes tree with an update methods that implements the iSAM algorithm.
|
||||||
|
* Given a set of new factors, it re-eliminates the invalidated part of the tree.
|
||||||
|
* \nosubgrouping
|
||||||
|
*/
|
||||||
|
template<class BAYESTREE>
|
||||||
|
class ISAM: public BAYESTREE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef BAYESTREE Base;
|
||||||
|
typedef typename Base::FactorGraphType FactorGraphType;
|
||||||
|
typedef typename Base::Cliques Cliques;
|
||||||
|
typedef typename Base::Eliminate Eliminate;
|
||||||
|
typedef typename Base::EliminationTraits EliminationTraits;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// @name Standard Constructors
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/** Create an empty Bayes Tree */
|
||||||
|
ISAM() {}
|
||||||
|
|
||||||
|
/** Copy constructor */
|
||||||
|
ISAM(const Base& bayesTree) : Base(bayesTree) {}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
/// @name Advanced Interface Interface
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update the Bayes tree with a set of new factors, typically derived from measurements
|
||||||
|
* @param newFactors is a factor graph that contains the new factors
|
||||||
|
* @param function an elimination routine
|
||||||
|
*/
|
||||||
|
void update(const FactorGraphType& newFactors, const Eliminate& function = EliminationTraits::DefaultEliminate);
|
||||||
|
|
||||||
|
/** update_internal provides access to list of orphans for drawing purposes */
|
||||||
|
void update_internal(const FactorGraphType& newFactors, Cliques& orphans,
|
||||||
|
const Eliminate& function = EliminationTraits::DefaultEliminate);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}/// namespace gtsam
|
||||||
|
|
@ -177,8 +177,18 @@ namespace gtsam {
|
||||||
// Gather factors
|
// Gather factors
|
||||||
FactorGraphType gatheredFactors;
|
FactorGraphType gatheredFactors;
|
||||||
gatheredFactors.reserve(node->factors.size() + node->children.size());
|
gatheredFactors.reserve(node->factors.size() + node->children.size());
|
||||||
gatheredFactors.push_back(node->factors.begin(), node->factors.end());
|
gatheredFactors += node->factors;
|
||||||
gatheredFactors.push_back(myData.childFactors.begin(), myData.childFactors.end());
|
gatheredFactors += myData.childFactors;
|
||||||
|
|
||||||
|
// Check for Bayes tree orphan subtrees, and add them to our children
|
||||||
|
BOOST_FOREACH(const sharedFactor& f, node->factors)
|
||||||
|
{
|
||||||
|
if(const BayesTreeOrphanWrapper<BTNode>* asSubtree = dynamic_cast<const BayesTreeOrphanWrapper<BTNode>*>(f.get()))
|
||||||
|
{
|
||||||
|
myData.bayesTreeNode->children.push_back(asSubtree->clique);
|
||||||
|
asSubtree->clique->parent_ = myData.bayesTreeNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Do dense elimination step
|
// Do dense elimination step
|
||||||
std::pair<boost::shared_ptr<ConditionalType>, boost::shared_ptr<FactorType> > eliminationResult =
|
std::pair<boost::shared_ptr<ConditionalType>, boost::shared_ptr<FactorType> > eliminationResult =
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* 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 SymbolicISAM.cpp
|
||||||
|
* @date July 29, 2013
|
||||||
|
* @author Frank Dellaert
|
||||||
|
* @author Richard Roberts
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtsam/symbolic/SymbolicISAM.h>
|
||||||
|
#include <gtsam/inference/ISAM-inst.h>
|
||||||
|
|
||||||
|
namespace gtsam {
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
SymbolicISAM::SymbolicISAM() {}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
SymbolicISAM::SymbolicISAM(const SymbolicBayesTree& bayesTree) :
|
||||||
|
Base(bayesTree) {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* 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 SymbolicISAM.h
|
||||||
|
* @date July 29, 2013
|
||||||
|
* @author Frank Dellaert
|
||||||
|
* @author Richard Roberts
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtsam/symbolic/SymbolicBayesTree.h>
|
||||||
|
#include <gtsam/inference/ISAM.h>
|
||||||
|
|
||||||
|
namespace gtsam {
|
||||||
|
|
||||||
|
class GTSAM_EXPORT SymbolicISAM : public ISAM<SymbolicBayesTree>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef ISAM<SymbolicBayesTree> Base;
|
||||||
|
typedef SymbolicISAM This;
|
||||||
|
typedef boost::shared_ptr<This> shared_ptr;
|
||||||
|
|
||||||
|
/// @name Standard Constructors
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/** Create an empty Bayes Tree */
|
||||||
|
SymbolicISAM();
|
||||||
|
|
||||||
|
/** Copy constructor */
|
||||||
|
SymbolicISAM(const SymbolicBayesTree& bayesTree);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -341,6 +341,28 @@ TEST( BayesTreeOrdered, removeTop4 )
|
||||||
EXPECT(orphans.empty());
|
EXPECT(orphans.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST( BayesTreeOrdered, removeTop5 )
|
||||||
|
{
|
||||||
|
// Remove top called with variables that are not in the Bayes tree
|
||||||
|
SymbolicFactorGraph graph = list_of
|
||||||
|
(SymbolicFactor(L(5)))
|
||||||
|
(SymbolicFactor(X(4), L(5)))
|
||||||
|
(SymbolicFactor(X(2), X(4)))
|
||||||
|
(SymbolicFactor(X(3), X(2)));
|
||||||
|
SymbolicBayesTree bayesTree = *graph.eliminateMultifrontal(
|
||||||
|
Ordering(list_of (X(3)) (X(2)) (X(4)) (L(5)) ));
|
||||||
|
|
||||||
|
// Remove nonexistant
|
||||||
|
SymbolicBayesNet bn;
|
||||||
|
SymbolicBayesTree::Cliques orphans;
|
||||||
|
bayesTree.removeTop(list_of(X(10)), bn, orphans);
|
||||||
|
|
||||||
|
SymbolicBayesNet expectedBn;
|
||||||
|
EXPECT(assert_equal(expectedBn, bn));
|
||||||
|
EXPECT(orphans.empty());
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST( SymbolicBayesTree, thinTree ) {
|
TEST( SymbolicBayesTree, thinTree ) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* 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 testISAM.cpp
|
||||||
|
* @brief Unit tests for ISAM
|
||||||
|
* @author Michael Kaess
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/assign/std/list.hpp> // for operator +=
|
||||||
|
using namespace boost::assign;
|
||||||
|
|
||||||
|
#include <CppUnitLite/TestHarness.h>
|
||||||
|
|
||||||
|
#include <gtsam/symbolic/SymbolicISAM.h>
|
||||||
|
#include <gtsam/symbolic/tests/symbolicExampleGraphs.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace gtsam;
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
// Some numbers that should be consistent among all smoother tests
|
||||||
|
|
||||||
|
//static double sigmax1 = 0.786153, sigmax2 = 0.687131 ,sigmax3 = 0.671512,
|
||||||
|
//sigmax4 = 0.669534, sigmax5 = sigmax3,, sigmax7 = sigmax1, sigmax6 = sigmax2;
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
||||||
|
//// SLAM example from RSS sqrtSAM paper
|
||||||
|
//SymbolicConditional::shared_ptr x3(new SymbolicConditional("x3")),
|
||||||
|
// x2(new SymbolicConditional("x2","x3")),
|
||||||
|
// x1(new SymbolicConditional("x1","x2","x3")),
|
||||||
|
// l1(new SymbolicConditional("l1","x1","x2")),
|
||||||
|
// l2(new SymbolicConditional("l2","x1","x3"));
|
||||||
|
//
|
||||||
|
//// ISAM for sqrtSAM example
|
||||||
|
//SymbolicISAM createSlamSymbolicISAM(){
|
||||||
|
// // Create using insert
|
||||||
|
// SymbolicISAM bayesTree_slam;
|
||||||
|
// bayesTree_slam.insert(x3);
|
||||||
|
// bayesTree_slam.insert(x2);
|
||||||
|
// bayesTree_slam.insert(x1);
|
||||||
|
// bayesTree_slam.insert(l2);
|
||||||
|
// bayesTree_slam.insert(l1);
|
||||||
|
// return bayesTree_slam;
|
||||||
|
//}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
||||||
|
//// Conditionals for ASIA example from the tutorial with A and D evidence
|
||||||
|
//SymbolicConditional::shared_ptr
|
||||||
|
// B(new SymbolicConditional("B")),
|
||||||
|
// L(new SymbolicConditional("L", "B")),
|
||||||
|
// E(new SymbolicConditional("E", "B", "L")),
|
||||||
|
// S(new SymbolicConditional("S", "L", "B")),
|
||||||
|
// T(new SymbolicConditional("T", "E", "L")),
|
||||||
|
// X(new SymbolicConditional("X", "E"));
|
||||||
|
//
|
||||||
|
//// ISAM for Asia example
|
||||||
|
//SymbolicISAM createAsiaSymbolicISAM() {
|
||||||
|
// SymbolicISAM bayesTree;
|
||||||
|
// bayesTree.insert(B);
|
||||||
|
// bayesTree.insert(L);
|
||||||
|
// bayesTree.insert(E);
|
||||||
|
// bayesTree.insert(S);
|
||||||
|
// bayesTree.insert(T);
|
||||||
|
// bayesTree.insert(X);
|
||||||
|
// return bayesTree;
|
||||||
|
//}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST( SymbolicISAM, iSAM )
|
||||||
|
{
|
||||||
|
// Now we modify the Bayes tree by inserting a new factor over B and S
|
||||||
|
|
||||||
|
SymbolicFactorGraph fullGraph;
|
||||||
|
fullGraph += asiaGraph;
|
||||||
|
fullGraph += SymbolicFactor(_B_, _S_);
|
||||||
|
|
||||||
|
// This ordering is chosen to match the one chosen by COLAMD during the ISAM update
|
||||||
|
SymbolicBayesTree expected = *fullGraph.eliminateMultifrontal(Ordering(list_of(_X_)(_B_)(_S_)(_E_)(_L_)(_T_)));
|
||||||
|
|
||||||
|
// Add factor on B and S
|
||||||
|
SymbolicISAM actual = *asiaGraph.eliminateMultifrontal();
|
||||||
|
|
||||||
|
// Check whether the same
|
||||||
|
EXPECT(assert_equal(expected, (const SymbolicBayesTree&)actual));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
//TEST( ISAM, iSAM_slam )
|
||||||
|
//{
|
||||||
|
// // Create using insert
|
||||||
|
// SymbolicISAM bayesTree_slam = createSlamSymbolicISAM();
|
||||||
|
//
|
||||||
|
// //New conditionals for the expected Bayes tree
|
||||||
|
// SymbolicConditional::shared_ptr
|
||||||
|
// l1_(new SymbolicConditional("l1","x1","x2","x3"));
|
||||||
|
//
|
||||||
|
// // Create expected Bayes tree
|
||||||
|
// SymbolicISAM expected_slam;
|
||||||
|
// expected_slam.insert(x3);
|
||||||
|
// expected_slam.insert(x2);
|
||||||
|
// expected_slam.insert(x1);
|
||||||
|
// expected_slam.insert(l1_);
|
||||||
|
// expected_slam.insert(l2);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // create new factors to be inserted
|
||||||
|
// SymbolicFactorGraph factorGraph_slam;
|
||||||
|
// factorGraph_slam.push_factor("x3","l1");
|
||||||
|
// factorGraph_slam.push_factor("x3");
|
||||||
|
//
|
||||||
|
// // do incremental inference
|
||||||
|
// bayesTree_slam.update(factorGraph_slam);
|
||||||
|
//
|
||||||
|
// // Check whether the same
|
||||||
|
// CHECK(assert_equal(expected_slam,bayesTree_slam));
|
||||||
|
//}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
int main() { TestResult tr; return TestRegistry::runAllTests(tr);}
|
||||||
|
/* ************************************************************************* */
|
||||||
Loading…
Reference in New Issue