1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2  Header:       FGFDMExec.h
3  Author:       Jon Berndt
4  Date started: 11/17/98
5  file The header file for the JSBSim executive.
6 
7  ------------- Copyright (C) 1999  Jon S. Berndt (jon@jsbsim.org) -------------
8 
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free
11  Software Foundation; either version 2 of the License, or (at your option) any
12  later version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
17  details.
18 
19  You should have received a copy of the GNU Lesser General Public License along
20  with this program; if not, write to the Free Software Foundation, Inc., 59
21  Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23  Further information about the GNU Lesser General Public License can also be
24  found on the world wide web at http://www.gnu.org.
25 
26 HISTORY
27 --------------------------------------------------------------------------------
28 11/17/98   JSB   Created
29 7/31/99     TP   Added RunIC function that runs the sim so that every frame
30                  begins with the IC values from the given FGInitialCondition
31                  object and dt=0.
32 
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 SENTRY
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
36 
37 #ifndef FGFDMEXEC_HEADER_H
38 #define FGFDMEXEC_HEADER_H
39 
40 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 INCLUDES
42 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
43 
44 #include "models/FGPropagate.h"
45 #include "models/FGOutput.h"
46 #include "math/FGTemplateFunc.h"
47 
48 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49 FORWARD DECLARATIONS
50 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
51 
52 namespace JSBSim {
53 
54 class FGScript;
55 class FGTrim;
56 class FGAerodynamics;
57 class FGAircraft;
58 class FGAtmosphere;
59 class FGAccelerations;
60 class FGWinds;
61 class FGAuxiliary;
62 class FGBuoyantForces;
63 class FGExternalReactions;
64 class FGGroundReactions;
65 class FGFCS;
66 class FGInertial;
67 class FGInput;
68 class FGPropulsion;
69 class FGMassBalance;
70 class FGTrim;
71 
72 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 CLASS DOCUMENTATION
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
75 
76 /** Encapsulates the JSBSim simulation executive.
77     This class is the executive class through which all other simulation classes
78     are instantiated, initialized, and run. When integrated with FlightGear (or
79     other flight simulator) this class is typically instantiated by an interface
80     class on the simulator side.
81 
82     At the time of simulation initialization, the interface
83     class creates an instance of this executive class. The
84     executive is subsequently directed to load the chosen aircraft specification
85     file:
86 
87     @code
88     fdmex = new FGFDMExec( ... );
89     result = fdmex->LoadModel( ... );
90     @endcode
91 
92     When an aircraft model is loaded, the config file is parsed and for each of
93     the sections of the config file (propulsion, flight control, etc.) the
94     corresponding Load() method is called (e.g. FGFCS::Load()).
95 
96     Subsequent to the creation of the executive and loading of the model,
97     initialization is performed. Initialization involves copying control inputs
98     into the appropriate JSBSim data storage locations, configuring it for the
99     set of user supplied initial conditions, and then copying state variables
100     from JSBSim. The state variables are used to drive the instrument displays
101     and to place the vehicle model in world space for visual rendering:
102 
103     @code
104     copy_to_JSBsim(); // copy control inputs to JSBSim
105     fdmex->RunIC(); // loop JSBSim once w/o integrating
106     copy_from_JSBsim(); // update the bus
107     @endcode
108 
109     Once initialization is complete, cyclic execution proceeds:
110 
111     @code
112     copy_to_JSBsim(); // copy control inputs to JSBSim
113     fdmex->Run(); // execute JSBSim
114     copy_from_JSBsim(); // update the bus
115     @endcode
116 
117     JSBSim can be used in a standalone mode by creating a compact stub program
118     that effectively performs the same progression of steps as outlined above
119     for the integrated version, but with two exceptions. First, the
120     copy_to_JSBSim() and copy_from_JSBSim() functions are not used because the
121     control inputs are handled directly by the scripting facilities and outputs
122     are handled by the output (data logging) class. Second, the name of a script
123     file can be supplied to the stub program. Scripting (see FGScript) provides
124     a way to supply command inputs to the simulation:
125 
126     @code
127     FDMExec = new JSBSim::FGFDMExec();
128     FDMExec->LoadScript( ScriptName ); // the script loads the aircraft and ICs
129     result = FDMExec->Run();
130     while (result) { // cyclic execution
131       result = FDMExec->Run(); // execute JSBSim
132     }
133     @endcode
134 
135     The standalone mode has been useful for verifying changes before committing
136     updates to the source code repository. It is also useful for running sets of
137     tests that reveal some aspects of simulated aircraft performance, such as
138     range, time-to-climb, takeoff distance, etc.
139 
140     <h3>JSBSim Debugging Directives</h3>
141 
142     This describes to any interested entity the debug level
143     requested by setting the JSBSIM_DEBUG environment variable.
144     The bitmasked value choices are as follows:
145     - <b>unset</b>: In this case (the default) JSBSim would only print
146        out the normally expected messages, essentially echoing
147        the config files as they are read. If the environment
148        variable is not set, debug_lvl is set to 1 internally
149     - <b>0</b>: This requests JSBSim not to output any messages
150        whatsoever
151     - <b>1</b>: This value explicity requests the normal JSBSim
152        startup messages
153     - <b>2</b>: This value asks for a message to be printed out when
154        a class is instantiated
155     - <b>4</b>: When this value is set, a message is displayed when a
156        FGModel object executes its Run() method
157     - <b>8</b>: When this value is set, various runtime state variables
158        are printed out periodically
159     - <b>16</b>: When set various parameters are sanity checked and
160        a message is printed out when they go out of bounds
161 
162     <h3>Properties</h3>
163     @property simulator/do_trim (write only) Can be set to the integer equivalent to one of
164                                 tLongitudinal (0), tFull (1), tGround (2), tPullup (3),
165                                 tCustom (4), tTurn (5). Setting this to a legal value
166                                 (such as by a script) causes a trim to be performed. This
167                                 property actually maps toa function call of DoTrim().
168 
169     @author Jon S. Berndt
170     @version $Revision: 1.106 $
171 */
172 
173 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 CLASS DECLARATION
175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
176 
177 class FGFDMExec : public FGJSBBase
178 {
179   struct childData {
180     FGFDMExec* exec;
181     std::string info;
182     FGColumnVector3 Loc;
183     FGColumnVector3 Orient;
184     bool mated;
185     bool internal;
186 
childDatachildData187     childData(void) {
188       info = "";
189       Loc = FGColumnVector3(0,0,0);
190       Orient = FGColumnVector3(0,0,0);
191       mated = true;
192       internal = false;
193     }
194 
RunchildData195     void Run(void) {exec->Run();}
AssignStatechildData196     void AssignState(FGPropagate* source_prop) {
197       exec->GetPropagate()->SetVState(source_prop->GetVState());
198     }
199 
~childDatachildData200     ~childData(void) {
201       delete exec;
202     }
203   };
204 
205 public:
206 
207   /// Default constructor
208   FGFDMExec(FGPropertyManager* root = 0, unsigned int* fdmctr = 0);
209 
210   /// Default destructor
211   ~FGFDMExec();
212 
213   // This list of enums is very important! The order in which models are listed
214   // here determines the order of execution of the models.
215   //
216   // There are some conditions that need to be met :
217   // 1. FCS can request mass geometry changes via the inertia/pointmass-*
218   //    properties so it must be executed before MassBalance
219   // 2. MassBalance must be executed before Propulsion, Aerodynamics,
220   //    GroundReactions, ExternalReactions and BuoyantForces to ensure that
221   //    their moments are computed with the updated CG position.
222   enum eModels { ePropagate=0,
223                  eInput,
224                  eInertial,
225                  eAtmosphere,
226                  eWinds,
227                  eSystems,
228                  eMassBalance,
229                  eAuxiliary,
230                  ePropulsion,
231                  eAerodynamics,
232                  eGroundReactions,
233                  eExternalReactions,
234                  eBuoyantForces,
235                  eAircraft,
236                  eAccelerations,
237                  eOutput,
238                  eNumStandardModels };
239 
240   /** Unbind all tied JSBSim properties. */
Unbind(void)241   void Unbind(void) {instance->Unbind();}
242 
243   /** This function executes each scheduled model in succession.
244       @return true if successful, false if sim should be ended  */
245   bool Run(void);
246 
247   /** Initializes the sim from the initial condition object and executes
248       each scheduled model without integrating i.e. dt=0.
249       @return true if successful */
250   bool RunIC(void);
251 
252   /** Sets the ground callback pointer. For optimal memory management, a shared
253       pointer is used internally that maintains a reference counter. The calling
254       application must therefore use FGGroundCallback_ptr 'smart pointers' to
255       manage their copy of the ground callback.
256       @param gc A pointer to a ground callback object
257       @see FGGroundCallback
258    */
SetGroundCallback(FGGroundCallback * gc)259   void SetGroundCallback(FGGroundCallback* gc) { FGLocation::SetGroundCallback(gc); }
260 
261   /** Loads an aircraft model.
262       @param AircraftPath path to the aircraft/ directory. For instance:
263       "aircraft". Under aircraft, then, would be directories for various
264       modeled aircraft such as C172/, x15/, etc.
265       @param EnginePath path to the directory under which engine config
266       files are kept, for instance "engine"
267       @param SystemsPath path to the directory under which systems config
268       files are kept, for instance "systems"
269       @param model the name of the aircraft model itself. This file will
270       be looked for in the directory specified in the AircraftPath variable,
271       and in turn under the directory with the same name as the model. For
272       instance: "aircraft/x15/x15.xml"
273       @param addModelToPath set to true to add the model name to the
274       AircraftPath, defaults to true
275       @return true if successful */
276   bool LoadModel(const SGPath& AircraftPath, const SGPath& EnginePath,
277                  const SGPath& SystemsPath, const std::string& model,
278                  bool addModelToPath = true);
279 
280   /** Loads an aircraft model.  The paths to the aircraft and engine
281       config file directories must be set prior to calling this.  See
282       below.
283       @param model the name of the aircraft model itself. This file will
284       be looked for in the directory specified in the AircraftPath variable,
285       and in turn under the directory with the same name as the model. For
286       instance: "aircraft/x15/x15.xml"
287       @param addModelToPath set to true to add the model name to the
288       AircraftPath, defaults to true
289       @return true if successful*/
290   bool LoadModel(const std::string& model, bool addModelToPath = true);
291 
292   /** Loads a script
293       @param Script The full path name and file name for the script to be loaded.
294       @param deltaT The simulation integration step size, if given.  If no value is supplied
295                     then 0.0 is used and the value is expected to be supplied in
296                     the script file itself.
297       @param initfile The initialization file that will override the initialization file
298                       specified in the script file. If no file name is given on the command line,
299                       the file specified in the script will be used. If an initialization file
300                       is not given in either place, an error will result.
301       @return true if successfully loads; false otherwise. */
302   bool LoadScript(const SGPath& Script, double deltaT=0.0,
303                   const SGPath& initfile=SGPath());
304 
305   /** Sets the path to the engine config file directories.
306       @param path path to the directory under which engine config
307       files are kept, for instance "engine"  */
SetEnginePath(const SGPath & path)308   bool SetEnginePath(const SGPath& path) {
309     EnginePath = GetFullPath(path);
310     return true;
311   }
312 
313   /** Sets the path to the aircraft config file directories.
314       @param path path to the aircraft directory. For instance:
315       "aircraft". Under aircraft, then, would be directories for various
316       modeled aircraft such as C172/, x15/, etc.  */
SetAircraftPath(const SGPath & path)317   bool SetAircraftPath(const SGPath& path) {
318     AircraftPath = GetFullPath(path);
319     return true;
320   }
321 
322   /** Sets the path to the systems config file directories.
323       @param path path to the directory under which systems config
324       files are kept, for instance "systems"  */
SetSystemsPath(const SGPath & path)325   bool SetSystemsPath(const SGPath& path) {
326     SystemsPath = GetFullPath(path);
327     return true;
328   }
329 
330   /// @name Top-level executive State and Model retrieval mechanism
331   ///@{
332   /// Returns the FGAtmosphere pointer.
GetAtmosphere(void)333   FGAtmosphere* GetAtmosphere(void)    {return (FGAtmosphere*)Models[eAtmosphere];}
334   /// Returns the FGAccelerations pointer.
GetAccelerations(void)335   FGAccelerations* GetAccelerations(void)    {return (FGAccelerations*)Models[eAccelerations];}
336   /// Returns the FGWinds pointer.
GetWinds(void)337   FGWinds* GetWinds(void)    {return (FGWinds*)Models[eWinds];}
338   /// Returns the FGFCS pointer.
GetFCS(void)339   FGFCS* GetFCS(void)                  {return (FGFCS*)Models[eSystems];}
340   /// Returns the FGPropulsion pointer.
GetPropulsion(void)341   FGPropulsion* GetPropulsion(void)    {return (FGPropulsion*)Models[ePropulsion];}
342   /// Returns the FGAircraft pointer.
GetMassBalance(void)343   FGMassBalance* GetMassBalance(void)  {return (FGMassBalance*)Models[eMassBalance];}
344   /// Returns the FGAerodynamics pointer
GetAerodynamics(void)345   FGAerodynamics* GetAerodynamics(void){return (FGAerodynamics*)Models[eAerodynamics];}
346   /// Returns the FGInertial pointer.
GetInertial(void)347   FGInertial* GetInertial(void)        {return (FGInertial*)Models[eInertial];}
348   /// Returns the FGGroundReactions pointer.
GetGroundReactions(void)349   FGGroundReactions* GetGroundReactions(void) {return (FGGroundReactions*)Models[eGroundReactions];}
350   /// Returns the FGExternalReactions pointer.
GetExternalReactions(void)351   FGExternalReactions* GetExternalReactions(void) {return (FGExternalReactions*)Models[eExternalReactions];}
352   /// Returns the FGBuoyantForces pointer.
GetBuoyantForces(void)353   FGBuoyantForces* GetBuoyantForces(void) {return (FGBuoyantForces*)Models[eBuoyantForces];}
354   /// Returns the FGAircraft pointer.
GetAircraft(void)355   FGAircraft* GetAircraft(void)        {return (FGAircraft*)Models[eAircraft];}
356   /// Returns the FGPropagate pointer.
GetPropagate(void)357   FGPropagate* GetPropagate(void)      {return (FGPropagate*)Models[ePropagate];}
358   /// Returns the FGAuxiliary pointer.
GetAuxiliary(void)359   FGAuxiliary* GetAuxiliary(void)      {return (FGAuxiliary*)Models[eAuxiliary];}
360   /// Returns the FGInput pointer.
GetInput(void)361   FGInput* GetInput(void)              {return (FGInput*)Models[eInput];}
362   /// Returns the FGOutput pointer.
GetOutput(void)363   FGOutput* GetOutput(void)            {return (FGOutput*)Models[eOutput];}
364   /** Get a pointer to the ground callback currently used. It is recommanded
365       to store the returned pointer in a 'smart pointer' FGGroundCallback_ptr.
366       @return A pointer to the current ground callback object.
367       @see FGGroundCallback
368    */
GetGroundCallback(void)369   FGGroundCallback* GetGroundCallback(void) {return FGLocation::GetGroundCallback();}
370   /// Retrieves the script object
GetScript(void)371   FGScript* GetScript(void) {return Script;}
372   /// Returns a pointer to the FGInitialCondition object
GetIC(void)373   FGInitialCondition* GetIC(void)      {return IC;}
374   /// Returns a pointer to the FGTrim object
375   FGTrim* GetTrim(void);
376   ///@}
377 
378   /// Retrieves the engine path.
GetEnginePath(void)379   const SGPath& GetEnginePath(void)    {return EnginePath;}
380   /// Retrieves the aircraft path.
GetAircraftPath(void)381   const SGPath& GetAircraftPath(void)  {return AircraftPath;}
382   /// Retrieves the systems path.
GetSystemsPath(void)383   const SGPath& GetSystemsPath(void)   {return SystemsPath;}
384   /// Retrieves the full aircraft path name.
GetFullAircraftPath(void)385   const SGPath& GetFullAircraftPath(void) {return FullAircraftPath;}
386 
387   /** Retrieves the value of a property.
388       @param property the name of the property
389       @result the value of the specified property */
GetPropertyValue(const std::string & property)390   inline double GetPropertyValue(const std::string& property)
391   { return instance->GetNode()->GetDouble(property); }
392 
393   /** Sets a property value.
394       @param property the property to be set
395       @param value the value to set the property to */
SetPropertyValue(const std::string & property,double value)396   inline void SetPropertyValue(const std::string& property, double value) {
397     instance->GetNode()->SetDouble(property, value);
398   }
399 
400   /// Returns the model name.
GetModelName(void)401   const std::string& GetModelName(void) const { return modelName; }
402 
403   /// Returns a pointer to the property manager object.
404   FGPropertyManager* GetPropertyManager(void);
405   /// Returns a vector of strings representing the names of all loaded models (future)
406   std::vector <std::string> EnumerateFDMs(void);
407   /// Gets the number of child FDMs.
GetFDMCount(void)408   int GetFDMCount(void) const {return (int)ChildFDMList.size();}
409   /// Gets a particular child FDM.
GetChildFDM(int i)410   childData* GetChildFDM(int i) const {return ChildFDMList[i];}
411   /// Marks this instance of the Exec object as a "child" object.
SetChild(bool ch)412   void SetChild(bool ch) {IsChild = ch;}
413 
414   /** Sets the output (logging) mechanism for this run.
415       Calling this function passes the name of an output directives file to
416       the FGOutput object associated with this run. The call to this function
417       should be made prior to loading an aircraft model. This call results in an
418       FGOutput object being built as the first Output object in the FDMExec-managed
419       list of Output objects that may be created for an aircraft model. If this call
420       is made after an aircraft model is loaded, there is no effect. Any Output
421       objects added by the aircraft model itself (in an &lt;output> element) will be
422       added after this one. Care should be taken not to refer to the same file
423       name.
424       An output directives file contains an &lt;output> &lt;/output> element, within
425       which should be specified the parameters or parameter groups that should
426       be logged.
427       @param fname the filename of an output directives file.
428     */
SetOutputDirectives(const SGPath & fname)429   bool SetOutputDirectives(const SGPath& fname)
430   { return Output->SetDirectivesFile(GetFullPath(fname)); }
431 
432   /** Forces the specified output object to print its items once */
433   void ForceOutput(int idx=0) { Output->ForceOutput(idx); }
434 
435   /** Sets the logging rate in Hz for all output objects (if any). */
SetLoggingRate(double rate)436   void SetLoggingRate(double rate) { Output->SetRateHz(rate); }
437 
438   /** Sets (or overrides) the output filename
439       @param n index of file
440       @param fname the name of the file to output data to
441       @return true if successful, false if there is no output specified for the flight model */
SetOutputFileName(const int n,const std::string & fname)442   bool SetOutputFileName(const int n, const std::string& fname) { return Output->SetOutputName(n, fname); }
443 
444   /** Retrieves the current output filename.
445       @param n index of file
446       @return the name of the output file for the output specified by the flight model.
447               If none is specified, the empty string is returned. */
GetOutputFileName(int n)448   std::string GetOutputFileName(int n) const { return Output->GetOutputName(n); }
449 
450   /** Executes trimming in the selected mode.
451   *   @param mode Specifies how to trim:
452   * - tLongitudinal=0
453   * - tFull
454   * - tGround
455   * - tPullup
456   * - tCustom
457   * - tTurn
458   * - tNone  */
459   void DoTrim(int mode);
460 
461   /// Disables data logging to all outputs.
DisableOutput(void)462   void DisableOutput(void) { Output->Disable(); }
463   /// Enables data logging to all outputs.
EnableOutput(void)464   void EnableOutput(void) { Output->Enable(); }
465   /// Pauses execution by preventing time from incrementing.
Hold(void)466   void Hold(void) {holding = true;}
467   /// Turn on hold after increment
EnableIncrementThenHold(int Timesteps)468   void EnableIncrementThenHold(int Timesteps) {TimeStepsUntilHold = Timesteps; IncrementThenHolding = true;}
469   /// Checks if required to hold afer increment
470   void CheckIncrementalHold(void);
471   /// Resumes execution from a "Hold".
Resume(void)472   void Resume(void) {holding = false;}
473   /// Returns true if the simulation is Holding (i.e. simulation time is not moving).
Holding(void)474   bool Holding(void) {return holding;}
475   /** Resets the initial conditions object and prepares the simulation to run
476       again. If mode is set to 1 the output instances will take special actions
477       such as closing the current output file and open a new one with a
478       different name.
479       @param mode Sets the reset mode.*/
480   void ResetToInitialConditions(int mode);
481   /// Sets the debug level.
SetDebugLevel(int level)482   void SetDebugLevel(int level) {debug_lvl = level;}
483 
484   struct PropertyCatalogStructure {
485     /// Name of the property.
486     std::string base_string;
487     /// The node for the property.
488     FGPropertyNode_ptr node;
489   };
490 
491   /** Builds a catalog of properties.
492   *   This function descends the property tree and creates a list (an STL vector)
493   *   containing the name and node for all properties.
494   *   @param pcs The "root" property catalog structure pointer.  */
495   void BuildPropertyCatalog(struct PropertyCatalogStructure* pcs);
496 
497   /** Retrieves property or properties matching the supplied string.
498   *   A string is returned that contains a carriage return delimited list of all
499   *   strings in the property catalog that matches the supplied check string.
500   *   @param check The string to search for in the property catalog.
501   *   @return the carriage-return-delimited string containing all matching strings
502   *               in the catalog.  */
503   std::string QueryPropertyCatalog(const std::string& check);
504 
505   // Print the contents of the property catalog for the loaded aircraft.
506   void PrintPropertyCatalog(void);
507 
508   // Print the simulation configuration
509   void PrintSimulationConfiguration(void) const;
510 
GetPropertyCatalog(void)511   std::vector<std::string>& GetPropertyCatalog(void) {return PropertyCatalog;}
512 
SetTrimStatus(bool status)513   void SetTrimStatus(bool status){ trim_status = status; }
GetTrimStatus(void)514   bool GetTrimStatus(void) const { return trim_status; }
SetTrimMode(int mode)515   void SetTrimMode(int mode){ ta_mode = mode; }
GetTrimMode(void)516   int GetTrimMode(void) const { return ta_mode; }
517 
518   std::string GetPropulsionTankReport();
519 
520   /// Returns the cumulative simulation time in seconds.
GetSimTime(void)521   double GetSimTime(void) const { return sim_time; }
522 
523   /// Returns the simulation delta T.
GetDeltaT(void)524   double GetDeltaT(void) const {return dT;}
525 
526   /// Suspends the simulation and sets the delta T to zero.
SuspendIntegration(void)527   void SuspendIntegration(void) {saved_dT = dT; dT = 0.0;}
528 
529   /// Resumes the simulation by resetting delta T to the correct value.
ResumeIntegration(void)530   void ResumeIntegration(void)  {dT = saved_dT;}
531 
532   /** Returns the simulation suspension state.
533       @return true if suspended, false if executing  */
IntegrationSuspended(void)534   bool IntegrationSuspended(void) const {return dT == 0.0;}
535 
536   /** Sets the current sim time.
537       @param cur_time the current time
538       @return the current simulation time.      */
Setsim_time(double cur_time)539   double Setsim_time(double cur_time) {
540     sim_time = cur_time;
541     GetGroundCallback()->SetTime(sim_time);
542     return sim_time;
543   }
544 
545   /** Sets the integration time step for the simulation executive.
546       @param delta_t the time step in seconds.     */
Setdt(double delta_t)547   void Setdt(double delta_t) { dT = delta_t; }
548 
549   /** Sets the root directory where JSBSim starts looking for its system directories.
550       @param rootDir the string containing the root directory. */
SetRootDir(const SGPath & rootDir)551   void SetRootDir(const SGPath& rootDir) {RootDir = rootDir;}
552 
553   /** Retrieves the Root Directory.
554       @return the string representing the root (base) JSBSim directory. */
GetRootDir(void)555   const SGPath& GetRootDir(void) const {return RootDir;}
556 
557   /** Increments the simulation time if not in Holding mode. The Frame counter
558       is also incremented.
559       @return the new simulation time.     */
IncrTime(void)560   double IncrTime(void) {
561     if (!holding && !IntegrationSuspended()) {
562       sim_time += dT;
563       GetGroundCallback()->SetTime(sim_time);
564       Frame++;
565     }
566     return sim_time;
567   }
568 
569   /** Retrieves the current frame count. */
GetFrame(void)570   unsigned int GetFrame(void) const {return Frame;}
571 
572   /** Retrieves the current debug level setting. */
GetDebugLevel(void)573   int GetDebugLevel(void) const {return debug_lvl;};
574 
575   /** Initializes the simulation with initial conditions
576       @param FGIC The initial conditions that will be passed to the simulation. */
577   void Initialize(FGInitialCondition *FGIC);
578 
579   /** Sets the property forces/hold-down. This allows to do hard 'hold-down'
580       such as for rockets on a launch pad with engines ignited.
581       @param hd enables the 'hold-down' function if non-zero
582   */
583   void SetHoldDown(bool hd);
584 
585   /** Gets the value of the property forces/hold-down.
586       @result zero if the 'hold-down' function is disabled, non-zero otherwise.
587   */
GetHoldDown(void)588   bool GetHoldDown(void) const {return HoldDown;}
589 
GetTemplateFunc(const std::string & name)590   FGTemplateFunc* GetTemplateFunc(const std::string& name) {
591     return TemplateFunctions.count(name) ? TemplateFunctions[name] : nullptr;
592   }
593 
AddTemplateFunc(const std::string & name,Element * el)594   void AddTemplateFunc(const std::string& name, Element* el) {
595     TemplateFunctions[name] = new FGTemplateFunc(this, el);
596   }
597 
598 private:
599   unsigned int Frame;
600   unsigned int IdFDM;
601   int disperse;
602   unsigned short Terminate;
603   double dT;
604   double saved_dT;
605   double sim_time;
606   bool holding;
607   bool IncrementThenHolding;
608   int TimeStepsUntilHold;
609   int RandomSeed;
610   bool Constructing;
611   bool modelLoaded;
612   bool IsChild;
613   std::string modelName;
614   SGPath AircraftPath;
615   SGPath FullAircraftPath;
616   SGPath EnginePath;
617   SGPath SystemsPath;
618   std::string CFGVersion;
619   std::string Release;
620   SGPath RootDir;
621 
622   // Standard Model pointers - shortcuts for internal executive use only.
623   FGPropagate* Propagate;
624   FGInertial* Inertial;
625   FGAtmosphere* Atmosphere;
626   FGWinds* Winds;
627   FGAuxiliary* Auxiliary;
628   FGFCS* FCS;
629   FGPropulsion* Propulsion;
630   FGAerodynamics* Aerodynamics;
631   FGGroundReactions* GroundReactions;
632   FGExternalReactions* ExternalReactions;
633   FGBuoyantForces* BuoyantForces;
634   FGMassBalance* MassBalance;
635   FGAircraft* Aircraft;
636   FGAccelerations* Accelerations;
637   FGOutput* Output;
638 
639   bool trim_status;
640   int ta_mode;
641   unsigned int ResetMode;
642   int trim_completed;
643 
644   FGScript*           Script;
645   FGInitialCondition* IC;
646   FGTrim*             Trim;
647 
648   FGPropertyManager* Root;
649   bool StandAlone;
650   FGPropertyManager* instance;
651 
652   bool HoldDown;
653 
654   // The FDM counter is used to give each child FDM an unique ID. The root FDM
655   // has the ID 0
656   unsigned int*      FDMctr;
657 
658   std::vector <std::string> PropertyCatalog;
659   std::vector <childData*> ChildFDMList;
660   std::vector <FGModel*> Models;
661   std::map<std::string, FGTemplateFunc_ptr> TemplateFunctions;
662 
663   bool ReadFileHeader(Element*);
664   bool ReadChild(Element*);
665   bool ReadPrologue(Element*);
666   void SRand(int sr);
SRand(void)667   int  SRand(void) const {return RandomSeed;}
668   void LoadInputs(unsigned int idx);
669   void LoadPlanetConstants(void);
670   void LoadModelConstants(void);
671   bool Allocate(void);
672   bool DeAllocate(void);
GetDisperse(void)673   int GetDisperse(void) const {return disperse;}
GetFullPath(const SGPath & name)674   SGPath GetFullPath(const SGPath& name) {
675     if (name.isRelative())
676       return RootDir/name.utf8Str();
677     else
678       return name;
679   }
680 
681   void Debug(int from);
682 };
683 }
684 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
685 #endif
686