MRPT  1.9.9
homog_matrices.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 #pragma once
10 
11 #include <mrpt/core/exceptions.h>
12 
13 namespace mrpt::math
14 {
15 /** Efficiently compute the inverse of a 4x4 homogeneous matrix by only
16  * transposing the rotation 3x3 part and solving the translation with dot
17  * products.
18  * This is a generic template which works with:
19  * MATRIXLIKE: CMatrixTemplateNumeric, CMatrixFixedNumeric
20  */
21 template <class MATRIXLIKE1, class MATRIXLIKE2>
22 void homogeneousMatrixInverse(const MATRIXLIKE1& M, MATRIXLIKE2& out_inverse_M)
23 {
25  ASSERT_(M.isSquare() && M.rows() == 4);
26 
27  /* Instead of performing a generic 4x4 matrix inversion, we only need to
28  transpose the rotation part, then replace the translation part by
29  three dot products. See, for example:
30  https://graphics.stanford.edu/courses/cs248-98-fall/Final/q4.html
31 
32  [ux vx wx tx] -1 [ux uy uz -dot(u,t)]
33  [uy vy wy ty] [vx vy vz -dot(v,t)]
34  [uz vz wz tz] = [wx wy wz -dot(w,t)]
35  [ 0 0 0 1] [ 0 0 0 1 ]
36  */
37 
38  out_inverse_M.setSize(4, 4);
39 
40  // 3x3 rotation part:
41  out_inverse_M.set_unsafe(0, 0, M.get_unsafe(0, 0));
42  out_inverse_M.set_unsafe(0, 1, M.get_unsafe(1, 0));
43  out_inverse_M.set_unsafe(0, 2, M.get_unsafe(2, 0));
44 
45  out_inverse_M.set_unsafe(1, 0, M.get_unsafe(0, 1));
46  out_inverse_M.set_unsafe(1, 1, M.get_unsafe(1, 1));
47  out_inverse_M.set_unsafe(1, 2, M.get_unsafe(2, 1));
48 
49  out_inverse_M.set_unsafe(2, 0, M.get_unsafe(0, 2));
50  out_inverse_M.set_unsafe(2, 1, M.get_unsafe(1, 2));
51  out_inverse_M.set_unsafe(2, 2, M.get_unsafe(2, 2));
52 
53  const double tx = -M.get_unsafe(0, 3);
54  const double ty = -M.get_unsafe(1, 3);
55  const double tz = -M.get_unsafe(2, 3);
56 
57  const double tx_ = tx * M.get_unsafe(0, 0) + ty * M.get_unsafe(1, 0) +
58  tz * M.get_unsafe(2, 0);
59  const double ty_ = tx * M.get_unsafe(0, 1) + ty * M.get_unsafe(1, 1) +
60  tz * M.get_unsafe(2, 1);
61  const double tz_ = tx * M.get_unsafe(0, 2) + ty * M.get_unsafe(1, 2) +
62  tz * M.get_unsafe(2, 2);
63 
64  out_inverse_M.set_unsafe(0, 3, tx_);
65  out_inverse_M.set_unsafe(1, 3, ty_);
66  out_inverse_M.set_unsafe(2, 3, tz_);
67 
68  out_inverse_M.set_unsafe(3, 0, 0);
69  out_inverse_M.set_unsafe(3, 1, 0);
70  out_inverse_M.set_unsafe(3, 2, 0);
71  out_inverse_M.set_unsafe(3, 3, 1);
72 
73  MRPT_END
74 }
75 //! \overload
76 template <class IN_ROTMATRIX, class IN_XYZ, class OUT_ROTMATRIX, class OUT_XYZ>
78  const IN_ROTMATRIX& in_R, const IN_XYZ& in_xyz, OUT_ROTMATRIX& out_R,
79  OUT_XYZ& out_xyz)
80 {
82  ASSERT_(in_R.isSquare() && in_R.rows() == 3 && in_xyz.size() == 3);
83  out_R.setSize(3, 3);
84  out_xyz.resize(3);
85 
86  // translation part:
87  using T = typename IN_ROTMATRIX::Scalar;
88  const T tx = -in_xyz[0];
89  const T ty = -in_xyz[1];
90  const T tz = -in_xyz[2];
91 
92  out_xyz[0] = tx * in_R.get_unsafe(0, 0) + ty * in_R.get_unsafe(1, 0) +
93  tz * in_R.get_unsafe(2, 0);
94  out_xyz[1] = tx * in_R.get_unsafe(0, 1) + ty * in_R.get_unsafe(1, 1) +
95  tz * in_R.get_unsafe(2, 1);
96  out_xyz[2] = tx * in_R.get_unsafe(0, 2) + ty * in_R.get_unsafe(1, 2) +
97  tz * in_R.get_unsafe(2, 2);
98 
99  // 3x3 rotation part: transpose
100  out_R = in_R.adjoint();
101 
102  MRPT_END
103 }
104 //! \overload
105 template <class MATRIXLIKE>
106 inline void homogeneousMatrixInverse(MATRIXLIKE& M)
107 {
108  ASSERTDEB_(M.cols() == M.rows() && M.rows() == 4);
109  // translation:
110  const double tx = -M(0, 3);
111  const double ty = -M(1, 3);
112  const double tz = -M(2, 3);
113  M(0, 3) = tx * M(0, 0) + ty * M(1, 0) + tz * M(2, 0);
114  M(1, 3) = tx * M(0, 1) + ty * M(1, 1) + tz * M(2, 1);
115  M(2, 3) = tx * M(0, 2) + ty * M(1, 2) + tz * M(2, 2);
116  // 3x3 rotation part:
117  double t; // avoid std::swap() to avoid <algorithm> only for that.
118  t = M(1, 0);
119  M(1, 0) = M(0, 1);
120  M(0, 1) = t;
121  t = M(2, 0);
122  M(2, 0) = M(0, 2);
123  M(0, 2) = t;
124  t = M(1, 2);
125  M(1, 2) = M(2, 1);
126  M(2, 1) = t;
127 }
128 }
129 
130 
double Scalar
Definition: KmUtils.h:44
#define MRPT_START
Definition: exceptions.h:262
GLdouble GLdouble t
Definition: glext.h:3689
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
This base provides a set of functions for maths stuff.
GLbyte ty
Definition: glext.h:6092
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...
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
Definition: exceptions.h:205
#define MRPT_END
Definition: exceptions.h:266
GLbyte GLbyte tz
Definition: glext.h:6092



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