quaternion.h

Go to the documentation of this file.
00001 /***************************************************************************
00002                           quaternion.h  -  description
00003                              -------------------
00004     begin                : Fri Feb 28 2003
00005     copyright            : (C) 2003-2006 by Ben Swerts
00006     email                : bswerts@users.sourceforge.net
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00019 
00029 
00030 
00031 
00032 #ifndef QUATERNION_H
00033 #define QUATERNION_H
00034 
00035 
00037 
00038 // C++ header files
00039 #include <cmath>
00040 #ifndef QT_NO_DEBUG
00041   #include <iostream>
00042 #endif
00043 
00044 // Xbrabo header files
00045 #include <vector3d.h> // includes point3d.h
00046 template <class T> class Vector3D; // if vector3d.h was already included, we still need a forward declaration (don't know why)
00047 
00051 
00053 template <class T> class Quaternion
00054 {
00055   public:
00056     Quaternion();                       // default constructor (quaternion with zero rotation)
00057     Quaternion(const T w, const T x, const T y, const T z); // constructs a quaternion (w, x, y, z)
00058     Quaternion(const T xAngle, const T yAngle, const T zAngle);       // constructs a quaternion from Euler angles xAngle, yAngle and zAngle
00059     Quaternion(const Vector3D<T> v, const T angle);         // constructs a quaternion from an 'angle around a certain axis' representation
00060     ~Quaternion();                      // destructor
00061 
00063     Quaternion operator*(const Quaternion& quat); // multiplication
00064     Quaternion& operator=(const Quaternion& quat);// copy constructor
00065 
00067     void identity();                    // set the quaternion to the identity quaternion
00068     void normalize();                   // normalize the quaternion
00069     void setValues(const T w, const T x, const T y, const T z);       // set the values
00070     void conjugate();                   // changes the quaternion into its conjugate
00071     void inverse();                     // changes the quaternion into its inverse
00072 
00073     // public member function for retrieving data
00074     T w() const;                        // returns the w-value
00075     T x() const;                        // returns the x-value
00076     T y() const;                        // returns the y-value
00077     T z() const;                        // returns the z-value
00078 
00079     // public member functions for converting between representations
00080     void eulerToQuaternion(const T xAngle, const T yAngle, const T zAngle);     // converts Euler angles to a quaternion
00081     void axisToQuaternion(const Vector3D<T> v, const T angle);        // converts from axis/angle to quaternion
00082     void getAxisAngle(Vector3D<T>& v, T& angle);  // returns axis/angle for the quaternion
00083 
00084   private:
00085     // private member functions
00086     void limitRange(const T minimum, T& value, const T maximum);      // limits a value between a min and a max
00087 
00088     // private member data
00089     T wQuat, xQuat, yQuat, zQuat;   
00090 };
00091 
00095 
00097 template <class T> Quaternion<T>::Quaternion()
00099 {
00100   identity();
00101 }
00102 
00104 template <class T> Quaternion<T>::Quaternion(const T w, const T x, const T y, const T z)
00107 {
00108   setValues(w, x, y, z);
00109 }
00110 
00112 template <class T> Quaternion<T>::Quaternion(const T xAngle, const T yAngle, const T zAngle)
00115 {
00116   eulerToQuaternion(xAngle, yAngle, zAngle);
00117 }
00118 
00120 template <class T> Quaternion<T>::Quaternion(const Vector3D<T> v, const T angle)
00123 {
00124   axisToQuaternion(v, angle);
00125 }
00126 
00128 template <class T> Quaternion<T>::~Quaternion()
00130 {
00131 }
00132 
00134 template <class T> Quaternion<T> Quaternion<T>::operator*(const Quaternion& quat)
00136 {
00137   T rw = wQuat*quat.wQuat - xQuat*quat.xQuat - yQuat*quat.yQuat - zQuat*quat.zQuat;
00138   T rx = xQuat*quat.wQuat + wQuat*quat.xQuat + zQuat*quat.yQuat - yQuat*quat.zQuat;
00139   T ry = yQuat*quat.wQuat + wQuat*quat.yQuat + xQuat*quat.zQuat - zQuat*quat.xQuat;
00140   T rz = zQuat*quat.wQuat + wQuat*quat.zQuat + yQuat*quat.xQuat - xQuat*quat.yQuat;
00141 
00142   return Quaternion(rw, rx, ry, rz);
00143 }
00144 
00146 template <class T> Quaternion<T>& Quaternion<T>::operator=(const Quaternion& quat)
00148 {
00149   wQuat = quat.wQuat;
00150   xQuat = quat.xQuat;
00151   yQuat = quat.yQuat;
00152   zQuat = quat.zQuat;
00153 
00154   return (*this);
00155 }
00156 
00158 template <class T> void Quaternion<T>::identity()
00160 {
00161   wQuat = 1.0f; // identity quaternion for multiplication
00162   xQuat = 0.0f;
00163   yQuat = 0.0f;
00164   zQuat = 0.0f;
00165 }
00166 
00168 template <class T> void Quaternion<T>::normalize()
00170 {
00171   T norm = wQuat*wQuat + xQuat*xQuat + yQuat*yQuat + zQuat*zQuat;
00172   if(norm < Point3D<T>::TOLERANCE)
00173   {
00174 #ifndef QT_NO_DEBUG
00175     std::cerr << "Quaternion::normalize(): Norm of the quaternion too close to zero" << std::endl;
00176 #endif
00177     return;
00178   }
00179 
00180   wQuat /= norm;
00181   xQuat /= norm;
00182   yQuat /= norm;
00183   zQuat /= norm;
00184 
00185   norm = wQuat*wQuat + xQuat*xQuat + yQuat*yQuat + zQuat*zQuat;
00186   if(fabs(norm - 1.0f) > Point3D<T>::TOLERANCE)
00187   {
00188 #ifndef QT_NO_DEBUG
00189     std::cerr << "Quaternion::normalize(): Norm of the quaternion not equal to 1 but " << norm << std::endl;
00190 #endif
00191     return;
00192   }
00193 
00194   limitRange(-1.0, wQuat, 1.0);
00195   limitRange(-1.0, xQuat, 1.0);
00196   limitRange(-1.0, yQuat, 1.0);
00197   limitRange(-1.0, zQuat, 1.0);
00198 }
00199 
00201 template <class T> void Quaternion<T>::setValues(const T w, const T x, const T y, const T z)
00203 {
00204   if((w*w + x*x + y*y + z*z) < Point3D<T>::TOLERANCE)
00205   {
00206 #ifndef QT_NO_DEBUG
00207     std::cerr << "Quaternion::setValues(wxyz): Norm of the quaternion too close to zero" << std::endl;
00208     std::cerr << " values: " << w << " " << x << " " << y << " " << z << std::endl;
00209 #endif
00210     identity();
00211     return;
00212   }
00213 
00214   wQuat = w;
00215   xQuat = x;
00216   yQuat = y;
00217   zQuat = z;
00218 
00219   normalize();
00220 }
00221 
00223 template <class T> void Quaternion<T>::conjugate()
00225 {
00226   xQuat = -xQuat;
00227   yQuat = -yQuat;
00228   zQuat = -zQuat;
00229 }
00230 
00232 template <class T> void Quaternion<T>::inverse()
00234 {
00235   conjugate();
00236   T norm = wQuat*wQuat + xQuat*xQuat + yQuat*yQuat + zQuat*zQuat;
00237   wQuat /= norm;
00238   xQuat /= norm;
00239   yQuat /= norm;
00240   zQuat /= norm;
00241 }
00242 
00244 template <class T> T Quaternion<T>::w() const
00246 {
00247   return wQuat;
00248 }
00249 
00251 template <class T> T Quaternion<T>::x() const
00253 {
00254   return xQuat;
00255 }
00256 
00258 template <class T> T Quaternion<T>::y() const
00260 {
00261   return yQuat;
00262 }
00263 
00265 template <class T> T Quaternion<T>::z() const
00267 {
00268   return zQuat;
00269 }
00270 
00272 template <class T> void Quaternion<T>::eulerToQuaternion(const T xAngle, const T yAngle, const T zAngle)
00274 {
00275   T ex = xAngle*Point3D<T>::DEGTORAD / 2.0;  // temp half euler angles
00276   T ey = yAngle*Point3D<T>::DEGTORAD / 2.0;  // temp half euler angles
00277   T ez = zAngle*Point3D<T>::DEGTORAD / 2.0;  // temp half euler angles
00278 
00279   T cr = cos(ex);  // roll
00280   T cp = cos(ey);  // pitch
00281   T cy = cos(ez);  // yaw
00282 
00283   T sr = sin(ex);  // roll
00284   T sp = sin(ey);  // pitch
00285   T sy = sin(ez);  // yaw
00286 
00287   T cpcy = cp*cy;
00288   T spsy = sp*sy;
00289 
00290   wQuat = cr*cpcy + sr*spsy;
00291   xQuat = sr*cpcy - cr*spsy;
00292   yQuat = cr*sp*cy + sr*cp*sy;
00293   zQuat = cr*cp*sy - sr*sp*cy;
00294 
00295   normalize();
00296 }
00297 
00299 template <class T> void Quaternion<T>::axisToQuaternion(const Vector3D<T> v, const T angle)
00302 {
00304   if(v.isZero())
00305   {
00306     setValues(1.0, 0.0, 0.0, 0.0);
00307     return;
00308   }
00309 
00311   Vector3D<T> unitVector = v;
00312   unitVector.normalize();
00313 
00315   T rad = angle * Point3D<T>::DEGTORAD / 2.0;
00316   T scale = sin(rad);
00317   setValues(cos(rad), unitVector.x() * scale, unitVector.y() * scale, unitVector.z() * scale);
00318   normalize();
00319 }
00320 
00322 template <class T> void Quaternion<T>::getAxisAngle(Vector3D<T>& v, T& angle)
00325 {
00326   T scale = sqrt(xQuat*xQuat + yQuat*yQuat + zQuat*zQuat);
00327 
00328   if(fabs(scale) < Point3D<T>::TOLERANCE)
00329   {
00331     angle = 0.0;
00332     v.setValues(0.0, 0.0, 1.0);
00333   }
00334   else
00335   {
00336     angle = acos(wQuat)*2.0*Point3D<T>::RADTODEG;
00337     v.setValues(xQuat/scale, yQuat/scale, zQuat/scale);
00338     v.normalize();
00339   }
00340 }
00341 
00342 
00346 
00348 template <class T> void Quaternion<T>::limitRange(const T minimum, T& value, const T maximum)
00350 {
00351   if(value < minimum)
00352     value = minimum;
00353   else if(value > maximum)
00354     value = maximum;
00355 }
00356 
00357 #endif
00358 

Generated on Fri May 19 14:31:55 2006 for Brabosphere by  doxygen 1.4.6-NO