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