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