1
// This file is part of Eigen, a lightweight C++ template library
4
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
6
// Eigen is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU Lesser General Public
8
// License as published by the Free Software Foundation; either
9
// version 3 of the License, or (at your option) any later version.
11
// Alternatively, you can redistribute it and/or
12
// modify it under the terms of the GNU General Public License as
13
// published by the Free Software Foundation; either version 2 of
14
// the License, or (at your option) any later version.
16
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
17
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
19
// GNU General Public License for more details.
21
// You should have received a copy of the GNU Lesser General Public
22
// License and a copy of the GNU General Public License along with
23
// Eigen. If not, see <http://www.gnu.org/licenses/>.
25
#ifndef EIGEN_ANGLEAXIS_H
26
#define EIGEN_ANGLEAXIS_H
28
/** \geometry_module \ingroup Geometry_Module
32
* \brief Represents a 3D rotation as a rotation angle around an arbitrary 3D axis
34
* \param _Scalar the scalar type, i.e., the type of the coefficients.
36
* \warning When setting up an AngleAxis object, the axis vector \b must \b be \b normalized.
38
* The following two typedefs are provided for convenience:
39
* \li \c AngleAxisf for \c float
40
* \li \c AngleAxisd for \c double
42
* Combined with MatrixBase::Unit{X,Y,Z}, AngleAxis can be used to easily
43
* mimic Euler-angles. Here is an example:
44
* \include AngleAxis_mimic_euler.cpp
45
* Output: \verbinclude AngleAxis_mimic_euler.out
47
* \note This class is not aimed to be used to store a rotation transformation,
48
* but rather to make easier the creation of other rotation (Quaternion, rotation Matrix)
49
* and transformation objects.
51
* \sa class Quaternion, class Transform, MatrixBase::UnitX()
55
template<typename _Scalar> struct traits<AngleAxis<_Scalar> >
57
typedef _Scalar Scalar;
61
template<typename _Scalar>
62
class AngleAxis : public RotationBase<AngleAxis<_Scalar>,3>
64
typedef RotationBase<AngleAxis<_Scalar>,3> Base;
68
using Base::operator*;
71
/** the scalar type of the coefficients */
72
typedef _Scalar Scalar;
73
typedef Matrix<Scalar,3,3> Matrix3;
74
typedef Matrix<Scalar,3,1> Vector3;
75
typedef Quaternion<Scalar> QuaternionType;
84
/** Default constructor without initialization. */
86
/** Constructs and initialize the angle-axis rotation from an \a angle in radian
87
* and an \a axis which \b must \b be \b normalized.
89
* \warning If the \a axis vector is not normalized, then the angle-axis object
90
* represents an invalid rotation. */
91
template<typename Derived>
92
inline AngleAxis(Scalar angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle) {}
93
/** Constructs and initialize the angle-axis rotation from a quaternion \a q. */
94
template<typename QuatDerived> inline explicit AngleAxis(const QuaternionBase<QuatDerived>& q) { *this = q; }
95
/** Constructs and initialize the angle-axis rotation from a 3x3 rotation matrix. */
96
template<typename Derived>
97
inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
99
Scalar angle() const { return m_angle; }
100
Scalar& angle() { return m_angle; }
102
const Vector3& axis() const { return m_axis; }
103
Vector3& axis() { return m_axis; }
105
/** Concatenates two rotations */
106
inline QuaternionType operator* (const AngleAxis& other) const
107
{ return QuaternionType(*this) * QuaternionType(other); }
109
/** Concatenates two rotations */
110
inline QuaternionType operator* (const QuaternionType& other) const
111
{ return QuaternionType(*this) * other; }
113
/** Concatenates two rotations */
114
friend inline QuaternionType operator* (const QuaternionType& a, const AngleAxis& b)
115
{ return a * QuaternionType(b); }
117
/** \returns the inverse rotation, i.e., an angle-axis with opposite rotation angle */
118
AngleAxis inverse() const
119
{ return AngleAxis(-m_angle, m_axis); }
121
template<class QuatDerived>
122
AngleAxis& operator=(const QuaternionBase<QuatDerived>& q);
123
template<typename Derived>
124
AngleAxis& operator=(const MatrixBase<Derived>& m);
126
template<typename Derived>
127
AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m);
128
Matrix3 toRotationMatrix(void) const;
130
/** \returns \c *this with scalar type casted to \a NewScalarType
132
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
133
* then this function smartly returns a const reference to \c *this.
135
template<typename NewScalarType>
136
inline typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const
137
{ return typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); }
139
/** Copy constructor with scalar type conversion */
140
template<typename OtherScalarType>
141
inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other)
143
m_axis = other.axis().template cast<Scalar>();
144
m_angle = Scalar(other.angle());
147
inline static const AngleAxis Identity() { return AngleAxis(0, Vector3::UnitX()); }
149
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
150
* determined by \a prec.
152
* \sa MatrixBase::isApprox() */
153
bool isApprox(const AngleAxis& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
154
{ return m_axis.isApprox(other.m_axis, prec) && internal::isApprox(m_angle,other.m_angle, prec); }
157
/** \ingroup Geometry_Module
158
* single precision angle-axis type */
159
typedef AngleAxis<float> AngleAxisf;
160
/** \ingroup Geometry_Module
161
* double precision angle-axis type */
162
typedef AngleAxis<double> AngleAxisd;
164
/** Set \c *this from a \b unit quaternion.
165
* The axis is normalized.
167
* \warning As any other method dealing with quaternion, if the input quaternion
168
* is not normalized then the result is undefined.
170
template<typename Scalar>
171
template<typename QuatDerived>
172
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q)
177
Scalar n2 = q.vec().squaredNorm();
178
if (n2 < NumTraits<Scalar>::dummy_precision()*NumTraits<Scalar>::dummy_precision())
185
m_angle = Scalar(2)*acos(min(max(Scalar(-1),q.w()),Scalar(1)));
186
m_axis = q.vec() / internal::sqrt(n2);
191
/** Set \c *this from a 3x3 rotation matrix \a mat.
193
template<typename Scalar>
194
template<typename Derived>
195
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const MatrixBase<Derived>& mat)
197
// Since a direct conversion would not be really faster,
198
// let's use the robust Quaternion implementation:
199
return *this = QuaternionType(mat);
203
* \brief Sets \c *this from a 3x3 rotation matrix.
205
template<typename Scalar>
206
template<typename Derived>
207
AngleAxis<Scalar>& AngleAxis<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
209
return *this = QuaternionType(mat);
212
/** Constructs and \returns an equivalent 3x3 rotation matrix.
214
template<typename Scalar>
215
typename AngleAxis<Scalar>::Matrix3
216
AngleAxis<Scalar>::toRotationMatrix(void) const
219
Vector3 sin_axis = internal::sin(m_angle) * m_axis;
220
Scalar c = internal::cos(m_angle);
221
Vector3 cos1_axis = (Scalar(1)-c) * m_axis;
224
tmp = cos1_axis.x() * m_axis.y();
225
res.coeffRef(0,1) = tmp - sin_axis.z();
226
res.coeffRef(1,0) = tmp + sin_axis.z();
228
tmp = cos1_axis.x() * m_axis.z();
229
res.coeffRef(0,2) = tmp + sin_axis.y();
230
res.coeffRef(2,0) = tmp - sin_axis.y();
232
tmp = cos1_axis.y() * m_axis.z();
233
res.coeffRef(1,2) = tmp - sin_axis.x();
234
res.coeffRef(2,1) = tmp + sin_axis.x();
236
res.diagonal() = (cos1_axis.cwiseProduct(m_axis)).array() + c;
241
#endif // EIGEN_ANGLEAXIS_H