Eigen  5.0.1-dev+60122df6
 
Loading...
Searching...
No Matches
Quaternion.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
5// Copyright (C) 2009 Mathieu Gautier <mathieu.gautier@cea.fr>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10
11#ifndef EIGEN_QUATERNION_H
12#define EIGEN_QUATERNION_H
13// IWYU pragma: private
14#include "./InternalHeaderCheck.h"
15
16namespace Eigen {
17
18/***************************************************************************
19 * Definition of QuaternionBase<Derived>
20 * The implementation is at the end of the file
21 ***************************************************************************/
22
23namespace internal {
24template <typename Other, int OtherRows = Other::RowsAtCompileTime, int OtherCols = Other::ColsAtCompileTime>
25struct quaternionbase_assign_impl;
26}
27
34template <class Derived>
35class QuaternionBase : public RotationBase<Derived, 3> {
36 public:
37 typedef RotationBase<Derived, 3> Base;
38
39 using Base::operator*;
40 using Base::derived;
41
42 typedef typename internal::traits<Derived>::Scalar Scalar;
43 typedef typename NumTraits<Scalar>::Real RealScalar;
44 typedef typename internal::traits<Derived>::Coefficients Coefficients;
45 typedef typename Coefficients::CoeffReturnType CoeffReturnType;
46 typedef std::conditional_t<bool(internal::traits<Derived>::Flags& LvalueBit), Scalar&, CoeffReturnType>
47 NonConstCoeffReturnType;
48
49 enum { Flags = Eigen::internal::traits<Derived>::Flags };
50
51 // typedef typename Matrix<Scalar,4,1> Coefficients;
58
60 EIGEN_DEVICE_FUNC constexpr CoeffReturnType x() const { return this->derived().coeffs().coeff(0); }
62 EIGEN_DEVICE_FUNC constexpr CoeffReturnType y() const { return this->derived().coeffs().coeff(1); }
64 EIGEN_DEVICE_FUNC constexpr CoeffReturnType z() const { return this->derived().coeffs().coeff(2); }
66 EIGEN_DEVICE_FUNC constexpr CoeffReturnType w() const { return this->derived().coeffs().coeff(3); }
67
69 EIGEN_DEVICE_FUNC constexpr NonConstCoeffReturnType x() { return this->derived().coeffs().x(); }
71 EIGEN_DEVICE_FUNC constexpr NonConstCoeffReturnType y() { return this->derived().coeffs().y(); }
73 EIGEN_DEVICE_FUNC constexpr NonConstCoeffReturnType z() { return this->derived().coeffs().z(); }
75 EIGEN_DEVICE_FUNC constexpr NonConstCoeffReturnType w() { return this->derived().coeffs().w(); }
76
78 EIGEN_DEVICE_FUNC inline const VectorBlock<const Coefficients, 3> vec() const { return coeffs().template head<3>(); }
79
81 EIGEN_DEVICE_FUNC inline VectorBlock<Coefficients, 3> vec() { return coeffs().template head<3>(); }
82
84 EIGEN_DEVICE_FUNC inline const typename internal::traits<Derived>::Coefficients& coeffs() const {
85 return derived().coeffs();
86 }
87
96 EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Coefficients coeffsScalarFirst() const {
97 return derived().coeffsScalarFirst();
98 }
99
107 EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Coefficients coeffsScalarLast() const {
108 return derived().coeffsScalarLast();
109 }
110
112 EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Coefficients& coeffs() { return derived().coeffs(); }
113
114 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE QuaternionBase<Derived>& operator=(const QuaternionBase<Derived>& other);
115 template <class OtherDerived>
116 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const QuaternionBase<OtherDerived>& other);
117
118 // disabled this copy operator as it is giving very strange compilation errors when compiling
119 // test_stdvector with GCC 4.4.2. This looks like a GCC bug though, so feel free to re-enable it if it's
120 // useful; however notice that we already have the templated operator= above and e.g. in MatrixBase
121 // we didn't have to add, in addition to templated operator=, such a non-templated copy operator.
122 // Derived& operator=(const QuaternionBase& other)
123 // { return operator=<Derived>(other); }
124
125 EIGEN_DEVICE_FUNC Derived& operator=(const AngleAxisType& aa);
126 template <class OtherDerived>
127 EIGEN_DEVICE_FUNC Derived& operator=(const MatrixBase<OtherDerived>& m);
128
132 EIGEN_DEVICE_FUNC static inline Quaternion<Scalar> Identity() {
133 return Quaternion<Scalar>(Scalar(1), Scalar(0), Scalar(0), Scalar(0));
134 }
135
138 EIGEN_DEVICE_FUNC inline QuaternionBase& setIdentity() {
139 coeffs() << Scalar(0), Scalar(0), Scalar(0), Scalar(1);
140 return *this;
141 }
142
146 EIGEN_DEVICE_FUNC inline Scalar squaredNorm() const { return coeffs().squaredNorm(); }
147
151 EIGEN_DEVICE_FUNC inline Scalar norm() const { return coeffs().norm(); }
152
155 EIGEN_DEVICE_FUNC inline void normalize() { coeffs().normalize(); }
158 EIGEN_DEVICE_FUNC inline Quaternion<Scalar> normalized() const { return Quaternion<Scalar>(coeffs().normalized()); }
159
165 template <class OtherDerived>
166 EIGEN_DEVICE_FUNC inline Scalar dot(const QuaternionBase<OtherDerived>& other) const {
167 return coeffs().dot(other.coeffs());
168 }
169
170 template <class OtherDerived>
171 EIGEN_DEVICE_FUNC Scalar angularDistance(const QuaternionBase<OtherDerived>& other) const;
172
174 EIGEN_DEVICE_FUNC inline Matrix3 toRotationMatrix() const;
175
177 template <typename Derived1, typename Derived2>
178 EIGEN_DEVICE_FUNC Derived& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
179
180 template <class OtherDerived>
181 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Quaternion<Scalar> operator*(const QuaternionBase<OtherDerived>& q) const;
182 template <class OtherDerived>
183 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*=(const QuaternionBase<OtherDerived>& q);
184
186 EIGEN_DEVICE_FUNC Quaternion<Scalar> inverse() const;
187
189 EIGEN_DEVICE_FUNC Quaternion<Scalar> conjugate() const;
190
191 template <class OtherDerived>
192 EIGEN_DEVICE_FUNC Quaternion<Scalar> slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const;
193
198 template <class OtherDerived>
199 EIGEN_DEVICE_FUNC inline bool operator==(const QuaternionBase<OtherDerived>& other) const {
200 return coeffs() == other.coeffs();
201 }
202
207 template <class OtherDerived>
208 EIGEN_DEVICE_FUNC inline bool operator!=(const QuaternionBase<OtherDerived>& other) const {
209 return coeffs() != other.coeffs();
210 }
211
216 template <class OtherDerived>
217 EIGEN_DEVICE_FUNC bool isApprox(const QuaternionBase<OtherDerived>& other,
218 const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const {
219 return coeffs().isApprox(other.coeffs(), prec);
220 }
221
223 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Vector3 _transformVector(const Vector3& v) const;
224
225#ifdef EIGEN_PARSED_BY_DOXYGEN
231 template <typename NewScalarType>
232 EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<Derived, Quaternion<NewScalarType> >::type cast() const;
233
234#else
235
236 template <typename NewScalarType>
237 EIGEN_DEVICE_FUNC inline std::enable_if_t<internal::is_same<Scalar, NewScalarType>::value, const Derived&> cast()
238 const {
239 return derived();
240 }
241
242 template <typename NewScalarType>
243 EIGEN_DEVICE_FUNC inline std::enable_if_t<!internal::is_same<Scalar, NewScalarType>::value,
245 cast() const {
247 }
248#endif
249
250#ifndef EIGEN_NO_IO
251 friend std::ostream& operator<<(std::ostream& s, const QuaternionBase<Derived>& q) {
252 s << q.x() << "i + " << q.y() << "j + " << q.z() << "k"
253 << " + " << q.w();
254 return s;
255 }
256#endif
257
258#ifdef EIGEN_QUATERNIONBASE_PLUGIN
259#include EIGEN_QUATERNIONBASE_PLUGIN
260#endif
261 protected:
262 EIGEN_DEFAULT_COPY_CONSTRUCTOR(QuaternionBase)
263 EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(QuaternionBase)
264};
265
266/***************************************************************************
267 * Definition/implementation of Quaternion<Scalar>
268 ***************************************************************************/
269
296
297namespace internal {
298template <typename Scalar_, int Options_>
299struct traits<Quaternion<Scalar_, Options_> > {
300 typedef Quaternion<Scalar_, Options_> PlainObject;
301 typedef Scalar_ Scalar;
302 typedef Matrix<Scalar_, 4, 1, Options_> Coefficients;
303 enum { Alignment = internal::traits<Coefficients>::Alignment, Flags = LvalueBit };
304};
305} // namespace internal
306
307template <typename Scalar_, int Options_>
308class Quaternion : public QuaternionBase<Quaternion<Scalar_, Options_> > {
309 public:
311 enum { NeedsAlignment = internal::traits<Quaternion>::Alignment > 0 };
312
313 typedef Scalar_ Scalar;
314
315 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Quaternion)
316 using Base::operator*=;
317
318 typedef typename internal::traits<Quaternion>::Coefficients Coefficients;
319 typedef typename Base::AngleAxisType AngleAxisType;
320
322 EIGEN_DEVICE_FUNC inline Quaternion() {}
323
331 EIGEN_DEVICE_FUNC inline Quaternion(const Scalar& w, const Scalar& x, const Scalar& y, const Scalar& z)
332 : m_coeffs(x, y, z, w) {}
333
337 template <typename Derived>
338 EIGEN_DEVICE_FUNC inline Quaternion(const Scalar& w, const Eigen::MatrixBase<Derived>& vec)
339 : m_coeffs(vec.x(), vec.y(), vec.z(), w) {
340 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived, 3);
341 }
342
344 EIGEN_DEVICE_FUNC explicit inline Quaternion(const Scalar* data) : m_coeffs(data) {}
345
347 template <class Derived>
348 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Quaternion(const QuaternionBase<Derived>& other) {
349 this->Base::operator=(other);
350 }
351
353 EIGEN_DEVICE_FUNC explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; }
354
359 template <typename Derived>
360 EIGEN_DEVICE_FUNC explicit inline Quaternion(const MatrixBase<Derived>& other) {
361 *this = other;
362 }
363
365 template <typename OtherScalar, int OtherOptions>
366 EIGEN_DEVICE_FUNC explicit inline Quaternion(const Quaternion<OtherScalar, OtherOptions>& other) {
367 m_coeffs = other.coeffs().template cast<Scalar>();
368 }
369
370 // We define a copy constructor, which means we don't get an implicit move constructor or assignment operator.
372 EIGEN_DEVICE_FUNC inline Quaternion(Quaternion&& other) noexcept(std::is_nothrow_move_constructible<Scalar>::value)
373 : m_coeffs(std::move(other.coeffs())) {}
374
376 EIGEN_DEVICE_FUNC Quaternion& operator=(Quaternion&& other) noexcept(std::is_nothrow_move_assignable<Scalar>::value) {
377 m_coeffs = std::move(other.coeffs());
378 return *this;
379 }
380
381 EIGEN_DEVICE_FUNC static Quaternion UnitRandom();
382
383 EIGEN_DEVICE_FUNC static Quaternion FromCoeffsScalarLast(const Scalar& x, const Scalar& y, const Scalar& z,
384 const Scalar& w);
385
386 EIGEN_DEVICE_FUNC static Quaternion FromCoeffsScalarFirst(const Scalar& w, const Scalar& x, const Scalar& y,
387 const Scalar& z);
388
389 template <typename Derived1, typename Derived2>
390 EIGEN_DEVICE_FUNC static Quaternion FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
391
392 EIGEN_DEVICE_FUNC inline Coefficients& coeffs() { return m_coeffs; }
393 EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs; }
394
395 EIGEN_DEVICE_FUNC inline Coefficients coeffsScalarLast() const { return m_coeffs; }
396
397 EIGEN_DEVICE_FUNC inline Coefficients coeffsScalarFirst() const {
398 return {m_coeffs.w(), m_coeffs.x(), m_coeffs.y(), m_coeffs.z()};
399 }
400 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(bool(NeedsAlignment))
401
402#ifdef EIGEN_QUATERNION_PLUGIN
403#include EIGEN_QUATERNION_PLUGIN
404#endif
405
406 protected:
407 Coefficients m_coeffs;
408
409#ifndef EIGEN_PARSED_BY_DOXYGEN
410 EIGEN_STATIC_ASSERT((Options_ & DontAlign) == Options_, INVALID_MATRIX_TEMPLATE_PARAMETERS)
411#endif
412};
413
420
421/***************************************************************************
422 * Specialization of Map<Quaternion<Scalar>>
423 ***************************************************************************/
424
425namespace internal {
426template <typename Scalar_, int Options_>
427struct traits<Map<Quaternion<Scalar_>, Options_> >
428 : traits<Quaternion<Scalar_, (int(Options_) & Aligned) == Aligned ? AutoAlign : DontAlign> > {
429 typedef Map<Matrix<Scalar_, 4, 1>, Options_> Coefficients;
430};
431} // namespace internal
432
433namespace internal {
434template <typename Scalar_, int Options_>
435struct traits<Map<const Quaternion<Scalar_>, Options_> >
436 : traits<Quaternion<Scalar_, (int(Options_) & Aligned) == Aligned ? AutoAlign : DontAlign> > {
437 typedef Map<const Matrix<Scalar_, 4, 1>, Options_> Coefficients;
438 typedef traits<Quaternion<Scalar_, (int(Options_) & Aligned) == Aligned ? AutoAlign : DontAlign> > TraitsBase;
439 enum { Flags = TraitsBase::Flags & ~LvalueBit };
440};
441} // namespace internal
442
454template <typename Scalar_, int Options_>
455class Map<const Quaternion<Scalar_>, Options_> : public QuaternionBase<Map<const Quaternion<Scalar_>, Options_> > {
456 public:
457 typedef QuaternionBase<Map<const Quaternion<Scalar_>, Options_> > Base;
458
459 typedef Scalar_ Scalar;
460 typedef typename internal::traits<Map>::Coefficients Coefficients;
461 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
462 using Base::operator*=;
463
470 EIGEN_DEVICE_FUNC explicit EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
471
472 EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs; }
473
474 EIGEN_DEVICE_FUNC inline Coefficients coeffsScalarLast() const { return m_coeffs; }
475
476 EIGEN_DEVICE_FUNC inline Coefficients coeffsScalarFirst() const {
477 return {m_coeffs.w(), m_coeffs.x(), m_coeffs.y(), m_coeffs.z()};
478 }
479
480 protected:
481 const Coefficients m_coeffs;
482};
483
495template <typename Scalar_, int Options_>
496class Map<Quaternion<Scalar_>, Options_> : public QuaternionBase<Map<Quaternion<Scalar_>, Options_> > {
497 public:
498 typedef QuaternionBase<Map<Quaternion<Scalar_>, Options_> > Base;
499
500 typedef Scalar_ Scalar;
501 typedef typename internal::traits<Map>::Coefficients Coefficients;
502 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
503 using Base::operator*=;
504
511 EIGEN_DEVICE_FUNC explicit EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
512
513 EIGEN_DEVICE_FUNC inline Coefficients& coeffs() { return m_coeffs; }
514 EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs; }
515
516 EIGEN_DEVICE_FUNC inline Coefficients coeffsScalarLast() const { return m_coeffs; }
517
518 EIGEN_DEVICE_FUNC inline Coefficients coeffsScalarFirst() const {
519 return {m_coeffs.w(), m_coeffs.x(), m_coeffs.y(), m_coeffs.z()};
520 }
521
522 protected:
523 Coefficients m_coeffs;
524};
525
538
539/***************************************************************************
540 * Implementation of QuaternionBase methods
541 ***************************************************************************/
542
543// Generic Quaternion * Quaternion product
544// This product can be specialized for a given architecture via the Arch template argument.
545namespace internal {
546template <int Arch, class Derived1, class Derived2, typename Scalar>
547struct quat_product {
548 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived1>& a,
549 const QuaternionBase<Derived2>& b) {
550 return Quaternion<Scalar>(a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
551 a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
552 a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
553 a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x());
554 }
555};
556} // namespace internal
557
559template <class Derived>
560template <class OtherDerived>
561EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Quaternion<typename internal::traits<Derived>::Scalar>
562QuaternionBase<Derived>::operator*(const QuaternionBase<OtherDerived>& other) const {
563 EIGEN_STATIC_ASSERT(
564 (internal::is_same<typename Derived::Scalar, typename OtherDerived::Scalar>::value),
565 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
566 return internal::quat_product<Architecture::Target, Derived, OtherDerived,
567 typename internal::traits<Derived>::Scalar>::run(*this, other);
568}
569
571template <class Derived>
572template <class OtherDerived>
573EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*=(
574 const QuaternionBase<OtherDerived>& other) {
575 derived() = derived() * other.derived();
576 return derived();
577}
578
586template <class Derived>
587EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
589 // Note that this algorithm comes from the optimization by hand
590 // of the conversion to a Matrix followed by a Matrix/Vector product.
591 // It appears to be much faster than the common algorithm found
592 // in the literature (30 versus 39 flops). It also requires two
593 // Vector3 as temporaries.
594 Vector3 uv = this->vec().cross(v);
595 uv += uv;
596 return v + this->w() * uv + this->vec().cross(uv);
597}
598
599template <class Derived>
600EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(
601 const QuaternionBase<Derived>& other) {
602 coeffs() = other.coeffs();
603 return derived();
604}
605
606template <class Derived>
607template <class OtherDerived>
608EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(
609 const QuaternionBase<OtherDerived>& other) {
610 coeffs() = other.coeffs();
611 return derived();
612}
613
616template <class Derived>
617EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisType& aa) {
618 EIGEN_USING_STD(cos)
619 EIGEN_USING_STD(sin)
620 Scalar ha = Scalar(0.5) * aa.angle(); // Scalar(0.5) to suppress precision loss warnings
621 this->w() = cos(ha);
622 this->vec() = sin(ha) * aa.axis();
623 return derived();
624}
625
631
632template <class Derived>
633template <class MatrixDerived>
634EIGEN_DEVICE_FUNC inline Derived& QuaternionBase<Derived>::operator=(const MatrixBase<MatrixDerived>& xpr) {
635 EIGEN_STATIC_ASSERT(
636 (internal::is_same<typename Derived::Scalar, typename MatrixDerived::Scalar>::value),
637 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
638 internal::quaternionbase_assign_impl<MatrixDerived>::run(*this, xpr.derived());
639 return derived();
640}
641
645template <class Derived>
647 void) const {
648 // NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!)
649 // if not inlined then the cost of the return by value is huge ~ +35%,
650 // however, not inlining this function is an order of magnitude slower, so
651 // it has to be inlined, and so the return by value is not an issue
652 Matrix3 res;
653
654 const Scalar tx = Scalar(2) * this->x();
655 const Scalar ty = Scalar(2) * this->y();
656 const Scalar tz = Scalar(2) * this->z();
657 const Scalar twx = tx * this->w();
658 const Scalar twy = ty * this->w();
659 const Scalar twz = tz * this->w();
660 const Scalar txx = tx * this->x();
661 const Scalar txy = ty * this->x();
662 const Scalar txz = tz * this->x();
663 const Scalar tyy = ty * this->y();
664 const Scalar tyz = tz * this->y();
665 const Scalar tzz = tz * this->z();
666
667 res.coeffRef(0, 0) = Scalar(1) - (tyy + tzz);
668 res.coeffRef(0, 1) = txy - twz;
669 res.coeffRef(0, 2) = txz + twy;
670 res.coeffRef(1, 0) = txy + twz;
671 res.coeffRef(1, 1) = Scalar(1) - (txx + tzz);
672 res.coeffRef(1, 2) = tyz - twx;
673 res.coeffRef(2, 0) = txz - twy;
674 res.coeffRef(2, 1) = tyz + twx;
675 res.coeffRef(2, 2) = Scalar(1) - (txx + tyy);
676
677 return res;
678}
679
690template <class Derived>
691template <typename Derived1, typename Derived2>
692EIGEN_DEVICE_FUNC inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a,
693 const MatrixBase<Derived2>& b) {
694 EIGEN_USING_STD(sqrt)
695 Vector3 v0 = a.normalized();
696 Vector3 v1 = b.normalized();
697 Scalar c = v1.dot(v0);
698
699 // if dot == -1, vectors are nearly opposites
700 // => accurately compute the rotation axis by computing the
701 // intersection of the two planes. This is done by solving:
702 // x^T v0 = 0
703 // x^T v1 = 0
704 // under the constraint:
705 // ||x|| = 1
706 // which yields a singular value problem
707 if (c < Scalar(-1) + NumTraits<Scalar>::dummy_precision()) {
708 c = numext::maxi(c, Scalar(-1));
710 m << v0.transpose(), v1.transpose();
712 Vector3 axis = svd.matrixV().col(2);
713
714 Scalar w2 = (Scalar(1) + c) * Scalar(0.5);
715 this->w() = sqrt(w2);
716 this->vec() = axis * sqrt(Scalar(1) - w2);
717 return derived();
718 }
719 Vector3 axis = v0.cross(v1);
720 Scalar s = sqrt((Scalar(1) + c) * Scalar(2));
721 Scalar invs = Scalar(1) / s;
722 this->vec() = axis * invs;
723 this->w() = s * Scalar(0.5);
724
725 return derived();
726}
727
732template <typename Scalar, int Options>
734 EIGEN_USING_STD(sqrt)
735 EIGEN_USING_STD(sin)
736 EIGEN_USING_STD(cos)
737 const Scalar u1 = internal::random<Scalar>(0, 1), u2 = internal::random<Scalar>(0, 2 * EIGEN_PI),
738 u3 = internal::random<Scalar>(0, 2 * EIGEN_PI);
739 const Scalar a = sqrt(Scalar(1) - u1), b = sqrt(u1);
740 return Quaternion(a * sin(u2), a * cos(u2), b * sin(u3), b * cos(u3));
741}
742
749template <typename Scalar, int Options>
751 const Scalar& y,
752 const Scalar& z,
753 const Scalar& w) {
754 return Quaternion(w, x, y, z);
755}
756
764template <typename Scalar, int Options>
766 const Scalar& x,
767 const Scalar& y,
768 const Scalar& z) {
769 return Quaternion(w, x, y, z);
770}
771
782template <typename Scalar, int Options>
783template <typename Derived1, typename Derived2>
784EIGEN_DEVICE_FUNC Quaternion<Scalar, Options> Quaternion<Scalar, Options>::FromTwoVectors(
785 const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b) {
786 Quaternion quat;
787 quat.setFromTwoVectors(a, b);
788 return quat;
789}
790
797template <class Derived>
799 const {
800 // FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
801 Scalar n2 = this->squaredNorm();
802 if (n2 > Scalar(0))
803 return Quaternion<Scalar>(conjugate().coeffs() / n2);
804 else {
805 // return an invalid result to flag the error
806 return Quaternion<Scalar>(Coefficients::Zero());
807 }
808}
809
810// Generic conjugate of a Quaternion
811namespace internal {
812template <int Arch, class Derived, typename Scalar>
813struct quat_conj {
814 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived>& q) {
815 return Quaternion<Scalar>(q.w(), -q.x(), -q.y(), -q.z());
816 }
817};
818} // namespace internal
819
826template <class Derived>
828 const {
829 return internal::quat_conj<Architecture::Target, Derived, typename internal::traits<Derived>::Scalar>::run(*this);
830}
831
835template <class Derived>
836template <class OtherDerived>
837EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Scalar QuaternionBase<Derived>::angularDistance(
838 const QuaternionBase<OtherDerived>& other) const {
839 EIGEN_USING_STD(atan2)
840 Quaternion<Scalar> d = (*this) * other.conjugate();
841 return Scalar(2) * atan2(d.vec().norm(), numext::abs(d.w()));
842}
843
850template <class Derived>
851template <class OtherDerived>
852EIGEN_DEVICE_FUNC Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Derived>::slerp(
853 const Scalar& t, const QuaternionBase<OtherDerived>& other) const {
854 EIGEN_USING_STD(acos)
855 EIGEN_USING_STD(sin)
856 const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
857 Scalar d = this->dot(other);
858 Scalar absD = numext::abs(d);
859
860 Scalar scale0;
861 Scalar scale1;
862
863 if (absD >= one) {
864 scale0 = Scalar(1) - t;
865 scale1 = t;
866 } else {
867 // theta is the angle between the 2 quaternions
868 Scalar theta = acos(absD);
869 Scalar sinTheta = numext::sqrt(Scalar(1) - absD * absD);
870
871 scale0 = sin((Scalar(1) - t) * theta) / sinTheta;
872 scale1 = sin((t * theta)) / sinTheta;
873 }
874 if (d < Scalar(0)) scale1 = -scale1;
875
876 return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
877}
878
879namespace internal {
880
881// set from a rotation matrix
882template <typename Other>
883struct quaternionbase_assign_impl<Other, 3, 3> {
884 typedef typename Other::Scalar Scalar;
885 template <class Derived>
886 EIGEN_DEVICE_FUNC static inline void run(QuaternionBase<Derived>& q, const Other& a_mat) {
887 const typename internal::nested_eval<Other, 2>::type mat(a_mat);
888 EIGEN_USING_STD(sqrt)
889 // This algorithm comes from "Quaternion Calculus and Fast Animation",
890 // Ken Shoemake, 1987 SIGGRAPH course notes
891 Scalar t = mat.trace();
892 if (t > Scalar(0)) {
893 t = sqrt(t + Scalar(1.0));
894 q.w() = Scalar(0.5) * t;
895 t = Scalar(0.5) / t;
896 q.x() = (mat.coeff(2, 1) - mat.coeff(1, 2)) * t;
897 q.y() = (mat.coeff(0, 2) - mat.coeff(2, 0)) * t;
898 q.z() = (mat.coeff(1, 0) - mat.coeff(0, 1)) * t;
899 } else {
900 Index i = 0;
901 if (mat.coeff(1, 1) > mat.coeff(0, 0)) i = 1;
902 if (mat.coeff(2, 2) > mat.coeff(i, i)) i = 2;
903 Index j = (i + 1) % 3;
904 Index k = (j + 1) % 3;
905
906 t = sqrt(mat.coeff(i, i) - mat.coeff(j, j) - mat.coeff(k, k) + Scalar(1.0));
907 q.coeffs().coeffRef(i) = Scalar(0.5) * t;
908 t = Scalar(0.5) / t;
909 q.w() = (mat.coeff(k, j) - mat.coeff(j, k)) * t;
910 q.coeffs().coeffRef(j) = (mat.coeff(j, i) + mat.coeff(i, j)) * t;
911 q.coeffs().coeffRef(k) = (mat.coeff(k, i) + mat.coeff(i, k)) * t;
912 }
913 }
914};
915
916// set from a vector of coefficients assumed to be a quaternion
917template <typename Other>
918struct quaternionbase_assign_impl<Other, 4, 1> {
919 typedef typename Other::Scalar Scalar;
920 template <class Derived>
921 EIGEN_DEVICE_FUNC static inline void run(QuaternionBase<Derived>& q, const Other& vec) {
922 q.coeffs() = vec;
923 }
924};
925
926} // end namespace internal
927
928} // end namespace Eigen
929
930#endif // EIGEN_QUATERNION_H
Represents a 3D rotation as a rotation angle around an arbitrary 3D axis.
Definition AngleAxis.h:52
const Vector3 & axis() const
Definition AngleAxis.h:99
Scalar angle() const
Definition AngleAxis.h:94
const std::enable_if_t< std::is_same< typename LhsDerived::Scalar, typename RhsDerived::Scalar >::value, Eigen::CwiseBinaryOp< Eigen::internal::scalar_atan2_op< typename LhsDerived::Scalar, typename RhsDerived::Scalar >, const LhsDerived, const RhsDerived > > atan2(const Eigen::ArrayBase< LhsDerived > &x, const Eigen::ArrayBase< RhsDerived > &exponents)
Definition GlobalFunctions.h:209
Two-sided Jacobi SVD decomposition of a rectangular matrix.
Definition JacobiSVD.h:500
Map(Scalar *coeffs)
Definition Quaternion.h:511
Map(const Scalar *coeffs)
Definition Quaternion.h:470
A matrix or vector expression mapping an existing array of data.
Definition Map.h:96
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:52
const PlainObject normalized() const
Definition Dot.h:92
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:186
constexpr Scalar & coeffRef(Index rowId, Index colId)
Definition PlainObjectBase.h:191
Base class for quaternion expressions.
Definition Quaternion.h:35
Matrix< Scalar, 3, 3 > Matrix3
Definition Quaternion.h:55
internal::traits< Derived >::Coefficients coeffsScalarLast() const
Definition Quaternion.h:107
constexpr CoeffReturnType z() const
Definition Quaternion.h:64
Scalar squaredNorm() const
Definition Quaternion.h:146
QuaternionBase & setIdentity()
Definition Quaternion.h:138
Quaternion< Scalar > normalized() const
Definition Quaternion.h:158
internal::traits< Derived >::Coefficients & coeffs()
Definition Quaternion.h:112
Matrix< Scalar, 3, 1 > Vector3
Definition Quaternion.h:53
constexpr CoeffReturnType x() const
Definition Quaternion.h:60
internal::cast_return_type< Derived, Quaternion< NewScalarType > >::type cast() const
constexpr NonConstCoeffReturnType z()
Definition Quaternion.h:73
VectorBlock< Coefficients, 3 > vec()
Definition Quaternion.h:81
const VectorBlock< const Coefficients, 3 > vec() const
Definition Quaternion.h:78
constexpr NonConstCoeffReturnType w()
Definition Quaternion.h:75
static Quaternion< Scalar > Identity()
Definition Quaternion.h:132
bool operator!=(const QuaternionBase< OtherDerived > &other) const
Definition Quaternion.h:208
Quaternion< Scalar > conjugate() const
Definition Quaternion.h:827
bool isApprox(const QuaternionBase< OtherDerived > &other, const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition Quaternion.h:217
void normalize()
Definition Quaternion.h:155
Derived & setFromTwoVectors(const MatrixBase< Derived1 > &a, const MatrixBase< Derived2 > &b)
Definition Quaternion.h:692
Matrix3 toRotationMatrix() const
Definition Quaternion.h:646
constexpr CoeffReturnType y() const
Definition Quaternion.h:62
Scalar dot(const QuaternionBase< OtherDerived > &other) const
Definition Quaternion.h:166
Derived & operator=(const AngleAxisType &aa)
Definition Quaternion.h:617
Vector3 _transformVector(const Vector3 &v) const
Definition Quaternion.h:588
Scalar norm() const
Definition Quaternion.h:151
Quaternion< Scalar > inverse() const
Definition Quaternion.h:798
const internal::traits< Derived >::Coefficients & coeffs() const
Definition Quaternion.h:84
bool operator==(const QuaternionBase< OtherDerived > &other) const
Definition Quaternion.h:199
internal::traits< Derived >::Coefficients coeffsScalarFirst() const
Definition Quaternion.h:96
constexpr CoeffReturnType w() const
Definition Quaternion.h:66
constexpr NonConstCoeffReturnType x()
Definition Quaternion.h:69
AngleAxis< Scalar > AngleAxisType
Definition Quaternion.h:57
constexpr NonConstCoeffReturnType y()
Definition Quaternion.h:71
Derived & operator*=(const QuaternionBase< OtherDerived > &q)
Definition Quaternion.h:573
The quaternion class used to represent 3D orientations and rotations.
Definition Quaternion.h:308
Quaternion(Quaternion &&other) noexcept(std::is_nothrow_move_constructible< Scalar >::value)
Definition Quaternion.h:372
Quaternion(const Quaternion< OtherScalar, OtherOptions > &other)
Definition Quaternion.h:366
static Quaternion FromCoeffsScalarLast(const Scalar &x, const Scalar &y, const Scalar &z, const Scalar &w)
Definition Quaternion.h:750
Quaternion(const Scalar &w, const Scalar &x, const Scalar &y, const Scalar &z)
Definition Quaternion.h:331
Quaternion(const QuaternionBase< Derived > &other)
Definition Quaternion.h:348
Quaternion(const Scalar &w, const Eigen::MatrixBase< Derived > &vec)
Definition Quaternion.h:338
static Quaternion UnitRandom()
Definition Quaternion.h:733
Quaternion(const MatrixBase< Derived > &other)
Definition Quaternion.h:360
Quaternion(const AngleAxisType &aa)
Definition Quaternion.h:353
Quaternion()
Definition Quaternion.h:322
static Quaternion FromCoeffsScalarFirst(const Scalar &w, const Scalar &x, const Scalar &y, const Scalar &z)
Definition Quaternion.h:765
Quaternion & operator=(Quaternion &&other) noexcept(std::is_nothrow_move_assignable< Scalar >::value)
Definition Quaternion.h:376
Quaternion(const Scalar *data)
Definition Quaternion.h:344
Common base class for compact rotation representations.
Definition RotationBase.h:32
const MatrixVType & matrixV() const
Definition SVDBase.h:189
Expression of a fixed-size or dynamic-size sub-vector.
Definition VectorBlock.h:58
Map< Quaternion< double >, Aligned > QuaternionMapAlignedd
Definition Quaternion.h:537
Quaternion< double > Quaterniond
Definition Quaternion.h:419
Quaternion< float > Quaternionf
Definition Quaternion.h:416
Map< Quaternion< float >, 0 > QuaternionMapf
Definition Quaternion.h:528
Map< Quaternion< double >, 0 > QuaternionMapd
Definition Quaternion.h:531
Map< Quaternion< float >, Aligned > QuaternionMapAlignedf
Definition Quaternion.h:534
@ Aligned
Definition Constants.h:242
@ DontAlign
Definition Constants.h:324
@ AutoAlign
Definition Constants.h:322
@ ComputeFullV
Definition Constants.h:393
const unsigned int LvalueBit
Definition Constants.h:148
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_cos_op< typename Derived::Scalar >, const Derived > cos(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sin_op< typename Derived::Scalar >, const Derived > sin(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_acos_op< typename Derived::Scalar >, const Derived > acos(const Eigen::ArrayBase< Derived > &x)