toon-members
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Toon-members] TooN so2.h so3.h test/SXX_test.cc sim2.h sim3.h


From: Gerhard Reitmayr
Subject: [Toon-members] TooN so2.h so3.h test/SXX_test.cc sim2.h sim3.h
Date: Wed, 29 Jun 2011 20:20:01 +0000

CVSROOT:        /cvsroot/toon
Module name:    TooN
Changes by:     Gerhard Reitmayr <gerhard>      11/06/29 20:20:00

Modified files:
        .              : so2.h so3.h 
        test           : SXX_test.cc 
Added files:
        .              : sim2.h sim3.h 

Log message:
        added 2D and 3D similarity group implementations

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/TooN/so2.h?cvsroot=toon&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/TooN/so3.h?cvsroot=toon&r1=1.49&r2=1.50
http://cvs.savannah.gnu.org/viewcvs/TooN/sim2.h?cvsroot=toon&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/TooN/sim3.h?cvsroot=toon&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/TooN/test/SXX_test.cc?cvsroot=toon&r1=1.10&r2=1.11

Patches:
Index: so2.h
===================================================================
RCS file: /cvsroot/toon/TooN/so2.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- so2.h       7 Apr 2011 23:17:02 -0000       1.13
+++ so2.h       29 Jun 2011 20:20:00 -0000      1.14
@@ -36,11 +36,13 @@
 
 namespace TooN {
 
-template<typename Precision> class SO2;
+template <typename Precision> class SO2;
 template <typename Precision> class SE2;
+template <typename Precision> class SIM2;
 
 template<typename Precision> inline std::istream & operator>>(std::istream &, 
SO2<Precision> & );
 template<typename Precision> inline std::istream & operator>>(std::istream &, 
SE2<Precision> & );
+template<typename Precision> inline std::istream & operator>>(std::istream &, 
SIM2<Precision> & );
 
 /// Class to represent a two-dimensional rotation matrix. Two-dimensional 
rotation
 /// matrices are members of the Special Orthogonal Lie group SO2. This group 
can be parameterised with
@@ -50,6 +52,7 @@
 class SO2 {
        friend std::istream& operator>> <Precision>(std::istream&, SO2& );
        friend std::istream& operator>> <Precision>(std::istream&, 
SE2<Precision>& );
+       friend std::istream& operator>> <Precision>(std::istream&, 
SIM2<Precision>& );
 
 public:
        /// Default constructor. Initialises the matrix to the identity (no 
rotation)

Index: so3.h
===================================================================
RCS file: /cvsroot/toon/TooN/so3.h,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -b -r1.49 -r1.50
--- so3.h       7 Apr 2011 23:17:02 -0000       1.49
+++ so3.h       29 Jun 2011 20:20:00 -0000      1.50
@@ -38,9 +38,11 @@
 
 template <typename Precision> class SO3;
 template <typename Precision> class SE3;
+template <typename Precision> class SIM3;
 
 template<class Precision> inline std::istream & operator>>(std::istream &, 
SO3<Precision> & );
 template<class Precision> inline std::istream & operator>>(std::istream &, 
SE3<Precision> & );
+template<class Precision> inline std::istream & operator>>(std::istream &, 
SIM3<Precision> & );
 
 /// Class to represent a three-dimensional rotation matrix. Three-dimensional 
rotation
 /// matrices are members of the Special Orthogonal Lie group SO3. This group 
can be parameterised
@@ -54,7 +56,9 @@
 public:
        friend std::istream& operator>> <Precision> (std::istream& is, 
SO3<Precision> & rhs);
        friend std::istream& operator>> <Precision> (std::istream& is, 
SE3<Precision> & rhs);
+       friend std::istream& operator>> <Precision> (std::istream& is, 
SIM3<Precision> & rhs);
        friend class SE3<Precision>;
+       friend class SIM3<Precision>;
        
        /// Default constructor. Initialises the matrix to the identity (no 
rotation)
        SO3() : my_matrix(Identity) {}

Index: test/SXX_test.cc
===================================================================
RCS file: /cvsroot/toon/TooN/test/SXX_test.cc,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- test/SXX_test.cc    1 Feb 2010 17:33:18 -0000       1.10
+++ test/SXX_test.cc    29 Jun 2011 20:20:00 -0000      1.11
@@ -7,6 +7,8 @@
 #include <TooN/se2.h>
 #include <TooN/so3.h>
 #include <TooN/se3.h>
+#include <TooN/sim2.h>
+#include <TooN/sim3.h>
 
 void test_so2(){
     cout << "---------------SO2 Tests---------------\n";
@@ -246,6 +248,158 @@
     cout << r << endl;
 }
 
+void test_sim3(){
+    cout << "---------------SIM3 Tests---------------\n";
+    
+    TooN::SIM3<> r1;
+    cout << "default constructor\n";
+    cout << r1 << endl;
+    cout << "default constructor <int>\n";
+    TooN::SIM3<int> r2;
+    cout << r2 << endl;
+    TooN::SIM3<> r(TooN::makeVector(0.1, 0.1, 0.1, 0.2, -0.2, 0.2, 0.5));
+    cout << "constructor\n";
+    cout << r << endl;
+    cout << "generator 0,1,2,3,4,5,6\n";
+    cout << TooN::SIM3<>::generator(0) ;
+    cout << TooN::SIM3<>::generator(1) ;
+    cout << TooN::SIM3<>::generator(2) << endl;
+    cout << TooN::SIM3<>::generator(3) ;
+    cout << TooN::SIM3<>::generator(4) ;
+    cout << TooN::SIM3<>::generator(5) << endl;
+    cout << TooN::SIM3<>::generator(6) << endl;
+    cout << "ln()\n";
+    cout << r.ln() << endl;
+    cout << "inverse\n";
+    cout << r.inverse() << endl;
+    cout << "inverse.ln()\n";
+    cout << r.inverse().ln() << endl;
+    cout << "times\n";
+    cout << r * r.inverse() << endl;
+    cout << (r *= r.inverse()) << endl;
+    r = TooN::SIM3<>::exp(TooN::makeVector(0.1, 0.1, 0.1, 0.2, -0.2, 0.2, 
0.5));
+
+    TooN::Vector<4> t = TooN::makeVector(0,1,2,3);
+    cout << "right and left multiply with vector " << t << "\n";
+    cout << r * t << endl;
+    cout << t * r << endl;
+    TooN::Vector<3> t3 = TooN::makeVector(0,1,2);
+    cout << "right with a 3 vector " << t3 << "\n";
+    cout << r * t3 << endl;
+
+    TooN::Matrix<4> l = TooN::Identity;
+    cout << "right and left multiply with matrix\n" << l << "\n";
+    cout << r * l << endl;
+    cout << l * r << endl;
+    TooN::Matrix<4,6> l2(TooN::Zeros);
+    l2[0] = TooN::makeVector(0,1,2,3,4,5);
+    cout << "right with rectangular matrix\n";
+    cout << r * l2 << endl;
+    cout << l2.T() * r << endl;
+
+#if 0    
+    TooN::SO3<> rot(TooN::makeVector(-0.2, 0.2, -0.2));
+    cout << "mult with SO3\n";
+    cout << rot * r << endl;
+    
+    TooN::Vector<6> a = TooN::makeVector(0,1,2,0.1, 0.2, 0.3);
+    cout << "adjoint with a " << a << "\n";
+    cout << r.adjoint(a) << endl;
+    cout << "0 0 0 0 0 0 = " << r.adjoint(a) - (r * TooN::SE3<>(a) * 
r.inverse()).ln() << endl;
+    cout << "trinvadjoint with a " << a << "\n";
+    cout << r.trinvadjoint(a) << endl;
+    cout << "0 = " << r.trinvadjoint(a) * r.adjoint(a) - a * a << endl; 
+
+    TooN::Matrix<6> ma(TooN::Identity);
+    ma[0] = TooN::makeVector(0.1, 0.2, 0.1, 0.2, 0.1, 0.3);
+    ma = ma.T() * ma;
+    cout << "adjoint with ma\n" << ma << "\n";
+    cout << r.adjoint(ma) << endl;
+    cout << "trinvadjoint with ma\n";
+    cout << r.trinvadjoint(ma) << endl;
+#endif
+
+    cout << "read from istream\n";
+    istringstream is("0 -1 0 1 1 0 0 2 0 0 1 3");
+    is >> r;
+    cout << r << endl;
+    cout << r.get_rotation() << "\n" << r.get_translation() << "\n" << 
r.get_scale() << endl;
+}
+
+void test_sim2(){
+    cout << "---------------SIM2 Tests---------------\n";
+    
+    TooN::SIM2<> r1;
+    cout << "default constructor\n";
+    cout << r1 << endl;
+    cout << "default constructor <int>\n";
+    TooN::SIM2<int> r2;
+    cout << r2 << endl;
+    TooN::SIM2<> r(TooN::makeVector(0.1, 0.1, 0.1, 0.2));
+    cout << "constructor\n";
+    cout << r << endl;
+    cout << "generator 0,1,2,3\n";
+    cout << TooN::SIM2<>::generator(0);
+    cout << TooN::SIM2<>::generator(1);
+    cout << TooN::SIM2<>::generator(2) << endl;
+    cout << TooN::SIM2<>::generator(3) << endl;
+    cout << "ln()\n";
+    cout << r.ln() << endl;
+    cout << "inverse\n";
+    cout << r.inverse() << endl;
+    cout << "inverse.ln()\n";
+    cout << r.inverse().ln() << endl;
+    cout << "times\n";
+    cout << r * r.inverse() << endl;
+    cout << (r *= r.inverse()) << endl;
+    r = TooN::SIM2<>::exp(TooN::makeVector(0.1, 0.1, 0.1, 0.2));
+
+    TooN::Vector<3> t = TooN::makeVector(0,1,2);
+    cout << "right and left multiply with vector " << t << "\n";
+    cout << r * t << endl;
+    cout << t * r << endl;
+    TooN::Vector<2> t3 = TooN::makeVector(0,1);
+    cout << "right with a 2 vector " << t3 << "\n";
+    cout << r * t3 << endl;
+
+    TooN::Matrix<3> l = TooN::Identity;
+    cout << "right and left multiply with matrix\n" << l << "\n";
+    cout << r * l << endl;
+    cout << l * r << endl;
+    TooN::Matrix<3,6> l2(TooN::Zeros);
+    l2[0] = TooN::makeVector(0,1,2,3,4,5);
+    cout << "right with rectangular matrix\n" << l2 << "\n";
+    cout << r * l2 << endl;
+    cout << l2.T() * r << endl;
+
+#if 0    
+    TooN::SO3<> rot(TooN::makeVector(-0.2, 0.2, -0.2));
+    cout << "mult with SO3\n";
+    cout << rot * r << endl;
+    
+    TooN::Vector<6> a = TooN::makeVector(0,1,2,0.1, 0.2, 0.3);
+    cout << "adjoint with a " << a << "\n";
+    cout << r.adjoint(a) << endl;
+    cout << "0 0 0 0 0 0 = " << r.adjoint(a) - (r * TooN::SE3<>(a) * 
r.inverse()).ln() << endl;
+    cout << "trinvadjoint with a " << a << "\n";
+    cout << r.trinvadjoint(a) << endl;
+    cout << "0 = " << r.trinvadjoint(a) * r.adjoint(a) - a * a << endl; 
+
+    TooN::Matrix<6> ma(TooN::Identity);
+    ma[0] = TooN::makeVector(0.1, 0.2, 0.1, 0.2, 0.1, 0.3);
+    ma = ma.T() * ma;
+    cout << "adjoint with ma\n" << ma << "\n";
+    cout << r.adjoint(ma) << endl;
+    cout << "trinvadjoint with ma\n";
+    cout << r.trinvadjoint(ma) << endl;
+#endif
+
+    cout << "read from istream\n";
+    istringstream is("0 -1 0 1 1 0");
+    is >> r;
+    cout << r << endl;
+    cout << r.get_rotation() << "\n" << r.get_translation() << "\n" << 
r.get_scale() << endl;
+}
 
 void test_se2_exp(){
     cout << "------------------SE2 check------------------\n";
@@ -261,12 +415,17 @@
 
 int main(int, char* *){
  
+ #if 0
     test_so2();
     test_so3();
     test_se2();
     test_se3();
+    test_sim3();
  
     test_se2_exp();
+#endif
+
+    test_sim2();
  
     return 0;
 }

Index: sim2.h
===================================================================
RCS file: sim2.h
diff -N sim2.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sim2.h      29 Jun 2011 20:20:00 -0000      1.1
@@ -0,0 +1,406 @@
+// -*- c++ -*-
+
+// Copyright (C) 2011 Tom Drummond (address@hidden),
+// Ed Rosten (address@hidden), Gerhard Reitmayr (address@hidden)
+//
+// This file is part of the TooN Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/* This code mostly made by copying from sim3.h !! */
+
+#ifndef TOON_INCLUDE_SIM2_H
+#define TOON_INCLUDE_SIM2_H
+
+#include <TooN/se2.h>
+
+namespace TooN {
+
+/// Represent a two-dimensional Similarity transformation (a rotation, a 
uniform scale and a translation). 
+/// This can be represented by a \f$2\times 3\f$ matrix operating on a 
homogeneous co-ordinate, 
+/// so that a vector \f$\underline{x}\f$ is transformed to a new location 
\f$\underline{x}'\f$
+/// by
+/// \f[\begin{aligned}\underline{x}' &= E\times\underline{x}\\ 
\begin{bmatrix}x'\\y'\end{bmatrix} &= \begin{pmatrix}r_{11} & r_{12} & 
t_1\\r_{21} & r_{22} & 
t_2\end{pmatrix}\begin{bmatrix}x\\y\\1\end{bmatrix}\end{aligned}\f]
+/// 
+/// This transformation is a member of the Lie group SIM2. These can be 
parameterised with
+/// four numbers (in the space of the Lie Algebra). In this class, the first 
two parameters are a
+/// translation vector while the third is the amount of rotation in the plane 
as for SO2. The forth is the logarithm of the scale factor.
+/// @ingroup gTransforms
+template <typename Precision = DefaultPrecision>
+class SIM2 {
+public:
+       /// Default constructor. Initialises the the rotation to zero (the 
identity), the scale factor to one and the translation to zero
+       SIM2() : my_scale(1) {}
+       template <class A> SIM2(const SO2<Precision>& R, const 
Vector<2,Precision,A>& T, const Precision s) : my_se2(R,T), my_scale(s) {}
+       template <int S, class P, class A> SIM2(const Vector<S, P, A> & v) { 
*this = exp(v); }
+
+       /// Returns the rotation part of the transformation as a SO2
+       SO2<Precision> & get_rotation(){return my_se2.get_rotation();}
+       /// @overload
+       const SO2<Precision> & get_rotation() const {return 
my_se2.get_rotation();}
+       /// Returns the translation part of the transformation as a Vector
+       Vector<2, Precision> & get_translation() {return 
my_se2.get_translation();}
+       /// @overload
+       const Vector<2, Precision> & get_translation() const {return 
my_se2.get_translation();}
+
+       /// Returns the scale factor of the transformation
+       Precision & get_scale() {return my_scale;}
+       /// @overload
+       const Precision & get_scale() const {return my_scale;}
+
+       /// Exponentiate a Vector in the Lie Algebra to generate a new SIM2.
+       /// See the Detailed Description for details of this vector.
+       /// @param vect The Vector to exponentiate
+       template <int S, typename P, typename A>
+       static inline SIM2 exp(const Vector<S,P, A>& vect);
+       
+       /// Take the logarithm of the matrix, generating the corresponding 
vector in the Lie Algebra.
+       /// See the Detailed Description for details of this vector.
+       static inline Vector<4, Precision> ln(const SIM2& se2);
+       /// @overload
+       Vector<4, Precision> ln() const { return SIM2::ln(*this); }
+
+       /// compute the inverse of the transformation
+       SIM2 inverse() const {
+               const SO2<Precision> & rinv = get_rotation().inverse();
+               const Precision inv_scale = 1/get_scale();
+               return SIM2(rinv, -(rinv*(inv_scale*get_translation())), 
inv_scale);
+       };
+
+       /// Right-multiply by another SIM2 (concatenate the two transformations)
+       /// @param rhs The multipier
+       template <typename P>
+       SIM2<typename Internal::MultiplyType<Precision,P>::type> operator 
*(const SIM2<P>& rhs) const { 
+               return SIM2<typename 
Internal::MultiplyType<Precision,P>::type>(get_rotation()*rhs.get_rotation(), 
get_translation() + get_rotation() * (get_scale()*rhs.get_translation()), 
get_scale() * rhs.get_scale());
+       }
+
+       /// Self right-multiply by another SIM2 (concatenate the two 
transformations)
+       /// @param rhs The multipier
+       inline SIM2& operator *=(const SIM2& rhs) {
+               *this = *this * rhs; 
+               return *this; 
+       }
+
+       /// returns the generators for the Lie group. These are a set of 
matrices that
+       /// form a basis for the vector space of the Lie algebra.
+       /// - 0 is translation in x
+       /// - 1 is translation in y
+       /// - 2 is rotation in the plane
+       /// - 3 is uniform scale
+       static inline Matrix<3,3, Precision> generator(int i) {
+               Matrix<3,3,Precision> result(Zeros);
+               switch(i){
+               case 0:
+               case 1:
+                       result(i,2) = 1;
+                       break;
+               case 2:
+                       result(0,1) = -1;
+                       result(1,0) = 1;
+                       break;
+               case 3:
+                       result(0,0) = 1;
+                       result(1,1) = 1;
+                       break;
+               }
+               return result;
+       }
+
+       /// transfers a vector in the Lie algebra, from one coord frame to 
another
+       /// so that exp(adjoint(vect)) = (*this) * exp(vect) * (this->inverse())
+       template<typename Accessor>
+       Vector<4, Precision> adjoint(const Vector<4,Precision, Accessor> & 
vect) const {
+               Vector<4, Precision> result;
+               result[2] = vect[2];
+               result.template slice<0,2>() = get_rotation() * vect.template 
slice<0,2>();
+               result[0] += vect[2] * get_translation()[1];
+               result[1] -= vect[2] * get_translation()[0];
+               return result;
+       }
+
+       template <typename Accessor>
+       Matrix<4,4,Precision> adjoint(const Matrix<4,4,Precision,Accessor>& M) 
const {
+               Matrix<4,4,Precision> result;
+               for(int i=0; i<4; ++i)
+                       result.T()[i] = adjoint(M.T()[i]);
+               for(int i=0; i<4; ++i)
+                       result[i] = adjoint(result[i]);
+               return result;
+       }
+
+private:
+       SE2<Precision> my_se2;
+       Precision my_scale;
+};
+
+/// Write an SIM2 to a stream 
+/// @relates SIM2
+template <class Precision>
+inline std::ostream& operator<<(std::ostream& os, const SIM2<Precision> & rhs){
+       std::streamsize fw = os.width();
+       for(int i=0; i<2; i++){
+               os.width(fw);
+               os << rhs.get_rotation().get_matrix()[i] * rhs.get_scale();
+               os.width(fw);
+               os << rhs.get_translation()[i] << '\n';
+       }
+       return os;
+}
+
+/// Read an SIM2 from a stream 
+/// @relates SIM2
+template <class Precision>
+inline std::istream& operator>>(std::istream& is, SIM2<Precision>& rhs){
+       for(int i=0; i<2; i++)
+               is >> rhs.get_rotation().my_matrix[i].ref() >> 
rhs.get_translation()[i];
+       rhs.get_scale() = (norm(rhs.get_rotation().my_matrix[0]) + 
norm(rhs.get_rotation().my_matrix[1]))/2;
+       rhs.get_rotation().coerce();
+       return is;
+}
+
+
+//////////////////
+// operator *   //
+// SIM2 * Vector //
+//////////////////
+
+namespace Internal {
+template<int S, typename P, typename PV, typename A>
+struct SIM2VMult;
+}
+
+template<int S, typename P, typename PV, typename A>
+struct Operator<Internal::SIM2VMult<S,P,PV,A> > {
+       const SIM2<P> & lhs;
+       const Vector<S,PV,A> & rhs;
+       
+       Operator(const SIM2<P> & l, const Vector<S,PV,A> & r ) : lhs(l), rhs(r) 
{}
+       
+       template <int S0, typename P0, typename A0>
+       void eval(Vector<S0, P0, A0> & res ) const {
+               SizeMismatch<3,S>::test(3, rhs.size());
+               res.template 
slice<0,2>()=lhs.get_rotation()*(lhs.get_scale()*rhs.template slice<0,2>());
+               res.template slice<0,2>()+=lhs.get_translation() * rhs[2];
+               res[2] = rhs[2];
+       }
+       int size() const { return 3; }
+};
+
+/// Right-multiply with a Vector<3>
+/// @relates SIM2
+template<int S, typename P, typename PV, typename A>
+inline Vector<3, typename Internal::MultiplyType<P,PV>::type> operator*(const 
SIM2<P> & lhs, const Vector<S,PV,A>& rhs){
+       return Vector<3, typename 
Internal::MultiplyType<P,PV>::type>(Operator<Internal::SIM2VMult<S,P,PV,A> 
>(lhs,rhs));
+}
+
+/// Right-multiply with a Vector<2> (special case, extended to be a 
homogeneous vector)
+/// @relates SIM2
+template <typename P, typename PV, typename A>
+inline Vector<2, typename Internal::MultiplyType<P,PV>::type> operator*(const 
SIM2<P>& lhs, const Vector<2,PV,A>& rhs){
+       return lhs.get_translation() + lhs.get_rotation() * (lhs.get_scale() * 
rhs);
+}
+
+//////////////////
+// operator *   //
+// Vector * SIM2 //
+//////////////////
+
+namespace Internal {
+template<int S, typename P, typename PV, typename A>
+struct VSIM2Mult;
+}
+
+template<int S, typename P, typename PV, typename A>
+struct Operator<Internal::VSIM2Mult<S,P,PV,A> > {
+       const Vector<S,PV,A> & lhs;
+       const SIM2<P> & rhs;
+       
+       Operator(const Vector<S,PV,A> & l, const SIM2<P> & r ) : lhs(l), rhs(r) 
{}
+       
+       template <int S0, typename P0, typename A0>
+       void eval(Vector<S0, P0, A0> & res ) const {
+               SizeMismatch<3,S>::test(3, lhs.size());
+               res.template slice<0,2>() = (lhs.template slice<0,2>()* 
rhs.get_scale())*rhs.get_rotation();
+               res[2] = lhs[2];
+               res[2] += lhs.template slice<0,2>() * rhs.get_translation();
+       }
+       int size() const { return 3; }
+};
+
+/// Left-multiply with a Vector<3>
+/// @relates SIM2
+template<int S, typename P, typename PV, typename A>
+inline Vector<3, typename Internal::MultiplyType<PV,P>::type> operator*(const 
Vector<S,PV,A>& lhs, const SIM2<P> & rhs){
+       return Vector<3, typename 
Internal::MultiplyType<PV,P>::type>(Operator<Internal::VSIM2Mult<S, P,PV,A> 
>(lhs,rhs));
+}
+
+//////////////////
+// operator *   //
+// SIM2 * Matrix //
+//////////////////
+
+namespace Internal {
+template <int R, int C, typename PM, typename A, typename P>
+struct SIM2MMult;
+}
+
+template<int R, int Cols, typename PM, typename A, typename P>
+struct Operator<Internal::SIM2MMult<R, Cols, PM, A, P> > {
+       const SIM2<P> & lhs;
+       const Matrix<R,Cols,PM,A> & rhs;
+       
+       Operator(const SIM2<P> & l, const Matrix<R,Cols,PM,A> & r ) : lhs(l), 
rhs(r) {}
+       
+       template <int R0, int C0, typename P0, typename A0>
+       void eval(Matrix<R0, C0, P0, A0> & res ) const {
+               SizeMismatch<3,R>::test(3, rhs.num_rows());
+               for(int i=0; i<rhs.num_cols(); ++i)
+                       res.T()[i] = lhs * rhs.T()[i];
+       }
+       int num_cols() const { return rhs.num_cols(); }
+       int num_rows() const { return 3; }
+};
+
+/// Right-multiply with a Matrix<3>
+/// @relates SIM2
+template <int R, int Cols, typename PM, typename A, typename P> 
+inline Matrix<3,Cols, typename Internal::MultiplyType<P,PM>::type> 
operator*(const SIM2<P> & lhs, const Matrix<R,Cols,PM, A>& rhs){
+       return Matrix<3,Cols,typename 
Internal::MultiplyType<P,PM>::type>(Operator<Internal::SIM2MMult<R, Cols, PM, 
A, P> >(lhs,rhs));
+}
+
+//////////////////
+// operator *   //
+// Matrix * SIM2 //
+//////////////////
+
+namespace Internal {
+template <int Rows, int C, typename PM, typename A, typename P>
+struct MSIM2Mult;
+}
+
+template<int Rows, int C, typename PM, typename A, typename P>
+struct Operator<Internal::MSIM2Mult<Rows, C, PM, A, P> > {
+       const Matrix<Rows,C,PM,A> & lhs;
+       const SIM2<P> & rhs;
+       
+       Operator( const Matrix<Rows,C,PM,A> & l, const SIM2<P> & r ) : lhs(l), 
rhs(r) {}
+       
+       template <int R0, int C0, typename P0, typename A0>
+       void eval(Matrix<R0, C0, P0, A0> & res ) const {
+               SizeMismatch<3, C>::test(3, lhs.num_cols());
+               for(int i=0; i<lhs.num_rows(); ++i)
+                       res[i] = lhs[i] * rhs;
+       }
+       int num_cols() const { return 3; }
+       int num_rows() const { return lhs.num_rows(); }
+};
+
+/// Left-multiply with a Matrix<3>
+/// @relates SIM2
+template <int Rows, int C, typename PM, typename A, typename P> 
+inline Matrix<Rows,3, typename Internal::MultiplyType<PM,P>::type> 
operator*(const Matrix<Rows,C,PM, A>& lhs, const SIM2<P> & rhs ){
+       return Matrix<Rows,3,typename 
Internal::MultiplyType<PM,P>::type>(Operator<Internal::MSIM2Mult<Rows, C, PM, 
A, P> >(lhs,rhs));
+}
+
+template <typename Precision>
+template <int S, typename PV, typename Accessor>
+inline SIM2<Precision> SIM2<Precision>::exp(const Vector<S, PV, Accessor>& mu){
+       SizeMismatch<4,S>::test(4, mu.size());
+
+       static const Precision one_6th = 1.0/6.0;
+       static const Precision one_20th = 1.0/20.0;
+  
+       using std::exp;
+  
+       SIM2<Precision> result;
+  
+       // rotation
+       const Precision theta = mu[2];
+       result.get_rotation() = SO2<Precision>::exp(theta);
+
+       // scale
+       const Precision s = mu[3];
+       const Precision es = exp(s);
+       result.get_scale() = es;
+
+       // translation
+       const Precision a = es * sin(theta);
+       const Precision b = es * cos(theta);
+       const Precision c = (fabs(s) < 1e-6) ? (1 + s/2 + s*s/6) : expm1(s)/s;
+
+       const Precision inv_s_theta = 1/(s*s + theta * theta);
+
+       const Precision CC = (a*s + (1-b)*theta) * inv_s_theta / theta;
+       const Precision CCC = ((b-1)*s + a*theta) * inv_s_theta;
+
+       const Vector<2, Precision> cross = makeVector( -theta * mu[1], theta * 
mu[0]);
+       result.get_translation() = CCC * mu.template slice<0,2>() + 
TooN::operator*(CC, cross); 
+
+       return result;
+}
+ 
+template <typename Precision>
+inline Vector<4, Precision> SIM2<Precision>::ln(const SIM2<Precision> & sim2) {
+       using std::log;
+
+       Vector<4, Precision> result;
+
+       // rotation
+       const Precision theta = sim2.get_rotation().ln();
+       result[2] = theta;
+
+       // scale 
+       const Precision es = sim2.get_scale();
+       const Precision s = log(sim2.get_scale());
+       result[3] = s;
+
+       // translation
+       const Precision a = es * sin(theta);
+       const Precision b = es * cos(theta);
+       const Precision c = (fabs(s) < 1e-6) ? (1 + s/2 + s*s/6) : expm1(s)/s;
+
+       const Precision inv_s_theta = 1/(s*s + theta * theta);
+
+       const Precision CC = (a*s + (1-b)*theta) * inv_s_theta / theta;
+       const Precision CCC = ((b-1)*s + a*theta) * inv_s_theta;
+       
+       Matrix<2,2, Precision> cross = Zeros; cross(0,1) = -theta; cross(1,0) = 
theta;
+       const Matrix<2,2, Precision> W = CCC * Identity + CC * cross;   
+       result.template slice<0,2>() = gaussian_elimination(W, 
sim2.get_translation());
+
+       return result;
+}
+
+#if 0
+/// Multiply a SO2 with and SE2
+/// @relates SE2
+/// @relates SO2
+template <typename Precision>
+inline SE2<Precision> operator*(const SO2<Precision> & lhs, const 
SE2<Precision>& rhs){
+       return SE2<Precision>( lhs*rhs.get_rotation(), 
lhs*rhs.get_translation());
+}
+#endif
+
+}
+#endif

Index: sim3.h
===================================================================
RCS file: sim3.h
diff -N sim3.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sim3.h      29 Jun 2011 20:20:00 -0000      1.1
@@ -0,0 +1,503 @@
+// -*- c++ -*-
+
+// Copyright (C) 2011 Tom Drummond (address@hidden)
+//
+// This file is part of the TooN Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#ifndef TOON_INCLUDE_SIM3_H
+#define TOON_INCLUDE_SIM3_H
+
+#include <TooN/se3.h>
+
+namespace TooN {
+
+
+/// Represent a three-dimensional similarity transformation (a rotation, a 
scale factor and a translation). 
+/// This can be represented by a \f$3\times\f$4 matrix operating on a 
homogeneous co-ordinate, 
+/// so that a vector \f$\underline{x}\f$ is transformed to a new location 
\f$\underline{x}'\f$
+/// by
+/// \f[\begin{aligned}\underline{x}' &= E\times\underline{x}\\ 
\begin{bmatrix}x'\\y'\\z'\end{bmatrix} &= \begin{pmatrix}r_{11} & r_{12} & 
r_{13} & t_1\\r_{21} & r_{22} & r_{23} & t_2\\r_{31} & r_{32} & r_{33} & 
t_3\end{pmatrix}\begin{bmatrix}x\\y\\z\\1\end{bmatrix}\end{aligned}\f]
+/// 
+/// This transformation is a member of the Lie group SIM3. These can be 
parameterised with
+/// seven numbers (in the space of the Lie Algebra). In this class, the first 
three parameters are a
+/// translation vector while the second three are a rotation vector, whose 
direction is the axis of rotation
+/// and length the amount of rotation (in radians), as for SO3. The seventh 
parameter is the log of the scale of the transformation.
+/// @ingroup gTransforms
+template <typename Precision = DefaultPrecision>
+class SIM3 {
+public:
+       /// Default constructor. Initialises the the rotation to zero (the 
identity), the scale to one and the translation to zero
+       inline SIM3() : my_scale(1) {}
+
+       template <int S, typename P, typename A> 
+       SIM3(const SO3<Precision> & R, const Vector<S, P, A>& T, const 
Precision & s) : my_se3(R,T), my_scale(s) {}
+       template <int S, typename P, typename A>
+       SIM3(const Vector<S, P, A> & v) { *this = exp(v); }
+
+       /// Returns the rotation part of the transformation as a SO3
+       inline SO3<Precision>& get_rotation(){return my_se3.get_rotation();}
+       /// @overload
+       inline const SO3<Precision>& get_rotation() const {return 
my_se3.get_rotation();}
+
+       /// Returns the translation part of the transformation as a Vector
+       inline Vector<3, Precision>& get_translation() {return 
my_se3.get_translation();}
+       /// @overload
+       inline const Vector<3, Precision>& get_translation() const {return 
my_se3.get_translation();}
+
+       /// Returns the scale factor
+       inline Precision & get_scale() { return my_scale; }
+       /// @overload
+       inline const Precision & get_scale() const { return my_scale; }
+
+       /// Exponentiate a Vector in the Lie Algebra to generate a new SIM3.
+       /// See the Detailed Description for details of this vector.
+       /// @param vect The Vector to exponentiate
+       template <int S, typename P, typename A>
+       static inline SIM3 exp(const Vector<S, P, A>& vect);
+
+       /// Take the logarithm of the matrix, generating the corresponding 
vector in the Lie Algebra.
+       /// See the Detailed Description for details of this vector.
+       static inline Vector<7, Precision> ln(const SIM3& se3);
+       /// @overload
+       inline Vector<7, Precision> ln() const { return SIM3::ln(*this); }
+
+       inline SIM3 inverse() const {
+               const SO3<Precision> rinv = get_rotation().inverse();
+               const Precision inv_scale = 1/my_scale;
+               return SIM3(rinv, -(inv_scale*(rinv*get_translation())), 
inv_scale);
+       }
+
+       /// Right-multiply by another SIM3 (concatenate the two transformations)
+       /// @param rhs The multipier
+       inline SIM3& operator *=(const SIM3& rhs) {
+               get_translation() += get_rotation() * (get_scale() * 
rhs.get_translation());
+               get_rotation() *= rhs.get_rotation();
+               get_scale() *= rhs.get_scale();
+               return *this;
+       }
+
+       /// Right-multiply by another SIM3 (concatenate the two transformations)
+       /// @param rhs The multipier
+       template<typename P>
+       inline SIM3<typename Internal::MultiplyType<Precision, P>::type> 
operator *(const SIM3<P>& rhs) const { 
+           return SIM3<typename Internal::MultiplyType<Precision, 
P>::type>(get_rotation()*rhs.get_rotation(), get_translation() + 
get_rotation()*(get_scale()*rhs.get_translation()), 
get_scale()*rhs.get_scale());
+       }
+
+       inline SIM3& left_multiply_by(const SIM3& left) {
+               get_translation() = left.get_translation() + 
left.get_rotation() * (left.get_scale() * get_translation());
+               get_rotation() = left.get_rotation() * get_rotation();
+               get_scale() = left.get_scale() * get_scale();
+               return *this;
+       }
+
+       static inline Matrix<4,4,Precision> generator(int i){
+               Matrix<4,4,Precision> result(Zeros);
+               if(i < 3){
+                       result(i,3)=1;
+                       return result;
+               }
+               if(i < 6){
+                       result[(i+1)%3][(i+2)%3] = -1;
+                       result[(i+2)%3][(i+1)%3] = 1;
+                       return result;
+               }
+               result(0,0) = 1;
+               result(1,1) = 1;
+               result(2,2) = 1;
+               return result;
+       }
+
+  /// Returns the i-th generator times pos
+       template<typename Base>
+       inline static Vector<4,Precision> generator_field(int i, const 
Vector<4, Precision, Base>& pos)
+       {
+               Vector<4, Precision> result(Zeros);
+               if(i < 3){
+                 result[i]=pos[3];
+                 return result;
+               }
+               if(i < 6){
+                       result[(i+1)%3] = - pos[(i+2)%3];
+                       result[(i+2)%3] = pos[(i+1)%3];
+                       return result;
+               }
+               result.template slice<0,3>() = pos.template slice<0,3>();
+               return result;
+       }
+  
+       /// Transfer a matrix in the Lie Algebra from one
+       /// co-ordinate frame to another. This is the operation such that for a 
matrix 
+       /// \f$ B \f$, 
+       /// \f$ e^{\text{Adj}(v)} = Be^{v}B^{-1} \f$
+       /// @param M The Matrix to transfer
+       template<int S, typename P2, typename Accessor>
+       inline Vector<7, Precision> adjoint(const Vector<S,P2, Accessor>& 
vect)const;
+
+       /// Transfer covectors between frames (using the transpose of the 
inverse of the adjoint)
+       /// so that trinvadjoint(vect1) * adjoint(vect2) = vect1 * vect2
+       template<int S, typename P2, typename Accessor>
+       inline Vector<7, Precision> trinvadjoint(const Vector<S,P2,Accessor>& 
vect)const;
+       
+       ///@overload
+       template <int R, int C, typename P2, typename Accessor>
+       inline Matrix<7,7,Precision> adjoint(const Matrix<R,C,P2,Accessor>& 
M)const;
+
+       ///@overload
+       template <int R, int C, typename P2, typename Accessor>
+       inline Matrix<7,7,Precision> trinvadjoint(const 
Matrix<R,C,P2,Accessor>& M)const;
+
+private:
+       SE3<Precision> my_se3;
+       Precision my_scale;
+};
+
+// transfers a vector in the Lie algebra
+// from one coord frame to another
+// so that exp(adjoint(vect)) = (*this) * exp(vect) * (this->inverse())
+template<typename Precision>
+template<int S, typename P2, typename Accessor>
+inline Vector<7, Precision> SIM3<Precision>::adjoint(const Vector<S,P2, 
Accessor>& vect) const{
+       SizeMismatch<7,S>::test(7, vect.size());
+       Vector<7, Precision> result;
+       result.template slice<3,3>() = get_rotation() * vect.template 
slice<3,3>();
+       result.template slice<0,3>() = get_rotation() * vect.template 
slice<0,3>();
+       result.template slice<0,3>() += get_translation() ^ result.template 
slice<3,3>();
+       return result;
+}
+
+// tansfers covectors between frames
+// (using the transpose of the inverse of the adjoint)
+// so that trinvadjoint(vect1) * adjoint(vect2) = vect1 * vect2
+template<typename Precision>
+template<int S, typename P2, typename Accessor>
+inline Vector<7, Precision> SIM3<Precision>::trinvadjoint(const Vector<S,P2, 
Accessor>& vect) const{
+       SizeMismatch<7,S>::test(7, vect.size());
+       Vector<7, Precision> result;
+       result.template slice<3,3>() = get_rotation() * vect.template 
slice<3,3>();
+       result.template slice<0,3>() = get_rotation() * vect.template 
slice<0,3>();
+       result.template slice<3,3>() += get_translation() ^ result.template 
slice<0,3>();
+       return result;
+}
+
+template<typename Precision>
+template<int R, int C, typename P2, typename Accessor>
+inline Matrix<7,7,Precision> SIM3<Precision>::adjoint(const 
Matrix<R,C,P2,Accessor>& M)const{
+       SizeMismatch<7,R>::test(7, M.num_cols());
+       SizeMismatch<7,C>::test(7, M.num_rows());
+
+       Matrix<7,7,Precision> result;
+       for(int i=0; i<7; i++){
+               result.T()[i] = adjoint(M.T()[i]);
+       }
+       for(int i=0; i<7; i++){
+               result[i] = adjoint(result[i]);
+       }
+       return result;
+}
+
+template<typename Precision>
+template<int R, int C, typename P2, typename Accessor>
+inline Matrix<7,7,Precision> SIM3<Precision>::trinvadjoint(const 
Matrix<R,C,P2,Accessor>& M)const{
+       SizeMismatch<7,R>::test(7, M.num_cols());
+       SizeMismatch<7,C>::test(7, M.num_rows());
+
+       Matrix<7,7,Precision> result;
+       for(int i=0; i<7; i++){
+               result.T()[i] = trinvadjoint(M.T()[i]);
+       }
+       for(int i=0; i<7; i++){
+               result[i] = trinvadjoint(result[i]);
+       }
+       return result;
+}
+
+/// Write an SIM3 to a stream 
+/// @relates SIM3
+template <typename Precision>
+inline std::ostream& operator <<(std::ostream& os, const SIM3<Precision>& rhs){
+       std::streamsize fw = os.width();
+       for(int i=0; i<3; i++){
+               os.width(fw);
+               os << rhs.get_rotation().get_matrix()[i] * rhs.get_scale();
+               os.width(fw);
+               os << rhs.get_translation()[i] << '\n';
+       }
+       return os;
+}
+
+
+/// Reads an SIM3 from a stream 
+/// @relates SIM3
+template <typename Precision>
+inline std::istream& operator>>(std::istream& is, SIM3<Precision>& rhs){
+       for(int i=0; i<3; i++){
+               is >> rhs.get_rotation().my_matrix[i].ref() >> 
rhs.get_translation()[i];
+       }
+       rhs.get_scale() = (norm(rhs.get_rotation().my_matrix[0]) + 
norm(rhs.get_rotation().my_matrix[1]) + 
norm(rhs.get_rotation().my_matrix[2]))/3;
+       rhs.get_rotation().coerce();
+       return is;
+}
+
+//////////////////
+// operator *   //
+// SIM3 * Vector //
+//////////////////
+
+namespace Internal {
+template<int S, typename PV, typename A, typename P>
+struct SIM3VMult;
+}
+
+template<int S, typename PV, typename A, typename P>
+struct Operator<Internal::SIM3VMult<S,PV,A,P> > {
+       const SIM3<P> & lhs;
+       const Vector<S,PV,A> & rhs;
+       
+       Operator(const SIM3<P> & l, const Vector<S,PV,A> & r ) : lhs(l), rhs(r) 
{}
+       
+       template <int S0, typename P0, typename A0>
+       void eval(Vector<S0, P0, A0> & res ) const {
+               SizeMismatch<4,S>::test(4, rhs.size());
+               res.template slice<0,3>()=lhs.get_rotation() * (lhs.get_scale() 
* rhs.template slice<0,3>());
+               res.template 
slice<0,3>()+=TooN::operator*(lhs.get_translation(),rhs[3]);
+               res[3] = rhs[3];
+       }
+       int size() const { return 4; }
+};
+
+/// Right-multiply by a Vector
+/// @relates SIM3
+template<int S, typename PV, typename A, typename P> inline
+Vector<4, typename Internal::MultiplyType<P,PV>::type> operator*(const SIM3<P> 
& lhs, const Vector<S,PV,A>& rhs){
+       return Vector<4, typename 
Internal::MultiplyType<P,PV>::type>(Operator<Internal::SIM3VMult<S,PV,A,P> 
>(lhs,rhs));
+}
+
+/// Right-multiply by a Vector
+/// @relates SIM3
+template <typename PV, typename A, typename P> inline
+Vector<3, typename Internal::MultiplyType<P,PV>::type> operator*(const 
SIM3<P>& lhs, const Vector<3,PV,A>& rhs){
+       return lhs.get_translation() + lhs.get_rotation() * (lhs.get_scale() * 
rhs);
+}
+
+//////////////////
+// operator *   //
+// Vector * SIM3 //
+//////////////////
+
+namespace Internal {
+template<int S, typename PV, typename A, typename P>
+struct VSIM3Mult;
+}
+
+template<int S, typename PV, typename A, typename P>
+struct Operator<Internal::VSIM3Mult<S,PV,A,P> > {
+       const Vector<S,PV,A> & lhs;
+       const SIM3<P> & rhs;
+       
+       Operator( const Vector<S,PV,A> & l, const SIM3<P> & r ) : lhs(l), 
rhs(r) {}
+       
+       template <int S0, typename P0, typename A0>
+       void eval(Vector<S0, P0, A0> & res ) const {
+               SizeMismatch<4,S>::test(4, lhs.size());
+               res.template slice<0,3>()= rhs.get_scale() * lhs.template 
slice<0,3>() * rhs.get_rotation();
+               res[3] = lhs[3];
+               res[3] += lhs.template slice<0,3>() * rhs.get_translation();
+       }
+       int size() const { return 4; }
+};
+
+/// Left-multiply by a Vector
+/// @relates SIM3
+template<int S, typename PV, typename A, typename P> inline
+Vector<4, typename Internal::MultiplyType<P,PV>::type> operator*( const 
Vector<S,PV,A>& lhs, const SIM3<P> & rhs){
+       return Vector<4, typename 
Internal::MultiplyType<P,PV>::type>(Operator<Internal::VSIM3Mult<S,PV,A,P> 
>(lhs,rhs));
+}
+
+//////////////////
+// operator *   //
+// SIM3 * Matrix //
+//////////////////
+
+namespace Internal {
+template <int R, int C, typename PM, typename A, typename P>
+struct SIM3MMult;
+}
+
+template<int R, int Cols, typename PM, typename A, typename P>
+struct Operator<Internal::SIM3MMult<R, Cols, PM, A, P> > {
+       const SIM3<P> & lhs;
+       const Matrix<R,Cols,PM,A> & rhs;
+       
+       Operator(const SIM3<P> & l, const Matrix<R,Cols,PM,A> & r ) : lhs(l), 
rhs(r) {}
+       
+       template <int R0, int C0, typename P0, typename A0>
+       void eval(Matrix<R0, C0, P0, A0> & res ) const {
+               SizeMismatch<4,R>::test(4, rhs.num_rows());
+               for(int i=0; i<rhs.num_cols(); ++i)
+                       res.T()[i] = lhs * rhs.T()[i];
+       }
+       int num_cols() const { return rhs.num_cols(); }
+       int num_rows() const { return 4; }
+};
+
+/// Right-multiply by a Matrix
+/// @relates SIM3
+template <int R, int Cols, typename PM, typename A, typename P> inline 
+Matrix<4,Cols, typename Internal::MultiplyType<P,PM>::type> operator*(const 
SIM3<P> & lhs, const Matrix<R,Cols,PM, A>& rhs){
+       return Matrix<4,Cols,typename 
Internal::MultiplyType<P,PM>::type>(Operator<Internal::SIM3MMult<R, Cols, PM, 
A, P> >(lhs,rhs));
+}
+
+//////////////////
+// operator *   //
+// Matrix * SIM3 //
+//////////////////
+
+namespace Internal {
+template <int Rows, int C, typename PM, typename A, typename P>
+struct MSIM3Mult;
+}
+
+template<int Rows, int C, typename PM, typename A, typename P>
+struct Operator<Internal::MSIM3Mult<Rows, C, PM, A, P> > {
+       const Matrix<Rows,C,PM,A> & lhs;
+       const SIM3<P> & rhs;
+       
+       Operator( const Matrix<Rows,C,PM,A> & l, const SIM3<P> & r ) : lhs(l), 
rhs(r) {}
+       
+       template <int R0, int C0, typename P0, typename A0>
+       void eval(Matrix<R0, C0, P0, A0> & res ) const {
+               SizeMismatch<4, C>::test(4, lhs.num_cols());
+               for(int i=0; i<lhs.num_rows(); ++i)
+                       res[i] = lhs[i] * rhs;
+       }
+       int num_cols() const { return 4; }
+       int num_rows() const { return lhs.num_rows(); }
+};
+
+/// Left-multiply by a Matrix
+/// @relates SIM3
+template <int Rows, int C, typename PM, typename A, typename P> inline 
+Matrix<Rows,4, typename Internal::MultiplyType<PM,P>::type> operator*(const 
Matrix<Rows,C,PM, A>& lhs, const SIM3<P> & rhs ){
+       return Matrix<Rows,4,typename 
Internal::MultiplyType<PM,P>::type>(Operator<Internal::MSIM3Mult<Rows, C, PM, 
A, P> >(lhs,rhs));
+}
+
+template <typename Precision>
+template <int S, typename P, typename VA>
+inline SIM3<Precision> SIM3<Precision>::exp(const Vector<S, P, VA>& mu){
+       SizeMismatch<7,S>::test(7, mu.size());
+       static const Precision one_6th = 1.0/6.0;
+       static const Precision one_20th = 1.0/20.0;
+
+       using std::sqrt;
+       using std::exp;
+       
+       SIM3<Precision> result;
+       
+       const Vector<3,Precision> w = mu.template slice<3,3>();
+       const Precision theta_sq = w*w;
+       const Precision theta = sqrt(theta_sq);
+       
+       // scale
+       const Precision s = mu[6];
+       const Precision es = exp(s);
+       result.get_scale() = es;
+       
+       // rotation
+       Precision A, B;
+       if (theta_sq < 1e-8) {
+               A = 1.0 - one_6th * theta_sq;
+               B = 0.5;
+       } else {
+               if (theta_sq < 1e-6) {
+                       A = 1.0 - theta_sq * one_6th*(1.0 - one_20th * 
theta_sq);
+                       B = 0.5 - 0.25 * one_6th * theta_sq;
+               } else {
+                       const Precision inv_theta = 1.0/theta;
+                       A = sin(theta) * inv_theta;
+                       B = (1 - cos(theta)) * (inv_theta * inv_theta);
+               }
+       }
+       rodrigues_so3_exp(w, A, B, result.get_rotation().my_matrix);
+       
+       // translation
+       const Precision a = es * sin(theta);
+       const Precision b = es * cos(theta);
+       const Precision c = (fabs(s) < 1e-6) ? (1 + s/2 + s*s/6) : expm1(s)/s;
+
+       const Precision inv_s_theta = 1/(s*s + theta_sq);
+       
+       const Precision CC = (a*s + (1-b)*theta) * inv_s_theta / theta;
+       const Precision CCC = (c - ((b-1)*s + a*theta) * inv_s_theta) / (theta 
* theta);
+       
+       const Vector<3,Precision> cross = w ^ mu.template slice<0,3>();
+       result.get_translation() = c * mu.template slice<0,3>() + 
TooN::operator*(CC, cross) + TooN::operator*(CCC, (w ^ cross));       
+
+       return result;
+}
+
+template <typename Precision>
+inline Vector<7, Precision> SIM3<Precision>::ln(const SIM3<Precision>& sim3) {
+       using std::sqrt;
+       using std::log;
+
+       Vector<7, Precision> result;
+       
+       // rotation
+       result.template slice<3,3>() = sim3.get_rotation().ln();
+       const Precision theta_sq = norm_sq(result.template slice<3,3>());
+       const Precision theta = sqrt(theta_sq);
+
+       // scale 
+       const Precision es = sim3.get_scale();
+       const Precision s = log(sim3.get_scale());
+       result[6] = s;
+
+       // Translation
+       const Precision a = es * sin(theta);
+       const Precision b = es * cos(theta);
+       const Precision c = (fabs(s) < 1e-6) ? (1 + s/2 + s*s/6) : expm1(s)/s;
+       const Precision inv_s_theta = 1/(s*s + theta_sq);
+       
+       const Precision CC = (a*s + (1-b)*theta) * inv_s_theta / theta;
+       const Precision CCC = (c - ((b-1)*s + a*theta) * inv_s_theta) / (theta 
* theta);
+       const Matrix<3,3, Precision> cross = 
cross_product_matrix(result.template slice<3,3>());
+       const Matrix<3,3, Precision> W = Identity * c + cross * CC + cross * 
cross * CCC;
+       
+       result.template slice<0,3>() = gaussian_elimination(W, 
sim3.get_translation());
+
+       return result;
+}
+
+#if 0
+template <typename Precision>
+inline SE3<Precision> operator*(const SO3<Precision>& lhs, const 
SE3<Precision>& rhs){
+       return SE3<Precision>(lhs*rhs.get_rotation(),lhs*rhs.get_translation());
+}
+#endif
+
+}
+
+#endif



reply via email to

[Prev in Thread] Current Thread [Next in Thread]