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