TooN
sim2.h
1 // -*- c++ -*-
2 
3 // Copyright (C) 2011 Tom Drummond (twd20@cam.ac.uk),
4 // Ed Rosten (er258@cam.ac.uk), Gerhard Reitmayr (gr281@cam.ac.uk)
5 
6 //All rights reserved.
7 //
8 //Redistribution and use in source and binary forms, with or without
9 //modification, are permitted provided that the following conditions
10 //are met:
11 //1. Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //2. Redistributions in binary form must reproduce the above copyright
14 // notice, this list of conditions and the following disclaimer in the
15 // documentation and/or other materials provided with the distribution.
16 //
17 //THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER 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 AUTHOR OR OTHER 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 /* This code mostly made by copying from sim3.h !! */
30 
31 #ifndef TOON_INCLUDE_SIM2_H
32 #define TOON_INCLUDE_SIM2_H
33 
34 #include <TooN/se2.h>
35 #include <TooN/sim3.h>
36 
37 namespace TooN {
38 
49 template <typename Precision = DefaultPrecision>
50 class SIM2 {
51 public:
53  SIM2() : my_scale(1) {}
54  template <class A> SIM2(const SO2<Precision>& R, const Vector<2,Precision,A>& T, const Precision s) : my_se2(R,T), my_scale(s) {}
55  template <int S, class P, class A> SIM2(const Vector<S, P, A> & v) { *this = exp(v); }
56 
58  SO2<Precision> & get_rotation(){return my_se2.get_rotation();}
60  const SO2<Precision> & get_rotation() const {return my_se2.get_rotation();}
62  Vector<2, Precision> & get_translation() {return my_se2.get_translation();}
64  const Vector<2, Precision> & get_translation() const {return my_se2.get_translation();}
65 
67  Precision & get_scale() {return my_scale;}
69  const Precision & get_scale() const {return my_scale;}
70 
74  template <int S, typename P, typename A>
75  static inline SIM2 exp(const Vector<S,P, A>& vect);
76 
79  static inline Vector<4, Precision> ln(const SIM2& se2);
81  Vector<4, Precision> ln() const { return SIM2::ln(*this); }
82 
84  SIM2 inverse() const {
85  const SO2<Precision> & rinv = get_rotation().inverse();
86  const Precision inv_scale = 1/get_scale();
87  return SIM2(rinv, -(rinv*(inv_scale*get_translation())), inv_scale);
88  };
89 
92  template <typename P>
95  }
96 
99  inline SIM2& operator *=(const SIM2& rhs) {
100  *this = *this * rhs;
101  return *this;
102  }
103 
110  static inline Matrix<3,3, Precision> generator(int i) {
111  Matrix<3,3,Precision> result(Zeros);
112  switch(i){
113  case 0:
114  case 1:
115  result(i,2) = 1;
116  break;
117  case 2:
118  result(0,1) = -1;
119  result(1,0) = 1;
120  break;
121  case 3:
122  result(0,0) = 1;
123  result(1,1) = 1;
124  break;
125  }
126  return result;
127  }
128 
131  template<typename Accessor>
133  Vector<4, Precision> result;
134  result[2] = vect[2];
135  result.template slice<0,2>() = get_rotation() * vect.template slice<0,2>();
136  result[0] += vect[2] * get_translation()[1];
137  result[1] -= vect[2] * get_translation()[0];
138  return result;
139  }
140 
141  template <typename Accessor>
143  Matrix<4,4,Precision> result;
144  for(int i=0; i<4; ++i)
145  result.T()[i] = adjoint(M.T()[i]);
146  for(int i=0; i<4; ++i)
147  result[i] = adjoint(result[i]);
148  return result;
149  }
150 
151 private:
152  SE2<Precision> my_se2;
153  Precision my_scale;
154 };
155 
158 template <class Precision>
159 inline std::ostream& operator<<(std::ostream& os, const SIM2<Precision> & rhs){
160  std::streamsize fw = os.width();
161  for(int i=0; i<2; i++){
162  os.width(fw);
163  os << rhs.get_rotation().get_matrix()[i] * rhs.get_scale();
164  os.width(fw);
165  os << rhs.get_translation()[i] << '\n';
166  }
167  return os;
168 }
169 
172 template <class Precision>
173 inline std::istream& operator>>(std::istream& is, SIM2<Precision>& rhs){
174  for(int i=0; i<2; i++)
175  is >> rhs.get_rotation().my_matrix[i].ref() >> rhs.get_translation()[i];
176  rhs.get_scale() = (norm(rhs.get_rotation().my_matrix[0]) + norm(rhs.get_rotation().my_matrix[1]))/2;
177  rhs.get_rotation().coerce();
178  return is;
179 }
180 
181 
183 // operator * //
184 // SIM2 * Vector //
186 
187 namespace Internal {
188 template<int S, typename P, typename PV, typename A>
189 struct SIM2VMult;
190 }
191 
192 template<int S, typename P, typename PV, typename A>
193 struct Operator<Internal::SIM2VMult<S,P,PV,A> > {
194  const SIM2<P> & lhs;
195  const Vector<S,PV,A> & rhs;
196 
197  Operator(const SIM2<P> & l, const Vector<S,PV,A> & r ) : lhs(l), rhs(r) {}
198 
199  template <int S0, typename P0, typename A0>
200  void eval(Vector<S0, P0, A0> & res ) const {
201  SizeMismatch<3,S>::test(3, rhs.size());
202  res.template slice<0,2>()=lhs.get_rotation()*(lhs.get_scale()*rhs.template slice<0,2>());
203  res.template slice<0,2>()+=lhs.get_translation() * rhs[2];
204  res[2] = rhs[2];
205  }
206  int size() const { return 3; }
207 };
208 
211 template<int S, typename P, typename PV, typename A>
214 }
215 
218 template <typename P, typename PV, typename A>
220  return lhs.get_translation() + lhs.get_rotation() * (lhs.get_scale() * rhs);
221 }
222 
224 // operator * //
225 // Vector * SIM2 //
227 
228 namespace Internal {
229 template<int S, typename P, typename PV, typename A>
230 struct VSIM2Mult;
231 }
232 
233 template<int S, typename P, typename PV, typename A>
234 struct Operator<Internal::VSIM2Mult<S,P,PV,A> > {
235  const Vector<S,PV,A> & lhs;
236  const SIM2<P> & rhs;
237 
238  Operator(const Vector<S,PV,A> & l, const SIM2<P> & r ) : lhs(l), rhs(r) {}
239 
240  template <int S0, typename P0, typename A0>
241  void eval(Vector<S0, P0, A0> & res ) const {
242  SizeMismatch<3,S>::test(3, lhs.size());
243  res.template slice<0,2>() = (lhs.template slice<0,2>()* rhs.get_scale())*rhs.get_rotation();
244  res[2] = lhs[2];
245  res[2] += lhs.template slice<0,2>() * rhs.get_translation();
246  }
247  int size() const { return 3; }
248 };
249 
252 template<int S, typename P, typename PV, typename A>
255 }
256 
258 // operator * //
259 // SIM2 * Matrix //
261 
262 namespace Internal {
263 template <int R, int C, typename PM, typename A, typename P>
264 struct SIM2MMult;
265 }
266 
267 template<int R, int Cols, typename PM, typename A, typename P>
268 struct Operator<Internal::SIM2MMult<R, Cols, PM, A, P> > {
269  const SIM2<P> & lhs;
270  const Matrix<R,Cols,PM,A> & rhs;
271 
272  Operator(const SIM2<P> & l, const Matrix<R,Cols,PM,A> & r ) : lhs(l), rhs(r) {}
273 
274  template <int R0, int C0, typename P0, typename A0>
275  void eval(Matrix<R0, C0, P0, A0> & res ) const {
276  SizeMismatch<3,R>::test(3, rhs.num_rows());
277  for(int i=0; i<rhs.num_cols(); ++i)
278  res.T()[i] = lhs * rhs.T()[i];
279  }
280  int num_cols() const { return rhs.num_cols(); }
281  int num_rows() const { return 3; }
282 };
283 
286 template <int R, int Cols, typename PM, typename A, typename P>
289 }
290 
292 // operator * //
293 // Matrix * SIM2 //
295 
296 namespace Internal {
297 template <int Rows, int C, typename PM, typename A, typename P>
298 struct MSIM2Mult;
299 }
300 
301 template<int Rows, int C, typename PM, typename A, typename P>
302 struct Operator<Internal::MSIM2Mult<Rows, C, PM, A, P> > {
303  const Matrix<Rows,C,PM,A> & lhs;
304  const SIM2<P> & rhs;
305 
306  Operator( const Matrix<Rows,C,PM,A> & l, const SIM2<P> & r ) : lhs(l), rhs(r) {}
307 
308  template <int R0, int C0, typename P0, typename A0>
309  void eval(Matrix<R0, C0, P0, A0> & res ) const {
310  SizeMismatch<3, C>::test(3, lhs.num_cols());
311  for(int i=0; i<lhs.num_rows(); ++i)
312  res[i] = lhs[i] * rhs;
313  }
314  int num_cols() const { return 3; }
315  int num_rows() const { return lhs.num_rows(); }
316 };
317 
320 template <int Rows, int C, typename PM, typename A, typename P>
323 }
324 
325 template <typename Precision>
326 template <int S, typename PV, typename Accessor>
328  SizeMismatch<4,S>::test(4, mu.size());
329 
330  static const Precision one_6th = 1.0/6.0;
331  static const Precision one_20th = 1.0/20.0;
332 
333  using std::exp;
334 
335  SIM2<Precision> result;
336 
337  // rotation
338  const Precision theta = mu[2];
339  result.get_rotation() = SO2<Precision>::exp(theta);
340 
341  // scale
342  result.get_scale() = exp(mu[3]);
343 
344  // translation
345  const Vector<3, Precision> coeff = Internal::compute_rodrigues_coefficients_sim3(mu[3], theta);
346  const Vector<2, Precision> cross = makeVector( -theta * mu[1], theta * mu[0]);
347  result.get_translation() = coeff[2] * mu.template slice<0,2>() + TooN::operator*(coeff[1], cross);
348 
349  return result;
350 }
351 
352 template <typename Precision>
354  using std::log;
355 
356  Vector<4, Precision> result;
357 
358  // rotation
359  const Precision theta = sim2.get_rotation().ln();
360  result[2] = theta;
361 
362  // scale
363  result[3] = log(sim2.get_scale());
364 
365  // translation
366  const Vector<3, Precision> coeff = Internal::compute_rodrigues_coefficients_sim3(result[3], theta);
367  Matrix<2,2, Precision> cross = Zeros; cross(0,1) = -theta; cross(1,0) = theta;
368  const Matrix<2,2, Precision> W = coeff[2] * Identity + coeff[1] * cross;
369  result.template slice<0,2>() = gaussian_elimination(W, sim2.get_translation());
370 
371  return result;
372 }
373 
374 #if 0
375 template <typename Precision>
379 inline SE2<Precision> operator*(const SO2<Precision> & lhs, const SE2<Precision>& rhs){
380  return SE2<Precision>( lhs*rhs.get_rotation(), lhs*rhs.get_translation());
381 }
382 #endif
383 
384 }
385 #endif
Matrix< R, C, P > exp(const Matrix< R, C, P, B > &m)
computes the matrix exponential of a matrix m by scaling m by 1/(powers of 2), using Taylor series an...
Definition: helpers.h:330
SO2< Precision > & get_rotation()
Returns the rotation part of the transformation as a SO2.
Definition: sim2.h:58
Vector< 4, Precision > adjoint(const Vector< 4, Precision, Accessor > &vect) const
transfers a vector in the Lie algebra, from one coord frame to another so that exp(adjoint(vect)) = (...
Definition: sim2.h:132
SIM2 inverse() const
compute the inverse of the transformation
Definition: sim2.h:84
Vector< 3, typename Internal::MultiplyType< PV, P >::type > operator*(const Vector< S, PV, A > &lhs, const SIM2< P > &rhs)
Left-multiply with a Vector<3>
Definition: sim2.h:253
Matrix< R, C, P > log(const Matrix< R, C, P, B > &m)
computes the matrix logarithm of a matrix m using the inverse scaling and squaring method...
Definition: helpers.h:373
Precision norm(const Vector< Size, Precision, Base > &v)
Compute the norm of v.
Definition: helpers.h:97
Pretty generic SFINAE introspection generator.
Definition: vec_test.cc:21
A vector.
Definition: vector.hh:126
Vector< 3, typename Internal::MultiplyType< P, PV >::type > operator*(const SIM2< P > &lhs, const Vector< S, PV, A > &rhs)
Right-multiply with a Vector<3>
Definition: sim2.h:212
SIM2()
Default constructor. Initialises the the rotation to zero (the identity), the scale factor to one and...
Definition: sim2.h:53
std::istream & operator>>(std::istream &is, SIM2< Precision > &rhs)
Read an SIM2 from a stream.
Definition: sim2.h:173
Definition: sim2.h:189
Class to represent a two-dimensional rotation matrix.
Definition: so2.h:37
Vector< 2, Precision > & get_translation()
Returns the translation part of the transformation as a Vector.
Definition: sim2.h:62
static SO2 exp(const Precision &d)
Exponentiate an angle in the Lie algebra to generate a new SO2.
Definition: so2.h:89
Precision & get_scale()
Returns the scale factor of the transformation.
Definition: sim2.h:67
Definition: operators.hh:119
SIM2 & operator*=(const SIM2 &rhs)
Self right-multiply by another SIM2 (concatenate the two transformations)
Definition: sim2.h:99
const SO2< Precision > & get_rotation() const
Definition: sim2.h:60
Represent a two-dimensional Similarity transformation (a rotation, a uniform scale and a translation)...
Definition: sim2.h:50
static Matrix< 3, 3, Precision > generator(int i)
returns the generators for the Lie group.
Definition: sim2.h:110
Definition: sim2.h:264
SIM2< typename Internal::MultiplyType< Precision, P >::type > operator*(const SIM2< P > &rhs) const
Right-multiply by another SIM2 (concatenate the two transformations)
Definition: sim2.h:93
const Precision & get_scale() const
Definition: sim2.h:69
Definition: size_mismatch.hh:103
static SIM2 exp(const Vector< S, P, A > &vect)
Exponentiate a Vector in the Lie Algebra to generate a new SIM2.
Vector< 2, Precision > & get_translation()
Returns the translation part of the transformation as a Vector.
Definition: se2.h:62
const Vector< 2, Precision > & get_translation() const
Definition: sim2.h:64
Represent a two-dimensional Euclidean transformation (a rotation and a translation).
Definition: se2.h:50
Vector< N, Precision > gaussian_elimination(Matrix< N, N, Precision > A, Vector< N, Precision > b)
Return the solution for , given and .
Definition: gaussian_elimination.h:43
Definition: sim2.h:298
Vector< 4, Precision > ln() const
Definition: sim2.h:81
SO2< Precision > & get_rotation()
Returns the rotation part of the transformation as a SO2.
Definition: se2.h:58
Matrix< 3, Cols, typename Internal::MultiplyType< P, PM >::type > operator*(const SIM2< P > &lhs, const Matrix< R, Cols, PM, A > &rhs)
Right-multiply with a Matrix<3>
Definition: sim2.h:287
Definition: sim2.h:230
Vector< 2, typename Internal::MultiplyType< P, PV >::type > operator*(const SIM2< P > &lhs, const Vector< 2, PV, A > &rhs)
Right-multiply with a Vector<2> (special case, extended to be a homogeneous vector) ...
Definition: sim2.h:219
Matrix< Rows, 3, typename Internal::MultiplyType< PM, P >::type > operator*(const Matrix< Rows, C, PM, A > &lhs, const SIM2< P > &rhs)
Left-multiply with a Matrix<3>
Definition: sim2.h:321