JSBSim Flight Dynamics Model  1.0 (02 March 2017)
An Open Source Flight Dynamics and Control Software Library in C++
FGFDMExec.cpp
1 
2 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 
4  Module: FGFDMExec.cpp
5  Author: Jon S. Berndt
6  Date started: 11/17/98
7  Purpose: Schedules and runs the model routines.
8 
9  ------------- Copyright (C) 1999 Jon S. Berndt (jon@jsbsim.org) -------------
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 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 
31 This class wraps up the simulation scheduling routines.
32 
33 HISTORY
34 --------------------------------------------------------------------------------
35 11/17/98 JSB Created
36 
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 COMMENTS, REFERENCES, and NOTES
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40 
41 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 INCLUDES
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
44 
45 #include <iostream>
46 #include <iterator>
47 #include <cstdlib>
48 #include <iomanip>
49 
50 #include "FGFDMExec.h"
51 #include "models/atmosphere/FGStandardAtmosphere.h"
52 #include "models/atmosphere/FGWinds.h"
53 #include "models/FGFCS.h"
54 #include "models/FGPropulsion.h"
55 #include "models/FGMassBalance.h"
56 #include "models/FGGroundReactions.h"
57 #include "models/FGExternalReactions.h"
58 #include "models/FGBuoyantForces.h"
59 #include "models/FGAerodynamics.h"
60 #include "models/FGInertial.h"
61 #include "models/FGAircraft.h"
62 #include "models/FGAccelerations.h"
63 #include "models/FGPropagate.h"
64 #include "models/FGAuxiliary.h"
65 #include "models/FGInput.h"
66 #include "models/FGOutput.h"
67 #include "initialization/FGTrim.h"
68 #include "input_output/FGScript.h"
69 #include "input_output/FGXMLFileRead.h"
70 
71 using namespace std;
72 
73 namespace JSBSim {
74 
75 IDENT(IdSrc,"$Id: FGFDMExec.cpp,v 1.193 2017/02/25 14:23:18 bcoconni Exp $");
76 IDENT(IdHdr,ID_FDMEXEC);
77 
78 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 CLASS IMPLEMENTATION
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
81 
82 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 // Constructor
84 
85 FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root), FDMctr(fdmctr)
86 {
87  Frame = 0;
88  Error = 0;
89  IC = 0;
90  Trim = 0;
91  Script = 0;
92  disperse = 0;
93 
94  RootDir = "";
95 
96  modelLoaded = false;
97  IsChild = false;
98  holding = false;
99  Terminate = false;
100  StandAlone = false;
101  ResetMode = 0;
102  RandomSeed = 0;
103  HoldDown = false;
104 
105  IncrementThenHolding = false; // increment then hold is off by default
106  TimeStepsUntilHold = -1;
107 
108  sim_time = 0.0;
109  dT = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is
110  // run in standalone mode with no initialization file.
111 
112  AircraftPath = "aircraft";
113  EnginePath = "engine";
114  SystemsPath = "systems";
115 
116  try {
117  char* num = getenv("JSBSIM_DEBUG");
118  if (num) debug_lvl = atoi(num); // set debug level
119  } catch (...) { // if error set to 1
120  debug_lvl = 1;
121  }
122 
123  if (Root == 0) { // Then this is the root FDM
124  Root = new FGPropertyManager; // Create the property manager
125  StandAlone = true;
126  }
127 
128  if (FDMctr == 0) {
129  FDMctr = new unsigned int; // Create and initialize the child FDM counter
130  (*FDMctr) = 0;
131  }
132 
133  // Store this FDM's ID
134  IdFDM = (*FDMctr); // The main (parent) JSBSim instance is always the "zeroth"
135 
136  // Prepare FDMctr for the next child FDM id
137  (*FDMctr)++; // instance. "child" instances are loaded last.
138 
139  FGPropertyNode* instanceRoot = Root->GetNode("/fdm/jsbsim",IdFDM,true);
140  instance = new FGPropertyManager(instanceRoot);
141 
142  try {
143  char* num = getenv("JSBSIM_DISPERSE");
144  if (num) {
145  if (atoi(num) != 0) disperse = 1; // set dispersions on
146  }
147  } catch (...) { // if error set to false
148  disperse = 0;
149  std::cerr << "Could not process JSBSIM_DISPERSIONS environment variable: Assumed NO dispersions." << endl;
150  }
151 
152  Debug(0);
153  // this is to catch errors in binding member functions to the property tree.
154  try {
155  Allocate();
156  } catch (const string& msg ) {
157  cout << "Caught error: " << msg << endl;
158  exit(1);
159  }
160 
161  trim_status = false;
162  ta_mode = 99;
163  trim_completed = 0;
164 
165  Constructing = true;
166  typedef int (FGFDMExec::*iPMF)(void) const;
167  instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, false);
168  instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false);
169  instance->Tie("simulation/disperse", this, &FGFDMExec::GetDisperse);
170  instance->Tie("simulation/randomseed", this, (iPMF)&FGFDMExec::SRand, &FGFDMExec::SRand, false);
171  instance->Tie("simulation/terminate", (int *)&Terminate);
172  instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime);
173  instance->Tie("simulation/dt", this, &FGFDMExec::GetDeltaT);
174  instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel);
175  instance->Tie("simulation/frame", (int *)&Frame, false);
176  instance->Tie("simulation/trim-completed", (int *)&trim_completed, false);
177  instance->Tie("forces/hold-down", this, &FGFDMExec::GetHoldDown, &FGFDMExec::SetHoldDown);
178 
179  Constructing = false;
180 }
181 
182 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183 
185 {
186  try {
187  Unbind();
188  DeAllocate();
189 
190  delete instance;
191 
192  if (IdFDM == 0) { // Meaning this is no child FDM
193  if(Root != 0) {
194  if(StandAlone)
195  delete Root;
196  Root = 0;
197  }
198  if(FDMctr != 0) {
199  delete FDMctr;
200  FDMctr = 0;
201  }
202  }
203  } catch (const string& msg ) {
204  cout << "Caught error: " << msg << endl;
205  }
206 
207  for (unsigned int i=1; i<ChildFDMList.size(); i++) delete ChildFDMList[i]->exec;
208  ChildFDMList.clear();
209 
210  PropertyCatalog.clear();
211 
213 
214  if (FDMctr != 0) (*FDMctr)--;
215 
216  Debug(1);
217 }
218 
219 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220 
221 bool FGFDMExec::Allocate(void)
222 {
223  bool result=true;
224 
225  Models.resize(eNumStandardModels);
226 
227  // First build the inertial model since some other models are relying on
228  // the inertial model and the ground callback to build themselves.
229  // Note that this does not affect the order in which the models will be
230  // executed later.
231  Models[eInertial] = new FGInertial(this);
232  SetGroundCallback(new FGDefaultGroundCallback(static_cast<FGInertial*>(Models[eInertial])->GetRefRadius()));
233 
234  // See the eModels enum specification in the header file. The order of the
235  // enums specifies the order of execution. The Models[] vector is the primary
236  // storage array for the list of models.
237  Models[ePropagate] = new FGPropagate(this);
238  Models[eInput] = new FGInput(this);
239  Models[eAtmosphere] = new FGStandardAtmosphere(this);
240  Models[eWinds] = new FGWinds(this);
241  Models[eSystems] = new FGFCS(this);
242  Models[eMassBalance] = new FGMassBalance(this);
243  Models[eAuxiliary] = new FGAuxiliary(this);
244  Models[ePropulsion] = new FGPropulsion(this);
245  Models[eAerodynamics] = new FGAerodynamics (this);
246  Models[eGroundReactions] = new FGGroundReactions(this);
247  Models[eExternalReactions] = new FGExternalReactions(this);
248  Models[eBuoyantForces] = new FGBuoyantForces(this);
249  Models[eAircraft] = new FGAircraft(this);
250  Models[eAccelerations] = new FGAccelerations(this);
251  Models[eOutput] = new FGOutput(this);
252 
253  // Assign the Model shortcuts for internal executive use only.
254  Propagate = (FGPropagate*)Models[ePropagate];
255  Inertial = (FGInertial*)Models[eInertial];
256  Atmosphere = (FGAtmosphere*)Models[eAtmosphere];
257  Winds = (FGWinds*)Models[eWinds];
258  FCS = (FGFCS*)Models[eSystems];
259  MassBalance = (FGMassBalance*)Models[eMassBalance];
260  Auxiliary = (FGAuxiliary*)Models[eAuxiliary];
261  Propulsion = (FGPropulsion*)Models[ePropulsion];
262  Aerodynamics = (FGAerodynamics*)Models[eAerodynamics];
263  GroundReactions = (FGGroundReactions*)Models[eGroundReactions];
264  ExternalReactions = (FGExternalReactions*)Models[eExternalReactions];
265  BuoyantForces = (FGBuoyantForces*)Models[eBuoyantForces];
266  Aircraft = (FGAircraft*)Models[eAircraft];
267  Accelerations = (FGAccelerations*)Models[eAccelerations];
268  Output = (FGOutput*)Models[eOutput];
269 
270  // Initialize planet (environment) constants
271  LoadPlanetConstants();
272 
273  // Initialize models
274  for (unsigned int i = 0; i < Models.size(); i++) {
275  // The Input/Output models must not be initialized prior to IC loading
276  if (i == eInput || i == eOutput) continue;
277 
278  LoadInputs(i);
279  Models[i]->InitModel();
280  }
281 
282  IC = new FGInitialCondition(this);
283  IC->bind(instance);
284 
285  modelLoaded = false;
286 
287  return result;
288 }
289 
290 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291 
292 bool FGFDMExec::DeAllocate(void)
293 {
294 
295  for (unsigned int i=0; i<eNumStandardModels; i++) delete Models[i];
296  Models.clear();
297 
298  delete Script;
299  delete IC;
300  delete Trim;
301 
302  Error = 0;
303 
304  modelLoaded = false;
305  return modelLoaded;
306 }
307 
308 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309 
310 bool FGFDMExec::Run(void)
311 {
312  bool success=true;
313 
314  Debug(2);
315 
316  for (unsigned int i=1; i<ChildFDMList.size(); i++) {
317  ChildFDMList[i]->AssignState( (FGPropagate*)Models[ePropagate] ); // Transfer state to the child FDM
318  ChildFDMList[i]->Run();
319  }
320 
321  IncrTime();
322 
323  // returns true if success, false if complete
324  if (Script != 0 && !IntegrationSuspended()) success = Script->RunScript();
325 
326  for (unsigned int i = 0; i < Models.size(); i++) {
327  LoadInputs(i);
328  Models[i]->Run(holding);
329  }
330 
331  if (ResetMode) {
332  unsigned int mode = ResetMode;
333 
334  ResetMode = 0;
336  }
337 
338  if (Terminate) success = false;
339 
340  return success;
341 }
342 
343 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
344 
345 void FGFDMExec::LoadInputs(unsigned int idx)
346 {
347  switch(idx) {
348  case ePropagate:
349  Propagate->in.vPQRidot = Accelerations->GetPQRidot();
350  Propagate->in.vUVWidot = Accelerations->GetUVWidot();
351  Propagate->in.DeltaT = dT;
352  break;
353  case eInput:
354  break;
355  case eInertial:
356  Inertial->in.Radius = Propagate->GetRadius();
357  Inertial->in.Latitude = Propagate->GetLatitude();
358  break;
359  case eAtmosphere:
360  Atmosphere->in.altitudeASL = Propagate->GetAltitudeASL();
361  break;
362  case eWinds:
363  Winds->in.AltitudeASL = Propagate->GetAltitudeASL();
364  Winds->in.DistanceAGL = Propagate->GetDistanceAGL();
365  Winds->in.Tl2b = Propagate->GetTl2b();
366  Winds->in.Tw2b = Auxiliary->GetTw2b();
367  Winds->in.V = Auxiliary->GetVt();
368  Winds->in.totalDeltaT = dT * Winds->GetRate();
369  break;
370  case eAuxiliary:
371  Auxiliary->in.Pressure = Atmosphere->GetPressure();
372  Auxiliary->in.Density = Atmosphere->GetDensity();
373  Auxiliary->in.DensitySL = Atmosphere->GetDensitySL();
374  Auxiliary->in.PressureSL = Atmosphere->GetPressureSL();
375  Auxiliary->in.Temperature = Atmosphere->GetTemperature();
376  Auxiliary->in.SoundSpeed = Atmosphere->GetSoundSpeed();
377  Auxiliary->in.KinematicViscosity = Atmosphere->GetKinematicViscosity();
378  Auxiliary->in.DistanceAGL = Propagate->GetDistanceAGL();
379  Auxiliary->in.Mass = MassBalance->GetMass();
380  Auxiliary->in.Tl2b = Propagate->GetTl2b();
381  Auxiliary->in.Tb2l = Propagate->GetTb2l();
382  Auxiliary->in.vPQR = Propagate->GetPQR();
383  Auxiliary->in.vPQRi = Propagate->GetPQRi();
384  Auxiliary->in.vPQRidot = Accelerations->GetPQRidot();
385  Auxiliary->in.vUVW = Propagate->GetUVW();
386  Auxiliary->in.vUVWdot = Accelerations->GetUVWdot();
387  Auxiliary->in.vVel = Propagate->GetVel();
388  Auxiliary->in.vBodyAccel = Accelerations->GetBodyAccel();
389  Auxiliary->in.ToEyePt = MassBalance->StructuralToBody(Aircraft->GetXYZep());
390  Auxiliary->in.VRPBody = MassBalance->StructuralToBody(Aircraft->GetXYZvrp());
391  Auxiliary->in.RPBody = MassBalance->StructuralToBody(Aircraft->GetXYZrp());
392  Auxiliary->in.vFw = Aerodynamics->GetvFw();
393  Auxiliary->in.vLocation = Propagate->GetLocation();
394  Auxiliary->in.CosTht = Propagate->GetCosEuler(eTht);
395  Auxiliary->in.SinTht = Propagate->GetSinEuler(eTht);
396  Auxiliary->in.CosPhi = Propagate->GetCosEuler(ePhi);
397  Auxiliary->in.SinPhi = Propagate->GetSinEuler(ePhi);
398  Auxiliary->in.Psi = Propagate->GetEuler(ePsi);
399  Auxiliary->in.TotalWindNED = Winds->GetTotalWindNED();
400  Auxiliary->in.TurbPQR = Winds->GetTurbPQR();
401  Auxiliary->in.WindPsi = Winds->GetWindPsi();
402  Auxiliary->in.Vwind = Winds->GetTotalWindNED().Magnitude();
403  break;
404  case eSystems:
405  // Dynamic inputs come into the components that FCS manages through properties
406  break;
407  case ePropulsion:
408  Propulsion->in.Pressure = Atmosphere->GetPressure();
409  Propulsion->in.PressureRatio = Atmosphere->GetPressureRatio();
410  Propulsion->in.Temperature = Atmosphere->GetTemperature();
411  Propulsion->in.DensityRatio = Atmosphere->GetDensityRatio();
412  Propulsion->in.Density = Atmosphere->GetDensity();
413  Propulsion->in.Soundspeed = Atmosphere->GetSoundSpeed();
414  Propulsion->in.TotalPressure = Auxiliary->GetTotalPressure();
415  Propulsion->in.Vc = Auxiliary->GetVcalibratedKTS();
416  Propulsion->in.Vt = Auxiliary->GetVt();
417  Propulsion->in.qbar = Auxiliary->Getqbar();
418  Propulsion->in.TAT_c = Auxiliary->GetTAT_C();
419  Propulsion->in.AeroUVW = Auxiliary->GetAeroUVW();
420  Propulsion->in.AeroPQR = Auxiliary->GetAeroPQR();
421  Propulsion->in.alpha = Auxiliary->Getalpha();
422  Propulsion->in.beta = Auxiliary->Getbeta();
423  Propulsion->in.TotalDeltaT = dT * Propulsion->GetRate();
424  Propulsion->in.ThrottlePos = FCS->GetThrottlePos();
425  Propulsion->in.MixturePos = FCS->GetMixturePos();
426  Propulsion->in.ThrottleCmd = FCS->GetThrottleCmd();
427  Propulsion->in.MixtureCmd = FCS->GetMixtureCmd();
428  Propulsion->in.PropAdvance = FCS->GetPropAdvance();
429  Propulsion->in.PropFeather = FCS->GetPropFeather();
430  Propulsion->in.H_agl = Propagate->GetDistanceAGL();
431  Propulsion->in.PQRi = Propagate->GetPQRi();
432 
433  break;
434  case eAerodynamics:
435  Aerodynamics->in.Alpha = Auxiliary->Getalpha();
436  Aerodynamics->in.Beta = Auxiliary->Getbeta();
437  Aerodynamics->in.Qbar = Auxiliary->Getqbar();
438  Aerodynamics->in.Vt = Auxiliary->GetVt();
439  Aerodynamics->in.Tb2w = Auxiliary->GetTb2w();
440  Aerodynamics->in.Tw2b = Auxiliary->GetTw2b();
441  Aerodynamics->in.RPBody = MassBalance->StructuralToBody(Aircraft->GetXYZrp());
442  break;
443  case eGroundReactions:
444  // There are no external inputs to this model.
445  GroundReactions->in.Vground = Auxiliary->GetVground();
446  GroundReactions->in.VcalibratedKts = Auxiliary->GetVcalibratedKTS();
447  GroundReactions->in.Temperature = Atmosphere->GetTemperature();
448  GroundReactions->in.TakeoffThrottle = (FCS->GetThrottlePos().size() > 0) ? (FCS->GetThrottlePos(0) > 0.90) : false;
449  GroundReactions->in.BrakePos = FCS->GetBrakePos();
450  GroundReactions->in.FCSGearPos = FCS->GetGearPos();
451  GroundReactions->in.EmptyWeight = MassBalance->GetEmptyWeight();
452  GroundReactions->in.Tb2l = Propagate->GetTb2l();
453  GroundReactions->in.Tec2l = Propagate->GetTec2l();
454  GroundReactions->in.Tec2b = Propagate->GetTec2b();
455  GroundReactions->in.PQR = Propagate->GetPQR();
456  GroundReactions->in.UVW = Propagate->GetUVW();
457  GroundReactions->in.DistanceAGL = Propagate->GetDistanceAGL();
458  GroundReactions->in.DistanceASL = Propagate->GetAltitudeASL();
459  GroundReactions->in.TotalDeltaT = dT * GroundReactions->GetRate();
460  GroundReactions->in.WOW = GroundReactions->GetWOW();
461  GroundReactions->in.Location = Propagate->GetLocation();
462  GroundReactions->in.vXYZcg = MassBalance->GetXYZcg();
463  break;
464  case eExternalReactions:
465  // There are no external inputs to this model.
466  break;
467  case eBuoyantForces:
468  BuoyantForces->in.Density = Atmosphere->GetDensity();
469  BuoyantForces->in.Pressure = Atmosphere->GetPressure();
470  BuoyantForces->in.Temperature = Atmosphere->GetTemperature();
471  BuoyantForces->in.gravity = Inertial->gravity();
472  break;
473  case eMassBalance:
474  MassBalance->in.GasInertia = BuoyantForces->GetGasMassInertia();
475  MassBalance->in.GasMass = BuoyantForces->GetGasMass();
476  MassBalance->in.GasMoment = BuoyantForces->GetGasMassMoment();
477  MassBalance->in.TanksWeight = Propulsion->GetTanksWeight();
478  MassBalance->in.TanksMoment = Propulsion->GetTanksMoment();
479  MassBalance->in.TankInertia = Propulsion->CalculateTankInertias();
480  break;
481  case eAircraft:
482  Aircraft->in.AeroForce = Aerodynamics->GetForces();
483  Aircraft->in.PropForce = Propulsion->GetForces();
484  Aircraft->in.GroundForce = GroundReactions->GetForces();
485  Aircraft->in.ExternalForce = ExternalReactions->GetForces();
486  Aircraft->in.BuoyantForce = BuoyantForces->GetForces();
487  Aircraft->in.AeroMoment = Aerodynamics->GetMoments();
488  Aircraft->in.PropMoment = Propulsion->GetMoments();
489  Aircraft->in.GroundMoment = GroundReactions->GetMoments();
490  Aircraft->in.ExternalMoment = ExternalReactions->GetMoments();
491  Aircraft->in.BuoyantMoment = BuoyantForces->GetMoments();
492  break;
493  case eAccelerations:
494  Accelerations->in.J = MassBalance->GetJ();
495  Accelerations->in.Jinv = MassBalance->GetJinv();
496  Accelerations->in.Ti2b = Propagate->GetTi2b();
497  Accelerations->in.Tb2i = Propagate->GetTb2i();
498  Accelerations->in.Tec2b = Propagate->GetTec2b();
499  Accelerations->in.Tec2i = Propagate->GetTec2i();
500  Accelerations->in.Moment = Aircraft->GetMoments();
501  Accelerations->in.GroundMoment = GroundReactions->GetMoments();
502  Accelerations->in.Force = Aircraft->GetForces();
503  Accelerations->in.GroundForce = GroundReactions->GetForces();
504  Accelerations->in.GAccel = Inertial->GetGAccel(Propagate->GetRadius());
505  Accelerations->in.J2Grav = Inertial->GetGravityJ2(Propagate->GetLocation());
506  Accelerations->in.vPQRi = Propagate->GetPQRi();
507  Accelerations->in.vPQR = Propagate->GetPQR();
508  Accelerations->in.vUVW = Propagate->GetUVW();
509  Accelerations->in.vInertialPosition = Propagate->GetInertialPosition();
510  Accelerations->in.DeltaT = dT;
511  Accelerations->in.Mass = MassBalance->GetMass();
512  Accelerations->in.MultipliersList = GroundReactions->GetMultipliersList();
513  Accelerations->in.TerrainVelocity = Propagate->GetTerrainVelocity();
514  Accelerations->in.TerrainAngularVel = Propagate->GetTerrainAngularVelocity();
515  break;
516  default:
517  break;
518  }
519 }
520 
521 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
522 
523 void FGFDMExec::LoadPlanetConstants(void)
524 {
525  Propagate->in.vOmegaPlanet = Inertial->GetOmegaPlanet();
526  Accelerations->in.vOmegaPlanet = Inertial->GetOmegaPlanet();
527  Propagate->in.SemiMajor = Inertial->GetSemimajor();
528  Propagate->in.SemiMinor = Inertial->GetSemiminor();
529  Auxiliary->in.SLGravity = Inertial->SLgravity();
530 }
531 
532 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 
534 void FGFDMExec::LoadModelConstants(void)
535 {
536  Winds->in.wingspan = Aircraft->GetWingSpan();
537  Aerodynamics->in.Wingarea = Aircraft->GetWingArea();
538  Aerodynamics->in.Wingchord = Aircraft->Getcbar();
539  Aerodynamics->in.Wingincidence = Aircraft->GetWingIncidence();
540  Aerodynamics->in.Wingspan = Aircraft->GetWingSpan();
541  Auxiliary->in.Wingspan = Aircraft->GetWingSpan();
542  Auxiliary->in.Wingchord = Aircraft->Getcbar();
543  Auxiliary->in.PitotAngle = Aircraft->GetPitotAngle();
544  GroundReactions->in.vXYZcg = MassBalance->GetXYZcg();
545 
546  LoadPlanetConstants();
547 }
548 
549 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
550 // This call will cause the sim time to reset to 0.0
551 
553 {
554  FGPropulsion* propulsion = (FGPropulsion*)Models[ePropulsion];
555 
556  SuspendIntegration(); // saves the integration rate, dt, then sets it to 0.0.
557  Initialize(IC);
558 
559  Models[eInput]->InitModel();
560  Models[eOutput]->InitModel();
561 
562  Run();
563  Propagate->InitializeDerivatives();
564  ResumeIntegration(); // Restores the integration rate to what it was.
565 
566  if (debug_lvl > 0) {
567  MassBalance->GetMassPropertiesReport(0);
568 
569  cout << endl << fgblue << highint
570  << "End of vehicle configuration loading." << endl
571  << "-------------------------------------------------------------------------------"
572  << reset << std::setprecision(6) << endl;
573  }
574 
575  for (unsigned int n=0; n < propulsion->GetNumEngines(); ++n) {
576  if (IC->IsEngineRunning(n)) {
577  try {
578  propulsion->InitRunning(n);
579  } catch (const string& str) {
580  cerr << str << endl;
581  return false;
582  }
583  }
584  }
585 
586  return true;
587 }
588 
589 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
590 
592 {
593  Propagate->SetInitialState(FGIC);
594  Winds->SetWindNED(FGIC->GetWindNEDFpsIC());
595  Run();
596 }
597 
598 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
599 
601 {
602  if (Constructing) return;
603 
604  if (mode == 1) Output->SetStartNewOutput();
605 
606  for (unsigned int i = 0; i < Models.size(); i++) {
607  // The Input/Output models will be initialized during the RunIC() execution
608  if (i == eInput || i == eOutput) continue;
609 
610  LoadInputs(i);
611  Models[i]->InitModel();
612  }
613 
614  if (Script)
615  Script->ResetEvents();
616  else
617  Setsim_time(0.0);
618 
619  RunIC();
620 }
621 
622 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
623 
625 {
626  HoldDown = hd;
627  Accelerations->SetHoldDown(hd);
628  if (hd) {
629  Propagate->in.vPQRidot = Accelerations->GetPQRidot();
630  Propagate->in.vUVWidot = Accelerations->GetUVWidot();
631  }
632  Propagate->SetHoldDown(hd);
633 }
634 
635 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
636 
637 vector <string> FGFDMExec::EnumerateFDMs(void)
638 {
639  vector <string> FDMList;
640  FGAircraft* Aircraft = (FGAircraft*)Models[eAircraft];
641 
642  FDMList.push_back(Aircraft->GetAircraftName());
643 
644  for (unsigned int i=1; i<ChildFDMList.size(); i++) {
645  FDMList.push_back(ChildFDMList[i]->exec->GetAircraft()->GetAircraftName());
646  }
647 
648  return FDMList;
649 }
650 
651 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652 
653 bool FGFDMExec::LoadScript(const SGPath& script, double deltaT,
654  const SGPath& initfile)
655 {
656  bool result;
657 
658  Script = new FGScript(this);
659  result = Script->LoadScript(GetFullPath(script), deltaT, initfile);
660 
661  return result;
662 }
663 
664 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665 
666 bool FGFDMExec::LoadModel(const SGPath& AircraftPath, const SGPath& EnginePath,
667  const SGPath& SystemsPath, const string& model,
668  bool addModelToPath)
669 {
670  FGFDMExec::AircraftPath = GetFullPath(AircraftPath);
671  FGFDMExec::EnginePath = GetFullPath(EnginePath);
672  FGFDMExec::SystemsPath = GetFullPath(SystemsPath);
673 
674  return LoadModel(model, addModelToPath);
675 }
676 
677 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 
679 bool FGFDMExec::LoadModel(const string& model, bool addModelToPath)
680 {
681  SGPath aircraftCfgFileName;
682  bool result = false; // initialize result to false, indicating input file not yet read
683 
684  modelName = model; // Set the class modelName attribute
685 
686  if( AircraftPath.isNull() || EnginePath.isNull() || SystemsPath.isNull()) {
687  cerr << "Error: attempted to load aircraft with undefined ";
688  cerr << "aircraft, engine, and system paths" << endl;
689  return false;
690  }
691 
692  FullAircraftPath = AircraftPath;
693  if (addModelToPath) FullAircraftPath.append(model);
694  aircraftCfgFileName = FullAircraftPath/(model + ".xml");
695 
696  if (modelLoaded) {
697  DeAllocate();
698  Allocate();
699  }
700 
701  int saved_debug_lvl = debug_lvl;
702  FGXMLFileRead XMLFileRead;
703  Element *document = XMLFileRead.LoadXMLDocument(aircraftCfgFileName); // "document" is a class member
704 
705  if (document) {
706  if (IsChild) debug_lvl = 0;
707 
708  ReadPrologue(document);
709 
710  if (IsChild) debug_lvl = saved_debug_lvl;
711 
712  // Process the fileheader element in the aircraft config file. This element is OPTIONAL.
713  Element* element = document->FindElement("fileheader");
714  if (element) {
715  result = ReadFileHeader(element);
716  if (!result) {
717  cerr << endl << "Aircraft fileheader element has problems in file " << aircraftCfgFileName << endl;
718  return result;
719  }
720  }
721 
722  if (IsChild) debug_lvl = 0;
723 
724  // Process the metrics element. This element is REQUIRED.
725  element = document->FindElement("metrics");
726  if (element) {
727  result = ((FGAircraft*)Models[eAircraft])->Load(element);
728  if (!result) {
729  cerr << endl << "Aircraft metrics element has problems in file " << aircraftCfgFileName << endl;
730  return result;
731  }
732  } else {
733  cerr << endl << "No metrics element was found in the aircraft config file." << endl;
734  return false;
735  }
736 
737  // Process the mass_balance element. This element is REQUIRED.
738  element = document->FindElement("mass_balance");
739  if (element) {
740  result = ((FGMassBalance*)Models[eMassBalance])->Load(element);
741  if (!result) {
742  cerr << endl << "Aircraft mass_balance element has problems in file " << aircraftCfgFileName << endl;
743  return result;
744  }
745  } else {
746  cerr << endl << "No mass_balance element was found in the aircraft config file." << endl;
747  return false;
748  }
749 
750  // Process the ground_reactions element. This element is REQUIRED.
751  element = document->FindElement("ground_reactions");
752  if (element) {
753  result = ((FGGroundReactions*)Models[eGroundReactions])->Load(element);
754  if (!result) {
755  cerr << endl << element->ReadFrom()
756  << "Aircraft ground_reactions element has problems in file "
757  << aircraftCfgFileName << endl;
758  return result;
759  }
760  } else {
761  cerr << endl << "No ground_reactions element was found in the aircraft config file." << endl;
762  return false;
763  }
764 
765  // Process the external_reactions element. This element is OPTIONAL.
766  element = document->FindElement("external_reactions");
767  if (element) {
768  result = ((FGExternalReactions*)Models[eExternalReactions])->Load(element);
769  if (!result) {
770  cerr << endl << "Aircraft external_reactions element has problems in file " << aircraftCfgFileName << endl;
771  return result;
772  }
773  }
774 
775  // Process the buoyant_forces element. This element is OPTIONAL.
776  element = document->FindElement("buoyant_forces");
777  if (element) {
778  result = ((FGBuoyantForces*)Models[eBuoyantForces])->Load(element);
779  if (!result) {
780  cerr << endl << "Aircraft buoyant_forces element has problems in file " << aircraftCfgFileName << endl;
781  return result;
782  }
783  }
784 
785  // Process the propulsion element. This element is OPTIONAL.
786  element = document->FindElement("propulsion");
787  if (element) {
788  result = ((FGPropulsion*)Models[ePropulsion])->Load(element);
789  if (!result) {
790  cerr << endl << "Aircraft propulsion element has problems in file " << aircraftCfgFileName << endl;
791  return result;
792  }
793  for (unsigned int i=0; i<((FGPropulsion*)Models[ePropulsion])->GetNumEngines(); i++)
794  ((FGFCS*)Models[eSystems])->AddThrottle();
795  }
796 
797  // Process the system element[s]. This element is OPTIONAL, and there may be more than one.
798  element = document->FindElement("system");
799  while (element) {
800  result = ((FGFCS*)Models[eSystems])->Load(element);
801  if (!result) {
802  cerr << endl << "Aircraft system element has problems in file " << aircraftCfgFileName << endl;
803  return result;
804  }
805  element = document->FindNextElement("system");
806  }
807 
808  // Process the autopilot element. This element is OPTIONAL.
809  element = document->FindElement("autopilot");
810  if (element) {
811  result = ((FGFCS*)Models[eSystems])->Load(element);
812  if (!result) {
813  cerr << endl << "Aircraft autopilot element has problems in file " << aircraftCfgFileName << endl;
814  return result;
815  }
816  }
817 
818  // Process the flight_control element. This element is OPTIONAL.
819  element = document->FindElement("flight_control");
820  if (element) {
821  result = ((FGFCS*)Models[eSystems])->Load(element);
822  if (!result) {
823  cerr << endl << "Aircraft flight_control element has problems in file " << aircraftCfgFileName << endl;
824  return result;
825  }
826  }
827 
828  // Process the aerodynamics element. This element is OPTIONAL, but almost always expected.
829  element = document->FindElement("aerodynamics");
830  if (element) {
831  result = ((FGAerodynamics*)Models[eAerodynamics])->Load(element);
832  if (!result) {
833  cerr << endl << "Aircraft aerodynamics element has problems in file " << aircraftCfgFileName << endl;
834  return result;
835  }
836  } else {
837  cerr << endl << "No expected aerodynamics element was found in the aircraft config file." << endl;
838  }
839 
840  // Process the input element. This element is OPTIONAL, and there may be more than one.
841  element = document->FindElement("input");
842  while (element) {
843  if (!static_cast<FGInput*>(Models[eInput])->Load(element))
844  return false;
845 
846  element = document->FindNextElement("input");
847  }
848 
849  // Process the output element[s]. This element is OPTIONAL, and there may be
850  // more than one.
851  element = document->FindElement("output");
852  while (element) {
853  if (!static_cast<FGOutput*>(Models[eOutput])->Load(element))
854  return false;
855 
856  element = document->FindNextElement("output");
857  }
858 
859  // Lastly, process the child element. This element is OPTIONAL - and NOT YET SUPPORTED.
860  element = document->FindElement("child");
861  if (element) {
862  result = ReadChild(element);
863  if (!result) {
864  cerr << endl << "Aircraft child element has problems in file " << aircraftCfgFileName << endl;
865  return result;
866  }
867  }
868 
869  // Since all vehicle characteristics have been loaded, place the values in the Inputs
870  // structure for the FGModel-derived classes.
871  LoadModelConstants();
872 
873  modelLoaded = true;
874 
875  if (IsChild) debug_lvl = saved_debug_lvl;
876 
877  } else {
878  cerr << fgred
879  << " JSBSim failed to open the configuration file: " << aircraftCfgFileName
880  << fgdef << endl;
881  }
882 
883  for (unsigned int i=0; i< Models.size(); i++) LoadInputs(i);
884 
885  if (result) {
886  struct PropertyCatalogStructure masterPCS;
887  masterPCS.base_string = "";
888  masterPCS.node = Root->GetNode();
889  BuildPropertyCatalog(&masterPCS);
890  }
891 
892  return result;
893 }
894 
895 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
896 
897 string FGFDMExec::GetPropulsionTankReport()
898 {
899  return ((FGPropulsion*)Models[ePropulsion])->GetPropulsionTankReport();
900 }
901 
902 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903 
905 {
906  struct PropertyCatalogStructure* pcsNew = new struct PropertyCatalogStructure;
907 
908  for (int i=0; i<pcs->node->nChildren(); i++) {
909  string access="";
910  pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName();
911  int node_idx = pcs->node->getChild(i)->getIndex();
912  if (node_idx != 0) {
913  pcsNew->base_string = CreateIndexedPropertyName(pcsNew->base_string, node_idx);
914  }
915  if (pcs->node->getChild(i)->nChildren() == 0) {
916  if (pcsNew->base_string.substr(0,12) == string("/fdm/jsbsim/")) {
917  pcsNew->base_string = pcsNew->base_string.erase(0,12);
918  }
919  if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::READ)) access="R";
920  if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::WRITE)) access+="W";
921  PropertyCatalog.push_back(pcsNew->base_string+" ("+access+")");
922  } else {
923  pcsNew->node = (FGPropertyNode*)pcs->node->getChild(i);
924  BuildPropertyCatalog(pcsNew);
925  }
926  }
927  delete pcsNew;
928 }
929 
930 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
931 
932 string FGFDMExec::QueryPropertyCatalog(const string& in)
933 {
934  string results="";
935  for (unsigned i=0; i<PropertyCatalog.size(); i++) {
936  if (PropertyCatalog[i].find(in) != string::npos) results += PropertyCatalog[i] + "\n";
937  }
938  if (results.empty()) return "No matches found\n";
939  return results;
940 }
941 
942 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
943 
944 void FGFDMExec::PrintPropertyCatalog(void)
945 {
946  cout << endl;
947  cout << " " << fgblue << highint << underon << "Property Catalog for "
948  << modelName << reset << endl << endl;
949  for (unsigned i=0; i<PropertyCatalog.size(); i++) {
950  cout << " " << PropertyCatalog[i] << endl;
951  }
952 }
953 
954 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 
956 void FGFDMExec::PrintSimulationConfiguration(void) const
957 {
958  cout << endl << "Simulation Configuration" << endl << "------------------------" << endl;
959  cout << MassBalance->Name << endl;
960  cout << GroundReactions->Name << endl;
961  cout << Aerodynamics->Name << endl;
962  cout << Propulsion->Name << endl;
963 }
964 
965 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
966 
967 bool FGFDMExec::ReadFileHeader(Element* el)
968 {
969  bool result = true; // true for success
970 
971  if (debug_lvl == 0) return result;
972 
973  if (IsChild) {
974  cout << endl <<highint << fgblue << "Reading child model: " << IdFDM << reset << endl << endl;
975  }
976 
977  if (el->FindElement("description"))
978  cout << " Description: " << el->FindElement("description")->GetDataLine() << endl;
979  if (el->FindElement("author"))
980  cout << " Model Author: " << el->FindElement("author")->GetDataLine() << endl;
981  if (el->FindElement("filecreationdate"))
982  cout << " Creation Date: " << el->FindElement("filecreationdate")->GetDataLine() << endl;
983  if (el->FindElement("version"))
984  cout << " Version: " << el->FindElement("version")->GetDataLine() << endl;
985 
986  return result;
987 }
988 
989 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
990 
991 bool FGFDMExec::ReadPrologue(Element* el) // el for ReadPrologue is the document element
992 {
993  bool result = true; // true for success
994 
995  if (!el) return false;
996 
997  string AircraftName = el->GetAttributeValue("name");
998  ((FGAircraft*)Models[eAircraft])->SetAircraftName(AircraftName);
999 
1000  if (debug_lvl & 1) cout << underon << "Reading Aircraft Configuration File"
1001  << underoff << ": " << highint << AircraftName << normint << endl;
1002 
1003  CFGVersion = el->GetAttributeValue("version");
1004  Release = el->GetAttributeValue("release");
1005 
1006  if (debug_lvl & 1)
1007  cout << " Version: " << highint << CFGVersion
1008  << normint << endl;
1009  if (CFGVersion != needed_cfg_version) {
1010  cerr << endl << fgred << "YOU HAVE AN INCOMPATIBLE CFG FILE FOR THIS AIRCRAFT."
1011  " RESULTS WILL BE UNPREDICTABLE !!" << endl;
1012  cerr << "Current version needed is: " << needed_cfg_version << endl;
1013  cerr << " You have version: " << CFGVersion << endl << fgdef << endl;
1014  return false;
1015  }
1016 
1017  if (Release == "ALPHA" && (debug_lvl & 1)) {
1018  cout << endl << endl
1019  << highint << "This aircraft model is an " << fgred << Release
1020  << reset << highint << " release!!!" << endl << endl << reset
1021  << "This aircraft model may not even properly load, and probably"
1022  << " will not fly as expected." << endl << endl
1023  << fgred << highint << "Use this model for development purposes ONLY!!!"
1024  << normint << reset << endl << endl;
1025  } else if (Release == "BETA" && (debug_lvl & 1)) {
1026  cout << endl << endl
1027  << highint << "This aircraft model is a " << fgred << Release
1028  << reset << highint << " release!!!" << endl << endl << reset
1029  << "This aircraft model probably will not fly as expected." << endl << endl
1030  << fgblue << highint << "Use this model for development purposes ONLY!!!"
1031  << normint << reset << endl << endl;
1032  } else if (Release == "PRODUCTION" && (debug_lvl & 1)) {
1033  cout << endl << endl
1034  << highint << "This aircraft model is a " << fgblue << Release
1035  << reset << highint << " release." << endl << endl << reset;
1036  } else if (debug_lvl & 1) {
1037  cout << endl << endl
1038  << highint << "This aircraft model is an " << fgred << Release
1039  << reset << highint << " release!!!" << endl << endl << reset
1040  << "This aircraft model may not even properly load, and probably"
1041  << " will not fly as expected." << endl << endl
1042  << fgred << highint << "Use this model for development purposes ONLY!!!"
1043  << normint << reset << endl << endl;
1044  }
1045 
1046  return result;
1047 }
1048 
1049 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1050 
1051 bool FGFDMExec::ReadChild(Element* el)
1052 {
1053  // Add a new childData object to the child FDM list
1054  // Populate that childData element with a new FDMExec object
1055  // Set the IsChild flag for that FDMExec object
1056  // Get the aircraft name
1057  // set debug level to print out no additional data for child objects
1058  // Load the model given the aircraft name
1059  // reset debug level to prior setting
1060 
1061  struct childData* child = new childData;
1062 
1063  child->exec = new FGFDMExec(Root, FDMctr);
1064  child->exec->SetChild(true);
1065 
1066  string childAircraft = el->GetAttributeValue("name");
1067  string sMated = el->GetAttributeValue("mated");
1068  if (sMated == "false") child->mated = false; // child objects are mated by default.
1069  string sInternal = el->GetAttributeValue("internal");
1070  if (sInternal == "true") child->internal = true; // child objects are external by default.
1071 
1072  child->exec->SetAircraftPath( AircraftPath );
1073  child->exec->SetEnginePath( EnginePath );
1074  child->exec->SetSystemsPath( SystemsPath );
1075  child->exec->LoadModel(childAircraft);
1076 
1077  Element* location = el->FindElement("location");
1078  if (location) {
1079  child->Loc = location->FindElementTripletConvertTo("IN");
1080  } else {
1081  cerr << endl << highint << fgred << " No location was found for this child object!" << reset << endl;
1082  exit(-1);
1083  }
1084 
1085  Element* orientation = el->FindElement("orient");
1086  if (orientation) {
1087  child->Orient = orientation->FindElementTripletConvertTo("RAD");
1088  } else if (debug_lvl > 0) {
1089  cerr << endl << highint << " No orientation was found for this child object! Assuming 0,0,0." << reset << endl;
1090  }
1091 
1092  ChildFDMList.push_back(child);
1093 
1094  return true;
1095 }
1096 
1097 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1098 
1100 {
1101  return instance;
1102 }
1103 
1104 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1105 
1107 {
1108  delete Trim;
1109  Trim = new FGTrim(this,tNone);
1110  return Trim;
1111 }
1112 
1113 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114 
1116 {
1117  // Only check if increment then hold is on
1118  if( IncrementThenHolding ) {
1119 
1120  if (TimeStepsUntilHold == 0) {
1121 
1122  // Should hold simulation if TimeStepsUntilHold has reached zero
1123  holding = true;
1124 
1125  // Still need to decrement TimeStepsUntilHold as value of -1
1126  // indicates that incremental then hold is turned off
1127  IncrementThenHolding = false;
1128  TimeStepsUntilHold--;
1129 
1130  } else if ( TimeStepsUntilHold > 0 ) {
1131  // Keep decrementing until 0 is reached
1132  TimeStepsUntilHold--;
1133  }
1134  }
1135 }
1136 
1137 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1138 
1139 void FGFDMExec::DoTrim(int mode)
1140 {
1141  if (Constructing) return;
1142 
1143  if (mode < 0 || mode > JSBSim::tNone)
1144  throw("Illegal trimming mode!");
1145 
1146  FGTrim trim(this, (JSBSim::TrimMode)mode);
1147  bool success = trim.DoTrim();
1148  trim.Report();
1149 
1150  if (!success)
1151  throw("Trim Failed");
1152 
1153  trim_completed = 1;
1154 }
1155 
1156 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1157 
1158 void FGFDMExec::SRand(int sr)
1159 {
1160  RandomSeed = sr;
1161  gaussian_random_number_phase = 0;
1162  srand(RandomSeed);
1163 }
1164 
1165 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1166 // The bitmasked value choices are as follows:
1167 // unset: In this case (the default) JSBSim would only print
1168 // out the normally expected messages, essentially echoing
1169 // the config files as they are read. If the environment
1170 // variable is not set, debug_lvl is set to 1 internally
1171 // 0: This requests JSBSim not to output any messages
1172 // whatsoever.
1173 // 1: This value explicity requests the normal JSBSim
1174 // startup messages
1175 // 2: This value asks for a message to be printed out when
1176 // a class is instantiated
1177 // 4: When this value is set, a message is displayed when a
1178 // FGModel object executes its Run() method
1179 // 8: When this value is set, various runtime state variables
1180 // are printed out periodically
1181 // 16: When set various parameters are sanity checked and
1182 // a message is printed out when they go out of bounds
1183 
1184 void FGFDMExec::Debug(int from)
1185 {
1186  if (debug_lvl <= 0) return;
1187 
1188  if (debug_lvl & 1 && IdFDM == 0) { // Standard console startup message output
1189  if (from == 0) { // Constructor
1190  cout << "\n\n "
1191  << "JSBSim Flight Dynamics Model v" << JSBSim_version << endl;
1192  cout << " [JSBSim-ML v" << needed_cfg_version << "]\n\n";
1193  cout << "JSBSim startup beginning ...\n\n";
1194  if (disperse == 1) cout << "Dispersions are ON." << endl << endl;
1195  } else if (from == 3) {
1196  cout << "\n\nJSBSim startup complete\n\n";
1197  }
1198  }
1199  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
1200  if (from == 0) cout << "Instantiated: FGFDMExec" << endl;
1201  if (from == 1) cout << "Destroyed: FGFDMExec" << endl;
1202  }
1203  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
1204  if (from == 2) {
1205  cout << "================== Frame: " << Frame << " Time: "
1206  << sim_time << " dt: " << dT << endl;
1207  }
1208  }
1209  if (debug_lvl & 8 ) { // Runtime state variables
1210  }
1211  if (debug_lvl & 16) { // Sanity checking
1212  }
1213  if (debug_lvl & 64) {
1214  if (from == 0) { // Constructor
1215  cout << IdSrc << endl;
1216  cout << IdHdr << endl;
1217  }
1218  }
1219 }
1220 }
1221 
1222 
Encapsulates an Aircraft and its systems.
Definition: FGAircraft.h:110
FGColumnVector3 TerrainAngularVel
Terrain angular velocities with respect to the local frame (expressed in the ECEF frame)...
const FGMatrix33 & GetTw2b(void)
Calculates and returns the wind-to-body axis transformation matrix.
Definition: FGAuxiliary.h:198
const FGColumnVector3 & GetGasMassMoment(void)
Gets the total moment from the gas mass.
FGMatrix33 Jinv
The inverse of the inertia matrix J.
const FGMatrix33 & GetTec2b(void) const
Retrieves the ECEF-to-body transformation matrix.
Definition: FGPropagate.h:478
const FGColumnVector3 & GetBodyAccel(void) const
Retrieves the acceleration resulting from the applied forces.
Encapsulates the Buoyant forces calculations.
double GetCosEuler(int idx) const
Retrieves the cosine of a vehicle Euler angle component.
Definition: FGPropagate.h:406
bool LoadScript(const SGPath &Script, double deltaT=0.0, const SGPath &initfile=SGPath())
Loads a script.
Definition: FGFDMExec.cpp:653
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
const FGMatrix33 & GetTl2b(void) const
Retrieves the local-to-body transformation matrix.
Definition: FGPropagate.h:468
FGMatrix33 Ti2b
Transformation matrix from the ECI to the Body frame.
FGTrim * GetTrim(void)
Returns a pointer to the FGTrim object.
Definition: FGFDMExec.cpp:1106
FGColumnVector3 vPQRi
Angular velocities of the body with respect to the ECI frame (expressed in the body frame)...
std::vector< std::string > EnumerateFDMs(void)
Returns a vector of strings representing the names of all loaded models (future)
Definition: FGFDMExec.cpp:637
virtual const FGColumnVector3 & GetTotalWindNED(void) const
Retrieves the total wind components in NED frame.
Definition: FGWinds.h:140
void SuspendIntegration(void)
Suspends the simulation and sets the delta T to zero.
Definition: FGFDMExec.h:539
const FGColumnVector3 & GetPQRi(void) const
Retrieves the body angular rates vector, relative to the ECI (inertial) frame.
Definition: FGPropagate.h:232
bool RunIC(void)
Initializes the sim from the initial condition object and executes each scheduled model without integ...
Definition: FGFDMExec.cpp:552
virtual void SetWindNED(double wN, double wE, double wD)
Sets the wind components in NED frame.
Definition: FGWinds.h:148
FGColumnVector3 TerrainVelocity
Terrain velocities with respect to the local frame (expressed in the ECEF frame). ...
Class wrapper for property handling.
const std::string & GetAircraftName(void) const
Gets the aircraft name.
Definition: FGAircraft.h:139
static char reset[5]
resets text properties
Definition: FGJSBBase.h:131
Encapsulates the aerodynamic calculations.
std::vector< LagrangeMultiplier * > * MultipliersList
List of Lagrange multipliers set by FGLGear for friction forces calculations.
STL namespace.
FGColumnVector3 Force
Total forces applied to the body except friction and gravity (expressed in the body frame) ...
bool LoadScript(const SGPath &script, double default_dT, const SGPath &initfile)
Loads a script to drive JSBSim (usually in standalone mode).
Definition: FGScript.cpp:99
virtual double GetPressure(void) const
Returns the pressure in psf.
Definition: FGAtmosphere.h:152
Element * FindElement(const std::string &el="")
Searches for a specified element.
double GetThrottlePos(int engine) const
Gets the throttle position.
Definition: FGFCS.cpp:377
void DoTrim(int mode)
Executes trimming in the selected mode.
Definition: FGFDMExec.cpp:1139
double GetWingSpan(void) const
Gets the wing span.
Definition: FGAircraft.h:144
void SetGroundCallback(FGGroundCallback *gc)
Sets the ground callback pointer.
Definition: FGFDMExec.h:271
double GetAltitudeASL(void) const
Returns the current altitude above sea level.
Definition: FGPropagate.h:337
void SetHoldDown(bool hd)
Sets the property forces/hold-down.
Definition: FGFDMExec.cpp:624
double GetSinEuler(int idx) const
Retrieves the sine of a vehicle Euler angle component.
Definition: FGPropagate.h:418
const FGColumnVector3 & GetPQRidot(void) const
Retrieves the axis angular acceleration vector in the ECI frame.
double GetMixtureCmd(int engine) const
Gets the mixture command.
Definition: FGFCS.h:254
static char normint[6]
normal intensity text
Definition: FGJSBBase.h:129
Models inertial forces (e.g.
Definition: FGInertial.h:70
void Report(void)
Print the results of the trim.
Definition: FGTrim.cpp:117
const FGColumnVector3 & GetUVWdot(void) const
Retrieves the body axis acceleration.
std::string base_string
Name of the property.
Definition: FGFDMExec.h:498
FGColumnVector3 vOmegaPlanet
Earth rotating vector (expressed in the ECI frame).
void BuildPropertyCatalog(struct PropertyCatalogStructure *pcs)
Builds a catalog of properties.
Definition: FGFDMExec.cpp:904
FGPropertyManager * GetPropertyManager(void)
Returns a pointer to the property manager object.
Definition: FGFDMExec.cpp:1099
FGColumnVector3 vUVW
Velocities of the body with respect to the local frame (expressed in the body frame).
const FGColumnVector3 & GetvFw(void) const
Retrieves the aerodynamic forces in the wind axes.
const FGColumnVector3 & GetUVW(void) const
Retrieves the body frame vehicle velocity vector.
Definition: FGPropagate.h:204
double GetMixturePos(int engine) const
Gets the mixture position.
Definition: FGFCS.h:333
const FGColumnVector3 & GetPQR(void) const
Retrieves the body angular rates vector, relative to the ECEF frame.
Definition: FGPropagate.h:218
static char fgred[6]
red text
Definition: FGJSBBase.h:141
void Initialize(FGInitialCondition *FGIC)
Initializes the simulation with initial conditions.
Definition: FGFDMExec.cpp:591
void SetDebugLevel(int level)
Sets the debug level.
Definition: FGFDMExec.h:494
FGColumnVector3 vPQR
Angular velocities of the body with respect to the local frame (expressed in the body frame)...
FGColumnVector3 Moment
Total moments applied to the body except friction and gravity (expressed in the body frame) ...
double GetPropAdvance(int engine) const
Gets the prop pitch position.
Definition: FGFCS.h:352
Models atmospheric disturbances: winds, gusts, turbulence, downbursts, etc.
Definition: FGWinds.h:119
double Setsim_time(double cur_time)
Sets the current sim time.
Definition: FGFDMExec.h:551
virtual double GetPressureRatio(void) const
Returns the ratio of at-altitude pressure over the sea level value.
Definition: FGAtmosphere.h:161
FGColumnVector3 GroundForce
Forces generated by the ground normal reactions expressed in the body frame. Does not account for fri...
double GetThrottleCmd(int engine) const
Gets the throttle command.
Definition: FGFCS.cpp:359
int GetDebugLevel(void) const
Retrieves the current debug level setting.
Definition: FGFDMExec.h:585
Models the EOM and integration/propagation of state.
Definition: FGPropagate.h:102
bool GetPropFeather(int engine) const
Gets the prop feather position.
Definition: FGFCS.h:359
void Tie(const std::string &name, bool *pointer, bool useDefault=true)
Tie a property to an external bool variable.
const FGColumnVector3 & GetForces(void) const
Gets the total aerodynamic force vector.
const FGMatrix33 & GetTec2i(void) const
Retrieves the ECEF-to-ECI transformation matrix.
Definition: FGPropagate.h:494
const FGColumnVector3 & GetMoments(void) const
Retrieves the total moment resulting from the forces defined in the external reactions.
const FGMatrix33 & GetTb2i(void) const
Retrieves the body-to-ECI transformation matrix.
Definition: FGPropagate.h:490
const FGMatrix33 & GetGasMassInertia(void)
Gets the total moments of inertia for the gas mass in the body frame.
const FGColumnVector3 & GetForces(void) const
Retrieves the total forces defined in the external reactions.
static char fgdef[6]
default text
Definition: FGJSBBase.h:145
bool RunScript(void)
This function is called each pass through the executive Run() method IF scripting is enabled...
Definition: FGScript.cpp:366
Propulsion management class.
Definition: FGPropulsion.h:106
FGColumnVector3 vInertialPosition
Body position (X,Y,Z) measured in the ECI frame.
virtual double GetDensitySL(void) const
Returns the sea level density in slugs/ft^3.
Definition: FGAtmosphere.h:181
const FGColumnVector3 & GetUVWidot(void) const
Retrieves the body axis acceleration in the ECI frame.
Encapsulates the JSBSim scripting capability.
Definition: FGScript.h:172
virtual double GetSoundSpeed(void) const
Returns the speed of sound in ft/sec.
Definition: FGAtmosphere.h:191
const FGColumnVector3 & GetMoments(void) const
Gets the total Buoyancy moment vector.
virtual double GetWindPsi(void) const
Retrieves the direction that the wind is coming from.
Definition: FGWinds.h:165
double GAccel
Gravity intensity assuming the Earth is spherical.
const FGMatrix33 & GetTec2l(void) const
Retrieves the ECEF-to-local transformation matrix.
Definition: FGPropagate.h:504
double GetGasMass(void) const
Gets the total gas mass.
const FGMatrix33 & GetTb2l(void) const
Retrieves the body-to-local transformation matrix.
Definition: FGPropagate.h:474
const FGColumnVector3 & GetVel(void) const
Retrieves the velocity vector.
Definition: FGPropagate.h:192
const FGColumnVector3 & GetForces(void) const
Gets the total Buoyant force vector.
std::string GetDataLine(unsigned int i=0)
Gets a line of data belonging to an element.
static char underoff[6]
underline off
Definition: FGJSBBase.h:135
const FGColumnVector3 & GetEuler(void) const
Retrieves the Euler angles that define the vehicle orientation.
Definition: FGPropagate.h:260
FGPropertyNode_ptr node
The node for the property.
Definition: FGFDMExec.h:500
Handles simulation input.
Definition: FGInput.h:91
Models an empty, abstract base atmosphere class.
Definition: FGAtmosphere.h:84
virtual double GetDensity(void) const
Returns the density in slugs/ft^3.
Definition: FGAtmosphere.h:175
FGColumnVector3 J2Grav
Gravity intensity vector using WGS84 formulas (expressed in the ECEF frame).
FGMatrix33 Tec2i
Transformation matrix from the ECEF to the ECI frame.
void ResumeIntegration(void)
Resumes the simulation by resetting delta T to the correct value.
Definition: FGFDMExec.h:542
The trimming routine for JSBSim.
Definition: FGTrim.h:130
FGColumnVector3 GroundMoment
Moments generated by the ground normal reactions expressed in the body frame. Does not account for fr...
double Getcbar(void) const
Gets the average wing chord.
Definition: FGAircraft.h:146
const FGColumnVector3 & GetInertialPosition(void) const
Retrieves the inertial position vector.
Definition: FGPropagate.h:320
static char fgblue[6]
blue text
Definition: FGJSBBase.h:137
Initializes the simulation run.
Encapsulates the Flight Control System (FCS) functionality.
Definition: FGFCS.h:193
unsigned int GetRate(void)
Get the output rate for the model in frames.
Definition: FGModel.h:100
bool IntegrationSuspended(void) const
Returns the simulation suspension state.
Definition: FGFDMExec.h:546
std::string QueryPropertyCatalog(const std::string &check)
Retrieves property or properties matching the supplied string.
Definition: FGFDMExec.cpp:932
double GetSimTime(void) const
Returns the cumulative simulation time in seconds.
Definition: FGFDMExec.h:533
FGMatrix33 J
The body inertia matrix expressed in the body frame.
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
const FGColumnVector3 GetWindNEDFpsIC(void) const
Gets the initial wind velocity in the NED local frame.
Manages ground reactions modeling.
const FGMatrix33 & GetTb2w(void)
Calculates and returns the body-to-wind axis transformation matrix.
Definition: FGAuxiliary.h:203
void SetStartNewOutput(void)
Reset the output prior to a restart of the simulation.
Definition: FGOutput.cpp:128
Handles the calculation of accelerations.
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
static char highint[5]
highlights text
Definition: FGJSBBase.h:125
void InitRunning(int n)
Sets up the engines as running.
Encapsulates various uncategorized scheduled functions.
Definition: FGAuxiliary.h:109
FGFDMExec(FGPropertyManager *root=0, unsigned int *fdmctr=0)
Default constructor.
Definition: FGFDMExec.cpp:85
FGMatrix33 Tec2b
Transformation matrix from the ECEF to the Body frame.
bool IsEngineRunning(unsigned int n) const
Is an engine running ?
double Magnitude(void) const
Length of the vector.
double GetDeltaT(void) const
Returns the simulation delta T.
Definition: FGFDMExec.h:536
void CheckIncrementalHold(void)
Checks if required to hold afer increment.
Definition: FGFDMExec.cpp:1115
bool Run(void)
This function executes each scheduled model in succession.
Definition: FGFDMExec.cpp:310
double GetTotalPressure(void) const
Returns the total pressure.
Definition: FGAuxiliary.h:149
double GetVcalibratedKTS(void) const
Returns Calibrated airspeed in knots.
Definition: FGAuxiliary.h:135
void SetHoldDown(bool hd)
Sets the property forces/hold-down.
double GetGearPos(void) const
Gets the gear position (0 up, 1 down), defaults to down.
Definition: FGFCS.h:339
Encapsulates the JSBSim simulation executive.
Definition: FGFDMExec.h:189
FGMatrix33 Tb2i
Transformation matrix from the Body to the ECI frame.
Models weight, balance and moment of inertia information.
virtual double GetDensityRatio(void) const
Returns the ratio of at-altitude density over the sea level value.
Definition: FGAtmosphere.h:184
~FGFDMExec()
Default destructor.
Definition: FGFDMExec.cpp:184
double GetVground(void) const
Gets the ground speed in feet per second.
Definition: FGAuxiliary.h:217
bool LoadModel(const SGPath &AircraftPath, const SGPath &EnginePath, const SGPath &SystemsPath, const std::string &model, bool addModelToPath=true)
Loads an aircraft model.
Definition: FGFDMExec.cpp:666
void ResetToInitialConditions(int mode)
Resets the initial conditions object and prepares the simulation to run again.
Definition: FGFDMExec.cpp:600
FGColumnVector3 StructuralToBody(const FGColumnVector3 &r) const
Conversion from the structural frame to the body frame.
FGColumnVector3 FindElementTripletConvertTo(const std::string &target_units)
Composes a 3-element column vector for the supplied location or orientation.
static char underon[5]
underlines text
Definition: FGJSBBase.h:133
double GetVt(void) const
Gets the magnitude of total vehicle velocity including wind effects in feet per second.
Definition: FGAuxiliary.h:211
bool GetHoldDown(void) const
Gets the value of the property forces/hold-down.
Definition: FGFDMExec.h:600
const FGMatrix33 & GetTi2b(void) const
Retrieves the ECI-to-body transformation matrix.
Definition: FGPropagate.h:486
virtual double GetTemperature() const
Returns the actual, modeled temperature at the current altitude in degrees Rankine.
Definition: FGAtmosphere.h:117
void Unbind(void)
Unbind all tied JSBSim properties.
Definition: FGFDMExec.h:253
virtual double GetKinematicViscosity(void) const
Returns the kinematic viscosity.
Definition: FGAtmosphere.h:210
const FGColumnVector3 & GetMoments(void) const
Gets the total aerodynamic moment vector about the CG.
Manages the external and/or arbitrary forces.
void SetHoldDown(bool hd)
Sets the property forces/hold-down.
double GetWingArea(void) const
Gets the wing area.
Definition: FGAircraft.h:142
bool DoTrim(void)
Execute the trim.
Definition: FGTrim.cpp:190
Handles simulation output.
Definition: FGOutput.h:131
double IncrTime(void)
Increments the simulation time if not in Holding mode.
Definition: FGFDMExec.h:572
unsigned int GetNumEngines(void) const
Retrieves the number of engines defined for the aircraft.
Definition: FGPropulsion.h:134