Main MRPT website > C++ reference for MRPT 1.9.9
CPose3D.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 "base-precomp.h" // Precompiled headers
11 
12 #include <mrpt/config.h> // for HAVE_SINCOS
13 #include <mrpt/utils/types_math.h> // for CVectorD...
14 #include <mrpt/math/CMatrix.h> // for CMatrix
15 #include <mrpt/math/geometry.h> // for skew_sym...
16 #include <mrpt/math/matrix_serialization.h> // for operator>>
17 #include <mrpt/math/wrap2pi.h> // for wrapToPi
18 #include <mrpt/poses/CPoint2D.h> // for CPoint2D
19 #include <mrpt/poses/CPoint3D.h> // for CPoint3D
20 #include <mrpt/poses/CPose2D.h> // for CPose2D
21 #include <mrpt/poses/CPose3D.h> // for CPose3D
22 #include <mrpt/poses/CPose3DQuat.h> // for CPose3DQuat
23 #include <mrpt/poses/CPose3DRotVec.h> // for CPose3DR...
24 #include <mrpt/utils/CStream.h> // for CStream
25 #include <algorithm> // for move
26 #include <cmath> // for fabs
27 #include <iomanip> // for operator<<
28 #include <limits> // for numeric_...
29 #include <ostream> // for operator<<
30 #include <string> // for allocator
31 #include <mrpt/math/CArrayNumeric.h> // for CArrayDo...
32 #include <mrpt/math/CMatrixFixedNumeric.h> // for CMatrixF...
33 #include <mrpt/math/CMatrixTemplateNumeric.h> // for CMatrixD...
34 #include <mrpt/math/CQuaternion.h> // for CQuatern...
35 #include <mrpt/math/homog_matrices.h> // for homogene...
36 #include <mrpt/math/lightweight_geom_data.h> // for TPoint3D
37 #include <mrpt/math/ops_containers.h> // for dotProduct
38 #include <mrpt/utils/CSerializable.h> // for CSeriali...
39 #include <mrpt/utils/bits.h> // for square
40 #include <mrpt/math/utils_matlab.h>
41 #include <mrpt/otherlibs/sophus/so3.hpp>
42 #include <mrpt/otherlibs/sophus/se3.hpp>
43 
44 using namespace mrpt;
45 using namespace mrpt::math;
46 using namespace mrpt::utils;
47 using namespace mrpt::poses;
48 
50 
51 /*---------------------------------------------------------------
52  Constructors
53  ---------------------------------------------------------------*/
54 CPose3D::CPose3D() : m_ypr_uptodate(true), m_yaw(0), m_pitch(0), m_roll(0)
55 {
56  m_coords[0] = m_coords[1] = m_coords[2] = 0;
57  m_ROT.unit(3, 1.0);
58 }
59 
61  const double x, const double y, const double z, const double yaw,
62  const double pitch, const double roll)
63  : m_ROT(UNINITIALIZED_MATRIX), m_ypr_uptodate(false)
64 {
65  setFromValues(x, y, z, yaw, pitch, roll);
66 }
67 
68 CPose3D::CPose3D(const mrpt::math::TPose3D& o) : m_ypr_uptodate(false)
69 {
70  setFromValues(o.x, o.y, o.z, o.yaw, o.pitch, o.roll);
71 }
72 
73 CPose3D::CPose3D(const CPose2D& p) : m_ypr_uptodate(false)
74 {
75  setFromValues(p.x(), p.y(), 0, p.phi(), 0, 0);
76 }
77 
79  : m_ypr_uptodate(false), m_yaw(), m_pitch(), m_roll()
80 {
81  setFromValues(p.x(), p.y(), p.z());
82 }
83 
85  : m_ROT(UNINITIALIZED_MATRIX), m_ypr_uptodate(false)
86 {
89  for (int r = 0; r < 3; r++)
90  for (int c = 0; c < 3; c++) m_ROT(r, c) = m.get_unsafe(r, c);
91  for (int r = 0; r < 3; r++) m_coords[r] = m.get_unsafe(r, 3);
92 }
93 
95  : m_ROT(UNINITIALIZED_MATRIX), m_ypr_uptodate(false)
96 {
97  for (int r = 0; r < 3; r++)
98  for (int c = 0; c < 3; c++) m_ROT(r, c) = m.get_unsafe(r, c);
99  for (int r = 0; r < 3; r++) m_coords[r] = m.get_unsafe(r, 3);
100 }
101 
102 /** Constructor from a quaternion (which only represents the 3D rotation part)
103  * and a 3D displacement. */
105  const mrpt::math::CQuaternionDouble& q, const double _x, const double _y,
106  const double _z)
107  : m_ROT(UNINITIALIZED_MATRIX), m_ypr_uptodate(false)
108 {
109  double yaw, pitch, roll;
110  q.rpy(roll, pitch, yaw);
111  this->setFromValues(_x, _y, _z, yaw, pitch, roll);
112 }
113 
114 /** Constructor from a quaternion-based full pose. */
116  : m_ROT(UNINITIALIZED_MATRIX), m_ypr_uptodate(false)
117 {
118  // Extract XYZ + ROT from quaternion:
119  m_coords[0] = p.x();
120  m_coords[1] = p.y();
121  m_coords[2] = p.z();
122  p.quat().rotationMatrixNoResize(m_ROT);
123 }
124 
125 /** Constructor from a rotation vector-based full pose. */
127  : m_ROT(UNINITIALIZED_MATRIX), m_ypr_uptodate(false)
128 {
129  m_coords[0] = p.m_coords[0];
130  m_coords[1] = p.m_coords[1];
131  m_coords[2] = p.m_coords[2];
132 
133  this->setRotationMatrix(this->exp_rotation(p.m_rotvec));
134 }
135 
136 /*---------------------------------------------------------------
137  Implements the writing to a CStream capability of
138  CSerializable objects
139  ---------------------------------------------------------------*/
140 void CPose3D::writeToStream(mrpt::utils::CStream& out, int* version) const
141 {
142  if (version)
143  *version = 2;
144  else
145  {
146  const CPose3DQuat q(*this);
147  // The coordinates:
148  out << q[0] << q[1] << q[2] << q[3] << q[4] << q[5] << q[6];
149  }
150 }
151 
152 /*---------------------------------------------------------------
153  Implements the reading from a CStream capability of
154  CSerializable objects
155  ---------------------------------------------------------------*/
157 {
158  switch (version)
159  {
160  case 0:
161  {
162  // The coordinates:
163  CMatrix HM2;
164  in >> HM2;
165  ASSERT_(mrpt::math::size(HM2, 1) == 4 && HM2.isSquare())
166 
167  m_ROT = HM2.block(0, 0, 3, 3).cast<double>();
168 
169  m_coords[0] = HM2.get_unsafe(0, 3);
170  m_coords[1] = HM2.get_unsafe(1, 3);
171  m_coords[2] = HM2.get_unsafe(2, 3);
172  m_ypr_uptodate = false;
173  }
174  break;
175  case 1:
176  {
177  // The coordinates:
178  CMatrixDouble44 HM;
179  in >> HM;
180 
181  m_ROT = HM.block(0, 0, 3, 3);
182 
183  m_coords[0] = HM.get_unsafe(0, 3);
184  m_coords[1] = HM.get_unsafe(1, 3);
185  m_coords[2] = HM.get_unsafe(2, 3);
186  m_ypr_uptodate = false;
187  }
188  break;
189  case 2:
190  {
191  // An equivalent CPose3DQuat
193  in >> p[0] >> p[1] >> p[2] >> p[3] >> p[4] >> p[5] >> p[6];
194 
195  // Extract XYZ + ROT from quaternion:
196  m_ypr_uptodate = false;
197  m_coords[0] = p.x();
198  m_coords[1] = p.y();
199  m_coords[2] = p.z();
200  p.quat().rotationMatrixNoResize(m_ROT);
201  }
202  break;
203  default:
205  };
206 }
207 
208 /** Textual output stream function.
209  */
210 std::ostream& mrpt::poses::operator<<(std::ostream& o, const CPose3D& p)
211 {
212  const std::streamsize old_pre = o.precision();
213  const std::ios_base::fmtflags old_flags = o.flags();
214  o << "(x,y,z,yaw,pitch,roll)=(" << std::fixed << std::setprecision(4)
215  << p.m_coords[0] << "," << p.m_coords[1] << "," << p.m_coords[2] << ","
216  << std::setprecision(2) << RAD2DEG(p.yaw()) << "deg,"
217  << RAD2DEG(p.pitch()) << "deg," << RAD2DEG(p.roll()) << "deg)";
218  o.flags(old_flags);
219  o.precision(old_pre);
220  return o;
221 }
222 
223 /*---------------------------------------------------------------
224  Implements the writing to a mxArray for Matlab
225  ---------------------------------------------------------------*/
226 #if MRPT_HAS_MATLAB
227 // Add to implement mexplus::from template specialization
229 
231 {
232  const char* fields[] = {"R", "t"};
233  mexplus::MxArray pose_struct(
234  mexplus::MxArray::Struct(sizeof(fields) / sizeof(fields[0]), fields));
235  pose_struct.set("R", mrpt::math::convertToMatlab(this->m_ROT));
236  pose_struct.set("t", mrpt::math::convertToMatlab(this->m_coords));
237  return pose_struct.release();
238 }
239 #endif
240 
241 /*---------------------------------------------------------------
242  normalizeAngles
243 ---------------------------------------------------------------*/
245 /*---------------------------------------------------------------
246  Set the pose from 3D point and yaw/pitch/roll angles, in radians.
247 ---------------------------------------------------------------*/
249  const double x0, const double y0, const double z0, const double yaw,
250  const double pitch, const double roll)
251 {
252  m_coords[0] = x0;
253  m_coords[1] = y0;
254  m_coords[2] = z0;
255  this->m_yaw = mrpt::math::wrapToPi(yaw);
256  this->m_pitch = mrpt::math::wrapToPi(pitch);
257  this->m_roll = mrpt::math::wrapToPi(roll);
258 
259  m_ypr_uptodate = true;
260 
262 }
263 
264 /*---------------------------------------------------------------
265  Set the pose from 3D point and yaw/pitch/roll angles, in radians.
266 ---------------------------------------------------------------*/
268 {
269 #ifdef HAVE_SINCOS
270  double cy, sy;
271  ::sincos(m_yaw, &sy, &cy);
272  double cp, sp;
273  ::sincos(m_pitch, &sp, &cp);
274  double cr, sr;
275  ::sincos(m_roll, &sr, &cr);
276 #else
277  const double cy = cos(m_yaw);
278  const double sy = sin(m_yaw);
279  const double cp = cos(m_pitch);
280  const double sp = sin(m_pitch);
281  const double cr = cos(m_roll);
282  const double sr = sin(m_roll);
283 #endif
284 
285  alignas(16) const double rot_vals[] = {cy * cp,
286  cy * sp * sr - sy * cr,
287  cy * sp * cr + sy * sr,
288  sy * cp,
289  sy * sp * sr + cy * cr,
290  sy * sp * cr - cy * sr,
291  -sp,
292  cp * sr,
293  cp * cr};
294  m_ROT.loadFromArray(rot_vals);
295 }
296 
297 /*---------------------------------------------------------------
298  Scalar multiplication.
299 ---------------------------------------------------------------*/
300 void CPose3D::operator*=(const double s)
301 {
303  m_coords[0] *= s;
304  m_coords[1] *= s;
305  m_coords[2] *= s;
306  m_yaw *= s;
307  m_pitch *= s;
308  m_roll *= s;
310 }
311 
312 /*---------------------------------------------------------------
313  getYawPitchRoll
314 ---------------------------------------------------------------*/
315 void CPose3D::getYawPitchRoll(double& yaw, double& pitch, double& roll) const
316 {
318  std::abs(
319  sqrt(
320  square(m_ROT(0, 0)) + square(m_ROT(1, 0)) +
321  square(m_ROT(2, 0))) -
322  1) < 3e-3,
323  "Homogeneous matrix is not orthogonal & normalized!: " +
324  m_ROT.inMatlabFormat())
326  std::abs(
327  sqrt(
328  square(m_ROT(0, 1)) + square(m_ROT(1, 1)) +
329  square(m_ROT(2, 1))) -
330  1) < 3e-3,
331  "Homogeneous matrix is not orthogonal & normalized!: " +
332  m_ROT.inMatlabFormat())
334  std::abs(
335  sqrt(
336  square(m_ROT(0, 2)) + square(m_ROT(1, 2)) +
337  square(m_ROT(2, 2))) -
338  1) < 3e-3,
339  "Homogeneous matrix is not orthogonal & normalized!: " +
340  m_ROT.inMatlabFormat())
341 
342  // Pitch is in the range [-pi/2, pi/2 ], so this calculation is enough:
343  pitch = atan2(
344  -m_ROT(2, 0),
345  hypot(m_ROT(0, 0), m_ROT(1, 0))); // asin( - m_ROT(2,0) );
346 
347  // Roll:
348  if ((fabs(m_ROT(2, 1)) + fabs(m_ROT(2, 2))) <
349  10 * std::numeric_limits<double>::epsilon())
350  {
351  // Gimbal lock between yaw and roll. This one is arbitrarily forced to
352  // be zero.
353  // Check
354  // http://reference.mrpt.org/devel/classmrpt_1_1poses_1_1_c_pose3_d.html.
355  // If cos(pitch)==0, the homogeneous matrix is:
356  // When sin(pitch)==1:
357  // /0 cysr-sycr cycr+sysr x\ /0 sin(r-y) cos(r-y) x\.
358  // |0 sysr+cycr sycr-cysr y| = |0 cos(r-y) -sin(r-y) y|
359  // |-1 0 0 z| |-1 0 0 z|
360  // \0 0 0 1/ \0 0 0 1/
361  //
362  // And when sin(pitch)=-1:
363  // /0 -cysr-sycr -cycr+sysr x\ /0 -sin(r+y) -cos(r+y) x\.
364  // |0 -sysr+cycr -sycr-cysr y| = |0 cos(r+y) -sin(r+y) y|
365  // |1 0 0 z| |1 0 0 z|
366  // \0 0 0 1/ \0 0 0 1/
367  //
368  // Both cases are in a "gimbal lock" status. This happens because pitch
369  // is vertical.
370 
371  roll = 0.0;
372  if (pitch > 0)
373  yaw = atan2(m_ROT(1, 2), m_ROT(0, 2));
374  else
375  yaw = atan2(-m_ROT(1, 2), -m_ROT(0, 2));
376  }
377  else
378  {
379  roll = atan2(m_ROT(2, 1), m_ROT(2, 2));
380  // Yaw:
381  yaw = atan2(m_ROT(1, 0), m_ROT(0, 0));
382  }
383 }
384 
385 /*---------------------------------------------------------------
386  sphericalCoordinates
387 ---------------------------------------------------------------*/
389  const TPoint3D& point, double& out_range, double& out_yaw,
390  double& out_pitch) const
391 {
392  // Pass to coordinates as seen from this 6D pose:
393  TPoint3D local;
394  this->inverseComposePoint(
395  point.x, point.y, point.z, local.x, local.y, local.z);
396 
397  // Range:
398  out_range = local.norm();
399 
400  // Yaw:
401  if (local.y != 0 || local.x != 0)
402  out_yaw = atan2(local.y, local.x);
403  else
404  out_yaw = 0;
405 
406  // Pitch:
407  if (out_range != 0)
408  out_pitch = -asin(local.z / out_range);
409  else
410  out_pitch = 0;
411 }
412 
414 {
415  return CPose3D(
416  -m_coords[0], -m_coords[1], -m_coords[2], -m_yaw, -m_pitch, -m_roll);
417 }
418 
419 /*---------------------------------------------------------------
420  addComponents
421 ---------------------------------------------------------------*/
423 {
425  m_coords[0] += p.m_coords[0];
426  m_coords[1] += p.m_coords[1];
427  m_coords[2] += p.m_coords[2];
428  m_yaw += p.m_yaw;
429  m_pitch += p.m_pitch;
430  m_roll += p.m_roll;
432 }
433 
434 /*---------------------------------------------------------------
435  distanceEuclidean6D
436 ---------------------------------------------------------------*/
437 double CPose3D::distanceEuclidean6D(const CPose3D& o) const
438 {
440  o.updateYawPitchRoll();
441  return sqrt(
442  square(o.m_coords[0] - m_coords[0]) +
443  square(o.m_coords[1] - m_coords[1]) +
444  square(o.m_coords[2] - m_coords[2]) +
445  square(wrapToPi(o.m_yaw - m_yaw)) +
447  square(wrapToPi(o.m_roll - m_roll)));
448 }
449 
450 /*---------------------------------------------------------------
451  composePoint
452 ---------------------------------------------------------------*/
454  double lx, double ly, double lz, double& gx, double& gy, double& gz,
455  mrpt::math::CMatrixFixedNumeric<double, 3, 3>* out_jacobian_df_dpoint,
456  mrpt::math::CMatrixFixedNumeric<double, 3, 6>* out_jacobian_df_dpose,
457  mrpt::math::CMatrixFixedNumeric<double, 3, 6>* out_jacobian_df_dse3,
458  bool use_small_rot_approx) const
459 {
460  // Jacob: df/dpoint
461  if (out_jacobian_df_dpoint) *out_jacobian_df_dpoint = m_ROT;
462 
463  // Jacob: df/dpose
464  if (out_jacobian_df_dpose)
465  {
466  if (use_small_rot_approx)
467  {
468  // Linearized Jacobians around (yaw,pitch,roll)=(0,0,0):
469  alignas(16) const double nums[3 * 6] = {
470  1, 0, 0, -ly, lz, 0, 0, 1, 0, lx, 0, -lz, 0, 0, 1, 0, -lx, ly};
471  out_jacobian_df_dpose->loadFromArray(nums);
472  }
473  else
474  {
475  // Exact Jacobians:
477 #ifdef HAVE_SINCOS
478  double cy, sy;
479  ::sincos(m_yaw, &sy, &cy);
480  double cp, sp;
481  ::sincos(m_pitch, &sp, &cp);
482  double cr, sr;
483  ::sincos(m_roll, &sr, &cr);
484 #else
485  const double cy = cos(m_yaw);
486  const double sy = sin(m_yaw);
487  const double cp = cos(m_pitch);
488  const double sp = sin(m_pitch);
489  const double cr = cos(m_roll);
490  const double sr = sin(m_roll);
491 #endif
492 
493  alignas(16) const double nums[3 * 6] = {
494  1, 0, 0,
495  -lx * sy * cp + ly * (-sy * sp * sr - cy * cr) +
496  lz * (-sy * sp * cr + cy * sr), // d_x'/d_yaw
497  -lx * cy * sp + ly * (cy * cp * sr) +
498  lz * (cy * cp * cr), // d_x'/d_pitch
499  ly * (cy * sp * cr + sy * sr) +
500  lz * (-cy * sp * sr + sy * cr), // d_x'/d_roll
501  0,
502  1, 0,
503  lx * cy * cp + ly * (cy * sp * sr - sy * cr) +
504  lz * (cy * sp * cr + sy * sr), // d_y'/d_yaw
505  -lx * sy * sp + ly * (sy * cp * sr) +
506  lz * (sy * cp * cr), // d_y'/d_pitch
507  ly * (sy * sp * cr - cy * sr) +
508  lz * (-sy * sp * sr - cy * cr), // d_y'/d_roll
509  0,
510  0, 1,
511  0, // d_z' / d_yaw
512  -lx * cp - ly * sp * sr - lz * sp * cr, // d_z' / d_pitch
513  ly * cp * cr - lz * cp * sr // d_z' / d_roll
514  };
515  out_jacobian_df_dpose->loadFromArray(nums);
516  }
517  }
518 
519  gx = m_ROT(0, 0) * lx + m_ROT(0, 1) * ly + m_ROT(0, 2) * lz + m_coords[0];
520  gy = m_ROT(1, 0) * lx + m_ROT(1, 1) * ly + m_ROT(1, 2) * lz + m_coords[1];
521  gz = m_ROT(2, 0) * lx + m_ROT(2, 1) * ly + m_ROT(2, 2) * lz + m_coords[2];
522 
523  // Jacob: df/dse3
524  if (out_jacobian_df_dse3)
525  {
526  alignas(16) const double nums[3 * 6] = {
527  1, 0, 0, 0, gz, -gy, 0, 1, 0, -gz, 0, gx, 0, 0, 1, gy, -gx, 0};
528  out_jacobian_df_dse3->loadFromArray(nums);
529  }
530 }
531 
532 // TODO: Use SSE2? OTOH, this forces mem align...
533 #if MRPT_HAS_SSE2 && defined(MRPT_USE_SSE2)
534 /*static inline __m128 transformSSE(const __m128* matrix, const __m128& in)
535 {
536  ASSERT_(((size_t)matrix & 15) == 0);
537  __m128 a0 = _mm_mul_ps(_mm_load_ps((float*)(matrix+0)),
538 _mm_shuffle_ps(in,in,_MM_SHUFFLE(0,0,0,0)));
539  __m128 a1 = _mm_mul_ps(_mm_load_ps((float*)(matrix+1)),
540 _mm_shuffle_ps(in,in,_MM_SHUFFLE(1,1,1,1)));
541  __m128 a2 = _mm_mul_ps(_mm_load_ps((float*)(matrix+2)),
542 _mm_shuffle_ps(in,in,_MM_SHUFFLE(2,2,2,2)));
543 
544  return _mm_add_ps(_mm_add_ps(a0,a1),a2);
545 }*/
546 #endif // SSE2
547 
548 /*---------------------------------------------------------------
549  getAsVector
550 ---------------------------------------------------------------*/
552 {
554  r.resize(6);
555  r[0] = m_coords[0];
556  r[1] = m_coords[1];
557  r[2] = m_coords[2];
558  r[3] = m_yaw;
559  r[4] = m_pitch;
560  r[5] = m_roll;
561 }
562 
564 {
566  r[0] = m_coords[0];
567  r[1] = m_coords[1];
568  r[2] = m_coords[2];
569  r[3] = m_yaw;
570  r[4] = m_pitch;
571  r[5] = m_roll;
572 }
573 
574 /*---------------------------------------------------------------
575  unary -
576 ---------------------------------------------------------------*/
578 {
580  b.getInverseHomogeneousMatrix(B_INV);
581  return CPose3D(B_INV);
582 }
583 
587 {
590  .getAsQuaternion(q, out_dq_dr);
591 }
592 
593 bool mrpt::poses::operator==(const CPose3D& p1, const CPose3D& p2)
594 {
595  return (p1.m_coords == p2.m_coords) &&
596  ((p1.getRotationMatrix() - p2.getRotationMatrix())
597  .array()
598  .abs()
599  .maxCoeff() < 1e-6);
600 }
601 
602 bool mrpt::poses::operator!=(const CPose3D& p1, const CPose3D& p2)
603 {
604  return (p1.m_coords != p2.m_coords) ||
605  ((p1.getRotationMatrix() - p2.getRotationMatrix())
606  .array()
607  .abs()
608  .maxCoeff() >= 1e-6);
609 }
610 
611 /*---------------------------------------------------------------
612  point3D = pose3D + point3D
613  ---------------------------------------------------------------*/
615 {
616  return CPoint3D(
617  m_coords[0] + m_ROT(0, 0) * b.x() + m_ROT(0, 1) * b.y() +
618  m_ROT(0, 2) * b.z(),
619  m_coords[1] + m_ROT(1, 0) * b.x() + m_ROT(1, 1) * b.y() +
620  m_ROT(1, 2) * b.z(),
621  m_coords[2] + m_ROT(2, 0) * b.x() + m_ROT(2, 1) * b.y() +
622  m_ROT(2, 2) * b.z());
623 }
624 
625 /*---------------------------------------------------------------
626  point3D = pose3D + point2D
627  ---------------------------------------------------------------*/
629 {
630  return CPoint3D(
631  m_coords[0] + m_ROT(0, 0) * b.x() + m_ROT(0, 1) * b.y(),
632  m_coords[1] + m_ROT(1, 0) * b.x() + m_ROT(1, 1) * b.y(),
633  m_coords[2] + m_ROT(2, 0) * b.x() + m_ROT(2, 1) * b.y());
634 }
635 
636 /*---------------------------------------------------------------
637  this = A + B
638  ---------------------------------------------------------------*/
639 void CPose3D::composeFrom(const CPose3D& A, const CPose3D& B)
640 {
641  // The translation part HM(0:3,3)
642  if (this == &B)
643  {
644  // we need to make a temporary copy of the vector:
645  const CArrayDouble<3> B_coords = B.m_coords;
646  for (int r = 0; r < 3; r++)
647  m_coords[r] = A.m_coords[r] + A.m_ROT(r, 0) * B_coords[0] +
648  A.m_ROT(r, 1) * B_coords[1] +
649  A.m_ROT(r, 2) * B_coords[2];
650  }
651  else
652  {
653  for (int r = 0; r < 3; r++)
654  m_coords[r] = A.m_coords[r] + A.m_ROT(r, 0) * B.m_coords[0] +
655  A.m_ROT(r, 1) * B.m_coords[1] +
656  A.m_ROT(r, 2) * B.m_coords[2];
657  }
658 
659  // Important: Make this multiplication AFTER the translational part, to cope
660  // with the case when A==this
661  m_ROT.multiply_AB(A.m_ROT, B.m_ROT);
662 
663  m_ypr_uptodate = false;
664 }
665 
666 /** Convert this pose into its inverse, saving the result in itself. */
668 {
670  CArrayDouble<3> inv_xyz;
671 
673 
674  m_ROT = inv_rot;
675  m_coords = inv_xyz;
676  m_ypr_uptodate = false;
677 }
678 
679 /*---------------------------------------------------------------
680  isHorizontal
681  ---------------------------------------------------------------*/
682 bool CPose3D::isHorizontal(const double tolerance) const
683 {
685  return (fabs(m_pitch) <= tolerance || M_PI - fabs(m_pitch) <= tolerance) &&
686  (fabs(m_roll) <= tolerance ||
687  fabs(mrpt::math::wrapToPi(m_roll - M_PI)) <= tolerance);
688 }
689 
690 /** Makes \f$ this = A \ominus B \f$ this method is slightly more efficient
691  * than "this= A - B;" since it avoids the temporary object.
692  * \note A or B can be "this" without problems.
693  * \sa composeFrom, composePoint
694  */
696 {
697  // this = A (-) B
698  // HM_this = inv(HM_B) * HM_A
699  //
700  // [ R_b | t_b ] -1 [ R_a | t_a ] [ R_b^t * Ra | .. ]
701  // [ ------+-----] * [ ------+-----] = [ ---------- +----------]
702  // [ 0 0 0 | 1 ] [ 0 0 0 | 1 ] [ 0 0 0 | 1 ]
703  //
704 
705  // XYZ part:
707  CArrayDouble<3> t_b_inv;
708  mrpt::math::homogeneousMatrixInverse(B.m_ROT, B.m_coords, R_b_inv, t_b_inv);
709 
710  for (int i = 0; i < 3; i++)
711  m_coords[i] = t_b_inv[i] + R_b_inv(i, 0) * A.m_coords[0] +
712  R_b_inv(i, 1) * A.m_coords[1] +
713  R_b_inv(i, 2) * A.m_coords[2];
714 
715  // Rot part:
716  m_ROT.multiply_AB(R_b_inv, A.m_ROT);
717  m_ypr_uptodate = false;
718 }
719 
720 /** Computes the 3D point L such as \f$ L = G \ominus this \f$.
721  * \sa composePoint, composeFrom
722  */
724  const double gx, const double gy, const double gz, double& lx, double& ly,
725  double& lz,
726  mrpt::math::CMatrixFixedNumeric<double, 3, 3>* out_jacobian_df_dpoint,
727  mrpt::math::CMatrixFixedNumeric<double, 3, 6>* out_jacobian_df_dpose,
728  mrpt::math::CMatrixFixedNumeric<double, 3, 6>* out_jacobian_df_dse3) const
729 {
731  CArrayDouble<3> t_inv;
733 
734  // Jacob: df/dpoint
735  if (out_jacobian_df_dpoint) *out_jacobian_df_dpoint = R_inv;
736 
737  // Jacob: df/dpose
738  if (out_jacobian_df_dpose)
739  {
740  // TODO: Perhaps this and the sin/cos's can be avoided if all needed
741  // terms are already in m_ROT ???
743 
744 #ifdef HAVE_SINCOS
745  double cy, sy;
746  ::sincos(m_yaw, &sy, &cy);
747  double cp, sp;
748  ::sincos(m_pitch, &sp, &cp);
749  double cr, sr;
750  ::sincos(m_roll, &sr, &cr);
751 #else
752  const double cy = cos(m_yaw);
753  const double sy = sin(m_yaw);
754  const double cp = cos(m_pitch);
755  const double sp = sin(m_pitch);
756  const double cr = cos(m_roll);
757  const double sr = sin(m_roll);
758 #endif
759 
760  const double m11_dy = -sy * cp;
761  const double m12_dy = cy * cp;
762  const double m13_dy = 0;
763  const double m11_dp = -cy * sp;
764  const double m12_dp = -sy * sp;
765  const double m13_dp = -cp;
766  const double m11_dr = 0;
767  const double m12_dr = 0;
768  const double m13_dr = 0;
769 
770  const double m21_dy = (-sy * sp * sr - cy * cr);
771  const double m22_dy = (cy * sp * sr - sy * cr);
772  const double m23_dy = 0;
773  const double m21_dp = (cy * cp * sr);
774  const double m22_dp = (sy * cp * sr);
775  const double m23_dp = -sp * sr;
776  const double m21_dr = (cy * sp * cr + sy * sr);
777  const double m22_dr = (sy * sp * cr - cy * sr);
778  const double m23_dr = cp * cr;
779 
780  const double m31_dy = (-sy * sp * cr + cy * sr);
781  const double m32_dy = (cy * sp * cr + sy * sr);
782  const double m33_dy = 0;
783  const double m31_dp = (cy * cp * cr);
784  const double m32_dp = (sy * cp * cr);
785  const double m33_dp = -sp * cr;
786  const double m31_dr = (-cy * sp * sr + sy * cr);
787  const double m32_dr = (-sy * sp * sr - cy * cr);
788  const double m33_dr = -cp * sr;
789 
790  const double Ax = gx - m_coords[0];
791  const double Ay = gy - m_coords[1];
792  const double Az = gz - m_coords[2];
793 
794  alignas(16) const double nums[3 * 6] = {
795  -m_ROT(0, 0),
796  -m_ROT(1, 0),
797  -m_ROT(2, 0),
798  Ax * m11_dy + Ay * m12_dy + Az * m13_dy, // d_x'/d_yaw
799  Ax * m11_dp + Ay * m12_dp + Az * m13_dp, // d_x'/d_pitch
800  Ax * m11_dr + Ay * m12_dr + Az * m13_dr, // d_x'/d_roll
801 
802  -m_ROT(0, 1),
803  -m_ROT(1, 1),
804  -m_ROT(2, 1),
805  Ax * m21_dy + Ay * m22_dy + Az * m23_dy, // d_x'/d_yaw
806  Ax * m21_dp + Ay * m22_dp + Az * m23_dp, // d_x'/d_pitch
807  Ax * m21_dr + Ay * m22_dr + Az * m23_dr, // d_x'/d_roll
808 
809  -m_ROT(0, 2),
810  -m_ROT(1, 2),
811  -m_ROT(2, 2),
812  Ax * m31_dy + Ay * m32_dy + Az * m33_dy, // d_x'/d_yaw
813  Ax * m31_dp + Ay * m32_dp + Az * m33_dp, // d_x'/d_pitch
814  Ax * m31_dr + Ay * m32_dr + Az * m33_dr, // d_x'/d_roll
815  };
816  out_jacobian_df_dpose->loadFromArray(nums);
817  }
818 
819  lx = t_inv[0] + R_inv(0, 0) * gx + R_inv(0, 1) * gy + R_inv(0, 2) * gz;
820  ly = t_inv[1] + R_inv(1, 0) * gx + R_inv(1, 1) * gy + R_inv(1, 2) * gz;
821  lz = t_inv[2] + R_inv(2, 0) * gx + R_inv(2, 1) * gy + R_inv(2, 2) * gz;
822 
823  // Jacob: df/dse3
824  if (out_jacobian_df_dse3)
825  {
826  alignas(16) const double nums[3 * 6] = {
827  -1, 0, 0, 0, -lz, ly, 0, -1, 0, lz, 0, -lx, 0, 0, -1, -ly, lx, 0};
828  out_jacobian_df_dse3->loadFromArray(nums);
829  }
830 }
831 
833  const mrpt::math::CArrayNumeric<double, 6>& mu, bool pseudo_exponential)
834 {
836  CPose3D::exp(mu, P, pseudo_exponential);
837  return P;
838 }
839 
841  const mrpt::math::CArrayNumeric<double, 6>& mu, CPose3D& out_pose,
842  bool pseudo_exponential)
843 {
844  if (pseudo_exponential)
845  {
846  auto R = Sophus::SO3<double>::exp(mu.block<3, 1>(3, 0));
847  out_pose.setRotationMatrix(R.matrix());
848  out_pose.x(mu[0]);
849  out_pose.y(mu[1]);
850  out_pose.z(mu[2]);
851  }
852  else
853  {
854  auto R = Sophus::SE3<double>::exp(mu);
855  out_pose = CPose3D(CMatrixDouble44(R.matrix()));
856  }
857 }
858 
860 {
861  Sophus::SO3<double> R(this->m_ROT);
862  return R.log();
863 }
864 
867 {
868  auto R = Sophus::SO3<double>::exp(w);
869  return R.matrix();
870 }
871 
872 void CPose3D::ln(CArrayDouble<6>& result) const
873 {
874  const Sophus::SE3<double> RT(m_ROT, m_coords);
875  result = RT.log();
876 }
877 
878 /* The following code fragments are based on formulas originally reported in the
879  * TooN and RobotVision packages */
880 namespace mrpt
881 {
882 namespace poses
883 {
884 template <class VEC3, class MAT33>
885 inline void deltaR(const MAT33& R, VEC3& v)
886 {
887  v[0] = R(2, 1) - R(1, 2);
888  v[1] = R(0, 2) - R(2, 0);
889  v[2] = R(1, 0) - R(0, 1);
890 }
891 
892 template <typename VEC3, typename MAT3x3, typename MAT3x9>
893 inline void M3x9(const VEC3& a, const MAT3x3& B, MAT3x9& RES)
894 {
895  alignas(16) const double vals[] = {
896  a[0], -B(0, 2), B(0, 1), B(0, 2), a[0], -B(0, 0), -B(0, 1),
897  B(0, 0), a[0], a[1], -B(1, 2), B(1, 1), B(1, 2), a[1],
898  -B(1, 0), -B(1, 1), B(1, 0), a[1], a[2], -B(2, 2), B(2, 1),
899  B(2, 2), a[2], -B(2, 0), -B(2, 1), B(2, 0), a[2]};
900  RES.loadFromArray(vals);
901 }
902 
904 {
905  const CMatrixDouble33& R = P.getRotationMatrix();
906  const CArrayDouble<3>& t = P.m_coords;
907 
908  CArrayDouble<3> abc;
909  deltaR(R, abc);
910  double a = abc[0];
911  double b = abc[1];
912  double c = abc[2];
913 
914  alignas(16) const double vals[] = {
915  -b * t[1] - c * t[2], 2 * b * t[0] - a * t[1],
916  2 * c * t[0] - a * t[2], -b * t[0] + 2 * a * t[1],
917  -a * t[0] - c * t[2], 2 * c * t[1] - b * t[2],
918  -c * t[0] + 2 * a * t[2], -c * t[1] + 2 * b * t[2],
919  -a * t[0] - b * t[1]};
920  return CMatrixDouble33(vals);
921 }
922 
924 {
927 
928  const CMatrixDouble33& R = P.getRotationMatrix();
929  const CArrayDouble<3>& t = P.m_coords;
930 
931  const double d = 0.5 * (R(0, 0) + R(1, 1) + R(2, 2) - 1);
932 
933  if (d > 0.9999)
934  {
935  a[0] = a[1] = a[2] = 0;
936  B.zeros();
937  }
938  else
939  {
940  const double theta = acos(d);
941  const double theta2 = square(theta);
942  const double oned2 = (1 - square(d));
943  const double sq = std::sqrt(oned2);
944  const double cot = 1. / tan(0.5 * theta);
945  const double csc2 = square(1. / sin(0.5 * theta));
946 
948  CArrayDouble<3> vr;
949  deltaR(R, vr);
950  mrpt::math::skew_symmetric3(vr, skewR);
951 
952  CArrayDouble<3> skewR_t;
953  skewR.multiply_Ab(t, skewR_t);
954 
955  skewR_t *= -(d * theta - sq) / (8 * pow(sq, 3));
956  a = skewR_t;
957 
959  skewR2.multiply_AB(skewR, skewR);
960 
961  CArrayDouble<3> skewR2_t;
962  skewR2.multiply_Ab(t, skewR2_t);
963  skewR2_t *=
964  (((theta * sq - d * theta2) * (0.5 * theta * cot - 1)) -
965  theta * sq * ((0.25 * theta * cot) + 0.125 * theta2 * csc2 - 1)) /
966  (4 * theta2 * square(oned2));
967  a += skewR2_t;
968 
970  B *= -0.5 * theta / (2 * sq);
971 
972  B += -(theta * cot - 2) / (8 * oned2) * ddeltaRt_dR(P);
973  }
974  M3x9(a, B, J);
975 }
976 }
977 }
978 
980 {
981  J.zeros();
982  // Jacobian structure 6x12:
983  // (3rows, for t) [ d_Vinvt_dR (3x9) | Vinv (3x3) ]
984  // [ -------------------------+------------- ]
985  // (3rows, for \omega) [ d_lnR_dR (3x9) | 0 (3x3) ]
986  //
987  // derivs wrt: R_col1 R_col2 R_col3 | t
988  //
989  // (Will be explained better in:
990  // http://www.mrpt.org/6D_poses:equivalences_compositions_and_uncertainty )
991  //
992  {
994  ln_rot_jacob(m_ROT, M);
995  J.insertMatrix(3, 0, M);
996  }
997  {
999  dVinvt_dR(*this, M);
1000  J.insertMatrix(0, 0, M);
1001  }
1002 
1003  const CMatrixDouble33& R = m_ROT;
1004  CArrayDouble<3> omega;
1006 
1008  V_inv.unit(3, 1.0); // Start with the identity_3
1009 
1010  const double d = 0.5 * (R(0, 0) + R(1, 1) + R(2, 2) - 1);
1011  if (d > 0.99999)
1012  {
1013  mrpt::poses::deltaR(R, omega);
1014  omega *= 0.5;
1015  mrpt::math::skew_symmetric3(omega, Omega);
1017  Omega2.multiply_AAt(Omega);
1018  Omega2 *= 1.0 / 12.0;
1019 
1020  Omega *= 0.5;
1021 
1022  V_inv -= Omega;
1023  V_inv -= Omega2;
1024  }
1025  else
1026  {
1027  mrpt::poses::deltaR(R, omega);
1028 
1029  const double theta = acos(d);
1030  omega *= theta / (2 * std::sqrt(1 - d * d));
1031 
1032  mrpt::math::skew_symmetric3(omega, Omega);
1033 
1035  Omega2.multiply_AAt(Omega);
1036 
1037  Omega2 *= (1 - theta / (2 * std::tan(theta * 0.5))) / square(theta);
1038  Omega *= 0.5;
1039 
1040  V_inv -= Omega;
1041  V_inv += Omega2;
1042  }
1043  J.insertMatrix(0, 9, V_inv);
1044 }
1045 
1048 {
1049  const double d = 0.5 * (R(0, 0) + R(1, 1) + R(2, 2) - 1);
1052  if (d > 0.99999)
1053  {
1054  a[0] = a[1] = a[2] = 0;
1055  B.unit(3, -0.5);
1056  }
1057  else
1058  {
1059  const double theta = acos(d);
1060  const double d2 = square(d);
1061  const double sq = std::sqrt(1 - d2);
1062  deltaR(R, a);
1063  a *= (d * theta - sq) / (4 * (sq * sq * sq));
1064  B.unit(3, -theta / (2 * sq));
1065  }
1066  M3x9(a, B, M);
1067 }
1068 
1069 // Eq. 10.3.5 in tech report
1070 // http://ingmec.ual.es/~jlblanco/papers/jlblanco2010geometry3D_techrep.pdf
1072  const CPose3D& D, Eigen::Matrix<double, 12, 6>& jacob)
1073 {
1074  jacob.block<9, 3>(0, 0).setZero();
1075  jacob.block<3, 3>(9, 0).setIdentity();
1076  for (int i = 0; i < 3; i++)
1077  {
1078  Eigen::Block<Eigen::Matrix<double, 12, 6>, 3, 3, false> trg_blc =
1079  jacob.block<3, 3>(3 * i, 3);
1080  mrpt::math::skew_symmetric3_neg(D.m_ROT.block<3, 1>(0, i), trg_blc);
1081  }
1082  {
1083  Eigen::Block<Eigen::Matrix<double, 12, 6>, 3, 3, false> trg_blc =
1084  jacob.block<3, 3>(9, 3);
1086  }
1087 }
1088 
1089 // Eq. 10.3.7 in tech report
1090 // http://ingmec.ual.es/~jlblanco/papers/jlblanco2010geometry3D_techrep.pdf
1092  const CPose3D& A, const CPose3D& D, Eigen::Matrix<double, 12, 6>& jacob)
1093 {
1094  jacob.block<9, 3>(0, 0).setZero();
1095  jacob.block<3, 3>(9, 0) = A.getRotationMatrix();
1096  Eigen::Matrix<double, 3, 3> aux;
1097  for (int i = 0; i < 3; i++)
1098  {
1100  D.getRotationMatrix().block<3, 1>(0, i), aux);
1101  jacob.block<3, 3>(3 * i, 3) = A.m_ROT * aux;
1102  }
1104  jacob.block<3, 3>(9, 3) = A.m_ROT * aux;
1105 }
1106 
1108 {
1109  for (int i = 0; i < 3; i++)
1110  for (int j = 0; j < 3; j++)
1111  m_ROT(i, j) = std::numeric_limits<double>::quiet_NaN();
1112 
1113  for (int i = 0; i < 3; i++)
1114  m_coords[i] = std::numeric_limits<double>::quiet_NaN();
1115 }
#define local
Definition: zutil.h:47
double x() const
Common members of all points & poses classes.
Definition: CPoseOrPoint.h:135
void inverseComposeFrom(const CPose3D &A, const CPose3D &B)
Makes this method is slightly more efficient than "this= A - B;" since it avoids the temporary objec...
Definition: CPose3D.cpp:695
CPose3D getOppositeScalar() const
Return the opposite of the current pose instance by taking the negative of all its components individ...
Definition: CPose3D.cpp:413
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
GLdouble GLdouble t
Definition: glext.h:3689
GLdouble GLdouble z
Definition: glext.h:3872
static mrpt::math::CMatrixDouble33 exp_rotation(const mrpt::math::CArrayNumeric< double, 3 > &vect)
Exponentiate a vector in the Lie algebra to generate a new SO(3) (a 3x3 rotation matrix).
Definition: CPose3D.cpp:865
mxArray * convertToMatlab(const Eigen::EigenBase< Derived > &mat)
Convert vectors, arrays and matrices into Matlab vectors/matrices.
Definition: utils_matlab.h:38
The virtual base class which provides a unified interface for all persistent objects in MRPT...
Definition: CSerializable.h:44
void skew_symmetric3(const VECTOR &v, MATRIX &M)
Computes the 3x3 skew symmetric matrix from a 3-vector or 3-array: .
Definition: geometry.h:853
mrpt::math::CMatrixDouble33 m_ROT
The 3x3 rotation matrix, access with getRotationMatrix(), setRotationMatrix() (It&#39;s not safe to set t...
Definition: CPose3D.h:103
void setToNaN() override
Set all data fields to quiet NaN.
Definition: CPose3D.cpp:1107
bool isHorizontal(const double tolerance=0) const
Return true if the 6D pose represents a Z axis almost exactly vertical (upwards or downwards)...
Definition: CPose3D.cpp:682
double roll
Roll coordinate (rotation angle over X coordinate).
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
bool m_ypr_uptodate
Whether yaw/pitch/roll members are up-to-date since the last rotation matrix update.
Definition: CPose3D.h:107
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:3721
mrpt::math::CArrayDouble< 3 > ln_rotation() const
Take the logarithm of the 3x3 rotation matrix, generating the corresponding vector in the Lie Algebra...
Definition: CPose3D.cpp:859
This file implements several operations that operate element-wise on individual or pairs of container...
double x
X,Y,Z, coords.
CArrayNumeric is an array for numeric types supporting several mathematical operations (actually...
Definition: CArrayNumeric.h:26
void getAsQuaternion(mrpt::math::CQuaternion< double > &q, mrpt::math::CMatrixFixedNumeric< double, 4, 3 > *out_dq_dr=NULL) const
Returns the quaternion associated to the rotation of this object (NOTE: XYZ translation is ignored) ...
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
Definition: eigen_frwds.h:42
double pitch() const
Get the PITCH angle (in radians)
Definition: CPose3D.h:539
double yaw() const
Get the YAW angle (in radians)
Definition: CPose3D.h:533
CPose3D operator+(const CPose3D &b) const
The operator is the pose compounding operator.
Definition: CPose3D.h:261
void rebuildRotationMatrix()
Rebuild the homog matrix from the angles.
Definition: CPose3D.cpp:267
void getAsQuaternion(mrpt::math::CQuaternionDouble &q, mrpt::math::CMatrixFixedNumeric< double, 4, 3 > *out_dq_dr=nullptr) const
Returns the quaternion associated to the rotation of this object (NOTE: XYZ translation is ignored) ...
Definition: CPose3D.cpp:584
#define M_PI
Definition: bits.h:92
CMatrixFixedNumeric< double, 3, 3 > CMatrixDouble33
Definition: eigen_frwds.h:55
double yaw
Yaw coordinate (rotation angle over Z axis).
GLdouble s
Definition: glext.h:3676
void updateYawPitchRoll() const
Updates Yaw/pitch/roll members from the m_ROT.
Definition: CPose3D.h:117
void inverse()
Convert this pose into its inverse, saving the result in itself.
Definition: CPose3D.cpp:667
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
void setRotationMatrix(const mrpt::math::CMatrixDouble33 &ROT)
Sets the 3x3 rotation matrix.
Definition: CPose3D.h:249
void readFromStream(mrpt::utils::CStream &in, int version) override
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
Definition: CPose3D.cpp:156
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
double distanceEuclidean6D(const CPose3D &o) const
The euclidean distance between two poses taken as two 6-length vectors (angles in radians)...
Definition: CPose3D.cpp:437
#define ASSERTDEBMSG_(f, __ERROR_MSG)
static void jacob_dexpeD_de(const CPose3D &D, Eigen::Matrix< double, 12, 6 > &jacob)
The Jacobian d (e^eps * D) / d eps , with eps=increment in Lie Algebra.
Definition: CPose3D.cpp:1071
void skew_symmetric3_neg(const VECTOR &v, MATRIX &M)
Computes the negative version of a 3x3 skew symmetric matrix from a 3-vector or 3-array: ...
Definition: geometry.h:887
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:41
A numeric matrix of compile-time fixed size.
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
void dVinvt_dR(const CPose3D &P, CMatrixFixedNumeric< double, 3, 9 > &J)
Definition: CPose3D.cpp:923
mrpt::math::CArrayDouble< 3 > m_coords
The translation vector [x,y,z] access directly or with x(), y(), z() setter/getter methods...
Definition: CPose3D.h:98
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
const GLubyte * c
Definition: glext.h:6313
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
bool operator!=(const CPoint< DERIVEDCLASS > &p1, const CPoint< DERIVEDCLASS > &p2)
Definition: CPoint.h:171
CPose2D operator-(const CPose2D &p)
Unary - operator: return the inverse pose "-p" (Note that is NOT the same than a pose with negative x...
Definition: CPose2D.cpp:328
void addComponents(const CPose3D &p)
Scalar sum of all 6 components: This is diferent from poses composition, which is implemented as "+" ...
Definition: CPose3D.cpp:422
void sphericalCoordinates(const mrpt::math::TPoint3D &point, double &out_range, double &out_yaw, double &out_pitch) const
Computes the spherical coordinates of a 3D point as seen from the 6D pose specified by this object...
Definition: CPose3D.cpp:388
void M3x9(const VEC3 &a, const MAT3x3 &B, MAT3x9 &RES)
Definition: CPose3D.cpp:893
GLubyte GLubyte b
Definition: glext.h:6279
#define IMPLEMENTS_MEXPLUS_FROM(complete_type)
double x
X,Y,Z coordinates.
A class used to store a 3D pose as a translation (x,y,z) and a quaternion (qr,qx,qy,qz).
Definition: CPose3DQuat.h:48
void deltaR(const MAT33 &R, VEC3 &v)
Definition: CPose3D.cpp:885
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:53
double m_yaw
These variables are updated every time that the object rotation matrix is modified (construction...
Definition: CPose3D.h:111
A class used to store a 2D point.
Definition: CPoint2D.h:36
A class used to store a 3D point.
Definition: CPoint3D.h:32
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
double roll() const
Get the ROLL angle (in radians)
Definition: CPose3D.h:545
double pitch
Pitch coordinate (rotation angle over Y axis).
void operator*=(const double s)
Scalar multiplication of x,y,z,yaw,pitch & roll (angles will be wrapped to the ]-pi,pi] interval).
Definition: CPose3D.cpp:300
void getYawPitchRoll(double &yaw, double &pitch, double &roll) const
Returns the three angles (yaw, pitch, roll), in radians, from the rotation matrix.
Definition: CPose3D.cpp:315
#define RAD2DEG
void ln_jacob(mrpt::math::CMatrixFixedNumeric< double, 6, 12 > &J) const
Jacobian of the logarithm of the 3x4 matrix defined by this pose.
Definition: CPose3D.cpp:979
const GLdouble * v
Definition: glext.h:3678
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
CMatrixDouble33 ddeltaRt_dR(const CPose3D &P)
Definition: CPose3D.cpp:903
#define ASSERT_ABOVEEQ_(__A, __B)
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
size_t size(const MATRIXLIKE &m, const int dim)
bool operator==(const CPoint< DERIVEDCLASS > &p1, const CPoint< DERIVEDCLASS > &p2)
Definition: CPoint.h:163
virtual mxArray * writeToMatlab() const
Introduces a pure virtual method responsible for writing to a mxArray Matlab object, typically a MATLAB struct whose contents are documented in each derived class.
Definition: CSerializable.h:89
void homogeneousMatrixInverse(const MATRIXLIKE1 &M, MATRIXLIKE2 &out_inverse_M)
Efficiently compute the inverse of a 4x4 homogeneous matrix by only transposing the rotation 3x3 part...
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
Definition: CPose2D.h:40
const float R
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:88
static void ln_rot_jacob(const mrpt::math::CMatrixDouble33 &R, mrpt::math::CMatrixFixedNumeric< double, 3, 9 > &M)
Static function to compute the Jacobian of the SO(3) Logarithm function, evaluated at a given 3x3 rot...
Definition: CPose3D.cpp:1046
This file implements matrix/vector text and binary serialization.
void composePoint(double lx, double ly, double lz, double &gx, double &gy, double &gz, mrpt::math::CMatrixFixedNumeric< double, 3, 3 > *out_jacobian_df_dpoint=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dpose=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dse3=nullptr, bool use_small_rot_approx=false) const
An alternative, slightly more efficient way of doing with G and L being 3D points and P this 6D pose...
Definition: CPose3D.cpp:453
mrpt::math::CArrayDouble< 3 > m_rotvec
The rotation vector [vx,vy,vz].
Definition: CPose3DRotVec.h:53
CPose3D()
Default constructor, with all the coordinates set to zero.
Definition: CPose3D.cpp:54
void setFromValues(const double x0, const double y0, const double z0, const double yaw=0, const double pitch=0, const double roll=0)
Set the pose from a 3D position (meters) and yaw/pitch/roll angles (radians) - This method recomputes...
Definition: CPose3D.cpp:248
Lightweight 3D pose (three spatial coordinates, plus three angular coordinates).
GLuint in
Definition: glext.h:7274
#define ASSERT_(f)
A partial specialization of CArrayNumeric for double numbers.
Definition: CArrayNumeric.h:87
GLenum GLint GLint y
Definition: glext.h:3538
void normalizeAngles()
Rebuild the internal matrix & update the yaw/pitch/roll angles within the ]-PI,PI] range (Must be cal...
Definition: CPose3D.cpp:244
mrpt::math::CArrayDouble< 6 > ln() const
Definition: CPose3D.h:689
A 3D pose, with a 3D translation and a rotation in 3D parameterized in rotation-vector form (equivale...
Definition: CPose3DRotVec.h:44
GLenum GLint x
Definition: glext.h:3538
A quaternion, which can represent a 3D rotation as pair , with a real part "r" and a 3D vector ...
Definition: CQuaternion.h:46
void getRotationMatrix(mrpt::math::CMatrixDouble33 &ROT) const
Get the 3x3 rotation matrix.
Definition: CPose3D.h:237
Lightweight 3D point.
void getAsVector(mrpt::math::CVectorDouble &v) const
Returns a 1x6 vector with [x y z yaw pitch roll].
Definition: CPose3D.cpp:551
This class is a "CSerializable" wrapper for "CMatrixFloat".
Definition: CMatrix.h:25
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const override
Introduces a pure virtual method responsible for writing to a CStream.
Definition: CPose3D.cpp:140
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
static CPose3D exp(const mrpt::math::CArrayNumeric< double, 6 > &vect, bool pseudo_exponential=false)
Exponentiate a Vector in the SE(3) Lie Algebra to generate a new CPose3D (static method).
Definition: CPose3D.cpp:832
GLfloat GLfloat p
Definition: glext.h:6305
static void jacob_dAexpeD_de(const CPose3D &A, const CPose3D &D, Eigen::Matrix< double, 12, 6 > &jacob)
The Jacobian d (A * e^eps * D) / d eps , with eps=increment in Lie Algebra.
Definition: CPose3D.cpp:1091
CMatrixFixedNumeric< double, 4, 4 > CMatrixDouble44
Definition: eigen_frwds.h:56
struct mxArray_tag mxArray
Forward declaration for mxArray (avoid #including as much as possible to speed up compiling) ...
Definition: CSerializable.h:19
void inverseComposePoint(const double gx, const double gy, const double gz, double &lx, double &ly, double &lz, mrpt::math::CMatrixFixedNumeric< double, 3, 3 > *out_jacobian_df_dpoint=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dpose=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dse3=nullptr) const
Computes the 3D point L such as .
Definition: CPose3D.cpp:723
std::ostream & operator<<(std::ostream &o, const CPoint< DERIVEDCLASS > &p)
Dumps a point as a string [x,y] or [x,y,z].
Definition: CPoint.h:137



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