]> git.mxchange.org Git - flightgear.git/commitdiff
Initial revision.
authorcurt <curt>
Sat, 22 Dec 2001 17:39:21 +0000 (17:39 +0000)
committercurt <curt>
Sat, 22 Dec 2001 17:39:21 +0000 (17:39 +0000)
src/FDM/JSBSim/FGScript.cpp [new file with mode: 0644]
src/FDM/JSBSim/FGScript.h [new file with mode: 0644]

diff --git a/src/FDM/JSBSim/FGScript.cpp b/src/FDM/JSBSim/FGScript.cpp
new file mode 100644 (file)
index 0000000..690d5ab
--- /dev/null
@@ -0,0 +1,409 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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
+  unsigned i;\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
+}\r
+\r
diff --git a/src/FDM/JSBSim/FGScript.h b/src/FDM/JSBSim/FGScript.h
new file mode 100644 (file)
index 0000000..df39f1e
--- /dev/null
@@ -0,0 +1,199 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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>&lt;?xml version=&quot;1.0&quot;?&gt;\r
+    &lt;runscript name=&quot;C172-01A&quot;&gt;\r
+\r
+    &lt;!--\r
+    This run is for testing C172 runs\r
+    --&gt;\r
+\r
+    &lt;use aircraft=&quot;c172&quot;&gt;\r
+    &lt;use initialize=&quot;reset00&quot;&gt;\r
+\r
+    &lt;run start=&quot;0.0&quot; end=&quot;4.5&quot; dt=&quot;0.05&quot;&gt;\r
+      &lt;when&gt;\r
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;ge&quot; value=&quot;0.25&quot;&gt;\r
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;le&quot; value=&quot;0.50&quot;&gt;\r
+        &lt;set name=&quot;FG_AILERON_CMD&quot; type=&quot;FG_VALUE&quot; value=&quot;0.25&quot;\r
+        action=&quot;FG_STEP&quot; persistent=&quot;false&quot; tc =&quot;0.25&quot;&gt;\r
+      &lt;/when&gt;\r
+      &lt;when&gt;\r
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;ge&quot; value=&quot;0.5&quot;&gt;\r
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;le&quot; value=&quot;1.5&quot;&gt;\r
+        &lt;set name=&quot;FG_AILERON_CMD&quot; type=&quot;FG_DELTA&quot; value=&quot;0.5&quot;\r
+        action=&quot;FG_EXP&quot; persistent=&quot;false&quot; tc =&quot;0.5&quot;&gt;\r
+      &lt;/when&gt;\r
+      &lt;when&gt;\r
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;ge&quot; value=&quot;1.5&quot;&gt;\r
+        &lt;parameter name=&quot;FG_TIME&quot; comparison=&quot;le&quot; value=&quot;2.5&quot;&gt;\r
+        &lt;set name=&quot;FG_RUDDER_CMD&quot; type=&quot;FG_DELTA&quot; value=&quot;0.5&quot;\r
+        action=&quot;FG_RAMP&quot; persistent=&quot;false&quot; tc =&quot;0.5&quot;&gt;\r
+      &lt;/when&gt;\r
+    &lt;/run&gt;\r
+\r
+    &lt;/runscript&gt;</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
+    &lt;!-- and --&gt; symbols. The aircraft and initialization files\r
+    to be used are specified in the &quot;use&quot; lines. Next,\r
+    comes the &quot;run&quot; section, where the conditions are\r
+    described in &quot;when&quot; 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