JSBSim Flight Dynamics Model 1.0 (23 February 2013)
An Open Source Flight Dynamics and Control Software Library in C++

FGMatrix33.cpp

00001 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00002 
00003 Module: FGMatrix33.cpp
00004 Author: Tony Peden, Jon Berndt, Mathias Frolich
00005 Date started: 1998
00006 Purpose: FGMatrix33 class
00007 Called by: Various
00008 
00009  ------------- Copyright (C) 1998 by the authors above -------------
00010 
00011  This program is free software; you can redistribute it and/or modify it under
00012  the terms of the GNU Lesser General Public License as published by the Free Software
00013  Foundation; either version 2 of the License, or (at your option) any later
00014  version.
00015 
00016  This program is distributed in the hope that it will be useful, but WITHOUT
00017  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00019  details.
00020 
00021  You should have received a copy of the GNU Lesser General Public License along with
00022  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00023  Place - Suite 330, Boston, MA  02111-1307, USA.
00024 
00025  Further information about the GNU Lesser General Public License can also be found on
00026  the world wide web at http://www.gnu.org.
00027 
00028 FUNCTIONAL DESCRIPTION
00029 --------------------------------------------------------------------------------
00030 
00031 HISTORY
00032 --------------------------------------------------------------------------------
00033 ??/??/??   TP   Created
00034 03/16/2000 JSB  Added exception throwing
00035 
00036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00037 INCLUDES
00038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00039 
00040 #include "FGMatrix33.h"
00041 #include "FGColumnVector3.h"
00042 #include "FGQuaternion.h"
00043 #include <sstream>
00044 #include <iomanip>
00045 
00046 #include <iostream>
00047 
00048 using namespace std;
00049 
00050 namespace JSBSim {
00051 
00052 static const char *IdSrc = "$Id: FGMatrix33.cpp,v 1.14 2012/11/22 22:04:06 bcoconni Exp $";
00053 static const char *IdHdr = ID_MATRIX33;
00054 
00055 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00056 CLASS IMPLEMENTATION
00057 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
00058 
00059 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00060 
00061 FGMatrix33::FGMatrix33(void)
00062 {
00063   data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
00064     data[6] = data[7] = data[8] = 0.0;
00065 }
00066 
00067 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00068 
00069 string FGMatrix33::Dump(const string& delimiter) const
00070 {
00071   ostringstream buffer;
00072   buffer << setw(12) << setprecision(10) << data[0] << delimiter;
00073   buffer << setw(12) << setprecision(10) << data[3] << delimiter;
00074   buffer << setw(12) << setprecision(10) << data[6] << delimiter;
00075   buffer << setw(12) << setprecision(10) << data[1] << delimiter;
00076   buffer << setw(12) << setprecision(10) << data[4] << delimiter;
00077   buffer << setw(12) << setprecision(10) << data[7] << delimiter;
00078   buffer << setw(12) << setprecision(10) << data[2] << delimiter;
00079   buffer << setw(12) << setprecision(10) << data[5] << delimiter;
00080   buffer << setw(12) << setprecision(10) << data[8];
00081   return buffer.str();
00082 }
00083 
00084 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00085 
00086 string FGMatrix33::Dump(const string& delimiter, const string& prefix) const
00087 {
00088   ostringstream buffer;
00089 
00090   buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[0] << delimiter;
00091   buffer << right << fixed << setw(9) << setprecision(6) << data[3] << delimiter;
00092   buffer << right << fixed << setw(9) << setprecision(6) << data[6] << endl;
00093 
00094   buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[1] << delimiter;
00095   buffer << right << fixed << setw(9) << setprecision(6) << data[4] << delimiter;
00096   buffer << right << fixed << setw(9) << setprecision(6) << data[7] << endl;
00097 
00098   buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[2] << delimiter;
00099   buffer << right << fixed << setw(9) << setprecision(6) << data[5] << delimiter;
00100   buffer << right << fixed << setw(9) << setprecision(6) << data[8];
00101 
00102   buffer << setw(0) << left;
00103 
00104   return buffer.str();
00105 }
00106 
00107 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00108 
00109 FGQuaternion FGMatrix33::GetQuaternion(void) const
00110 {
00111   FGQuaternion Q;
00112 
00113   double tempQ[4];
00114   int idx;
00115 
00116   tempQ[0] = 1.0 + data[0] + data[4] + data[8];
00117   tempQ[1] = 1.0 + data[0] - data[4] - data[8];
00118   tempQ[2] = 1.0 - data[0] + data[4] - data[8];
00119   tempQ[3] = 1.0 - data[0] - data[4] + data[8];
00120 
00121   // Find largest of the above
00122   idx = 0;
00123   for (int i=1; i<4; i++) if (tempQ[i] > tempQ[idx]) idx = i;
00124 
00125   switch(idx) {
00126     case 0:
00127       Q(1) = 0.50*sqrt(tempQ[0]);
00128       Q(2) = 0.25*(data[7] - data[5])/Q(1);
00129       Q(3) = 0.25*(data[2] - data[6])/Q(1);
00130       Q(4) = 0.25*(data[3] - data[1])/Q(1);
00131       break;
00132     case 1:
00133       Q(2) = 0.50*sqrt(tempQ[1]);
00134       Q(1) = 0.25*(data[7] - data[5])/Q(2);
00135       Q(3) = 0.25*(data[3] + data[1])/Q(2);
00136       Q(4) = 0.25*(data[2] + data[6])/Q(2);
00137       break;
00138     case 2:
00139       Q(3) = 0.50*sqrt(tempQ[2]);
00140       Q(1) = 0.25*(data[2] - data[6])/Q(3);
00141       Q(2) = 0.25*(data[3] + data[1])/Q(3);
00142       Q(4) = 0.25*(data[7] + data[5])/Q(3);
00143       break;
00144     case 3:
00145       Q(4) = 0.50*sqrt(tempQ[3]);
00146       Q(1) = 0.25*(data[3] - data[1])/Q(4);
00147       Q(2) = 0.25*(data[6] + data[2])/Q(4);
00148       Q(3) = 0.25*(data[7] + data[5])/Q(4);
00149       break;
00150     default:
00151       //error
00152       break;
00153   }
00154 
00155   return (Q);
00156 }
00157 
00158 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00159 // Compute the Euler-angles
00160 // Also see Jack Kuipers, "Quaternions and Rotation Sequences", section 7.8..
00161 
00162 FGColumnVector3 FGMatrix33::GetEuler(void) const
00163 {
00164   FGColumnVector3 mEulerAngles;
00165 
00166   if (data[8] == 0.0)
00167     mEulerAngles(1) = 0.5*M_PI;
00168   else
00169     mEulerAngles(1) = atan2(data[7], data[8]);
00170   
00171   if (data[6] < -1.0)
00172     mEulerAngles(2) = 0.5*M_PI;
00173   else if (1.0 < data[6])
00174     mEulerAngles(2) = -0.5*M_PI;
00175   else
00176     mEulerAngles(2) = asin(-data[6]);
00177   
00178   if (data[0] == 0.0)
00179     mEulerAngles(3) = 0.5*M_PI;
00180   else {
00181     double psi = atan2(data[3], data[0]);
00182     if (psi < 0.0)
00183       psi += 2*M_PI;
00184     mEulerAngles(3) = psi;
00185   }
00186 
00187   return mEulerAngles;
00188 }
00189 
00190 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00191 
00192 ostream& operator<<(ostream& os, const FGMatrix33& M)
00193 {
00194   for (unsigned int i=1; i<=M.Rows(); i++) {
00195     for (unsigned int j=1; j<=M.Cols(); j++) {
00196       if (i == M.Rows() && j == M.Cols())
00197         os << M(i,j);
00198       else
00199         os << M(i,j) << ", ";
00200     }
00201   }
00202   return os;
00203 }
00204 
00205 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00206 
00207 istream& operator>>(istream& is, FGMatrix33& M)
00208 {
00209   for (unsigned int i=1; i<=M.Rows(); i++) {
00210     for (unsigned int j=1; j<=M.Cols(); j++) {
00211       is >> M(i,j);
00212     }
00213   }
00214   return is;
00215 }
00216 
00217 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00218 
00219 double FGMatrix33::Determinant(void) const {
00220   return data[0]*data[4]*data[8] + data[3]*data[7]*data[2]
00221        + data[6]*data[1]*data[5] - data[6]*data[4]*data[2]
00222        - data[3]*data[1]*data[8] - data[7]*data[5]*data[0];
00223 }
00224 
00225 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00226 
00227 FGMatrix33 FGMatrix33::Inverse(void) const {
00228   // Compute the inverse of a general matrix using Cramers rule.
00229   // I guess googling for cramers rule gives tons of references
00230   // for this. :)
00231 
00232   if (Determinant() != 0.0) {
00233     double rdet = 1.0/Determinant();
00234 
00235     double i11 = rdet*(data[4]*data[8]-data[7]*data[5]);
00236     double i21 = rdet*(data[7]*data[2]-data[1]*data[8]);
00237     double i31 = rdet*(data[1]*data[5]-data[4]*data[2]);
00238     double i12 = rdet*(data[6]*data[5]-data[3]*data[8]);
00239     double i22 = rdet*(data[0]*data[8]-data[6]*data[2]);
00240     double i32 = rdet*(data[3]*data[2]-data[0]*data[5]);
00241     double i13 = rdet*(data[3]*data[7]-data[6]*data[4]);
00242     double i23 = rdet*(data[6]*data[1]-data[0]*data[7]);
00243     double i33 = rdet*(data[0]*data[4]-data[3]*data[1]);
00244 
00245     return FGMatrix33( i11, i12, i13,
00246                        i21, i22, i23,
00247                        i31, i32, i33 );
00248   } else {
00249     return FGMatrix33( 0, 0, 0,
00250                        0, 0, 0,
00251                        0, 0, 0 );
00252   }
00253 }
00254 
00255 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00256 
00257 void FGMatrix33::InitMatrix(void)
00258 {
00259   data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
00260     data[6] = data[7] = data[8] = 0.0;
00261 }
00262 
00263 // *****************************************************************************
00264 // binary operators ************************************************************
00265 // *****************************************************************************
00266 
00267 FGMatrix33 FGMatrix33::operator-(const FGMatrix33& M) const
00268 {
00269   return FGMatrix33( data[0] - M.data[0],
00270                      data[3] - M.data[3],
00271                      data[6] - M.data[6],
00272                      data[1] - M.data[1],
00273                      data[4] - M.data[4],
00274                      data[7] - M.data[7],
00275                      data[2] - M.data[2],
00276                      data[5] - M.data[5],
00277                      data[8] - M.data[8] );
00278 }
00279 
00280 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00281 
00282 FGMatrix33& FGMatrix33::operator-=(const FGMatrix33 &M)
00283 {
00284   data[0] -= M.data[0];
00285   data[1] -= M.data[1];
00286   data[2] -= M.data[2];
00287   data[3] -= M.data[3];
00288   data[4] -= M.data[4];
00289   data[5] -= M.data[5];
00290   data[6] -= M.data[6];
00291   data[7] -= M.data[7];
00292   data[8] -= M.data[8];
00293 
00294   return *this;
00295 }
00296 
00297 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00298 
00299 FGMatrix33 FGMatrix33::operator+(const FGMatrix33& M) const
00300 {
00301   return FGMatrix33( data[0] + M.data[0],
00302                      data[3] + M.data[3],
00303                      data[6] + M.data[6],
00304                      data[1] + M.data[1],
00305                      data[4] + M.data[4],
00306                      data[7] + M.data[7],
00307                      data[2] + M.data[2],
00308                      data[5] + M.data[5],
00309                      data[8] + M.data[8] );
00310 }
00311 
00312 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00313 
00314 FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M)
00315 {
00316   data[0] += M.data[0];
00317   data[3] += M.data[3];
00318   data[6] += M.data[6];
00319   data[1] += M.data[1];
00320   data[4] += M.data[4];
00321   data[7] += M.data[7];
00322   data[2] += M.data[2];
00323   data[5] += M.data[5];
00324   data[8] += M.data[8];
00325 
00326   return *this;
00327 }
00328 
00329 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00330 
00331 FGMatrix33 FGMatrix33::operator*(const double scalar) const
00332 {
00333   return FGMatrix33( scalar * data[0],
00334                      scalar * data[3],
00335                      scalar * data[6],
00336                      scalar * data[1],
00337                      scalar * data[4],
00338                      scalar * data[7],
00339                      scalar * data[2],
00340                      scalar * data[5],
00341                      scalar * data[8] );
00342 }
00343 
00344 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00345 /*
00346 FGMatrix33 operator*(double scalar, FGMatrix33 &M)
00347 {
00348   return FGMatrix33( scalar * M(1,1),
00349                      scalar * M(1,2),
00350                      scalar * M(1,3),
00351                      scalar * M(2,1),
00352                      scalar * M(2,2),
00353                      scalar * M(2,3),
00354                      scalar * M(3,1),
00355                      scalar * M(3,2),
00356                      scalar * M(3,3) );
00357 }
00358 */
00359 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00360 
00361 FGMatrix33& FGMatrix33::operator*=(const double scalar)
00362 {
00363   data[0] *= scalar;
00364   data[3] *= scalar;
00365   data[6] *= scalar;
00366   data[1] *= scalar;
00367   data[4] *= scalar;
00368   data[7] *= scalar;
00369   data[2] *= scalar;
00370   data[5] *= scalar;
00371   data[8] *= scalar;
00372 
00373   return *this;
00374 }
00375 
00376 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00377 
00378 FGMatrix33 FGMatrix33::operator*(const FGMatrix33& M) const
00379 {
00380   FGMatrix33 Product;
00381 
00382   Product.data[0] = data[0]*M.data[0] + data[3]*M.data[1] + data[6]*M.data[2];
00383   Product.data[3] = data[0]*M.data[3] + data[3]*M.data[4] + data[6]*M.data[5];
00384   Product.data[6] = data[0]*M.data[6] + data[3]*M.data[7] + data[6]*M.data[8];
00385   Product.data[1] = data[1]*M.data[0] + data[4]*M.data[1] + data[7]*M.data[2];
00386   Product.data[4] = data[1]*M.data[3] + data[4]*M.data[4] + data[7]*M.data[5];
00387   Product.data[7] = data[1]*M.data[6] + data[4]*M.data[7] + data[7]*M.data[8];
00388   Product.data[2] = data[2]*M.data[0] + data[5]*M.data[1] + data[8]*M.data[2];
00389   Product.data[5] = data[2]*M.data[3] + data[5]*M.data[4] + data[8]*M.data[5];
00390   Product.data[8] = data[2]*M.data[6] + data[5]*M.data[7] + data[8]*M.data[8];
00391 
00392   return Product;
00393 }
00394 
00395 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00396 
00397 FGMatrix33& FGMatrix33::operator*=(const FGMatrix33& M)
00398 {
00399   // FIXME: Make compiler friendlier
00400   double a,b,c;
00401 
00402   a = data[0]; b=data[3]; c=data[6];
00403   data[0] = a*M.data[0] + b*M.data[1] + c*M.data[2];
00404   data[3] = a*M.data[3] + b*M.data[4] + c*M.data[5];
00405   data[6] = a*M.data[6] + b*M.data[7] + c*M.data[8];
00406 
00407   a = data[1]; b=data[4]; c=data[7];
00408   data[1] = a*M.data[0] + b*M.data[1] + c*M.data[2];
00409   data[4] = a*M.data[3] + b*M.data[4] + c*M.data[5];
00410   data[7] = a*M.data[6] + b*M.data[7] + c*M.data[8];
00411 
00412   a = data[2]; b=data[5]; c=data[8];
00413   data[2] = a*M.data[0] + b*M.data[1] + c*M.data[2];
00414   data[5] = a*M.data[3] + b*M.data[4] + c*M.data[5];
00415   data[8] = a*M.data[6] + b*M.data[7] + c*M.data[8];
00416 
00417   return *this;
00418 }
00419 
00420 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00421 
00422 FGMatrix33 FGMatrix33::operator/(const double scalar) const
00423 {
00424   FGMatrix33 Quot;
00425 
00426   if ( scalar != 0 ) {
00427     double tmp = 1.0/scalar;
00428     Quot.data[0] = data[0] * tmp;
00429     Quot.data[3] = data[3] * tmp;
00430     Quot.data[6] = data[6] * tmp;
00431     Quot.data[1] = data[1] * tmp;
00432     Quot.data[4] = data[4] * tmp;
00433     Quot.data[7] = data[7] * tmp;
00434     Quot.data[2] = data[2] * tmp;
00435     Quot.data[5] = data[5] * tmp;
00436     Quot.data[8] = data[8] * tmp;
00437   } else {
00438     MatrixException mE;
00439     mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)";
00440     throw mE;
00441   }
00442   return Quot;
00443 }
00444 
00445 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00446 
00447 FGMatrix33& FGMatrix33::operator/=(const double scalar)
00448 {
00449   if ( scalar != 0 ) {
00450     double tmp = 1.0/scalar;
00451     data[0] *= tmp;
00452     data[3] *= tmp;
00453     data[6] *= tmp;
00454     data[1] *= tmp;
00455     data[4] *= tmp;
00456     data[7] *= tmp;
00457     data[2] *= tmp;
00458     data[5] *= tmp;
00459     data[8] *= tmp;
00460   } else {
00461     MatrixException mE;
00462     mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)";
00463     throw mE;
00464   }
00465   return *this;
00466 }
00467 
00468 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00469 
00470 void FGMatrix33::T(void)
00471 {
00472   double tmp;
00473 
00474   tmp = data[3];
00475   data[3] = data[1];
00476   data[1] = tmp;
00477 
00478   tmp = data[6];
00479   data[6] = data[2];
00480   data[2] = tmp;
00481 
00482   tmp = data[7];
00483   data[7] = data[5];
00484   data[5] = tmp;
00485 }
00486 
00487 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00488 
00489 FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const
00490 {
00491   double v1 = v(1);
00492   double v2 = v(2);
00493   double v3 = v(3);
00494 
00495   double tmp1 = v1*data[0];  //[(col-1)*eRows+row-1]
00496   double tmp2 = v1*data[1];
00497   double tmp3 = v1*data[2];
00498 
00499   tmp1 += v2*data[3];
00500   tmp2 += v2*data[4];
00501   tmp3 += v2*data[5];
00502 
00503   tmp1 += v3*data[6];
00504   tmp2 += v3*data[7];
00505   tmp3 += v3*data[8];
00506 
00507   return FGColumnVector3( tmp1, tmp2, tmp3 );
00508 }
00509 
00510 }