GSLAM  3.0.0
SIM3.h
1 // GSLAM - A general SLAM framework and benchmark
2 // Copyright 2018 PILAB Inc. All rights reserved.
3 // https://github.com/zdzhaoyong/GSLAM
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright notice,
11 // this list of conditions and the following disclaimer in the documentation
12 // and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors may be
14 // used to endorse or promote products derived from this software without
15 // specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 // Author: zd5945@126.com (Yong Zhao)
30 
31 #ifndef GSLAM_SIM3_H
32 #define GSLAM_SIM3_H
33 
34 #include "SE3.h"
35 
36 namespace GSLAM {
37 
38 /**
39 Represent a three-dimensional similarity transformation,7 degrees of freedom
40 a rotation: R (Here is represented by 4 paraments quaternion:Class SO3)--3 DoF
41 a translation: T (a 3 paraments vector)--3 DoF
42 a scale: s --1 DoF
43 It is the equivalent of a 4*4 Matrix:
44  | R*s T^T|
45  | 0 1 |
46 
47  This transformation is a member of the Lie group SIM3.
48  These can be parameterised with seven numbers (in the space of the Lie Algebra).
49  In this class, the first three parameters are a translation vector,
50  while the second three are a rotation vector,whose direction is the axis of rotation,
51  and length the amount of rotation (in radians), as for SO3.
52  The seventh parameter is the log of the scale of the transformation.
53 
54 **/
55 
56 template <typename Precision =double>
57 class SIM3_
58 {
59 public:
60  /// Default constructor. Initialises the the rotation to zero (the identity),
61  /// the scale to one and the translation to zero
62  inline SIM3_():my_scale(1){}
63 
64  SIM3_(const SO3_<Precision> &R,const Point3_<Precision> &T,const Precision& S=1.0)
65  :my_se3(R,T),my_scale(S){}
66 
67  SIM3_(const SE3_<Precision> &T,const Precision& S=1.0)
68  :my_se3(T),my_scale(S){}
69 
70  template<typename Scalar>
71  inline operator SIM3_<Scalar>()
72  {
73  return SIM3_<Scalar>(my_se3,my_scale);
74  }
75 
76  inline Point3_<Precision> get_translation()const
77  {
78  return my_se3.get_translation();
79  }
80 
81  inline Point3_<Precision>& get_translation()
82  {
83  return my_se3.get_translation();
84  }
85 
86  inline SO3_<Precision> get_rotation()const
87  {
88  return my_se3.get_rotation();
89  }
90  inline SO3_<Precision>& get_rotation()
91  {
92  return my_se3.get_rotation();
93  }
94 
95  inline SE3_<Precision> get_se3()const
96  {
97  return my_se3;
98  }
99  inline SE3_<Precision>& get_se3()
100  {
101  return my_se3;
102  }
103 
104  inline Precision& get_scale()
105  {
106  return my_scale;
107  }
108 
109  inline Precision get_scale()const
110  {
111  return my_scale;
112  }
113 
114  inline SIM3_<Precision> operator *(const SIM3_<Precision>& rhs) const
115  {
116  return SIM3_<Precision>(my_se3.get_rotation()*rhs.get_rotation(),
117  get_translation() + get_rotation()*(get_scale()*rhs.get_translation()),
118  get_scale()*rhs.get_scale());
119  }
120 
121  inline Point3_<Precision> operator *(const Point3_<Precision>& P) const
122  {
123  return get_rotation()*(P*my_scale)+my_se3.get_translation();
124  }
125 
126  inline SIM3_<Precision> inv()const
127  {
128  const SO3_<Precision> rinv= get_rotation().inv();
129  const Precision inv_scale= 1./my_scale;
130  return SIM3_(rinv,(-inv_scale)*(rinv*get_translation()),inv_scale);
131  }
132 
133  static SIM3_ exp(const Vector<Precision,7>& mu)
134  {
135  Point3_<Precision> p(mu[0],mu[1],mu[2]);
136  Point3_<Precision> r(mu[3],mu[4],mu[5]);
137  Precision sigma=mu[6];
138  Precision scale=::exp(sigma);
139  Precision theta_sq = r.dot(r);
140  Precision theta = sqrt(theta_sq);
141  Precision half_theta = static_cast<Precision>(0.5) * theta;
142 
143  Precision imag_factor;
144  Precision real_factor;
145 
146  if (theta < static_cast<Precision>(1e-10)) {
147  Precision theta_po4 = theta_sq * theta_sq;
148  imag_factor = static_cast<Precision>(0.5) -
149  static_cast<Precision>(1.0 / 48.0) * theta_sq +
150  static_cast<Precision>(1.0 / 3840.0) * theta_po4;
151  real_factor = static_cast<Precision>(1) -
152  static_cast<Precision>(0.5) * theta_sq +
153  static_cast<Precision>(1.0 / 384.0) * theta_po4;
154  } else {
155  Precision sin_half_theta = sin(half_theta);
156  imag_factor = sin_half_theta / theta;
157  real_factor = cos(half_theta);
158  }
159 
160  Precision A, B, C;
161  if (abs(sigma) < NEAR_ZERO) {
162  C = 1.;
163  if (abs(theta) < NEAR_ZERO) {
164  A = 0.5;
165  B = static_cast<Precision>(1. / 6.);
166  } else {
167  Precision theta_sq = theta * theta;
168  A = (1. - cos(theta)) / theta_sq;
169  B = (theta - sin(theta)) / (theta_sq * theta);
170  }
171  } else {
172  C = (scale - 1.) / sigma;
173  if (abs(theta) < NEAR_ZERO) {
174  Precision sigma_sq = sigma * sigma;
175  A = ((sigma - 1.) * scale + 1.) / sigma_sq;
176  B = ((0.5 * sigma_sq - sigma + 1.) * scale) / (sigma_sq * sigma);
177  } else {
178  Precision a = scale * sin(theta);
179  Precision b = scale * cos(theta);
180  Precision c = theta_sq + sigma * sigma;
181  A = (a * sigma + (1. - b) * theta) / (theta * c);
182  B = (C - ((b - 1.) * sigma + a * theta) / (c)) * 1. / (theta_sq);
183  }
184  }
185 
186  SO3_<Precision> R( imag_factor * r.x, imag_factor * r.y,imag_factor * r.z,real_factor);
187  auto rcp=r.cross(p);
188  auto t= A*rcp+B*r.cross(rcp)+C*p;
189  return SIM3_<Precision>(R,t,scale);
190  }
191 
192  Vector<Precision,7> log() const{
193  Vector<Precision,7> result;
194  const auto& l=get_rotation();
195  const auto& t=get_translation();
196  const auto& scale=my_scale;
197  const Precision squared_w = l.w*l.w;
198  const Precision n = sqrt(l.x*l.x+l.y*l.y+l.z*l.z);
199  const Precision sigma= ::log(scale);
200 
201  Precision A_inv;
202 
203  if (n < NEAR_ZERO)
204  {
205  //If n is too small
206  A_inv = 2./l.w - 2.*(1.0-squared_w)/(l.w*squared_w);
207  }
208  else
209  {
210  if (fabs(l.w)<NEAR_ZERO)
211  {
212  //If w is too small
213  if (l.w>0)
214  {
215  A_inv = M_PI/n;
216  }
217  else
218  {
219  A_inv = -M_PI/n;
220  }
221  }
222  else
223  A_inv = 2*atan(n/l.w)/n;
224  }
225 
226  Precision theta=A_inv*n;
227  Point3_<Precision> r(l.x*A_inv,l.y*A_inv,l.z*A_inv);
228 
229  const Precision scale_sq = scale * scale;
230  const Precision theta_sq = theta * theta;
231  const Precision sin_theta = sin(theta);
232  const Precision cos_theta = cos(theta);
233 
234  Precision a, b, c;
235  if (abs(sigma * sigma) < NEAR_ZERO) {
236  c = 1. - 0.5 * sigma;
237  a = -0.5;
238  if (abs(theta_sq) < NEAR_ZERO) {
239  b = Precision(1. / 12.);
240  } else {
241  b = (theta * sin_theta + 2. * cos_theta - 2.) /
242  (2. * theta_sq * (cos_theta - 1.));
243  }
244  } else {
245  const Precision scale_cu = scale_sq * scale;
246  c = sigma / (scale - 1.);
247  if (abs(theta_sq) < NEAR_ZERO) {
248  a = (-sigma * scale + scale - 1.) / ((scale - 1.) * (scale - 1.));
249  b = (scale_sq * sigma - 2. * scale_sq + scale * sigma + 2. * scale) /
250  (2. * scale_cu - 6. * scale_sq + 6. * scale - 2.);
251  } else {
252  const Precision s_sin_theta = scale * sin_theta;
253  const Precision s_cos_theta = scale * cos_theta;
254  a = (theta * s_cos_theta - theta - sigma * s_sin_theta) /
255  (theta * (scale_sq - 2. * s_cos_theta + 1.));
256  b = -scale *
257  (theta * s_sin_theta - theta * sin_theta + sigma * s_cos_theta -
258  scale * sigma + sigma * cos_theta - sigma) /
259  (theta_sq * (scale_cu - 2. * scale * s_cos_theta - scale_sq +
260  2. * s_cos_theta + scale - 1.));
261  }
262  }
263 
264  auto rcrosst=r.cross(t);
265  Point3_<Precision> p=a*rcrosst+b*r.cross(rcrosst)+c*t;
266  result.set(Vector3<Precision>(p.x,p.y,p.z),0,0);
267  result.set(Vector3<Precision>(r.x,r.y,r.z),3,0);
268  result[6]=sigma;
269  return result;
270  }
271 
272 #ifdef SOPHUS_SIM3_HPP
273  SIM3_(const Sophus::Sim3Group<Precision>& sim3)
274  {
275  Eigen::Quaternion<Precision> quat(sim3.rxso3().quaternion().coeffs());
276  quat.normalize();
277  get_rotation()=Sophus::SO3Group<Precision>(quat);
278  get_translation()=*(Point3_<Precision>*)sim3.translation().data();
279  get_scale()=sim3.scale();
280  }
281  operator Sophus::Sim3Group<Precision>()
282  {
283  auto translation=get_translation();
284  return Sophus::Sim3Group<Precision>(Sophus::RxSO3Group<Precision>(std::sqrt(get_scale()),
285  get_rotation()),
286  Eigen::Map<Eigen::Matrix<Precision, 3, 1>>(&translation.x));
287  }
288 #endif
289 protected:
290  SE3_<Precision> my_se3;
291  Precision my_scale;
292 };
293 
294 typedef SIM3_<double> SIM3d;
295 typedef SIM3_<float> SIM3f;
296 typedef SIM3d SIM3;
297 
298 } // end of namespace GSLAM
299 
300 
301 #endif // SIM3_H
Definition: Matrix.h:697
Definition: Point.h:162
3D rotation represented by the quaternion.
Definition: SO3.h:131
Definition: Camera.h:45
SIM3_()
Default constructor. Initialises the the rotation to zero (the identity), the scale to one and the tr...
Definition: SIM3.h:62
Represent a three-dimensional similarity transformation,7 degrees of freedom a rotation: R (Here is r...
Definition: SIM3.h:57
Represent a three-dimensional Euclidean transformation (a rotation and a translation).
Definition: SE3.h:69
Definition: Matrix.h:548