Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/Orient

Go to the documentation of this file.
00001 /* **-*-c++-*-**************************************************************
00002   Copyright (C)2002 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: Orient 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.21 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #ifndef _BASE_ORIENT_HPP_
00026 #define _BASE_ORIENT_HPP_
00027 
00028 #include <iostream>
00029 #include <math.h>
00030 
00031 #include <base/base>
00032 #include <base/array>
00033 #include <base/consts>
00034 #include <base/Vector>
00035 #include <base/Matrix>
00036 #include <base/Quat4>
00037 #include <base/Matrix3>
00038 
00039 
00040 namespace base {
00041 
00042 class Serializer;
00043 
00044 
00045 /// Orientation in 3D
00046 /**
00047  * Represents an orientation in 3D using various internal representations.
00048  * 
00049  * There are many parameterizations and terms in use for rotations and orientation/attitude.
00050  * Some of the more common are:
00051  *
00052  *  - 3x3 transformation matrices.  As this has 9 direction cosine values, it contains redundant information.
00053  *                                  Consequently, without care, roundoff errors can yield matrices
00054  *                                  that contain unwanted effects (e.g. scaling, skew)
00055  *                                  There are no singularities.  This is the representation used
00056  *                                  by OpenGL.
00057  *
00058  *  - Euler parameters.             A vector of 4 components - not to be confused with Euler angles.
00059  *                                  The mathematics corresponds to unit Quaternions - hence this
00060  *                                  representation is often refered to as such.  No singularities, 
00061  *                                  hence useful for interpolation.  Roundoff error often results
00062  *                                  in non-normalized vectors.  Some formulations place the scalar
00063  *                                  component as the first component and some as the last component
00064  *                                  (it is placed last here)
00065  *
00066  *  - Cardan-Bryant angles.         These are a 3 component vectors that represents rotations about
00067  *                                  3 principle axes (anti-cyclic).  The possibilities are XYZ, XZY,
00068  *                                  YZX, YXZ, ZYX and ZXY. i.e. rotation about the first axis, followed
00069  *                                  by a rotation about the (now transformed) second axis and finally
00070  *                                  about the (now twice transformed) third axis.
00071  *                                  Commonly refered to as Euler angles (although technically they are not).
00072  *                                  Has a singularity (gimble-lock) when 2nd rotation is 90 or 270deg.
00073  *                                  Often the terms Roll, Pitch and Yaw (RPY) are used, where Roll is roation
00074  *                                  about the forward axis by phi, Pitch is about the right axis by theta 
00075  *                                  and Yaw is about the up axis by psi.
00076  *                                  For aeronautics, and the manipulator DH notation frames, the axes
00077  *                                  are assigned x-forward, y-right & z-up.  In this case RPY
00078  *                                  is equivelent to EulerXYZ applied in the order Roll,Pitch,Yaw
00079  *                                  Note that For the OpenSim world frame the assignments are x-back, y-right & z-up. 
00080  *
00081  * - Euler angles.                  A 3 component vector similar to Cardan-Bryant angles, but where
00082  *                                  the first and last rotation axis are the same (cyclic). Possibilities 
00083  *                                  are XYX, XZX, YXY, YZY, ZXZ and ZYZ.  Has a singularity when the 2nd 
00084  *                                  rotation is 0 or 180deg.
00085  *                                  Euler used ZXZ, which is the most common - and also called 'x-convention'.
00086  *                                
00087  * - Rodriguez parameters.          A 3 component vector. Also known as a Rotation Vector (Benati, Rodriguez-Hamilton), or Gibbs Vector.
00088  *                                  Defined by gamma = v.tan(theta/2), where v is the axis of rotation and theta is the
00089  *                                  angle.  Has a gimble-lock singularity at 180deg.
00090  *
00091  * \todo finish implementing and testing this class!
00092  */
00093 class Orient
00094 {
00095 
00096 public:
00097   /** Quat      - Euler parameters expressed as a quaternion (v.x,v.y,v.z,w)
00098    *  Mat       - 3x3 transformation matrix of direction cosines.
00099    *  EulerABC  - Euler (possibly Cardan-Bryant) angles about the axes A, B & C in that order.
00100    *  EulerRPY  - Euler (Cardan-Bryant) Roll, Pitch, Yaw angles (alpha,beta,gamma). 
00101    *               This is equivelent to EulerXYZ and assumes that the
00102    *               x-axis points forward, y-axis points right and the z-axis up.
00103    *               (Aeronautical convention)
00104    *  Euler     - alias for EulerZXZ
00105    *  Rodriguez - Rodriguez parameters (gamma1, gamma2, gamma3)
00106    */
00107 public:  
00108   typedef Byte Representation;
00109   
00110 public:   
00111   // Static axes
00112   static const Representation EulerXYZs;  
00113   static const Representation EulerXYXs;  
00114   static const Representation EulerXZYs;  
00115   static const Representation EulerXZXs;  
00116   static const Representation EulerYZXs;  
00117   static const Representation EulerYZYs;  
00118   static const Representation EulerYXZs;  
00119   static const Representation EulerYXYs;  
00120   static const Representation EulerZXYs;  
00121   static const Representation EulerZXZs;  
00122   static const Representation EulerZYXs;  
00123   static const Representation EulerZYZs;  
00124   // Rotating axes
00125   static const Representation EulerZYXr; 
00126   static const Representation EulerXYXr; 
00127   static const Representation EulerYZXr; 
00128   static const Representation EulerXZXr; 
00129   static const Representation EulerXZYr; 
00130   static const Representation EulerYZYr; 
00131   static const Representation EulerZXYr; 
00132   static const Representation EulerYXYr; 
00133   static const Representation EulerYXZr; 
00134   static const Representation EulerZXZr; 
00135   static const Representation EulerXYZr; 
00136   static const Representation EulerZYZr; 
00137 
00138   static const Representation LastEuler = 23;
00139   
00140   static const Representation EulerRPY; // EulerXYZs
00141 
00142   static const Representation Quat = 24;
00143   static const Representation Mat  = 25;
00144   static const Representation Rodriguez = 26;
00145   static const Representation RepEnd = 27;
00146 
00147 
00148   /// construct a zero orientation. (like the identify transform - defaults to EulerRPY vector 0)
00149   Orient(); 
00150 
00151   /// construct a zero orientation. (like the identify transform)
00152   Orient(Representation representation);
00153 
00154   /// construct from a quaternion (x,y,z,w)
00155   Orient(const Quat4& q);
00156 
00157   /// construct from EulerRPY
00158   Orient(Real roll, Real pitch, Real yaw);  
00159 
00160   /// construct from a Vector.  
00161   explicit Orient(const Vector& v, Representation representation = EulerRPY);
00162 
00163   /// construct from a 3x3 rotation transformation matrix
00164   Orient(const Matrix3& m3);
00165 
00166   /// construct from a 3x3 rotation transformation matrix
00167   Orient(const Matrix& m);
00168 
00169   Orient(const Orient& copy);
00170 
00171   ~Orient(); 
00172 
00173   
00174   Representation representation() const { return rep; }
00175 
00176   static String representationString(Representation rep);
00177   
00178   static bool isEuler(Representation rep) { return rep<=LastEuler; }
00179   bool isEuler() const { return rep<=LastEuler; }
00180   
00181   static Int size(Representation rep) 
00182   {
00183     if (rep == Mat)  return 9;
00184     if (rep == Quat) return 4;
00185     return 3;
00186   }
00187 
00188   Int size() const 
00189   {
00190     return size(rep);
00191   }
00192 
00193 
00194   Real& operator[](Int i)  
00195   { 
00196     if (rep!=Mat)
00197       return v[i]; 
00198     else {
00199       Int r=i/3;
00200       Int c=i-(r*3);
00201       return (*m)(r,c);
00202     }
00203   }
00204 
00205   const Real& operator[](Int i) const
00206   { 
00207     if (rep!=Mat)
00208       return v[i]; 
00209     else {
00210       Int r=i/3;
00211       Int c=i-(r*3);
00212       return (*m)(r,c);
00213     }
00214   }
00215 
00216   Orient& operator=(const Quat4& q)
00217   {
00218     if (rep == Mat)
00219       delete &(*m);
00220     rep = Quat;
00221     v.resize(4);
00222     v[0]=q.v.x; v[1]=q.v.y; v[2]=q.v.z; v[3]=q.w;
00223     return *this;
00224   }
00225   
00226   Orient& operator=(const Matrix3& mt);
00227   
00228   Orient& operator=(const Orient& copy) throw();
00229 
00230   
00231   void setIdentity(Representation representation = Quat);
00232   void setFromRotationComponent(const Matrix4& mt);  
00233 
00234   /// equality.
00235   /** NB: expensive if representations are not the same (conversion attempted) */
00236   bool operator==(const Orient& o) const throw();
00237 
00238 
00239   bool operator!=(const Orient& o) const throw()
00240     { return !operator==(o); }
00241 
00242   
00243   bool equals(const Orient& o, Real epsilon = consts::epsilon) const throw();
00244 
00245 
00246   void rotatePoint(Point3& p) const
00247   {
00248     Quat4 q(getQuat4());
00249     q.rotatePoint(p);
00250   }
00251   
00252   Point3 rotate(const Point3& p) const
00253   {
00254     Quat4 q(getQuat4());
00255     return q.rotate(p);
00256   }
00257   
00258   void rotatePoint(Point4& p) const
00259   {
00260     Quat4 q(getQuat4());
00261     q.rotatePoint(p);
00262   }
00263   
00264   Point4 rotate(const Point4& p) const
00265   {
00266     Quat4 q(getQuat4());
00267     return q.rotate(p);
00268   }
00269 
00270 
00271   /// invert the rotation (i.e. switch to the reverse rotation)
00272   Orient& invert();
00273   
00274 
00275   /// interpolate between the orientations lower and upper t:[0..1]
00276   static Orient interpolate(const Orient& lower, const Orient& upper, Real t);
00277 
00278   // these involve representation conversion if required
00279   Matrix  getRotationMatrix() const;
00280   Matrix3 getRotationMatrix3() const;
00281   Quat4   getQuat4() const;
00282   Vector  getVector(Representation representation) const;
00283   Vector3 getVector3(Representation representation) const;
00284 
00285   /// automatic conversion to a Vector
00286   operator Vector() const 
00287     { if (rep!=Mat) return v; else return getVector(rep); }
00288 
00289   /// automatic conversion to a rotation matrix
00290   operator Matrix3() const
00291     { return getRotationMatrix3(); }
00292     
00293   /// automatic conversion to a Quat4
00294   operator Quat4() const
00295     { return getQuat4(); }
00296     
00297     
00298   /// request change the internal representation (which may or may not be honored)
00299   void changeRepresentation(Representation newRepresentation)
00300   { try { changeRep(newRepresentation); } catch (std::exception&e) {} }
00301 
00302 
00303   /// returns the inverse of B, such that omega = B(v)^-1 . dv/dt, where omega is angular velocity and v is this orientation
00304   Matrix getBinv() const;
00305 
00306   void serialize(Serializer& s); ///< read or write object state to Serializer
00307 
00308 protected:
00309   mutable Representation rep;
00310   mutable Vector v; ///< component of vector-based representations (Quat, Euler, etc.)
00311   typedef Matrix* MatrixRef;
00312   mutable MatrixRef m; ///< Matrix(3,3) ref if rep==Mat
00313 
00314   enum Axis { X=0, Y=1, Z=2, W=3 };
00315   enum Frame { Static=0, Rotating=1 };
00316   enum Repetition { NonRepeating=0, Repeating=1 };
00317   enum Parity { Even=0, Odd=1 };
00318 
00319   inline static Representation eulerRep(Axis axis, Parity parity, Repetition repetition, Frame frame)
00320   { return Representation(((((((Byte(axis))<<1)+(Byte(parity)))<<1)+(Byte(repetition)))<<1)+(Byte(frame))); }
00321    
00322   static inline Frame      frame(Representation rep)      { return Frame(Byte(rep)&1); }
00323   static inline Repetition repetition(Representation rep) { return Repetition((Byte(rep)>>1)&1); }
00324   static inline Parity     parity(Representation rep)     { return Parity((Byte(rep)>>2)&1); }
00325   
00326   static inline Axis       axisI(Representation rep) { return Axis(EulSafe[((Byte(rep)>>3)&3)]); }
00327   static inline Axis       axisJ(Representation rep) { return Axis(Byte(EulNext[axisI(rep)+(parity(rep)==Odd)])); }
00328   static inline Axis       axisK(Representation rep) { return Axis(Byte(EulNext[axisI(rep)+(parity(rep)!=Odd)])); }
00329   static inline Axis       axisH(Representation rep) { return ((repetition(rep)==NonRepeating)?axisK(rep):axisI(rep)); }
00330   static inline void       getRep(Representation rep, Axis& i, Axis& j, Axis& k, Axis& h,
00331                                                Parity& n, Repetition& s, Frame& f) 
00332     {
00333       Byte o=rep;
00334       f=Frame(o&1); o>>=1;
00335       s=Repetition(o&1); o>>=1; 
00336       n=Parity(o&1); o>>=1;
00337       i=Axis(EulSafe[o&3]);
00338       j=Axis(EulNext[Byte(i)+Byte(n)]);
00339       k=Axis(EulNext[Byte(i)+1-Byte(n)]);
00340       h=s?k:i;
00341     }
00342 
00343   
00344   static Byte EulSafe[4];
00345   static Byte EulNext[4];
00346 
00347 
00348   /// change the current internal representation to that specified.
00349   void changeRep(Representation newRep) const;
00350 
00351   friend std::ostream& operator<<(std::ostream& out, const Orient& o);
00352 };
00353 
00354 
00355 // Operations
00356 
00357 
00358 inline std::ostream& operator<<(std::ostream& out, const Orient& o) // Output
00359 { return (o.rep!=Orient::Mat)?(out << o.v):(out << *o.m); }
00360 
00361 
00362 
00363 } // base
00364 
00365 #endif

Generated on Thu Jul 29 15:56:08 2004 for OpenSim by doxygen 1.3.6