testHybridNonlinearFactorGraph.cpp
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
3  * Atlanta, Georgia 30332-0415
4  * All Rights Reserved
5  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
6  * See LICENSE for the license information
7  * -------------------------------------------------------------------------- */
8 
19 #include <gtsam/base/utilities.h>
24 #include <gtsam/geometry/Pose2.h>
36 
37 #include "Switching.h"
38 
39 // Include for test suite
41 
42 using namespace std;
43 using namespace gtsam;
48 
49 /* ****************************************************************************
50  * Test that any linearizedFactorGraph gaussian factors are appended to the
51  * existing gaussian factor graph in the hybrid factor graph.
52  */
55 
56  // Add a simple prior factor to the nonlinear factor graph
57  fg.emplace_shared<PriorFactor<double>>(X(0), 0, Isotropic::Sigma(1, 0.1));
58 
59  // Linearization point
60  Values linearizationPoint;
61  linearizationPoint.insert<double>(X(0), 0);
62 
63  // Linearize the factor graph.
64  HybridGaussianFactorGraph ghfg = *fg.linearize(linearizationPoint);
65  EXPECT_LONGS_EQUAL(1, ghfg.size());
66 
67  // Check that the error is the same for the nonlinear values.
68  const VectorValues zero{{X(0), Vector1(0)}};
69  const HybridValues hybridValues{zero, {}, linearizationPoint};
70  EXPECT_DOUBLES_EQUAL(fg.error(hybridValues), ghfg.error(hybridValues), 1e-9);
71 }
72 
73 /***************************************************************************
74  * Test equality for Hybrid Nonlinear Factor Graph.
75  */
79 
80  // Test empty factor graphs
82 
83  auto f0 = std::make_shared<PriorFactor<Pose2>>(
84  1, Pose2(), noiseModel::Isotropic::Sigma(3, 0.001));
87 
88  auto f1 = std::make_shared<BetweenFactor<Pose2>>(
89  1, 2, Pose2(), noiseModel::Isotropic::Sigma(3, 0.1));
92 
93  // Test non-empty graphs
95 }
96 
97 /***************************************************************************
98  * Test that the resize method works correctly for a HybridNonlinearFactorGraph.
99  */
102  auto nonlinearFactor = std::make_shared<BetweenFactor<double>>();
103  fg.push_back(nonlinearFactor);
104 
105  auto discreteFactor = std::make_shared<DecisionTreeFactor>();
106  fg.push_back(discreteFactor);
107 
108  auto dcFactor = std::make_shared<HybridNonlinearFactor>();
109  fg.push_back(dcFactor);
110 
111  EXPECT_LONGS_EQUAL(fg.size(), 3);
112 
113  fg.resize(0);
114  EXPECT_LONGS_EQUAL(fg.size(), 0);
115 }
116 
117 /***************************************************************************/
118 namespace test_motion {
119 gtsam::DiscreteKey m1(M(1), 2);
120 auto noise_model = noiseModel::Isotropic::Sigma(1, 1.0);
121 std::vector<NoiseModelFactor::shared_ptr> components = {
122  std::make_shared<MotionModel>(X(0), X(1), 0.0, noise_model),
123  std::make_shared<MotionModel>(X(0), X(1), 1.0, noise_model)};
124 } // namespace test_motion
125 
126 /***************************************************************************
127  * Test that the resize method works correctly for a
128  * HybridGaussianFactorGraph.
129  */
131  using namespace test_motion;
132 
134  auto nonlinearFactor = std::make_shared<BetweenFactor<double>>(
135  X(0), X(1), 0.0, Isotropic::Sigma(1, 0.1));
136  hnfg.push_back(nonlinearFactor);
137  auto discreteFactor = std::make_shared<DecisionTreeFactor>();
138  hnfg.push_back(discreteFactor);
139 
140  auto dcFactor = std::make_shared<HybridNonlinearFactor>(m1, components);
141  hnfg.push_back(dcFactor);
142 
143  Values linearizationPoint;
144  linearizationPoint.insert<double>(X(0), 0);
145  linearizationPoint.insert<double>(X(1), 1);
146 
147  // Generate `HybridGaussianFactorGraph` by linearizing
148  HybridGaussianFactorGraph gfg = *hnfg.linearize(linearizationPoint);
149 
150  EXPECT_LONGS_EQUAL(gfg.size(), 3);
151 
152  gfg.resize(0);
153  EXPECT_LONGS_EQUAL(gfg.size(), 0);
154 }
155 
156 /*****************************************************************************
157  * Test push_back on HFG makes the correct distinction.
158  */
161 
162  auto nonlinearFactor = std::make_shared<BetweenFactor<double>>();
163  fg.push_back(nonlinearFactor);
164 
165  EXPECT_LONGS_EQUAL(fg.size(), 1);
166 
168 
169  auto discreteFactor = std::make_shared<DecisionTreeFactor>();
170  fg.push_back(discreteFactor);
171 
172  EXPECT_LONGS_EQUAL(fg.size(), 1);
173 
175 
176  auto dcFactor = std::make_shared<HybridNonlinearFactor>();
177  fg.push_back(dcFactor);
178 
179  EXPECT_LONGS_EQUAL(fg.size(), 1);
180 
181  // Now do the same with HybridGaussianFactorGraph
183 
184  auto gaussianFactor = std::make_shared<JacobianFactor>();
185  ghfg.push_back(gaussianFactor);
186 
187  EXPECT_LONGS_EQUAL(ghfg.size(), 1);
188 
189  ghfg = HybridGaussianFactorGraph();
190  ghfg.push_back(discreteFactor);
191 
192  EXPECT_LONGS_EQUAL(ghfg.size(), 1);
193 
194  ghfg = HybridGaussianFactorGraph();
195  ghfg.push_back(dcFactor);
196 
198  hgfg2.push_back(ghfg.begin(), ghfg.end());
199 
200  EXPECT_LONGS_EQUAL(ghfg.size(), 1);
201 
204  auto noise = noiseModel::Isotropic::Sigma(3, 1.0);
205  factors.emplace_shared<PriorFactor<Pose2>>(0, Pose2(0, 0, 0), noise);
206  factors.emplace_shared<PriorFactor<Pose2>>(1, Pose2(1, 0, 0), noise);
207  factors.emplace_shared<PriorFactor<Pose2>>(2, Pose2(2, 0, 0), noise);
208  // TODO(Varun) This does not currently work. It should work once HybridFactor
209  // becomes a base class of NoiseModelFactor.
210  // hnfg.push_back(factors.begin(), factors.end());
211 
212  // EXPECT_LONGS_EQUAL(3, hnfg.size());
213 }
214 
215 /* ****************************************************************************/
216 // Test hybrid nonlinear factor graph errorTree
218  Switching s(3);
219 
220  const HybridNonlinearFactorGraph &graph = s.nonlinearFactorGraph();
221  const Values &values = s.linearizationPoint;
222 
223  auto error_tree = graph.errorTree(s.linearizationPoint);
224 
225  auto dkeys = graph.discreteKeys();
226  DiscreteKeys discrete_keys(dkeys.begin(), dkeys.end());
227 
228  // Compute the sum of errors for each factor.
229  auto assignments = DiscreteValues::CartesianProduct(discrete_keys);
230  std::vector<double> leaves(assignments.size());
231  for (auto &&factor : graph) {
232  for (size_t i = 0; i < assignments.size(); ++i) {
233  leaves[i] +=
234  factor->error(HybridValues(VectorValues(), assignments[i], values));
235  }
236  }
237  // Swap i=1 and i=2 to give correct ordering.
238  double temp = leaves[1];
239  leaves[1] = leaves[2];
240  leaves[2] = temp;
241  AlgebraicDecisionTree<Key> expected_error(discrete_keys, leaves);
242 
243  EXPECT(assert_equal(expected_error, error_tree, 1e-7));
244 }
245 
246 /****************************************************************************
247  * Test construction of switching-like hybrid factor graph.
248  */
250  Switching self(3);
251 
252  EXPECT_LONGS_EQUAL(7, self.nonlinearFactorGraph().size());
253  EXPECT_LONGS_EQUAL(7, self.linearizedFactorGraph().size());
254 }
255 
256 /****************************************************************************
257  * Test linearization on a switching-like hybrid factor graph.
258  */
260  Switching self(3);
261 
262  // Linearize here:
263  HybridGaussianFactorGraph actualLinearized =
264  *self.nonlinearFactorGraph().linearize(self.linearizationPoint);
265 
266  EXPECT_LONGS_EQUAL(7, actualLinearized.size());
267 }
268 
269 /****************************************************************************
270  * Test elimination tree construction
271  */
273  Switching self(3);
274 
275  // Create ordering.
277  for (size_t k = 0; k < self.K; k++) ordering.push_back(X(k));
278 
279  // Create elimination tree.
280  HybridEliminationTree etree(self.linearizedFactorGraph(), ordering);
281  EXPECT_LONGS_EQUAL(1, etree.roots().size())
282 }
283 
284 /****************************************************************************
285  *Test elimination function by eliminating x0 in *-x0-*-x1 graph.
286  */
287 TEST(GaussianElimination, Eliminate_x0) {
288  Switching self(3);
289 
290  // Gather factors on x0, has a simple Gaussian and a hybrid factor.
292  // Add gaussian prior
293  factors.push_back(self.linearUnaryFactors[0]);
294  // Add first hybrid factor
295  factors.push_back(self.linearBinaryFactors[0]);
296 
297  // Eliminate x0
298  const Ordering ordering{X(0)};
299 
301  CHECK(result.first);
302  EXPECT_LONGS_EQUAL(1, result.first->nrFrontals());
303  CHECK(result.second);
304  // Has two keys, x2 and m1
305  EXPECT_LONGS_EQUAL(2, result.second->size());
306 }
307 
308 /****************************************************************************
309  * Test elimination function by eliminating x1 in x0-*-x1-*-x2 chain.
310  * m0/ \m1
311  */
312 TEST(HybridsGaussianElimination, Eliminate_x1) {
313  Switching self(3);
314 
315  // Gather factors on x1, will be two hybrid factors (with x0 and x2, resp.).
317  factors.push_back(self.linearBinaryFactors[0]); // involves m0
318  factors.push_back(self.linearBinaryFactors[1]); // involves m1
319 
320  // Eliminate x1
321  const Ordering ordering{X(1)};
322 
324  CHECK(result.first);
325  EXPECT_LONGS_EQUAL(1, result.first->nrFrontals());
326  CHECK(result.second);
327  // Note: separator keys should include m1, m2.
328  EXPECT_LONGS_EQUAL(4, result.second->size());
329 }
330 
331 /****************************************************************************
332  * Helper method to generate gaussian factor graphs with a specific mode.
333  */
335  Values linearizationPoint) {
337  graph.addPrior<double>(X(0), 0, Isotropic::Sigma(1, 0.1));
338 
339  auto between_x0_x1 = std::make_shared<MotionModel>(X(0), X(1), between,
340  Isotropic::Sigma(1, 1.0));
341 
342  graph.push_back(between_x0_x1);
343 
344  return graph.linearize(linearizationPoint);
345 }
346 
347 /****************************************************************************
348  * Test elimination function by eliminating x0 and x1 in graph.
349  */
350 TEST(HybridGaussianElimination, EliminateHybrid_2_Variable) {
351  Switching self(2, 1.0, 0.1);
352 
353  auto factors = self.linearizedFactorGraph();
354 
355  // Eliminate x0
356  const Ordering ordering{X(0), X(1)};
357 
358  const auto [hybridConditional, factorOnModes] =
360 
361  auto hybridGaussianConditional =
362  dynamic_pointer_cast<HybridGaussianConditional>(
363  hybridConditional->inner());
364 
365  CHECK(hybridGaussianConditional);
366  // Frontals = [x0, x1]
367  EXPECT_LONGS_EQUAL(2, hybridGaussianConditional->nrFrontals());
368  // 1 parent, which is the mode
369  EXPECT_LONGS_EQUAL(1, hybridGaussianConditional->nrParents());
370 
371  // This is now a discreteFactor
372  auto discreteFactor = dynamic_pointer_cast<TableFactor>(factorOnModes);
373  CHECK(discreteFactor);
374  EXPECT_LONGS_EQUAL(1, discreteFactor->discreteKeys().size());
375 }
376 
377 /****************************************************************************
378  * Test partial elimination
379  */
380 TEST(HybridNonlinearFactorGraph, Partial_Elimination) {
381  Switching self(3);
382 
383  // Create ordering of only continuous variables.
385  for (size_t k = 0; k < self.K; k++) ordering.push_back(X(k));
386 
387  // Eliminate partially i.e. only continuous part.
388  const auto [hybridBayesNet, remainingFactorGraph] =
389  self.linearizedFactorGraph().eliminatePartialSequential(ordering);
390 
391  CHECK(hybridBayesNet);
392  EXPECT_LONGS_EQUAL(3, hybridBayesNet->size());
393  EXPECT(hybridBayesNet->at(0)->frontals() == KeyVector{X(0)});
394  EXPECT(hybridBayesNet->at(0)->parents() == KeyVector({X(1), M(0)}));
395  EXPECT(hybridBayesNet->at(1)->frontals() == KeyVector{X(1)});
396  EXPECT(hybridBayesNet->at(1)->parents() == KeyVector({X(2), M(0), M(1)}));
397  EXPECT(hybridBayesNet->at(2)->frontals() == KeyVector{X(2)});
398  EXPECT(hybridBayesNet->at(2)->parents() == KeyVector({M(0), M(1)}));
399 
400  CHECK(remainingFactorGraph);
401  EXPECT_LONGS_EQUAL(3, remainingFactorGraph->size());
402  EXPECT(remainingFactorGraph->at(0)->keys() == KeyVector({M(0)}));
403  EXPECT(remainingFactorGraph->at(1)->keys() == KeyVector({M(1), M(0)}));
404  EXPECT(remainingFactorGraph->at(2)->keys() == KeyVector({M(0), M(1)}));
405 }
406 
407 /* ****************************************************************************/
409  Switching self(3);
410  HybridNonlinearFactorGraph fg = self.nonlinearFactorGraph();
411 
412  {
413  HybridValues values(VectorValues(), DiscreteValues{{M(0), 0}, {M(1), 0}},
414  self.linearizationPoint);
415  // regression
416  EXPECT_DOUBLES_EQUAL(152.791759469, fg.error(values), 1e-9);
417  }
418  {
419  HybridValues values(VectorValues(), DiscreteValues{{M(0), 0}, {M(1), 1}},
420  self.linearizationPoint);
421  // regression
422  EXPECT_DOUBLES_EQUAL(151.598612289, fg.error(values), 1e-9);
423  }
424  {
425  HybridValues values(VectorValues(), DiscreteValues{{M(0), 1}, {M(1), 0}},
426  self.linearizationPoint);
427  // regression
428  EXPECT_DOUBLES_EQUAL(151.703972804, fg.error(values), 1e-9);
429  }
430  {
431  HybridValues values(VectorValues(), DiscreteValues{{M(0), 1}, {M(1), 1}},
432  self.linearizationPoint);
433  // regression
434  EXPECT_DOUBLES_EQUAL(151.609437912, fg.error(values), 1e-9);
435  }
436 }
437 
438 /* ****************************************************************************/
440  Switching self(3);
441 
442  // Get nonlinear factor graph and add linear factors to be holistic.
443  // TODO(Frank): ???
444  HybridNonlinearFactorGraph fg = self.nonlinearFactorGraph();
445  fg.add(self.linearizedFactorGraph());
446 
447  // Optimize to get HybridValues
449  self.linearizedFactorGraph().eliminateSequential();
450  HybridValues hv = bn->optimize();
451 
452  // Print and verify
453  // fg.print();
454  // std::cout << "\n\n\n" << std::endl;
455  // fg.printErrors(
456  // HybridValues(hv.continuous(), DiscreteValues(),
457  // self.linearizationPoint));
458 }
459 
460 /****************************************************************************
461  * Test full elimination
462  */
463 TEST(HybridNonlinearFactorGraph, Full_Elimination) {
464  Switching self(3);
465 
466  // We first do a partial elimination
467  DiscreteBayesNet discreteBayesNet;
468 
469  {
470  // Create ordering.
472  for (size_t k = 0; k < self.K; k++) ordering.push_back(X(k));
473 
474  // Eliminate partially.
475  const auto [hybridBayesNet_partial, remainingFactorGraph_partial] =
476  self.linearizedFactorGraph().eliminatePartialSequential(ordering);
477 
478  DiscreteFactorGraph discrete_fg =
479  remainingFactorGraph_partial->discreteFactors();
480 
481  ordering.clear();
482  for (size_t k = 0; k < self.K - 1; k++) ordering.push_back(M(k));
483  discreteBayesNet =
485  }
486 
487  // Create ordering.
489  for (size_t k = 0; k < self.K; k++) ordering.push_back(X(k));
490  for (size_t k = 0; k < self.K - 1; k++) ordering.push_back(M(k));
491 
492  // Eliminate partially.
493  HybridBayesNet::shared_ptr hybridBayesNet =
494  self.linearizedFactorGraph().eliminateSequential(ordering);
495 
496  CHECK(hybridBayesNet);
497  EXPECT_LONGS_EQUAL(5, hybridBayesNet->size());
498  // p(x0 | x1, m0)
499  EXPECT(hybridBayesNet->at(0)->frontals() == KeyVector{X(0)});
500  EXPECT(hybridBayesNet->at(0)->parents() == KeyVector({X(1), M(0)}));
501  // p(x1 | x2, m0, m1)
502  EXPECT(hybridBayesNet->at(1)->frontals() == KeyVector{X(1)});
503  EXPECT(hybridBayesNet->at(1)->parents() == KeyVector({X(2), M(0), M(1)}));
504  // p(x2 | m0, m1)
505  EXPECT(hybridBayesNet->at(2)->frontals() == KeyVector{X(2)});
506  EXPECT(hybridBayesNet->at(2)->parents() == KeyVector({M(0), M(1)}));
507  // P(m0 | m1)
508  EXPECT(hybridBayesNet->at(3)->frontals() == KeyVector{M(0)});
509  EXPECT(hybridBayesNet->at(3)->parents() == KeyVector({M(1)}));
510  EXPECT(
511  dynamic_pointer_cast<DiscreteConditional>(hybridBayesNet->at(3)->inner())
512  ->equals(*discreteBayesNet.at(0)));
513  // P(m1)
514  EXPECT(hybridBayesNet->at(4)->frontals() == KeyVector{M(1)});
515  EXPECT_LONGS_EQUAL(0, hybridBayesNet->at(4)->nrParents());
516  TableDistribution dtc =
517  *hybridBayesNet->at(4)->asDiscrete<TableDistribution>();
519  .equals(*discreteBayesNet.at(1)));
520 }
521 
522 /****************************************************************************
523  * Test printing
524  */
526  Switching self(3);
527 
528  auto linearizedFactorGraph = self.linearizedFactorGraph();
529 
530  // Create ordering.
532  for (size_t k = 0; k < self.K; k++) ordering.push_back(X(k));
533 
534  // Eliminate partially.
535  const auto [hybridBayesNet, remainingFactorGraph] =
536  linearizedFactorGraph.eliminatePartialSequential(ordering);
537 
538  // Set precision so we are consistent on all platforms
539  std::cout << std::setprecision(6);
540 
541 #ifdef GTSAM_DT_MERGING
542  string expected_hybridFactorGraph = R"(
543 size: 7
544 Factor 0
545 GaussianFactor:
546 
547  A[x0] = [
548  10
549 ]
550  b = [ -10 ]
551  No noise model
552 
553 Factor 1
554 GaussianFactor:
555 
556  A[x1] = [
557  10
558 ]
559  b = [ -10 ]
560  No noise model
561 
562 Factor 2
563 GaussianFactor:
564 
565  A[x2] = [
566  10
567 ]
568  b = [ -10 ]
569  No noise model
570 
571 Factor 3
572 HybridGaussianFactor:
573 Hybrid [x0 x1; m0]{
574  Choice(m0)
575  0 Leaf :
576  A[x0] = [
577  -1
578 ]
579  A[x1] = [
580  1
581 ]
582  b = [ -1 ]
583  No noise model
584 scalar: 0.918939
585 
586  1 Leaf :
587  A[x0] = [
588  -1
589 ]
590  A[x1] = [
591  1
592 ]
593  b = [ -0 ]
594  No noise model
595 scalar: 0.918939
596 
597 }
598 
599 Factor 4
600 HybridGaussianFactor:
601 Hybrid [x1 x2; m1]{
602  Choice(m1)
603  0 Leaf :
604  A[x1] = [
605  -1
606 ]
607  A[x2] = [
608  1
609 ]
610  b = [ -1 ]
611  No noise model
612 scalar: 0.918939
613 
614  1 Leaf :
615  A[x1] = [
616  -1
617 ]
618  A[x2] = [
619  1
620 ]
621  b = [ -0 ]
622  No noise model
623 scalar: 0.918939
624 
625 }
626 
627 Factor 5
628 DiscreteFactor:
629  P( m0 ):
630  Leaf 0.5
631 
632 
633 Factor 6
634 DiscreteFactor:
635  P( m1 | m0 ):
636  Choice(m1)
637  0 Choice(m0)
638  0 0 Leaf 0.33333333
639  0 1 Leaf 0.6
640  1 Choice(m0)
641  1 0 Leaf 0.66666667
642  1 1 Leaf 0.4
643 
644 
645 )";
646 #else
647  string expected_hybridFactorGraph = R"(
648 size: 7
649 Factor 0
650 GaussianFactor:
651 
652  A[x0] = [
653  10
654 ]
655  b = [ -10 ]
656  No noise model
657 
658 Factor 1
659 GaussianFactor:
660 
661  A[x1] = [
662  10
663 ]
664  b = [ -10 ]
665  No noise model
666 
667 Factor 2
668 GaussianFactor:
669 
670  A[x2] = [
671  10
672 ]
673  b = [ -10 ]
674  No noise model
675 
676 Factor 3
677 HybridGaussianFactor:
678 Hybrid [x0 x1; m0]{
679  Choice(m0)
680  0 Leaf :
681  A[x0] = [
682  -1
683 ]
684  A[x1] = [
685  1
686 ]
687  b = [ -1 ]
688  No noise model
689 scalar: 0.918939
690 
691  1 Leaf :
692  A[x0] = [
693  -1
694 ]
695  A[x1] = [
696  1
697 ]
698  b = [ -0 ]
699  No noise model
700 scalar: 0.918939
701 
702 }
703 
704 Factor 4
705 HybridGaussianFactor:
706 Hybrid [x1 x2; m1]{
707  Choice(m1)
708  0 Leaf :
709  A[x1] = [
710  -1
711 ]
712  A[x2] = [
713  1
714 ]
715  b = [ -1 ]
716  No noise model
717 scalar: 0.918939
718 
719  1 Leaf :
720  A[x1] = [
721  -1
722 ]
723  A[x2] = [
724  1
725 ]
726  b = [ -0 ]
727  No noise model
728 scalar: 0.918939
729 
730 }
731 
732 Factor 5
733 DiscreteFactor:
734  P( m0 ):
735  Choice(m0)
736  0 Leaf 0.5
737  1 Leaf 0.5
738 
739 
740 Factor 6
741 DiscreteFactor:
742  P( m1 | m0 ):
743  Choice(m1)
744  0 Choice(m0)
745  0 0 Leaf 0.33333333
746  0 1 Leaf 0.6
747  1 Choice(m0)
748  1 0 Leaf 0.66666667
749  1 1 Leaf 0.4
750 
751 
752 )";
753 #endif
754 
755  EXPECT(assert_print_equal(expected_hybridFactorGraph, linearizedFactorGraph));
756 
757  // Expected output for hybridBayesNet.
758  string expected_hybridBayesNet = R"(
759 size: 3
760 conditional 0: P( x0 | x1 m0)
761  Discrete Keys = (m0, 2),
762  logNormalizationConstant: 1.38862
763 
764  Choice(m0)
765  0 Leaf p(x0 | x1)
766  R = [ 10.0499 ]
767  S[x1] = [ -0.0995037 ]
768  d = [ -9.85087 ]
769  logNormalizationConstant: 1.38862
770  No noise model
771 
772  1 Leaf p(x0 | x1)
773  R = [ 10.0499 ]
774  S[x1] = [ -0.0995037 ]
775  d = [ -9.95037 ]
776  logNormalizationConstant: 1.38862
777  No noise model
778 
779 conditional 1: P( x1 | x2 m0 m1)
780  Discrete Keys = (m0, 2), (m1, 2),
781  logNormalizationConstant: 1.3935
782 
783  Choice(m1)
784  0 Choice(m0)
785  0 0 Leaf p(x1 | x2)
786  R = [ 10.099 ]
787  S[x2] = [ -0.0990196 ]
788  d = [ -9.99901 ]
789  logNormalizationConstant: 1.3935
790  No noise model
791 
792  0 1 Leaf p(x1 | x2)
793  R = [ 10.099 ]
794  S[x2] = [ -0.0990196 ]
795  d = [ -9.90098 ]
796  logNormalizationConstant: 1.3935
797  No noise model
798 
799  1 Choice(m0)
800  1 0 Leaf p(x1 | x2)
801  R = [ 10.099 ]
802  S[x2] = [ -0.0990196 ]
803  d = [ -10.098 ]
804  logNormalizationConstant: 1.3935
805  No noise model
806 
807  1 1 Leaf p(x1 | x2)
808  R = [ 10.099 ]
809  S[x2] = [ -0.0990196 ]
810  d = [ -10 ]
811  logNormalizationConstant: 1.3935
812  No noise model
813 
814 conditional 2: P( x2 | m0 m1)
815  Discrete Keys = (m0, 2), (m1, 2),
816  logNormalizationConstant: 1.38857
817 
818  Choice(m1)
819  0 Choice(m0)
820  0 0 Leaf p(x2)
821  R = [ 10.0494 ]
822  d = [ -10.1489 ]
823  mean: 1 elements
824  x2: -1.0099
825  logNormalizationConstant: 1.38857
826  No noise model
827 
828  0 1 Leaf p(x2)
829  R = [ 10.0494 ]
830  d = [ -10.1479 ]
831  mean: 1 elements
832  x2: -1.0098
833  logNormalizationConstant: 1.38857
834  No noise model
835 
836  1 Choice(m0)
837  1 0 Leaf p(x2)
838  R = [ 10.0494 ]
839  d = [ -10.0504 ]
840  mean: 1 elements
841  x2: -1.0001
842  logNormalizationConstant: 1.38857
843  No noise model
844 
845  1 1 Leaf p(x2)
846  R = [ 10.0494 ]
847  d = [ -10.0494 ]
848  mean: 1 elements
849  x2: -1
850  logNormalizationConstant: 1.38857
851  No noise model
852 
853 )";
854  EXPECT(assert_print_equal(expected_hybridBayesNet, *hybridBayesNet));
855 }
856 
857 /****************************************************************************
858  * Simple PlanarSLAM example test with 2 poses and 2 landmarks (each pose
859  * connects to 1 landmark) to expose issue with default decision tree creation
860  * in hybrid elimination. The hybrid factor is between the poses X0 and X1.
861  * The issue arises if we eliminate a landmark variable first since it is not
862  * connected to a HybridFactor.
863  */
864 TEST(HybridNonlinearFactorGraph, DefaultDecisionTree) {
866 
867  // Add a prior on pose x0 at the origin.
868  // A prior factor consists of a mean and a noise model (covariance matrix)
869  Pose2 prior(0.0, 0.0, 0.0); // prior mean is at origin
870  auto priorNoise = noiseModel::Diagonal::Sigmas(
871  Vector3(0.3, 0.3, 0.1)); // 30cm std on x,y, 0.1 rad on theta
873 
874  using PlanarMotionModel = BetweenFactor<Pose2>;
875 
876  // Add odometry factor
877  Pose2 odometry(2.0, 0.0, 0.0);
878  auto noise_model = noiseModel::Isotropic::Sigma(3, 1.0);
879  std::vector<NoiseModelFactor::shared_ptr> motion_models = {
880  std::make_shared<PlanarMotionModel>(X(0), X(1), Pose2(0, 0, 0),
881  noise_model),
882  std::make_shared<PlanarMotionModel>(X(0), X(1), odometry, noise_model)};
883  fg.emplace_shared<HybridNonlinearFactor>(DiscreteKey{M(1), 2}, motion_models);
884 
885  // Add Range-Bearing measurements to from X0 to L0 and X1 to L1.
886  // create a noise model for the landmark measurements
887  auto measurementNoise = noiseModel::Diagonal::Sigmas(
888  Vector2(0.1, 0.2)); // 0.1 rad std on bearing, 20cm on range
889  // create the measurement values - indices are (pose id, landmark id)
890  Rot2 bearing11 = Rot2::fromDegrees(45), bearing22 = Rot2::fromDegrees(90);
891  double range11 = std::sqrt(4.0 + 4.0), range22 = 2.0;
892 
893  // Add Bearing-Range factors
895  X(0), L(0), bearing11, range11, measurementNoise);
897  X(1), L(1), bearing22, range22, measurementNoise);
898 
899  // Create (deliberately inaccurate) initial estimate
900  Values initialEstimate;
901  initialEstimate.insert(X(0), Pose2(0.5, 0.0, 0.2));
902  initialEstimate.insert(X(1), Pose2(2.3, 0.1, -0.2));
903  initialEstimate.insert(L(0), Point2(1.8, 2.1));
904  initialEstimate.insert(L(1), Point2(4.1, 1.8));
905 
906  // We want to eliminate variables not connected to DCFactors first.
907  const Ordering ordering{L(0), L(1), X(0), X(1)};
908 
909  HybridGaussianFactorGraph linearized = *fg.linearize(initialEstimate);
910 
911  // This should NOT fail
912  const auto [hybridBayesNet, remainingFactorGraph] =
914  EXPECT_LONGS_EQUAL(4, hybridBayesNet->size());
915  EXPECT_LONGS_EQUAL(1, remainingFactorGraph->size());
916 }
917 
932  const std::vector<double> &means, const std::vector<double> &sigmas,
933  DiscreteKey &m1, double x0_measurement, double measurement_noise = 1e-3) {
934  auto model0 = noiseModel::Isotropic::Sigma(1, sigmas[0]);
935  auto model1 = noiseModel::Isotropic::Sigma(1, sigmas[1]);
936  auto prior_noise = noiseModel::Isotropic::Sigma(1, measurement_noise);
937 
938  auto f0 =
939  std::make_shared<BetweenFactor<double>>(X(0), X(1), means[0], model0);
940  auto f1 =
941  std::make_shared<BetweenFactor<double>>(X(0), X(1), means[1], model1);
942 
943  // Create HybridNonlinearFactor
944  // We take negative since we want
945  // the underlying scalar to be log(\sqrt(|2πΣ|))
946  std::vector<NonlinearFactorValuePair> factors{{f0, 0.0}, {f1, 0.0}};
947 
948  HybridNonlinearFactor mixtureFactor(m1, factors);
949 
951  hfg.push_back(mixtureFactor);
952 
953  hfg.push_back(PriorFactor<double>(X(0), x0_measurement, prior_noise));
954 
955  return hfg;
956 }
957 } // namespace test_relinearization
958 
959 /* ************************************************************************* */
968  using namespace test_relinearization;
969 
970  DiscreteKey m1(M(1), 2);
971 
972  Values values;
973  double x0 = 0.0, x1 = 1.75;
974  values.insert(X(0), x0);
975  values.insert(X(1), x1);
976 
977  std::vector<double> means = {0.0, 2.0}, sigmas = {1e-0, 1e-0};
978 
980 
981  {
982  auto bn = hfg.linearize(values)->eliminateSequential();
983  HybridValues actual = bn->optimize();
984 
986  VectorValues{{X(0), Vector1(0.0)}, {X(1), Vector1(-1.75)}},
987  DiscreteValues{{M(1), 0}});
988 
989  EXPECT(assert_equal(expected, actual));
990 
991  DiscreteValues dv0{{M(1), 0}};
992  VectorValues cont0 = bn->optimize(dv0);
993  double error0 = bn->error(HybridValues(cont0, dv0));
994 
995  // regression
996  EXPECT_DOUBLES_EQUAL(0.69314718056, error0, 1e-9);
997 
998  DiscreteValues dv1{{M(1), 1}};
999  VectorValues cont1 = bn->optimize(dv1);
1000  double error1 = bn->error(HybridValues(cont1, dv1));
1001  EXPECT_DOUBLES_EQUAL(error0, error1, 1e-9);
1002  }
1003 
1004  {
1005  // Add measurement on x1
1006  auto prior_noise = noiseModel::Isotropic::Sigma(1, 1e-3);
1007  hfg.push_back(PriorFactor<double>(X(1), means[1], prior_noise));
1008 
1009  auto bn = hfg.linearize(values)->eliminateSequential();
1010  HybridValues actual = bn->optimize();
1011 
1013  VectorValues{{X(0), Vector1(0.0)}, {X(1), Vector1(0.25)}},
1014  DiscreteValues{{M(1), 1}});
1015 
1016  EXPECT(assert_equal(expected, actual));
1017 
1018  {
1019  DiscreteValues dv{{M(1), 0}};
1020  VectorValues cont = bn->optimize(dv);
1021  double error = bn->error(HybridValues(cont, dv));
1022  // regression
1023  EXPECT_DOUBLES_EQUAL(2.12692448787, error, 1e-9);
1024  }
1025  {
1026  DiscreteValues dv{{M(1), 1}};
1027  VectorValues cont = bn->optimize(dv);
1028  double error = bn->error(HybridValues(cont, dv));
1029  // regression
1030  EXPECT_DOUBLES_EQUAL(0.126928487854, error, 1e-9);
1031  }
1032  }
1033 }
1034 
1035 /* ************************************************************************* */
1043 TEST(HybridNonlinearFactorGraph, DifferentCovariances) {
1044  using namespace test_relinearization;
1045 
1046  DiscreteKey m1(M(1), 2);
1047 
1048  Values values;
1049  double x0 = 1.0, x1 = 1.0;
1050  values.insert(X(0), x0);
1051  values.insert(X(1), x1);
1052 
1053  std::vector<double> means = {0.0, 0.0}, sigmas = {1e2, 1e-2};
1054 
1055  // Create FG with HybridNonlinearFactor and prior on X1
1057  // Linearize
1058  auto hgfg = hfg.linearize(values);
1059  // and eliminate
1060  auto hbn = hgfg->eliminateSequential();
1061 
1062  VectorValues cv;
1063  cv.insert(X(0), Vector1(0.0));
1064  cv.insert(X(1), Vector1(0.0));
1065 
1066  DiscreteValues dv0{{M(1), 0}};
1067  DiscreteValues dv1{{M(1), 1}};
1068 
1069  TableDistribution expected_m1(m1, "0.5 0.5");
1070  TableDistribution actual_m1 = *(hbn->at(2)->asDiscrete<TableDistribution>());
1071 
1072  EXPECT(assert_equal(expected_m1, actual_m1));
1073 }
1074 
1076  using namespace test_relinearization;
1077 
1078  DiscreteKey m1(M(1), 2);
1079 
1080  Values values;
1081  double x0 = 0.0, x1 = 0.8;
1082  values.insert(X(0), x0);
1083  values.insert(X(1), x1);
1084 
1085  std::vector<double> means = {0.0, 1.0}, sigmas = {1e-2, 1e-2};
1086 
1087  double prior_sigma = 1e-2;
1088  // Create FG with HybridNonlinearFactor and prior on X1
1090  CreateFactorGraph(means, sigmas, m1, 0.0, prior_sigma);
1092  X(1), 1.2, noiseModel::Isotropic::Sigma(1, prior_sigma)));
1093 
1094  // Linearize
1095  auto hgfg = hfg.linearize(values);
1096  // and eliminate
1097  auto hbn = hgfg->eliminateSequential();
1098 
1099  HybridValues delta = hbn->optimize();
1100  values = values.retract(delta.continuous());
1101 
1102  Values expected_first_result;
1103  expected_first_result.insert(X(0), 0.0666666666667);
1104  expected_first_result.insert(X(1), 1.13333333333);
1105  EXPECT(assert_equal(expected_first_result, values));
1106 
1107  // Re-linearize
1108  hgfg = hfg.linearize(values);
1109  // and eliminate
1110  hbn = hgfg->eliminateSequential();
1111  delta = hbn->optimize();
1112  HybridValues result(delta.continuous(), delta.discrete(),
1113  values.retract(delta.continuous()));
1114 
1115  HybridValues expected_result(
1116  VectorValues{{X(0), Vector1(0)}, {X(1), Vector1(0)}},
1117  DiscreteValues{{M(1), 1}}, expected_first_result);
1118  EXPECT(assert_equal(expected_result, result));
1119 }
1120 
1121 /* *************************************************************************
1122  */
1123 int main() {
1124  TestResult tr;
1125  return TestRegistry::runAllTests(tr);
1126 }
1127 /* *************************************************************************
1128  */
TestRegistry::runAllTests
static int runAllTests(TestResult &result)
Definition: TestRegistry.cpp:27
gtsam::EliminateDiscrete
std::pair< DiscreteConditional::shared_ptr, DiscreteFactor::shared_ptr > EliminateDiscrete(const DiscreteFactorGraph &factors, const Ordering &frontalKeys)
Main elimination function for DiscreteFactorGraph.
Definition: DiscreteFactorGraph.cpp:202
gtsam::EliminateableFactorGraph::eliminateSequential
std::shared_ptr< BayesNetType > eliminateSequential(OptionalOrderingType orderingType={}, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex={}) const
Definition: EliminateableFactorGraph-inst.h:29
TableDistribution.h
Pose2.h
2D Pose
DiscreteBayesNet.h
GaussianFactorGraph.h
Linear Factor Graph where all factors are Gaussians.
gtsam::HybridValues
Definition: HybridValues.h:37
gtsam::GaussianFactorGraph::shared_ptr
std::shared_ptr< This > shared_ptr
shared_ptr to this class
Definition: GaussianFactorGraph.h:82
gtsam::DiscreteFactorGraph
Definition: DiscreteFactorGraph.h:99
test_constructor::f1
auto f1
Definition: testHybridNonlinearFactor.cpp:56
gtsam::Values::size
size_t size() const
Definition: Values.h:178
s
RealScalar s
Definition: level1_cplx_impl.h:126
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
gtsam::FactorGraph::error
double error(const HybridValues &values) const
Definition: FactorGraph-inst.h:66
EXPECT_LONGS_EQUAL
#define EXPECT_LONGS_EQUAL(expected, actual)
Definition: Test.h:154
EXPECT
#define EXPECT(condition)
Definition: Test.h:150
gtsam::Vector2
Eigen::Vector2d Vector2
Definition: Vector.h:43
HybridNonlinearFactorGraph.h
Nonlinear hybrid factor graph that uses type erasure.
test_constructor::sigmas
Vector1 sigmas
Definition: testHybridNonlinearFactor.cpp:52
TestHarness.h
DiscreteFactorGraph.h
gtsam::HybridNonlinearFactorGraph
Definition: HybridNonlinearFactorGraph.h:33
gtsam::HybridValues::retract
HybridValues retract(const VectorValues &delta) const
Definition: HybridValues.cpp:79
gtsam::VectorValues::insert
iterator insert(const std::pair< Key, Vector > &key_value)
Definition: VectorValues.cpp:90
Switching.h
gtsam::assert_print_equal
bool assert_print_equal(const std::string &expected, const V &actual, const std::string &s="")
Definition: TestableAssertions.h:353
simple_graph::factors
const GaussianFactorGraph factors
Definition: testJacobianFactor.cpp:213
gtsam::DiscreteConditional::equals
bool equals(const DiscreteFactor &other, double tol=1e-9) const override
GTSAM-style equals.
Definition: DiscreteConditional.cpp:159
gtsam::PriorFactor
Definition: nonlinear/PriorFactor.h:30
gtsam::DecisionTreeFactor::error
double error(const DiscreteValues &values) const override
Calculate error for DiscreteValues x, is -log(probability).
Definition: DecisionTreeFactor.cpp:57
different_sigmas::values
HybridValues values
Definition: testHybridBayesNet.cpp:247
gtsam::NonlinearFactorGraph::linearize
std::shared_ptr< GaussianFactorGraph > linearize(const Values &linearizationPoint) const
Linearize a nonlinear factor graph.
Definition: NonlinearFactorGraph.cpp:239
main
int main()
Definition: testHybridNonlinearFactorGraph.cpp:1123
X
#define X
Definition: icosphere.cpp:20
gtsam::DiscreteKeys
DiscreteKeys is a set of keys that can be assembled using the & operator.
Definition: DiscreteKey.h:41
GaussianBayesNet.h
Chordal Bayes Net, the result of eliminating a factor graph.
gtsam::Vector3
Eigen::Vector3d Vector3
Definition: Vector.h:44
gtsam::EliminationTree
Definition: EliminationTree.h:51
gtsam::means
Point2Pair means(const std::vector< Point2Pair > &abPointPairs)
Calculate the two means of a set of Point2 pairs.
Definition: Point2.cpp:116
gtsam::KeyVector
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:92
result
Values result
Definition: OdometryOptimize.cpp:8
test_relinearization::CreateFactorGraph
static HybridNonlinearFactorGraph CreateFactorGraph(const std::vector< double > &means, const std::vector< double > &sigmas, DiscreteKey &m1, double x0_measurement, double measurement_noise=1e-3)
Create a Factor Graph by directly specifying all the factors instead of creating conditionals first....
Definition: testHybridNonlinearFactorGraph.cpp:931
test_motion::noise_model
auto noise_model
Definition: testHybridNonlinearFactorGraph.cpp:120
gtsam::Switching::linearizedFactorGraph
HybridGaussianFactorGraph linearizedFactorGraph() const
Get the full linear factor graph.
Definition: Switching.h:220
utilities.h
TestableAssertions.h
Provides additional testing facilities for common data structures.
gtsam::AlgebraicDecisionTree< Key >
pruning_fixture::factor
DecisionTreeFactor factor(D &C &B &A, "0.0 0.0 0.0 0.60658897 0.61241912 0.61241969 0.61247685 0.61247742 0.0 " "0.0 0.0 0.99995287 1.0 1.0 1.0 1.0")
size
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
gtsam::EliminationTree::roots
const FastVector< sharedNode > & roots() const
Definition: EliminationTree.h:154
gtsam::Switching
ϕ(X(0)) .. ϕ(X(k),X(k+1)) .. ϕ(X(k);z_k) .. ϕ(M(0)) .. ϕ(M(K-3),M(K-2))
Definition: Switching.h:124
odometry
Pose2 odometry(2.0, 0.0, 0.0)
gtsam::GaussianFactorGraph
Definition: GaussianFactorGraph.h:73
Vector1
Eigen::Matrix< double, 1, 1 > Vector1
Definition: testEvent.cpp:33
PriorFactor.h
gtsam::FactorGraph::resize
virtual void resize(size_t size)
Definition: FactorGraph.h:367
HybridFactor.h
gtsam.examples.PlanarManipulatorExample.delta
def delta(g0, g1)
Definition: PlanarManipulatorExample.py:45
gtsam::DiscreteBayesNet
Definition: DiscreteBayesNet.h:38
gtsam::VectorValues
Definition: VectorValues.h:74
test_constructor::f0
auto f0
Definition: testHybridNonlinearFactor.cpp:55
BetweenFactor.h
x1
Pose3 x1
Definition: testPose3.cpp:692
gtsam::TableDistribution
Definition: TableDistribution.h:39
gtsam::noiseModel::Isotropic
Definition: NoiseModel.h:541
gtsam::EliminateableFactorGraph::eliminatePartialSequential
std::pair< std::shared_ptr< BayesNetType >, std::shared_ptr< FactorGraphType > > eliminatePartialSequential(const Ordering &ordering, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex={}) const
Definition: EliminateableFactorGraph-inst.h:151
gtsam::BearingRangeFactor
Definition: sam/BearingRangeFactor.h:34
gtsam::NonlinearFactorGraph
Definition: NonlinearFactorGraph.h:55
zero
EIGEN_DONT_INLINE Scalar zero()
Definition: svd_common.h:296
cholesky::expected
Matrix expected
Definition: testMatrix.cpp:916
gtsam::NonlinearFactorGraph::addPrior
void addPrior(Key key, const T &prior, const SharedNoiseModel &model=nullptr)
Definition: NonlinearFactorGraph.h:199
x0
static Symbol x0('x', 0)
gtsam::HybridGaussianFactorGraph
Definition: HybridGaussianFactorGraph.h:106
L
MatrixXd L
Definition: LLT_example.cpp:6
test_motion::m1
gtsam::DiscreteKey m1(M(1), 2)
gtsam::HybridValues::insert
void insert(Key j, const Vector &value)
Definition: HybridValues.cpp:85
gtsam::Point2
Vector2 Point2
Definition: Point2.h:32
gtsam::EliminateHybrid
std::pair< HybridConditional::shared_ptr, std::shared_ptr< Factor > > EliminateHybrid(const HybridGaussianFactorGraph &factors, const Ordering &keys)
Main elimination function for HybridGaussianFactorGraph.
Definition: HybridGaussianFactorGraph.cpp:536
priorNoise
auto priorNoise
Definition: doc/Code/OdometryExample.cpp:6
test_relinearization
Definition: testHybridNonlinearFactorGraph.cpp:918
EXPECT_DOUBLES_EQUAL
#define EXPECT_DOUBLES_EQUAL(expected, actual, threshold)
Definition: Test.h:161
gtsam::TableDistribution::toDecisionTreeFactor
DecisionTreeFactor toDecisionTreeFactor() const override
Get a DecisionTreeFactor representation.
Definition: TableDistribution.h:158
gtsam::HybridEliminationTree
Definition: HybridEliminationTree.h:31
ordering
static enum @1096 ordering
TEST
TEST(HybridNonlinearFactorGraph, GaussianFactorGraph)
Definition: testHybridNonlinearFactorGraph.cpp:53
TestResult
Definition: TestResult.h:26
gtsam::Conditional::nrFrontals
size_t nrFrontals() const
Definition: Conditional.h:131
gtsam::FactorGraph::size
size_t size() const
Definition: FactorGraph.h:297
batchGFG
GaussianFactorGraph::shared_ptr batchGFG(double between, Values linearizationPoint)
Definition: testHybridNonlinearFactorGraph.cpp:334
HybridEliminationTree.h
HybridNonlinearFactor.h
A set of nonlinear factors indexed by a set of discrete keys.
gtsam::Rot2
Definition: Rot2.h:35
gtsam::DiscreteConditional
Definition: DiscreteConditional.h:37
gtsam
traits
Definition: SFMdata.h:40
switching3::graph2
const HybridGaussianFactorGraph graph2
Definition: testHybridGaussianISAM.cpp:54
error
static double error
Definition: testRot3.cpp:37
NoiseModel.h
test_motion
Definition: testHybridNonlinearFactorGraph.cpp:118
NonlinearFactorGraph.h
Factor Graph consisting of non-linear factors.
gtsam::DiscreteValues
Definition: DiscreteValues.h:34
gtsam::FactorGraph::push_back
IsDerived< DERIVEDFACTOR > push_back(std::shared_ptr< DERIVEDFACTOR > factor)
Add a factor directly using a shared_ptr.
Definition: FactorGraph.h:147
DiscreteDistribution.h
gtsam::Values
Definition: Values.h:65
CHECK
#define CHECK(condition)
Definition: Test.h:108
gtsam::DiscreteKey
std::pair< Key, size_t > DiscreteKey
Definition: DiscreteKey.h:38
std
Definition: BFloat16.h:88
gtsam::FactorGraph::end
const_iterator end() const
Definition: FactorGraph.h:342
gtsam::Values::insert
void insert(Key j, const Value &val)
Definition: Values.cpp:156
gtsam::HybridNonlinearFactorGraph::linearize
std::shared_ptr< HybridGaussianFactorGraph > linearize(const Values &continuousValues) const
Linearize all the continuous factors in the HybridNonlinearFactorGraph.
Definition: HybridNonlinearFactorGraph.cpp:139
switching3::graph1
const HybridGaussianFactorGraph graph1
Definition: testHybridGaussianISAM.cpp:51
gtsam::testing::between
T between(const T &t1, const T &t2)
Definition: lieProxies.h:36
gtsam::assert_equal
bool assert_equal(const Matrix &expected, const Matrix &actual, double tol)
Definition: Matrix.cpp:41
gtsam::FactorGraph::begin
const_iterator begin() const
Definition: FactorGraph.h:339
different_sigmas::prior
const auto prior
Definition: testHybridBayesNet.cpp:240
test_motion::components
std::vector< NoiseModelFactor::shared_ptr > components
Definition: testHybridNonlinearFactorGraph.cpp:121
gtsam::HybridBayesNet::shared_ptr
std::shared_ptr< HybridBayesNet > shared_ptr
Definition: HybridBayesNet.h:42
gtsam::FactorGraph::add
IsDerived< DERIVEDFACTOR > add(std::shared_ptr< DERIVEDFACTOR > factor)
add is a synonym for push_back.
Definition: FactorGraph.h:171
graph
NonlinearFactorGraph graph
Definition: doc/Code/OdometryExample.cpp:2
model1
noiseModel::Isotropic::shared_ptr model1
Definition: testEssentialMatrixFactor.cpp:26
gtsam::Ordering
Definition: inference/Ordering.h:33
ceres::sqrt
Jet< T, N > sqrt(const Jet< T, N > &f)
Definition: jet.h:418
i
int i
Definition: BiCGSTAB_step_by_step.cpp:9
gtsam::HybridNonlinearFactor
Implementation of a discrete-conditioned hybrid factor.
Definition: HybridNonlinearFactor.h:58
gtsam::FactorGraph::emplace_shared
IsDerived< DERIVEDFACTOR > emplace_shared(Args &&... args)
Emplace a shared pointer to factor of given type.
Definition: FactorGraph.h:153
gtsam::Pose2
Definition: Pose2.h:39
BearingRangeFactor.h
a single factor contains both the bearing and the range to prevent handle to pair bearing and range f...
gtsam::BetweenFactor
Definition: BetweenFactor.h:40
M
Matrix< RealScalar, Dynamic, Dynamic > M
Definition: bench_gemm.cpp:51


gtsam
Author(s):
autogenerated on Wed Mar 19 2025 03:06:50