00001 // This is core/vnl/vnl_quaternion.h 00002 #ifndef vnl_quaternion_h_ 00003 #define vnl_quaternion_h_ 00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE 00005 #pragma interface 00006 #endif 00007 //: 00008 // \file 00009 // \brief Unit quaternion represents rotation in 3D. 00010 // \author awf@robots.ox.ac.uk 00011 // \date 16 Mar 00 00012 // 00013 // \verbatim 00014 // Modifications 00015 // 20-05-2000 fsm. changed FLOAT to T since gcc will barf at 00016 // the very reasonable forward declaration 00017 // template <class FLOAT> class vnl_quaternion; 00018 // 23-3-2001 LSB (Manchester) Tidied documentation 00019 // 13-1-2003 Peter Vanroose - removed unimplemented method rotation_matrix() 00020 // 20-2-2006 Ian Scott - Added conversion to from Euler angles 00021 // 06-5-2006 Peter Vanroose - replaced all vnl_vector by vnl_vector_fixed 00022 // \endverbatim 00023 00024 #include <vnl/vnl_vector_fixed.h> 00025 #include <vnl/vnl_matrix_fixed.h> 00026 #include <vcl_iostream.h> 00027 00028 //: 4-element vector that represents rotation in 3D. 00029 // vnl_quaternion is a 4-element vector with 1 real and 3 imaginary 00030 // components: 00031 // \code 00032 // q = r + (i*x + j*y + k*z) 00033 // r = cos(theta/2) 00034 // (x, y, z) = sin(theta/2) (kx, ky, kz) 00035 // \endcode 00036 // where theta and k are respectively the angle and axis of rotation. 00037 // 3D vectors can be thought of as imaginary quaternions, and so a 00038 // quaternion is represented as a vnl_vector_fixed<T,4> with the imaginary 00039 // part before the real part for 1-1 alignment. 00040 // 00041 // Unit quaternions provide a more efficient representation for 00042 // rotation, than the usual orthonormal matrix that has nine 00043 // parameters and six orthonormal constraints. The unit 00044 // quaternion has only one unit magnitude constraint. Composing 00045 // rotations with quaternions results in fewer multiplications 00046 // and less error. To insure valid rotation results, the 00047 // nearest unit quaternion is computed, and this is much easier 00048 // than finding the nearest orthonormal matrix. Transforming 00049 // vectors with a quaternion requires more operations compared 00050 // to multiplication with the equivalent orthonormal matrix. 00051 // 00052 // \sa 00053 // vnl_vector_fixed and vnl_matrix_fixed for basic operations on vectors and matrices. 00054 // \sa 00055 // Envelope for envelope-letter scheme that avoids deep copy on 00056 // return by value in arithmetic expressions like: q1 * q2 * q3 *... 00057 // 00058 00059 export template <class T> 00060 class vnl_quaternion : public vnl_vector_fixed<T, 4> 00061 { 00062 typedef vnl_vector_fixed<T,4> Base; 00063 public: 00064 00065 //: Constructor for null quaternion 00066 vnl_quaternion() {} 00067 00068 //: Construct quaternion from components x,y,z,r 00069 vnl_quaternion(T x, T y, T z, T r); 00070 00071 //: Construct quaternion from Euler Angles, 00072 // That is a rotation about the X axis, followed by Y, followed by 00073 // the Z axis, using a fixed reference frame. 00074 vnl_quaternion(T theta_X, T theta_Y, T theta_Z); 00075 00076 //: Construct quaternion from axis and angle of rotation. 00077 // \note If you specify an angle in [0, 2pi], then methods angle() and axis() will return the same values. 00078 // However, if you specify an angle in [-2pi, 0], then methods angle() and axis() will return values with opposite signs. 00079 // \sa vnl_quaternion::angle() 00080 // \sa vnl_quaternion::axis() 00081 vnl_quaternion(vnl_vector_fixed<T,3> const& axis, T angle); 00082 00083 //: Construct quaternion from from 3x3 row-major matrix 00084 explicit vnl_quaternion(vnl_matrix_fixed<T,3,3> const& transform); 00085 00086 //: Construct quaternion from a 3D vector 00087 vnl_quaternion(vnl_vector_fixed<T,3> const& vec); 00088 00089 //: Construct quaternion from a 4D vector 00090 vnl_quaternion (vnl_vector_fixed<T,4> const& vec); 00091 00092 //: Copy constructor -- Creates a copy of from quaternion. 00093 inline vnl_quaternion(vnl_quaternion<T> const& from) : Base(from) {} 00094 00095 //: Free internal array 00096 inline ~vnl_quaternion() {} // vnl_vector_fixed will free data array 00097 00098 //: Overloads assignment operator to copy rhs quaternion into lhs quaternion. 00099 inline vnl_quaternion& operator= (vnl_quaternion<T> const& rhs) { Base::operator=(rhs); return *this; } 00100 00101 //: Imaginary component, parallel to axis of rotation. 00102 // Use this accessor to both get and set the component. 00103 inline T& x() { return this->operator()(0); } 00104 //: Imaginary component, parallel to axis of rotation. 00105 // Use this accessor to both get and set the component. 00106 inline T& y() { return this->operator()(1); } 00107 //: Imaginary component, parallel to axis of rotation. 00108 // Use this accessor to both get and set the component. 00109 inline T& z() { return this->operator()(2); } 00110 //: Real component. 00111 // Use this accessor to both get and set the component. 00112 inline T& r() { return this->operator()(3); } 00113 00114 //: Imaginary component, parallel to axis of rotation. 00115 // Use this accessor to get the component. 00116 inline T x() const { return this->operator()(0); } 00117 //: Imaginary component, parallel to axis of rotation. 00118 // Use this accessor to get the component. 00119 inline T y() const { return this->operator()(1); } 00120 //: Imaginary component, parallel to axis of rotation. 00121 // Use this accessor to get the component. 00122 inline T z() const { return this->operator()(2); } 00123 //: Real component. 00124 // Use this accessor to get the component. 00125 inline T r() const { return this->operator()(3); } 00126 00127 //: Copies and returns the real part. 00128 inline T real() const { return (*this)[3]; } 00129 00130 //: Copies and returns the imaginary part. 00131 inline vnl_vector_fixed<T,3> imaginary() const { return this->extract(3,0); } 00132 00133 //: Axis of rotation. 00134 // \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). 00135 vnl_vector_fixed<T,3> axis() const; 00136 00137 //: Angle of rotation. 00138 // \note Returned angle lies in [0, 2*pi] 00139 T angle() const; 00140 00141 //: 3x3 rotation matrix 00142 vnl_matrix_fixed<T,3,3> rotation_matrix_transpose() const; 00143 00144 //: 4x4 rotation matrix 00145 vnl_matrix_fixed<T,4,4> rotation_matrix_transpose_4() const; 00146 00147 //: Same real, opposite img part 00148 vnl_quaternion<T> conjugate() const; 00149 00150 //: Inverse for nonzero quat 00151 vnl_quaternion<T> inverse() const; 00152 00153 vnl_quaternion<T> operator* (vnl_quaternion<T> const&) const; 00154 00155 //: Rotate 3D v 00156 // The quaternion must be normalised first. 00157 vnl_vector_fixed<T,3> rotate(vnl_vector_fixed<T,3> const&) const; 00158 00159 //: Rotation representation in Euler angles. 00160 // The angles raturned will be [theta_X,theta_Y,theta_Z] 00161 // where the final rotation is found be first applying theta_X radians 00162 // about the X axis, then theta_Y about the Y-axis, etc. 00163 // The axes stay in a fixed reference frame. 00164 // The quaternion mut be normalised first. 00165 vnl_vector_fixed<T,3> rotation_euler_angles() const; 00166 }; 00167 00168 //: operator<< 00169 // \relates vnl_quaternion 00170 template <class T> 00171 inline vcl_ostream& operator<< (vcl_ostream& os, vnl_quaternion<T> const& q) 00172 { 00173 return os << *((const vnl_vector_fixed<T,4>*) &q); 00174 } 00175 00176 #define VNL_QUATERNION_INSTANTIATE(T) extern "Please #include <vnl/vnl_quaternion.txx> first" 00177 00178 #endif // vnl_quaternion_h_
1.5.1