diff options
author | Gael Guennebaud <g.gael@free.fr> | 2014-06-20 15:09:42 +0200 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2014-06-20 15:09:42 +0200 |
commit | 963d338922e9ef1addcd29c1b43e9b66243207c0 (patch) | |
tree | beae315b55c989467944572714325dda85baacdb /Eigen | |
parent | 98ef44fe55925ba8f144889c0ec42be9bf572cc3 (diff) |
Fix bug #827: improve accuracy of quaternion to angle-axis conversion
Diffstat (limited to 'Eigen')
-rw-r--r-- | Eigen/src/Geometry/AngleAxis.h | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/Eigen/src/Geometry/AngleAxis.h b/Eigen/src/Geometry/AngleAxis.h index b42048c55..636712c2b 100644 --- a/Eigen/src/Geometry/AngleAxis.h +++ b/Eigen/src/Geometry/AngleAxis.h @@ -77,7 +77,9 @@ public: * represents an invalid rotation. */ template<typename Derived> inline AngleAxis(const Scalar& angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle) {} - /** Constructs and initialize the angle-axis rotation from a quaternion \a q. */ + /** Constructs and initialize the angle-axis rotation from a quaternion \a q. + * This function implicitly normalizes the quaternion \a q. + */ template<typename QuatDerived> inline explicit AngleAxis(const QuaternionBase<QuatDerived>& q) { *this = q; } /** Constructs and initialize the angle-axis rotation from a 3x3 rotation matrix. */ template<typename Derived> @@ -149,29 +151,27 @@ typedef AngleAxis<float> AngleAxisf; typedef AngleAxis<double> AngleAxisd; /** Set \c *this from a \b unit quaternion. - * The axis is normalized. + * The resulting axis is normalized. * - * \warning As any other method dealing with quaternion, if the input quaternion - * is not normalized then the result is undefined. + * This function implicitly normalizes the quaternion \a q. */ template<typename Scalar> template<typename QuatDerived> AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q) { - using std::acos; - EIGEN_USING_STD_MATH(min); - EIGEN_USING_STD_MATH(max); - using std::sqrt; - Scalar n2 = q.vec().squaredNorm(); - if (n2 < NumTraits<Scalar>::dummy_precision()*NumTraits<Scalar>::dummy_precision()) + using std::atan2; + Scalar n = q.vec().norm(); + if(n<NumTraits<Scalar>::epsilon()) + n = q.vec().stableNorm(); + if (n > Scalar(0)) { - m_angle = Scalar(0); - m_axis << Scalar(1), Scalar(0), Scalar(0); + m_angle = Scalar(2)*atan2(n, q.w()); + m_axis = q.vec() / n; } else { - m_angle = Scalar(2)*acos((min)((max)(Scalar(-1),q.w()),Scalar(1))); - m_axis = q.vec() / sqrt(n2); + m_angle = 0; + m_axis << 1, 0, 0; } return *this; } |