12 #include <Eigen/Geometry> 24 template<
typename QuatType>
void check_slerp(
const QuatType& q0,
const QuatType&
q1)
30 Scalar largeEps = test_precision<Scalar>();
32 Scalar theta_tot = AA(q1*q0.inverse()).angle();
37 QuatType
q = q0.slerp(
t,q1);
38 Scalar
theta = AA(q*q0.inverse()).angle();
40 if(theta_tot==0)
VERIFY(theta_tot==0);
41 else VERIFY(
abs(theta -
t * theta_tot) < largeEps);
45 template<
typename Scalar,
int Options>
void quaternion(
void)
56 Scalar largeEps = test_precision<Scalar>();
62 Vector3
v0 = Vector3::Random(),
63 v1 = Vector3::Random(),
64 v2 = Vector3::Random(),
65 v3 = Vector3::Random();
73 VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
74 q1.coeffs().setRandom();
80 q1 = AngleAxisx(a, v0.normalized());
81 q2 = AngleAxisx(a,
v1.normalized());
84 Scalar refangle =
abs(AngleAxisx(q1.inverse()*
q2).angle());
88 if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
96 q1.toRotationMatrix() * q2.toRotationMatrix() *
v2);
99 || !(q2 * q1 * v2).
isApprox(q1.toRotationMatrix() * q2.toRotationMatrix() *
v2));
101 q2 = q1.toRotationMatrix();
106 Quaternionx
q3(rot1.transpose()*rot1);
111 AngleAxisx aa = AngleAxisx(q1);
116 if (
abs(aa.angle()) > 5*test_precision<Scalar>()
117 && (aa.axis() - v1.normalized()).norm() <
Scalar(1.99)
118 && (aa.axis() + v1.normalized()).norm() <
Scalar(1.99))
135 VERIFY_IS_APPROX( v2.normalized(),(Quaternionx::FromTwoVectors(v1, v2)*
v1).normalized());
136 VERIFY_IS_APPROX( v1.normalized(),(Quaternionx::FromTwoVectors(v1, v1)*
v1).normalized());
137 VERIFY_IS_APPROX(-v1.normalized(),(Quaternionx::FromTwoVectors(v1,-v1)*
v1).normalized());
156 Quaternionx *
q =
new Quaternionx;
159 q1 = Quaternionx::UnitRandom();
160 q2 = Quaternionx::UnitRandom();
163 q1 = AngleAxisx(
b, v1.normalized());
167 q1 = AngleAxisx(
b, v1.normalized());
168 q2 = AngleAxisx(-
b, -v1.normalized());
171 q1 = Quaternionx::UnitRandom();
172 q2.coeffs() = -q1.coeffs();
179 typedef Map<Quaternion<Scalar> > MQuaternionUA;
180 typedef Map<const Quaternion<Scalar> > MCQuaternionUA;
185 Vector3
v0 = Vector3::Random(),
186 v1 = Vector3::Random();
192 Scalar* array3unaligned = array3+1;
194 MQuaternionA mq1(array1);
195 MCQuaternionA mcq1(array1);
196 MQuaternionA mq2(array2);
197 MQuaternionUA mq3(array3unaligned);
198 MCQuaternionUA mcq3(array3unaligned);
201 mq1 = AngleAxisx(a, v0.normalized());
205 Quaternionx
q1 = mq1;
206 Quaternionx
q2 = mq2;
207 Quaternionx
q3 = mq3;
208 Quaternionx q4 = MCQuaternionUA(array3unaligned);
213 #ifdef EIGEN_VECTORIZE 214 if(internal::packet_traits<Scalar>::Vectorizable)
236 VERIFY_IS_APPROX(mcq3.coeffs().x() + mcq3.coeffs().y() + mcq3.coeffs().z() + mcq3.coeffs().w(), mcq3.coeffs().sum());
237 VERIFY_IS_APPROX(mcq3.x() + mcq3.y() + mcq3.z() + mcq3.w(), mcq3.coeffs().sum());
239 const Quaternionx& cq3(q3);
240 VERIFY( &cq3.x() == &q3.x() );
241 const MQuaternionUA& cmq3(mq3);
242 VERIFY( &cmq3.x() == &mq3.x() );
256 Scalar* arrayunaligned = array3+1;
258 QuaternionA *
q1 = ::new(reinterpret_cast<void*>(array1)) QuaternionA;
259 QuaternionUA *
q2 = ::new(reinterpret_cast<void*>(array2)) QuaternionUA;
260 QuaternionUA *
q3 = ::new(reinterpret_cast<void*>(arrayunaligned)) QuaternionUA;
262 q1->coeffs().setRandom();
268 #if defined(EIGEN_VECTORIZE) && EIGEN_MAX_STATIC_ALIGN_BYTES>0 291 CALL_SUBTEST_1(( quaternion<float,AutoAlign>() ));
293 CALL_SUBTEST_2(( quaternion<double,AutoAlign>() ));
295 CALL_SUBTEST_3(( quaternion<float,DontAlign>() ));
296 CALL_SUBTEST_4(( quaternion<double,DontAlign>() ));
297 CALL_SUBTEST_5(( quaternionAlignment<float>() ));
298 CALL_SUBTEST_6(( quaternionAlignment<double>() ));
299 CALL_SUBTEST_1( mapQuaternion<float>() );
300 CALL_SUBTEST_2( mapQuaternion<double>() );
#define VERIFY_RAISES_ASSERT(a)
A matrix or vector expression mapping an existing array of data.
Quaternion< double > Quaterniond
const unsigned int LvalueBit
#define VERIFY_IS_APPROX(a, b)
Eigen::Triplet< double > T
Array< double, 1, 3 > e(1./3., 0.5, 2.)
EIGEN_DEVICE_FUNC const Scalar & q
#define VERIFY_IS_MUCH_SMALLER_THAN(a, b)
EIGEN_DEVICE_FUNC const AcosReturnType acos() const
A small structure to hold a non zero as a triplet (i,j,value).
The quaternion class used to represent 3D orientations and rotations.
void test_geo_quaternion()
#define VERIFY_IS_NOT_APPROX(a, b)
void check_const_correctness(const PlainObjectType &)
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
void quaternionAlignment(void)
Map< Matrix< T, Dynamic, Dynamic, ColMajor >, 0, OuterStride<> > matrix(T *data, int rows, int cols, int stride)
EIGEN_DEVICE_FUNC bool isApprox(const Scalar &x, const Scalar &y, const typename NumTraits< Scalar >::Real &precision=NumTraits< Scalar >::dummy_precision())
void check_slerp(const QuatType &q0, const QuatType &q1)
Represents a 3D rotation as a rotation angle around an arbitrary 3D axis.
Quaternion< float > Quaternionf