Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

stat_coordsys.h

Go to the documentation of this file.
00001 // -*-c++-*-
00002 #ifndef IG_STAT_COORDSYS_H
00003 #define IG_STAT_COORDSYS_H
00004 
00005 // $Id: stat_coordsys.h,v 1.1.2.6 2005/05/30 09:14:25 hkuiper Exp $
00006 
00007 // CwMtx matrix and vector math library
00008 // Copyright (C) 1999-2001  Harry Kuiper
00009 // Copyright (C) 2000  Will DeVore (template conversion)
00010 
00011 // This library is free software; you can redistribute it and/or
00012 // modify it under the terms of the GNU Lesser General Public
00013 // License as published by the Free Software Foundation; either
00014 // version 2 of the License, or (at your option) any later version.
00015 
00016 // This library is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA
00025 
00026 #ifndef IG_STAT_SMATRIX_H
00027 #include "stat_smatrix.h"
00028 #endif
00029 
00030 #ifndef IG_STAT_QUATERNION_H
00031 #include "stat_quatern.h"
00032 #endif
00033 
00034 #ifndef IG_STAT_SVECTOR_H
00035 #include "stat_svector.h"
00036 #endif
00037 
00038 // CWTSSquareMatrix utilities for use in coordinate systems
00039 
00040 namespace CwMtx
00041 {
00042 
00043   // NOTE: These template functions only work with floating point
00044   // template arguments due to the use of sin(3), cos(3), tan(3), etc.
00045 
00046   // PLEASE, READ THIS!!!
00047 
00048   // Function smatFromEuler321(sclrAbout3, sclrAbout2, sclrAbout1)
00049   // returns a transformation matrix which transforms coordinates from
00050   // the reference axis system to coordinates in an axis system with
00051   // Euler angles: sclrAbout3, sclrAbout2, sclrAbout1 relative to that
00052   // reference axis system DO NOT CHANGE THIS DEFINITION!!!
00053 
00054   // rotation about axis 3 (yaw angle), axis 2 (pitch angle) axis 1
00055   // (roll angle)
00056   template <class T>
00057   CWTSSquareMatrix<3, T>
00058   smatFromEuler321Angles(T sclrAbout3,
00059                          T sclrAbout2,
00060                          T sclrAbout1)
00061   {
00062     CWTSSquareMatrix<3, T> smat;
00063 
00064     // to reduce the number of calls to CPU expensive sin(..) and
00065     // cos(..) functions
00066     T sin3 = sin(sclrAbout3);
00067     T sin2 = sin(sclrAbout2);
00068     T sin1 = sin(sclrAbout1);
00069 
00070     T cos3 = cos(sclrAbout3);
00071     T cos2 = cos(sclrAbout2);
00072     T cos1 = cos(sclrAbout1);
00073 
00074     // first row
00075     smat[0][0] =  cos3*cos2;
00076     smat[0][1] =  sin3*cos2;
00077     smat[0][2] = -sin2;
00078 
00079     // second row
00080     smat[1][0] = -sin3*cos1 + cos3*sin2*sin1;
00081     smat[1][1] =  cos3*cos1 + sin3*sin2*sin1;
00082     smat[1][2] =  cos2*sin1;
00083 
00084     // third row
00085     smat[2][0] =  sin3*sin1 + cos3*sin2*cos1;
00086     smat[2][1] = -cos3*sin1 + sin3*sin2*cos1;
00087     smat[2][2] =  cos2*cos1;
00088 
00089     return smat;
00090   }
00091 
00092   // Next three functions calculate Euler angles from a transformation matrix
00093   // WARNING!!! They suffer from the ubiquitos singularities at 0, pi, 2*pi,
00094   // etc.
00095 
00096   // yaw angle, rotation angle about Z-axis
00097   template <class T>
00098   T
00099   euler321Angle3FromSmat(const CWTSSquareMatrix<3, T> &smat)
00100   {
00101     return atan2(smat[0][1], smat[0][0]);
00102   }
00103 
00104   // pitch angle, rotation angle about Y-axis
00105   template <class T>
00106   T
00107   euler321Angle2FromSmat(const CWTSSquareMatrix<3, T> &smat)
00108   {
00109     return asin(-smat[0][2]);
00110   }
00111 
00112   // roll angle, rotation angle about X-axis
00113   template <class T>
00114   T
00115   euler321Angle1FromSmat(const CWTSSquareMatrix<3, T> &smat)
00116   {
00117     return atan2(smat[1][2], smat[2][2]);
00118   }
00119 
00120   // CWTSQuaternion utilities for use in coordinate systems
00121 
00122   // PLEASE, READ THIS!!!
00123 
00124   // next three functions calculate Euler angles from a quaternion
00125   // that represents a rigid body's attitude WARNING!!! They do suffer
00126   // from the ubiquitos singularities around 0, pi and 2*pi.
00127 
00128   // yaw angle, rotation angle about Z-axis
00129   template <class T>
00130   T
00131   euler321Angle3FromQtn(const CWTSQuaternion<T> &qtn)
00132   {
00133     // to reduce the number of calls to the subscript operator
00134     T qtn0 = qtn[0];
00135     T qtn1 = qtn[1];
00136     T qtn2 = qtn[2];
00137     T qtn3 = qtn[3];
00138 
00139     // NOTE: Speed tip from Jeffrey T Duncan: use the identity: 1 =
00140     // q0^2 + q1^2 + q2^2 + q3^2 which simplifies: q0^2 - q1^2 -
00141     // q2^2 + q3^2 down to: 2*(q0^2 + q3^2) - 1
00142     return atan2(2*(qtn0*qtn1 + qtn2*qtn3),
00143                  2*(qtn0*qtn0 + qtn3*qtn3) - 1);
00144   }
00145 
00146   // pitch angle, rotation angle about Y-axis
00147   template <class T>
00148   T
00149   euler321Angle2FromQtn(const CWTSQuaternion<T> &qtn)
00150   {
00151     return asin(-2*(qtn[0]*qtn[2] - qtn[1]*qtn[3]));
00152   }
00153 
00154   // roll angle, rotation angle about X-axis
00155   template <class T>
00156   T
00157   euler321Angle1FromQtn(const CWTSQuaternion<T> &qtn)
00158   {
00159     // to reduce the number of calls to the subscript operator
00160     T qtn0 = qtn[0];
00161     T qtn1 = qtn[1];
00162     T qtn2 = qtn[2];
00163     T qtn3 = qtn[3];
00164 
00165     return atan2(2*(qtn1*qtn2 + qtn0*qtn3),
00166                  2*(qtn2*qtn2 + qtn3*qtn3) - 1);
00167   }
00168 
00169   // Function QtnFromEulerAxisAndAngle returns a quaternion
00170   // representing a rigid body's attitude from its Euler axis and
00171   // angle. NOTE: Argument vector svecEulerAxis MUST be a unit vector.
00172   template <class T>
00173   CWTSQuaternion<T>
00174   qtnFromEulerAxisAndAngle(const CWTSSpaceVector<T> &svecEulerAxis,
00175                            const T &sclrEulerAngle)
00176   {
00177     return CWTSQuaternion<T>(1, svecEulerAxis, 0.5*sclrEulerAngle);
00178   }
00179 
00180   // returns Euler axis
00181   template <class T>
00182   CWTSSpaceVector<T>
00183   eulerAxisFromQtn(const CWTSQuaternion<T> &qtn)
00184   {
00185     T sclrTmp = sqrt(1 - qtn[3]*qtn[3]);
00186 
00187     return CWTSSpaceVector<T>(qtn[0]/sclrTmp,
00188                               qtn[1]/sclrTmp,
00189                               qtn[2]/sclrTmp);
00190   }
00191 
00192   // returns Euler angle
00193   template <class T>
00194   T
00195   eulerAngleFromQtn(const CWTSQuaternion<T> &qtn)
00196   {
00197     return 2*acos(qtn[3]);
00198   }
00199 
00200   // Function QtnFromEuler321 returns a quaternion representing a
00201   // rigid body's attitude. The quaternion elements correspond to the
00202   // Euler symmetric parameters of the body. The body's attitude must
00203   // be entered in Euler angle representation with rotation order
00204   // 3-2-1, i.e. first about Z-axis next about Y-axis and finally
00205   // about X-axis.
00206 
00207   // rotation about axis 3 (yaw angle), axis 2 (pitch angle) axis 1
00208   // (roll angle)
00209   template <class T>
00210   CWTSQuaternion<T>
00211   qtnFromEuler321Angles(T sclrAbout3,
00212                         T sclrAbout2,
00213                         T sclrAbout1)
00214   {
00215     return
00216       CWTSQuaternion<T>(1, CWTSSpaceVector<T>(0, 0, 1), 0.5*sclrAbout3)
00217       *CWTSQuaternion<T>(1, CWTSSpaceVector<T>(0, 1, 0), 0.5*sclrAbout2)
00218       *CWTSQuaternion<T>(1, CWTSSpaceVector<T>(1, 0, 0), 0.5*sclrAbout1);
00219   }
00220 
00221   // SmatFromQtn returns the transformation matrix corresponding to a
00222   // quaternion
00223   template <class T>
00224   CWTSSquareMatrix<3, T>
00225   smatFromQtn(const CWTSQuaternion<T> &qtn)
00226   {
00227     CWTSSquareMatrix<3, T> smat;
00228 
00229     // to reduce the number of calls to the subscript operator
00230     T qtn0 = qtn[0];
00231     T qtn1 = qtn[1];
00232     T qtn2 = qtn[2];
00233     T qtn3 = qtn[3];
00234 
00235     smat[0][0] = 1 - 2*(qtn1*qtn1 + qtn2*qtn2);
00236     smat[0][1] = 2*(qtn0*qtn1 + qtn2*qtn3);
00237     smat[0][2] = 2*(qtn0*qtn2 - qtn1*qtn3);
00238 
00239     smat[1][0] = 2*(qtn0*qtn1 - qtn2*qtn3);
00240     smat[1][1] = 1 - 2*(qtn0*qtn0 + qtn2*qtn2);
00241     smat[1][2] = 2*(qtn1*qtn2 + qtn0*qtn3);
00242 
00243     smat[2][0] = 2*(qtn0*qtn2 + qtn1*qtn3);
00244     smat[2][1] = 2*(qtn1*qtn2 - qtn0*qtn3);
00245     smat[2][2] = 1 - 2*(qtn0*qtn0 + qtn1*qtn1);
00246 
00247     return smat;
00248   }
00249 
00250   // QtnFromSmat returns the quaternion corresponding to a
00251   // transformation matrix
00252   template <class T>
00253   CWTSQuaternion<T>
00254   qtnFromSmat(const CWTSSquareMatrix<3, T> &smat)
00255   {
00256     // Check trace to prevent loss of accuracy
00257     T sclrTmp = tr(smat);
00258     CWTSQuaternion<T> qtn;
00259 
00260     if(sclrTmp > 0)
00261       {
00262         // No trouble, we can use standard expression
00263         sclrTmp = 0.5*sqrt(1 + sclrTmp);
00264         qtn[0] = 0.25*(smat[1][2] - smat[2][1])/sclrTmp;
00265         qtn[1] = 0.25*(smat[2][0] - smat[0][2])/sclrTmp;
00266         qtn[2] = 0.25*(smat[0][1] - smat[1][0])/sclrTmp;
00267         qtn[3] = sclrTmp;
00268       }
00269     else
00270       {
00271         // We could be in trouble, so we have to take
00272         // precautions. NOTE: Parts of this piece of code were taken
00273         // from the example in the article "Rotating Objects Using
00274         // Quaternions" in Game Developer Magazine written by Nick
00275         // Bobick, july 3, 1998, vol. 2, issue 26.
00276         int i = 0;
00277         if (smat[1][1] > smat[0][0]) i = 1;
00278         if (smat[2][2] > smat[i][i]) i = 2;
00279 
00280         switch (i)
00281           {
00282           case 0:
00283             sclrTmp = 0.5*sqrt(1 + smat[0][0] - smat[1][1] - smat[2][2]);
00284             qtn[0] = sclrTmp;
00285             qtn[1] = 0.25*(smat[0][1] + smat[1][0])/sclrTmp;
00286             qtn[2] = 0.25*(smat[0][2] + smat[2][0])/sclrTmp;
00287             qtn[3] = 0.25*(smat[1][2] - smat[2][1])/sclrTmp;
00288             break;
00289 
00290           case 1:
00291             sclrTmp = 0.5*sqrt(1 - smat[0][0] + smat[1][1] - smat[2][2]);
00292             qtn[0] = 0.25*(smat[1][0] + smat[0][1])/sclrTmp;
00293             qtn[1] = sclrTmp;
00294             qtn[2] = 0.25*(smat[1][2] + smat[2][1])/sclrTmp;
00295             qtn[3] = 0.25*(smat[2][0] - smat[0][2])/sclrTmp;
00296             break;
00297 
00298           case 2:
00299             sclrTmp = 0.5*sqrt(1 - smat[0][0] - smat[1][1] + smat[2][2]);
00300             qtn[0] = 0.25*(smat[2][0] + smat[0][2])/sclrTmp;
00301             qtn[1] = 0.25*(smat[2][1] + smat[1][2])/sclrTmp;
00302             qtn[2] = sclrTmp;
00303             qtn[3] = 0.25*(smat[0][1] - smat[1][0])/sclrTmp;
00304 
00305             break;
00306           }
00307       }
00308 
00309     return qtn;
00310   }
00311 
00312   // NOTE: This function duplicates eulerAxisFromQtn(qtn) it only has
00313   // a different return type.
00314   template <class T>
00315   CWTSVector<3, T>
00316   axisAngleFromQtn( const CWTSQuaternion<T> &qtn )
00317   {
00318     return eulerAxisFromQtn(qtn);
00319   }
00320 
00321   // NOTE: This function duplicates qtnFromEulerAxisAndAngle(..) it
00322   // only has a different function profile.
00323   template <class T>
00324   CWTSQuaternion<T>
00325   qtnFromAxisAndAngle(const CWTSVector<3, T> &vAxis,
00326                       const T sAngle)
00327   {
00328     return qtnFromEulerAxisAndAngle(vAxis, sAngle);
00329   }
00330 
00331   template <class T>
00332   CWTSSquareMatrix<3, T>
00333   changeOfBasis(CWTSSpaceVector< CWTSSpaceVector<T> >&from, 
00334                 CWTSSpaceVector< CWTSSpaceVector<T> >&to)
00335   {
00336     CWTSSquareMatrix<3, T> A;
00337 
00338     // This is a "change of basis" from the "from" frame to the "to"
00339     // frame.  the "to" frame is typically the "Standard basis"
00340     // frame.  The "from" is a frame that represents the current
00341     // orientation of the object in the shape of an orthonormal
00342     // tripod.
00343 
00344     enum { x , y , z };
00345 
00346     // _X,_Y,_Z is typically the standard basis frame.
00347 
00348     //  | x^_X , y^_X , z^_X |
00349     //  | x^_Y , y^_Y , z^_Y |
00350     //  | x^_Z , y^_Z , z^_Z |
00351         
00352     A[0][0] = from[x]*to[x];
00353     A[0][1] = from[y]*to[x];
00354     A[0][2] = from[z]*to[x];
00355 
00356     A[1][0] = from[x]*to[y];
00357     A[1][1] = from[y]*to[y];
00358     A[1][2] = from[z]*to[y];
00359 
00360     A[2][0] = from[x]*to[z];
00361     A[2][1] = from[y]*to[z];
00362     A[2][2] = from[z]*to[z];
00363         
00364     // This is simply the transpose done manually which would save
00365     // and inverse call.
00366     //  | x ^ _X , x ^ _Y , x ^ _Z |
00367     //  | y ^ _X , y ^ _Y , y ^ _Z |
00368     //  | z ^ _X , z ^ _Y , z ^ _Z |
00369         
00370     // And finally we return the matrix that takes the "from" frame
00371     // to the "to"/"Standard basis" frame.
00372     return A;
00373   }
00374 
00375 }
00376 
00377 #endif   // IG_STAT_COORDSYS_H

Generated on Sun Jul 3 12:18:45 2005 for Matrix and vector library by  doxygen 1.4.2