]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGFDMExec.cpp
Latest JSBSim changes.
[flightgear.git] / src / FDM / JSBSim / FGFDMExec.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGFDMExec.cpp
4  Author:       Jon S. Berndt
5  Date started: 11/17/98
6  Purpose:      Schedules and runs the model routines.
7  Called by:    The GUI.
8
9  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
10
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU General Public License as published by the Free Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  version.
15
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19  details.
20
21  You should have received a copy of the GNU General Public License along with
22  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23  Place - Suite 330, Boston, MA  02111-1307, USA.
24
25  Further information about the GNU General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30
31 This class wraps up the simulation scheduling routines.
32
33 HISTORY
34 --------------------------------------------------------------------------------
35 11/17/98   JSB   Created
36
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 COMMENTS, REFERENCES,  and NOTES
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40
41 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 INCLUDES
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
44
45 #ifdef FGFS
46 #  include <simgear/compiler.h>
47 #  include STL_IOSTREAM
48 #  include STL_ITERATOR
49 #else
50 #  if defined(sgi) && !defined(__GNUC__)
51 #    include <iostream.h>
52 #  else
53 #    include <iostream>
54 #  endif
55 #  include <iterator>
56 #endif
57
58 #include "FGFDMExec.h"
59 #include "FGState.h"
60 #include "FGAtmosphere.h"
61 #include "FGFCS.h"
62 #include "FGPropulsion.h"
63 #include "FGMassBalance.h"
64 #include "FGGroundReactions.h"
65 #include "FGAerodynamics.h"
66 #include "FGInertial.h"
67 #include "FGAircraft.h"
68 #include "FGTranslation.h"
69 #include "FGRotation.h"
70 #include "FGPosition.h"
71 #include "FGAuxiliary.h"
72 #include "FGOutput.h"
73 #include "FGConfigFile.h"
74 #include "FGInitialCondition.h"
75
76 static const char *IdSrc = "$Id$";
77 static const char *IdHdr = ID_FDMEXEC;
78
79 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80 GLOBAL DECLARATIONS
81 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
82
83 short debug_lvl;  // This describes to any interested entity the debug level
84                   // requested by setting the JSBSIM_DEBUG environment variable.
85                   // The bitmasked value choices are as follows:
86                   // a) unset: In this case (the default) JSBSim would only print
87                   //    out the normally expected messages, essentially echoing
88                   //    the config files as they are read. If the environment
89                   //    variable is not set, debug_lvl is set to 1 internally
90                   // b) 0: This requests JSBSim not to output any messages
91                   //    whatsoever.
92                   // c) 1: This value explicity requests the normal JSBSim
93                   //    startup messages
94                   // d) 2: This value asks for a message to be printed out when
95                   //    a class is instantiated
96                   // e) 4: When this value is set, a message is displayed when a
97                   //    FGModel object executes its Run() method
98                   // f) 8: When this value is set, various runtime state variables
99                   //    are printed out periodically
100                   // g) 16: When set various parameters are sanity checked and
101                   //    a message is printed out when they go out of bounds.
102
103 unsigned int FGFDMExec::FDMctr = 0;
104
105 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 CLASS IMPLEMENTATION
107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
108
109 // Constructor
110
111 FGFDMExec::FGFDMExec(void)
112 {
113   Frame           = 0;
114   FirstModel      = 0;
115   Error           = 0;
116   State           = 0;
117   Atmosphere      = 0;
118   FCS             = 0;
119   Propulsion      = 0;
120   MassBalance     = 0;
121   Aerodynamics    = 0;
122   Inertial        = 0;
123   GroundReactions = 0;
124   Aircraft        = 0;
125   Translation     = 0;
126   Rotation        = 0;
127   Position        = 0;
128   Auxiliary       = 0;
129   Output          = 0;
130
131   terminate = false;
132   frozen = false;
133   modelLoaded = false;
134   Scripted = false;
135
136   IdFDM = FDMctr;
137   FDMctr++;
138
139   try {
140     char* num = getenv("JSBSIM_DEBUG");
141     if (!num) debug_lvl = 1;
142     else debug_lvl = atoi(num); // set debug level
143   } catch (...) {               // if error set to 1
144     debug_lvl = 1;
145   }
146
147   Debug(0);
148
149   Allocate();
150 }
151
152 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153
154 FGFDMExec::~FGFDMExec()
155 {
156   DeAllocate();
157
158   Debug(1);
159 }
160
161 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
162
163 bool FGFDMExec::Allocate(void)
164 {
165   bool result=true;
166
167   Atmosphere      = new FGAtmosphere(this);
168   FCS             = new FGFCS(this);
169   Propulsion      = new FGPropulsion(this);
170   MassBalance     = new FGMassBalance(this);
171   Aerodynamics    = new FGAerodynamics (this);
172   Inertial        = new FGInertial(this);
173   GroundReactions = new FGGroundReactions(this);
174   Aircraft        = new FGAircraft(this);
175   Translation     = new FGTranslation(this);
176   Rotation        = new FGRotation(this);
177   Position        = new FGPosition(this);
178   Auxiliary       = new FGAuxiliary(this);
179   Output          = new FGOutput(this);
180
181   State        = new FGState(this); // This must be done here, as the FGState
182                                     // class needs valid pointers to the above
183                                     // model classes
184   
185   // Initialize models so they can communicate with each other
186
187   if (!Atmosphere->InitModel()) {
188     cerr << fgred << "Atmosphere model init failed" << fgdef << endl;
189     Error+=1;}
190   if (!FCS->InitModel())        {
191     cerr << fgred << "FCS model init failed" << fgdef << endl;
192     Error+=2;}
193   if (!Propulsion->InitModel()) {
194     cerr << fgred << "FGPropulsion model init failed" << fgdef << endl;
195     Error+=4;}
196   if (!MassBalance->InitModel()) {
197     cerr << fgred << "FGMassBalance model init failed" << fgdef << endl;
198     Error+=8;}
199   if (!Aerodynamics->InitModel()) {
200     cerr << fgred << "FGAerodynamics model init failed" << fgdef << endl;
201     Error+=16;}
202   if (!Inertial->InitModel()) {
203     cerr << fgred << "FGInertial model init failed" << fgdef << endl;
204     Error+=32;}
205   if (!GroundReactions->InitModel())   {
206     cerr << fgred << "Ground Reactions model init failed" << fgdef << endl;
207     Error+=64;}
208   if (!Aircraft->InitModel())   {
209     cerr << fgred << "Aircraft model init failed" << fgdef << endl;
210     Error+=128;}
211   if (!Translation->InitModel()){
212     cerr << fgred << "Translation model init failed" << fgdef << endl;
213     Error+=256;}
214   if (!Rotation->InitModel())   {
215     cerr << fgred << "Rotation model init failed" << fgdef << endl;
216     Error+=512;}
217   if (!Position->InitModel())   {
218     cerr << fgred << "Position model init failed" << fgdef << endl;
219     Error+=1024;}
220   if (!Auxiliary->InitModel())  {
221     cerr << fgred << "Auxiliary model init failed" << fgdef << endl;
222     Error+=2058;}
223   if (!Output->InitModel())     {
224     cerr << fgred << "Output model init failed" << fgdef << endl;
225     Error+=4096;}
226
227   if (Error > 0) result = false;
228
229   // Schedule a model. The second arg (the integer) is the pass number. For
230   // instance, the atmosphere model gets executed every fifth pass it is called
231   // by the executive. Everything else here gets executed each pass.
232
233   Schedule(Atmosphere,      1);
234   Schedule(FCS,             1);
235   Schedule(Propulsion,      1);
236   Schedule(MassBalance,     1);
237   Schedule(Aerodynamics,    1);
238   Schedule(Inertial,        1);
239   Schedule(GroundReactions, 1);
240   Schedule(Aircraft,        1);
241   Schedule(Rotation,        1);
242   Schedule(Translation,     1);
243   Schedule(Position,        1);
244   Schedule(Auxiliary,       1);
245   Schedule(Output,          1);
246
247   modelLoaded = false;
248
249   return result;
250 }
251
252 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253
254 bool FGFDMExec::DeAllocate(void) {
255
256   if ( Atmosphere != 0 )     delete Atmosphere;
257   if ( FCS != 0 )            delete FCS;
258   if ( Propulsion != 0)      delete Propulsion;
259   if ( MassBalance != 0)     delete MassBalance;
260   if ( Aerodynamics != 0)    delete Aerodynamics;
261   if ( Inertial != 0)        delete Inertial;
262   if ( GroundReactions != 0) delete GroundReactions;
263   if ( Aircraft != 0 )       delete Aircraft;
264   if ( Translation != 0 )    delete Translation;
265   if ( Rotation != 0 )       delete Rotation;
266   if ( Position != 0 )       delete Position;
267   if ( Auxiliary != 0 )      delete Auxiliary;
268   if ( Output != 0 )         delete Output;
269   if ( State != 0 )          delete State;
270
271   FirstModel  = 0L;
272   Error       = 0;
273
274   State           = 0;
275   Atmosphere      = 0;
276   FCS             = 0;
277   Propulsion      = 0;
278   MassBalance     = 0;
279   Aerodynamics    = 0;
280   Inertial        = 0;
281   GroundReactions = 0;
282   Aircraft        = 0;
283   Translation     = 0;
284   Rotation        = 0;
285   Position        = 0;
286   Auxiliary       = 0;
287   Output          = 0;
288
289   modelLoaded = false;
290   return modelLoaded;
291 }
292
293 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294
295 int FGFDMExec::Schedule(FGModel* model, int rate)
296 {
297   FGModel* model_iterator;
298
299   model_iterator = FirstModel;
300
301   if (model_iterator == 0L) {                  // this is the first model
302
303     FirstModel = model;
304     FirstModel->NextModel = 0L;
305     FirstModel->SetRate(rate);
306
307   } else {                                     // subsequent model
308
309     while (model_iterator->NextModel != 0L) {
310       model_iterator = model_iterator->NextModel;
311     }
312     model_iterator->NextModel = model;
313     model_iterator->NextModel->SetRate(rate);
314
315   }
316   
317   return 0;
318 }
319
320 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321
322 bool FGFDMExec::Run(void)
323 {
324   FGModel* model_iterator;
325
326   if (frozen) return true;
327
328   model_iterator = FirstModel;
329   if (model_iterator == 0L) return false;
330
331   if (Scripted) {
332     RunScript();
333     if (State->Getsim_time() >= EndTime) return false;
334   }
335
336   Debug(2);
337
338   while (!model_iterator->Run()) {
339     model_iterator = model_iterator->NextModel;
340     if (model_iterator == 0L) break;
341   }
342
343   frame = Frame++;
344   State->IncrTime();
345
346   return true;
347 }
348
349 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350
351 bool FGFDMExec::RunIC(FGInitialCondition *fgic)
352 {
353   State->Suspend();
354   State->Initialize(fgic);
355   Run();
356   State->Resume();
357   return true;
358 }
359
360 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361
362 bool FGFDMExec::LoadModel(string APath, string EPath, string model)
363 {
364   bool result = false;
365
366   string aircraftCfgFileName;
367
368   AircraftPath = APath;
369   EnginePath   = EPath;
370
371 # ifndef macintosh
372   aircraftCfgFileName = AircraftPath + "/" + model + "/" + model + ".xml";
373 # else
374   aircraftCfgFileName = AircraftPath + ";" + model + ";" + model + ".xml";
375 # endif
376
377   FGConfigFile AC_cfg(aircraftCfgFileName);
378   if (!AC_cfg.IsOpen()) return false;
379
380   if (modelLoaded) {
381     DeAllocate();
382     Allocate();
383   }
384
385   result = Aircraft->Load(&AC_cfg);
386
387   if (result) {
388     modelLoaded = true;
389     Debug(3);
390   } else {
391     cerr << fgred
392          << "  FGFDMExec: Failed to load aircraft and/or engine model"
393          << fgdef << endl;
394   }
395
396   return result;
397 }
398
399 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400
401 bool FGFDMExec::LoadScript(string script)
402 {
403   FGConfigFile Script(script);
404   string token="";
405   string aircraft="";
406   string initialize="";
407   bool result = false;
408   double dt = 0.0;
409   unsigned i;
410   struct condition *newCondition;
411
412   if (!Script.IsOpen()) return false;
413
414   Script.GetNextConfigLine();
415   ScriptName = Script.GetValue("name");
416   Scripted = true;
417   if (debug_lvl > 0) cout << "Reading Script File " << ScriptName << endl;
418
419   while (Script.GetNextConfigLine() != string("EOF") && Script.GetValue() != string("/runscript")) {
420     token = Script.GetValue();
421     if (token == "use") {
422       if ((token = Script.GetValue("aircraft")) != string("")) {
423         aircraft = token;
424         if (debug_lvl > 0) cout << "  Use aircraft: " << token << endl;
425       } else if ((token = Script.GetValue("initialize")) != string("")) {
426         initialize = token;
427         if (debug_lvl > 0) cout << "  Use reset file: " << token << endl;
428       } else {
429         cerr << "Unknown 'use' keyword: \"" << token << "\"" << endl;
430       }
431     } else if (token == "run") {
432       StartTime = strtod(Script.GetValue("start").c_str(), NULL);
433       State->Setsim_time(StartTime);
434       EndTime   = strtod(Script.GetValue("end").c_str(), NULL);
435       dt        = strtod(Script.GetValue("dt").c_str(), NULL);
436       State->Setdt(dt);
437       Script.GetNextConfigLine();
438       token = Script.GetValue();
439       while (token != string("/run")) {
440
441         if (token == "when") {
442           Script.GetNextConfigLine();
443           token = Script.GetValue();
444           newCondition = new struct condition();
445           while (token != string("/when")) {
446             if (token == "parameter") {
447               newCondition->TestParam.push_back(State->GetParameterIndex(Script.GetValue("name")));
448               newCondition->TestValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));
449               newCondition->Comparison.push_back(Script.GetValue("comparison"));
450             } else if (token == "set") {
451               newCondition->SetParam.push_back(State->GetParameterIndex(Script.GetValue("name")));
452               newCondition->SetValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));
453               newCondition->Triggered.push_back(false);
454               newCondition->OriginalValue.push_back(0.0);
455               newCondition->newValue.push_back(0.0);
456               newCondition->StartTime.push_back(0.0);
457               newCondition->EndTime.push_back(0.0);
458               string tempCompare = Script.GetValue("type");
459               if      (tempCompare == "FG_DELTA") newCondition->Type.push_back(FG_DELTA);
460               else if (tempCompare == "FG_BOOL")  newCondition->Type.push_back(FG_BOOL);
461               else if (tempCompare == "FG_VALUE") newCondition->Type.push_back(FG_VALUE);
462               else                                newCondition->Type.push_back((eType)0);
463               tempCompare = Script.GetValue("action");
464               if      (tempCompare == "FG_RAMP") newCondition->Action.push_back(FG_RAMP);
465               else if (tempCompare == "FG_STEP") newCondition->Action.push_back(FG_STEP);
466               else if (tempCompare == "FG_EXP")  newCondition->Action.push_back(FG_EXP);
467               else                               newCondition->Action.push_back((eAction)0);
468               
469               if (Script.GetValue("persistent") == "true")
470                 newCondition->Persistent.push_back(true);
471               else
472                 newCondition->Persistent.push_back(false);
473                 
474               newCondition->TC.push_back(strtod(Script.GetValue("tc").c_str(), NULL));
475               
476             } else {
477               cerr << "Unrecognized keyword in script file: \" [when] " << token << "\"" << endl;
478             }
479             Script.GetNextConfigLine();
480             token = Script.GetValue();
481           }
482           Conditions.push_back(*newCondition);
483           Script.GetNextConfigLine();
484           token = Script.GetValue();
485
486         } else {
487           cerr << "Error reading script file: expected \"when\", got \"" << token << "\"" << endl;
488         }
489
490       }
491     } else if (token.empty()) {
492      // do nothing
493     } else {
494       cerr << "Unrecognized keyword in script file: \"" << token << "\" [runscript] " << endl;
495     }
496   }
497
498   if (aircraft == "") {
499     cerr << "Aircraft file not loaded in script" << endl;
500     exit(-1);
501   }
502
503   Debug(4);
504
505   result = LoadModel("aircraft", "engine", aircraft);
506   if (!result) {
507     cerr << "Aircraft file " << aircraft << " was not found" << endl;
508           exit(-1);
509   }
510
511   FGInitialCondition IC(this);
512   if ( ! IC.Load("aircraft", aircraft, initialize)) {
513     cerr << "Initialization unsuccessful" << endl;
514     exit(-1);
515   }
516
517   return true;
518 }
519
520 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
521
522 void FGFDMExec::RunScript(void)
523 {
524   vector <struct condition>::iterator iC = Conditions.begin();
525   bool truth = false;
526   bool WholeTruth = false;
527   unsigned i;
528
529   double currentTime = State->Getsim_time();
530   double newSetValue = 0;
531
532   while (iC < Conditions.end()) {
533     // determine whether the set of conditional tests for this condition equate
534     // to true
535     for (i=0; i<iC->TestValue.size(); i++) {
536            if (iC->Comparison[i] == "lt")
537               truth = State->GetParameter(iC->TestParam[i]) <  iC->TestValue[i];
538       else if (iC->Comparison[i] == "le")
539               truth = State->GetParameter(iC->TestParam[i]) <= iC->TestValue[i];
540       else if (iC->Comparison[i] == "eq")
541               truth = State->GetParameter(iC->TestParam[i]) == iC->TestValue[i];
542       else if (iC->Comparison[i] == "ge")
543               truth = State->GetParameter(iC->TestParam[i]) >= iC->TestValue[i];
544       else if (iC->Comparison[i] == "gt")
545               truth = State->GetParameter(iC->TestParam[i]) >  iC->TestValue[i];
546       else if (iC->Comparison[i] == "ne")
547               truth = State->GetParameter(iC->TestParam[i]) != iC->TestValue[i];
548       else
549               cerr << "Bad comparison" << endl;
550
551       if (i == 0) WholeTruth = truth;
552       else        WholeTruth = WholeTruth && truth;
553
554       if (!truth && iC->Persistent[i] && iC->Triggered[i]) iC->Triggered[i] = false;
555     }
556
557     // if the conditions are true, do the setting of the desired parameters
558
559     if (WholeTruth) {
560       for (i=0; i<iC->SetValue.size(); i++) {
561         if ( ! iC->Triggered[i]) {
562           iC->OriginalValue[i] = State->GetParameter(iC->SetParam[i]);
563           switch (iC->Type[i]) {
564           case FG_VALUE:
565             iC->newValue[i] = iC->SetValue[i];
566             break;
567           case FG_DELTA:
568             iC->newValue[i] = iC->OriginalValue[i] + iC->SetValue[i];
569             break;
570           case FG_BOOL:
571             iC->newValue[i] = iC->SetValue[i];
572             break;
573           default:
574             cerr << "Invalid Type specified" << endl;
575             break;
576           }
577           iC->Triggered[i] = true;
578           iC->StartTime[i] = currentTime;
579         }
580
581         switch (iC->Action[i]) {
582         case FG_RAMP:
583         newSetValue = (currentTime - iC->StartTime[i])/(iC->TC[i])
584                       * (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];
585           if (newSetValue > iC->newValue[i]) newSetValue = iC->newValue[i];
586           break;
587         case FG_STEP:
588           newSetValue = iC->newValue[i];
589           break;
590         case FG_EXP:
591           newSetValue = (1 - exp(-(currentTime - iC->StartTime[i])/(iC->TC[i])))
592               * (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];
593           break;
594         default:
595           cerr << "Invalid Action specified" << endl;
596           break;
597         }
598         State->SetParameter(iC->SetParam[i], newSetValue);
599       }
600     }
601     iC++;
602   }
603 }
604
605 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
606 //    The bitmasked value choices are as follows:
607 //    unset: In this case (the default) JSBSim would only print
608 //       out the normally expected messages, essentially echoing
609 //       the config files as they are read. If the environment
610 //       variable is not set, debug_lvl is set to 1 internally
611 //    0: This requests JSBSim not to output any messages
612 //       whatsoever.
613 //    1: This value explicity requests the normal JSBSim
614 //       startup messages
615 //    2: This value asks for a message to be printed out when
616 //       a class is instantiated
617 //    4: When this value is set, a message is displayed when a
618 //       FGModel object executes its Run() method
619 //    8: When this value is set, various runtime state variables
620 //       are printed out periodically
621 //    16: When set various parameters are sanity checked and
622 //       a message is printed out when they go out of bounds
623
624 void FGFDMExec::Debug(int from)
625 {
626   unsigned int i;
627
628   if (debug_lvl <= 0) return;
629
630   if (debug_lvl & 1) { // Standard console startup message output
631     if (from == 0) { // Constructor
632       cout << "\n\n     " << highint << underon << "JSBSim Flight Dynamics Model v"
633                                      << JSBSim_version << underoff << normint << endl;
634       cout << halfint << "            [cfg file spec v" << needed_cfg_version << "]\n\n";
635       cout << normint << "JSBSim startup beginning ...\n\n";
636     } else if (from == 3) {
637       cout << "\n\nJSBSim startup complete\n\n";
638     } else if (from == 4)  { // print out script data
639       vector <struct condition>::iterator iterConditions = Conditions.begin();
640       int count=0;
641
642       cout << "\n  Script goes from " << StartTime << " to " << EndTime
643            << " with dt = " << State->Getdt() << endl << endl;
644
645       while (iterConditions < Conditions.end()) {
646         cout << "  Condition: " << count++ << endl;
647         cout << "    if (";
648
649         for (i=0; i<iterConditions->TestValue.size(); i++) {
650           if (i>0) cout << " and" << endl << "        ";
651           cout << "(" << State->paramdef[iterConditions->TestParam[i]]
652                       << iterConditions->Comparison[i] << " "
653                       << iterConditions->TestValue[i] << ")";
654         }
655         cout << ") then {";
656
657         for (i=0; i<iterConditions->SetValue.size(); i++) {
658           cout << endl << "      set" << State->paramdef[iterConditions->SetParam[i]]
659                << "to " << iterConditions->SetValue[i];
660
661           switch (iterConditions->Type[i]) {
662           case FG_VALUE:
663             cout << " (constant";
664             break;
665           case FG_DELTA:
666             cout << " (delta";
667             break;
668           case FG_BOOL:
669             cout << " (boolean";
670             break;
671           default:
672             cout << " (unspecified type";
673           }
674
675           switch (iterConditions->Action[i]) {
676           case FG_RAMP:
677             cout << " via ramp";
678             break;
679           case FG_STEP:
680             cout << " via step";
681             break;
682           case FG_EXP:
683             cout << " via exponential approach";
684             break;
685           default:
686             cout << " via unspecified action";
687           }
688
689           if (!iterConditions->Persistent[i]) cout << endl
690                              << "                              once";
691           else cout << endl
692                              << "                              repeatedly";
693
694           if (iterConditions->Action[i] == FG_RAMP ||
695               iterConditions->Action[i] == FG_EXP) cout << endl
696                              << "                              with time constant "
697                              << iterConditions->TC[i];
698         }
699         cout << ")" << endl << "    }" << endl << endl;
700
701         iterConditions++;
702       }
703
704       cout << endl;
705     }
706   }
707   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
708     if (from == 0) cout << "Instantiated: FGFDMExec" << endl;
709     if (from == 1) cout << "Destroyed:    FGFDMExec" << endl;
710   }
711   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
712     if (from == 2) {
713       cout << "================== Frame: " << Frame << "  Time: "
714            << State->Getsim_time() << endl;
715     }
716   }
717   if (debug_lvl & 8 ) { // Runtime state variables
718   }
719   if (debug_lvl & 16) { // Sanity checking
720   }
721 }