1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library 2*bf2c3715SXin Li // for linear algebra. 3*bf2c3715SXin Li // 4*bf2c3715SXin Li // Copyright (C) 2008 Gael Guennebaud <[email protected]> 5*bf2c3715SXin Li // 6*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla 7*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed 8*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9*bf2c3715SXin Li 10*bf2c3715SXin Li #ifndef EIGEN_ANGLEAXIS_H 11*bf2c3715SXin Li #define EIGEN_ANGLEAXIS_H 12*bf2c3715SXin Li 13*bf2c3715SXin Li namespace Eigen { 14*bf2c3715SXin Li 15*bf2c3715SXin Li /** \geometry_module \ingroup Geometry_Module 16*bf2c3715SXin Li * 17*bf2c3715SXin Li * \class AngleAxis 18*bf2c3715SXin Li * 19*bf2c3715SXin Li * \brief Represents a 3D rotation as a rotation angle around an arbitrary 3D axis 20*bf2c3715SXin Li * 21*bf2c3715SXin Li * \param _Scalar the scalar type, i.e., the type of the coefficients. 22*bf2c3715SXin Li * 23*bf2c3715SXin Li * \warning When setting up an AngleAxis object, the axis vector \b must \b be \b normalized. 24*bf2c3715SXin Li * 25*bf2c3715SXin Li * The following two typedefs are provided for convenience: 26*bf2c3715SXin Li * \li \c AngleAxisf for \c float 27*bf2c3715SXin Li * \li \c AngleAxisd for \c double 28*bf2c3715SXin Li * 29*bf2c3715SXin Li * Combined with MatrixBase::Unit{X,Y,Z}, AngleAxis can be used to easily 30*bf2c3715SXin Li * mimic Euler-angles. Here is an example: 31*bf2c3715SXin Li * \include AngleAxis_mimic_euler.cpp 32*bf2c3715SXin Li * Output: \verbinclude AngleAxis_mimic_euler.out 33*bf2c3715SXin Li * 34*bf2c3715SXin Li * \note This class is not aimed to be used to store a rotation transformation, 35*bf2c3715SXin Li * but rather to make easier the creation of other rotation (Quaternion, rotation Matrix) 36*bf2c3715SXin Li * and transformation objects. 37*bf2c3715SXin Li * 38*bf2c3715SXin Li * \sa class Quaternion, class Transform, MatrixBase::UnitX() 39*bf2c3715SXin Li */ 40*bf2c3715SXin Li 41*bf2c3715SXin Li namespace internal { 42*bf2c3715SXin Li template<typename _Scalar> struct traits<AngleAxis<_Scalar> > 43*bf2c3715SXin Li { 44*bf2c3715SXin Li typedef _Scalar Scalar; 45*bf2c3715SXin Li }; 46*bf2c3715SXin Li } 47*bf2c3715SXin Li 48*bf2c3715SXin Li template<typename _Scalar> 49*bf2c3715SXin Li class AngleAxis : public RotationBase<AngleAxis<_Scalar>,3> 50*bf2c3715SXin Li { 51*bf2c3715SXin Li typedef RotationBase<AngleAxis<_Scalar>,3> Base; 52*bf2c3715SXin Li 53*bf2c3715SXin Li public: 54*bf2c3715SXin Li 55*bf2c3715SXin Li using Base::operator*; 56*bf2c3715SXin Li 57*bf2c3715SXin Li enum { Dim = 3 }; 58*bf2c3715SXin Li /** the scalar type of the coefficients */ 59*bf2c3715SXin Li typedef _Scalar Scalar; 60*bf2c3715SXin Li typedef Matrix<Scalar,3,3> Matrix3; 61*bf2c3715SXin Li typedef Matrix<Scalar,3,1> Vector3; 62*bf2c3715SXin Li typedef Quaternion<Scalar> QuaternionType; 63*bf2c3715SXin Li 64*bf2c3715SXin Li protected: 65*bf2c3715SXin Li 66*bf2c3715SXin Li Vector3 m_axis; 67*bf2c3715SXin Li Scalar m_angle; 68*bf2c3715SXin Li 69*bf2c3715SXin Li public: 70*bf2c3715SXin Li 71*bf2c3715SXin Li /** Default constructor without initialization. */ 72*bf2c3715SXin Li EIGEN_DEVICE_FUNC AngleAxis() {} 73*bf2c3715SXin Li /** Constructs and initialize the angle-axis rotation from an \a angle in radian 74*bf2c3715SXin Li * and an \a axis which \b must \b be \b normalized. 75*bf2c3715SXin Li * 76*bf2c3715SXin Li * \warning If the \a axis vector is not normalized, then the angle-axis object 77*bf2c3715SXin Li * represents an invalid rotation. */ 78*bf2c3715SXin Li template<typename Derived> 79*bf2c3715SXin Li EIGEN_DEVICE_FUNC 80*bf2c3715SXin Li inline AngleAxis(const Scalar& angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle) {} 81*bf2c3715SXin Li /** Constructs and initialize the angle-axis rotation from a quaternion \a q. 82*bf2c3715SXin Li * This function implicitly normalizes the quaternion \a q. 83*bf2c3715SXin Li */ 84*bf2c3715SXin Li template<typename QuatDerived> 85*bf2c3715SXin Li EIGEN_DEVICE_FUNC inline explicit AngleAxis(const QuaternionBase<QuatDerived>& q) { *this = q; } 86*bf2c3715SXin Li /** Constructs and initialize the angle-axis rotation from a 3x3 rotation matrix. */ 87*bf2c3715SXin Li template<typename Derived> 88*bf2c3715SXin Li EIGEN_DEVICE_FUNC inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; } 89*bf2c3715SXin Li 90*bf2c3715SXin Li /** \returns the value of the rotation angle in radian */ 91*bf2c3715SXin Li EIGEN_DEVICE_FUNC Scalar angle() const { return m_angle; } 92*bf2c3715SXin Li /** \returns a read-write reference to the stored angle in radian */ 93*bf2c3715SXin Li EIGEN_DEVICE_FUNC Scalar& angle() { return m_angle; } 94*bf2c3715SXin Li 95*bf2c3715SXin Li /** \returns the rotation axis */ 96*bf2c3715SXin Li EIGEN_DEVICE_FUNC const Vector3& axis() const { return m_axis; } 97*bf2c3715SXin Li /** \returns a read-write reference to the stored rotation axis. 98*bf2c3715SXin Li * 99*bf2c3715SXin Li * \warning The rotation axis must remain a \b unit vector. 100*bf2c3715SXin Li */ 101*bf2c3715SXin Li EIGEN_DEVICE_FUNC Vector3& axis() { return m_axis; } 102*bf2c3715SXin Li 103*bf2c3715SXin Li /** Concatenates two rotations */ 104*bf2c3715SXin Li EIGEN_DEVICE_FUNC inline QuaternionType operator* (const AngleAxis& other) const 105*bf2c3715SXin Li { return QuaternionType(*this) * QuaternionType(other); } 106*bf2c3715SXin Li 107*bf2c3715SXin Li /** Concatenates two rotations */ 108*bf2c3715SXin Li EIGEN_DEVICE_FUNC inline QuaternionType operator* (const QuaternionType& other) const 109*bf2c3715SXin Li { return QuaternionType(*this) * other; } 110*bf2c3715SXin Li 111*bf2c3715SXin Li /** Concatenates two rotations */ 112*bf2c3715SXin Li friend EIGEN_DEVICE_FUNC inline QuaternionType operator* (const QuaternionType& a, const AngleAxis& b) 113*bf2c3715SXin Li { return a * QuaternionType(b); } 114*bf2c3715SXin Li 115*bf2c3715SXin Li /** \returns the inverse rotation, i.e., an angle-axis with opposite rotation angle */ 116*bf2c3715SXin Li EIGEN_DEVICE_FUNC AngleAxis inverse() const 117*bf2c3715SXin Li { return AngleAxis(-m_angle, m_axis); } 118*bf2c3715SXin Li 119*bf2c3715SXin Li template<class QuatDerived> 120*bf2c3715SXin Li EIGEN_DEVICE_FUNC AngleAxis& operator=(const QuaternionBase<QuatDerived>& q); 121*bf2c3715SXin Li template<typename Derived> 122*bf2c3715SXin Li EIGEN_DEVICE_FUNC AngleAxis& operator=(const MatrixBase<Derived>& m); 123*bf2c3715SXin Li 124*bf2c3715SXin Li template<typename Derived> 125*bf2c3715SXin Li EIGEN_DEVICE_FUNC AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m); 126*bf2c3715SXin Li EIGEN_DEVICE_FUNC Matrix3 toRotationMatrix(void) const; 127*bf2c3715SXin Li 128*bf2c3715SXin Li /** \returns \c *this with scalar type casted to \a NewScalarType 129*bf2c3715SXin Li * 130*bf2c3715SXin Li * Note that if \a NewScalarType is equal to the current scalar type of \c *this 131*bf2c3715SXin Li * then this function smartly returns a const reference to \c *this. 132*bf2c3715SXin Li */ 133*bf2c3715SXin Li template<typename NewScalarType> 134*bf2c3715SXin Li EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const 135*bf2c3715SXin Li { return typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); } 136*bf2c3715SXin Li 137*bf2c3715SXin Li /** Copy constructor with scalar type conversion */ 138*bf2c3715SXin Li template<typename OtherScalarType> 139*bf2c3715SXin Li EIGEN_DEVICE_FUNC inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other) 140*bf2c3715SXin Li { 141*bf2c3715SXin Li m_axis = other.axis().template cast<Scalar>(); 142*bf2c3715SXin Li m_angle = Scalar(other.angle()); 143*bf2c3715SXin Li } 144*bf2c3715SXin Li 145*bf2c3715SXin Li EIGEN_DEVICE_FUNC static inline const AngleAxis Identity() { return AngleAxis(Scalar(0), Vector3::UnitX()); } 146*bf2c3715SXin Li 147*bf2c3715SXin Li /** \returns \c true if \c *this is approximately equal to \a other, within the precision 148*bf2c3715SXin Li * determined by \a prec. 149*bf2c3715SXin Li * 150*bf2c3715SXin Li * \sa MatrixBase::isApprox() */ 151*bf2c3715SXin Li EIGEN_DEVICE_FUNC bool isApprox(const AngleAxis& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const 152*bf2c3715SXin Li { return m_axis.isApprox(other.m_axis, prec) && internal::isApprox(m_angle,other.m_angle, prec); } 153*bf2c3715SXin Li }; 154*bf2c3715SXin Li 155*bf2c3715SXin Li /** \ingroup Geometry_Module 156*bf2c3715SXin Li * single precision angle-axis type */ 157*bf2c3715SXin Li typedef AngleAxis<float> AngleAxisf; 158*bf2c3715SXin Li /** \ingroup Geometry_Module 159*bf2c3715SXin Li * double precision angle-axis type */ 160*bf2c3715SXin Li typedef AngleAxis<double> AngleAxisd; 161*bf2c3715SXin Li 162*bf2c3715SXin Li /** Set \c *this from a \b unit quaternion. 163*bf2c3715SXin Li * 164*bf2c3715SXin Li * The resulting axis is normalized, and the computed angle is in the [0,pi] range. 165*bf2c3715SXin Li * 166*bf2c3715SXin Li * This function implicitly normalizes the quaternion \a q. 167*bf2c3715SXin Li */ 168*bf2c3715SXin Li template<typename Scalar> 169*bf2c3715SXin Li template<typename QuatDerived> 170*bf2c3715SXin Li EIGEN_DEVICE_FUNC AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q) 171*bf2c3715SXin Li { 172*bf2c3715SXin Li EIGEN_USING_STD(atan2) 173*bf2c3715SXin Li EIGEN_USING_STD(abs) 174*bf2c3715SXin Li Scalar n = q.vec().norm(); 175*bf2c3715SXin Li if(n<NumTraits<Scalar>::epsilon()) 176*bf2c3715SXin Li n = q.vec().stableNorm(); 177*bf2c3715SXin Li 178*bf2c3715SXin Li if (n != Scalar(0)) 179*bf2c3715SXin Li { 180*bf2c3715SXin Li m_angle = Scalar(2)*atan2(n, abs(q.w())); 181*bf2c3715SXin Li if(q.w() < Scalar(0)) 182*bf2c3715SXin Li n = -n; 183*bf2c3715SXin Li m_axis = q.vec() / n; 184*bf2c3715SXin Li } 185*bf2c3715SXin Li else 186*bf2c3715SXin Li { 187*bf2c3715SXin Li m_angle = Scalar(0); 188*bf2c3715SXin Li m_axis << Scalar(1), Scalar(0), Scalar(0); 189*bf2c3715SXin Li } 190*bf2c3715SXin Li return *this; 191*bf2c3715SXin Li } 192*bf2c3715SXin Li 193*bf2c3715SXin Li /** Set \c *this from a 3x3 rotation matrix \a mat. 194*bf2c3715SXin Li */ 195*bf2c3715SXin Li template<typename Scalar> 196*bf2c3715SXin Li template<typename Derived> 197*bf2c3715SXin Li EIGEN_DEVICE_FUNC AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const MatrixBase<Derived>& mat) 198*bf2c3715SXin Li { 199*bf2c3715SXin Li // Since a direct conversion would not be really faster, 200*bf2c3715SXin Li // let's use the robust Quaternion implementation: 201*bf2c3715SXin Li return *this = QuaternionType(mat); 202*bf2c3715SXin Li } 203*bf2c3715SXin Li 204*bf2c3715SXin Li /** 205*bf2c3715SXin Li * \brief Sets \c *this from a 3x3 rotation matrix. 206*bf2c3715SXin Li **/ 207*bf2c3715SXin Li template<typename Scalar> 208*bf2c3715SXin Li template<typename Derived> 209*bf2c3715SXin Li EIGEN_DEVICE_FUNC AngleAxis<Scalar>& AngleAxis<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat) 210*bf2c3715SXin Li { 211*bf2c3715SXin Li return *this = QuaternionType(mat); 212*bf2c3715SXin Li } 213*bf2c3715SXin Li 214*bf2c3715SXin Li /** Constructs and \returns an equivalent 3x3 rotation matrix. 215*bf2c3715SXin Li */ 216*bf2c3715SXin Li template<typename Scalar> 217*bf2c3715SXin Li typename AngleAxis<Scalar>::Matrix3 218*bf2c3715SXin Li EIGEN_DEVICE_FUNC AngleAxis<Scalar>::toRotationMatrix(void) const 219*bf2c3715SXin Li { 220*bf2c3715SXin Li EIGEN_USING_STD(sin) 221*bf2c3715SXin Li EIGEN_USING_STD(cos) 222*bf2c3715SXin Li Matrix3 res; 223*bf2c3715SXin Li Vector3 sin_axis = sin(m_angle) * m_axis; 224*bf2c3715SXin Li Scalar c = cos(m_angle); 225*bf2c3715SXin Li Vector3 cos1_axis = (Scalar(1)-c) * m_axis; 226*bf2c3715SXin Li 227*bf2c3715SXin Li Scalar tmp; 228*bf2c3715SXin Li tmp = cos1_axis.x() * m_axis.y(); 229*bf2c3715SXin Li res.coeffRef(0,1) = tmp - sin_axis.z(); 230*bf2c3715SXin Li res.coeffRef(1,0) = tmp + sin_axis.z(); 231*bf2c3715SXin Li 232*bf2c3715SXin Li tmp = cos1_axis.x() * m_axis.z(); 233*bf2c3715SXin Li res.coeffRef(0,2) = tmp + sin_axis.y(); 234*bf2c3715SXin Li res.coeffRef(2,0) = tmp - sin_axis.y(); 235*bf2c3715SXin Li 236*bf2c3715SXin Li tmp = cos1_axis.y() * m_axis.z(); 237*bf2c3715SXin Li res.coeffRef(1,2) = tmp - sin_axis.x(); 238*bf2c3715SXin Li res.coeffRef(2,1) = tmp + sin_axis.x(); 239*bf2c3715SXin Li 240*bf2c3715SXin Li res.diagonal() = (cos1_axis.cwiseProduct(m_axis)).array() + c; 241*bf2c3715SXin Li 242*bf2c3715SXin Li return res; 243*bf2c3715SXin Li } 244*bf2c3715SXin Li 245*bf2c3715SXin Li } // end namespace Eigen 246*bf2c3715SXin Li 247*bf2c3715SXin Li #endif // EIGEN_ANGLEAXIS_H 248