JSBSim Flight Dynamics Model 1.3.0 (09 Apr 2026)
An Open Source Flight Dynamics and Control Software Library in C++
Loading...
Searching...
No Matches
FGMatrix33.cpp
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3Module: FGMatrix33.cpp
4Author: Tony Peden, Jon Berndt, Mathias Frolich
5Date started: 1998
6Purpose: FGMatrix33 class
7Called by: Various
8
9 ------------- Copyright (C) 1998 by the authors above -------------
10
11 This program is free software; you can redistribute it and/or modify it under
12 the terms of the GNU Lesser General Public License as published by the Free
13 Software Foundation; either version 2 of the License, or (at your option) any
14 later version.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19 details.
20
21 You should have received a copy of the GNU Lesser General Public License along
22 with this program; if not, write to the Free Software Foundation, Inc., 59
23 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25 Further information about the GNU Lesser General Public License can also be
26 found on the world wide web at http://www.gnu.org.
27
28FUNCTIONAL DESCRIPTION
29--------------------------------------------------------------------------------
30
31HISTORY
32--------------------------------------------------------------------------------
33??/??/?? TP Created
3403/16/2000 JSB Added exception throwing
35
36%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37INCLUDES
38%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39
40#include "FGMatrix33.h"
41#include "FGColumnVector3.h"
42#include "FGQuaternion.h"
43#include <sstream>
44#include <iomanip>
45
46#include <iostream>
47
48using namespace std;
49
50namespace JSBSim {
51
52/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53CLASS IMPLEMENTATION
54%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
55
56//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57
59{
60 data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
61 data[6] = data[7] = data[8] = 0.0;
62}
63
64//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65
66string FGMatrix33::Dump(const string& delimiter) const
67{
68 ostringstream buffer;
69 buffer << setw(12) << setprecision(10) << data[0] << delimiter;
70 buffer << setw(12) << setprecision(10) << data[3] << delimiter;
71 buffer << setw(12) << setprecision(10) << data[6] << delimiter;
72 buffer << setw(12) << setprecision(10) << data[1] << delimiter;
73 buffer << setw(12) << setprecision(10) << data[4] << delimiter;
74 buffer << setw(12) << setprecision(10) << data[7] << delimiter;
75 buffer << setw(12) << setprecision(10) << data[2] << delimiter;
76 buffer << setw(12) << setprecision(10) << data[5] << delimiter;
77 buffer << setw(12) << setprecision(10) << data[8];
78 return buffer.str();
79}
80
81//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82
83string FGMatrix33::Dump(const string& delimiter, const string& prefix) const
84{
85 ostringstream buffer;
86
87 buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[0] << delimiter;
88 buffer << right << fixed << setw(9) << setprecision(6) << data[3] << delimiter;
89 buffer << right << fixed << setw(9) << setprecision(6) << data[6] << endl;
90
91 buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[1] << delimiter;
92 buffer << right << fixed << setw(9) << setprecision(6) << data[4] << delimiter;
93 buffer << right << fixed << setw(9) << setprecision(6) << data[7] << endl;
94
95 buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[2] << delimiter;
96 buffer << right << fixed << setw(9) << setprecision(6) << data[5] << delimiter;
97 buffer << right << fixed << setw(9) << setprecision(6) << data[8];
98
99 buffer << setw(0) << left;
100
101 return buffer.str();
102}
103
104//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
105
107{
108 FGQuaternion Q;
109
110 double tempQ[4];
111 int idx;
112
113 tempQ[0] = 1.0 + data[0] + data[4] + data[8];
114 tempQ[1] = 1.0 + data[0] - data[4] - data[8];
115 tempQ[2] = 1.0 - data[0] + data[4] - data[8];
116 tempQ[3] = 1.0 - data[0] - data[4] + data[8];
117
118 // Find largest of the above
119 idx = 0;
120 for (int i=1; i<4; i++) if (tempQ[i] > tempQ[idx]) idx = i;
121
122 switch(idx) {
123 case 0:
124 Q(1) = 0.50*sqrt(tempQ[0]);
125 Q(2) = 0.25*(data[7] - data[5])/Q(1);
126 Q(3) = 0.25*(data[2] - data[6])/Q(1);
127 Q(4) = 0.25*(data[3] - data[1])/Q(1);
128 break;
129 case 1:
130 Q(2) = 0.50*sqrt(tempQ[1]);
131 Q(1) = 0.25*(data[7] - data[5])/Q(2);
132 Q(3) = 0.25*(data[3] + data[1])/Q(2);
133 Q(4) = 0.25*(data[2] + data[6])/Q(2);
134 break;
135 case 2:
136 Q(3) = 0.50*sqrt(tempQ[2]);
137 Q(1) = 0.25*(data[2] - data[6])/Q(3);
138 Q(2) = 0.25*(data[3] + data[1])/Q(3);
139 Q(4) = 0.25*(data[7] + data[5])/Q(3);
140 break;
141 case 3:
142 Q(4) = 0.50*sqrt(tempQ[3]);
143 Q(1) = 0.25*(data[3] - data[1])/Q(4);
144 Q(2) = 0.25*(data[6] + data[2])/Q(4);
145 Q(3) = 0.25*(data[7] + data[5])/Q(4);
146 break;
147 default:
148 //error
149 break;
150 }
151
152 return (Q);
153}
154
155//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156// Compute the Euler-angles
157// Also see Jack Kuipers, "Quaternions and Rotation Sequences", section 7.8..
158
160{
161 FGColumnVector3 mEulerAngles;
162 bool GimbalLock = false;
163
164 if (data[6] <= -1.0) {
165 mEulerAngles(2) = 0.5*M_PI;
166 GimbalLock = true;
167 }
168 else if (1.0 <= data[6]) {
169 mEulerAngles(2) = -0.5*M_PI;
170 GimbalLock = true;
171 }
172 else
173 mEulerAngles(2) = asin(-data[6]);
174
175 if (GimbalLock)
176 mEulerAngles(1) = atan2(-data[5], data[4]);
177 else
178 mEulerAngles(1) = atan2(data[7], data[8]);
179
180 if (GimbalLock)
181 mEulerAngles(3) = 0.0;
182 else {
183 double psi = atan2(data[3], data[0]);
184 if (psi < 0.0)
185 psi += 2*M_PI;
186 mEulerAngles(3) = psi;
187 }
188
189 return mEulerAngles;
190}
191
192//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193
194ostream& operator<<(ostream& os, const FGMatrix33& M)
195{
196 for (unsigned int i=1; i<=M.Rows(); i++) {
197 for (unsigned int j=1; j<=M.Cols(); j++) {
198 if (i == M.Rows() && j == M.Cols())
199 os << M(i,j);
200 else
201 os << M(i,j) << ", ";
202 }
203 }
204 return os;
205}
206
207//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208
209istream& operator>>(istream& is, FGMatrix33& M)
210{
211 for (unsigned int i=1; i<=M.Rows(); i++) {
212 for (unsigned int j=1; j<=M.Cols(); j++) {
213 is >> M(i,j);
214 }
215 }
216 return is;
217}
218
219//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220
221double FGMatrix33::Determinant(void) const {
222 return data[0]*data[4]*data[8] + data[3]*data[7]*data[2]
223 + data[6]*data[1]*data[5] - data[6]*data[4]*data[2]
224 - data[3]*data[1]*data[8] - data[7]*data[5]*data[0];
225}
226
227//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228
230 // Compute the inverse of a general matrix using Cramers rule.
231 // I guess googling for cramers rule gives tons of references
232 // for this. :)
233
234 if (Determinant() != 0.0) {
235 double rdet = 1.0/Determinant();
236
237 double i11 = rdet*(data[4]*data[8]-data[7]*data[5]);
238 double i21 = rdet*(data[7]*data[2]-data[1]*data[8]);
239 double i31 = rdet*(data[1]*data[5]-data[4]*data[2]);
240 double i12 = rdet*(data[6]*data[5]-data[3]*data[8]);
241 double i22 = rdet*(data[0]*data[8]-data[6]*data[2]);
242 double i32 = rdet*(data[3]*data[2]-data[0]*data[5]);
243 double i13 = rdet*(data[3]*data[7]-data[6]*data[4]);
244 double i23 = rdet*(data[6]*data[1]-data[0]*data[7]);
245 double i33 = rdet*(data[0]*data[4]-data[3]*data[1]);
246
247 return FGMatrix33( i11, i12, i13,
248 i21, i22, i23,
249 i31, i32, i33 );
250 } else {
251 return FGMatrix33( 0, 0, 0,
252 0, 0, 0,
253 0, 0, 0 );
254 }
255}
256
257//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258
260{
261 data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
262 data[6] = data[7] = data[8] = 0.0;
263}
264
265// *****************************************************************************
266// binary operators ************************************************************
267// *****************************************************************************
268
270{
271 return FGMatrix33( data[0] - M.data[0],
272 data[3] - M.data[3],
273 data[6] - M.data[6],
274 data[1] - M.data[1],
275 data[4] - M.data[4],
276 data[7] - M.data[7],
277 data[2] - M.data[2],
278 data[5] - M.data[5],
279 data[8] - M.data[8] );
280}
281
282//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
283
285{
286 data[0] -= M.data[0];
287 data[1] -= M.data[1];
288 data[2] -= M.data[2];
289 data[3] -= M.data[3];
290 data[4] -= M.data[4];
291 data[5] -= M.data[5];
292 data[6] -= M.data[6];
293 data[7] -= M.data[7];
294 data[8] -= M.data[8];
295
296 return *this;
297}
298
299//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300
302{
303 return FGMatrix33( data[0] + M.data[0],
304 data[3] + M.data[3],
305 data[6] + M.data[6],
306 data[1] + M.data[1],
307 data[4] + M.data[4],
308 data[7] + M.data[7],
309 data[2] + M.data[2],
310 data[5] + M.data[5],
311 data[8] + M.data[8] );
312}
313
314//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315
317{
318 data[0] += M.data[0];
319 data[3] += M.data[3];
320 data[6] += M.data[6];
321 data[1] += M.data[1];
322 data[4] += M.data[4];
323 data[7] += M.data[7];
324 data[2] += M.data[2];
325 data[5] += M.data[5];
326 data[8] += M.data[8];
327
328 return *this;
329}
330
331//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332
333FGMatrix33 FGMatrix33::operator*(const double scalar) const
334{
335 return FGMatrix33( scalar * data[0],
336 scalar * data[3],
337 scalar * data[6],
338 scalar * data[1],
339 scalar * data[4],
340 scalar * data[7],
341 scalar * data[2],
342 scalar * data[5],
343 scalar * data[8] );
344}
345
346//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347/*
348FGMatrix33 operator*(double scalar, FGMatrix33 &M)
349{
350 return FGMatrix33( scalar * M(1,1),
351 scalar * M(1,2),
352 scalar * M(1,3),
353 scalar * M(2,1),
354 scalar * M(2,2),
355 scalar * M(2,3),
356 scalar * M(3,1),
357 scalar * M(3,2),
358 scalar * M(3,3) );
359}
360*/
361//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
362
364{
365 data[0] *= scalar;
366 data[3] *= scalar;
367 data[6] *= scalar;
368 data[1] *= scalar;
369 data[4] *= scalar;
370 data[7] *= scalar;
371 data[2] *= scalar;
372 data[5] *= scalar;
373 data[8] *= scalar;
374
375 return *this;
376}
377
378//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379
381{
382 FGMatrix33 Product;
383
384 Product.data[0] = data[0]*M.data[0] + data[3]*M.data[1] + data[6]*M.data[2];
385 Product.data[3] = data[0]*M.data[3] + data[3]*M.data[4] + data[6]*M.data[5];
386 Product.data[6] = data[0]*M.data[6] + data[3]*M.data[7] + data[6]*M.data[8];
387 Product.data[1] = data[1]*M.data[0] + data[4]*M.data[1] + data[7]*M.data[2];
388 Product.data[4] = data[1]*M.data[3] + data[4]*M.data[4] + data[7]*M.data[5];
389 Product.data[7] = data[1]*M.data[6] + data[4]*M.data[7] + data[7]*M.data[8];
390 Product.data[2] = data[2]*M.data[0] + data[5]*M.data[1] + data[8]*M.data[2];
391 Product.data[5] = data[2]*M.data[3] + data[5]*M.data[4] + data[8]*M.data[5];
392 Product.data[8] = data[2]*M.data[6] + data[5]*M.data[7] + data[8]*M.data[8];
393
394 return Product;
395}
396
397//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398
400{
401 // FIXME: Make compiler friendlier
402 double a,b,c;
403
404 a = data[0]; b=data[3]; c=data[6];
405 data[0] = a*M.data[0] + b*M.data[1] + c*M.data[2];
406 data[3] = a*M.data[3] + b*M.data[4] + c*M.data[5];
407 data[6] = a*M.data[6] + b*M.data[7] + c*M.data[8];
408
409 a = data[1]; b=data[4]; c=data[7];
410 data[1] = a*M.data[0] + b*M.data[1] + c*M.data[2];
411 data[4] = a*M.data[3] + b*M.data[4] + c*M.data[5];
412 data[7] = a*M.data[6] + b*M.data[7] + c*M.data[8];
413
414 a = data[2]; b=data[5]; c=data[8];
415 data[2] = a*M.data[0] + b*M.data[1] + c*M.data[2];
416 data[5] = a*M.data[3] + b*M.data[4] + c*M.data[5];
417 data[8] = a*M.data[6] + b*M.data[7] + c*M.data[8];
418
419 return *this;
420}
421
422//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423
424FGMatrix33 FGMatrix33::operator/(const double scalar) const
425{
426 FGMatrix33 Quot;
427
428 double tmp = 1.0/scalar;
429 Quot.data[0] = data[0] * tmp;
430 Quot.data[3] = data[3] * tmp;
431 Quot.data[6] = data[6] * tmp;
432 Quot.data[1] = data[1] * tmp;
433 Quot.data[4] = data[4] * tmp;
434 Quot.data[7] = data[7] * tmp;
435 Quot.data[2] = data[2] * tmp;
436 Quot.data[5] = data[5] * tmp;
437 Quot.data[8] = data[8] * tmp;
438
439 return Quot;
440}
441
442//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443
445{
446 double tmp = 1.0/scalar;
447 data[0] *= tmp;
448 data[3] *= tmp;
449 data[6] *= tmp;
450 data[1] *= tmp;
451 data[4] *= tmp;
452 data[7] *= tmp;
453 data[2] *= tmp;
454 data[5] *= tmp;
455 data[8] *= tmp;
456
457 return *this;
458}
459
460//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461
463{
464 double tmp;
465
466 tmp = data[3];
467 data[3] = data[1];
468 data[1] = tmp;
469
470 tmp = data[6];
471 data[6] = data[2];
472 data[2] = tmp;
473
474 tmp = data[7];
475 data[7] = data[5];
476 data[5] = tmp;
477}
478
479//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
480
482{
483 double v1 = v(1);
484 double v2 = v(2);
485 double v3 = v(3);
486
487 double tmp1 = v1*data[0]; //[(col-1)*eRows+row-1]
488 double tmp2 = v1*data[1];
489 double tmp3 = v1*data[2];
490
491 tmp1 += v2*data[3];
492 tmp2 += v2*data[4];
493 tmp3 += v2*data[5];
494
495 tmp1 += v3*data[6];
496 tmp2 += v3*data[7];
497 tmp3 += v3*data[8];
498
499 return FGColumnVector3( tmp1, tmp2, tmp3 );
500}
501
502}
This class implements a 3 element column vector.
Handles matrix math operations.
Definition FGMatrix33.h:70
void T(void)
Transposes this matrix.
FGMatrix33 operator+(const FGMatrix33 &B) const
Matrix addition.
FGMatrix33 & operator+=(const FGMatrix33 &B)
In place matrix addition.
unsigned int Cols(void) const
Number of cloumns in the matrix.
Definition FGMatrix33.h:214
FGMatrix33 & operator*=(const FGMatrix33 &B)
In place matrix multiplication.
FGColumnVector3 operator*(const FGColumnVector3 &v) const
Matrix vector multiplication.
FGMatrix33 Inverse(void) const
Return the inverse of the matrix.
double Determinant(void) const
Determinant of the matrix.
FGMatrix33 & operator/=(const double scalar)
In place matrix scale.
FGMatrix33 operator-(const FGMatrix33 &B) const
Matrix subtraction.
std::string Dump(const std::string &delimeter) const
Prints the contents of the matrix.
FGQuaternion GetQuaternion(void) const
Returns the quaternion associated with this direction cosine (rotation) matrix.
FGMatrix33 & operator-=(const FGMatrix33 &B)
In place matrix subtraction.
unsigned int Rows(void) const
Number of rows in the matrix.
Definition FGMatrix33.h:209
FGMatrix33 operator/(const double scalar) const
Multiply the matrix with 1.0/scalar.
FGMatrix33(void)
Default initializer.
void InitMatrix(void)
Initialize the matrix.
FGColumnVector3 GetEuler() const
Returns the Euler angle column vector associated with this matrix.
Models the Quaternion representation of rotations.
Main namespace for the JSBSim Flight Dynamics Model.
Definition FGFDMExec.cpp:71
istream & operator>>(istream &is, FGMatrix33 &M)
Read matrix from a stream.
ostream & operator<<(ostream &os, const FGColumnVector3 &col)
Write vector to a stream.