Main MRPT website > C++ reference for MRPT 1.9.9
ba_common.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-2017, 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 
10 #include "vision-precomp.h" // Precompiled headers
11 
13 #include <mrpt/vision/pinhole.h>
15 #include "ba_internals.h"
16 
17 using namespace std;
18 using namespace mrpt;
19 using namespace mrpt::vision;
20 using namespace mrpt::utils;
21 using namespace mrpt::math;
22 using namespace mrpt::poses;
23 
24 /* -------------------------------------------------------------------------------------
25  ba_initial_estimate
26 
27  Fills the frames & landmark points maps with an initial gross estimate
28  from the sequence \a observations, so they can be fed to bundle adjustment
29  methods.
30  ------------------------------------------------------------------------------------
31  */
33  const TSequenceFeatureObservations& observations,
34  const TCamera& camera_params, TFramePosesMap& frame_poses,
35  TLandmarkLocationsMap& landmark_points)
36 {
37  MRPT_UNUSED_PARAM(camera_params);
39  // VERY CRUDE APPROACH: All camera poses at the origin, all points at
40  // (0,0,1)
41  // TODO: Improve with the data in "observations"...
42 
43  // Clear previous contents:
44  frame_poses.clear();
45  landmark_points.clear();
46 
47  // Go thru the obs list and insert poses:
48  for (TSequenceFeatureObservations::const_iterator it = observations.begin();
49  it != observations.end(); ++it)
50  {
51  const TFeatureID feat_ID = it->id_feature;
52  const TCameraPoseID frame_ID = it->id_frame;
53 
54  frame_poses[frame_ID] = CPose3D(0, 0, 0, 0, 0, 0);
55  landmark_points[feat_ID] = TPoint3D(0, 0, 1);
56  }
57  MRPT_END
58 }
59 
61  const TSequenceFeatureObservations& observations,
62  const TCamera& camera_params, TFramePosesVec& frame_poses,
63  TLandmarkLocationsVec& landmark_points)
64 {
65  MRPT_UNUSED_PARAM(camera_params);
67  // VERY CRUDE APPROACH: All camera poses at the origin, all points at
68  // (0,0,1)
69  // TODO: Improve with the data in "observations"...
70 
71  // Clear previous contents:
72  frame_poses.clear();
73  landmark_points.clear();
74 
75  if (observations.empty()) return;
76 
77  // Go thru the obs list and insert poses:
78 
79  TFeatureID max_pt_id = 0;
80  TCameraPoseID max_fr_id = 0;
81 
82  for (TSequenceFeatureObservations::const_iterator it = observations.begin();
83  it != observations.end(); ++it)
84  {
85  const TFeatureID feat_ID = it->id_feature;
86  const TCameraPoseID frame_ID = it->id_frame;
87  keep_max(max_fr_id, frame_ID);
88  keep_max(max_pt_id, feat_ID);
89  }
90 
91  // Insert N copies of the same values:
92  frame_poses.assign(max_fr_id + 1, CPose3D(0, 0, 0, 0, 0, 0));
93  landmark_points.assign(max_pt_id + 1, TPoint3D(0, 0, 1));
94 
95  MRPT_END
96 }
97 
98 // This function is what to do for each feature in the reprojection loops below.
99 // -> residual: the raw residual, even if using robust kernel
100 // -> sum+= scaled squared norm of the residual (which != squared norm if using
101 // robust kernel)
102 template <bool POSES_INVERSE>
104  const TCamera& camera_params, const TFeatureObservation& OBS,
105  std::array<double, 2>& out_residual,
106  const TFramePosesVec::value_type& frame,
107  const TLandmarkLocationsVec::value_type& point, double& sum,
108  const bool use_robust_kernel, const double kernel_param,
109  double* out_kernel_1st_deriv)
110 {
111  const TPixelCoordf z_pred =
112  mrpt::vision::pinhole::projectPoint_no_distortion<POSES_INVERSE>(
113  camera_params, frame, point);
114  const TPixelCoordf& z_meas = OBS.px;
115 
116  out_residual[0] = z_meas.x - z_pred.x;
117  out_residual[1] = z_meas.y - z_pred.y;
118 
119  const double sum_2 = square(out_residual[0]) + square(out_residual[1]);
120 
121  if (use_robust_kernel)
122  {
124  kernel.param_sq = square(kernel_param);
125  double kernel_1st_deriv, kernel_2nd_deriv;
126 
127  sum += kernel.eval(sum_2, kernel_1st_deriv, kernel_2nd_deriv);
128  if (out_kernel_1st_deriv) *out_kernel_1st_deriv = kernel_1st_deriv;
129  }
130  else
131  {
132  sum += sum_2;
133  }
134 }
135 
136 /** Compute reprojection error vector (used from within Bundle Adjustment
137  * methods, but can be used in general)
138  * See mrpt::vision::bundle_adj_full for a description of most parameters.
139  *
140  * \return Overall squared reprojection error.
141  */
143  const TSequenceFeatureObservations& observations,
144  const TCamera& camera_params, const TFramePosesMap& frame_poses,
145  const TLandmarkLocationsMap& landmark_points,
146  std::vector<std::array<double, 2>>& out_residuals,
147  const bool frame_poses_are_inverse, const bool use_robust_kernel,
148  const double kernel_param, std::vector<double>* out_kernel_1st_deriv)
149 {
150  MRPT_START
151 
152  double sum = 0;
153 
154  const size_t N = observations.size();
155  out_residuals.resize(N);
156  if (out_kernel_1st_deriv) out_kernel_1st_deriv->resize(N);
157 
158  for (size_t i = 0; i < N; i++)
159  {
160  const TFeatureObservation& OBS = observations[i];
161 
162  const TFeatureID i_p = OBS.id_feature;
163  const TCameraPoseID i_f = OBS.id_frame;
164 
165  TFramePosesMap::const_iterator itF = frame_poses.find(i_f);
166  TLandmarkLocationsMap::const_iterator itP = landmark_points.find(i_p);
167  ASSERTMSG_(itF != frame_poses.end(), "Frame ID is not in list!")
168  ASSERTMSG_(itP != landmark_points.end(), "Landmark ID is not in list!")
169 
170  const TFramePosesMap::mapped_type& frame = itF->second;
171  const TLandmarkLocationsMap::mapped_type& point = itP->second;
172 
173  double* ptr_1st_deriv =
174  out_kernel_1st_deriv ? &((*out_kernel_1st_deriv)[i]) : nullptr;
175 
176  if (frame_poses_are_inverse)
177  reprojectionResidualsElement<true>(
178  camera_params, OBS, out_residuals[i], frame, point, sum,
179  use_robust_kernel, kernel_param, ptr_1st_deriv);
180  else
181  reprojectionResidualsElement<false>(
182  camera_params, OBS, out_residuals[i], frame, point, sum,
183  use_robust_kernel, kernel_param, ptr_1st_deriv);
184  }
185 
186  return sum;
187 
188  MRPT_END
189 }
190 
192  const TSequenceFeatureObservations& observations,
193  const TCamera& camera_params, const TFramePosesVec& frame_poses,
194  const TLandmarkLocationsVec& landmark_points,
195  std::vector<std::array<double, 2>>& out_residuals,
196  const bool frame_poses_are_inverse, const bool use_robust_kernel,
197  const double kernel_param, std::vector<double>* out_kernel_1st_deriv)
198 {
199  MRPT_START
200 
201  double sum = 0;
202 
203  const size_t N = observations.size();
204  out_residuals.resize(N);
205  if (out_kernel_1st_deriv) out_kernel_1st_deriv->resize(N);
206 
207  for (size_t i = 0; i < N; i++)
208  {
209  const TFeatureObservation& OBS = observations[i];
210 
211  const TFeatureID i_p = OBS.id_feature;
212  const TCameraPoseID i_f = OBS.id_frame;
213 
214  ASSERT_BELOW_(i_p, landmark_points.size())
215  ASSERT_BELOW_(i_f, frame_poses.size())
216 
217  const TFramePosesVec::value_type& frame = frame_poses[i_f];
218  const TLandmarkLocationsVec::value_type& point = landmark_points[i_p];
219 
220  double* ptr_1st_deriv =
221  out_kernel_1st_deriv ? &((*out_kernel_1st_deriv)[i]) : nullptr;
222 
223  if (frame_poses_are_inverse)
224  reprojectionResidualsElement<true>(
225  camera_params, OBS, out_residuals[i], frame, point, sum,
226  use_robust_kernel, kernel_param, ptr_1st_deriv);
227  else
228  reprojectionResidualsElement<false>(
229  camera_params, OBS, out_residuals[i], frame, point, sum,
230  use_robust_kernel, kernel_param, ptr_1st_deriv);
231  }
232 
233  return sum;
234  MRPT_END
235 }
236 
237 // Compute gradients & Hessian blocks
239  const TSequenceFeatureObservations& observations,
240  const vector<std::array<double, 2>>& residual_vec,
241  const mrpt::aligned_containers<JacData<6, 3, 2>>::vector_t& jac_data_vec,
243  mrpt::aligned_containers<CArrayDouble<6>>::vector_t& eps_frame,
245  mrpt::aligned_containers<CArrayDouble<3>>::vector_t& eps_point,
246  const size_t num_fix_frames, const size_t num_fix_points,
247  const vector<double>* kernel_1st_deriv)
248 {
249  MRPT_START
250 
251  const size_t N = observations.size();
252  const bool use_robust_kernel = (kernel_1st_deriv != nullptr);
253 
254  for (size_t i = 0; i < N; i++)
255  {
256  const TFeatureObservation& OBS = observations[i];
257 
258  const TFeatureID i_p = OBS.id_feature;
259  const TCameraPoseID i_f = OBS.id_frame;
260 
261  const Eigen::Matrix<double, 2, 1> RESID(&residual_vec[i][0]);
262  const JacData<6, 3, 2>& JACOB = jac_data_vec[i];
263  ASSERTDEB_(JACOB.frame_id == i_f && JACOB.point_id == i_p)
264 
265  if (i_f >= num_fix_frames)
266  {
267  const size_t frame_id = i_f - num_fix_frames;
269  ASSERT_BELOW_(frame_id, U.size())
270 
272  JtJ.multiply_AtA(JACOB.J_frame);
273 
274  CArrayDouble<6> eps_delta;
275  JACOB.J_frame.multiply_Atb(
276  RESID, eps_delta); // eps_delta = J^t * RESID
277  if (!use_robust_kernel)
278  {
279  eps_frame[frame_id] += eps_delta;
280  }
281  else
282  {
283  const double rho_1st_der = (*kernel_1st_deriv)[i];
284  eps_frame[frame_id] += eps_delta * rho_1st_der;
285  }
286  U[frame_id] += JtJ;
287  }
288  if (i_p >= num_fix_points)
289  {
290  const size_t point_id = i_p - num_fix_points;
292  ASSERT_BELOW_(point_id, V.size())
293 
295  JtJ.multiply_AtA(JACOB.J_point);
296 
297  CArrayDouble<3> eps_delta;
298  JACOB.J_point.multiply_Atb(
299  RESID, eps_delta); // eps_delta = J^t * RESID
300  if (!use_robust_kernel)
301  {
302  eps_point[point_id] += eps_delta;
303  }
304  else
305  {
306  const double rho_1st_der = (*kernel_1st_deriv)[i];
307  eps_point[point_id] += eps_delta * rho_1st_der;
308  }
309 
310  V[point_id] += JtJ;
311  }
312  }
313 
314  MRPT_END
315 }
316 
318  const TFramePosesVec& frame_poses, const CVectorDouble& delta,
319  const size_t delta_first_idx, const size_t delta_num_vals,
320  TFramePosesVec& new_frame_poses, const size_t num_fix_frames)
321 {
322  MRPT_START
323 
324  new_frame_poses.resize(frame_poses.size());
325 
326  for (size_t i = 0; i < num_fix_frames; ++i)
327  new_frame_poses[i] = frame_poses[i];
328 
329  size_t delta_used_vals = 0;
330  const double* delta_val = &delta[delta_first_idx];
331 
332  for (size_t i = num_fix_frames; i < frame_poses.size(); i++)
333  {
334  const CPose3D& old_pose = frame_poses[i];
335  CPose3D& new_pose = new_frame_poses[i];
336 
337  // Use the Lie Algebra methods for the increment:
338  const CArrayDouble<6> incr(delta_val);
339  const CPose3D incrPose = CPose3D::exp(incr);
340 
341  // new_pose = old_pose [+] delta
342  // = exp(delta) (+) old_pose
343  new_pose.composeFrom(incrPose, old_pose);
344 
345  // Move to the next entry in delta:
346  delta_val += 6;
347  delta_used_vals += 6;
348  }
349 
350  ASSERT_(delta_used_vals == delta_num_vals)
351 
352  MRPT_END
353 }
355  const TLandmarkLocationsVec& landmark_points, const CVectorDouble& delta,
356  const size_t delta_first_idx, const size_t delta_num_vals,
357  TLandmarkLocationsVec& new_landmark_points, const size_t num_fix_points)
358 {
359  MRPT_START
360 
361  new_landmark_points.resize(landmark_points.size());
362 
363  for (size_t i = 0; i < num_fix_points; ++i)
364  new_landmark_points[i] = landmark_points[i];
365 
366  size_t delta_used_vals = 0;
367  const double* delta_val = &delta[delta_first_idx];
368 
369  for (size_t i = num_fix_points; i < landmark_points.size(); i++)
370  {
371  const TPoint3D& old_point = landmark_points[i];
372  TPoint3D& new_point = new_landmark_points[i];
373 
374  for (size_t j = 0; j < 3; j++)
375  new_point[j] = old_point[j] + delta_val[j];
376 
377  // Move to the next entry in delta:
378  delta_val += 3;
379  delta_used_vals += 3;
380  }
381 
382  ASSERT_(delta_used_vals == delta_num_vals)
383 
384  MRPT_END
385 }
A pair (x,y) of pixel coordinates (subpixel resolution).
Definition: TPixelCoord.h:21
mrpt::math::CMatrixFixedNumeric< double, ObsDim, PointDof > J_point
Definition: ba_internals.h:54
TLandmarkID id_feature
A unique ID of this feature.
void reprojectionResidualsElement(const TCamera &camera_params, const TFeatureObservation &OBS, std::array< double, 2 > &out_residual, const TFramePosesVec::value_type &frame, const TLandmarkLocationsVec::value_type &point, double &sum, const bool use_robust_kernel, const double kernel_param, double *out_kernel_1st_deriv)
Definition: ba_common.cpp:103
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
mrpt::aligned_containers< TCameraPoseID, mrpt::poses::CPose3D >::map_t TFramePosesMap
A list of camera frames (6D poses) indexed by unique IDs.
#define ASSERT_BELOW_(__A, __B)
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
Definition: eigen_frwds.h:42
One feature observation entry, used within sequences with TSequenceFeatureObservations.
STL namespace.
const Scalar * const_iterator
Definition: eigen_plugins.h:27
void add_se3_deltas_to_frames(const mrpt::vision::TFramePosesVec &frame_poses, const mrpt::math::CVectorDouble &delta, const size_t delta_first_idx, const size_t delta_num_vals, mrpt::vision::TFramePosesVec &new_frame_poses, const size_t num_fix_frames)
For each pose in the vector frame_poses, adds a "delta" increment to the manifold, with the "delta" given in the se(3) Lie algebra:
Definition: ba_common.cpp:317
mrpt::utils::TPixelCoordf px
The pixel coordinates of the observed feature.
TCameraPoseID frame_id
Definition: ba_internals.h:49
Helper types for STL containers with Eigen memory allocators.
A complete sequence of observations of features from different camera frames (poses).
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
mrpt::aligned_containers< mrpt::poses::CPose3D >::vector_t TFramePosesVec
A list of camera frames (6D poses), which assumes indexes are unique, consecutive IDs...
A numeric matrix of compile-time fixed size.
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
#define MRPT_END
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
void composeFrom(const CPose3D &A, const CPose3D &B)
Makes "this = A (+) B"; this method is slightly more efficient than "this= A + B;" since it avoids th...
Definition: CPose3D.cpp:639
void add_3d_deltas_to_points(const mrpt::vision::TLandmarkLocationsVec &landmark_points, const mrpt::math::CVectorDouble &delta, const size_t delta_first_idx, const size_t delta_num_vals, mrpt::vision::TLandmarkLocationsVec &new_landmark_points, const size_t num_fix_points)
For each pose in the vector frame_poses, adds a "delta" increment to the manifold, with the "delta" given in the se(3) Lie algebra:
Definition: ba_common.cpp:354
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
Classes for computer vision, detectors, features, etc.
uint64_t TFeatureID
Definition of a feature ID.
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
Definition: bits.h:227
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
#define MRPT_START
uint64_t TCameraPoseID
Unique IDs for camera frames (poses)
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:88
void ba_build_gradient_Hessians(const TSequenceFeatureObservations &observations, const std::vector< std::array< double, 2 >> &residual_vec, const mrpt::aligned_containers< JacData< 6, 3, 2 >>::vector_t &jac_data_vec, mrpt::aligned_containers< mrpt::math::CMatrixFixedNumeric< double, 6, 6 >>::vector_t &U, mrpt::aligned_containers< CArrayDouble< 6 >>::vector_t &eps_frame, mrpt::aligned_containers< mrpt::math::CMatrixFixedNumeric< double, 3, 3 >>::vector_t &V, mrpt::aligned_containers< CArrayDouble< 3 >>::vector_t &eps_point, const size_t num_fix_frames, const size_t num_fix_points, const vector< double > *kernel_1st_deriv)
Construct the BA linear system.
Definition: ba_common.cpp:238
#define ASSERT_(f)
std::vector< mrpt::math::TPoint3D > TLandmarkLocationsVec
A list of landmarks (3D points), which assumes indexes are unique, consecutive IDs.
A partial specialization of CArrayNumeric for double numbers.
Definition: CArrayNumeric.h:87
mrpt::math::CMatrixFixedNumeric< double, ObsDim, FrameDof > J_frame
Definition: ba_internals.h:53
double reprojectionResiduals(const mrpt::vision::TSequenceFeatureObservations &observations, const mrpt::utils::TCamera &camera_params, const mrpt::vision::TFramePosesVec &frame_poses, const mrpt::vision::TLandmarkLocationsVec &landmark_points, std::vector< std::array< double, 2 >> &out_residuals, const bool frame_poses_are_inverse, const bool use_robust_kernel=true, const double kernel_param=3.0, std::vector< double > *out_kernel_1st_deriv=nullptr)
Compute reprojection error vector (used from within Bundle Adjustment methods, but can be used in gen...
Definition: ba_common.cpp:191
TCameraPoseID id_frame
A unique ID of a "frame" (camera position) from where the feature was observed.
std::map< TLandmarkID, mrpt::math::TPoint3D > TLandmarkLocationsMap
A list of landmarks (3D points) indexed by unique IDs.
Lightweight 3D point.
void ba_initial_estimate(const mrpt::vision::TSequenceFeatureObservations &observations, const mrpt::utils::TCamera &camera_params, mrpt::vision::TFramePosesVec &frame_poses, mrpt::vision::TLandmarkLocationsVec &landmark_points)
Fills the frames & landmark points maps with an initial gross estimate from the sequence observations...
Definition: ba_common.cpp:60
TLandmarkID point_id
Definition: ba_internals.h:50
#define ASSERTMSG_(f, __ERROR_MSG)
Structure to hold the parameters of a pinhole camera model.
Definition: TCamera.h:32



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019