testHybridEstimation.cpp
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
19 #include <gtsam/geometry/Pose2.h>
20 #include <gtsam/geometry/Pose3.h>
26 #include <gtsam/inference/Symbol.h>
35 
36 // Include for test suite
38 
39 #include <bitset>
40 
41 #include "Switching.h"
42 
43 using namespace std;
44 using namespace gtsam;
45 
48 
49 TEST(HybridEstimation, Full) {
50  size_t K = 6;
51  std::vector<double> measurements = {0, 1, 2, 2, 2, 3};
52  // Ground truth discrete seq
53  std::vector<size_t> discrete_seq = {1, 1, 0, 0, 1};
54  // Switching example of robot moving in 1D
55  // with given measurements and equal mode priors.
56  Switching switching(K, 1.0, 0.1, measurements, "1/1 1/1");
58 
59  Ordering hybridOrdering;
60  for (size_t k = 0; k < K; k++) {
61  hybridOrdering.push_back(X(k));
62  }
63  for (size_t k = 0; k < K - 1; k++) {
64  hybridOrdering.push_back(M(k));
65  }
66 
68 
69  EXPECT_LONGS_EQUAL(2 * K - 1, bayesNet->size());
70 
71  HybridValues delta = bayesNet->optimize();
72 
73  Values initial = switching.linearizationPoint;
74  Values result = initial.retract(delta.continuous());
75 
76  DiscreteValues expected_discrete;
77  for (size_t k = 0; k < K - 1; k++) {
78  expected_discrete[M(k)] = discrete_seq[k];
79  }
80  EXPECT(assert_equal(expected_discrete, delta.discrete()));
81 
82  Values expected_continuous;
83  for (size_t k = 0; k < K; k++) {
84  expected_continuous.insert(X(k), measurements[k]);
85  }
86  EXPECT(assert_equal(expected_continuous, result));
87 }
88 
89 /****************************************************************************/
90 // Test approximate inference with an additional pruning step.
91 TEST(HybridEstimation, IncrementalSmoother) {
92  size_t K = 15;
93  std::vector<double> measurements = {0, 1, 2, 2, 2, 2, 3, 4, 5, 6, 6,
94  7, 8, 9, 9, 9, 10, 11, 11, 11, 11};
95  // Ground truth discrete seq
96  std::vector<size_t> discrete_seq = {1, 1, 0, 0, 0, 1, 1, 1, 1, 0,
97  1, 1, 1, 0, 0, 1, 1, 0, 0, 0};
98  // Switching example of robot moving in 1D
99  // with given measurements and equal mode priors.
100  Switching switching(K, 1.0, 0.1, measurements, "1/1 1/1");
101  HybridSmoother smoother;
103  Values initial;
104 
105  // Add the X(0) prior
106  graph.push_back(switching.nonlinearFactorGraph.at(0));
107  initial.insert(X(0), switching.linearizationPoint.at<double>(X(0)));
108 
109  HybridGaussianFactorGraph linearized;
110 
111  for (size_t k = 1; k < K; k++) {
112  // Motion Model
113  graph.push_back(switching.nonlinearFactorGraph.at(k));
114  // Measurement
115  graph.push_back(switching.nonlinearFactorGraph.at(k + K - 1));
116 
117  initial.insert(X(k), switching.linearizationPoint.at<double>(X(k)));
118 
119  linearized = *graph.linearize(initial);
120  Ordering ordering = smoother.getOrdering(linearized);
121 
122  smoother.update(linearized, 3, ordering);
123  graph.resize(0);
124  }
125 
126  HybridValues delta = smoother.hybridBayesNet().optimize();
127 
128  Values result = initial.retract(delta.continuous());
129 
130  DiscreteValues expected_discrete;
131  for (size_t k = 0; k < K - 1; k++) {
132  expected_discrete[M(k)] = discrete_seq[k];
133  }
134  EXPECT(assert_equal(expected_discrete, delta.discrete()));
135 
136  Values expected_continuous;
137  for (size_t k = 0; k < K; k++) {
138  expected_continuous.insert(X(k), measurements[k]);
139  }
140  EXPECT(assert_equal(expected_continuous, result));
141 }
142 
156  size_t K, const std::vector<double>& measurements,
157  const std::vector<size_t>& discrete_seq, double measurement_sigma = 0.1,
158  double between_sigma = 1.0) {
160  Values linearizationPoint;
161 
162  // Add measurement factors
163  auto measurement_noise = noiseModel::Isotropic::Sigma(1, measurement_sigma);
164  for (size_t k = 0; k < K; k++) {
165  graph.emplace_shared<PriorFactor<double>>(X(k), measurements.at(k),
166  measurement_noise);
167  linearizationPoint.insert<double>(X(k), static_cast<double>(k + 1));
168  }
169 
171 
172  // Add "motion models".
173  auto motion_noise_model = noiseModel::Isotropic::Sigma(1, between_sigma);
174  for (size_t k = 0; k < K - 1; k++) {
175  auto motion_model = std::make_shared<MotionModel>(
176  X(k), X(k + 1), discrete_seq.at(k), motion_noise_model);
177  graph.push_back(motion_model);
178  }
179  GaussianFactorGraph::shared_ptr linear_graph =
180  graph.linearize(linearizationPoint);
181  return linear_graph;
182 }
183 
191 template <size_t K>
192 std::vector<size_t> getDiscreteSequence(size_t x) {
193  std::bitset<K - 1> seq = x;
194  std::vector<size_t> discrete_seq(K - 1);
195  for (size_t i = 0; i < K - 1; i++) {
196  // Save to discrete vector in reverse order
197  discrete_seq[K - 2 - i] = seq[i];
198  }
199  return discrete_seq;
200 }
201 
214  Ordering continuous(graph.continuousKeySet());
215  const auto [bayesNet, remainingGraph] =
216  graph.eliminatePartialSequential(continuous);
217 
218  auto last_conditional = bayesNet->at(bayesNet->size() - 1);
219  DiscreteKeys discrete_keys = last_conditional->discreteKeys();
220 
221  const std::vector<DiscreteValues> assignments =
222  DiscreteValues::CartesianProduct(discrete_keys);
223 
224  std::reverse(discrete_keys.begin(), discrete_keys.end());
225 
226  vector<VectorValues::shared_ptr> vector_values;
227  for (const DiscreteValues& assignment : assignments) {
228  VectorValues values = bayesNet->optimize(assignment);
229  vector_values.push_back(std::make_shared<VectorValues>(values));
230  }
231  DecisionTree<Key, VectorValues::shared_ptr> delta_tree(discrete_keys,
232  vector_values);
233 
234  // Get the probPrime tree with the correct leaf probabilities
235  std::vector<double> probPrimes;
236  for (const DiscreteValues& assignment : assignments) {
237  VectorValues delta = *delta_tree(assignment);
238 
239  // If VectorValues is empty, it means this is a pruned branch.
240  // Set the probPrime to 0.0.
241  if (delta.size() == 0) {
242  probPrimes.push_back(0.0);
243  continue;
244  }
245 
246  double error = graph.error({delta, assignment});
247  probPrimes.push_back(exp(-error));
248  }
249  AlgebraicDecisionTree<Key> probPrimeTree(discrete_keys, probPrimes);
250  return probPrimeTree;
251 }
252 
253 /*********************************************************************************
254  * Test for correctness of different branches of the P'(Continuous | Discrete).
255  * The values should match those of P'(Continuous) for each discrete mode.
256  ********************************************************************************/
257 TEST(HybridEstimation, Probability) {
258  constexpr size_t K = 4;
259  std::vector<double> measurements = {0, 1, 2, 2};
260  double between_sigma = 1.0, measurement_sigma = 0.1;
261 
262  // Switching example of robot moving in 1D with
263  // given measurements and equal mode priors.
264  Switching switching(K, between_sigma, measurement_sigma, measurements,
265  "1/1 1/1");
266  auto graph = switching.linearizedFactorGraph;
267 
268  // Continuous elimination
269  Ordering continuous_ordering(graph.continuousKeySet());
270  auto [bayesNet, discreteGraph] =
271  graph.eliminatePartialSequential(continuous_ordering);
272 
273  // Discrete elimination
274  Ordering discrete_ordering(graph.discreteKeySet());
275  auto discreteBayesNet = discreteGraph->eliminateSequential(discrete_ordering);
276 
277  // Add the discrete conditionals to make it a full bayes net.
278  for (auto discrete_conditional : *discreteBayesNet) {
279  bayesNet->add(discrete_conditional);
280  }
281  auto discreteConditional = discreteBayesNet->at(0)->asDiscrete();
282 
283  HybridValues hybrid_values = bayesNet->optimize();
284 
285  // This is the correct sequence as designed
286  DiscreteValues discrete_seq;
287  discrete_seq[M(0)] = 1;
288  discrete_seq[M(1)] = 1;
289  discrete_seq[M(2)] = 0;
290 
291  EXPECT(assert_equal(discrete_seq, hybrid_values.discrete()));
292 }
293 
294 /****************************************************************************/
300 TEST(HybridEstimation, ProbabilityMultifrontal) {
301  constexpr size_t K = 4;
302  std::vector<double> measurements = {0, 1, 2, 2};
303 
304  double between_sigma = 1.0, measurement_sigma = 0.1;
305 
306  // Switching example of robot moving in 1D with given measurements and equal
307  // mode priors.
308  Switching switching(K, between_sigma, measurement_sigma, measurements,
309  "1/1 1/1");
310  auto graph = switching.linearizedFactorGraph;
311 
312  // Get the tree of unnormalized probabilities for each mode sequence.
313  AlgebraicDecisionTree<Key> expected_probPrimeTree = getProbPrimeTree(graph);
314 
315  // Eliminate continuous
316  Ordering continuous_ordering(graph.continuousKeySet());
317  const auto [bayesTree, discreteGraph] =
318  graph.eliminatePartialMultifrontal(continuous_ordering);
319 
320  // Get the last continuous conditional which will have all the discrete keys
321  Key last_continuous_key =
322  continuous_ordering.at(continuous_ordering.size() - 1);
323  auto last_conditional = (*bayesTree)[last_continuous_key]->conditional();
324  DiscreteKeys discrete_keys = last_conditional->discreteKeys();
325 
326  Ordering discrete(graph.discreteKeySet());
327  auto discreteBayesTree = discreteGraph->eliminateMultifrontal(discrete);
328 
329  EXPECT_LONGS_EQUAL(1, discreteBayesTree->size());
330  // DiscreteBayesTree should have only 1 clique
331  auto discrete_clique = (*discreteBayesTree)[discrete.at(0)];
332 
333  std::set<HybridBayesTreeClique::shared_ptr> clique_set;
334  for (auto node : bayesTree->nodes()) {
335  clique_set.insert(node.second);
336  }
337 
338  // Set the root of the bayes tree as the discrete clique
339  for (auto clique : clique_set) {
340  if (clique->conditional()->parents() ==
341  discrete_clique->conditional()->frontals()) {
342  discreteBayesTree->addClique(clique, discrete_clique);
343 
344  } else {
345  // Remove the clique from the children of the parents since
346  // it will get added again in addClique.
347  auto clique_it = std::find(clique->parent()->children.begin(),
348  clique->parent()->children.end(), clique);
349  clique->parent()->children.erase(clique_it);
350  discreteBayesTree->addClique(clique, clique->parent());
351  }
352  }
353 
354  HybridValues hybrid_values = discreteBayesTree->optimize();
355 
356  // This is the correct sequence as designed
357  DiscreteValues discrete_seq;
358  discrete_seq[M(0)] = 1;
359  discrete_seq[M(1)] = 1;
360  discrete_seq[M(2)] = 0;
361 
362  EXPECT(assert_equal(discrete_seq, hybrid_values.discrete()));
363 }
364 
365 /*********************************************************************************
366  // Create a hybrid nonlinear factor graph f(x0, x1, m0; z0, z1)
367  ********************************************************************************/
370 
371  constexpr double sigma = 0.5; // measurement noise
372  const auto noise_model = noiseModel::Isotropic::Sigma(1, sigma);
373 
374  // Add "measurement" factors:
375  nfg.emplace_shared<PriorFactor<double>>(X(0), 0.0, noise_model);
376  nfg.emplace_shared<PriorFactor<double>>(X(1), 1.0, noise_model);
377 
378  // Add mixture factor:
379  DiscreteKey m(M(0), 2);
380  const auto zero_motion =
381  std::make_shared<BetweenFactor<double>>(X(0), X(1), 0, noise_model);
382  const auto one_motion =
383  std::make_shared<BetweenFactor<double>>(X(0), X(1), 1, noise_model);
385  KeyVector{X(0), X(1)}, DiscreteKeys{m},
386  std::vector<NonlinearFactor::shared_ptr>{zero_motion, one_motion});
387 
388  return nfg;
389 }
390 
391 /*********************************************************************************
392  // Create a hybrid linear factor graph f(x0, x1, m0; z0, z1)
393  ********************************************************************************/
396 
397  Values initial;
398  double z0 = 0.0, z1 = 1.0;
399  initial.insert<double>(X(0), z0);
400  initial.insert<double>(X(1), z1);
401  return nfg.linearize(initial);
402 }
403 
404 /*********************************************************************************
405  * Do hybrid elimination and do regression test on discrete conditional.
406  ********************************************************************************/
407 TEST(HybridEstimation, eliminateSequentialRegression) {
408  // Create the factor graph from the nonlinear factor graph.
410 
411  // Create expected discrete conditional on m0.
412  DiscreteKey m(M(0), 2);
413  DiscreteConditional expected(m % "0.51341712/1"); // regression
414 
415  // Eliminate into BN using one ordering
416  const Ordering ordering1{X(0), X(1), M(0)};
417  HybridBayesNet::shared_ptr bn1 = fg->eliminateSequential(ordering1);
418 
419  // Check that the discrete conditional matches the expected.
420  auto dc1 = bn1->back()->asDiscrete();
421  EXPECT(assert_equal(expected, *dc1, 1e-9));
422 
423  // Eliminate into BN using a different ordering
424  const Ordering ordering2{X(0), X(1), M(0)};
425  HybridBayesNet::shared_ptr bn2 = fg->eliminateSequential(ordering2);
426 
427  // Check that the discrete conditional matches the expected.
428  auto dc2 = bn2->back()->asDiscrete();
429  EXPECT(assert_equal(expected, *dc2, 1e-9));
430 }
431 
432 /*********************************************************************************
433  * Test for correctness via sampling.
434  *
435  * Compute the conditional P(x0, m0, x1| z0, z1)
436  * with measurements z0, z1. To do so, we:
437  * 1. Start with the corresponding Factor Graph `FG`.
438  * 2. Eliminate the factor graph into a Bayes Net `BN`.
439  * 3. Sample from the Bayes Net.
440  * 4. Check that the ratio `BN(x)/FG(x) = constant` for all samples `x`.
441  ********************************************************************************/
442 TEST(HybridEstimation, CorrectnessViaSampling) {
443  // 1. Create the factor graph from the nonlinear factor graph.
444  const auto fg = createHybridGaussianFactorGraph();
445 
446  // 2. Eliminate into BN
447  const HybridBayesNet::shared_ptr bn = fg->eliminateSequential();
448 
449  // Set up sampling
450  std::mt19937_64 rng(11);
451 
452  // Compute the log-ratio between the Bayes net and the factor graph.
453  auto compute_ratio = [&](const HybridValues& sample) -> double {
454  return bn->evaluate(sample) / fg->probPrime(sample);
455  };
456 
457  // The error evaluated by the factor graph and the Bayes net should differ by
458  // the normalizing term computed via the Bayes net determinant.
459  const HybridValues sample = bn->sample(&rng);
460  double expected_ratio = compute_ratio(sample);
461  // regression
462  EXPECT_DOUBLES_EQUAL(0.728588, expected_ratio, 1e-6);
463 
464  // 3. Do sampling
465  constexpr int num_samples = 10;
466  for (size_t i = 0; i < num_samples; i++) {
467  // Sample from the bayes net
468  const HybridValues sample = bn->sample(&rng);
469 
470  // 4. Check that the ratio is constant.
471  EXPECT_DOUBLES_EQUAL(expected_ratio, compute_ratio(sample), 1e-6);
472  }
473 }
474 
475 /****************************************************************************/
480 std::shared_ptr<GaussianMixtureFactor> mixedVarianceFactor(
481  const MixtureFactor& mf, const Values& initial, const Key& mode,
482  double noise_tight, double noise_loose, size_t d, size_t tight_index) {
484 
485  constexpr double log2pi = 1.8378770664093454835606594728112;
486  // logConstant will be of the tighter model
487  double logNormalizationConstant = log(1.0 / noise_tight);
488  double logConstant = -0.5 * d * log2pi + logNormalizationConstant;
489 
490  auto func = [&](const Assignment<Key>& assignment,
491  const GaussianFactor::shared_ptr& gf) {
492  if (assignment.at(mode) != tight_index) {
493  double factor_log_constant = -0.5 * d * log2pi + log(1.0 / noise_loose);
494 
495  GaussianFactorGraph _gfg;
496  _gfg.push_back(gf);
497  Vector c(d);
498  for (size_t i = 0; i < d; i++) {
499  c(i) = std::sqrt(2.0 * (logConstant - factor_log_constant));
500  }
501 
503  return std::make_shared<JacobianFactor>(_gfg);
504  } else {
505  return dynamic_pointer_cast<JacobianFactor>(gf);
506  }
507  };
508  auto updated_components = gmf->factors().apply(func);
509  auto updated_gmf = std::make_shared<GaussianMixtureFactor>(
510  gmf->continuousKeys(), gmf->discreteKeys(), updated_components);
511 
512  return updated_gmf;
513 }
514 
515 /****************************************************************************/
516 TEST(HybridEstimation, ModeSelection) {
518  Values initial;
519 
520  auto measurement_model = noiseModel::Isotropic::Sigma(1, 0.1);
521  auto motion_model = noiseModel::Isotropic::Sigma(1, 1.0);
522 
523  graph.emplace_shared<PriorFactor<double>>(X(0), 0.0, measurement_model);
524  graph.emplace_shared<PriorFactor<double>>(X(1), 0.0, measurement_model);
525 
526  DiscreteKeys modes;
527  modes.emplace_back(M(0), 2);
528 
529  // The size of the noise model
530  size_t d = 1;
531  double noise_tight = 0.5, noise_loose = 5.0;
532 
533  auto model0 = std::make_shared<MotionModel>(
534  X(0), X(1), 0.0, noiseModel::Isotropic::Sigma(d, noise_loose)),
535  model1 = std::make_shared<MotionModel>(
536  X(0), X(1), 0.0, noiseModel::Isotropic::Sigma(d, noise_tight));
537 
538  std::vector<NonlinearFactor::shared_ptr> components = {model0, model1};
539 
540  KeyVector keys = {X(0), X(1)};
541  MixtureFactor mf(keys, modes, components);
542 
543  initial.insert(X(0), 0.0);
544  initial.insert(X(1), 0.0);
545 
546  auto gmf =
547  mixedVarianceFactor(mf, initial, M(0), noise_tight, noise_loose, d, 1);
548  graph.add(gmf);
549 
550  auto gfg = graph.linearize(initial);
551 
552  HybridBayesNet::shared_ptr bayesNet = gfg->eliminateSequential();
553 
554  HybridValues delta = bayesNet->optimize();
555  EXPECT_LONGS_EQUAL(1, delta.discrete().at(M(0)));
556 
557  /**************************************************************/
558  HybridBayesNet bn;
559  const DiscreteKey mode{M(0), 2};
560 
561  bn.push_back(
562  GaussianConditional::sharedMeanAndStddev(Z(0), -I_1x1, X(0), Z_1x1, 0.1));
563  bn.push_back(
564  GaussianConditional::sharedMeanAndStddev(Z(0), -I_1x1, X(1), Z_1x1, 0.1));
565  bn.emplace_back(new GaussianMixture(
566  {Z(0)}, {X(0), X(1)}, {mode},
567  {GaussianConditional::sharedMeanAndStddev(Z(0), I_1x1, X(0), -I_1x1, X(1),
568  Z_1x1, noise_loose),
569  GaussianConditional::sharedMeanAndStddev(Z(0), I_1x1, X(0), -I_1x1, X(1),
570  Z_1x1, noise_tight)}));
571 
573  vv.insert(Z(0), Z_1x1);
574 
575  auto fg = bn.toFactorGraph(vv);
576  auto expected_posterior = fg.eliminateSequential();
577 
578  EXPECT(assert_equal(*expected_posterior, *bayesNet, 1e-6));
579 }
580 
581 /****************************************************************************/
582 TEST(HybridEstimation, ModeSelection2) {
583  using symbol_shorthand::Z;
584 
585  // The size of the noise model
586  size_t d = 3;
587  double noise_tight = 0.5, noise_loose = 5.0;
588 
589  HybridBayesNet bn;
590  const DiscreteKey mode{M(0), 2};
591 
592  bn.push_back(
593  GaussianConditional::sharedMeanAndStddev(Z(0), -I_3x3, X(0), Z_3x1, 0.1));
594  bn.push_back(
595  GaussianConditional::sharedMeanAndStddev(Z(0), -I_3x3, X(1), Z_3x1, 0.1));
597  {Z(0)}, {X(0), X(1)}, {mode},
598  {GaussianConditional::sharedMeanAndStddev(Z(0), I_3x3, X(0), -I_3x3, X(1),
599  Z_3x1, noise_loose),
600  GaussianConditional::sharedMeanAndStddev(Z(0), I_3x3, X(0), -I_3x3, X(1),
601  Z_3x1, noise_tight)}));
602 
604  vv.insert(Z(0), Z_3x1);
605 
606  auto fg = bn.toFactorGraph(vv);
607 
608  auto expected_posterior = fg.eliminateSequential();
609 
610  // =====================================
611 
613  Values initial;
614 
615  auto measurement_model = noiseModel::Isotropic::Sigma(d, 0.1);
616  auto motion_model = noiseModel::Isotropic::Sigma(d, 1.0);
617 
618  graph.emplace_shared<PriorFactor<Vector3>>(X(0), Z_3x1, measurement_model);
619  graph.emplace_shared<PriorFactor<Vector3>>(X(1), Z_3x1, measurement_model);
620 
621  DiscreteKeys modes;
622  modes.emplace_back(M(0), 2);
623 
624  auto model0 = std::make_shared<BetweenFactor<Vector3>>(
625  X(0), X(1), Z_3x1, noiseModel::Isotropic::Sigma(d, noise_loose)),
627  X(0), X(1), Z_3x1, noiseModel::Isotropic::Sigma(d, noise_tight));
628 
629  std::vector<NonlinearFactor::shared_ptr> components = {model0, model1};
630 
631  KeyVector keys = {X(0), X(1)};
632  MixtureFactor mf(keys, modes, components);
633 
634  initial.insert<Vector3>(X(0), Z_3x1);
635  initial.insert<Vector3>(X(1), Z_3x1);
636 
637  auto gmf =
638  mixedVarianceFactor(mf, initial, M(0), noise_tight, noise_loose, d, 1);
639  graph.add(gmf);
640 
641  auto gfg = graph.linearize(initial);
642 
643  HybridBayesNet::shared_ptr bayesNet = gfg->eliminateSequential();
644 
645  EXPECT(assert_equal(*expected_posterior, *bayesNet, 1e-6));
646 }
647 
648 /* ************************************************************************* */
649 int main() {
650  TestResult tr;
651  return TestRegistry::runAllTests(tr);
652 }
653 /* ************************************************************************* */
std::shared_ptr< GaussianMixtureFactor > mixedVarianceFactor(const MixtureFactor &mf, const Values &initial, const Key &mode, double noise_tight, double noise_loose, size_t d, size_t tight_index)
Matrix3f m
Matrix< RealScalar, Dynamic, Dynamic > M
Definition: bench_gemm.cpp:51
An incremental smoother for hybrid factor graphs.
static const Eigen::MatrixBase< Vector3 >::ConstantReturnType Z_3x1
Definition: Vector.h:46
Nonlinear hybrid factor graph that uses type erasure.
IsDerived< DERIVEDFACTOR > emplace_shared(Args &&... args)
Emplace a shared pointer to factor of given type.
Definition: FactorGraph.h:196
static int runAllTests(TestResult &result)
Eigen::Vector3d Vector3
Definition: Vector.h:43
Factor Graph consisting of non-linear factors.
std::vector< size_t > getDiscreteSequence(size_t x)
Get the discrete sequence from the integer x.
const ValueType at(Key j) const
Definition: Values-inl.h:204
Matrix expected
Definition: testMatrix.cpp:971
IsDerived< DERIVEDFACTOR > push_back(std::shared_ptr< DERIVEDFACTOR > factor)
Add a factor directly using a shared_ptr.
Definition: FactorGraph.h:190
static std::mt19937 rng
bool assert_equal(const Matrix &expected, const Matrix &actual, double tol)
Definition: Matrix.cpp:40
std::pair< std::shared_ptr< BayesNetType >, std::shared_ptr< FactorGraphType > > eliminatePartialSequential(const Ordering &ordering, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex={}) const
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
leaf::MyValues values
static Cal3_S2 K(500, 500, 0.1, 640/2, 480/2)
Values initial
Definition: BFloat16.h:88
iterator insert(const std::pair< Key, Vector > &key_value)
const VectorValues & continuous() const
Return the multi-dimensional vector values.
Definition: HybridValues.h:89
const HybridBayesNet & hybridBayesNet() const
Return the Bayes Net posterior.
Nonlinear Mixture factor of continuous and discrete.
AlgebraicDecisionTree< Key > getProbPrimeTree(const HybridGaussianFactorGraph &graph)
Helper method to get the tree of unnormalized probabilities as per the elimination scheme...
NonlinearFactorGraph graph
EIGEN_DEVICE_FUNC const LogReturnType log() const
static enum @1107 ordering
#define EXPECT_DOUBLES_EQUAL(expected, actual, threshold)
Definition: Test.h:161
noiseModel::Isotropic::shared_ptr model1
IsDerived< DERIVEDFACTOR > add(std::shared_ptr< DERIVEDFACTOR > factor)
add is a synonym for push_back.
Definition: FactorGraph.h:214
A Bayes net of Gaussian Conditionals indexed by discrete keys.
Values retract(const VectorValues &delta) const
Definition: Values.cpp:98
std::shared_ptr< GaussianFactorGraph > linearize(const Values &linearizationPoint) const
Linearize a nonlinear factor graph.
EIGEN_DEVICE_FUNC const ExpReturnType exp() const
static const VectorValues vv
HybridGaussianFactorGraph linearizedFactorGraph
Definition: Switching.h:124
#define Z
Definition: icosphere.cpp:21
A conditional of gaussian mixtures indexed by discrete variables, as part of a Bayes Network...
Eigen::VectorXd Vector
Definition: Vector.h:38
Values result
gtsam::enable_if_t< needs_eigen_aligned_allocator< T >::value, std::shared_ptr< T > > make_shared(Args &&... args)
Definition: make_shared.h:56
int main()
HybridValues optimize() const
Solve the HybridBayesNet by first computing the MPE of all the discrete variables and then optimizing...
GaussianFactor::shared_ptr linearize(const Values &continuousValues, const DiscreteValues &discreteValues) const
AlgebraicDecisionTree< Key > error(const VectorValues &continuousValues) const
Compute error for each discrete assignment, and return as a tree.
#define EXPECT(condition)
Definition: Test.h:150
const KeySet continuousKeySet() const
Get all the continuous keys in the factor graph.
std::shared_ptr< BayesNetType > eliminateSequential(OptionalOrderingType orderingType={}, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex={}) const
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Linear Factor Graph where all factors are Gaussians.
std::shared_ptr< This > shared_ptr
shared_ptr to This
void push_back(std::shared_ptr< HybridConditional > conditional)
Add a hybrid conditional using a shared_ptr.
std::shared_ptr< This > shared_ptr
shared_ptr to this class
std::shared_ptr< This > shared_ptr
void emplace_back(Conditional *conditional)
traits
Definition: chartTesting.h:28
internal::enable_if<!(symbolic::is_symbolic< FirstType >::value||symbolic::is_symbolic< LastType >::value), ArithmeticSequence< typename internal::cleanup_index_type< FirstType >::type, Index > >::type seq(FirstType f, LastType l)
virtual void resize(size_t size)
Definition: FactorGraph.h:389
Values linearizationPoint
Definition: Switching.h:125
#define EXPECT_LONGS_EQUAL(expected, actual)
Definition: Test.h:154
HybridNonlinearFactorGraph nonlinearFactorGraph
Definition: Switching.h:123
void reverse(const MatrixType &m)
const sharedFactor at(size_t i) const
Definition: FactorGraph.h:343
const DiscreteValues & discrete() const
Return the discrete values.
Definition: HybridValues.h:92
std::pair< Key, size_t > DiscreteKey
Definition: DiscreteKey.h:38
std::shared_ptr< HybridGaussianFactorGraph > linearize(const Values &continuousValues) const
Linearize all the continuous factors in the HybridNonlinearFactorGraph.
Chordal Bayes Net, the result of eliminating a factor graph.
static const double sigma
size_t size() const
Definition: VectorValues.h:127
TEST(HybridEstimation, Full)
void insert(Key j, const Value &val)
Definition: Values.cpp:155
static double error
Definition: testRot3.cpp:37
Jet< T, N > sqrt(const Jet< T, N > &f)
Definition: jet.h:418
static const DiscreteKey mode(modeKey, 2)
Ordering getOrdering(const HybridGaussianFactorGraph &newFactors)
Implementation of a discrete conditional mixture factor.
Definition: MixtureFactor.h:47
const KeyVector keys
static HybridNonlinearFactorGraph createHybridNonlinearFactorGraph()
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:86
GaussianFactorGraph::shared_ptr specificModesFactorGraph(size_t K, const std::vector< double > &measurements, const std::vector< size_t > &discrete_seq, double measurement_sigma=0.1, double between_sigma=1.0)
A function to get a specific 1D robot motion problem as a linearized factor graph. This is the problem P(X|Z, M), i.e. estimating the continuous positions given the measurements and discrete sequence.
2D Pose
#define X
Definition: icosphere.cpp:20
void update(HybridGaussianFactorGraph graph, std::optional< size_t > maxNrLeaves={}, const std::optional< Ordering > given_ordering={})
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
Matrix2f mf
3D Pose
Gaussian Bayes Tree, the result of eliminating a GaussianJunctionTree.
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:102
std::shared_ptr< HybridBayesNet > shared_ptr
HybridGaussianFactorGraph toFactorGraph(const VectorValues &measurements) const
static HybridGaussianFactorGraph::shared_ptr createHybridGaussianFactorGraph()
DiscreteKeys is a set of keys that can be assembled using the & operator.
Definition: DiscreteKey.h:41


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:38:22