1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 Module: FGPropagate.cpp
6 Purpose: Integrate the EOM to determine instantaneous position
9 ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
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
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
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.
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.
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 This class encapsulates the integration of rates and accelerations to get the
31 current position of the aircraft.
34 --------------------------------------------------------------------------------
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 COMMENTS, REFERENCES, and NOTES
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40 [1] Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
41 Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420 Naval Postgraduate
43 [2] D. M. Henderson, "Euler Angles, Quaternions, and Transformation Matrices",
45 [3] Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
46 NASA-Ames", NASA CR-2497, January 1975
47 [4] Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
48 Wiley & Sons, 1979 ISBN 0-471-03032-5
49 [5] Bernard Etkin, "Dynamics of Flight, Stability and Control", Wiley & Sons,
50 1982 ISBN 0-471-08936-2
52 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
59 #include "FGPropagate.h"
61 #include <FGFDMExec.h>
62 #include "FGAircraft.h"
63 #include "FGMassBalance.h"
64 #include "FGInertial.h"
65 #include <input_output/FGPropertyManager.h>
69 static const char *IdSrc = "$Id$";
70 static const char *IdHdr = ID_PROPAGATE;
72 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
76 FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex)
81 last2_vPQRdot.InitMatrix();
82 last_vPQRdot.InitMatrix();
85 last2_vUVWdot.InitMatrix();
86 last_vUVWdot.InitMatrix();
89 last2_vLocationDot.InitMatrix();
90 last_vLocationDot.InitMatrix();
91 vLocationDot.InitMatrix();
93 vOmegaLocal.InitMatrix();
95 integrator_rotational_rate = eAdamsBashforth2;
96 integrator_translational_rate = eAdamsBashforth2;
97 integrator_rotational_position = eTrapezoidal;
98 integrator_translational_position = eTrapezoidal;
104 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 FGPropagate::~FGPropagate(void)
111 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113 bool FGPropagate::InitModel(void)
115 if (!FGModel::InitModel()) return false;
117 SeaLevelRadius = Inertial->GetRefRadius(); // For initialization ONLY
118 RunwayRadius = SeaLevelRadius;
120 VState.vLocation.SetRadius( SeaLevelRadius + 4.0 ); // Todo Add terrain elevation?
121 VState.vLocation.SetEllipse(Inertial->GetSemimajor(), Inertial->GetSemiminor());
122 vOmega = FGColumnVector3( 0.0, 0.0, Inertial->omega() ); // Earth rotation vector
124 last2_vPQRdot.InitMatrix();
125 last_vPQRdot.InitMatrix();
126 vPQRdot.InitMatrix();
128 last2_vUVWdot.InitMatrix();
129 last_vUVWdot.InitMatrix();
130 vUVWdot.InitMatrix();
132 last2_vLocationDot.InitMatrix();
133 last_vLocationDot.InitMatrix();
134 vLocationDot.InitMatrix();
136 vOmegaLocal.InitMatrix();
138 integrator_rotational_rate = eAdamsBashforth2;
139 integrator_translational_rate = eAdamsBashforth2;
140 integrator_rotational_position = eTrapezoidal;
141 integrator_translational_position = eTrapezoidal;
146 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148 void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
150 SeaLevelRadius = FGIC->GetSeaLevelRadiusFtIC();
151 RunwayRadius = SeaLevelRadius;
153 // Set the position lat/lon/radius
154 VState.vLocation.SetPosition( FGIC->GetLongitudeRadIC(),
155 FGIC->GetLatitudeRadIC(),
156 FGIC->GetAltitudeFtIC() + FGIC->GetSeaLevelRadiusFtIC() );
158 VehicleRadius = GetRadius();
159 radInv = 1.0/VehicleRadius;
161 // Set the Orientation from the euler angles
162 VState.vQtrn = FGQuaternion( FGIC->GetPhiRadIC(),
163 FGIC->GetThetaRadIC(),
164 FGIC->GetPsiRadIC() );
166 // Set the velocities in the instantaneus body frame
167 VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(),
168 FGIC->GetVBodyFpsIC(),
169 FGIC->GetWBodyFpsIC() );
171 // Set the angular velocities in the instantaneus body frame.
172 VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(),
174 FGIC->GetRRadpsIC() );
176 // Compute the local frame ECEF velocity
177 vVel = GetTb2l()*VState.vUVW;
179 // Finally, make sure that the quaternion stays normalized.
180 VState.vQtrn.Normalize();
182 // Recompute the RunwayRadius level.
183 RecomputeRunwayRadius();
186 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188 Purpose: Called on a schedule to perform EOM integration
189 Notes: [JB] Run in standalone mode, SeaLevelRadius will be reference radius.
190 In FGFS, SeaLevelRadius is stuffed from FGJSBSim in JSBSim.cxx each pass.
192 At the top of this Run() function, see several "shortcuts" (or, aliases) being
193 set up for use later, rather than using the longer class->function() notation.
195 This propagation is done using the current state values
196 and current derivatives. Based on these values we compute an approximation to the
197 state values for (now + dt).
199 In the code below, variables named beginning with a small "v" refer to a
200 a column vector, variables named beginning with a "T" refer to a transformation
201 matrix. ECEF refers to Earth Centered Earth Fixed. ECI refers to Earth Centered
206 bool FGPropagate::Run(void)
208 if (FGModel::Run()) return true; // Fast return if we have nothing to do ...
209 if (FDMExec->Holding()) return false;
211 RecomputeRunwayRadius();
213 // Calculate current aircraft radius from center of planet
215 VehicleRadius = GetRadius();
216 radInv = 1.0/VehicleRadius;
218 // These local copies of the transformation matrices are for use this
219 // pass through Run() only.
221 Tl2b = GetTl2b(); // local to body frame transform
222 Tb2l = Tl2b.Transposed(); // body to local frame transform
223 Tl2ec = GetTl2ec(); // local to ECEF transform
224 Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
225 Tec2b = Tl2b * Tec2l; // ECEF to body frame transform
226 Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform
227 Ti2ec = GetTi2ec(); // ECI to ECEF transform
228 Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
229 Ti2b = Tec2b*Ti2ec; // ECI to body frame transform
230 Tb2i = Ti2b.Transposed(); // body to ECI frame transform
232 // Compute vehicle velocity wrt ECEF frame, expressed in Local horizontal frame.
233 vVel = Tb2l * VState.vUVW;
235 // Inertial angular velocity measured in the body frame.
236 vPQRi = VState.vPQR + Tec2b*vOmega;
238 // Calculate state derivatives
239 CalculatePQRdot(); // Angular rate derivative
240 CalculateUVWdot(); // Translational rate derivative
241 CalculateQuatdot(); // Angular orientation derivative
242 CalculateLocationdot(); // Translational position derivative
244 // Integrate to propagate the state
246 double dt = State->Getdt()*rate; // The 'stepsize'
248 // Propagate rotational velocity
250 switch(integrator_rotational_rate) {
251 case eRectEuler: VState.vPQR += dt*vPQRdot;
253 case eTrapezoidal: VState.vPQR += 0.5*dt*(vPQRdot + last_vPQRdot);
255 case eAdamsBashforth2: VState.vPQR += dt*(1.5*vPQRdot - 0.5*last_vPQRdot);
257 case eAdamsBashforth3: VState.vPQR += (1/12.0)*dt*(23.0*vPQRdot - 16.0*last_vPQRdot + 5.0*last2_vPQRdot);
259 case eNone: // do nothing, freeze angular rate
263 // Propagate translational velocity
265 switch(integrator_translational_rate) {
266 case eRectEuler: VState.vUVW += dt*vUVWdot;
268 case eTrapezoidal: VState.vUVW += 0.5*dt*(vUVWdot + last_vUVWdot);
270 case eAdamsBashforth2: VState.vUVW += dt*(1.5*vUVWdot - 0.5*last_vUVWdot);
272 case eAdamsBashforth3: VState.vUVW += (1/12.0)*dt*(23.0*vUVWdot - 16.0*last_vUVWdot + 5.0*last2_vUVWdot);
274 case eNone: // do nothing, freeze translational rate
278 // Propagate angular position
280 switch(integrator_rotational_position) {
281 case eRectEuler: VState.vQtrn += dt*vQtrndot;
283 case eTrapezoidal: VState.vQtrn += 0.5*dt*(vQtrndot + last_vQtrndot);
285 case eAdamsBashforth2: VState.vQtrn += dt*(1.5*vQtrndot - 0.5*last_vQtrndot);
287 case eAdamsBashforth3: VState.vQtrn += (1/12.0)*dt*(23.0*vQtrndot - 16.0*last_vQtrndot + 5.0*last2_vQtrndot);
289 case eNone: // do nothing, freeze angular position
293 // Propagate translational position
295 switch(integrator_translational_position) {
296 case eRectEuler: VState.vLocation += dt*vLocationDot;
298 case eTrapezoidal: VState.vLocation += 0.5*dt*(vLocationDot + last_vLocationDot);
300 case eAdamsBashforth2: VState.vLocation += dt*(1.5*vLocationDot - 0.5*last_vLocationDot);
302 case eAdamsBashforth3: VState.vLocation += (1/12.0)*dt*(23.0*vLocationDot - 16.0*last_vLocationDot + 5.0*last2_vLocationDot);
304 case eNone: // do nothing, freeze translational position
310 last2_vPQRdot = last_vPQRdot;
311 last_vPQRdot = vPQRdot;
313 last2_vUVWdot = last_vUVWdot;
314 last_vUVWdot = vUVWdot;
316 last2_vQtrndot = last_vQtrndot;
317 last_vQtrndot = vQtrndot;
319 last2_vLocationDot = last_vLocationDot;
320 last_vLocationDot = vLocationDot;
326 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327 // Compute body frame rotational accelerations based on the current body moments
329 // vPQRdot is the derivative of the absolute angular velocity of the vehicle
330 // (body rate with respect to the inertial frame), expressed in the body frame,
331 // where the derivative is taken in the body frame.
332 // J is the inertia matrix
333 // Jinv is the inverse inertia matrix
334 // vMoments is the moment vector in the body frame
335 // vPQRi is the total inertial angular velocity of the vehicle
336 // expressed in the body frame.
337 // Reference: See Stevens and Lewis, "Aircraft Control and Simulation",
338 // Second edition (2004), eqn 1.5-16e (page 50)
340 void FGPropagate::CalculatePQRdot(void)
342 const FGColumnVector3& vMoments = Aircraft->GetMoments(); // current moments
343 const FGMatrix33& J = MassBalance->GetJ(); // inertia matrix
344 const FGMatrix33& Jinv = MassBalance->GetJinv(); // inertia matrix inverse
346 // Compute body frame rotational accelerations based on the current body
347 // moments and the total inertial angular velocity expressed in the body
350 vPQRdot = Jinv*(vMoments - vPQRi*(J*vPQRi));
353 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354 // Compute the quaternion orientation derivative
356 // vQtrndot is the quaternion derivative.
357 // Reference: See Stevens and Lewis, "Aircraft Control and Simulation",
358 // Second edition (2004), eqn 1.5-16b (page 50)
360 void FGPropagate::CalculateQuatdot(void)
362 vOmegaLocal.InitMatrix( radInv*vVel(eEast),
363 -radInv*vVel(eNorth),
364 -radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
366 // Compute quaternion orientation derivative on current body rates
367 vQtrndot = VState.vQtrn.GetQDot( VState.vPQR - Tl2b*vOmegaLocal);
370 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
371 // This set of calculations results in the body frame accelerations being
373 // Reference: See Stevens and Lewis, "Aircraft Control and Simulation",
374 // Second edition (2004), eqn 1.5-16d (page 50)
376 void FGPropagate::CalculateUVWdot(void)
378 double mass = MassBalance->GetMass(); // mass
379 const FGColumnVector3& vForces = Aircraft->GetForces(); // current forces
381 const FGColumnVector3 vGravAccel( 0.0, 0.0, Inertial->GetGAccel(VehicleRadius) );
383 // Begin to compute body frame accelerations based on the current body forces
384 vUVWdot = vForces/mass - VState.vPQR * VState.vUVW;
386 // Include Coriolis acceleration.
387 vUVWdot -= 2.0 * (Ti2b *vOmega) * VState.vUVW;
389 // Include Centrifugal acceleration.
390 if (!GroundReactions->GetWOW()) {
391 vUVWdot -= Ti2b*(vOmega*(vOmega*(Tec2i*VState.vLocation)));
394 // Include Gravitation accel
395 FGColumnVector3 gravAccel = Tl2b*vGravAccel;
396 vUVWdot += gravAccel;
399 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401 void FGPropagate::CalculateLocationdot(void)
403 // Transform the vehicle velocity relative to the ECEF frame, expressed
404 // in the body frame, to be expressed in the ECEF frame.
405 vLocationDot = Tb2ec * VState.vUVW;
407 // Now, transform the velocity vector of the body relative to the origin (Earth
408 // center) to be expressed in the inertial frame, and add the vehicle velocity
409 // contribution due to the rotation of the planet. The above velocity is only
410 // relative to the rotating ECEF frame.
411 // Reference: See Stevens and Lewis, "Aircraft Control and Simulation",
412 // Second edition (2004), eqn 1.5-16c (page 50)
414 vInertialVelocity = Tec2i * vLocationDot + (vOmega * (Tec2i * VState.vLocation));
417 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419 void FGPropagate::RecomputeRunwayRadius(void)
421 // Get the runway radius.
422 FGLocation contactloc;
424 FGGroundCallback* gcb = FDMExec->GetGroundCallback();
425 double t = State->Getsim_time();
426 gcb->GetAGLevel(t, VState.vLocation, contactloc, dv, dv);
427 RunwayRadius = contactloc.GetRadius();
430 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432 void FGPropagate::SetTerrainElevationASL(double tt)
434 FDMExec->GetGroundCallback()->SetTerrainGeoCentRadius(tt+SeaLevelRadius);
437 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439 double FGPropagate::GetTerrainElevationASL(void) const
441 return FDMExec->GetGroundCallback()->GetTerrainGeoCentRadius()-SeaLevelRadius;
444 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446 const FGMatrix33& FGPropagate::GetTi2ec(void)
448 return VState.vLocation.GetTi2ec(Inertial->GetEarthPositionAngle());
451 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453 const FGMatrix33& FGPropagate::GetTec2i(void)
455 return VState.vLocation.GetTec2i(Inertial->GetEarthPositionAngle());
458 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
460 void FGPropagate::Seth(double tt)
462 VState.vLocation.SetRadius( tt + SeaLevelRadius );
465 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
467 double FGPropagate::GetRunwayRadius(void) const
472 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
474 double FGPropagate::GetDistanceAGL(void) const
476 return VState.vLocation.GetRadius() - RunwayRadius;
479 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 void FGPropagate::SetDistanceAGL(double tt)
483 VState.vLocation.SetRadius( tt + RunwayRadius );
486 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
488 void FGPropagate::bind(void)
490 typedef double (FGPropagate::*PMF)(int) const;
491 // typedef double (FGPropagate::*dPMF)() const;
492 PropertyManager->Tie("velocities/h-dot-fps", this, &FGPropagate::Gethdot);
494 PropertyManager->Tie("velocities/v-north-fps", this, eNorth, (PMF)&FGPropagate::GetVel);
495 PropertyManager->Tie("velocities/v-east-fps", this, eEast, (PMF)&FGPropagate::GetVel);
496 PropertyManager->Tie("velocities/v-down-fps", this, eDown, (PMF)&FGPropagate::GetVel);
498 PropertyManager->Tie("velocities/u-fps", this, eU, (PMF)&FGPropagate::GetUVW);
499 PropertyManager->Tie("velocities/v-fps", this, eV, (PMF)&FGPropagate::GetUVW);
500 PropertyManager->Tie("velocities/w-fps", this, eW, (PMF)&FGPropagate::GetUVW);
502 PropertyManager->Tie("velocities/p-rad_sec", this, eP, (PMF)&FGPropagate::GetPQR);
503 PropertyManager->Tie("velocities/q-rad_sec", this, eQ, (PMF)&FGPropagate::GetPQR);
504 PropertyManager->Tie("velocities/r-rad_sec", this, eR, (PMF)&FGPropagate::GetPQR);
506 PropertyManager->Tie("velocities/eci-velocity-mag-fps", this, &FGPropagate::GetInertialVelocityMagnitude);
508 PropertyManager->Tie("accelerations/pdot-rad_sec2", this, eP, (PMF)&FGPropagate::GetPQRdot);
509 PropertyManager->Tie("accelerations/qdot-rad_sec2", this, eQ, (PMF)&FGPropagate::GetPQRdot);
510 PropertyManager->Tie("accelerations/rdot-rad_sec2", this, eR, (PMF)&FGPropagate::GetPQRdot);
512 PropertyManager->Tie("accelerations/udot-ft_sec2", this, eU, (PMF)&FGPropagate::GetUVWdot);
513 PropertyManager->Tie("accelerations/vdot-ft_sec2", this, eV, (PMF)&FGPropagate::GetUVWdot);
514 PropertyManager->Tie("accelerations/wdot-ft_sec2", this, eW, (PMF)&FGPropagate::GetUVWdot);
516 PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::Geth, &FGPropagate::Seth, true);
517 PropertyManager->Tie("position/h-sl-meters", this, &FGPropagate::Gethmeters, &FGPropagate::Sethmeters, true);
518 PropertyManager->Tie("position/lat-gc-rad", this, &FGPropagate::GetLatitude, &FGPropagate::SetLatitude);
519 PropertyManager->Tie("position/long-gc-rad", this, &FGPropagate::GetLongitude, &FGPropagate::SetLongitude);
520 PropertyManager->Tie("position/lat-gc-deg", this, &FGPropagate::GetLatitudeDeg, &FGPropagate::SetLatitudeDeg);
521 PropertyManager->Tie("position/long-gc-deg", this, &FGPropagate::GetLongitudeDeg, &FGPropagate::SetLongitudeDeg);
522 PropertyManager->Tie("position/lat-geod-rad", this, &FGPropagate::GetGeodLatitudeRad);
523 PropertyManager->Tie("position/lat-geod-deg", this, &FGPropagate::GetGeodLatitudeDeg);
524 PropertyManager->Tie("position/geod-alt-ft", this, &FGPropagate::GetGeodeticAltitude);
525 PropertyManager->Tie("position/h-agl-ft", this, &FGPropagate::GetDistanceAGL, &FGPropagate::SetDistanceAGL);
526 PropertyManager->Tie("position/radius-to-vehicle-ft", this, &FGPropagate::GetRadius);
527 PropertyManager->Tie("position/terrain-elevation-asl-ft", this,
528 &FGPropagate::GetTerrainElevationASL,
529 &FGPropagate::SetTerrainElevationASL, false);
531 PropertyManager->Tie("metrics/runway-radius", this, &FGPropagate::GetRunwayRadius);
533 PropertyManager->Tie("attitude/phi-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler);
534 PropertyManager->Tie("attitude/theta-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
535 PropertyManager->Tie("attitude/psi-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
537 PropertyManager->Tie("attitude/roll-rad", this, (int)ePhi, (PMF)&FGPropagate::GetEuler);
538 PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
539 PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
541 PropertyManager->Tie("simulation/integrator/rate/rotational", &integrator_rotational_rate);
542 PropertyManager->Tie("simulation/integrator/rate/translational", &integrator_translational_rate);
543 PropertyManager->Tie("simulation/integrator/position/rotational", &integrator_rotational_position);
544 PropertyManager->Tie("simulation/integrator/position/translational", &integrator_translational_position);
547 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
548 // The bitmasked value choices are as follows:
549 // unset: In this case (the default) JSBSim would only print
550 // out the normally expected messages, essentially echoing
551 // the config files as they are read. If the environment
552 // variable is not set, debug_lvl is set to 1 internally
553 // 0: This requests JSBSim not to output any messages
555 // 1: This value explicity requests the normal JSBSim
557 // 2: This value asks for a message to be printed out when
558 // a class is instantiated
559 // 4: When this value is set, a message is displayed when a
560 // FGModel object executes its Run() method
561 // 8: When this value is set, various runtime state variables
562 // are printed out periodically
563 // 16: When set various parameters are sanity checked and
564 // a message is printed out when they go out of bounds
566 void FGPropagate::Debug(int from)
568 if (debug_lvl <= 0) return;
570 if (debug_lvl & 1) { // Standard console startup message output
571 if (from == 0) { // Constructor
575 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
576 if (from == 0) cout << "Instantiated: FGPropagate" << endl;
577 if (from == 1) cout << "Destroyed: FGPropagate" << endl;
579 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
581 if (debug_lvl & 8 ) { // Runtime state variables
583 if (debug_lvl & 16) { // Sanity checking
584 if (from == 2) { // State sanity checking
585 if (fabs(VState.vPQR.Magnitude()) > 1000.0) {
586 cerr << endl << "Vehicle rotation rate is excessive (>1000 rad/sec): " << VState.vPQR.Magnitude() << endl;
589 if (fabs(VState.vUVW.Magnitude()) > 1.0e10) {
590 cerr << endl << "Vehicle velocity is excessive (>1e10 ft/sec): " << VState.vUVW.Magnitude() << endl;
593 if (fabs(GetDistanceAGL()) > 1e10) {
594 cerr << endl << "Vehicle altitude is excessive (>1e10 ft): " << GetDistanceAGL() << endl;
599 if (debug_lvl & 64) {
600 if (from == 0) { // Constructor
601 cout << IdSrc << endl;
602 cout << IdHdr << endl;