add templated at methods for FactorGraph so it can perform typecasting for us
parent
b78900563c
commit
790e3d515c
|
@ -42,8 +42,8 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <vector>
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Switching.h"
|
#include "Switching.h"
|
||||||
#include "TinyHybridExample.h"
|
#include "TinyHybridExample.h"
|
||||||
|
@ -613,11 +613,11 @@ TEST(HybridGaussianFactorGraph, assembleGraphTree) {
|
||||||
// Create expected decision tree with two factor graphs:
|
// Create expected decision tree with two factor graphs:
|
||||||
|
|
||||||
// Get mixture factor:
|
// Get mixture factor:
|
||||||
auto mixture = std::dynamic_pointer_cast<GaussianMixtureFactor>(fg.at(0));
|
auto mixture = fg.at<GaussianMixtureFactor>(0);
|
||||||
CHECK(mixture);
|
CHECK(mixture);
|
||||||
|
|
||||||
// Get prior factor:
|
// Get prior factor:
|
||||||
const auto gf = std::dynamic_pointer_cast<HybridConditional>(fg.at(1));
|
const auto gf = fg.at<HybridConditional>(1);
|
||||||
CHECK(gf);
|
CHECK(gf);
|
||||||
using GF = GaussianFactor::shared_ptr;
|
using GF = GaussianFactor::shared_ptr;
|
||||||
const GF prior = gf->asGaussian();
|
const GF prior = gf->asGaussian();
|
||||||
|
|
|
@ -310,6 +310,21 @@ class FactorGraph {
|
||||||
*/
|
*/
|
||||||
sharedFactor& at(size_t i) { return factors_.at(i); }
|
sharedFactor& at(size_t i) { return factors_.at(i); }
|
||||||
|
|
||||||
|
/** Get a specific factor by index and typecast to factor type F
|
||||||
|
* (this checks array bounds and may throw
|
||||||
|
* an exception, as opposed to operator[] which does not).
|
||||||
|
*/
|
||||||
|
template <typename F>
|
||||||
|
std::shared_ptr<F> at(size_t i) {
|
||||||
|
return std::dynamic_pointer_cast<F>(factors_.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Const version of templated `at` method.
|
||||||
|
template <typename F>
|
||||||
|
const std::shared_ptr<F> at(size_t i) const {
|
||||||
|
return std::dynamic_pointer_cast<F>(factors_.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
/** Get a specific factor by index (this does not check array bounds, as
|
/** Get a specific factor by index (this does not check array bounds, as
|
||||||
* opposed to at() which does).
|
* opposed to at() which does).
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -391,8 +391,7 @@ TEST(GaussianFactorGraph, clone) {
|
||||||
EXPECT(assert_equal(init_graph, actCloned)); // Same as the original version
|
EXPECT(assert_equal(init_graph, actCloned)); // Same as the original version
|
||||||
|
|
||||||
// Apply an in-place change to init_graph and compare
|
// Apply an in-place change to init_graph and compare
|
||||||
JacobianFactor::shared_ptr jacFactor0 =
|
JacobianFactor::shared_ptr jacFactor0 = init_graph.at<JacobianFactor>(0);
|
||||||
std::dynamic_pointer_cast<JacobianFactor>(init_graph.at(0));
|
|
||||||
CHECK(jacFactor0);
|
CHECK(jacFactor0);
|
||||||
jacFactor0->getA(jacFactor0->begin()) *= 7.;
|
jacFactor0->getA(jacFactor0->begin()) *= 7.;
|
||||||
EXPECT(assert_inequal(init_graph, exp_graph));
|
EXPECT(assert_inequal(init_graph, exp_graph));
|
||||||
|
|
|
@ -65,10 +65,9 @@ class GncOptimizer {
|
||||||
nfg_.resize(graph.size());
|
nfg_.resize(graph.size());
|
||||||
for (size_t i = 0; i < graph.size(); i++) {
|
for (size_t i = 0; i < graph.size(); i++) {
|
||||||
if (graph[i]) {
|
if (graph[i]) {
|
||||||
NoiseModelFactor::shared_ptr factor = std::dynamic_pointer_cast<
|
NoiseModelFactor::shared_ptr factor = graph.at<NoiseModelFactor>(i);
|
||||||
NoiseModelFactor>(graph[i]);
|
auto robust =
|
||||||
auto robust = std::dynamic_pointer_cast<
|
std::dynamic_pointer_cast<noiseModel::Robust>(factor->noiseModel());
|
||||||
noiseModel::Robust>(factor->noiseModel());
|
|
||||||
// if the factor has a robust loss, we remove the robust loss
|
// if the factor has a robust loss, we remove the robust loss
|
||||||
nfg_[i] = robust ? factor-> cloneWithNewNoiseModel(robust->noise()) : factor;
|
nfg_[i] = robust ? factor-> cloneWithNewNoiseModel(robust->noise()) : factor;
|
||||||
}
|
}
|
||||||
|
@ -401,11 +400,9 @@ class GncOptimizer {
|
||||||
newGraph.resize(nfg_.size());
|
newGraph.resize(nfg_.size());
|
||||||
for (size_t i = 0; i < nfg_.size(); i++) {
|
for (size_t i = 0; i < nfg_.size(); i++) {
|
||||||
if (nfg_[i]) {
|
if (nfg_[i]) {
|
||||||
auto factor = std::dynamic_pointer_cast<
|
auto factor = nfg_.at<NoiseModelFactor>(i);
|
||||||
NoiseModelFactor>(nfg_[i]);
|
auto noiseModel = std::dynamic_pointer_cast<noiseModel::Gaussian>(
|
||||||
auto noiseModel =
|
factor->noiseModel());
|
||||||
std::dynamic_pointer_cast<noiseModel::Gaussian>(
|
|
||||||
factor->noiseModel());
|
|
||||||
if (noiseModel) {
|
if (noiseModel) {
|
||||||
Matrix newInfo = weights[i] * noiseModel->information();
|
Matrix newInfo = weights[i] * noiseModel->information();
|
||||||
auto newNoiseModel = noiseModel::Gaussian::Information(newInfo);
|
auto newNoiseModel = noiseModel::Gaussian::Information(newInfo);
|
||||||
|
|
|
@ -372,9 +372,11 @@ TEST(ShonanAveraging2, noisyToyGraphWithHuber) {
|
||||||
|
|
||||||
// test that each factor is actually robust
|
// test that each factor is actually robust
|
||||||
for (size_t i=0; i<=4; i++) { // note: last is the Gauge factor and is not robust
|
for (size_t i=0; i<=4; i++) { // note: last is the Gauge factor and is not robust
|
||||||
const auto &robust = std::dynamic_pointer_cast<noiseModel::Robust>(
|
const auto &robust = std::dynamic_pointer_cast<noiseModel::Robust>(
|
||||||
std::dynamic_pointer_cast<NoiseModelFactor>(graph[i])->noiseModel());
|
graph.at<NoiseModelFactor>(i)->noiseModel());
|
||||||
EXPECT(robust); // we expect the factors to be use a robust noise model (in particular, Huber)
|
// we expect the factors to be use a robust noise model
|
||||||
|
// (in particular, Huber)
|
||||||
|
EXPECT(robust);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test result
|
// test result
|
||||||
|
|
|
@ -97,8 +97,7 @@ TEST(dataSet, load2D) {
|
||||||
auto model = noiseModel::Unit::Create(3);
|
auto model = noiseModel::Unit::Create(3);
|
||||||
BetweenFactor<Pose2> expected(1, 0, Pose2(-0.99879, 0.0417574, -0.00818381),
|
BetweenFactor<Pose2> expected(1, 0, Pose2(-0.99879, 0.0417574, -0.00818381),
|
||||||
model);
|
model);
|
||||||
BetweenFactor<Pose2>::shared_ptr actual =
|
BetweenFactor<Pose2>::shared_ptr actual = graph->at<BetweenFactor<Pose2>>(0);
|
||||||
std::dynamic_pointer_cast<BetweenFactor<Pose2>>(graph->at(0));
|
|
||||||
EXPECT(assert_equal(expected, *actual));
|
EXPECT(assert_equal(expected, *actual));
|
||||||
|
|
||||||
// Check binary measurements, Pose2
|
// Check binary measurements, Pose2
|
||||||
|
@ -113,9 +112,8 @@ TEST(dataSet, load2D) {
|
||||||
// // Check factor parsing
|
// // Check factor parsing
|
||||||
const auto actualFactors = parseFactors<Pose2>(filename);
|
const auto actualFactors = parseFactors<Pose2>(filename);
|
||||||
for (size_t i : {0, 1, 2, 3, 4, 5}) {
|
for (size_t i : {0, 1, 2, 3, 4, 5}) {
|
||||||
EXPECT(assert_equal(
|
EXPECT(assert_equal(*graph->at<BetweenFactor<Pose2>>(i), *actualFactors[i],
|
||||||
*std::dynamic_pointer_cast<BetweenFactor<Pose2>>(graph->at(i)),
|
1e-5));
|
||||||
*actualFactors[i], 1e-5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check pose parsing
|
// Check pose parsing
|
||||||
|
@ -194,9 +192,8 @@ TEST(dataSet, readG2o3D) {
|
||||||
// Check factor parsing
|
// Check factor parsing
|
||||||
const auto actualFactors = parseFactors<Pose3>(g2oFile);
|
const auto actualFactors = parseFactors<Pose3>(g2oFile);
|
||||||
for (size_t i : {0, 1, 2, 3, 4, 5}) {
|
for (size_t i : {0, 1, 2, 3, 4, 5}) {
|
||||||
EXPECT(assert_equal(
|
EXPECT(assert_equal(*expectedGraph.at<BetweenFactor<Pose3>>(i),
|
||||||
*std::dynamic_pointer_cast<BetweenFactor<Pose3>>(expectedGraph[i]),
|
*actualFactors[i], 1e-5));
|
||||||
*actualFactors[i], 1e-5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check pose parsing
|
// Check pose parsing
|
||||||
|
|
|
@ -183,13 +183,10 @@ class LoopyBelief {
|
||||||
// accumulate unary factors
|
// accumulate unary factors
|
||||||
if (graph.at(factorIndex)->size() == 1) {
|
if (graph.at(factorIndex)->size() == 1) {
|
||||||
if (!prodOfUnaries)
|
if (!prodOfUnaries)
|
||||||
prodOfUnaries = std::dynamic_pointer_cast<DecisionTreeFactor>(
|
prodOfUnaries = graph.at<DecisionTreeFactor>(factorIndex);
|
||||||
graph.at(factorIndex));
|
|
||||||
else
|
else
|
||||||
prodOfUnaries = std::make_shared<DecisionTreeFactor>(
|
prodOfUnaries = std::make_shared<DecisionTreeFactor>(
|
||||||
*prodOfUnaries *
|
*prodOfUnaries * (*graph.at<DecisionTreeFactor>(factorIndex)));
|
||||||
(*std::dynamic_pointer_cast<DecisionTreeFactor>(
|
|
||||||
graph.at(factorIndex))));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ TEST(NonlinearClusterTree, Clusters) {
|
||||||
Ordering ordering;
|
Ordering ordering;
|
||||||
ordering.push_back(x1);
|
ordering.push_back(x1);
|
||||||
const auto [bn, fg] = gfg->eliminatePartialSequential(ordering);
|
const auto [bn, fg] = gfg->eliminatePartialSequential(ordering);
|
||||||
auto expectedFactor = std::dynamic_pointer_cast<HessianFactor>(fg->at(0));
|
auto expectedFactor = fg->at<HessianFactor>(0);
|
||||||
if (!expectedFactor)
|
if (!expectedFactor)
|
||||||
throw std::runtime_error("Expected HessianFactor");
|
throw std::runtime_error("Expected HessianFactor");
|
||||||
|
|
||||||
|
|
|
@ -323,7 +323,7 @@ TEST( NonlinearFactor, cloneWithNewNoiseModel )
|
||||||
// create actual
|
// create actual
|
||||||
NonlinearFactorGraph actual;
|
NonlinearFactorGraph actual;
|
||||||
SharedNoiseModel noise2 = noiseModel::Isotropic::Sigma(2,sigma2);
|
SharedNoiseModel noise2 = noiseModel::Isotropic::Sigma(2,sigma2);
|
||||||
actual.push_back( std::dynamic_pointer_cast<NoiseModelFactor>(nfg[0])->cloneWithNewNoiseModel(noise2) );
|
actual.push_back(nfg.at<NoiseModelFactor>(0)->cloneWithNewNoiseModel(noise2));
|
||||||
|
|
||||||
// check it's all good
|
// check it's all good
|
||||||
CHECK(assert_equal(expected, actual));
|
CHECK(assert_equal(expected, actual));
|
||||||
|
|
Loading…
Reference in New Issue