testHybridGaussianFactor.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 
21 #include <gtsam/base/Testable.h>
30 #include <gtsam/inference/Symbol.h>
35 
36 // Include for test suite
38 
39 #include <memory>
40 
41 using namespace std;
42 using namespace gtsam;
46 
47 /* ************************************************************************* */
48 // Check iterators of empty hybrid factor.
49 TEST(HybridGaussianFactor, Constructor) {
50  HybridGaussianFactor factor;
51  HybridGaussianFactor::const_iterator const_it = factor.begin();
52  CHECK(const_it == factor.end());
53  HybridGaussianFactor::iterator it = factor.begin();
54  CHECK(it == factor.end());
55 }
56 
57 /* ************************************************************************* */
58 namespace test_constructor {
59 DiscreteKey m1(1, 2);
60 
61 auto A1 = Matrix::Zero(2, 1);
62 auto A2 = Matrix::Zero(2, 2);
63 auto b = Matrix::Zero(2, 1);
64 
65 auto f10 = std::make_shared<JacobianFactor>(X(1), A1, X(2), A2, b);
66 auto f11 = std::make_shared<JacobianFactor>(X(1), A1, X(2), A2, b);
67 } // namespace test_constructor
68 
69 /* ************************************************************************* */
70 // Test simple to complex constructors...
71 TEST(HybridGaussianFactor, ConstructorVariants) {
72  using namespace test_constructor;
73  HybridGaussianFactor fromFactors(m1, {f10, f11});
74 
75  std::vector<GaussianFactorValuePair> pairs{{f10, 0.0}, {f11, 0.0}};
76  HybridGaussianFactor fromPairs(m1, pairs);
77  assert_equal(fromFactors, fromPairs);
78 
79  HybridGaussianFactor::FactorValuePairs decisionTree({m1}, pairs);
80  HybridGaussianFactor fromDecisionTree({m1}, decisionTree);
81  assert_equal(fromDecisionTree, fromPairs);
82 }
83 
84 /* ************************************************************************* */
86  using namespace test_constructor;
88  // Check the number of keys matches what we expect
92 
93  DiscreteKey m2(2, 3);
94  auto A3 = Matrix::Zero(2, 3);
95  auto f20 = std::make_shared<JacobianFactor>(X(1), A1, X(3), A3, b);
96  auto f21 = std::make_shared<JacobianFactor>(X(1), A1, X(3), A3, b);
97  auto f22 = std::make_shared<JacobianFactor>(X(1), A1, X(3), A3, b);
99 
100  // Check the number of keys matches what we expect
104 }
105 
106 /* ************************************************************************* */
108  using namespace test_constructor;
109  HybridGaussianFactor hybridFactor(m1, {f10, f11});
110 
111  std::string expected =
112  R"(Hybrid [x1 x2; 1]{
113  Choice(1)
114  0 Leaf :
115  A[x1] = [
116  0;
117  0
118 ]
119  A[x2] = [
120  0, 0;
121  0, 0
122 ]
123  b = [ 0 0 ]
124  No noise model
125 scalar: 0
126 
127  1 Leaf :
128  A[x1] = [
129  0;
130  0
131 ]
132  A[x2] = [
133  0, 0;
134  0, 0
135 ]
136  b = [ 0 0 ]
137  No noise model
138 scalar: 0
139 
140 }
141 )";
142  EXPECT(assert_print_equal(expected, hybridFactor));
143 }
144 
145 /* ************************************************************************* */
147  DiscreteKeys dKeys;
148  dKeys.emplace_back(M(0), 2);
149  dKeys.emplace_back(M(1), 2);
150 
151  auto gaussians = std::make_shared<GaussianConditional>();
154 
155  EXPECT_LONGS_EQUAL(2, gm.discreteKeys().size());
156 }
157 
158 /* ************************************************************************* */
159 // Test the error of the HybridGaussianFactor
160 TEST(HybridGaussianFactor, Error) {
161  DiscreteKey m1(1, 2);
162 
163  auto A01 = Matrix2::Identity();
164  auto A02 = Matrix2::Identity();
165 
166  auto A11 = Matrix2::Identity();
167  auto A12 = Matrix2::Identity() * 2;
168 
169  auto b = Vector2::Zero();
170 
171  auto f0 = std::make_shared<JacobianFactor>(X(1), A01, X(2), A02, b);
172  auto f1 = std::make_shared<JacobianFactor>(X(1), A11, X(2), A12, b);
173  HybridGaussianFactor hybridFactor(m1, {f0, f1});
174 
175  VectorValues continuousValues;
176  continuousValues.insert(X(1), Vector2(0, 0));
177  continuousValues.insert(X(2), Vector2(1, 1));
178 
179  // error should return a tree of errors, with nodes for each discrete value.
180  AlgebraicDecisionTree<Key> error_tree =
181  hybridFactor.errorTree(continuousValues);
182 
183  std::vector<DiscreteKey> discrete_keys = {m1};
184  // Error values for regression test
185  std::vector<double> errors = {1, 4};
186  AlgebraicDecisionTree<Key> expected_error(discrete_keys, errors);
187 
188  EXPECT(assert_equal(expected_error, error_tree));
189 
190  // Test for single leaf given discrete assignment P(X|M,Z).
191  DiscreteValues discreteValues;
192  discreteValues[m1.first] = 1;
194  4.0, hybridFactor.error({continuousValues, discreteValues}), 1e-9);
195 }
196 
197 /* ************************************************************************* */
198 namespace test_direct_factor_graph {
212  const gtsam::Values &values, const std::vector<double> &means,
213  const std::vector<double> &sigmas, DiscreteKey &m1,
214  double measurement_noise = 1e-3) {
215  auto model0 = noiseModel::Isotropic::Sigma(1, sigmas[0]);
216  auto model1 = noiseModel::Isotropic::Sigma(1, sigmas[1]);
217  auto prior_noise = noiseModel::Isotropic::Sigma(1, measurement_noise);
218 
219  auto f0 =
220  std::make_shared<BetweenFactor<double>>(X(0), X(1), means[0], model0)
221  ->linearize(values);
222  auto f1 =
223  std::make_shared<BetweenFactor<double>>(X(0), X(1), means[1], model1)
224  ->linearize(values);
225 
226  // Create HybridGaussianFactor
227  // We take negative since we want
228  // the underlying scalar to be log(\sqrt(|2πΣ|))
229  std::vector<GaussianFactorValuePair> factors{{f0, model0->negLogConstant()},
230  {f1, model1->negLogConstant()}};
231  HybridGaussianFactor motionFactor(m1, factors);
232 
234  hfg.push_back(motionFactor);
235 
236  hfg.push_back(PriorFactor<double>(X(0), values.at<double>(X(0)), prior_noise)
237  .linearize(values));
238 
239  return hfg;
240 }
241 } // namespace test_direct_factor_graph
242 
243 /* ************************************************************************* */
251 TEST(HybridGaussianFactor, DifferentMeansFG) {
252  using namespace test_direct_factor_graph;
253 
254  DiscreteKey m1(M(1), 2);
255 
256  Values values;
257  double x1 = 0.0, x2 = 1.75;
258  values.insert(X(0), x1);
259  values.insert(X(1), x2);
260 
261  std::vector<double> means = {0.0, 2.0}, sigmas = {1e-0, 1e-0};
262 
264 
265  {
266  auto bn = hfg.eliminateSequential();
267  HybridValues actual = bn->optimize();
268 
270  VectorValues{{X(0), Vector1(0.0)}, {X(1), Vector1(-1.75)}},
271  DiscreteValues{{M(1), 0}});
272 
273  EXPECT(assert_equal(expected, actual));
274 
275  DiscreteValues dv0{{M(1), 0}};
276  VectorValues cont0 = bn->optimize(dv0);
277  double error0 = bn->error(HybridValues(cont0, dv0));
278  // regression
279  EXPECT_DOUBLES_EQUAL(0.69314718056, error0, 1e-9);
280 
281  DiscreteValues dv1{{M(1), 1}};
282  VectorValues cont1 = bn->optimize(dv1);
283  double error1 = bn->error(HybridValues(cont1, dv1));
284  EXPECT_DOUBLES_EQUAL(error0, error1, 1e-9);
285  }
286 
287  {
288  auto prior_noise = noiseModel::Isotropic::Sigma(1, 1e-3);
289  hfg.push_back(
290  PriorFactor<double>(X(1), means[1], prior_noise).linearize(values));
291 
292  auto bn = hfg.eliminateSequential();
293  HybridValues actual = bn->optimize();
294 
296  VectorValues{{X(0), Vector1(0.0)}, {X(1), Vector1(0.25)}},
297  DiscreteValues{{M(1), 1}});
298 
299  EXPECT(assert_equal(expected, actual));
300 
301  {
302  DiscreteValues dv{{M(1), 0}};
303  VectorValues cont = bn->optimize(dv);
304  double error = bn->error(HybridValues(cont, dv));
305  // regression
306  EXPECT_DOUBLES_EQUAL(2.12692448787, error, 1e-9);
307  }
308  {
309  DiscreteValues dv{{M(1), 1}};
310  VectorValues cont = bn->optimize(dv);
311  double error = bn->error(HybridValues(cont, dv));
312  // regression
313  EXPECT_DOUBLES_EQUAL(0.126928487854, error, 1e-9);
314  }
315  }
316 }
317 
318 /* ************************************************************************* */
326 TEST(HybridGaussianFactor, DifferentCovariancesFG) {
327  using namespace test_direct_factor_graph;
328 
329  DiscreteKey m1(M(1), 2);
330 
331  Values values;
332  double x1 = 1.0, x2 = 1.0;
333  values.insert(X(0), x1);
334  values.insert(X(1), x2);
335 
336  std::vector<double> means = {0.0, 0.0}, sigmas = {1e2, 1e-2};
337 
338  // Create FG with HybridGaussianFactor and prior on X1
340  auto hbn = fg.eliminateSequential();
341 
342  VectorValues cv;
343  cv.insert(X(0), Vector1(0.0));
344  cv.insert(X(1), Vector1(0.0));
345 
346  DiscreteValues dv0{{M(1), 0}};
347  DiscreteValues dv1{{M(1), 1}};
348 
349  DiscreteConditional expected_m1(m1, "0.5/0.5");
350  DiscreteConditional actual_m1 = *(hbn->at(2)->asDiscrete());
351 
352  EXPECT(assert_equal(expected_m1, actual_m1));
353 }
354 
355 /* ************************************************************************* */
356 int main() {
357  TestResult tr;
358  return TestRegistry::runAllTests(tr);
359 }
360 /* ************************************************************************* */
TestRegistry::runAllTests
static int runAllTests(TestResult &result)
Definition: TestRegistry.cpp:27
gtsam::EliminateableFactorGraph::eliminateSequential
std::shared_ptr< BayesNetType > eliminateSequential(OptionalOrderingType orderingType={}, const Eliminate &function=EliminationTraitsType::DefaultEliminate, OptionalVariableIndex variableIndex={}) const
Definition: EliminateableFactorGraph-inst.h:29
GaussianFactorGraph.h
Linear Factor Graph where all factors are Gaussians.
gtsam::HybridValues
Definition: HybridValues.h:37
test_constructor::b
auto b
Definition: testHybridGaussianFactor.cpp:63
test_constructor::f1
auto f1
Definition: testHybridNonlinearFactor.cpp:56
A3
static const double A3[]
Definition: expn.h:8
HybridGaussianConditional.h
A hybrid conditional in the Conditional Linear Gaussian scheme.
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
EXPECT_LONGS_EQUAL
#define EXPECT_LONGS_EQUAL(expected, actual)
Definition: Test.h:154
examples::hybridFactorA
const HybridGaussianFactor hybridFactorA(m1, {{f10, 10}, {f11, 11}})
Testable.h
Concept check for values that can be used in unit tests.
EXPECT
#define EXPECT(condition)
Definition: Test.h:150
gtsam::Vector2
Eigen::Vector2d Vector2
Definition: Vector.h:42
test_constructor::sigmas
Vector1 sigmas
Definition: testHybridNonlinearFactor.cpp:52
TestHarness.h
test_constructor::m1
DiscreteKey m1(1, 2)
gtsam::VectorValues::insert
iterator insert(const std::pair< Key, Vector > &key_value)
Definition: VectorValues.cpp:88
test_constructor
Definition: testHybridGaussianFactor.cpp:58
gtsam::assert_print_equal
bool assert_print_equal(const std::string &expected, const V &actual, const std::string &s="")
Definition: TestableAssertions.h:352
simple_graph::factors
const GaussianFactorGraph factors
Definition: testJacobianFactor.cpp:213
gtsam::PriorFactor
Definition: nonlinear/PriorFactor.h:30
HybridBayesNet.h
A Bayes net of Gaussian Conditionals indexed by discrete keys.
different_sigmas::values
HybridValues values
Definition: testHybridBayesNet.cpp:245
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
DiscreteConditional.h
gtsam::Factor::begin
const_iterator begin() const
Definition: Factor.h:146
gtsam::means
Point2Pair means(const std::vector< Point2Pair > &abPointPairs)
Calculate the two means of a set of Point2 pairs.
Definition: Point2.cpp:116
HybridGaussianFactor.h
A set of GaussianFactors, indexed by a set of discrete keys.
equal_constants::conditionals
const std::vector< GaussianConditional::shared_ptr > conditionals
Definition: testHybridGaussianConditional.cpp:53
test_constructor::f10
auto f10
Definition: testHybridGaussianFactor.cpp:65
TestableAssertions.h
Provides additional testing facilities for common data structures.
gtsam::AlgebraicDecisionTree< Key >
examples::f22
const auto f22
Definition: testHybridGaussianProductFactor.cpp:53
m2
MatrixType m2(n_dims)
Vector1
Eigen::Matrix< double, 1, 1 > Vector1
Definition: testEvent.cpp:33
PriorFactor.h
gtsam::VectorValues
Definition: VectorValues.h:74
test_constructor::f0
auto f0
Definition: testHybridNonlinearFactor.cpp:55
BetweenFactor.h
x1
Pose3 x1
Definition: testPose3.cpp:663
examples::f21
const auto f21
Definition: testHybridGaussianProductFactor.cpp:52
A2
static const double A2[]
Definition: expn.h:7
cholesky::expected
Matrix expected
Definition: testMatrix.cpp:971
gtsam::HybridGaussianConditional
A conditional of gaussian conditionals indexed by discrete variables, as part of a Bayes Network....
Definition: HybridGaussianConditional.h:54
main
int main()
Definition: testHybridGaussianFactor.cpp:327
gtsam::HybridGaussianFactorGraph
Definition: HybridGaussianFactorGraph.h:105
test_constructor::f11
auto f11
Definition: testHybridGaussianFactor.cpp:66
Symbol.h
gtsam::HybridValues::insert
void insert(Key j, const Vector &value)
Definition: HybridValues.cpp:85
VectorValues.h
Factor Graph Values.
gtsam::Factor::end
const_iterator end() const
Definition: Factor.h:149
A12
static const double A12[]
Definition: expn.h:17
examples::hybridFactorB
const HybridGaussianFactor hybridFactorB(m2, {{f20, 20}, {f21, 21}, {f22, 22}})
EXPECT_DOUBLES_EQUAL
#define EXPECT_DOUBLES_EQUAL(expected, actual, threshold)
Definition: Test.h:161
TestResult
Definition: TestResult.h:26
gtsam::DecisionTree< Key, GaussianFactorValuePair >
gtsam::DiscreteConditional
Definition: DiscreteConditional.h:37
gtsam::HybridValues::at
Vector & at(Key j)
Definition: HybridValues.cpp:129
TEST
TEST(HybridGaussianFactor, Constructor)
Definition: testHybridGaussianFactor.cpp:49
HybridGaussianFactorGraph.h
Linearized Hybrid factor graph that uses type erasure.
gtsam
traits
Definition: SFMdata.h:40
DiscreteValues.h
error
static double error
Definition: testRot3.cpp:37
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
gtsam::Values
Definition: Values.h:65
gtsam::Factor::keys
const KeyVector & keys() const
Access the factor's involved variable keys.
Definition: Factor.h:143
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::HybridGaussianFactor
Implementation of a discrete-conditioned hybrid factor. Implements a joint discrete-continuous factor...
Definition: HybridGaussianFactor.h:60
A1
static const double A1[]
Definition: expn.h:6
gtsam::HybridFactor::continuousKeys
const KeyVector & continuousKeys() const
Return only the continuous keys for this factor.
Definition: HybridFactor.h:134
A11
static const double A11[]
Definition: expn.h:16
gtsam::assert_equal
bool assert_equal(const Matrix &expected, const Matrix &actual, double tol)
Definition: Matrix.cpp:40
test_direct_factor_graph::CreateFactorGraph
static HybridGaussianFactorGraph CreateFactorGraph(const gtsam::Values &values, const std::vector< double > &means, const std::vector< double > &sigmas, DiscreteKey &m1, double measurement_noise=1e-3)
Create a Factor Graph by directly specifying all the factors instead of creating conditionals first....
Definition: testHybridGaussianFactor.cpp:182
test_direct_factor_graph
Definition: testHybridGaussianFactor.cpp:169
examples::f20
const auto f20
Definition: testHybridGaussianProductFactor.cpp:51
model1
noiseModel::Isotropic::shared_ptr model1
Definition: testEssentialMatrixFactor.cpp:26
Z
#define Z
Definition: icosphere.cpp:21
HybridValues.h
gtsam::HybridFactor::discreteKeys
const DiscreteKeys & discreteKeys() const
Return the discrete keys for this factor.
Definition: HybridFactor.h:131
x2
Pose3 x2(Rot3::Ypr(0.0, 0.0, 0.0), l2)
M
Matrix< RealScalar, Dynamic, Dynamic > M
Definition: bench_gemm.cpp:51


gtsam
Author(s):
autogenerated on Fri Nov 1 2024 03:40:14