bug #823: add static method to Quaternion for uniform random rotations.

This commit is contained in:
Joseph Mirabel 2016-05-20 13:15:40 +02:00
parent 2f656ce447
commit eb0cc2573a
2 changed files with 25 additions and 4 deletions

View File

@ -271,6 +271,8 @@ public:
explicit inline Quaternion(const Quaternion<OtherScalar, OtherOptions>& other) explicit inline Quaternion(const Quaternion<OtherScalar, OtherOptions>& other)
{ m_coeffs = other.coeffs().template cast<Scalar>(); } { m_coeffs = other.coeffs().template cast<Scalar>(); }
static Quaternion UniformRandom();
template<typename Derived1, typename Derived2> template<typename Derived1, typename Derived2>
static Quaternion FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b); static Quaternion FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
@ -609,6 +611,26 @@ inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Deri
return derived(); return derived();
} }
/** Returns a random quaternion following a uniform distribution law.
*
* \returns resulting quaternion
*
* \note The implementation is based on http://planning.cs.uiuc.edu/node198.html
*/
template<typename Scalar, int Options>
Quaternion<Scalar,Options> Quaternion<Scalar,Options>::UniformRandom()
{
const Scalar u1 = internal::random<Scalar>(0,1),
u2 = internal::random<Scalar>(0, 2*M_PI),
u3 = internal::random<Scalar>(0, 2*M_PI);
const Scalar a = std::sqrt (1 - u1),
b = std::sqrt (u1);
return Quaternion (a * std::sin (u2),
a * std::cos (u2),
b * std::sin (u3),
b * std::cos (u3));
}
/** Returns a quaternion representing a rotation between /** Returns a quaternion representing a rotation between
* the two arbitrary vectors \a a and \a b. In other words, the built * the two arbitrary vectors \a a and \a b. In other words, the built

View File

@ -50,7 +50,6 @@ template<typename Scalar, int Options> void quaternion(void)
using std::abs; using std::abs;
typedef Matrix<Scalar,3,1> Vector3; typedef Matrix<Scalar,3,1> Vector3;
typedef Matrix<Scalar,3,3> Matrix3; typedef Matrix<Scalar,3,3> Matrix3;
typedef Matrix<Scalar,4,1> Vector4;
typedef Quaternion<Scalar,Options> Quaternionx; typedef Quaternion<Scalar,Options> Quaternionx;
typedef AngleAxis<Scalar> AngleAxisx; typedef AngleAxis<Scalar> AngleAxisx;
@ -157,8 +156,8 @@ template<typename Scalar, int Options> void quaternion(void)
Quaternionx *q = new Quaternionx; Quaternionx *q = new Quaternionx;
delete q; delete q;
q1 = AngleAxisx(a, v0.normalized()); q1 = Quaternionx::UniformRandom ();
q2 = AngleAxisx(b, v1.normalized()); q2 = Quaternionx::UniformRandom ();
check_slerp(q1,q2); check_slerp(q1,q2);
q1 = AngleAxisx(b, v1.normalized()); q1 = AngleAxisx(b, v1.normalized());
@ -169,7 +168,7 @@ template<typename Scalar, int Options> void quaternion(void)
q2 = AngleAxisx(-b, -v1.normalized()); q2 = AngleAxisx(-b, -v1.normalized());
check_slerp(q1,q2); check_slerp(q1,q2);
q1.coeffs() = Vector4::Random().normalized(); q1 = Quaternionx::UniformRandom ();
q2.coeffs() = -q1.coeffs(); q2.coeffs() = -q1.coeffs();
check_slerp(q1,q2); check_slerp(q1,q2);
} }