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