Merge branch 'develop' into varun/test-hybrid-estimation

release/4.3a0
Varun Agrawal 2022-10-03 11:35:30 -04:00
commit 269d60e2c2
4 changed files with 69 additions and 7 deletions

View File

@ -66,6 +66,27 @@ class KeySet {
void serialize() const; void serialize() const;
}; };
// Actually a vector<Key>, needed for Matlab
class KeyVector {
KeyVector();
KeyVector(const gtsam::KeyVector& other);
// Note: no print function
// common STL methods
size_t size() const;
bool empty() const;
void clear();
// structure specific methods
size_t at(size_t i) const;
size_t front() const;
size_t back() const;
void push_back(size_t key) const;
void serialize() const;
};
// Actually a FastMap<Key,int> // Actually a FastMap<Key,int>
class KeyGroupMap { class KeyGroupMap {
KeyGroupMap(); KeyGroupMap();

View File

@ -199,12 +199,14 @@ std::pair<HybridConditional::shared_ptr, HybridFactor::shared_ptr>
discreteElimination(const HybridGaussianFactorGraph &factors, discreteElimination(const HybridGaussianFactorGraph &factors,
const Ordering &frontalKeys) { const Ordering &frontalKeys) {
DiscreteFactorGraph dfg; DiscreteFactorGraph dfg;
for (auto &fp : factors) {
if (auto ptr = boost::dynamic_pointer_cast<HybridDiscreteFactor>(fp)) { for (auto &factor : factors) {
dfg.push_back(ptr->inner()); if (auto p = boost::dynamic_pointer_cast<HybridDiscreteFactor>(factor)) {
} else if (auto p = dfg.push_back(p->inner());
boost::static_pointer_cast<HybridConditional>(fp)->inner()) { } else if (auto p = boost::static_pointer_cast<HybridConditional>(factor)) {
dfg.push_back(boost::static_pointer_cast<DiscreteConditional>(p)); auto discrete_conditional =
boost::static_pointer_cast<DiscreteConditional>(p->inner());
dfg.push_back(discrete_conditional);
} else { } else {
// It is an orphan wrapper // It is an orphan wrapper
} }
@ -293,6 +295,7 @@ hybridElimination(const HybridGaussianFactorGraph &factors,
return exp(-factor->error(empty_values)); return exp(-factor->error(empty_values));
}; };
DecisionTree<Key, double> fdt(separatorFactors, factorError); DecisionTree<Key, double> fdt(separatorFactors, factorError);
auto discreteFactor = auto discreteFactor =
boost::make_shared<DecisionTreeFactor>(discreteSeparator, fdt); boost::make_shared<DecisionTreeFactor>(discreteSeparator, fdt);

View File

@ -100,11 +100,23 @@ class MixtureFactor : public HybridFactor {
bool normalized = false) bool normalized = false)
: Base(keys, discreteKeys), normalized_(normalized) { : Base(keys, discreteKeys), normalized_(normalized) {
std::vector<NonlinearFactor::shared_ptr> nonlinear_factors; std::vector<NonlinearFactor::shared_ptr> nonlinear_factors;
KeySet continuous_keys_set(keys.begin(), keys.end());
KeySet factor_keys_set;
for (auto&& f : factors) { for (auto&& f : factors) {
// Insert all factor continuous keys in the continuous keys set.
std::copy(f->keys().begin(), f->keys().end(),
std::inserter(factor_keys_set, factor_keys_set.end()));
nonlinear_factors.push_back( nonlinear_factors.push_back(
boost::dynamic_pointer_cast<NonlinearFactor>(f)); boost::dynamic_pointer_cast<NonlinearFactor>(f));
} }
factors_ = Factors(discreteKeys, nonlinear_factors); factors_ = Factors(discreteKeys, nonlinear_factors);
if (continuous_keys_set != factor_keys_set) {
throw std::runtime_error(
"The specified continuous keys and the keys in the factors don't "
"match!");
}
} }
~MixtureFactor() = default; ~MixtureFactor() = default;

View File

@ -147,6 +147,32 @@ TEST(HybridGaussianFactorGraph, Resize) {
EXPECT_LONGS_EQUAL(gfg.size(), 0); EXPECT_LONGS_EQUAL(gfg.size(), 0);
} }
/***************************************************************************
* Test that the MixtureFactor reports correctly if the number of continuous
* keys provided do not match the keys in the factors.
*/
TEST(HybridGaussianFactorGraph, MixtureFactor) {
auto nonlinearFactor = boost::make_shared<BetweenFactor<double>>(
X(0), X(1), 0.0, Isotropic::Sigma(1, 0.1));
auto discreteFactor = boost::make_shared<DecisionTreeFactor>();
auto noise_model = noiseModel::Isotropic::Sigma(1, 1.0);
auto still = boost::make_shared<MotionModel>(X(0), X(1), 0.0, noise_model),
moving = boost::make_shared<MotionModel>(X(0), X(1), 1.0, noise_model);
std::vector<MotionModel::shared_ptr> components = {still, moving};
// Check for exception when number of continuous keys are under-specified.
KeyVector contKeys = {X(0)};
THROWS_EXCEPTION(boost::make_shared<MixtureFactor>(
contKeys, DiscreteKeys{gtsam::DiscreteKey(M(1), 2)}, components));
// Check for exception when number of continuous keys are too many.
contKeys = {X(0), X(1), X(2)};
THROWS_EXCEPTION(boost::make_shared<MixtureFactor>(
contKeys, DiscreteKeys{gtsam::DiscreteKey(M(1), 2)}, components));
}
/***************************************************************************** /*****************************************************************************
* Test push_back on HFG makes the correct distinction. * Test push_back on HFG makes the correct distinction.
*/ */
@ -348,7 +374,7 @@ TEST(HybridGaussianElimination, EliminateHybrid_2_Variable) {
EXPECT_LONGS_EQUAL(1, discreteFactor->discreteKeys().size()); EXPECT_LONGS_EQUAL(1, discreteFactor->discreteKeys().size());
EXPECT(discreteFactor->root_->isLeaf() == false); EXPECT(discreteFactor->root_->isLeaf() == false);
//TODO(Varun) Test emplace_discrete // TODO(Varun) Test emplace_discrete
} }
/**************************************************************************** /****************************************************************************