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 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 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 "FGColumnVector3.h" 47 #include "FGMatrix33.h" 48 #include "input_output/FGGroundCallback.h" 49 50 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 51 FORWARD DECLARATIONS 52 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 53 54 namespace JSBSim { 55 56 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 57 CLASS DOCUMENTATION 58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 59 60 /** FGLocation holds an arbitrary location in the Earth centered Earth fixed 61 reference frame (ECEF). The coordinate frame ECEF has its center in the middle 62 of the earth. The X-axis points from the center of the Earth towards a 63 location with zero latitude and longitude on the Earth surface. The Y-axis 64 points from the center of the Earth towards a location with zero latitude 65 and 90 deg East longitude on the Earth surface. The Z-axis points from the 66 Earth center to the geographic north pole. 67 68 This class provides access functions to set and get the location as either 69 the simple X, Y and Z values in ft or longitude/latitude and the radial 70 distance of the location from the Earth center. 71 72 It is common to associate a parent frame with a location. This frame is 73 usually called the local horizontal frame or simply the local frame. It is 74 also called the NED frame (North, East, Down), as well as the Navigation 75 frame. This frame has its X/Y plane parallel to the surface of the Earth 76 (with the assumption of a spherical Earth). The X-axis points towards north, 77 the Y-axis points east and the Z-axis points to the center of the Earth. 78 79 Since the local frame is determined by the location (and NOT by the 80 orientation of the vehicle IN any frame), this class also provides the 81 rotation matrices required to transform from the Earth centered (ECEF) frame 82 to the local horizontal frame and back. This class also "owns" the 83 transformations that go from the inertial frame (Earth-centered Inertial, or 84 ECI) to and from the ECEF frame, as well as to and from the local frame. 85 Again, this is because the ECI, ECEF, and local frames do not involve the 86 actual orientation of the vehicle - only the location on the Earth surface, 87 and the angular difference between the ECI and ECEF frames. There are 88 conversion functions for conversion of position vectors given in the one 89 frame to positions in the other frame. 90 91 To keep the transformation matrices between the ECI and ECEF frames up to 92 date, the Earth angular position must be updated by calling 93 SetEarthPositionAngle() or IncrementEarthPositionAngle(). This must be done 94 prior to any conversion from and to the ECI frame. 95 96 The Earth centered reference frame is NOT an inertial frame since it rotates 97 with the Earth. 98 99 The cartesian coordinates (X,Y,Z) in the Earth centered frame are the master values. All other 100 values are computed from these master values and are cached as long as the 101 location is changed by access through a non-const member function. Values 102 are cached to improve performance. It is best practice to work with a 103 natural set of master values. Other parameters that are derived from these 104 master values are calculated only when needed, and IF they are needed and 105 calculated, then they are cached (stored and remembered) so they do not need 106 to be re-calculated until the master values they are derived from are 107 themselves changed (and become stale). 108 109 Accuracy and round off 110 111 Given, 112 113 - that we model a vehicle near the Earth 114 - that the Earth surface radius is about 2*10^7, ft 115 - that we use double values for the representation of the location 116 117 we have an accuracy of about 118 119 1e-16*2e7ft/1 = 2e-9 ft 120 121 left. This should be sufficient for our needs. Note that this is the same 122 relative accuracy we would have when we compute directly with 123 lon/lat/radius. For the radius value this is clear. For the lon/lat pair 124 this is easy to see. Take for example KSFO located at about 37.61 deg north 125 122.35 deg west, which corresponds to 0.65642 rad north and 2.13541 rad 126 west. Both values are of magnitude of about 1. But 1 ft corresponds to about 127 1/(2e7*2*pi) = 7.9577e-09 rad. So the left accuracy with this representation 128 is also about 1*1e-16/7.9577e-09 = 1.2566e-08 which is of the same magnitude 129 as the representation chosen here. 130 131 The advantage of this representation is that it is a linear space without 132 singularities. The singularities are the north and south pole and most 133 notably the non-steady jump at -pi to pi. It is harder to track this jump 134 correctly especially when we need to work with error norms and derivatives 135 of the equations of motion within the time-stepping code. Also, the rate of 136 change is of the same magnitude for all components in this representation 137 which is an advantage for numerical stability in implicit time-stepping. 138 139 Note: The latitude is a GEOCENTRIC value. FlightGear converts latitude to a 140 geodetic value and uses that. In order to get best matching relative to a 141 map, geocentric latitude must be converted to geodetic. 142 143 @see Stevens and Lewis, "Aircraft Control and Simulation", Second edition 144 @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 145 146 @author Mathias Froehlich 147 */ 148 149 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 150 CLASS DECLARATION 151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 152 153 class FGLocation : public FGJSBBase 154 { 155 public: 156 /** Default constructor. */ 157 FGLocation(void); 158 159 /** Constructor to set the longitude, latitude and the distance 160 from the center of the earth. 161 @param lon longitude 162 @param lat GEOCENTRIC latitude 163 @param radius distance from center of earth to vehicle in feet*/ 164 FGLocation(double lon, double lat, double radius); 165 166 /** Constructor to initialize the location with the cartesian coordinates 167 (X,Y,Z) contained in the input FGColumnVector3. Distances are in feet, 168 the position is expressed in the ECEF frame. 169 @param lv vector that contain the cartesian coordinates*/ 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 /** Get the longitude. 230 @return the longitude in rad of the location represented with this 231 class instance. The returned values are in the range between 232 -pi <= lon <= pi. Longitude is positive east and negative west. */ GetLongitude()233 double GetLongitude() const { ComputeDerived(); return mLon; } 234 235 /** Get the longitude. 236 @return the longitude in deg of the location represented with this 237 class instance. The returned values are in the range between 238 -180 <= lon <= 180. Longitude is positive east and negative west. */ GetLongitudeDeg()239 double GetLongitudeDeg() const { ComputeDerived(); return radtodeg*mLon; } 240 241 /** Get the sine of Longitude. */ GetSinLongitude()242 double GetSinLongitude() const { ComputeDerived(); return -mTec2l(2,1); } 243 244 /** Get the cosine of Longitude. */ GetCosLongitude()245 double GetCosLongitude() const { ComputeDerived(); return mTec2l(2,2); } 246 247 /** Get the latitude. 248 @return the latitude in rad of the location represented with this 249 class instance. The returned values are in the range between 250 -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */ GetLatitude()251 double GetLatitude() const { ComputeDerived(); return mLat; } 252 253 /** Get the geodetic latitude. 254 @return the geodetic latitude in rad of the location represented with this 255 class instance. The returned values are in the range between 256 -pi/2 <= lon <= pi/2. Latitude is positive north and negative south. */ GetGeodLatitudeRad(void)257 double GetGeodLatitudeRad(void) const { ComputeDerived(); return mGeodLat; } 258 259 /** Get the latitude. 260 @return the latitude in deg of the location represented with this 261 class instance. The returned value is in the range between 262 -90 <= lon <= 90. Latitude is positive north and negative south. */ GetLatitudeDeg()263 double GetLatitudeDeg() const { ComputeDerived(); return radtodeg*mLat; } 264 265 /** Get the geodetic latitude in degrees. 266 @return the geodetic latitude in degrees of the location represented by 267 this class instance. The returned value is in the range between 268 -90 <= lon <= 90. Latitude is positive north and negative south. */ GetGeodLatitudeDeg(void)269 double GetGeodLatitudeDeg(void) const { ComputeDerived(); return radtodeg*mGeodLat; } 270 271 /** Gets the geodetic altitude in feet. */ GetGeodAltitude(void)272 double GetGeodAltitude(void) const {ComputeDerived(); return GeodeticAltitude;} 273 274 /** Get the sine of Latitude. */ GetSinLatitude()275 double GetSinLatitude() const { ComputeDerived(); return -mTec2l(3,3); } 276 277 /** Get the cosine of Latitude. */ GetCosLatitude()278 double GetCosLatitude() const { ComputeDerived(); return mTec2l(1,3); } 279 280 /** Get the cosine of Latitude. */ GetTanLatitude()281 double GetTanLatitude() const { 282 ComputeDerived(); 283 double cLat = mTec2l(1,3); 284 if (cLat == 0.0) 285 return 0.0; 286 else 287 return -mTec2l(3,3)/cLat; 288 } 289 290 /** Get the distance from the center of the earth. 291 @return the distance of the location represented with this class 292 instance to the center of the earth in ft. The radius value is 293 always positive. */ 294 //double GetRadius() const { return mECLoc.Magnitude(); } // may not work with FlightGear GetRadius()295 double GetRadius() const { ComputeDerived(); return mRadius; } 296 297 /** @name Functions that rely on the ground callback 298 The following functions allow to set and get the vehicle position above 299 the sea or the ground. The sea and the ground levels are obtained by 300 interrogating an FGGroundCallback instance. A ground callback must 301 therefore be set with SetGroundCallback() before calling any of these 302 functions. */ 303 ///@{ 304 /** Set the altitude above sea level. 305 @param altitudeASL altitude above Sea Level in feet. 306 @see SetGroundCallback */ SetAltitudeASL(double altitudeASL)307 void SetAltitudeASL(double altitudeASL) 308 { SetRadius(GetSeaLevelRadius() + altitudeASL); } 309 310 /** Set the altitude above ground level. 311 @param altitudeAGL altitude above Ground Level in feet. 312 @see SetGroundCallback */ SetAltitudeAGL(double altitudeAGL)313 void SetAltitudeAGL(double altitudeAGL) 314 { SetRadius(GetTerrainRadius() + altitudeAGL); } 315 316 /** Get the local sea level radius 317 @return the sea level radius at the location in feet. 318 @see SetGroundCallback */ GetSeaLevelRadius(void)319 double GetSeaLevelRadius(void) const 320 { ComputeDerived(); return GroundCallback->GetSeaLevelRadius(*this); } 321 322 /** Get the local terrain radius 323 @return the terrain level radius at the location in feet. 324 @see SetGroundCallback */ GetTerrainRadius(void)325 double GetTerrainRadius(void) const 326 { ComputeDerived(); return GroundCallback->GetTerrainGeoCentRadius(*this); } 327 328 /** Get the altitude above sea level. 329 @return the altitude ASL in feet. 330 @see SetGroundCallback */ GetAltitudeASL(void)331 double GetAltitudeASL(void) const 332 { return GetRadius() - GetSeaLevelRadius(); } 333 334 /** Get the altitude above ground level. 335 @return the altitude AGL in feet. 336 @see SetGroundCallback */ GetAltitudeAGL(void)337 double GetAltitudeAGL(void) const { 338 FGLocation c; 339 FGColumnVector3 n,v,w; 340 return GetContactPoint(c,n,v,w); 341 } 342 343 /** Get terrain contact point information below the current location. 344 @param contact Contact point location 345 @param normal Terrain normal vector in contact point (ECEF frame) 346 @param v Terrain linear velocity in contact point (ECEF frame) 347 @param w Terrain angular velocity in contact point (ECEF frame) 348 @return Location altitude above contact point (AGL) in feet. 349 @see SetGroundCallback */ GetContactPoint(FGLocation & contact,FGColumnVector3 & normal,FGColumnVector3 & v,FGColumnVector3 & w)350 double GetContactPoint(FGLocation& contact, FGColumnVector3& normal, 351 FGColumnVector3& v, FGColumnVector3& w) const 352 { ComputeDerived(); return GroundCallback->GetAGLevel(*this, contact, normal, v, w); } 353 ///@} 354 355 /** Sets the ground callback pointer. The FGGroundCallback instance will be 356 interrogated by FGLocation each time some terrain informations are needed. 357 This will mainly occur when altitudes above the sea level or above the 358 ground level are needed. A 'smart pointer' is used internally to prevent 359 the FGGroundCallback instance against accidental deletion. This can only 360 work if the calling application also make use of FGGroundCallback_ptr 361 'smart pointers' to manage their copy of the ground callback. 362 @param gc A pointer to a ground callback object 363 @see FGGroundCallback 364 */ SetGroundCallback(FGGroundCallback * gc)365 static void SetGroundCallback(FGGroundCallback* gc) { GroundCallback = gc; } 366 367 /** Get a pointer to the ground callback currently used. Since the 368 FGGroundcallback instance might have been created outside JSBSim, it is 369 recommanded to store the returned pointer in a 'smart pointer' 370 FGGroundCallback_ptr. This pointer maintains a reference counter and 371 protects the returned pointer against an accidental deletion of the object 372 it is pointing to. 373 @return A pointer to the current ground callback object. 374 @see FGGroundCallback 375 */ GetGroundCallback(void)376 static FGGroundCallback* GetGroundCallback(void) { return GroundCallback; } 377 378 /** Transform matrix from local horizontal to earth centered frame. 379 @return a const reference to the rotation matrix of the transform from 380 the local horizontal frame to the earth centered frame. */ GetTl2ec(void)381 const FGMatrix33& GetTl2ec(void) const { ComputeDerived(); return mTl2ec; } 382 383 /** Transform matrix from the earth centered to local horizontal frame. 384 @return a const reference to the rotation matrix of the transform from 385 the earth centered frame to the local horizontal frame. */ GetTec2l(void)386 const FGMatrix33& GetTec2l(void) const { ComputeDerived(); return mTec2l; } 387 388 /** Get the geodetic distance between the current location and a given 389 location. This corresponds to the shortest distance between the two 390 locations. Earth curvature is taken into account. 391 @param target_longitude the target longitude 392 @param target_latitude the target latitude 393 @return The geodetic distance between the two locations */ 394 double GetDistanceTo(double target_longitude, double target_latitude) const; 395 396 /** Get the heading that should be followed from the current location to 397 a given location along the shortest path. Earth curvature is 398 taken into account. 399 @param target_longitude the target longitude 400 @param target_latitude the target latitude 401 @return The heading that should be followed to reach the targeted 402 location along the shortest path */ 403 double GetHeadingTo(double target_longitude, double target_latitude) const; 404 405 /** Conversion from Local frame coordinates to a location in the 406 earth centered and fixed frame. 407 This function calculates the FGLocation of an object which position 408 relative to the vehicle is given as in input. 409 @param lvec Vector in the local horizontal coordinate frame 410 @return The location in the earth centered and fixed frame */ LocalToLocation(const FGColumnVector3 & lvec)411 FGLocation LocalToLocation(const FGColumnVector3& lvec) const { 412 ComputeDerived(); return mTl2ec*lvec + mECLoc; 413 } 414 415 /** Conversion from a location in the earth centered and fixed frame 416 to local horizontal frame coordinates. 417 This function calculates the relative position between the vehicle and 418 the input vector and returns the result expressed in the local frame. 419 @param ecvec Vector in the earth centered and fixed frame 420 @return The vector in the local horizontal coordinate frame */ LocationToLocal(const FGColumnVector3 & ecvec)421 FGColumnVector3 LocationToLocal(const FGColumnVector3& ecvec) const { 422 ComputeDerived(); return mTec2l*(ecvec - mECLoc); 423 } 424 425 // For time-stepping, locations have vector properties... 426 427 /** Read access the entries of the vector. 428 @param idx the component index. 429 Return the value of the matrix entry at the given index. 430 Indices are counted starting with 1. 431 Note that the index given in the argument is unchecked. */ operator()432 double operator()(unsigned int idx) const { return mECLoc.Entry(idx); } 433 434 /** Write access the entries of the vector. 435 @param idx the component index. 436 @return a reference to the vector entry at the given index. 437 Indices are counted starting with 1. 438 Note that the index given in the argument is unchecked. */ operator()439 double& operator()(unsigned int idx) { mCacheValid = false; return mECLoc.Entry(idx); } 440 441 /** Read access the entries of the vector. 442 @param idx the component index. 443 @return the value of the matrix entry at the given index. 444 Indices are counted starting with 1. 445 This function is just a shortcut for the <tt>double 446 operator()(unsigned int idx) const</tt> function. It is 447 used internally to access the elements in a more convenient way. 448 Note that the index given in the argument is unchecked. */ Entry(unsigned int idx)449 double Entry(unsigned int idx) const { return mECLoc.Entry(idx); } 450 451 /** Write access the entries of the vector. 452 @param idx the component index. 453 @return a reference to the vector entry at the given index. 454 Indices are counted starting with 1. 455 This function is just a shortcut for the double& 456 operator()(unsigned int idx) function. It is 457 used internally to access the elements in a more convenient way. 458 Note that the index given in the argument is unchecked. */ Entry(unsigned int idx)459 double& Entry(unsigned int idx) { 460 mCacheValid = false; return mECLoc.Entry(idx); 461 } 462 463 /** Sets this location via the supplied vector. 464 The location can be set by an Earth-centered, Earth-fixed (ECEF) frame 465 position vector. The cache is marked as invalid, so any future requests 466 for selected important data will cause the parameters to be calculated. 467 @param v the ECEF column vector in feet. 468 @return a reference to the FGLocation object. */ 469 const FGLocation& operator=(const FGColumnVector3& v) 470 { 471 mECLoc(eX) = v(eX); 472 mECLoc(eY) = v(eY); 473 mECLoc(eZ) = v(eZ); 474 mCacheValid = false; 475 //ComputeDerived(); 476 return *this; 477 } 478 479 /** Sets this location via the supplied location object. 480 @param v A location object reference. 481 @return a reference to the FGLocation object. */ 482 const FGLocation& operator=(const FGLocation& l); 483 484 /** This operator returns true if the ECEF location vectors for the two 485 location objects are equal. */ 486 bool operator==(const FGLocation& l) const { 487 return mECLoc == l.mECLoc; 488 } 489 490 /** This operator returns true if the ECEF location vectors for the two 491 location objects are not equal. */ 492 bool operator!=(const FGLocation& l) const { return ! operator==(l); } 493 494 /** This operator adds the ECEF position vectors. 495 The cartesian coordinates of the supplied vector (right side) are added to 496 the ECEF position vector on the left side of the equality, and a reference 497 to this object is returned. */ 498 const FGLocation& operator+=(const FGLocation &l) { 499 mCacheValid = false; 500 mECLoc += l.mECLoc; 501 return *this; 502 } 503 504 /** This operator substracts the ECEF position vectors. 505 The cartesian coordinates of the supplied vector (right side) are 506 substracted from the ECEF position vector on the left side of the 507 equality, and a reference to this object is returned. */ 508 const FGLocation& operator-=(const FGLocation &l) { 509 mCacheValid = false; 510 mECLoc -= l.mECLoc; 511 return *this; 512 } 513 514 /** This operator scales the ECEF position vector. 515 The cartesian coordinates of the ECEF position vector on the left side of 516 the equality are scaled by the supplied value (right side), and a 517 reference to this object is returned. */ 518 const FGLocation& operator*=(double scalar) { 519 mCacheValid = false; 520 mECLoc *= scalar; 521 return *this; 522 } 523 524 /** This operator scales the ECEF position vector. 525 The cartesian coordinates of the ECEF position vector on the left side of 526 the equality are scaled by the inverse of the supplied value (right side), 527 and a reference to this object is returned. */ 528 const FGLocation& operator/=(double scalar) { 529 return operator*=(1.0/scalar); 530 } 531 532 /** This operator adds two ECEF position vectors. 533 A new object is returned that defines a position which is the sum of the 534 cartesian coordinates of the two positions provided. */ 535 FGLocation operator+(const FGLocation& l) const { 536 return FGLocation(mECLoc + l.mECLoc); 537 } 538 539 /** This operator substracts two ECEF position vectors. 540 A new object is returned that defines a position which is the difference 541 of the cartesian coordinates of the two positions provided. */ 542 FGLocation operator-(const FGLocation& l) const { 543 return FGLocation(mECLoc - l.mECLoc); 544 } 545 546 /** This operator scales an ECEF position vector. 547 A new object is returned that defines a position made of the cartesian 548 coordinates of the provided ECEF position scaled by the supplied scalar 549 value. */ 550 FGLocation operator*(double scalar) const { 551 return FGLocation(scalar*mECLoc); 552 } 553 554 /** Cast to a simple 3d vector */ 555 operator const FGColumnVector3&() const { 556 return mECLoc; 557 } 558 559 private: 560 /** Computation of derived values. 561 This function re-computes the derived values like lat/lon and 562 transformation matrices. It does this unconditionally. */ 563 void ComputeDerivedUnconditional(void) const; 564 565 /** Computation of derived values. 566 This function checks if the derived values like lat/lon and 567 transformation matrices are already computed. If so, it 568 returns. If they need to be computed this is done here. */ ComputeDerived(void)569 void ComputeDerived(void) const { 570 if (!mCacheValid) 571 ComputeDerivedUnconditional(); 572 } 573 574 /** The coordinates in the earth centered frame. This is the master copy. 575 The coordinate frame has its center in the middle of the earth. 576 Its x-axis points from the center of the earth towards a 577 location with zero latitude and longitude on the earths 578 surface. The y-axis points from the center of the earth towards a 579 location with zero latitude and 90deg longitude on the earths 580 surface. The z-axis points from the earths center to the 581 geographic north pole. 582 @see W. C. Durham "Aircraft Dynamics & Control", section 2.2 */ 583 FGColumnVector3 mECLoc; 584 585 /** The cached lon/lat/radius values. */ 586 mutable double mLon; 587 mutable double mLat; 588 mutable double mRadius; 589 mutable double mGeodLat; 590 mutable double GeodeticAltitude; 591 592 /** The cached rotation matrices from and to the associated frames. */ 593 mutable FGMatrix33 mTl2ec; 594 mutable FGMatrix33 mTec2l; 595 596 /* Terms for geodetic latitude calculation. Values are from WGS84 model */ 597 double a; // Earth semimajor axis in feet 598 double e2; // Earth eccentricity squared 599 double c; 600 double ec; 601 double ec2; 602 603 /** A data validity flag. 604 This class implements caching of the derived values like the 605 orthogonal rotation matrices or the lon/lat/radius values. For caching we 606 carry a flag which signals if the values are valid or not. 607 The C++ keyword "mutable" tells the compiler that the data member is 608 allowed to change during a const member function. */ 609 mutable bool mCacheValid; 610 611 /** The ground callback object pointer */ 612 static FGGroundCallback_ptr GroundCallback; 613 }; 614 615 /** Scalar multiplication. 616 617 @param scalar scalar value to multiply with. 618 @param l Vector to multiply. 619 620 Multiply the Vector with a scalar value. */ 621 inline FGLocation operator*(double scalar, const FGLocation& l) 622 { 623 return l.operator*(scalar); 624 } 625 626 } // namespace JSBSim 627 628 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 629 #endif 630