-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
- Module: FGScript.cpp\r
- Author: Jon S. Berndt\r
- Date started: 12/21/01\r
- Purpose: Loads and runs JSBSim scripts.\r
-\r
- ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------\r
-\r
- This program is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License as published by the Free Software\r
- Foundation; either version 2 of the License, or (at your option) any later\r
- version.\r
-\r
- This program is distributed in the hope that it will be useful, but WITHOUT\r
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\r
- details.\r
-\r
- You should have received a copy of the GNU General Public License along with\r
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
- Place - Suite 330, Boston, MA 02111-1307, USA.\r
-\r
- Further information about the GNU General Public License can also be found on\r
- the world wide web at http://www.gnu.org.\r
-\r
-FUNCTIONAL DESCRIPTION\r
---------------------------------------------------------------------------------\r
-\r
-This class wraps up the simulation scripting routines.\r
-\r
-HISTORY\r
---------------------------------------------------------------------------------\r
-12/21/01 JSB Created\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-COMMENTS, REFERENCES, and NOTES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-INCLUDES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#ifdef FGFS\r
-# include <simgear/compiler.h>\r
-# include STL_IOSTREAM\r
-# include STL_ITERATOR\r
-#else\r
-# if defined(sgi) && !defined(__GNUC__)\r
-# include <iostream.h>\r
-# else\r
-# include <iostream>\r
-# endif\r
-# include <iterator>\r
-#endif\r
-\r
-#include "FGScript.h"\r
-#include "FGConfigFile.h"\r
-\r
-static const char *IdSrc = "$Id$";\r
-static const char *IdHdr = ID_FGSCRIPT;\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-GLOBAL DECLARATIONS\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS IMPLEMENTATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-// Constructor\r
-\r
-FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)\r
-{\r
- State = FDMExec->GetState();\r
- Debug(0);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-FGScript::~FGScript()\r
-{\r
- Debug(1);\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-bool FGScript::LoadScript(string script)\r
-{\r
- FGConfigFile Script(script);\r
- string token="";\r
- string aircraft="";\r
- string initialize="";\r
- bool result = false;\r
- double dt = 0.0;\r
- struct condition *newCondition;\r
-\r
- if (!Script.IsOpen()) return false;\r
-\r
- Script.GetNextConfigLine();\r
- if (Script.GetValue("runscript").length() <= 0) {\r
- cerr << "File: " << script << " is not a script file" << endl;\r
- delete FDMExec;\r
- return false; \r
- }\r
- ScriptName = Script.GetValue("name");\r
- Scripted = true;\r
-\r
- if (debug_lvl > 0) cout << "Reading Script File " << ScriptName << endl;\r
-\r
- while (Script.GetNextConfigLine() != string("EOF") && Script.GetValue() != string("/runscript")) {\r
- token = Script.GetValue();\r
- if (token == "use") {\r
- if ((token = Script.GetValue("aircraft")) != string("")) {\r
- aircraft = token;\r
- if (debug_lvl > 0) cout << " Use aircraft: " << token << endl;\r
- } else if ((token = Script.GetValue("initialize")) != string("")) {\r
- initialize = token;\r
- if (debug_lvl > 0) cout << " Use reset file: " << token << endl;\r
- } else {\r
- cerr << "Unknown 'use' keyword: \"" << token << "\"" << endl;\r
- }\r
- } else if (token == "run") {\r
- StartTime = strtod(Script.GetValue("start").c_str(), NULL);\r
- State->Setsim_time(StartTime);\r
- EndTime = strtod(Script.GetValue("end").c_str(), NULL);\r
- dt = strtod(Script.GetValue("dt").c_str(), NULL);\r
- State->Setdt(dt);\r
- Script.GetNextConfigLine();\r
- token = Script.GetValue();\r
- while (token != string("/run")) {\r
-\r
- if (token == "when") {\r
- Script.GetNextConfigLine();\r
- token = Script.GetValue();\r
- newCondition = new struct condition();\r
- while (token != string("/when")) {\r
- if (token == "parameter") {\r
- newCondition->TestParam.push_back(State->GetParameterIndex(Script.GetValue("name")));\r
- newCondition->TestValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));\r
- newCondition->Comparison.push_back(Script.GetValue("comparison"));\r
- } else if (token == "set") {\r
- newCondition->SetParam.push_back(State->GetParameterIndex(Script.GetValue("name")));\r
- newCondition->SetValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));\r
- newCondition->Triggered.push_back(false);\r
- newCondition->OriginalValue.push_back(0.0);\r
- newCondition->newValue.push_back(0.0);\r
- newCondition->StartTime.push_back(0.0);\r
- newCondition->EndTime.push_back(0.0);\r
- string tempCompare = Script.GetValue("type");\r
- if (tempCompare == "FG_DELTA") newCondition->Type.push_back(FG_DELTA);\r
- else if (tempCompare == "FG_BOOL") newCondition->Type.push_back(FG_BOOL);\r
- else if (tempCompare == "FG_VALUE") newCondition->Type.push_back(FG_VALUE);\r
- else newCondition->Type.push_back((eType)0);\r
- tempCompare = Script.GetValue("action");\r
- if (tempCompare == "FG_RAMP") newCondition->Action.push_back(FG_RAMP);\r
- else if (tempCompare == "FG_STEP") newCondition->Action.push_back(FG_STEP);\r
- else if (tempCompare == "FG_EXP") newCondition->Action.push_back(FG_EXP);\r
- else newCondition->Action.push_back((eAction)0);\r
- \r
- if (Script.GetValue("persistent") == "true")\r
- newCondition->Persistent.push_back(true);\r
- else\r
- newCondition->Persistent.push_back(false);\r
- \r
- newCondition->TC.push_back(strtod(Script.GetValue("tc").c_str(), NULL));\r
- \r
- } else {\r
- cerr << "Unrecognized keyword in script file: \" [when] " << token << "\"" << endl;\r
- }\r
- Script.GetNextConfigLine();\r
- token = Script.GetValue();\r
- }\r
- Conditions.push_back(*newCondition);\r
- Script.GetNextConfigLine();\r
- token = Script.GetValue();\r
-\r
- } else {\r
- cerr << "Error reading script file: expected \"when\", got \"" << token << "\"" << endl;\r
- }\r
-\r
- }\r
- } else if (token.empty()) {\r
- // do nothing\r
- } else {\r
- cerr << "Unrecognized keyword in script file: \"" << token << "\" [runscript] " << endl;\r
- }\r
- }\r
-\r
- if (aircraft == "") {\r
- cerr << "Aircraft file not loaded in script" << endl;\r
- exit(-1);\r
- }\r
-\r
- Debug(4);\r
-\r
- result = FDMExec->LoadModel("aircraft", "engine", aircraft);\r
- if (!result) {\r
- cerr << "Aircraft file " << aircraft << " was not found" << endl;\r
- exit(-1);\r
- }\r
-\r
- FGInitialCondition IC(FDMExec);\r
- if ( ! IC.Load("aircraft", aircraft, initialize)) {\r
- cerr << "Initialization unsuccessful" << endl;\r
- exit(-1);\r
- }\r
-\r
- return true;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-\r
-bool FGScript::RunScript(void)\r
-{\r
- vector <struct condition>::iterator iC = Conditions.begin();\r
- bool truth = false;\r
- bool WholeTruth = false;\r
- unsigned i;\r
-\r
- double currentTime = State->Getsim_time();\r
- double newSetValue = 0;\r
-\r
- if (currentTime > EndTime) return false;\r
-\r
- while (iC < Conditions.end()) {\r
- // determine whether the set of conditional tests for this condition equate\r
- // to true\r
- for (i=0; i<iC->TestValue.size(); i++) {\r
- if (iC->Comparison[i] == "lt")\r
- truth = State->GetParameter(iC->TestParam[i]) < iC->TestValue[i];\r
- else if (iC->Comparison[i] == "le")\r
- truth = State->GetParameter(iC->TestParam[i]) <= iC->TestValue[i];\r
- else if (iC->Comparison[i] == "eq")\r
- truth = State->GetParameter(iC->TestParam[i]) == iC->TestValue[i];\r
- else if (iC->Comparison[i] == "ge")\r
- truth = State->GetParameter(iC->TestParam[i]) >= iC->TestValue[i];\r
- else if (iC->Comparison[i] == "gt")\r
- truth = State->GetParameter(iC->TestParam[i]) > iC->TestValue[i];\r
- else if (iC->Comparison[i] == "ne")\r
- truth = State->GetParameter(iC->TestParam[i]) != iC->TestValue[i];\r
- else\r
- cerr << "Bad comparison" << endl;\r
-\r
- if (i == 0) WholeTruth = truth;\r
- else WholeTruth = WholeTruth && truth;\r
-\r
- if (!truth && iC->Persistent[i] && iC->Triggered[i]) iC->Triggered[i] = false;\r
- }\r
-\r
- // if the conditions are true, do the setting of the desired parameters\r
-\r
- if (WholeTruth) {\r
- for (i=0; i<iC->SetValue.size(); i++) {\r
- if ( ! iC->Triggered[i]) {\r
- iC->OriginalValue[i] = State->GetParameter(iC->SetParam[i]);\r
- switch (iC->Type[i]) {\r
- case FG_VALUE:\r
- iC->newValue[i] = iC->SetValue[i];\r
- break;\r
- case FG_DELTA:\r
- iC->newValue[i] = iC->OriginalValue[i] + iC->SetValue[i];\r
- break;\r
- case FG_BOOL:\r
- iC->newValue[i] = iC->SetValue[i];\r
- break;\r
- default:\r
- cerr << "Invalid Type specified" << endl;\r
- break;\r
- }\r
- iC->Triggered[i] = true;\r
- iC->StartTime[i] = currentTime;\r
- }\r
-\r
- switch (iC->Action[i]) {\r
- case FG_RAMP:\r
- newSetValue = (currentTime - iC->StartTime[i])/(iC->TC[i])\r
- * (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];\r
- if (newSetValue > iC->newValue[i]) newSetValue = iC->newValue[i];\r
- break;\r
- case FG_STEP:\r
- newSetValue = iC->newValue[i];\r
- break;\r
- case FG_EXP:\r
- newSetValue = (1 - exp(-(currentTime - iC->StartTime[i])/(iC->TC[i])))\r
- * (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];\r
- break;\r
- default:\r
- cerr << "Invalid Action specified" << endl;\r
- break;\r
- }\r
- State->SetParameter(iC->SetParam[i], newSetValue);\r
- }\r
- }\r
- iC++;\r
- }\r
- return true;\r
-}\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-// The bitmasked value choices are as follows:\r
-// unset: In this case (the default) JSBSim would only print\r
-// out the normally expected messages, essentially echoing\r
-// the config files as they are read. If the environment\r
-// variable is not set, debug_lvl is set to 1 internally\r
-// 0: This requests JSBSim not to output any messages\r
-// whatsoever.\r
-// 1: This value explicity requests the normal JSBSim\r
-// startup messages\r
-// 2: This value asks for a message to be printed out when\r
-// a class is instantiated\r
-// 4: When this value is set, a message is displayed when a\r
-// FGModel object executes its Run() method\r
-// 8: When this value is set, various runtime state variables\r
-// are printed out periodically\r
-// 16: When set various parameters are sanity checked and\r
-// a message is printed out when they go out of bounds\r
-\r
-void FGScript::Debug(int from)\r
-{\r
- unsigned int i;\r
-\r
- if (debug_lvl <= 0) return;\r
-\r
- if (debug_lvl & 1) { // Standard console startup message output\r
- if (from == 0) { // Constructor\r
- } else if (from == 3) {\r
- } else if (from == 4) { // print out script data\r
- vector <struct condition>::iterator iterConditions = Conditions.begin();\r
- int count=0;\r
-\r
- cout << "\n Script goes from " << StartTime << " to " << EndTime\r
- << " with dt = " << State->Getdt() << endl << endl;\r
-\r
- while (iterConditions < Conditions.end()) {\r
- cout << " Condition: " << count++ << endl;\r
- cout << " if (";\r
-\r
- for (i=0; i<iterConditions->TestValue.size(); i++) {\r
- if (i>0) cout << " and" << endl << " ";\r
- cout << "(" << State->paramdef[iterConditions->TestParam[i]]\r
- << iterConditions->Comparison[i] << " "\r
- << iterConditions->TestValue[i] << ")";\r
- }\r
- cout << ") then {";\r
-\r
- for (i=0; i<iterConditions->SetValue.size(); i++) {\r
- cout << endl << " set" << State->paramdef[iterConditions->SetParam[i]]\r
- << "to " << iterConditions->SetValue[i];\r
-\r
- switch (iterConditions->Type[i]) {\r
- case FG_VALUE:\r
- cout << " (constant";\r
- break;\r
- case FG_DELTA:\r
- cout << " (delta";\r
- break;\r
- case FG_BOOL:\r
- cout << " (boolean";\r
- break;\r
- default:\r
- cout << " (unspecified type";\r
- }\r
-\r
- switch (iterConditions->Action[i]) {\r
- case FG_RAMP:\r
- cout << " via ramp";\r
- break;\r
- case FG_STEP:\r
- cout << " via step";\r
- break;\r
- case FG_EXP:\r
- cout << " via exponential approach";\r
- break;\r
- default:\r
- cout << " via unspecified action";\r
- }\r
-\r
- if (!iterConditions->Persistent[i]) cout << endl\r
- << " once";\r
- else cout << endl\r
- << " repeatedly";\r
-\r
- if (iterConditions->Action[i] == FG_RAMP ||\r
- iterConditions->Action[i] == FG_EXP) cout << endl\r
- << " with time constant "\r
- << iterConditions->TC[i];\r
- }\r
- cout << ")" << endl << " }" << endl << endl;\r
-\r
- iterConditions++;\r
- }\r
-\r
- cout << endl;\r
- }\r
- }\r
- if (debug_lvl & 2 ) { // Instantiation/Destruction notification\r
- if (from == 0) cout << "Instantiated: FGScript" << endl;\r
- if (from == 1) cout << "Destroyed: FGScript" << endl;\r
- }\r
- if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
- }\r
- if (debug_lvl & 8 ) { // Runtime state variables\r
- }\r
- if (debug_lvl & 16) { // Sanity checking\r
- }\r
- if (debug_lvl & 64) {\r
- if (from == 0) { // Constructor\r
- cout << IdSrc << endl;\r
- cout << IdHdr << endl;\r
- }\r
- }\r
-}\r
-\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module: FGScript.cpp
+ Author: Jon S. Berndt
+ Date started: 12/21/01
+ Purpose: Loads and runs JSBSim scripts.
+
+ ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+This class wraps up the simulation scripting routines.
+
+HISTORY
+--------------------------------------------------------------------------------
+12/21/01 JSB Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES, and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifdef FGFS
+# include <simgear/compiler.h>
+# include STL_IOSTREAM
+# include STL_ITERATOR
+#else
+# if defined(sgi) && !defined(__GNUC__)
+# include <iostream.h>
+# else
+# include <iostream>
+# endif
+# include <iterator>
+#endif
+
+#include "FGScript.h"
+#include "FGConfigFile.h"
+
+static const char *IdSrc = "$Id$";
+static const char *IdHdr = ID_FGSCRIPT;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+GLOBAL DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+// Constructor
+
+FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
+{
+ State = FDMExec->GetState();
+ Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGScript::~FGScript()
+{
+ Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGScript::LoadScript(string script)
+{
+ FGConfigFile Script(script);
+ string token="";
+ string aircraft="";
+ string initialize="";
+ bool result = false;
+ double dt = 0.0;
+ struct condition *newCondition;
+
+ if (!Script.IsOpen()) return false;
+
+ Script.GetNextConfigLine();
+ if (Script.GetValue("runscript").length() <= 0) {
+ cerr << "File: " << script << " is not a script file" << endl;
+ delete FDMExec;
+ return false;
+ }
+ ScriptName = Script.GetValue("name");
+ Scripted = true;
+
+ if (debug_lvl > 0) cout << "Reading Script File " << ScriptName << endl;
+
+ while (Script.GetNextConfigLine() != string("EOF") && Script.GetValue() != string("/runscript")) {
+ token = Script.GetValue();
+ if (token == "use") {
+ if ((token = Script.GetValue("aircraft")) != string("")) {
+ aircraft = token;
+ if (debug_lvl > 0) cout << " Use aircraft: " << token << endl;
+ } else if ((token = Script.GetValue("initialize")) != string("")) {
+ initialize = token;
+ if (debug_lvl > 0) cout << " Use reset file: " << token << endl;
+ } else {
+ cerr << "Unknown 'use' keyword: \"" << token << "\"" << endl;
+ }
+ } else if (token == "run") {
+ StartTime = strtod(Script.GetValue("start").c_str(), NULL);
+ State->Setsim_time(StartTime);
+ EndTime = strtod(Script.GetValue("end").c_str(), NULL);
+ dt = strtod(Script.GetValue("dt").c_str(), NULL);
+ State->Setdt(dt);
+ Script.GetNextConfigLine();
+ token = Script.GetValue();
+ while (token != string("/run")) {
+
+ if (token == "when") {
+ Script.GetNextConfigLine();
+ token = Script.GetValue();
+ newCondition = new struct condition();
+ while (token != string("/when")) {
+ if (token == "parameter") {
+ newCondition->TestParam.push_back(State->GetParameterIndex(Script.GetValue("name")));
+ newCondition->TestValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));
+ newCondition->Comparison.push_back(Script.GetValue("comparison"));
+ } else if (token == "set") {
+ newCondition->SetParam.push_back(State->GetParameterIndex(Script.GetValue("name")));
+ newCondition->SetValue.push_back(strtod(Script.GetValue("value").c_str(), NULL));
+ newCondition->Triggered.push_back(false);
+ newCondition->OriginalValue.push_back(0.0);
+ newCondition->newValue.push_back(0.0);
+ newCondition->StartTime.push_back(0.0);
+ newCondition->EndTime.push_back(0.0);
+ string tempCompare = Script.GetValue("type");
+ if (tempCompare == "FG_DELTA") newCondition->Type.push_back(FG_DELTA);
+ else if (tempCompare == "FG_BOOL") newCondition->Type.push_back(FG_BOOL);
+ else if (tempCompare == "FG_VALUE") newCondition->Type.push_back(FG_VALUE);
+ else newCondition->Type.push_back((eType)0);
+ tempCompare = Script.GetValue("action");
+ if (tempCompare == "FG_RAMP") newCondition->Action.push_back(FG_RAMP);
+ else if (tempCompare == "FG_STEP") newCondition->Action.push_back(FG_STEP);
+ else if (tempCompare == "FG_EXP") newCondition->Action.push_back(FG_EXP);
+ else newCondition->Action.push_back((eAction)0);
+
+ if (Script.GetValue("persistent") == "true")
+ newCondition->Persistent.push_back(true);
+ else
+ newCondition->Persistent.push_back(false);
+
+ newCondition->TC.push_back(strtod(Script.GetValue("tc").c_str(), NULL));
+
+ } else {
+ cerr << "Unrecognized keyword in script file: \" [when] " << token << "\"" << endl;
+ }
+ Script.GetNextConfigLine();
+ token = Script.GetValue();
+ }
+ Conditions.push_back(*newCondition);
+ Script.GetNextConfigLine();
+ token = Script.GetValue();
+
+ } else {
+ cerr << "Error reading script file: expected \"when\", got \"" << token << "\"" << endl;
+ }
+
+ }
+ } else if (token.empty()) {
+ // do nothing
+ } else {
+ cerr << "Unrecognized keyword in script file: \"" << token << "\" [runscript] " << endl;
+ }
+ }
+
+ if (aircraft == "") {
+ cerr << "Aircraft file not loaded in script" << endl;
+ exit(-1);
+ }
+
+ Debug(4);
+
+ result = FDMExec->LoadModel("aircraft", "engine", aircraft);
+ if (!result) {
+ cerr << "Aircraft file " << aircraft << " was not found" << endl;
+ exit(-1);
+ }
+
+ FGInitialCondition IC(FDMExec);
+ if ( ! IC.Load("aircraft", aircraft, initialize)) {
+ cerr << "Initialization unsuccessful" << endl;
+ exit(-1);
+ }
+
+ return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGScript::RunScript(void)
+{
+ vector <struct condition>::iterator iC = Conditions.begin();
+ bool truth = false;
+ bool WholeTruth = false;
+ unsigned i;
+
+ double currentTime = State->Getsim_time();
+ double newSetValue = 0;
+
+ if (currentTime > EndTime) return false;
+
+ while (iC < Conditions.end()) {
+ // determine whether the set of conditional tests for this condition equate
+ // to true
+ for (i=0; i<iC->TestValue.size(); i++) {
+ if (iC->Comparison[i] == "lt")
+ truth = State->GetParameter(iC->TestParam[i]) < iC->TestValue[i];
+ else if (iC->Comparison[i] == "le")
+ truth = State->GetParameter(iC->TestParam[i]) <= iC->TestValue[i];
+ else if (iC->Comparison[i] == "eq")
+ truth = State->GetParameter(iC->TestParam[i]) == iC->TestValue[i];
+ else if (iC->Comparison[i] == "ge")
+ truth = State->GetParameter(iC->TestParam[i]) >= iC->TestValue[i];
+ else if (iC->Comparison[i] == "gt")
+ truth = State->GetParameter(iC->TestParam[i]) > iC->TestValue[i];
+ else if (iC->Comparison[i] == "ne")
+ truth = State->GetParameter(iC->TestParam[i]) != iC->TestValue[i];
+ else
+ cerr << "Bad comparison" << endl;
+
+ if (i == 0) WholeTruth = truth;
+ else WholeTruth = WholeTruth && truth;
+
+ if (!truth && iC->Persistent[i] && iC->Triggered[i]) iC->Triggered[i] = false;
+ }
+
+ // if the conditions are true, do the setting of the desired parameters
+
+ if (WholeTruth) {
+ for (i=0; i<iC->SetValue.size(); i++) {
+ if ( ! iC->Triggered[i]) {
+ iC->OriginalValue[i] = State->GetParameter(iC->SetParam[i]);
+ switch (iC->Type[i]) {
+ case FG_VALUE:
+ iC->newValue[i] = iC->SetValue[i];
+ break;
+ case FG_DELTA:
+ iC->newValue[i] = iC->OriginalValue[i] + iC->SetValue[i];
+ break;
+ case FG_BOOL:
+ iC->newValue[i] = iC->SetValue[i];
+ break;
+ default:
+ cerr << "Invalid Type specified" << endl;
+ break;
+ }
+ iC->Triggered[i] = true;
+ iC->StartTime[i] = currentTime;
+ }
+
+ switch (iC->Action[i]) {
+ case FG_RAMP:
+ newSetValue = (currentTime - iC->StartTime[i])/(iC->TC[i])
+ * (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];
+ if (newSetValue > iC->newValue[i]) newSetValue = iC->newValue[i];
+ break;
+ case FG_STEP:
+ newSetValue = iC->newValue[i];
+ break;
+ case FG_EXP:
+ newSetValue = (1 - exp(-(currentTime - iC->StartTime[i])/(iC->TC[i])))
+ * (iC->newValue[i] - iC->OriginalValue[i]) + iC->OriginalValue[i];
+ break;
+ default:
+ cerr << "Invalid Action specified" << endl;
+ break;
+ }
+ State->SetParameter(iC->SetParam[i], newSetValue);
+ }
+ }
+ iC++;
+ }
+ return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// The bitmasked value choices are as follows:
+// unset: In this case (the default) JSBSim would only print
+// out the normally expected messages, essentially echoing
+// the config files as they are read. If the environment
+// variable is not set, debug_lvl is set to 1 internally
+// 0: This requests JSBSim not to output any messages
+// whatsoever.
+// 1: This value explicity requests the normal JSBSim
+// startup messages
+// 2: This value asks for a message to be printed out when
+// a class is instantiated
+// 4: When this value is set, a message is displayed when a
+// FGModel object executes its Run() method
+// 8: When this value is set, various runtime state variables
+// are printed out periodically
+// 16: When set various parameters are sanity checked and
+// a message is printed out when they go out of bounds
+
+void FGScript::Debug(int from)
+{
+ unsigned int i;
+
+ if (debug_lvl <= 0) return;
+
+ if (debug_lvl & 1) { // Standard console startup message output
+ if (from == 0) { // Constructor
+ } else if (from == 3) {
+ } else if (from == 4) { // print out script data
+ vector <struct condition>::iterator iterConditions = Conditions.begin();
+ int count=0;
+
+ cout << "\n Script goes from " << StartTime << " to " << EndTime
+ << " with dt = " << State->Getdt() << endl << endl;
+
+ while (iterConditions < Conditions.end()) {
+ cout << " Condition: " << count++ << endl;
+ cout << " if (";
+
+ for (i=0; i<iterConditions->TestValue.size(); i++) {
+ if (i>0) cout << " and" << endl << " ";
+ cout << "(" << State->paramdef[iterConditions->TestParam[i]]
+ << iterConditions->Comparison[i] << " "
+ << iterConditions->TestValue[i] << ")";
+ }
+ cout << ") then {";
+
+ for (i=0; i<iterConditions->SetValue.size(); i++) {
+ cout << endl << " set" << State->paramdef[iterConditions->SetParam[i]]
+ << "to " << iterConditions->SetValue[i];
+
+ switch (iterConditions->Type[i]) {
+ case FG_VALUE:
+ cout << " (constant";
+ break;
+ case FG_DELTA:
+ cout << " (delta";
+ break;
+ case FG_BOOL:
+ cout << " (boolean";
+ break;
+ default:
+ cout << " (unspecified type";
+ }
+
+ switch (iterConditions->Action[i]) {
+ case FG_RAMP:
+ cout << " via ramp";
+ break;
+ case FG_STEP:
+ cout << " via step";
+ break;
+ case FG_EXP:
+ cout << " via exponential approach";
+ break;
+ default:
+ cout << " via unspecified action";
+ }
+
+ if (!iterConditions->Persistent[i]) cout << endl
+ << " once";
+ else cout << endl
+ << " repeatedly";
+
+ if (iterConditions->Action[i] == FG_RAMP ||
+ iterConditions->Action[i] == FG_EXP) cout << endl
+ << " with time constant "
+ << iterConditions->TC[i];
+ }
+ cout << ")" << endl << " }" << endl << endl;
+
+ iterConditions++;
+ }
+
+ cout << endl;
+ }
+ }
+ if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+ if (from == 0) cout << "Instantiated: FGScript" << endl;
+ if (from == 1) cout << "Destroyed: FGScript" << endl;
+ }
+ if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
+ }
+ if (debug_lvl & 8 ) { // Runtime state variables
+ }
+ if (debug_lvl & 16) { // Sanity checking
+ }
+ if (debug_lvl & 64) {
+ if (from == 0) { // Constructor
+ cout << IdSrc << endl;
+ cout << IdHdr << endl;
+ }
+ }
+}
+
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
- Header: FGScript.h\r
- Author: Jon Berndt\r
- Date started: 12/21/2001\r
-\r
- ------------- Copyright (C) 2001 Jon S. Berndt (jsb@hal-pc.org) -------------\r
-\r
- This program is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License as published by the Free Software\r
- Foundation; either version 2 of the License, or (at your option) any later\r
- version.\r
-\r
- This program is distributed in the hope that it will be useful, but WITHOUT\r
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\r
- details.\r
-\r
- You should have received a copy of the GNU General Public License along with\r
- this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
- Place - Suite 330, Boston, MA 02111-1307, USA.\r
-\r
- Further information about the GNU General Public License can also be found on\r
- the world wide web at http://www.gnu.org.\r
-\r
-HISTORY\r
---------------------------------------------------------------------------------\r
-12/21/01 JSB Created\r
-\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-SENTRY\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#ifndef FGSCRIPT_HEADER_H\r
-#define FGSCRIPT_HEADER_H\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-INCLUDES\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#include "FGJSBBase.h"\r
-#include "FGState.h"\r
-#include "FGFDMExec.h"\r
-#include <vector>\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-DEFINITIONS\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-#define ID_FGSCRIPT "$Id$"\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-FORWARD DECLARATIONS\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS DOCUMENTATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-/** Encapsulates the JSBSim scripting capability.\r
- @author Jon S. Berndt\r
- @version $Id$\r
-\r
- <h4>Scripting support provided via FGScript.</h4>\r
-\r
- <p>There is simple scripting support provided in the FGScript\r
- class. Commands are specified using the <u>Simple Scripting\r
- Directives for JSBSim</u> (SSDJ). The script file is in XML\r
- format. A test condition (or conditions) can be set up in the\r
- script and when the condition evaluates to true, the specified\r
- action[s] is/are taken. A test condition can be <em>persistent</em>,\r
- meaning that if a test condition evaluates to true, then passes\r
- and evaluates to false, the condition is reset and may again be\r
- triggered. When the set of tests evaluates to true for a given\r
- condition, an item may be set to another value. This value might\r
- be a boolean, a value, or a delta value, and the change from the\r
- current value to the new value can be either via a step function,\r
- a ramp, or an exponential approach. The speed of a ramp or\r
- approach is specified via the time constant. Here is the format\r
- of the script file:</p>\r
-\r
- <pre><strong><?xml version="1.0"?>\r
- <runscript name="C172-01A">\r
-\r
- <!--\r
- This run is for testing C172 runs\r
- -->\r
-\r
- <use aircraft="c172">\r
- <use initialize="reset00">\r
-\r
- <run start="0.0" end="4.5" dt="0.05">\r
- <when>\r
- <parameter name="FG_TIME" comparison="ge" value="0.25">\r
- <parameter name="FG_TIME" comparison="le" value="0.50">\r
- <set name="FG_AILERON_CMD" type="FG_VALUE" value="0.25"\r
- action="FG_STEP" persistent="false" tc ="0.25">\r
- </when>\r
- <when>\r
- <parameter name="FG_TIME" comparison="ge" value="0.5">\r
- <parameter name="FG_TIME" comparison="le" value="1.5">\r
- <set name="FG_AILERON_CMD" type="FG_DELTA" value="0.5"\r
- action="FG_EXP" persistent="false" tc ="0.5">\r
- </when>\r
- <when>\r
- <parameter name="FG_TIME" comparison="ge" value="1.5">\r
- <parameter name="FG_TIME" comparison="le" value="2.5">\r
- <set name="FG_RUDDER_CMD" type="FG_DELTA" value="0.5"\r
- action="FG_RAMP" persistent="false" tc ="0.5">\r
- </when>\r
- </run>\r
-\r
- </runscript></strong></pre>\r
-\r
- <p>The first line must always be present. The second line\r
- identifies this file as a script file, and gives a descriptive\r
- name to the script file. Comments are next, delineated by the\r
- <!-- and --> symbols. The aircraft and initialization files\r
- to be used are specified in the "use" lines. Next,\r
- comes the "run" section, where the conditions are\r
- described in "when" clauses.</p>\r
-\r
-*/\r
-\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-CLASS DECLARATION\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
-\r
-class FGScript : public FGJSBBase\r
-{\r
-public:\r
- /// Default constructor\r
- FGScript(FGFDMExec* exec);\r
-\r
- /// Default destructor\r
- ~FGScript();\r
-\r
- /** Loads a script to drive JSBSim (usually in standalone mode).\r
- The language is the Simple Script Directives for JSBSim (SSDJ).\r
- @param script the filename (including path name, if any) for the script.\r
- @return true if successful */\r
- bool LoadScript(string script);\r
-\r
- /** This function is called each pass through the executive Run() method IF\r
- scripting is enabled. \r
- @return false if script should exit (i.e. if time limits are violated */\r
- bool RunScript(void);\r
-\r
-private:\r
- enum eAction {\r
- FG_RAMP = 1,\r
- FG_STEP = 2,\r
- FG_EXP = 3\r
- };\r
-\r
- enum eType {\r
- FG_VALUE = 1,\r
- FG_DELTA = 2,\r
- FG_BOOL = 3\r
- };\r
-\r
- struct condition {\r
- vector <eParam> TestParam;\r
- vector <eParam> SetParam;\r
- vector <double> TestValue;\r
- vector <double> SetValue;\r
- vector <string> Comparison;\r
- vector <double> TC;\r
- vector <bool> Persistent;\r
- vector <eAction> Action;\r
- vector <eType> Type;\r
- vector <bool> Triggered;\r
- vector <double> newValue;\r
- vector <double> OriginalValue;\r
- vector <double> StartTime;\r
- vector <double> EndTime;\r
-\r
- condition() {\r
- }\r
- };\r
-\r
- bool Scripted;\r
-\r
- string ScriptName;\r
- double StartTime;\r
- double EndTime;\r
- vector <struct condition> Conditions;\r
-\r
- FGFDMExec* FDMExec;\r
- FGState* State;\r
- void Debug(int from);\r
-};\r
-\r
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-#endif\r
-\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ Header: FGScript.h
+ Author: Jon Berndt
+ Date started: 12/21/2001
+
+ ------------- Copyright (C) 2001 Jon S. Berndt (jsb@hal-pc.org) -------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Further information about the GNU General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+HISTORY
+--------------------------------------------------------------------------------
+12/21/01 JSB Created
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGSCRIPT_HEADER_H
+#define FGSCRIPT_HEADER_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGJSBBase.h"
+#include "FGState.h"
+#include "FGFDMExec.h"
+#include <vector>
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_FGSCRIPT "$Id$"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Encapsulates the JSBSim scripting capability.
+ @author Jon S. Berndt
+ @version $Id$
+
+ <h4>Scripting support provided via FGScript.</h4>
+
+ <p>There is simple scripting support provided in the FGScript
+ class. Commands are specified using the <u>Simple Scripting
+ Directives for JSBSim</u> (SSDJ). The script file is in XML
+ format. A test condition (or conditions) can be set up in the
+ script and when the condition evaluates to true, the specified
+ action[s] is/are taken. A test condition can be <em>persistent</em>,
+ meaning that if a test condition evaluates to true, then passes
+ and evaluates to false, the condition is reset and may again be
+ triggered. When the set of tests evaluates to true for a given
+ condition, an item may be set to another value. This value might
+ be a boolean, a value, or a delta value, and the change from the
+ current value to the new value can be either via a step function,
+ a ramp, or an exponential approach. The speed of a ramp or
+ approach is specified via the time constant. Here is the format
+ of the script file:</p>
+
+ <pre><strong><?xml version="1.0"?>
+ <runscript name="C172-01A">
+
+ <!--
+ This run is for testing C172 runs
+ -->
+
+ <use aircraft="c172">
+ <use initialize="reset00">
+
+ <run start="0.0" end="4.5" dt="0.05">
+ <when>
+ <parameter name="FG_TIME" comparison="ge" value="0.25">
+ <parameter name="FG_TIME" comparison="le" value="0.50">
+ <set name="FG_AILERON_CMD" type="FG_VALUE" value="0.25"
+ action="FG_STEP" persistent="false" tc ="0.25">
+ </when>
+ <when>
+ <parameter name="FG_TIME" comparison="ge" value="0.5">
+ <parameter name="FG_TIME" comparison="le" value="1.5">
+ <set name="FG_AILERON_CMD" type="FG_DELTA" value="0.5"
+ action="FG_EXP" persistent="false" tc ="0.5">
+ </when>
+ <when>
+ <parameter name="FG_TIME" comparison="ge" value="1.5">
+ <parameter name="FG_TIME" comparison="le" value="2.5">
+ <set name="FG_RUDDER_CMD" type="FG_DELTA" value="0.5"
+ action="FG_RAMP" persistent="false" tc ="0.5">
+ </when>
+ </run>
+
+ </runscript></strong></pre>
+
+ <p>The first line must always be present. The second line
+ identifies this file as a script file, and gives a descriptive
+ name to the script file. Comments are next, delineated by the
+ <!-- and --> symbols. The aircraft and initialization files
+ to be used are specified in the "use" lines. Next,
+ comes the "run" section, where the conditions are
+ described in "when" clauses.</p>
+
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGScript : public FGJSBBase
+{
+public:
+ /// Default constructor
+ FGScript(FGFDMExec* exec);
+
+ /// Default destructor
+ ~FGScript();
+
+ /** Loads a script to drive JSBSim (usually in standalone mode).
+ The language is the Simple Script Directives for JSBSim (SSDJ).
+ @param script the filename (including path name, if any) for the script.
+ @return true if successful */
+ bool LoadScript(string script);
+
+ /** This function is called each pass through the executive Run() method IF
+ scripting is enabled.
+ @return false if script should exit (i.e. if time limits are violated */
+ bool RunScript(void);
+
+private:
+ enum eAction {
+ FG_RAMP = 1,
+ FG_STEP = 2,
+ FG_EXP = 3
+ };
+
+ enum eType {
+ FG_VALUE = 1,
+ FG_DELTA = 2,
+ FG_BOOL = 3
+ };
+
+ struct condition {
+ vector <eParam> TestParam;
+ vector <eParam> SetParam;
+ vector <double> TestValue;
+ vector <double> SetValue;
+ vector <string> Comparison;
+ vector <double> TC;
+ vector <bool> Persistent;
+ vector <eAction> Action;
+ vector <eType> Type;
+ vector <bool> Triggered;
+ vector <double> newValue;
+ vector <double> OriginalValue;
+ vector <double> StartTime;
+ vector <double> EndTime;
+
+ condition() {
+ }
+ };
+
+ bool Scripted;
+
+ string ScriptName;
+ double StartTime;
+ double EndTime;
+ vector <struct condition> Conditions;
+
+ FGFDMExec* FDMExec;
+ FGState* State;
+ void Debug(int from);
+};
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+#endif
+