![]() |
JSBSim Flight Dynamics Model 1.0 (23 February 2013)
An Open Source Flight Dynamics and Control Software Library in C++
|
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 }