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



Page generated by Doxygen 1.8.14 for MRPT 2.0.2 Git: 9b4fd2465 Mon May 4 16:59:08 2020 +0200 at lun may 4 17:26:07 CEST 2020