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