MRPT  1.9.9
ScalarFactorGraph_unittest.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
11 #include <gtest/gtest.h>
12 
13 using namespace mrpt;
14 using namespace mrpt::graphs;
15 using namespace std;
16 
17 #if EIGEN_VERSION_AT_LEAST(3, 1, 0) // Requires Eigen>=3.1
18 
19 struct MySimpleUnaryEdge : public ScalarFactorGraph::UnaryFactorVirtualBase
20 {
21  MySimpleUnaryEdge(
22  vector<double>& parent, size_t nodeid, double observation,
23  double information)
24  : m_parent(parent),
25  m_observation(observation),
26  m_information(information)
27  {
28  this->node_id = nodeid;
29  }
30 
31  double evaluateResidual() const override
32  {
33  return m_parent[node_id] - m_observation;
34  }
35  double getInformation() const override { return m_information; }
36  void evalJacobian(double& dr_dx) const override { dr_dx = 1.0; }
37  protected:
38  vector<double>& m_parent;
39  double m_observation, m_information;
40 };
41 
42 struct MySimpleBinaryEdge : public ScalarFactorGraph::BinaryFactorVirtualBase
43 {
44  MySimpleBinaryEdge(
45  vector<double>& parent, size_t nodeid_i, size_t nodeid_j,
46  double information)
47  : m_parent(parent), m_information(information)
48  {
49  this->node_id_i = nodeid_i;
50  this->node_id_j = nodeid_j;
51  }
52 
53  double evaluateResidual() const override
54  {
55  return m_parent[node_id_i] - m_parent[node_id_j];
56  }
57  double getInformation() const override { return m_information; }
58  void evalJacobian(double& dr_dx_i, double& dr_dx_j) const override
59  {
60  dr_dx_i = +1.0;
61  dr_dx_j = -1.0;
62  }
63 
64  protected:
65  vector<double>& m_parent;
66  double m_information;
67 };
68 
69 TEST(ScalarFactorGraph, MiniMRF_UnaryEdges)
70 {
71  const size_t N = 4;
72  vector<double> my_map(N, .0);
73 
74  ScalarFactorGraph gmrf;
75  gmrf.enableProfiler(false);
76 
77  gmrf.initialize(N);
78 
79  std::deque<MySimpleUnaryEdge> edges1;
80 
81  edges1.push_back(MySimpleUnaryEdge(my_map, 0, 1.0, 4.0));
82  edges1.push_back(MySimpleUnaryEdge(my_map, 1, 5.0, 4.0));
83  edges1.push_back(MySimpleUnaryEdge(my_map, 2, 3.0, 4.0));
84  edges1.push_back(MySimpleUnaryEdge(my_map, 3, 2.0, 16.0));
85 
86  for (const auto& e : edges1) gmrf.addConstraint(e);
87 
88  // Test 1:
89  // --------------
90  {
91  my_map.assign(N, .0);
92 
93  Eigen::VectorXd x_incr, x_var;
94  gmrf.updateEstimation(x_incr, &x_var);
95 
96  EXPECT_NEAR(x_incr[0], 1.0, 1e-9);
97  EXPECT_NEAR(x_incr[1], 5.0, 1e-9);
98  EXPECT_NEAR(x_incr[2], 3.0, 1e-9);
99  EXPECT_NEAR(x_incr[3], 2.0, 1e-9);
100 
101  EXPECT_NEAR(x_var[0], 1.0 / 4.0, 1e-9);
102  EXPECT_NEAR(x_var[1], 1.0 / 4.0, 1e-9);
103  EXPECT_NEAR(x_var[2], 1.0 / 4.0, 1e-9);
104  EXPECT_NEAR(x_var[3], 1.0 / 16.0, 1e-9);
105  }
106 
107  // Test 2:
108  // --------------
109  {
110  my_map.assign(N, .0);
111 
112  // Add new edge:
113  edges1.push_back(MySimpleUnaryEdge(my_map, 0, 4.0, 2.0));
114  gmrf.addConstraint(*edges1.rbegin());
115 
116  Eigen::VectorXd x_incr, x_var;
117  gmrf.updateEstimation(x_incr, &x_var);
118 
119  EXPECT_NEAR(x_incr[0], 2.0, 1e-9);
120  EXPECT_NEAR(x_incr[1], 5.0, 1e-9);
121  EXPECT_NEAR(x_incr[2], 3.0, 1e-9);
122  EXPECT_NEAR(x_incr[3], 2.0, 1e-9);
123 
124  EXPECT_NEAR(x_var[0], 1.0 / (4.0 + 2.0), 1e-9);
125  EXPECT_NEAR(x_var[1], 1.0 / 4.0, 1e-9);
126  EXPECT_NEAR(x_var[2], 1.0 / 4.0, 1e-9);
127  EXPECT_NEAR(x_var[3], 1.0 / 16.0, 1e-9);
128  }
129 }
130 
131 TEST(ScalarFactorGraph, MiniMRF_BinaryEdges)
132 {
133  const size_t N = 4;
134  vector<double> my_map(N, .0);
135 
136  ScalarFactorGraph gmrf;
137  gmrf.enableProfiler(false);
138 
139  gmrf.initialize(N);
140 
141  // Edge to assign a value to node 0:
142  MySimpleUnaryEdge edge_val0(my_map, 0, 1.0 /*value*/, 1.0 /*information*/);
143  gmrf.addConstraint(edge_val0);
144 
145  MySimpleBinaryEdge edge_01(my_map, 0, 1, .1);
146  gmrf.addConstraint(edge_01);
147  MySimpleBinaryEdge edge_12(my_map, 1, 2, .1);
148  gmrf.addConstraint(edge_12);
149  MySimpleBinaryEdge edge_23(my_map, 2, 3, .1);
150  gmrf.addConstraint(edge_23);
151  MySimpleBinaryEdge edge_30(my_map, 3, 0, .1);
152  gmrf.addConstraint(edge_30);
153 
154  // Test 1:
155  // --------------
156  {
157  my_map.assign(N, .0);
158 
159  Eigen::VectorXd x_incr, x_var;
160  gmrf.updateEstimation(x_incr, &x_var);
161 
162  EXPECT_NEAR(x_incr[0], 1.0, 1e-6);
163  EXPECT_NEAR(x_incr[1], 1.0, 1e-6);
164  EXPECT_NEAR(x_incr[2], 1.0, 1e-6);
165  EXPECT_NEAR(x_incr[3], 1.0, 1e-6);
166 
167  EXPECT_NEAR(x_var[0], 1.0, 1e-6);
168 
169  EXPECT_GT(x_var[1], x_var[0]);
170  EXPECT_GT(x_var[3], x_var[0]);
171 
172  EXPECT_GT(x_var[2], x_var[1]);
173  EXPECT_GT(x_var[2], x_var[3]);
174  }
175 }
176 
177 #endif // Eigen>=3.1
void initialize(const size_t nodeCount)
Initialize the GMRF internal state and copy the prior factors.
Simple, scalar (1-dim) constraint (edge) for a GMRF.
Abstract graph and tree data structures, plus generic graph algorithms.
STL namespace.
TEST(NodeletsTests, pub_sub_multithread_test)
void enableProfiler(bool enable=true)
void addConstraint(const UnaryFactorVirtualBase &listOfConstraints)
Insert constraints into the GMRF problem.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
Simple, scalar (1-dim) constraint (edge) for a GMRF.
void updateEstimation(Eigen::VectorXd &solved_x_inc, Eigen::VectorXd *solved_variances=nullptr)
Sparse solver for GMRF (Gaussian Markov Random Fields) graphical models.



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020