aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2014-06-20 15:09:42 +0200
committerGravatar Gael Guennebaud <g.gael@free.fr>2014-06-20 15:09:42 +0200
commit963d338922e9ef1addcd29c1b43e9b66243207c0 (patch)
treebeae315b55c989467944572714325dda85baacdb /Eigen
parent98ef44fe55925ba8f144889c0ec42be9bf572cc3 (diff)
Fix bug #827: improve accuracy of quaternion to angle-axis conversion
Diffstat (limited to 'Eigen')
-rw-r--r--Eigen/src/Geometry/AngleAxis.h28
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;
}