31 using namespace gtsam;
32 using std::shared_ptr;
45 Values* init_values =
nullptr,
49 ISAM2Params::CHOLESKY,
true,
51 size_t maxPoses = 10) {
67 init.insert((0),
Pose2(0.01, 0.01, 0.01));
83 init.insert((
i+1),
Pose2(
double(
i+1)+0.1, -0.1, 0.01));
125 init.insert((
i+1),
Pose2(
double(
i+1)+0.1, -0.1, 0.01));
156 *full_graph = fullgraph;
159 *init_values = fullinit;
206 if(find(
isam.roots().begin(),
isam.roots().end(), node) ==
isam.roots().end())
208 if(node->parent_.expired())
210 if(find(node->parent()->children.begin(), node->parent()->children.end(), node) == node->parent()->children.end())
213 for(
Key j: node->conditional()->frontals())
215 if(
isam.nodes().at(
j).get() != node.get())
226 const string name_ =
test.getName();
238 expectedHessian.bottomRightCorner(1,1) = actualHessian.bottomRightCorner(1,1);
239 bool isamTreeEqual =
assert_equal(expectedHessian, actualHessian);
250 bool nodeGradientsOk =
true;
251 for (
const auto& [
key, clique] :
isam.nodes()) {
258 for(GaussianConditional::const_iterator jit = clique->conditional()->begin(); jit != clique->conditional()->end(); ++jit) {
259 const DenseIndex dim = clique->conditional()->getDim(jit);
260 Vector actual = clique->gradientContribution().segment(variablePosition, dim);
261 bool gradOk =
assert_equal(expectedGradient[*jit], actual);
263 nodeGradientsOk = nodeGradientsOk && gradOk;
264 variablePosition += dim;
266 bool dimOk = clique->gradientContribution().rows() == variablePosition;
268 nodeGradientsOk = nodeGradientsOk && dimOk;
275 bool expectedGradOk =
assert_equal(expectedGradient2, expectedGradient);
277 bool totalGradOk =
assert_equal(expectedGradient, actualGradient);
280 return nodeGradientsOk && expectedGradOk && totalGradOk && isamEqual && isamTreeEqual && consistent;
286 for(
size_t i = 0;
i < 10; ++
i) {
392 toRemove.push_back(12);
412 toRemove.push_back(7);
413 toRemove.push_back(14);
439 toRemove.push_back(swap_idx);
440 fullgraph.
remove(swap_idx);
454 for (
const auto& [
key, clique]:
isam.nodes()) {
461 for(GaussianConditional::const_iterator jit = clique->conditional()->begin(); jit != clique->conditional()->end(); ++jit) {
462 const DenseIndex dim = clique->conditional()->getDim(jit);
463 Vector actual = clique->gradientContribution().segment(variablePosition, dim);
465 variablePosition += dim;
467 EXPECT_LONGS_EQUAL((
long)clique->gradientContribution().rows(), (
long)variablePosition);
488 constrained.insert(make_pair((3), 1));
489 constrained.insert(make_pair((4), 2));
501 init.insert((0),
Pose2(0.01, 0.01, 0.01));
516 init.insert((
i+1),
Pose2(
double(
i+1)+0.1, -0.1, 0.01));
552 init.insert((
i+1),
Pose2(
double(
i+1)+0.1, -0.1, 0.01));
578 for (
const auto& [
key, clique]:
isam.nodes()) {
585 for(GaussianConditional::const_iterator jit = clique->conditional()->begin(); jit != clique->conditional()->end(); ++jit) {
586 const DenseIndex dim = clique->conditional()->getDim(jit);
587 Vector actual = clique->gradientContribution().segment(variablePosition, dim);
589 variablePosition += dim;
591 LONGS_EQUAL((
long)clique->gradientContribution().rows(), (
long)variablePosition);
603 TEST(
ISAM2, slamlike_solution_partial_relinearization_check)
609 params.enablePartialRelinearizationCheck =
true;
618 Matrix expectedAugmentedHessian, expected3AugmentedHessian;
620 for (
const auto& [
key, clique]:
isam.getDelta()) {
621 if(find(leafKeys.begin(), leafKeys.end(),
key) == leafKeys.end()) {
622 toKeep.push_back(
key);
635 ->marginal(toKeep,
EliminateQR)->augmentedHessian();
638 isam.marginalizeLeaves(leafKeys);
642 Matrix actualAugmentedHessian = actualMarginalGraph.augmentedHessian();
646 assert(actualAugmentedHessian.allFinite());
650 bool treeEqual =
assert_equal(expectedAugmentedHessian, actualAugmentedHessian, 1
e-6);
653 actualAugmentedHessian.bottomRightCorner(1,1) = expected3AugmentedHessian.bottomRightCorner(1,1);
bool nonlinEqual =
assert_equal(expected3AugmentedHessian, actualAugmentedHessian, 1
e-6);
657 bool afterNonlinCorrect =
assert_equal(expected3AugmentedHessian, actual3AugmentedHessian, 1
e-6);
659 bool ok = treeEqual && nonlinEqual && afterNonlinCorrect;
663 std::optional<FastMap<Key, int>> createOrderingConstraints(
const ISAM2&
isam,
const KeyVector& newKeys,
const KeySet& marginalizableKeys)
665 if (marginalizableKeys.empty()) {
671 for (
const auto& key_val :
isam.getDelta()) {
672 constrainedKeys.emplace(key_val.first, 1);
674 for (
const auto&
key : newKeys) {
675 constrainedKeys.emplace(
key, 1);
678 for (
const auto&
key : marginalizableKeys) {
679 constrainedKeys.at(
key) = 0;
681 return constrainedKeys;
687 std::stack<ISAM2Clique::shared_ptr> frontier;
688 frontier.push(rootClique);
690 while (!frontier.empty()) {
695 if (std::find(clique->conditional()->beginParents(), clique->conditional()->endParents(),
key) !=
696 clique->conditional()->endParents()) {
697 for (
Key i : clique->conditional()->frontals()) {
698 additionalKeys.push_back(
i);
701 frontier.push(child);
710 auto orderingConstraints = createOrderingConstraints(
isam, newValues.
keys(), marginalizableKeys);
714 for (
Key key : marginalizableKeys) {
715 markedKeys.push_back(
key);
718 markAffectedKeys(
key, child, markedKeys);
725 if (!marginalizableKeys.empty()) {
726 FastList<Key> leafKeys(marginalizableKeys.begin(), marginalizableKeys.end());
727 return checkMarginalizeLeaves(
isam, leafKeys);
751 constrainedKeys.insert(make_pair(0, 0));
752 constrainedKeys.insert(make_pair(1, 1));
753 constrainedKeys.insert(make_pair(2, 2));
758 EXPECT(checkMarginalizeLeaves(
isam, leafKeys));
780 constrainedKeys.insert(make_pair(0, 0));
781 constrainedKeys.insert(make_pair(1, 1));
782 constrainedKeys.insert(make_pair(2, 2));
783 constrainedKeys.insert(make_pair(3, 3));
788 EXPECT(checkMarginalizeLeaves(
isam, leafKeys));
817 constrainedKeys.insert(make_pair(0, 0));
818 constrainedKeys.insert(make_pair(1, 1));
819 constrainedKeys.insert(make_pair(2, 2));
820 constrainedKeys.insert(make_pair(3, 3));
821 constrainedKeys.insert(make_pair(4, 4));
822 constrainedKeys.insert(make_pair(5, 5));
827 EXPECT(checkMarginalizeLeaves(
isam, leafKeys));
845 constrainedKeys.insert(make_pair(0, 0));
846 constrainedKeys.insert(make_pair(1, 1));
847 constrainedKeys.insert(make_pair(2, 2));
852 EXPECT(checkMarginalizeLeaves(
isam, leafKeys));
863 EXPECT(checkMarginalizeLeaves(
isam, marginalizeKeys));
869 auto nm = noiseModel::Isotropic::Sigma(6, 1.0);
873 auto idxToKey = [gridDim](
int i,
int j){
return i * gridDim +
j;};
880 for (
int i = 0;
i < gridDim; ++
i) {
881 for (
int j = 0;
j < gridDim; ++
j) {
898 auto estimate =
isam.calculateBestEstimate();
901 std::vector<Key> key_list(gridDim * gridDim);
902 std::iota(key_list.begin(), key_list.end(), 0);
905 std::shuffle(key_list.begin(), key_list.end(), std::default_random_engine(1234));
907 for (
const auto&
key : key_list) {
909 marginalKeys.insert(
key);
910 EXPECT(updateAndMarginalize({}, {}, marginalKeys,
isam));
911 estimate =
isam.calculateBestEstimate();
918 auto nm = noiseModel::Isotropic::Sigma(6, 1.0);
925 Pose3 root = Pose3::Identity();
928 factors.addPrior(rootKey, Pose3::Identity(), nm);
932 auto estimate =
isam.calculateBestEstimate();
933 EXPECT(estimate.size() == 1);
936 KeySet marginalizableKeys;
937 marginalizableKeys.insert(rootKey);
939 EXPECT(updateAndMarginalize({}, {}, marginalizableKeys,
isam));
941 estimate =
isam.calculateBestEstimate();
948 auto nm = noiseModel::Isotropic::Sigma(6, 1.0);
953 params.findUnusedFactorSlots =
true;
961 Pose3 b = Pose3::Identity();
970 to_remove.insert(
aKey);
972 updateAndMarginalize({}, {}, to_remove,
isam);
993 int actual =
isam.roots().front()->calculate_nnz();
1004 :
Base(nullptr,
key), is_active_(active) {}
1012 Base::OptionalMatrixTypeT<Vector2>
H =
nullptr)
const override {
1014 *
H = Vector2::Identity();
1016 return Vector2::Zero();
1020 TEST(ActiveFactorTesting, Issue1596) {