30 using namespace gtsam;
31 using std::shared_ptr;
44 Values* init_values =
nullptr,
48 ISAM2Params::CHOLESKY,
true,
50 size_t maxPoses = 10) {
66 init.insert((0),
Pose2(0.01, 0.01, 0.01));
82 init.insert((
i+1),
Pose2(
double(
i+1)+0.1, -0.1, 0.01));
124 init.insert((
i+1),
Pose2(
double(
i+1)+0.1, -0.1, 0.01));
155 *full_graph = fullgraph;
158 *init_values = fullinit;
205 if(find(
isam.roots().begin(),
isam.roots().end(), node) ==
isam.roots().end())
207 if(node->parent_.expired())
209 if(find(node->parent()->children.begin(), node->parent()->children.end(), node) == node->parent()->children.end())
212 for(
Key j: node->conditional()->frontals())
214 if(
isam.nodes().at(
j).get() != node.get())
225 const string name_ =
test.getName();
237 expectedHessian.bottomRightCorner(1,1) = actualHessian.bottomRightCorner(1,1);
238 bool isamTreeEqual =
assert_equal(expectedHessian, actualHessian);
249 bool nodeGradientsOk =
true;
250 for (
const auto& [
key, clique] :
isam.nodes()) {
257 for(GaussianConditional::const_iterator jit = clique->conditional()->begin(); jit != clique->conditional()->end(); ++jit) {
258 const DenseIndex dim = clique->conditional()->getDim(jit);
259 Vector actual = clique->gradientContribution().segment(variablePosition, dim);
260 bool gradOk =
assert_equal(expectedGradient[*jit], actual);
262 nodeGradientsOk = nodeGradientsOk && gradOk;
263 variablePosition += dim;
265 bool dimOk = clique->gradientContribution().rows() == variablePosition;
267 nodeGradientsOk = nodeGradientsOk && dimOk;
274 bool expectedGradOk =
assert_equal(expectedGradient2, expectedGradient);
276 bool totalGradOk =
assert_equal(expectedGradient, actualGradient);
279 return nodeGradientsOk && expectedGradOk && totalGradOk && isamEqual && isamTreeEqual && consistent;
285 for(
size_t i = 0;
i < 10; ++
i) {
391 toRemove.push_back(12);
411 toRemove.push_back(7);
412 toRemove.push_back(14);
438 toRemove.push_back(swap_idx);
439 fullgraph.
remove(swap_idx);
453 for (
const auto& [
key, clique]:
isam.nodes()) {
460 for(GaussianConditional::const_iterator jit = clique->conditional()->begin(); jit != clique->conditional()->end(); ++jit) {
461 const DenseIndex dim = clique->conditional()->getDim(jit);
462 Vector actual = clique->gradientContribution().segment(variablePosition, dim);
464 variablePosition += dim;
466 EXPECT_LONGS_EQUAL((
long)clique->gradientContribution().rows(), (
long)variablePosition);
487 constrained.insert(make_pair((3), 1));
488 constrained.insert(make_pair((4), 2));
500 init.insert((0),
Pose2(0.01, 0.01, 0.01));
515 init.insert((
i+1),
Pose2(
double(
i+1)+0.1, -0.1, 0.01));
551 init.insert((
i+1),
Pose2(
double(
i+1)+0.1, -0.1, 0.01));
577 for (
const auto& [
key, clique]:
isam.nodes()) {
584 for(GaussianConditional::const_iterator jit = clique->conditional()->begin(); jit != clique->conditional()->end(); ++jit) {
585 const DenseIndex dim = clique->conditional()->getDim(jit);
586 Vector actual = clique->gradientContribution().segment(variablePosition, dim);
588 variablePosition += dim;
590 LONGS_EQUAL((
long)clique->gradientContribution().rows(), (
long)variablePosition);
602 TEST(
ISAM2, slamlike_solution_partial_relinearization_check)
608 params.enablePartialRelinearizationCheck =
true;
617 Matrix expectedAugmentedHessian, expected3AugmentedHessian;
619 for (
const auto& [
key, clique]:
isam.getDelta()) {
620 if(find(leafKeys.begin(), leafKeys.end(),
key) == leafKeys.end()) {
621 toKeep.push_back(
key);
634 ->marginal(toKeep,
EliminateQR)->augmentedHessian();
637 isam.marginalizeLeaves(leafKeys);
641 Matrix actualAugmentedHessian = actualMarginalGraph.augmentedHessian();
645 assert(actualAugmentedHessian.allFinite());
649 bool treeEqual =
assert_equal(expectedAugmentedHessian, actualAugmentedHessian, 1
e-6);
652 actualAugmentedHessian.bottomRightCorner(1,1) = expected3AugmentedHessian.bottomRightCorner(1,1);
bool nonlinEqual =
assert_equal(expected3AugmentedHessian, actualAugmentedHessian, 1
e-6);
656 bool afterNonlinCorrect =
assert_equal(expected3AugmentedHessian, actual3AugmentedHessian, 1
e-6);
658 bool ok = treeEqual && nonlinEqual && afterNonlinCorrect;
662 std::optional<FastMap<Key, int>> createOrderingConstraints(
const ISAM2&
isam,
const KeyVector& newKeys,
const KeySet& marginalizableKeys)
664 if (marginalizableKeys.empty()) {
670 for (
const auto& key_val :
isam.getDelta()) {
671 constrainedKeys.emplace(key_val.first, 1);
673 for (
const auto&
key : newKeys) {
674 constrainedKeys.emplace(
key, 1);
677 for (
const auto&
key : marginalizableKeys) {
678 constrainedKeys.at(
key) = 0;
680 return constrainedKeys;
686 std::stack<ISAM2Clique::shared_ptr> frontier;
687 frontier.push(rootClique);
689 while (!frontier.empty()) {
694 if (std::find(clique->conditional()->beginParents(), clique->conditional()->endParents(),
key) !=
695 clique->conditional()->endParents()) {
696 for (
Key i : clique->conditional()->frontals()) {
697 additionalKeys.push_back(
i);
700 frontier.push(child);
709 auto orderingConstraints = createOrderingConstraints(
isam, newValues.
keys(), marginalizableKeys);
713 for (
Key key : marginalizableKeys) {
714 markedKeys.push_back(
key);
717 markAffectedKeys(
key, child, markedKeys);
724 if (!marginalizableKeys.empty()) {
725 FastList<Key> leafKeys(marginalizableKeys.begin(), marginalizableKeys.end());
726 return checkMarginalizeLeaves(
isam, leafKeys);
750 constrainedKeys.insert(make_pair(0, 0));
751 constrainedKeys.insert(make_pair(1, 1));
752 constrainedKeys.insert(make_pair(2, 2));
757 EXPECT(checkMarginalizeLeaves(
isam, leafKeys));
779 constrainedKeys.insert(make_pair(0, 0));
780 constrainedKeys.insert(make_pair(1, 1));
781 constrainedKeys.insert(make_pair(2, 2));
782 constrainedKeys.insert(make_pair(3, 3));
787 EXPECT(checkMarginalizeLeaves(
isam, leafKeys));
816 constrainedKeys.insert(make_pair(0, 0));
817 constrainedKeys.insert(make_pair(1, 1));
818 constrainedKeys.insert(make_pair(2, 2));
819 constrainedKeys.insert(make_pair(3, 3));
820 constrainedKeys.insert(make_pair(4, 4));
821 constrainedKeys.insert(make_pair(5, 5));
826 EXPECT(checkMarginalizeLeaves(
isam, leafKeys));
844 constrainedKeys.insert(make_pair(0, 0));
845 constrainedKeys.insert(make_pair(1, 1));
846 constrainedKeys.insert(make_pair(2, 2));
851 EXPECT(checkMarginalizeLeaves(
isam, leafKeys));
862 EXPECT(checkMarginalizeLeaves(
isam, marginalizeKeys));
868 auto nm = noiseModel::Isotropic::Sigma(6, 1.0);
872 auto idxToKey = [gridDim](
int i,
int j){
return i * gridDim +
j;};
879 for (
int i = 0;
i < gridDim; ++
i) {
880 for (
int j = 0;
j < gridDim; ++
j) {
897 auto estimate =
isam.calculateBestEstimate();
900 std::vector<Key> key_list(gridDim * gridDim);
901 std::iota(key_list.begin(), key_list.end(), 0);
904 std::shuffle(key_list.begin(), key_list.end(), std::default_random_engine(1234));
906 for (
const auto&
key : key_list) {
908 marginalKeys.insert(
key);
909 EXPECT(updateAndMarginalize({}, {}, marginalKeys,
isam));
910 estimate =
isam.calculateBestEstimate();
917 auto nm = noiseModel::Isotropic::Sigma(6, 1.0);
924 Pose3 root = Pose3::Identity();
927 factors.addPrior(rootKey, Pose3::Identity(), nm);
931 auto estimate =
isam.calculateBestEstimate();
932 EXPECT(estimate.size() == 1);
935 KeySet marginalizableKeys;
936 marginalizableKeys.insert(rootKey);
938 EXPECT(updateAndMarginalize({}, {}, marginalizableKeys,
isam));
940 estimate =
isam.calculateBestEstimate();
947 auto nm = noiseModel::Isotropic::Sigma(6, 1.0);
952 params.findUnusedFactorSlots =
true;
960 Pose3 b = Pose3::Identity();
969 to_remove.insert(
aKey);
971 updateAndMarginalize({}, {}, to_remove,
isam);
992 int actual =
isam.roots().front()->calculate_nnz();
1003 :
Base(nullptr,
key), is_active_(active) {}
1011 Base::OptionalMatrixTypeT<Vector2>
H =
nullptr)
const override {
1013 *
H = Vector2::Identity();
1015 return Vector2::Zero();
1019 TEST(ActiveFactorTesting, Issue1596) {