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