MRPT  1.9.9
levmarq_impl.h
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 #ifndef GRAPH_SLAM_LEVMARQ_IMPL_H
10 #define GRAPH_SLAM_LEVMARQ_IMPL_H
11 
12 namespace mrpt
13 {
14 namespace graphslam
15 {
16 /// Internal auxiliary classes
17 namespace detail
18 {
19 using namespace mrpt;
20 using namespace mrpt::poses;
21 using namespace mrpt::graphslam;
22 using namespace mrpt::math;
23 using namespace std;
24 
25 // Auxiliary struct to update the oplus increments after each iteration
26 // Specializations are below.
27 template <class POSE, class gst>
28 struct AuxPoseOPlus;
29 
30 // Nodes: CPose2D
31 template <class gst>
32 struct AuxPoseOPlus<CPose2D, gst>
33 {
34  static inline void sumIncr(CPose2D& p, const typename gst::Array_O& delta)
35  {
36  p.x_incr(delta[0]);
37  p.y_incr(delta[1]);
38  p.phi_incr(delta[2]);
39  p.normalizePhi();
40  }
41 };
42 
43 // Nodes: CPosePDFGaussianInf
44 template <class gst>
46 {
47  template <class POSE>
48  static inline void sumIncr(POSE& p, const typename gst::Array_O& delta)
49  {
50  p.x_incr(delta[0]);
51  p.y_incr(delta[1]);
52  p.phi_incr(delta[2]);
53  p.normalizePhi();
54  }
55 };
56 
57 // Nodes: CPose2D
58 template <class gst>
59 struct AuxPoseOPlus<CPose3D, gst>
60 {
61  static inline void sumIncr(CPose3D& p, const typename gst::Array_O& delta)
62  {
63  // exp_delta_i = Exp_SE( delta_i )
64  typename gst::graph_t::constraint_t::type_value exp_delta_pose(
66  gst::SE_TYPE::exp(delta, exp_delta_pose);
67  p = p + exp_delta_pose;
68  }
69 };
70 
71 // Nodes: CPosePDFGaussianInf
72 template <class gst>
74 {
75  template <class POSE>
76  static inline void sumIncr(POSE& p, const typename gst::Array_O& delta)
77  {
78  // exp_delta_i = Exp_SE( delta_i )
79  typename gst::graph_t::constraint_t::type_value exp_delta_pose(
81  gst::SE_TYPE::exp(delta, exp_delta_pose);
82  p = p + exp_delta_pose;
83  }
84 };
85 
86 // An auxiliary struct to compute the pseudo-ln of a pose error, possibly
87 // modified with an information matrix.
88 // Specializations are below.
89 template <class EDGE, class gst>
90 struct AuxErrorEval;
91 
92 // For graphs of 2D constraints (no information matrix)
93 template <class gst>
94 struct AuxErrorEval<CPose2D, gst>
95 {
96  template <class POSE, class VEC, class EDGE_ITERATOR>
97  static inline void computePseudoLnError(
98  const POSE& DinvP1invP2, VEC& err, const EDGE_ITERATOR& edge)
99  {
100  MRPT_UNUSED_PARAM(edge);
101  gst::SE_TYPE::pseudo_ln(DinvP1invP2, err);
102  }
103 
104  template <class MAT, class EDGE_ITERATOR>
105  static inline void multiplyJtLambdaJ(
106  const MAT& J1, MAT& JtJ, const EDGE_ITERATOR& edge)
107  {
108  MRPT_UNUSED_PARAM(edge);
109  JtJ = J1.transpose() * J1;
110  }
111 
112  template <class MAT, class EDGE_ITERATOR>
113  static inline void multiplyJ1tLambdaJ2(
114  const MAT& J1, const MAT& J2, MAT& JtJ, const EDGE_ITERATOR& edge)
115  {
116  MRPT_UNUSED_PARAM(edge);
117  JtJ = J1.transpose() * J2;
118  }
119 
120  template <class JAC, class EDGE_ITERATOR, class VEC1, class VEC2>
121  static inline void multiply_Jt_W_err(
122  const JAC& J, const EDGE_ITERATOR& edge, const VEC1& ERR, VEC2& OUT)
123  {
124  MRPT_UNUSED_PARAM(edge);
125  const auto grad_incr = (J.transpose() * ERR).eval();
126  OUT += grad_incr;
127  }
128 };
129 
130 // For graphs of 3D constraints (no information matrix)
131 template <class gst>
132 struct AuxErrorEval<CPose3D, gst>
133 {
134  template <class POSE, class VEC, class EDGE_ITERATOR>
135  static inline void computePseudoLnError(
136  const POSE& DinvP1invP2, VEC& err, const EDGE_ITERATOR& edge)
137  {
138  MRPT_UNUSED_PARAM(edge);
139  gst::SE_TYPE::pseudo_ln(DinvP1invP2, err);
140  }
141 
142  template <class MAT, class EDGE_ITERATOR>
143  static inline void multiplyJtLambdaJ(
144  const MAT& J1, MAT& JtJ, const EDGE_ITERATOR& edge)
145  {
146  MRPT_UNUSED_PARAM(edge);
147  JtJ = J1.transpose() * J1;
148  }
149 
150  template <class MAT, class EDGE_ITERATOR>
151  static inline void multiplyJ1tLambdaJ2(
152  const MAT& J1, const MAT& J2, MAT& JtJ, const EDGE_ITERATOR& edge)
153  {
154  MRPT_UNUSED_PARAM(edge);
155  JtJ = J1.transpose() * J2;
156  }
157 
158  template <class JAC, class EDGE_ITERATOR, class VEC1, class VEC2>
159  static inline void multiply_Jt_W_err(
160  const JAC& J, const EDGE_ITERATOR& edge, const VEC1& ERR, VEC2& OUT)
161  {
162  MRPT_UNUSED_PARAM(edge);
163  OUT += J.transpose() * ERR;
164  }
165 };
166 
167 // For graphs of 2D constraints (with information matrix)
168 template <class gst>
170 {
171  template <class POSE, class VEC, class EDGE_ITERATOR>
172  static inline void computePseudoLnError(
173  const POSE& DinvP1invP2, VEC& err, const EDGE_ITERATOR& edge)
174  {
175  gst::SE_TYPE::pseudo_ln(DinvP1invP2, err);
176  }
177 
178  template <class MAT, class EDGE_ITERATOR>
179  static inline void multiplyJtLambdaJ(
180  const MAT& J1, MAT& JtJ, const EDGE_ITERATOR& edge)
181  {
182  JtJ = (J1.transpose() * edge->second.cov_inv) * J1;
183  }
184  template <class MAT, class EDGE_ITERATOR>
185  static inline void multiplyJ1tLambdaJ2(
186  const MAT& J1, const MAT& J2, MAT& JtJ, const EDGE_ITERATOR& edge)
187  {
188  JtJ = (J1.transpose() * edge->second.cov_inv) * J2;
189  }
190 
191  template <class JAC, class EDGE_ITERATOR, class VEC1, class VEC2>
192  static inline void multiply_Jt_W_err(
193  const JAC& J, const EDGE_ITERATOR& edge, const VEC1& ERR, VEC2& OUT)
194  {
195  OUT += (J.transpose() * edge->second.cov_inv) * ERR;
196  }
197 };
198 
199 // For graphs of 3D constraints (with information matrix)
200 template <class gst>
202 {
203  template <class POSE, class VEC, class EDGE_ITERATOR>
204  static inline void computePseudoLnError(
205  const POSE& DinvP1invP2, VEC& err, const EDGE_ITERATOR& edge)
206  {
207  MRPT_UNUSED_PARAM(edge);
208  gst::SE_TYPE::pseudo_ln(DinvP1invP2, err);
209  }
210 
211  template <class MAT, class EDGE_ITERATOR>
212  static inline void multiplyJtLambdaJ(
213  const MAT& J1, MAT& JtJ, const EDGE_ITERATOR& edge)
214  {
215  JtJ = (J1.transpose() * edge->second.cov_inv) * J1;
216  }
217 
218  template <class MAT, class EDGE_ITERATOR>
219  static inline void multiplyJ1tLambdaJ2(
220  const MAT& J1, const MAT& J2, MAT& JtJ, const EDGE_ITERATOR& edge)
221  {
222  JtJ = (J1.transpose() * edge->second.cov_inv) * J2;
223  }
224 
225  template <class JAC, class EDGE_ITERATOR, class VEC1, class VEC2>
226  static inline void multiply_Jt_W_err(
227  const JAC& J, const EDGE_ITERATOR& edge, const VEC1& ERR, VEC2& OUT)
228  {
229  OUT += (J.transpose() * edge->second.cov_inv) * ERR;
230  }
231 };
232 
233 } // namespace detail
234 
235 // Compute, at once, jacobians and the error vectors for each constraint in
236 // "lstObservationData", returns the overall squared error.
237 template <class GRAPH_T>
239  const GRAPH_T& graph,
240  const std::vector<typename graphslam_traits<GRAPH_T>::observation_info_t>&
241  lstObservationData,
244 {
245  MRPT_UNUSED_PARAM(graph);
246  using gst = graphslam_traits<GRAPH_T>;
247 
248  lstJacobians.clear();
249  errs.clear();
250 
251  const size_t nObservations = lstObservationData.size();
252 
253  for (size_t i = 0; i < nObservations; i++)
254  {
255  const typename gst::observation_info_t& obs = lstObservationData[i];
256  auto e = obs.edge;
257  const typename gst::graph_t::constraint_t::type_value* EDGE_POSE =
258  obs.edge_mean;
259  typename gst::graph_t::constraint_t::type_value* P1 = obs.P1;
260  typename gst::graph_t::constraint_t::type_value* P2 = obs.P2;
261 
262  const auto& ids = e->first;
263  const auto& edge = e->second;
264 
265  // Compute the residual pose error of these pair of nodes + its
266  // constraint:
267  // DinvP1invP2 = inv(EDGE) * inv(P1) * P2 = (P2 \ominus P1) \ominus EDGE
268  typename gst::graph_t::constraint_t::type_value DinvP1invP2 =
269  ((*P2) - (*P1)) - *EDGE_POSE;
270 
271  // Add to vector of errors:
272  errs.resize(errs.size() + 1);
274  DinvP1invP2, errs.back(), edge);
275 
276  // Compute the jacobians:
277  alignas(MRPT_MAX_ALIGN_BYTES)
278  std::pair<mrpt::graphs::TPairNodeIDs, typename gst::TPairJacobs>
279  newMapEntry;
280  newMapEntry.first = ids;
281  gst::SE_TYPE::jacobian_dDinvP1invP2_depsilon(
282  -(*EDGE_POSE), *P1, *P2, &newMapEntry.second.first,
283  &newMapEntry.second.second);
284 
285  // And insert into map of jacobians:
286  lstJacobians.insert(lstJacobians.end(), newMapEntry);
287  }
288 
289  // return overall square error: (Was:
290  // std::accumulate(...,mrpt::squareNorm_accum<>), but led to GCC
291  // errors when enabling parallelization)
292  double ret_err = 0.0;
293  for (size_t i = 0; i < errs.size(); i++) ret_err += errs[i].squaredNorm();
294  return ret_err;
295 }
296 
297 } // namespace graphslam
298 } // namespace mrpt
299 
300 #endif
static void multiplyJtLambdaJ(const MAT &J1, MAT &JtJ, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:143
static void multiplyJtLambdaJ(const MAT &J1, MAT &JtJ, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:179
static void sumIncr(POSE &p, const typename gst::Array_O &delta)
Definition: levmarq_impl.h:76
GLuint * ids
Definition: glext.h:3906
#define MRPT_MAX_ALIGN_BYTES
static void multiplyJ1tLambdaJ2(const MAT &J1, const MAT &J2, MAT &JtJ, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:185
static void computePseudoLnError(const POSE &DinvP1invP2, VEC &err, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:172
static void multiplyJ1tLambdaJ2(const MAT &J1, const MAT &J2, MAT &JtJ, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:219
static void computePseudoLnError(const POSE &DinvP1invP2, VEC &err, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:204
STL namespace.
std::vector< T, mrpt::aligned_allocator_cpp11< T > > aligned_std_vector
static void sumIncr(CPose3D &p, const typename gst::Array_O &delta)
Definition: levmarq_impl.h:61
double computeJacobiansAndErrors(const GRAPH_T &graph, const std::vector< typename graphslam_traits< GRAPH_T >::observation_info_t > &lstObservationData, typename graphslam_traits< GRAPH_T >::map_pairIDs_pairJacobs_t &lstJacobians, mrpt::aligned_std_vector< typename graphslam_traits< GRAPH_T >::Array_O > &errs)
Definition: levmarq_impl.h:238
Auxiliary struct used in graph-slam implementation: It holds the relevant information for each of the...
static void multiplyJ1tLambdaJ2(const MAT &J1, const MAT &J2, MAT &JtJ, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:113
static void sumIncr(POSE &p, const typename gst::Array_O &delta)
Definition: levmarq_impl.h:48
SLAM methods related to graphs of pose constraints.
This base provides a set of functions for maths stuff.
static void multiply_Jt_W_err(const JAC &J, const EDGE_ITERATOR &edge, const VEC1 &ERR, VEC2 &OUT)
Definition: levmarq_impl.h:121
mrpt::aligned_std_multimap< mrpt::graphs::TPairNodeIDs, TPairJacobs > map_pairIDs_pairJacobs_t
static void computePseudoLnError(const POSE &DinvP1invP2, VEC &err, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:135
static void multiply_Jt_W_err(const JAC &J, const EDGE_ITERATOR &edge, const VEC1 &ERR, VEC2 &OUT)
Definition: levmarq_impl.h:226
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Auxiliary traits template for use among graph-slam problems to make life easier with these complicate...
static void multiplyJtLambdaJ(const MAT &J1, MAT &JtJ, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:212
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
A Probability Density function (PDF) of a 2D pose as a Gaussian with a mean and the inverse of the c...
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
Definition: CPose2D.h:38
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:86
static void multiplyJtLambdaJ(const MAT &J1, MAT &JtJ, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:105
static void multiplyJ1tLambdaJ2(const MAT &J1, const MAT &J2, MAT &JtJ, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:151
static void multiply_Jt_W_err(const JAC &J, const EDGE_ITERATOR &edge, const VEC1 &ERR, VEC2 &OUT)
Definition: levmarq_impl.h:192
Declares a class that represents a Probability Density function (PDF) of a 3D pose as a Gaussian des...
static void multiply_Jt_W_err(const JAC &J, const EDGE_ITERATOR &edge, const VEC1 &ERR, VEC2 &OUT)
Definition: levmarq_impl.h:159
static void computePseudoLnError(const POSE &DinvP1invP2, VEC &err, const EDGE_ITERATOR &edge)
Definition: levmarq_impl.h:97
GLfloat GLfloat p
Definition: glext.h:6305
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
Definition: common.h:186
static void sumIncr(CPose2D &p, const typename gst::Array_O &delta)
Definition: levmarq_impl.h:34



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