FlightGear next
FGQuaternion.h
Go to the documentation of this file.
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3 Header: FGQuaternion.h
4 Author: Jon Berndt, Mathis Froehlich
5 Date started: 12/02/98
6
7 ------- Copyright (C) 1999 Jon S. Berndt (jon@jsbsim.org) ------------------
8 ------- (C) 2004 Mathias Froehlich (Mathias.Froehlich@web.de) ----
9
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
13 version.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 details.
19
20 You should have received a copy of the GNU Lesser General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22 Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 Further information about the GNU Lesser General Public License can also be found on
25 the world wide web at http://www.gnu.org.
26
27HISTORY
28-------------------------------------------------------------------------------
2912/02/98 JSB Created
3015/01/04 MF Quaternion class from old FGColumnVector4
31
32%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33SENTRY
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
35
36#ifndef FGQUATERNION_H
37#define FGQUATERNION_H
38
39/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40 INCLUDES
41 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
42
43#include <string>
44#include "FGJSBBase.h"
45#include "FGColumnVector3.h"
46
47namespace JSBSim {
48
49class FGMatrix33;
50
51/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 CLASS DOCUMENTATION
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
54
81
82/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 CLASS DECLARATION
84 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
85
86class FGQuaternion : public FGJSBBase {
87public:
90 FGQuaternion() : mCacheValid(false) {
91 data[0] = 1.0;
92 data[1] = data[2] = data[3] = 0.0;
93 }
94
98 FGQuaternion(const FGQuaternion& q);
99
105 FGQuaternion(double phi, double tht, double psi);
106
111
117 FGQuaternion(int idx, double angle)
118 : mCacheValid(false) {
119
120 double angle2 = 0.5*angle;
121
122 double Sangle2 = sin(angle2);
123 double Cangle2 = cos(angle2);
124
125 if (idx == ePhi) {
126 data[0] = Cangle2;
127 data[1] = Sangle2;
128 data[2] = 0.0;
129 data[3] = 0.0;
130
131 } else if (idx == eTht) {
132 data[0] = Cangle2;
133 data[1] = 0.0;
134 data[2] = Sangle2;
135 data[3] = 0.0;
136
137 } else {
138 data[0] = Cangle2;
139 data[1] = 0.0;
140 data[2] = 0.0;
141 data[3] = Sangle2;
142
143 }
144 }
145
152 FGQuaternion(double angle, const FGColumnVector3& axis)
153 : mCacheValid(false) {
154
155 double angle2 = 0.5 * angle;
156
157 double length = axis.Magnitude();
158 double Sangle2 = sin(angle2) / length;
159 double Cangle2 = cos(angle2);
160
161 data[0] = Cangle2;
162 data[1] = Sangle2 * axis(1);
163 data[2] = Sangle2 * axis(2);
164 data[3] = Sangle2 * axis(3);
165 }
166
171 FGQuaternion(const FGMatrix33& m);
172
175
183 FGQuaternion GetQDot(const FGColumnVector3& PQR) const;
184
188 const FGMatrix33& GetT(void) const { ComputeDerived(); return mT; }
189
193 const FGMatrix33& GetTInv(void) const { ComputeDerived(); return mTInv; }
194
199 const FGColumnVector3& GetEuler(void) const {
200 ComputeDerived();
201 return mEulerAngles;
202 }
203
210 double GetEuler(int i) const {
211 ComputeDerived();
212 return mEulerAngles(i);
213 }
214
220 double GetEulerDeg(int i) const {
221 ComputeDerived();
222 return radtodeg*mEulerAngles(i);
223 }
224
229 FGColumnVector3 const GetEulerDeg(void) const {
230 ComputeDerived();
231 return radtodeg*mEulerAngles;
232 }
233
237 double GetSinEuler(int i) const {
238 ComputeDerived();
239 return mEulerSines(i);
240 }
241
245 double GetCosEuler(int i) const {
246 ComputeDerived();
247 return mEulerCosines(i);
248 }
249
259 double operator()(unsigned int idx) const { return data[idx-1]; }
260
270 double& operator()(unsigned int idx) { mCacheValid = false; return data[idx-1]; }
271
285 double Entry(unsigned int idx) const { return data[idx-1]; }
286
300 double& Entry(unsigned int idx) {
301 mCacheValid = false;
302 return data[idx-1];
303 }
304
311 // Copy the master values ...
312 data[0] = q.data[0];
313 data[1] = q.data[1];
314 data[2] = q.data[2];
315 data[3] = q.data[3];
316 ComputeDerived();
317 // .. and copy the derived values if they are valid
318 mCacheValid = q.mCacheValid;
319 if (mCacheValid) {
320 mT = q.mT;
321 mTInv = q.mTInv;
322 mEulerAngles = q.mEulerAngles;
323 mEulerSines = q.mEulerSines;
324 mEulerCosines = q.mEulerCosines;
325 }
326 return *this;
327 }
328
330 operator FGMatrix33() const { return GetT(); }
331
335 bool operator==(const FGQuaternion& q) const {
336 return data[0] == q.data[0] && data[1] == q.data[1]
337 && data[2] == q.data[2] && data[3] == q.data[3];
338 }
339
343 bool operator!=(const FGQuaternion& q) const { return ! operator==(q); }
345 // Copy the master values ...
346 data[0] += q.data[0];
347 data[1] += q.data[1];
348 data[2] += q.data[2];
349 data[3] += q.data[3];
350 mCacheValid = false;
351 return *this;
352 }
353
358 // Copy the master values ...
359 data[0] -= q.data[0];
360 data[1] -= q.data[1];
361 data[2] -= q.data[2];
362 data[3] -= q.data[3];
363 mCacheValid = false;
364 return *this;
365 }
366
370 const FGQuaternion& operator*=(double scalar) {
371 data[0] *= scalar;
372 data[1] *= scalar;
373 data[2] *= scalar;
374 data[3] *= scalar;
375 mCacheValid = false;
376 return *this;
377 }
378
382 const FGQuaternion& operator/=(double scalar) {
383 return operator*=(1.0/scalar);
384 }
385
390 return FGQuaternion(data[0]+q.data[0], data[1]+q.data[1],
391 data[2]+q.data[2], data[3]+q.data[3]);
392 }
393
398 return FGQuaternion(data[0]-q.data[0], data[1]-q.data[1],
399 data[2]-q.data[2], data[3]-q.data[3]);
400 }
401
407 return FGQuaternion(data[0]*q.data[0]-data[1]*q.data[1]-data[2]*q.data[2]-data[3]*q.data[3],
408 data[0]*q.data[1]+data[1]*q.data[0]+data[2]*q.data[3]-data[3]*q.data[2],
409 data[0]*q.data[2]-data[1]*q.data[3]+data[2]*q.data[0]+data[3]*q.data[1],
410 data[0]*q.data[3]+data[1]*q.data[2]-data[2]*q.data[1]+data[3]*q.data[0]);
411 }
412
418 double q0 = data[0]*q.data[0]-data[1]*q.data[1]-data[2]*q.data[2]-data[3]*q.data[3];
419 double q1 = data[0]*q.data[1]+data[1]*q.data[0]+data[2]*q.data[3]-data[3]*q.data[2];
420 double q2 = data[0]*q.data[2]-data[1]*q.data[3]+data[2]*q.data[0]+data[3]*q.data[1];
421 double q3 = data[0]*q.data[3]+data[1]*q.data[2]-data[2]*q.data[1]+data[3]*q.data[0];
422 data[0] = q0;
423 data[1] = q1;
424 data[2] = q2;
425 data[3] = q3;
426 mCacheValid = false;
427 return *this;
428 }
429
436 FGQuaternion Inverse(void) const {
437 double norm = SqrMagnitude();
438 if (norm == 0.0)
439 return *this;
440 double rNorm = 1.0/norm;
441 return FGQuaternion( data[0]*rNorm, -data[1]*rNorm,
442 -data[2]*rNorm, -data[3]*rNorm );
443 }
444
451 return FGQuaternion( data[0], -data[1], -data[2], -data[3] );
452 }
453
454 friend FGQuaternion operator*(double, const FGQuaternion&);
455
460 double Magnitude(void) const { return sqrt(SqrMagnitude()); }
461
466 double SqrMagnitude(void) const {
467 return data[0]*data[0] + data[1]*data[1]
468 + data[2]*data[2] + data[3]*data[3];
469 }
470
476 void Normalize(void);
477
480 static FGQuaternion zero(void) { return FGQuaternion( 0.0, 0.0, 0.0, 0.0 ); }
481
482 std::string Dump(const std::string& delimiter) const;
483
484 friend FGQuaternion QExp(const FGColumnVector3& omega);
485
486private:
488 FGQuaternion(double q1, double q2, double q3, double q4) : mCacheValid(false)
489 { data[0] = q1; data[1] = q2; data[2] = q3; data[3] = q4; }
490
494 void ComputeDerivedUnconditional(void) const;
495
502 void ComputeDerived(void) const {
503 if (!mCacheValid)
504 ComputeDerivedUnconditional();
505 }
506
508 double data[4];
509
516 mutable bool mCacheValid;
517
519 mutable FGMatrix33 mT;
520 mutable FGMatrix33 mTInv;
521
523 mutable FGColumnVector3 mEulerAngles;
524
526 mutable FGColumnVector3 mEulerSines;
527 mutable FGColumnVector3 mEulerCosines;
528
529 void InitializeFromEulerAngles(double phi, double tht, double psi);
530};
531
539inline FGQuaternion operator*(double scalar, const FGQuaternion& q) {
540 return FGQuaternion(scalar*q.data[0], scalar*q.data[1], scalar*q.data[2], scalar*q.data[3]);
541}
542
548inline FGQuaternion QExp(const FGColumnVector3& omega) {
549 FGQuaternion qexp;
550 double angle = omega.Magnitude();
551 double sina_a = angle > 0.0 ? sin(angle)/angle : 1.0;
552
553 qexp.data[0] = cos(angle);
554 qexp.data[1] = omega(1) * sina_a;
555 qexp.data[2] = omega(2) * sina_a;
556 qexp.data[3] = omega(3) * sina_a;
557
558 return qexp;
559}
560
565std::ostream& operator<<(std::ostream& os, const FGQuaternion& q);
566
567} // namespace JSBSim
568#endif
#define i(x)
This class implements a 3 element column vector.
double Magnitude(void) const
Length of the vector.
static constexpr double radtodeg
Definition FGJSBBase.h:348
FGJSBBase()
Constructor for FGJSBBase.
Definition FGJSBBase.h:81
Handles matrix math operations.
Definition FGMatrix33.h:70
Models the Quaternion representation of rotations.
const FGMatrix33 & GetT(void) const
Transformation matrix.
double GetSinEuler(int i) const
Retrieves sine of the given euler angle.
const FGQuaternion & operator/=(double scalar)
Arithmetic operator "/=".
double Entry(unsigned int idx) const
Read access the entries of the vector.
FGQuaternion operator*(const FGQuaternion &q) const
Arithmetic operator "*".
FGQuaternion(int idx, double angle)
Initializer by one euler angle.
FGQuaternion operator+(const FGQuaternion &q) const
Arithmetic operator "+".
const FGQuaternion & operator+=(const FGQuaternion &q)
double GetCosEuler(int i) const
Retrieves cosine of the given euler angle.
double & operator()(unsigned int idx)
Write access the entries of the vector.
const FGColumnVector3 & GetEuler(void) const
Retrieves the Euler angles.
bool operator==(const FGQuaternion &q) const
Comparison operator "==".
double operator()(unsigned int idx) const
Read access the entries of the vector.
FGQuaternion(double angle, const FGColumnVector3 &axis)
Initializer by a rotation axis and an angle.
double SqrMagnitude(void) const
Square of the length of the vector.
double & Entry(unsigned int idx)
Write access the entries of the vector.
~FGQuaternion()
Destructor.
const FGQuaternion & operator=(const FGQuaternion &q)
Assignment operator "=".
const FGQuaternion & operator*=(double scalar)
Arithmetic operator "*=".
FGColumnVector3 const GetEulerDeg(void) const
Retrieves the Euler angle vector.
FGQuaternion GetQDot(const FGColumnVector3 &PQR) const
Quaternion derivative for given angular rates.
FGQuaternion Inverse(void) const
Inverse of the quaternion.
static FGQuaternion zero(void)
Zero quaternion vector.
double GetEuler(int i) const
Retrieves the Euler angles.
FGQuaternion operator-(const FGQuaternion &q) const
Arithmetic operator "-".
const FGQuaternion & operator-=(const FGQuaternion &q)
Arithmetic operator "-=".
friend FGQuaternion QExp(const FGColumnVector3 &omega)
Quaternion exponential.
FGQuaternion Conjugate(void) const
Conjugate of the quaternion.
const FGMatrix33 & GetTInv(void) const
Backward transformation matrix.
bool operator!=(const FGQuaternion &q) const
Comparison operator "!=".
double GetEulerDeg(int i) const
Retrieves the Euler angles.
double Magnitude(void) const
Length of the vector.
FGQuaternion()
Default initializer.
const FGQuaternion & operator*=(const FGQuaternion &q)
Arithmetic operator "*=".
void Normalize(void)
Normalize.
std::string Dump(const std::string &delimiter) const
ostream & operator<<(ostream &os, const FGColumnVector3 &col)
Write vector to a stream.
FGColumnVector3 operator*(double scalar, const FGColumnVector3 &A)
Scalar multiplication.
FGQuaternion QExp(const FGColumnVector3 &omega)
Quaternion exponential.