vnl_quaternion.h
Go to the documentation of this file.
1 // This is core/vnl/vnl_quaternion.h
2 #ifndef vnl_quaternion_h_
3 #define vnl_quaternion_h_
4 //:
5 // \file
6 // \brief Unit quaternion represents rotation in 3D.
7 // \author awf@robots.ox.ac.uk
8 // \date 16 Mar 00
9 //
10 // \verbatim
11 // Modifications
12 // 20-05-2000 fsm. changed FLOAT to T since gcc will barf at
13 // the very reasonable forward declaration
14 // template <class FLOAT> class vnl_quaternion;
15 // 23-3-2001 LSB (Manchester) Tidied documentation
16 // 13-1-2003 Peter Vanroose - removed unimplemented method rotation_matrix()
17 // 20-2-2006 Ian Scott - Added conversion to from Euler angles
18 // 06-5-2006 Peter Vanroose - replaced all vnl_vector by vnl_vector_fixed
19 // \endverbatim
20 
21 #include <iostream>
22 #include <vnl/vnl_vector_fixed.h>
23 #include <vnl/vnl_matrix_fixed.h>
24 #ifdef _MSC_VER
25 # include <vcl_msvc_warnings.h>
26 #endif
27 #include "vnl/vnl_export.h"
28 
29 //: 4-element vector that represents rotation in 3D.
30 // vnl_quaternion is a 4-element vector with 1 real and 3 imaginary
31 // components:
32 // \code
33 // q = r + (i*x + j*y + k*z)
34 // r = cos(theta/2)
35 // (x, y, z) = sin(theta/2) (kx, ky, kz)
36 // \endcode
37 // where theta and k are respectively the angle and axis of rotation.
38 //
39 // 3D vectors can be thought of as pure imaginary quaternions, and so a
40 // quaternion is represented as a vnl_vector_fixed<T,4> with the imaginary
41 // part before the real part for 1-1 alignment.
42 //
43 // Unit quaternions (i.e., for which $x^2 + y^2 + z^2 + r^2 = 1$)
44 // provide a more efficient representation for rotation
45 // than the usual orthonormal matrix that has nine
46 // parameters and six orthonormal constraints. The unit
47 // quaternion has only one unit magnitude constraint. Composing
48 // rotations with quaternions results in fewer multiplications
49 // and less error. To insure valid rotation results, the
50 // nearest unit quaternion is computed, and this is much easier
51 // than finding the nearest orthonormal matrix. Transforming
52 // vectors with a quaternion requires more operations compared
53 // to multiplication with the equivalent orthonormal matrix.
54 //
55 // \sa
56 // vnl_vector_fixed and vnl_matrix_fixed for basic operations on vectors and matrices.
57 // \sa
58 // Envelope for envelope-letter scheme that avoids deep copy on
59 // return by value in arithmetic expressions like: q1 * q2 * q3 *...
60 //
61 
62 template <class T>
63 class VNL_EXPORT vnl_quaternion : public vnl_vector_fixed<T, 4>
64 {
65  private:
67  public:
68 
69  //: Constructor for null quaternion
70  vnl_quaternion() = default;
71 
72  //: Construct quaternion from components x,y,z,r
73  vnl_quaternion(T x, T y, T z, T r);
74 
75  //: Construct quaternion from Euler Angles,
76  // That is a rotation about the X axis, followed by Y, followed by
77  // the Z axis, using a fixed reference frame.
78  vnl_quaternion(T theta_X, T theta_Y, T theta_Z);
79 
80  //: Construct quaternion from axis and angle of rotation.
81  // \note If you specify an angle in [0, 2pi], then methods angle() and axis() will return the same values.
82  // However, if you specify an angle in [-2pi, 0], then methods angle() and axis() will return values with opposite signs.
83  // \sa vnl_quaternion::angle()
84  // \sa vnl_quaternion::axis()
85  vnl_quaternion(vnl_vector_fixed<T,3> const& axis, double angle);
86 
87  //: Construct quaternion from 3x3 row-major matrix
88  explicit vnl_quaternion(vnl_matrix_fixed<T,3,3> const& transform);
89 
90  //: Construct quaternion from a 3D vector
92 
93  //: Construct quaternion from a 4D vector
95 
96  //: Copy constructor -- Creates a copy of from quaternion.
97  inline vnl_quaternion(vnl_quaternion<T> const& from) : Base(from) {}
98 
99  //: Free internal array
100  inline ~vnl_quaternion() = default; // vnl_vector_fixed will free data array
101 
102  //: Overloads assignment operator to copy rhs quaternion into lhs quaternion.
103  inline vnl_quaternion& operator= (vnl_quaternion<T> const& rhs) { Base::operator=(rhs); return *this; }
104 
105  //: Imaginary component, parallel to axis of rotation.
106  // Use this accessor to both get and set the component.
107  inline T& x() { return this->operator()(0); }
108  //: Imaginary component, parallel to axis of rotation.
109  // Use this accessor to both get and set the component.
110  inline T& y() { return this->operator()(1); }
111  //: Imaginary component, parallel to axis of rotation.
112  // Use this accessor to both get and set the component.
113  inline T& z() { return this->operator()(2); }
114  //: Real component.
115  // Use this accessor to both get and set the component.
116  inline T& r() { return this->operator()(3); }
117 
118  //: Imaginary component, parallel to axis of rotation.
119  // Use this accessor to get the component.
120  inline T x() const { return this->operator()(0); }
121  //: Imaginary component, parallel to axis of rotation.
122  // Use this accessor to get the component.
123  inline T y() const { return this->operator()(1); }
124  //: Imaginary component, parallel to axis of rotation.
125  // Use this accessor to get the component.
126  inline T z() const { return this->operator()(2); }
127  //: Real component.
128  // Use this accessor to get the component.
129  inline T r() const { return this->operator()(3); }
130 
131  //: Copies and returns the real part.
132  inline T real() const { return (*this)[3]; }
133 
134  //: Copies and returns the imaginary part.
135  inline vnl_vector_fixed<T,3> imaginary() const { return this->extract(3,0); }
136 
137  //: Axis of rotation.
138  // \note Axis not well defined for theta==0. In such a case (or if provided axis==(0,0,0)), this function returns (0,0,1).
139  vnl_vector_fixed<T,3> axis() const;
140 
141  //: Angle of rotation.
142  // \note Returned angle lies in [0, 2*pi]
143  double angle() const;
144 
145  //: 3x3 rotation matrix
146  // The orthonormal vectors are the rows of the matrix, not its columns
147  vnl_matrix_fixed<T,3,3> rotation_matrix_transpose() const;
148 
149  //: 4x4 rotation matrix
150  vnl_matrix_fixed<T,4,4> rotation_matrix_transpose_4() const;
151 
152  //: Same real, opposite img part
153  vnl_quaternion<T> conjugate() const;
154 
155  //: Inverse for nonzero quat
156  vnl_quaternion<T> inverse() const;
157 
159 
160  //: Rotate 3D v
161  // The quaternion must be normalised first.
162  vnl_vector_fixed<T,3> rotate(vnl_vector_fixed<T,3> const&) const;
163 
164  //: Rotation representation in Euler angles.
165  // The angles returned will be [theta_X,theta_Y,theta_Z]
166  // where the final rotation is found be first applying theta_X radians
167  // about the X axis, then theta_Y about the Y-axis, etc.
168  // The axes stay in a fixed reference frame.
169  // The quaternion mut be normalised first.
170  vnl_vector_fixed<T,3> rotation_euler_angles() const;
171 };
172 
173 //: operator<<
174 // \relatesalso vnl_quaternion
175 template <class T>
176 std::istream& operator>> (std::istream& is, vnl_quaternion<T> &q)
177 {
179  is >> v;
180  q = vnl_quaternion<T>(v);
181  return is;
182 }
183 
184 
185 //: operator<<
186 // \relatesalso vnl_quaternion
187 template <class T>
188 inline std::ostream& operator<< (std::ostream& os, vnl_quaternion<T> const& q)
189 {
190  return os << *((const vnl_vector_fixed<T,4>*) &q);
191 }
192 
193 #define VNL_QUATERNION_INSTANTIATE(T) extern "Please #include <vnl/vnl_quaternion.hxx> first"
194 
195 #endif // vnl_quaternion_h_
T & operator()(unsigned int i)
Return reference to the element at specified index.
T & z()
Imaginary component, parallel to axis of rotation.
vnl_quaternion(vnl_quaternion< T > const &from)
Copy constructor – Creates a copy of from quaternion.
T & r()
Real component.
T x() const
Imaginary component, parallel to axis of rotation.
vnl_vector_fixed< T, 3 > imaginary() const
Copies and returns the imaginary part.
T real() const
Copies and returns the real part.
4-element vector that represents rotation in 3D.
Definition: vnl_fwd.h:29
T & y()
Imaginary component, parallel to axis of rotation.
T y() const
Imaginary component, parallel to axis of rotation.
T & x()
Imaginary component, parallel to axis of rotation.
std::ostream & operator<<(std::ostream &s, vnl_decnum const &r)
decimal output.
Definition: vnl_decnum.h:393
VNL_EXPORT double angle(v const &, v const &)
#define v
Definition: vnl_vector.h:42
T z() const
Imaginary component, parallel to axis of rotation.
vnl_vector< T > extract(unsigned int len, unsigned int start=0) const
Returns a subvector specified by the start index and length. O(n).
T r() const
Real component.
Fixed length stack-stored, space-efficient vector.
Definition: vnl_fwd.h:22
fixed size matrix
Fixed length stack-stored vector.
T angle(const vnl_vector_fixed< T, n > &a, const vnl_vector_fixed< T, n > &b)
VNL_EXPORT std::istream & operator>>(std::istream &s, vnl_decnum &r)
decimal input.
Definition: vnl_decnum.cxx:411
vnl_vector_fixed< T, N > operator *(vnl_diag_matrix_fixed< T, N > const &D, vnl_vector_fixed< T, N > const &A)
Multiply a vnl_diag_matrix_fixed by a vnl_vector_fixed. n flops.
vnl_vector_fixed< T, n > & operator=(const vnl_vector_fixed< T, n > &rhs)=default
Copy operator.
vnl_vector_fixed< T, 4 > Base