src/vamos/body/Frame.cc

Go to the documentation of this file.
00001 //  Frame.cc - a coordinate system.
00002 //
00003 //  Copyright (C) 2001--2004 Sam Varner
00004 //
00005 //  This file is part of Vamos Automotive Simulator.
00006 //
00007 //  This program is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU General Public License as published by
00009 //  the Free Software Foundation; either version 2 of the License, or
00010 //  (at your option) any later version.
00011 //
00012 //  This program is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU General Public License
00018 //  along with this program; if not, write to the Free Software
00019 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 
00021 #include <vamos/body/Frame.h>
00022 #include <vamos/geometry/Conversions.h>
00023 
00024 #include <cassert>
00025 #include <cmath>
00026 
00027 using Vamos_Geometry::Three_Vector;
00028 using Vamos_Geometry::Three_Matrix;
00029 
00030 //* Class Frame
00031 
00032 //** Constructors
00033 
00034 // Specify the position and orientation.
00035 Vamos_Body::Frame::
00036 Frame (const Three_Vector& position, const Three_Matrix& orientation) :
00037   m_position (position),
00038   m_orientation (orientation)
00039 {
00040 }
00041 
00042 // Take the parent's orientation.
00043 Vamos_Body::Frame::
00044 Frame (const Three_Vector& position) :
00045   m_position (position)
00046 {
00047   m_orientation.identity ();
00048 }
00049 
00050 // Make a frame that's coincident with the parent frame.
00051 Vamos_Body::Frame::
00052 Frame ()
00053 {
00054   m_orientation.identity ();
00055 }
00056 
00057 // VEC is a vector in the parent's frame.  The representation of VEC
00058 // in this frame is returned.
00059 Three_Vector Vamos_Body::Frame::
00060 transform_in (const Three_Vector& vec) const
00061 {
00062   return rotate_in (vec - m_position);
00063 }
00064 
00065 // VEC is a vector in this frame.  The representation of VEC in the
00066 // parent's frame is returned.
00067 Three_Vector Vamos_Body::Frame::
00068 transform_out (const Three_Vector& vec) const
00069 {
00070   return rotate_out (vec) + m_position;
00071 }
00072 
00073 // Same as transform_out (VEC) above, except that the rotation is
00074 // about the point PIVOT expressed in this frame's coordinates.
00075 Three_Vector Vamos_Body::Frame::
00076 transform_out (const Three_Vector& vec, const Three_Vector& pivot) const
00077 {
00078   return rotate_out (vec - pivot) + m_position;
00079 }
00080 
00081 // Rotate the frame about the vector delta_theta, by an angle equal to
00082 // the magnitude of DELTA_THETA.
00083 void Vamos_Body::Frame::
00084 rotate (const Three_Vector& delta_theta)
00085 {
00086   m_orientation.rotate (delta_theta);
00087 }
00088 
00089 // Express the orientation of this frame as a vector in the parent
00090 // frame and a rotation about that vector.  ANGLE holds the rotation
00091 // angle when the function returns.  The returned vector has a
00092 // magnitude of sin (ANGLE).  The values returned are suitable for use
00093 // with the glRotate functions.
00094 Three_Vector Vamos_Body::Frame::
00095 axis_angle (double* angle) const
00096 {
00097   // To convert the rotation matrix representation of the body's orientation
00098   // to an axis-angle orientation, we transform first to a quaternion
00099   // representation.  The matrix-to-quaternion and quaternion-to-axis-angle
00100   // transformations are described in the Matrix and Quaternion FAQ 
00101   // (matrixfaq.htm) in the doc directory.
00102 
00103   // Make a local reference to the tranformation matrix for brevity.
00104   const Three_Matrix& omat = m_orientation;
00105 
00106   // Convert from matrix to quaternion
00107   double trace = omat [0][0] + omat [1][1] + omat [2][2] + 1.0;
00108   double s, w, x, y, z;
00109   s = w = x = y = z = 0.0;
00110   if (trace > 0.0)
00111     {
00112       s = 0.5 / sqrt (trace);
00113       w = 0.25 / s;
00114       x = (omat [2][1] - omat [1][2]) * s;
00115       y = (omat [0][2] - omat [2][0]) * s;
00116       z = (omat [1][0] - omat [0][1]) * s;
00117     }
00118   else
00119     {
00120       // Find the largest diagonal element and do the appropriate
00121       // transformation.
00122       double largest = omat [0][0];
00123       int index = 0;
00124       if (omat [1][1] > largest)
00125         {
00126           largest = omat [1][1];
00127           index = 1;
00128         }
00129 
00130       if (omat [2][2] > largest)
00131         {
00132           largest = omat [2][2];
00133           s = sqrt (1.0 - omat [0][0] - omat [1][1] + omat [2][2]) * 2.0;
00134           w = (omat [0][1] + omat [1][0]) / s;
00135           x = (omat [0][2] + omat [2][0]) / s;
00136           y = (omat [1][2] + omat [2][1]) / s;
00137           z = 0.5 / s;
00138         }
00139       else if (index == 0)
00140         {
00141           s = sqrt (1.0 + omat [0][0] - omat [1][1] - omat [2][2]) * 2.0;
00142           w = (omat [1][2] + omat [2][1]) / s;
00143           x = 0.5 / s;
00144           y = (omat [0][1] + omat [1][0]) / s;
00145           z = (omat [0][2] + omat [2][0]) / s;
00146         }
00147       else
00148         {
00149           assert (index == 1);
00150           s = sqrt (1.0 - omat [0][0] + omat [1][1] - omat [2][2]) * 2.0;
00151           w = (omat [0][2] + omat [2][0]) / s;
00152           x = (omat [0][1] + omat [1][0]) / s;
00153           y = 0.5 / s;
00154           z = (omat [1][2] + omat [2][1]) / s;
00155         }
00156     }
00157 
00158   // Convert from quaternion to angle-axis.
00159   *angle = Vamos_Geometry::rad_to_deg (acos (w) * 2.0);
00160 
00161   // The return value would be divided by sin (angle) to give a unit
00162   // vector, but glRotate* () does not care about the length so we'll
00163   // leave it as is.
00164   return Three_Vector (x, y, z);
00165 }

Generated on Thu Oct 19 04:05:55 2006 by  doxygen 1.4.6