]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGScript.cpp
Fix stall widths for the "auxilliary" (reverse flow) stalls so they
[flightgear.git] / src / FDM / JSBSim / FGScript.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGScript.cpp
4  Author:       Jon S. Berndt
5  Date started: 12/21/01
6  Purpose:      Loads and runs JSBSim scripts.
7
8  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
9
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  details.
19
20  You should have received a copy of the GNU General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23
24  Further information about the GNU General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 FUNCTIONAL DESCRIPTION
28 --------------------------------------------------------------------------------
29
30 This class wraps up the simulation scripting routines.
31
32 HISTORY
33 --------------------------------------------------------------------------------
34 12/21/01   JSB   Created
35
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 COMMENTS, REFERENCES,  and NOTES
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 INCLUDES
42 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
43
44 #ifdef FGFS
45 #  include <simgear/compiler.h>
46 #  include STL_IOSTREAM
47 #  include STL_ITERATOR
48 #else
49 #  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
50 #    include <iostream.h>
51 #  else
52 #    include <iostream>
53 #  endif
54 #  include <iterator>
55 #endif
56
57 #include "FGScript.h"
58 #include "FGConfigFile.h"
59 #include "FGTrim.h"
60
61 namespace JSBSim {
62
63 static const char *IdSrc = "$Id$";
64 static const char *IdHdr = ID_FGSCRIPT;
65
66 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67 GLOBAL DECLARATIONS
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
69
70 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 CLASS IMPLEMENTATION
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
73
74 // Constructor
75
76 FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
77 {
78   State = FDMExec->GetState();
79   PropertyManager=FDMExec->GetPropertyManager();
80   Debug(0);
81 }
82
83 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84
85 FGScript::~FGScript()
86 {
87   Debug(1);
88 }
89
90 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91
92 bool FGScript::LoadScript( string script )
93 {
94   FGConfigFile Script(script);
95   string token="";
96   string aircraft="";
97   string initialize="";
98   string prop_name;
99   bool result = false;
100   double dt = 0.0;
101   struct condition *newCondition;
102
103   if (!Script.IsOpen()) return false;
104
105   Script.GetNextConfigLine();
106   if (Script.GetValue("runscript").length() <= 0) {
107     cerr << "File: " << script << " is not a script file" << endl;
108     delete FDMExec;
109     return false;
110   }
111   ScriptName = Script.GetValue("name");
112   Scripted = true;
113
114   if (debug_lvl > 0) cout << "Reading and running from script file " << ScriptName << endl << endl;
115
116   while (Script.GetNextConfigLine() != string("EOF") && Script.GetValue() != string("/runscript")) {
117     token = Script.GetValue();
118     if (token == "use") {
119       if ((token = Script.GetValue("aircraft")) != string("")) {
120         aircraft = token;
121         result = FDMExec->LoadModel(aircraft);
122         if (!result) {
123           cerr << "Aircraft file " << aircraft << " was not found" << endl;
124           exit(-1);
125         }
126         if (debug_lvl > 0) cout << "  Use aircraft: " << token << endl;
127       } else if ((token = Script.GetValue("initialize")) != string("")) {
128         initialize = token;
129         if (debug_lvl > 0) cout << "  Use reset file: " << token << endl;
130       } else {
131         cerr << "Unknown 'use' keyword: \"" << token << "\"" << endl;
132       }
133     } else if (token == "run") {
134       StartTime = strtod(Script.GetValue("start").c_str(), NULL);
135       State->Setsim_time(StartTime);
136       EndTime   = strtod(Script.GetValue("end").c_str(), NULL);
137       dt        = strtod(Script.GetValue("dt").c_str(), NULL);
138       State->Setdt(dt);
139       Script.GetNextConfigLine();
140       token = Script.GetValue();
141       while (token != string("/run")) {
142
143         if (token == "when") {
144           Script.GetNextConfigLine();
145           token = Script.GetValue();
146           newCondition = new struct condition();
147           while (token != string("/when")) {
148             if (token == "parameter") {
149               prop_name = Script.GetValue("name");
150               newCondition->TestParam.push_back( PropertyManager->GetNode(prop_name) );
151               newCondition->TestValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));
152               newCondition->Comparison.push_back(Script.GetValue("comparison"));
153             } else if (token == "set") {
154               prop_name = Script.GetValue("name");
155               newCondition->SetParam.push_back( PropertyManager->GetNode(prop_name) );
156               newCondition->SetValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));
157               newCondition->Triggered.push_back(false);
158               newCondition->OriginalValue.push_back(0.0);
159               newCondition->newValue.push_back(0.0);
160               newCondition->StartTime.push_back(0.0);
161               newCondition->EndTime.push_back(0.0);
162               string tempCompare = Script.GetValue("type");
163               if      (tempCompare == "FG_DELTA") newCondition->Type.push_back(FG_DELTA);
164               else if (tempCompare == "FG_BOOL")  newCondition->Type.push_back(FG_BOOL);
165               else if (tempCompare == "FG_VALUE") newCondition->Type.push_back(FG_VALUE);
166               else                                newCondition->Type.push_back((eType)0);
167               tempCompare = Script.GetValue("action");
168               if      (tempCompare == "FG_RAMP") newCondition->Action.push_back(FG_RAMP);
169               else if (tempCompare == "FG_STEP") newCondition->Action.push_back(FG_STEP);
170               else if (tempCompare == "FG_EXP")  newCondition->Action.push_back(FG_EXP);
171               else                               newCondition->Action.push_back((eAction)0);
172
173               if (Script.GetValue("persistent") == "true")
174                 newCondition->Persistent.push_back(true);
175               else
176                 newCondition->Persistent.push_back(false);
177
178               newCondition->TC.push_back(strtod(Script.GetValue("tc").c_str(), NULL));
179
180             } else {
181               cerr << "Unrecognized keyword in script file: \" [when] " << token << "\"" << endl;
182             }
183             Script.GetNextConfigLine();
184             token = Script.GetValue();
185           }
186           Conditions.push_back(*newCondition);
187           Script.GetNextConfigLine();
188           token = Script.GetValue();
189
190         } else {
191           cerr << "Error reading script file: expected \"when\", got \"" << token << "\"" << endl;
192         }
193
194       }
195     } else if (token.empty()) {
196      // do nothing
197     } else {
198       cerr << "Unrecognized keyword in script file: \"" << token << "\" [runscript] " << endl;
199     }
200   }
201
202   if (aircraft == "") {
203     cerr << "Aircraft file not loaded in script" << endl;
204     exit(-1);
205   }
206
207   Debug(4);
208
209
210   FGInitialCondition *IC=FDMExec->GetIC();
211   if ( ! IC->Load( initialize )) {
212     cerr << "Initialization unsuccessful" << endl;
213     exit(-1);
214   }
215 /* comment this out for conversion capability
216   FGTrim fgt(FDMExec, tFull);
217   if ( !fgt.DoTrim() ) {
218     cout << "Trim Failed" << endl;
219   }
220   fgt.Report();
221 */
222   return true;
223 }
224
225 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226
227 bool FGScript::RunScript(void)
228 {
229   vector <struct condition>::iterator iC = Conditions.begin();
230   bool truth = false;
231   bool WholeTruth = false;
232   unsigned i;
233
234   double currentTime = State->Getsim_time();
235   double newSetValue = 0;
236
237   if (currentTime > EndTime) return false;
238
239   while (iC < Conditions.end()) {
240     // determine whether the set of conditional tests for this condition equate
241     // to true
242     for (i=0; i<iC->TestValue.size(); i++) {
243            if (iC->Comparison[i] == "lt")
244               truth = iC->TestParam[i]->getDoubleValue() <  iC->TestValue[i];
245       else if (iC->Comparison[i] == "le")
246               truth = iC->TestParam[i]->getDoubleValue() <= iC->TestValue[i];
247       else if (iC->Comparison[i] == "eq")
248               truth = iC->TestParam[i]->getDoubleValue() == iC->TestValue[i];
249       else if (iC->Comparison[i] == "ge")
250               truth = iC->TestParam[i]->getDoubleValue() >= iC->TestValue[i];
251       else if (iC->Comparison[i] == "gt")
252               truth = iC->TestParam[i]->getDoubleValue() >  iC->TestValue[i];
253       else if (iC->Comparison[i] == "ne")
254               truth = iC->TestParam[i]->getDoubleValue() != iC->TestValue[i];
255       else
256               cerr << "Bad comparison" << endl;
257
258       if (i == 0) WholeTruth = truth;
259       else        WholeTruth = WholeTruth && truth;
260
261       if (!truth && iC->Persistent[i] && iC->Triggered[i]) iC->Triggered[i] = false;
262     }
263
264     // if the conditions are true, do the setting of the desired parameters
265
266     if (WholeTruth) {
267       for (i=0; i<iC->SetValue.size(); i++) {
268         if ( ! iC->Triggered[i]) {
269           iC->OriginalValue[i] = iC->SetParam[i]->getDoubleValue();
270           switch (iC->Type[i]) {
271           case FG_VALUE:
272             iC->newValue[i] = iC->SetValue[i];
273             break;
274           case FG_DELTA:
275             iC->newValue[i] = iC->OriginalValue[i] + iC->SetValue[i];
276             break;
277           case FG_BOOL:
278             iC->newValue[i] = iC->SetValue[i];
279             break;
280           default:
281             cerr << "Invalid Type specified" << endl;
282             break;
283           }
284           iC->Triggered[i] = true;
285           iC->StartTime[i] = currentTime;
286         }
287
288         switch (iC->Action[i]) {
289         case FG_RAMP:
290         newSetValue = (currentTime - iC->StartTime[i])/(iC->TC[i])
291                       * (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];
292           if (newSetValue > iC->newValue[i]) newSetValue = iC->newValue[i];
293           break;
294         case FG_STEP:
295           newSetValue = iC->newValue[i];
296           break;
297         case FG_EXP:
298           newSetValue = (1 - exp(-(currentTime - iC->StartTime[i])/(iC->TC[i])))
299               * (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];
300           break;
301         default:
302           cerr << "Invalid Action specified" << endl;
303           break;
304         }
305         iC->SetParam[i]->setDoubleValue(newSetValue);
306       }
307     }
308     iC++;
309   }
310   return true;
311 }
312
313 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314 //    The bitmasked value choices are as follows:
315 //    unset: In this case (the default) JSBSim would only print
316 //       out the normally expected messages, essentially echoing
317 //       the config files as they are read. If the environment
318 //       variable is not set, debug_lvl is set to 1 internally
319 //    0: This requests JSBSim not to output any messages
320 //       whatsoever.
321 //    1: This value explicity requests the normal JSBSim
322 //       startup messages
323 //    2: This value asks for a message to be printed out when
324 //       a class is instantiated
325 //    4: When this value is set, a message is displayed when a
326 //       FGModel object executes its Run() method
327 //    8: When this value is set, various runtime state variables
328 //       are printed out periodically
329 //    16: When set various parameters are sanity checked and
330 //       a message is printed out when they go out of bounds
331
332 void FGScript::Debug(int from)
333 {
334   unsigned int i;
335
336   if (debug_lvl <= 0) return;
337
338   if (debug_lvl & 1) { // Standard console startup message output
339     if (from == 0) { // Constructor
340     } else if (from == 3) {
341     } else if (from == 4)  { // print out script data
342       vector <struct condition>::iterator iterConditions = Conditions.begin();
343       int count=0;
344
345       cout << "\n  Script goes from " << StartTime << " to " << EndTime
346            << " with dt = " << State->Getdt() << endl << endl;
347
348       while (iterConditions < Conditions.end()) {
349         cout << "  Condition: " << count++ << endl;
350         cout << "    if (";
351
352         for (i=0; i<iterConditions->TestValue.size(); i++) {
353           if (i>0) cout << " and" << endl << "        ";
354           cout << "(" << iterConditions->TestParam[i]->GetName()
355                       << " " << iterConditions->Comparison[i] << " "
356                       << iterConditions->TestValue[i] << ")";
357         }
358         cout << ") then {";
359
360         for (i=0; i<iterConditions->SetValue.size(); i++) {
361           cout << endl << "      set " << iterConditions->SetParam[i]->GetName()
362                << " to " << iterConditions->SetValue[i];
363
364           switch (iterConditions->Type[i]) {
365           case FG_VALUE:
366             cout << " (constant";
367             break;
368           case FG_DELTA:
369             cout << " (delta";
370             break;
371           case FG_BOOL:
372             cout << " (boolean";
373             break;
374           default:
375             cout << " (unspecified type";
376           }
377
378           switch (iterConditions->Action[i]) {
379           case FG_RAMP:
380             cout << " via ramp";
381             break;
382           case FG_STEP:
383             cout << " via step";
384             break;
385           case FG_EXP:
386             cout << " via exponential approach";
387             break;
388           default:
389             cout << " via unspecified action";
390           }
391
392           if (!iterConditions->Persistent[i]) cout << endl
393                              << "                              once";
394           else cout << endl
395                              << "                              repeatedly";
396
397           if (iterConditions->Action[i] == FG_RAMP ||
398               iterConditions->Action[i] == FG_EXP) cout << endl
399                              << "                              with time constant "
400                              << iterConditions->TC[i];
401         }
402         cout << ")" << endl << "    }" << endl << endl;
403
404         iterConditions++;
405       }
406
407       cout << endl;
408     }
409   }
410   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
411     if (from == 0) cout << "Instantiated: FGScript" << endl;
412     if (from == 1) cout << "Destroyed:    FGScript" << endl;
413   }
414   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
415   }
416   if (debug_lvl & 8 ) { // Runtime state variables
417   }
418   if (debug_lvl & 16) { // Sanity checking
419   }
420   if (debug_lvl & 64) {
421     if (from == 0) { // Constructor
422       cout << IdSrc << endl;
423       cout << IdHdr << endl;
424     }
425   }
426 }
427 }