]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/math/FGLocation.h
Use tiedPropertyLists instead of manually matched tie/untie calls.
[flightgear.git] / src / FDM / JSBSim / math / FGLocation.h
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Header:       FGLocation.h
4  Author:       Jon S. Berndt, Mathias Froehlich
5  Date started: 04/04/2004
6
7  ------- Copyright (C) 1999  Jon S. Berndt (jon@jsbsim.org) ------------------
8  -------           (C) 2004  Mathias Froehlich (Mathias.Froehlich@web.de) ----
9  -------           (C) 2011  Ola Røer Thorsen (ola@silentwings.no) -----------
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 Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  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 with
22  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23  Place - Suite 330, Boston, MA  02111-1307, USA.
24
25  Further information about the GNU Lesser General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27
28 HISTORY
29 -------------------------------------------------------------------------------
30 04/04/2004   MF   Created from code previously in the old positions class.
31 11/01/2011   ORT  Encapsulated ground callback code in FGLocation and removed
32                   it from FGFDMExec.
33
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 SENTRY
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
37
38 #ifndef FGLOCATION_H
39 #define FGLOCATION_H
40
41 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 INCLUDES
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
44
45 #include "FGJSBBase.h"
46 #include "input_output/FGPropertyManager.h"
47 #include "FGColumnVector3.h"
48 #include "FGMatrix33.h"
49 #include "input_output/FGGroundCallback.h"
50
51 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 DEFINITIONS
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
54
55 #define ID_LOCATION "$Id: FGLocation.h,v 1.29 2011/11/06 18:14:51 bcoconni Exp $"
56
57 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
58 FORWARD DECLARATIONS
59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
60
61 namespace JSBSim {
62
63 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
64 CLASS DOCUMENTATION
65 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
66
67 /** FGLocation holds an arbitrary location in the Earth centered Earth fixed
68     reference frame (ECEF). This coordinate frame has its center in the middle
69     of the earth. The X-axis points from the center of the Earth towards a
70     location with zero latitude and longitude on the Earth surface. The Y-axis
71     points from the center of the Earth towards a location with zero latitude
72     and 90 deg East longitude on the Earth surface. The Z-axis points from the
73     Earth center to the geographic north pole.
74
75     This class provides access functions to set and get the location as either
76     the simple X, Y and Z values in ft or longitude/latitude and the radial
77     distance of the location from the Earth center.
78
79     It is common to associate a parent frame with a location. This frame is
80     usually called the local horizontal frame or simply the local frame. It is
81     also called the NED frame (North, East, Down), as well as the Navigation
82     frame. This frame has its X/Y plane parallel to the surface of the Earth
83     (with the assumption of a spherical Earth). The X-axis points towards north,
84     the Y-axis points east and the Z-axis points to the center of the Earth.
85
86     Since the local frame is determined by the location (and NOT by the
87     orientation of the  vehicle IN any frame), this class also provides the
88     rotation matrices required to transform from the Earth centered (ECEF) frame
89     to the local horizontal frame and back. This class also "owns" the
90     transformations that go from the inertial frame (Earth-centered Inertial, or
91     ECI) to and from the ECEF frame, as well as to and from the local frame.
92     Again, this is because the ECI, ECEF, and local frames do not involve the
93     actual orientation of the vehicle - only the location on the Earth surface,
94     and the angular difference between the ECI and ECEF frames. There are
95     conversion functions for conversion of position vectors given in the one
96     frame to positions in the other frame.
97
98     The Earth centered reference frame is NOT an inertial frame since it rotates
99     with the Earth.
100
101     The coordinates in the Earth centered frame are the master values. All other
102     values are computed from these master values and are cached as long as the
103     location is changed by access through a non-const member function. Values
104     are cached to improve performance. It is best practice to work with a
105     natural set of master values. Other parameters that are derived from these
106     master values are calculated only when needed, and IF they are needed and
107     calculated, then they are cached (stored and remembered) so they do not need
108     to be re-calculated until the master values they are derived from are
109     themselves changed (and become stale).
110
111     Accuracy and round off
112
113     Given,
114
115     -that we model a vehicle near the Earth
116     -that the Earth surface radius is about 2*10^7, ft
117     -that we use double values for the representation of the location
118     
119     we have an accuracy of about
120     
121     1e-16*2e7ft/1 = 2e-9 ft
122     
123     left. This should be sufficient for our needs. Note that this is the same
124     relative accuracy we would have when we compute directly with
125     lon/lat/radius. For the radius value this is clear. For the lon/lat pair
126     this is easy to see. Take for example KSFO located at about 37.61 deg north
127     122.35 deg west, which corresponds to 0.65642 rad north and 2.13541 rad
128     west. Both values are of magnitude of about 1. But 1 ft corresponds to about
129     1/(2e7*2*pi) = 7.9577e-09 rad. So the left accuracy with this representation
130     is also about 1*1e-16/7.9577e-09 = 1.2566e-08 which is of the same magnitude
131     as the representation chosen here.
132
133     The advantage of this representation is that it is a linear space without
134     singularities. The singularities are the north and south pole and most
135     notably the non-steady jump at -pi to pi. It is harder to track this jump
136     correctly especially when we need to work with error norms and derivatives
137     of the equations of motion within the time-stepping code. Also, the rate of
138     change is of the same magnitude for all components in this representation
139     which is an advantage for numerical stability in implicit time-stepping.
140
141     Note: The latitude is a GEOCENTRIC value. FlightGear converts latitude to a
142     geodetic value and uses that. In order to get best matching relative to a
143     map, geocentric latitude must be converted to geodetic.
144
145     @see Stevens and Lewis, "Aircraft Control and Simulation", Second edition
146     @see W. C. Durham "Aircraft Dynamics & Control", section 2.2
147
148     @author Mathias Froehlich
149     @version $Id: FGLocation.h,v 1.29 2011/11/06 18:14:51 bcoconni Exp $
150   */
151
152 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153 CLASS DECLARATION
154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
155
156 class FGLocation : public FGJSBBase
157 {
158 public:
159   /** Default constructor. */
160   FGLocation(void);
161
162   /** Constructor to set the longitude, latitude and the distance
163       from the center of the earth.
164       @param lon longitude
165       @param lat GEOCENTRIC latitude
166       @param radius distance from center of earth to vehicle in feet*/
167   FGLocation(double lon, double lat, double radius);
168
169   /** Column constructor. */
170   FGLocation(const FGColumnVector3& lv);
171
172   /** Copy constructor. */
173   FGLocation(const FGLocation& l);
174
175   /** Set the longitude.
176       @param longitude Longitude in rad to set.
177       Sets the longitude of the location represented with this class
178       instance to the value of the given argument. The value is meant
179       to be in rad. The latitude and the radius value are preserved
180       with this call with the exception of radius being equal to
181       zero. If the radius is previously set to zero it is changed to be
182       equal to 1.0 past this call. Longitude is positive east and negative west. */
183   void SetLongitude(double longitude);
184
185   /** Set the latitude.
186       @param latitude Latitude in rad to set.
187       Sets the latitude of the location represented with this class
188       instance to the value of the given argument. The value is meant
189       to be in rad. The longitude and the radius value are preserved
190       with this call with the exception of radius being equal to
191       zero. If the radius is previously set to zero it is changed to be
192       equal to 1.0 past this call.
193       Latitude is positive north and negative south.
194       The arguments should be within the bounds of -pi/2 <= lat <= pi/2.
195       The behavior of this function with arguments outside this range is
196       left as an exercise to the gentle reader ... */
197   void SetLatitude(double latitude);
198
199   /** Set the distance from the center of the earth.
200       @param radius Radius in ft to set.
201       Sets the radius of the location represented with this class
202       instance to the value of the given argument. The value is meant
203       to be in ft. The latitude and longitude values are preserved
204       with this call with the exception of radius being equal to
205       zero. If the radius is previously set to zero, latitude and
206       longitude is set equal to zero past this call.
207       The argument should be positive.
208       The behavior of this function called with a negative argument is
209       left as an exercise to the gentle reader ... */
210   void SetRadius(double radius);
211
212   /** Sets the longitude, latitude and the distance from the center of the earth.
213       @param lon longitude in radians
214       @param lat GEOCENTRIC latitude in radians
215       @param radius distance from center of earth to vehicle in feet*/
216   void SetPosition(double lon, double lat, double radius);
217
218   /** Sets the longitude, latitude and the distance above the reference ellipsoid.
219       @param lon longitude in radians
220       @param lat GEODETIC latitude in radians
221       @param height distance above the reference ellipsoid to vehicle in feet*/
222   void SetPositionGeodetic(double lon, double lat, double height);
223
224   /** Sets the semimajor and semiminor axis lengths for this planet.
225       The eccentricity and flattening are calculated from the semimajor
226       and semiminor axis lengths */
227   void SetEllipse(double semimajor, double semiminor);
228
229   /** Sets the Earth position angle.
230       This is the relative orientation of the ECEF frame with respect to the
231       Inertial frame.
232       @param EPA Earth fixed frame (ECEF) rotation offset about the axis with
233                  respect to the Inertial (ECI) frame in radians. */
234   void SetEarthPositionAngle(double EPA) {epa = EPA; mCacheValid = false;}
235
236   /** Increments the Earth position angle.
237       This is the relative orientation of the ECEF frame with respect to the
238       Inertial frame.
239       @param delta delta to the Earth fixed frame (ECEF) rotation offset about the axis with
240                  respect to the Inertial (ECI) frame in radians. */
241   void IncrementEarthPositionAngle(double delta) {epa += delta; mCacheValid = false;}
242
243   /** Get the longitude.
244       @return the longitude in rad of the location represented with this
245       class instance. The returned values are in the range between
246       -pi <= lon <= pi. Longitude is positive east and negative west. */
247   double GetLongitude() const { ComputeDerived(); return mLon; }
248
249   /** Get the longitude.
250       @return the longitude in deg of the location represented with this
251       class instance. The returned values are in the range between
252       -180 <= lon <= 180.  Longitude is positive east and negative west. */
253   double GetLongitudeDeg() const { ComputeDerived(); return radtodeg*mLon; }
254
255   /** Get the sine of Longitude. */
256   double GetSinLongitude() const { ComputeDerived(); return -mTec2l(2,1); }
257
258   /** Get the cosine of Longitude. */
259   double GetCosLongitude() const { ComputeDerived(); return mTec2l(2,2); }
260
261   /** Get the latitude.
262       @return the latitude in rad of the location represented with this
263       class instance. The returned values are in the range between
264       -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */
265   double GetLatitude() const { ComputeDerived(); return mLat; }
266
267   /** Get the geodetic latitude.
268       @return the geodetic latitude in rad of the location represented with this
269       class instance. The returned values are in the range between
270       -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */
271   double GetGeodLatitudeRad(void) const { ComputeDerived(); return mGeodLat; }
272
273   /** Get the latitude.
274       @return the latitude in deg of the location represented with this
275       class instance. The returned value is in the range between
276       -90 <= lon <= 90. Latitude is positive north and negative south. */
277   double GetLatitudeDeg() const { ComputeDerived(); return radtodeg*mLat; }
278
279   /** Get the geodetic latitude in degrees.
280       @return the geodetic latitude in degrees of the location represented by
281       this class instance. The returned value is in the range between
282       -90 <= lon <= 90. Latitude is positive north and negative south. */
283   double GetGeodLatitudeDeg(void) const { ComputeDerived(); return radtodeg*mGeodLat; }
284
285   /** Gets the geodetic altitude in feet. */
286   double GetGeodAltitude(void) const {ComputeDerived(); return GeodeticAltitude;}
287
288   /** Get the sine of Latitude. */
289   double GetSinLatitude() const { ComputeDerived(); return -mTec2l(3,3); }
290
291   /** Get the cosine of Latitude. */
292   double GetCosLatitude() const { ComputeDerived(); return mTec2l(1,3); }
293
294   /** Get the cosine of Latitude. */
295   double GetTanLatitude() const {
296     ComputeDerived();
297     double cLat = mTec2l(1,3);
298     if (cLat == 0.0)
299       return 0.0;
300     else
301       return -mTec2l(3,3)/cLat;
302   }
303
304   double GetEPA() const {return epa;}
305
306   /** Get the distance from the center of the earth.
307       @return the distance of the location represented with this class
308       instance to the center of the earth in ft. The radius value is
309       always positive. */
310   //double GetRadius() const { return mECLoc.Magnitude(); } // may not work with FlightGear
311   double GetRadius() const { ComputeDerived(); return mRadius; }
312
313   /// @name Functions that need the ground callback to be set
314   ///@{
315   /** Set the altitude above sea level.
316       @param altitudeASL altitude above Sea Level in feet. */
317   void SetAltitudeASL(double altitudeASL)
318   { SetRadius(GroundCallback->GetSeaLevelRadius(*this) + altitudeASL); }
319
320   /** Set the altitude above ground level.
321       @param altitudeAGL altitude above Ground Level in feet. */
322   void SetAltitudeAGL(double altitudeAGL, double time)
323   { SetRadius(GroundCallback->GetTerrainGeoCentRadius(time, *this) + altitudeAGL); }
324
325   /** Get the local sea level radius
326       @return the sea level radius at the location in feet. */
327   double GetSeaLevelRadius(void) const
328   { ComputeDerived(); return GroundCallback->GetSeaLevelRadius(*this); }
329
330   /** Get the local terrain radius
331       @return the terrain level radius at the location in feet. */
332   double GetTerrainRadius(double time) const
333   { ComputeDerived(); return GroundCallback->GetTerrainGeoCentRadius(time, *this); }
334
335   /** Get the altitude above sea level.
336       @return the altitude ASL in feet. */
337   double GetAltitudeASL() const
338   { ComputeDerived(); return GroundCallback->GetAltitude(*this); }
339
340   /** Get the altitude above ground level.
341       @return the altitude AGL in feet. */
342   double GetAltitudeAGL(double time) const {
343     FGLocation c;
344     FGColumnVector3 n,v,w;
345     return GetContactPoint(time,c,n,v,w);
346   }
347
348   /** Get terrain contact point information below the current location.
349       @param time    Simulation time
350       @param contact Contact point location
351       @param normal  Terrain normal vector in contact point    (ECEF frame)
352       @param v       Terrain linear velocity in contact point  (ECEF frame)
353       @param w       Terrain angular velocity in contact point (ECEF frame)
354       @return Location altitude above contact point (AGL) in feet. */
355   double GetContactPoint(double time,
356                          FGLocation& contact, FGColumnVector3& normal,
357                          FGColumnVector3& v, FGColumnVector3& w) const
358   { ComputeDerived(); return GroundCallback->GetAGLevel(time, *this, contact, normal, v, w); }
359
360   /** Sets the ground callback pointer. For optimal memory management, a shared
361       pointer is used internally that maintains a reference counter. The calling
362       application must therefore use FGGroundCallback_ptr 'smart pointers' to
363       manage their copy of the ground callback.
364       @param gc A pointer to a ground callback object
365       @see FGGroundCallback
366    */
367   static void SetGroundCallback(FGGroundCallback* gc) { GroundCallback = gc; }
368
369   /** Get a pointer to the ground callback currently used. It is recommanded
370       to store the returned pointer in a 'smart pointer' FGGroundCallback_ptr.
371       @return A pointer to the current ground callback object.
372       @see FGGroundCallback
373    */
374   static FGGroundCallback* GetGroundCallback(void) { return GroundCallback; }
375   ///@}
376
377   /** Transform matrix from local horizontal to earth centered frame.
378       Returns a const reference to the rotation matrix of the transform from
379       the local horizontal frame to the earth centered frame. */
380   const FGMatrix33& GetTl2ec(void) const { ComputeDerived(); return mTl2ec; }
381
382   /** Transform matrix from the earth centered to local horizontal frame.
383       Returns a const reference to the rotation matrix of the transform from
384       the earth centered frame to the local horizontal frame. */
385   const FGMatrix33& GetTec2l(void) const { ComputeDerived(); return mTec2l; }
386
387   /** Transform matrix from inertial to earth centered frame.
388       Returns a const reference to the rotation matrix of the transform from
389       the inertial frame to the earth centered frame (ECI to ECEF). */
390   const FGMatrix33& GetTi2ec(void);
391
392   /** Transform matrix from the earth centered to inertial frame.
393       Returns a const reference to the rotation matrix of the transform from
394       the earth centered frame to the inertial frame (ECEF to ECI). */
395   const FGMatrix33& GetTec2i(void);
396
397   const FGMatrix33& GetTi2l(void) const {ComputeDerived(); return mTi2l;}
398
399   const FGMatrix33& GetTl2i(void) const {ComputeDerived(); return mTl2i;}
400
401   /** Conversion from Local frame coordinates to a location in the
402       earth centered and fixed frame.
403       @param lvec Vector in the local horizontal coordinate frame
404       @return The location in the earth centered and fixed frame */
405   FGLocation LocalToLocation(const FGColumnVector3& lvec) const {
406     ComputeDerived(); return mTl2ec*lvec + mECLoc;
407   }
408
409   /** Conversion from a location in the earth centered and fixed frame
410       to local horizontal frame coordinates.
411       @param ecvec Vector in the earth centered and fixed frame
412       @return The vector in the local horizontal coordinate frame */
413   FGColumnVector3 LocationToLocal(const FGColumnVector3& ecvec) const {
414     ComputeDerived(); return mTec2l*(ecvec - mECLoc);
415   }
416
417   // For time-stepping, locations have vector properties...
418
419   /** Read access the entries of the vector.
420       @param idx the component index.
421       Return the value of the matrix entry at the given index.
422       Indices are counted starting with 1.
423       Note that the index given in the argument is unchecked. */
424   double operator()(unsigned int idx) const { return mECLoc.Entry(idx); }
425
426   /** Write access the entries of the vector.
427       @param idx the component index.
428       @return a reference to the vector entry at the given index.
429       Indices are counted starting with 1.
430       Note that the index given in the argument is unchecked. */
431   double& operator()(unsigned int idx) { mCacheValid = false; return mECLoc.Entry(idx); }
432
433   /** Read access the entries of the vector.
434       @param idx the component index.
435       @return the value of the matrix entry at the given index.
436       Indices are counted starting with 1.
437       This function is just a shortcut for the <tt>double
438       operator()(unsigned int idx) const</tt> function. It is
439       used internally to access the elements in a more convenient way.
440       Note that the index given in the argument is unchecked. */
441   double Entry(unsigned int idx) const { return mECLoc.Entry(idx); }
442
443   /** Write access the entries of the vector.
444       @param idx the component index.
445       @return a reference to the vector entry at the given index.
446       Indices are counted starting with 1.
447       This function is just a shortcut for the double&
448       operator()(unsigned int idx) function. It is
449       used internally to access the elements in a more convenient way.
450       Note that the index given in the argument is unchecked. */
451   double& Entry(unsigned int idx) {
452     mCacheValid = false; return mECLoc.Entry(idx);
453   }
454
455   /** Sets this location via the supplied vector.
456       The location can be set by an Earth-centered, Earth-fixed (ECEF) frame
457       position vector. The cache is marked as invalid, so any future requests
458       for selected important data will cause the parameters to be calculated.
459       @param v the ECEF column vector in feet. 
460       @return a reference to the FGLocation object. */
461   const FGLocation& operator=(const FGColumnVector3& v)
462   {
463     mECLoc(eX) = v(eX);
464     mECLoc(eY) = v(eY);
465     mECLoc(eZ) = v(eZ);
466     mCacheValid = false;
467     ComputeDerived();
468     return *this;
469   }
470
471   /** Sets this location via the supplied location object.
472       @param v A location object reference. 
473       @return a reference to the FGLocation object. */
474   const FGLocation& operator=(const FGLocation& l);
475
476   /** This operator returns true if the ECEF location vectors for the two
477       location objects are equal. */
478   bool operator==(const FGLocation& l) const {
479     return mECLoc == l.mECLoc;
480   }
481
482   /** This operator returns true if the ECEF location vectors for the two
483       location objects are not equal. */
484   bool operator!=(const FGLocation& l) const { return ! operator==(l); }
485
486   /** This operator adds the ECEF position vectors.
487       The supplied vector (right side) is added to the ECEF position vector
488       on the left side of the equality, and a pointer to this object is
489       returned. */
490   const FGLocation& operator+=(const FGLocation &l) {
491     mCacheValid = false;
492     mECLoc += l.mECLoc;
493     return *this;
494   }
495
496   const FGLocation& operator-=(const FGLocation &l) {
497     mCacheValid = false;
498     mECLoc -= l.mECLoc;
499     return *this;
500   }
501
502   const FGLocation& operator*=(double scalar) {
503     mCacheValid = false;
504     mECLoc *= scalar;
505     return *this;
506   }
507
508   const FGLocation& operator/=(double scalar) {
509     return operator*=(1.0/scalar);
510   }
511
512   FGLocation operator+(const FGLocation& l) const {
513     return FGLocation(mECLoc + l.mECLoc);
514   }
515
516   FGLocation operator-(const FGLocation& l) const {
517     return FGLocation(mECLoc - l.mECLoc);
518   }
519
520   FGLocation operator*(double scalar) const {
521     return FGLocation(scalar*mECLoc);
522   }
523
524   /** Cast to a simple 3d vector */
525   operator const FGColumnVector3&() const {
526     return mECLoc;
527   }
528
529 private:
530   /** Computation of derived values.
531       This function re-computes the derived values like lat/lon and
532       transformation matrices. It does this unconditionally. */
533   void ComputeDerivedUnconditional(void) const;
534
535   /** Computation of derived values.
536       This function checks if the derived values like lat/lon and
537       transformation matrices are already computed. If so, it
538       returns. If they need to be computed this is done here. */
539   void ComputeDerived(void) const {
540     if (!mCacheValid)
541       ComputeDerivedUnconditional();
542   }
543
544   /** The coordinates in the earth centered frame. This is the master copy.
545       The coordinate frame has its center in the middle of the earth.
546       Its x-axis points from the center of the earth towards a
547       location with zero latitude and longitude on the earths
548       surface. The y-axis points from the center of the earth towards a
549       location with zero latitude and 90deg longitude on the earths
550       surface. The z-axis points from the earths center to the
551       geographic north pole.
552       @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 */
553   FGColumnVector3 mECLoc;
554
555   /** The cached lon/lat/radius values. */
556   mutable double mLon;
557   mutable double mLat;
558   mutable double mRadius;
559   mutable double mGeodLat;
560   mutable double GeodeticAltitude;
561   
562   double initial_longitude;
563
564   /** The cached rotation matrices from and to the associated frames. */
565   mutable FGMatrix33 mTl2ec;
566   mutable FGMatrix33 mTec2l;
567   mutable FGMatrix33 mTi2ec;
568   mutable FGMatrix33 mTec2i;
569   mutable FGMatrix33 mTi2l;
570   mutable FGMatrix33 mTl2i;
571
572   double epa;
573
574   /* Terms for geodetic latitude calculation. Values are from WGS84 model */
575   double a;    // Earth semimajor axis in feet (6,378,137.0 meters)
576   double b;    // Earth semiminor axis in feet (6,356,752.3142 meters)
577   double a2;
578   double b2;
579   double e;    // Earth eccentricity
580   double e2;   // Earth eccentricity squared
581   double eps2; //
582   double f;    // Flattening
583
584   /** A data validity flag.
585       This class implements caching of the derived values like the
586       orthogonal rotation matrices or the lon/lat/radius values. For caching we
587       carry a flag which signals if the values are valid or not.
588       The C++ keyword "mutable" tells the compiler that the data member is
589       allowed to change during a const member function. */
590   mutable bool mCacheValid;
591
592   /** The ground callback object pointer */
593   static FGGroundCallback_ptr GroundCallback;
594 };
595
596 /** Scalar multiplication.
597
598     @param scalar scalar value to multiply with.
599     @param l Vector to multiply.
600
601     Multiply the Vector with a scalar value. */
602 inline FGLocation operator*(double scalar, const FGLocation& l)
603 {
604   return l.operator*(scalar);
605 }
606
607 } // namespace JSBSim
608
609 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610 #endif