LieGroup_SE3.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2009-2013 CEA LIST (DIASI/LSI) <xde-support@saxifrage.cea.fr>
00005 //
00006 // This Source Code Form is subject to the terms of the Mozilla
00007 // Public License v. 2.0. If a copy of the MPL was not distributed
00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00009 
00010 #ifndef EIGEN_LGSM_LIE_SE3_H
00011 #define EIGEN_LGSM_LIE_SE3_H
00012 
00013 namespace internal {
00014 template<typename Other,
00015          int OtherRows=Other::RowsAtCompileTime,
00016          int OtherCols=Other::ColsAtCompileTime>
00017 struct liegroup_SE3_base_assign_impl;
00018 }
00019 
00020 /*******************************************************************************
00021 * Definition/implementation of LieGroupBase<Array<Scalar, 7, 1, Derived>
00022 ********************************************************************************/
00023 
00036 template<class Derived> 
00037 class LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1>, Derived> 
00038 {
00039 public:
00040   /* List of typedef */  
00042   typedef typename internal::traits<Derived>::Scalar Scalar;
00044   typedef Array<Scalar, 7, 1> BaseType;
00046   typedef typename internal::traits<Derived>::Coefficients Coefficients;
00048   typedef typename internal::traits<Derived>::PlainObject PlainObject;
00049 
00051   typedef Matrix<Scalar, 6, 6> AdjointMatrix;  
00053   typedef LieAlgebra<Matrix<Scalar, 6, 1> > Algebra;   
00055   typedef LieAlgebraDual<Matrix<Scalar, 6, 1> > AlgebraDual;
00056 
00058   typedef Matrix<Scalar, 3, 1> Vector3;
00060   typedef LieGroup<Quaternion<Scalar> > SO3Element;  // an element of SO(3)
00061 
00063   EIGEN_STRONG_INLINE PlainObject inverse() const;
00065   static PlainObject Identity();
00067   template<class OtherDerived> inline PlainObject operator*(const LieGroupBase<BaseType, OtherDerived>& other) const;
00069   template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator*=(const LieGroupBase<BaseType, OtherDerived>& other);
00071   template<class OtherDerived> inline Vector3 operator*(const MatrixBase<OtherDerived>& d) const;
00072 
00074   AdjointMatrix adjoint(void) const;
00076   template<class AlgebraDerived> inline Algebra adjoint(const LieAlgebraBase<Matrix<Scalar, 6, 1>, AlgebraDerived>& ) const;
00078   template<class AlgebraDualDerived> inline AlgebraDual adjointTr(const LieAlgebraDualBase<Matrix<Scalar, 6, 1>, AlgebraDualDerived>& ) const;
00079   
00083   inline Algebra log(const Scalar precision = 1e-6) const;
00084   
00086   EIGEN_STRONG_INLINE LieGroupBase& operator=(const LieGroupBase& other);
00088   template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator=(const LieGroupBase<BaseType, OtherDerived>& other);
00090   template<class OtherDerived> Derived& operator=(const MatrixBase<OtherDerived>& m);
00091 
00093   inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
00095   inline Derived& derived() { return *static_cast<Derived*>(this); }
00096 
00098   inline Map<SO3Element> getSO3Element(){ return Map<SO3Element>(this->derived().get().template head<4>().data()); }
00100   inline Map<const SO3Element> getSO3Element() const{ return Map<const SO3Element>(this->derived().get().template head<4>().data()); }
00102   // a map is prefered to a VectorBlock, because the underlying data is an array and not a matrix
00103   inline Map<Vector3> getR3Element(){ return Map<Vector3>(this->get().template tail<3>().data()); }
00105   inline Map<const Vector3> getR3Element() const { return Map<const Vector3>(this->get().template tail<3>().data()); }
00106 
00108   Coefficients& get() { return derived().get(); }
00110   const Coefficients& get() const { return derived().get(); }  
00111   
00113   template<class OtherDerived>
00114   friend std::ostream& operator <<(std::ostream& os, const LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1>, Derived>& g);
00115 };
00116 
00117 /***************************************************************
00118  * Implementation of LieGroupBase<Array<Scalar, 7, 1> > methods
00119  ***************************************************************/
00120 
00121 // assignation
00122 template<class Derived>
00123 inline LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>& 
00124   LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::operator=(const LieGroupBase& other) 
00125 {
00126   this->get() = other.get();
00127   return *this;
00128 }
00129 
00130 template<class Derived>
00131 template<class OtherDerived>
00132 inline Derived& 
00133   LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::operator=(const LieGroupBase<BaseType, OtherDerived>& other) 
00134 {
00135   this->get() = other.get();
00136   return derived();
00137 }
00138 
00139 template<class Derived>
00140 template<class MatrixDerived>
00141 inline Derived& 
00142   LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::operator=(const MatrixBase<MatrixDerived>& xpr)
00143   {
00144     EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename MatrixDerived::Scalar>::value),
00145    YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00146   
00147    internal::liegroup_SE3_base_assign_impl<MatrixDerived>::run(*this, xpr.derived());
00148 
00149    return derived();
00150   }
00151 // inverse
00152 template<class Derived>
00153 typename LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::PlainObject
00154   LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::inverse() const 
00155 {
00156      return PlainObject(-(this->getSO3Element().inverse().operator*(this->getR3Element()))  // -rot^-1*trans
00157                         , this->getSO3Element().inverse());                                 // rot^-1
00158 }
00159 
00160 // identity
00161 template<class Derived>
00162 typename LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::PlainObject 
00163   LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::Identity() 
00164 {
00165   return PlainObject(Vector3(0,0,0), SO3Element::Identity());
00166 }
00167 
00168 // composition
00169 //
00170 // [ R1   p1 ] * [ R2 p2 ] = [ (R1*p2 + p1) (R1*R2) ]  
00171 //
00172 template<class Derived>
00173 template<class OtherDerived> EIGEN_STRONG_INLINE 
00174 typename LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::PlainObject 
00175   LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::operator*(const LieGroupBase<Array<Scalar, 7, 1 >, OtherDerived>& other) const 
00176 {
00177   return PlainObject(this->getSO3Element() * other.getR3Element() + this->getR3Element()  // rot1 * trans2 + trans1
00178                      , this->getSO3Element() * other.getSO3Element());                         // rot1 * rot2
00179 }
00180 
00181 
00182 template<class Derived>
00183 template<class OtherDerived> EIGEN_STRONG_INLINE 
00184  Derived& 
00185 LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::operator*=(const LieGroupBase<BaseType, OtherDerived>& other) {
00186 
00187   this->getR3Element() = this->getSO3Element() * other.getR3Element() + this->getR3Element();
00188   this->getSO3Element() *= other.getSO3Element();
00189 
00190   return derived();
00191 }
00192 
00193 // composition
00194 // [ R1   p1 ] * [ p2 ] = [ R1*p2 + p1 ]  
00195 //
00196 template<class Derived>
00197 template<class OtherDerived> EIGEN_STRONG_INLINE 
00198 typename LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::Vector3 
00199  LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::operator*(const MatrixBase<OtherDerived>& vec) const 
00200 {
00201   return Vector3(this->getSO3Element() * vec + this->getR3Element());
00202 }
00203 
00204 // log
00205 template<class Derived>
00206 typename LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::Algebra 
00207   LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::log(const Scalar precision) const 
00208 {
00209   typename SO3Element::Algebra ang = this->getSO3Element().log(precision);
00210 
00211   const Scalar n2 = ang.squaredNorm();  // ||wtidle||^2
00212 
00213   if(n2 < precision)
00214     return Algebra(ang, this->getR3Element());
00215   else{
00216 
00217     const Scalar n = std::sqrt(n2);
00218 
00219 #ifndef USE_RLAB_LOG_FUNCTION   //Set in Lgsm file
00220     const Scalar sn = std::sin(n);
00221 
00222     Scalar val = (Scalar(2.0) * sn - n * (Scalar(1.0) + std::cos(n))) / (Scalar(2.0) *n2 * sn);
00223 
00224     Vector3 lin = -0.5*ang.cross(this->getR3Element());
00225     lin += (Scalar(1.0) - val * n2 ) * this->getR3Element();
00226     lin += val * ang.dot(this->getR3Element()) * ang;
00227 
00228     return Algebra(ang, lin);
00229 
00230 #else
00231     // The previous code is unstable when the norm of the rotation gets close to pi
00232     // because we divide by sn=sin(n) that is close to zero to obtain val
00233     // We replace that code with code from RLab -> they work with the norm/2, sin(norm/2) and cos(norm/2)/sin(norm/2)
00234     // and given that norm is between pi and -pi,  sin(norm/2) is not going to be close to zero
00235     // (see HTransform.cpp, Vector3D.cpp and Rotation.cpp from RLab)
00236     const Scalar n_div2 = n/2.0;
00237     const Scalar s = std::sin(n_div2) / n_div2;
00238     const Scalar c = std::cos(n_div2);
00239     const Scalar gamma = c / s;
00240 
00241     Eigen::Matrix<double, 3, 3> dexpinv = Eigen::Matrix<double, 3, 3>::Identity();
00242 
00243     double v1 = ang[0];
00244     double v2 = ang[1];
00245     double v3 = ang[2];
00246 
00247     Eigen::Matrix<double, 3, 3> w_ceil = Eigen::Matrix<double, 3, 3>::Zero();
00248     w_ceil(0, 1) = -v3;
00249     w_ceil(0, 2) = v2;
00250     w_ceil(1, 0) = v3;
00251     w_ceil(1, 2) = -v1;
00252     w_ceil(2, 0) = -v2;
00253     w_ceil(2, 1) = v1;
00254 
00255     Eigen::Matrix<double, 3, 3> w_ceil_sqr = Eigen::Matrix<double, 3, 3>::Zero();
00256     double v1sqr = v1 * v1;
00257     double v2sqr = v2 * v2;
00258     double v3sqr = v3 * v3;
00259     double v12 = v1 * v2;
00260     double v13 = v1 * v3;
00261     double v23 = v2 * v3;
00262 
00263     w_ceil_sqr(0, 0) = -v2sqr - v3sqr;
00264     w_ceil_sqr(0, 1) = v12;
00265     w_ceil_sqr(0, 2) = v13;
00266     w_ceil_sqr(1, 0) = v12;
00267     w_ceil_sqr(1, 1) = -v1sqr - v3sqr;
00268     w_ceil_sqr(1, 2) = v23;
00269     w_ceil_sqr(2, 0) = v13;
00270     w_ceil_sqr(2, 1) = v23;
00271     w_ceil_sqr(2, 2) = -v1sqr - v2sqr;
00272 
00273     dexpinv += -0.5 * w_ceil + (1 - gamma) / n2 * w_ceil_sqr;
00274 
00275     Vector3 lin = dexpinv*this->getR3Element();
00276 
00277     return Algebra(ang, lin);
00278 #endif
00279   }
00280 }
00281 
00282 
00283 //RLab code
00284 //dMatrix dexpinv;
00285 //dExpInv_SO3(xi.w, dexpinv);
00286 //xi.v = dexpinv*r;
00287 
00288 //void dExpInv_SO3(const Vector3D& w, dMatrix& dexpinv)
00289 //{
00290 //    double wnorm = w.Norm();
00291 
00292 //    dexpinv.resize(3, 3);
00293 //    dexpinv.identity();
00294 
00295 //    if (wnorm > RMATH_ZERO)
00296 //    {
00297 //        double half_wnorm = wnorm / 2;
00298 //        double s = sin(half_wnorm) / half_wnorm;
00299 //        double c = cos(half_wnorm);
00300 
00301 //        double gamma = c / s;
00302 //        double wnorm_sqr = wnorm * wnorm;
00303 
00304 //        //dMatrix temp1 = -0.5*w.Ceil(); temp1.print("-1/2*w.Ceil()");
00305 //        //dMatrix temp2 = (1 - gamma)/wnorm_sqr*w.CeilSqr(); temp2.print("(1 - gamma)/wnorm_sqr*w.CeilSqr()");
00306 
00307 //        dexpinv += -0.5 * w.Ceil() + (1 - gamma) / wnorm_sqr * w.CeilSqr();
00308 //    }
00309 //}
00310 
00311 // adjoint
00312 //
00313 // Ad_H =  [ R          0 ]
00314 //         [ ptilde*R   R ]
00315 //
00316 template<class Derived>
00317 typename LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::AdjointMatrix 
00318   LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::adjoint() const 
00319 {
00320   AdjointMatrix res;
00321 
00322   res.template block<3,3>(0,0) = this->getSO3Element().adjoint();
00323   res.template block<3,3>(3,3) = res.template block<3,3>(0,0);
00324 
00325 
00326   res.template block<3,3>(3,0) = (Matrix<Scalar,3,3>() <<
00327                                   0, -this->getR3Element()[2], this->getR3Element()[1], // 0 -z  y
00328                                   this->getR3Element()[2], 0, -this->getR3Element()[0], // z  0 -x 
00329                                   -this->getR3Element()[1], this->getR3Element()[0], 0) //-y  x  0
00330                          .finished()*res.template block<3,3>(0,0);
00331 
00332   (res.template block<3,3>(0,3)).setZero();
00333 
00334   return res;
00335 }
00336 
00337 //
00338 // Ad_H * T =  [ R          0 ] * [ w ] = [       R*w   ] 
00339 //             [ ptilde*R   R ]   [ v ]   [ (p^R*w)+R*v ]
00340 //
00341 template<class Derived>
00342 template<class AlgebraDerived>
00343 inline typename LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::Algebra 
00344   LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::adjoint(const LieAlgebraBase<Matrix<Scalar, 6, 1>, AlgebraDerived>& a) const 
00345 {
00346   Vector3 Rw = this->getSO3Element() * a.getso3Element();                       // R*w
00347 
00348   typename SO3Element::Algebra ang(Rw);
00349   Vector3 lin = this->getR3Element().cross(Rw) + this->getSO3Element() * a.getR3Element(); // (p^R*w)+R*v
00350 
00351   return Algebra(ang, lin);
00352 }
00353 
00354 //
00355 // (Ad_H)' * W =  [ R'   -R'*ptilde ] * [ t ] = [  R'*(f^p+t) ] 
00356 //                [ 0           R'  ]   [ f ]   [      R'*f   ]
00357 //
00358 template<class Derived>
00359 template<class AlgebraDualDerived> 
00360 inline typename LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::AlgebraDual 
00361   LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1 >, Derived>::adjointTr(const LieAlgebraDualBase<Matrix<Scalar, 6, 1>, AlgebraDualDerived>& ca) const 
00362 {
00363   return AlgebraDual(this->getSO3Element().inverse() * (ca.getR3Element().cross(this->getR3Element() ) + ca.getso3Element()),  // R'*(f^p+t)
00364                    this->getSO3Element().inverse() * ca.getR3Element());                                                     // R'*f
00365 }
00366 
00367 /***************************************************************************
00368 * Definition/implementation of LieGroup<Array<Scalar, 7, 1> >
00369 ***************************************************************************/
00370 
00383 template<typename _Scalar> class LieGroup<Array<_Scalar, 7, 1> > : 
00384   public LieGroupBase<Array<_Scalar, 7, 1>, LieGroup<Array<_Scalar, 7, 1> > > 
00385 {
00386 protected:
00388   typedef LieGroupBase<Array<_Scalar, 7, 1>, LieGroup<Array<_Scalar, 7, 1> > > Base;
00389 public:
00391   typedef _Scalar Scalar;
00393   typedef typename internal::traits<LieGroup<Array<_Scalar, 7, 1> > >::Coefficients Coefficients;
00394   // inherit assignement operator
00395   EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(LieGroup)
00396 
00397   
00398   inline LieGroup() : m_coeffs() {}
00400   inline LieGroup(const LieGroup& g) : m_coeffs(g.get() ) {}
00402   inline LieGroup(const Array<Scalar, 7, 1>& g) : m_coeffs(g) {}
00403 
00410   inline LieGroup(Scalar x, Scalar y, Scalar z, Scalar qw, Scalar qx, Scalar qy, Scalar qz) {
00411     // m_coeffs << qx, qy, qz, qw, x, y, z // operator<< is not inlined
00412     m_coeffs[0] = qx;
00413     m_coeffs[1] = qy;
00414     m_coeffs[2] = qz;
00415     m_coeffs[3] = qw;
00416     m_coeffs[4] = x;
00417     m_coeffs[5] = y;
00418     m_coeffs[6] = z;
00419   }
00421   EIGEN_STRONG_INLINE LieGroup(const typename Base::Vector3& v, const typename Base::SO3Element& r) {
00422     this->getR3Element() = v;
00423     this->getSO3Element() = r;
00424   }
00425   template<typename Derived>
00426   explicit inline LieGroup(const MatrixBase<Derived>& other) { this = other;}
00427 
00429   Coefficients& get() { return m_coeffs; }
00431   const Coefficients& get() const { return m_coeffs; }
00432 
00433 protected:
00435   Coefficients m_coeffs;
00436 };
00437 
00438 // set from a rotation matrix
00439 namespace internal {
00440   template<typename Other>
00441   struct liegroup_SE3_base_assign_impl<Other,4,4>
00442   {
00443     // Other and LieGroup Scalar must have the same type (it's already checked in the calling function)
00444     typedef typename Other::Scalar Scalar;
00445     template<class Derived> inline static void run(LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1>, Derived>& q, const Other& m)
00446     {   
00447       q.getSO3Element().get() =  m.template topLeftCorner<3,3>();
00448       q.getR3Element() = m.template topRightCorner<3,1>();
00449     }
00450   };
00451 
00452   // set from a vector of coefficients assumed to be a quaternion
00453   template<typename Other>
00454   struct liegroup_SE3_base_assign_impl<Other,3,1>
00455   {
00456     // Other and LieGroup Scalar must have the same type (it's already checked in the calling function)
00457     typedef typename Other::Scalar Scalar;
00458     template<class Derived> inline static void run(LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1>, Derived>& q, const Other& vec)
00459     {
00460       q.getR3Element() = vec;
00461       q.getSO3Element() = LieGroupBase<Array<typename internal::traits<Derived>::Scalar, 7, 1>, Derived>::SO3Element::Identity();
00462     }
00463   };
00464 } // namespace
00465 
00466 /***************************************************************************
00467 * Definition/implementation of Map<LieGroup<Array<Scalar, 7, 1> > >
00468 ***************************************************************************/
00469 
00470 // we don't need anything new
00471 
00472 
00473 #endif


lgsm
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:26:30