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