]> git.mxchange.org Git - flightgear.git/blobdiff - src/FDM/JSBSim/input_output/FGScript.cpp
Merge branch 'next' of D:\Git_New\flightgear into next
[flightgear.git] / src / FDM / JSBSim / input_output / FGScript.cpp
index 9ea8a91860a391147c9180497c2c25e3dcf9375f..60d39ed9bdb39f5c1afecdfc1b686b996836ad28 100755 (executable)
@@ -5,7 +5,7 @@
  Date started: 12/21/01
  Purpose:      Loads and runs JSBSim scripts.
 
- ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
+ ------------- Copyright (C) 1999  Jon S. Berndt (jon@jsbsim.org) -------------
 
  This program is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the Free Software
@@ -42,14 +42,19 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGScript.h"
-#include <input_output/FGXMLParse.h>
-#include <initialization/FGTrim.h>
+#include "input_output/FGXMLElement.h"
+#include "input_output/FGXMLParse.h"
+#include "initialization/FGTrim.h"
 
 #include <iostream>
+#include <cstdlib>
+#include <iomanip>
+
+using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGScript.cpp,v 1.46 2011/02/18 12:44:16 jberndt Exp $";
 static const char *IdHdr = ID_FGSCRIPT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -64,8 +69,8 @@ CLASS IMPLEMENTATION
 
 FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
 {
-  State = FDMExec->GetState();
   PropertyManager=FDMExec->GetPropertyManager();
+
   Debug(0);
 }
 
@@ -73,12 +78,19 @@ FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
 
 FGScript::~FGScript()
 {
-  unsigned int i;
+  unsigned int i, j;
 
-  for (i=0; i<local_properties.size(); i++) delete local_properties[i];
+  for (i=0; i<local_properties.size(); i++) {
+    delete local_properties[i]->value;
+    delete local_properties[i];
+  }
   local_properties.clear();
 
-  for (i=0; i<Events.size(); i++) delete Events[i].Condition;
+  for (i=0; i<Events.size(); i++) {
+    delete Events[i].Condition;
+    for (j=0; j<Events[i].Functions.size(); j++)
+      delete Events[i].Functions[j];
+  }
   Events.clear();
 
   Debug(1);
@@ -86,7 +98,7 @@ FGScript::~FGScript()
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGScript::LoadScript( string script )
+bool FGScript::LoadScript(string script, double deltaT)
 {
   string aircraft="", initialize="", comparison = "", prop_name="";
   string notifyPropertyName="";
@@ -132,10 +144,20 @@ bool FGScript::LoadScript( string script )
   // Set sim timing
 
   StartTime = run_element->GetAttributeValueAsNumber("start");
-  State->Setsim_time(StartTime);
+  FDMExec->Setsim_time(StartTime);
   EndTime   = run_element->GetAttributeValueAsNumber("end");
-  dt        = run_element->GetAttributeValueAsNumber("dt");
-  State->Setdt(dt);
+  // Make sure that the desired time is reached and executed.
+  EndTime += 0.99*FDMExec->GetDeltaT();
+
+  if (deltaT == 0.0)
+    dt = run_element->GetAttributeValueAsNumber("dt");
+  else {
+    dt = deltaT;
+    cout << endl << "Overriding simulation step size from the command line. New step size is: "
+         << deltaT << " seconds (" << 1/deltaT << " Hz)" << endl << endl;
+  }
+
+  FDMExec->Setdt(dt);
   
   // read aircraft and initialization files
 
@@ -172,7 +194,7 @@ bool FGScript::LoadScript( string script )
     if (output_file.empty()) {
       cerr << "No logging directives file was specified." << endl;
     } else {
-      FDMExec->SetOutputDirectives(output_file);
+      if (!FDMExec->SetOutputDirectives(output_file)) return false;
     }
   }
 
@@ -181,14 +203,20 @@ bool FGScript::LoadScript( string script )
   while (property_element) {
 
     double value=0.0;
+    string title="";
+
+    title = property_element->GetDataLine();
     if ( ! property_element->GetAttributeValue("value").empty())
       value = property_element->GetAttributeValueAsNumber("value");
 
     LocalProps *localProp = new LocalProps(value);
-    localProp->title = property_element->GetDataLine();
+    localProp->title = title;
     local_properties.push_back(localProp);
-
-    PropertyManager->Tie(localProp->title, (local_properties.back())->value);
+    if (PropertyManager->HasNode(title)) {
+      PropertyManager->GetNode(title)->setDoubleValue(value);
+    } else {
+      PropertyManager->Tie(localProp->title, localProp->value);
+    }
     property_element = run_element->FindNextElement("property");
   }
 
@@ -217,10 +245,17 @@ bool FGScript::LoadScript( string script )
     // Process the conditions
     condition_element = event_element->FindElement("condition");
     if (condition_element != 0) {
-      newCondition = new FGCondition(condition_element, PropertyManager);
+      try {
+        newCondition = new FGCondition(condition_element, PropertyManager);
+      } catch(string str) {
+        cout << endl << fgred << str << reset << endl << endl;
+        delete newEvent;
+        return false;
+      }
       newEvent->Condition = newCondition;
     } else {
       cerr << "No condition specified in script event " << newEvent->Name << endl;
+      delete newEvent;
       return false;
     }
 
@@ -234,16 +269,30 @@ bool FGScript::LoadScript( string script )
     // Notify about when this event is triggered?
     if ((notify_element = event_element->FindElement("notify")) != 0) {
       newEvent->Notify = true;
+      // Check here for new <description> tag that gets echoed
+      string notify_description = notify_element->FindElementValue("description");
+      if (!notify_description.empty()) {
+        newEvent->Description = notify_description;
+      }
       notify_property_element = notify_element->FindElement("property");
       while (notify_property_element) {
         notifyPropertyName = notify_property_element->GetDataLine();
         if (PropertyManager->GetNode(notifyPropertyName)) {
           newEvent->NotifyProperties.push_back( PropertyManager->GetNode(notifyPropertyName) );
+          string caption_attribute = notify_property_element->GetAttributeValue("caption");
+          if (caption_attribute.empty()) {
+            newEvent->DisplayString.push_back(notifyPropertyName);
+          } else {
+            newEvent->DisplayString.push_back(caption_attribute);
+          }
         } else {
           cout << endl << fgred << "  Could not find the property named "
                << notifyPropertyName << " in script" << endl << "  \""
-               << ScriptName << "\". This unknown property will not be "
-               << "echoed for notification." << reset << endl;
+               << ScriptName << "\". Execution is aborted. Please recheck "
+               << "your input files and scripts." << reset << endl;
+          delete newEvent->Condition;
+          delete newEvent;
+          return false;
         }
         notify_property_element = notify_element->FindNextElement("property");
       }
@@ -268,14 +317,14 @@ bool FGScript::LoadScript( string script )
       newEvent->newValue.push_back(0.0);
       newEvent->ValueSpan.push_back(0.0);
       string tempCompare = set_element->GetAttributeValue("type");
-      if      (tempCompare == "FG_DELTA") newEvent->Type.push_back(FG_DELTA);
-      else if (tempCompare == "FG_BOOL")  newEvent->Type.push_back(FG_BOOL);
-      else if (tempCompare == "FG_VALUE") newEvent->Type.push_back(FG_VALUE);
+      if      (to_lower(tempCompare).find("delta") != string::npos) newEvent->Type.push_back(FG_DELTA);
+      else if (to_lower(tempCompare).find("bool") != string::npos)  newEvent->Type.push_back(FG_BOOL);
+      else if (to_lower(tempCompare).find("value") != string::npos) newEvent->Type.push_back(FG_VALUE);
       else                                newEvent->Type.push_back(FG_VALUE); // DEFAULT
       tempCompare = set_element->GetAttributeValue("action");
-      if      (tempCompare == "FG_RAMP") newEvent->Action.push_back(FG_RAMP);
-      else if (tempCompare == "FG_STEP") newEvent->Action.push_back(FG_STEP);
-      else if (tempCompare == "FG_EXP")  newEvent->Action.push_back(FG_EXP);
+      if      (to_lower(tempCompare).find("ramp") != string::npos) newEvent->Action.push_back(FG_RAMP);
+      else if (to_lower(tempCompare).find("step") != string::npos) newEvent->Action.push_back(FG_STEP);
+      else if (to_lower(tempCompare).find("exp") != string::npos) newEvent->Action.push_back(FG_EXP);
       else                               newEvent->Action.push_back(FG_STEP); // DEFAULT
 
       if (!set_element->GetAttributeValue("tc").empty())
@@ -311,10 +360,10 @@ bool FGScript::RunScript(void)
   unsigned i, j;
   unsigned event_ctr = 0;
 
-  double currentTime = State->Getsim_time();
+  double currentTime = FDMExec->GetSimTime();
   double newSetValue = 0;
 
-  if (currentTime > EndTime) return false; //Script done!
+  if (currentTime > EndTime) return false;
 
   // Iterate over all events.
   for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) {
@@ -352,7 +401,9 @@ bool FGScript::RunScript(void)
       Events[ev_ctr].Triggered = true;
 
     } else if (Events[ev_ctr].Persistent) { // If the event is persistent, reset the trigger.
-
+      Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events
+      Events[ev_ctr].Notified = false;  // Also reset the notification flag
+    } else if (Events[ev_ctr].Continuous) { // If the event is continuous, reset the trigger.
       Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events
       Events[ev_ctr].Notified = false;  // Also reset the notification flag
     }
@@ -399,8 +450,12 @@ bool FGScript::RunScript(void)
       if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) {
         cout << endl << "  Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
              << " executed at time: " << currentTime << endl;
+        if (!Events[ev_ctr].Description.empty()) {
+          cout << "    " << Events[ev_ctr].Description << endl;
+        }
         for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) {
-          cout << "    " << Events[ev_ctr].NotifyProperties[j]->GetName()
+//          cout << "    " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
+          cout << "    " << Events[ev_ctr].DisplayString[j]
                << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
         }
         cout << endl;
@@ -444,22 +499,36 @@ void FGScript::Debug(int from)
       cout << endl;
       cout << "Script: \"" << ScriptName << "\"" << endl;
       cout << "  begins at " << StartTime << " seconds and runs to " << EndTime
-           << " seconds with dt = " << State->Getdt() << endl;
+        << " seconds with dt = " << setprecision(6) << FDMExec->GetDeltaT() << " (" <<
+        ceil(1.0/FDMExec->GetDeltaT()) << " Hz)" << endl;
       cout << endl;
 
+      for (unsigned int i=0; i<local_properties.size(); i++) {
+        cout << "Local property: " << local_properties[i]->title 
+             << " = " << PropertyManager->GetNode(local_properties[i]->title)->getDoubleValue()
+             << endl;
+      }
+      
+      if (local_properties.size() > 0) cout << endl;
+
       for (unsigned i=0; i<Events.size(); i++) {
         cout << "Event " << i;
         if (!Events[i].Name.empty()) cout << " (" << Events[i].Name << ")";
         cout << ":" << endl;
 
         if (Events[i].Persistent)
-          cout << "  " << "Always executes";
+          cout << "  " << "Whenever triggered, executes once";
+        else if (Events[i].Continuous)
+          cout << "  " << "While true, always executes";
         else
-          cout << "  " << "Executes once";
+          cout << "  " << "When first triggered, executes once";
 
         Events[i].Condition->PrintCondition();
 
-        cout << endl << "  Actions taken:" << endl << "    {";
+        cout << endl << "  Actions taken";
+        if (Events[i].Delay > 0.0)
+          cout << " (after a delay of " << Events[i].Delay << " secs)";
+        cout << ":" << endl << "    {";
         for (unsigned j=0; j<Events[i].SetValue.size(); j++) {
           if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) {
             if (Events[i].SetParam[j] == 0) {
@@ -469,7 +538,7 @@ void FGScript::Debug(int from)
                    << reset << endl;
               exit(-1);
             }
-            cout << endl << "      set " << Events[i].SetParam[j]->GetName()
+            cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
                  << " to function value";
           } else {
             if (Events[i].SetParam[j] == 0) {
@@ -479,7 +548,7 @@ void FGScript::Debug(int from)
                    << reset << endl;
               exit(-1);
             }
-            cout << endl << "      set " << Events[i].SetParam[j]->GetName()
+            cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
                  << " to " << Events[i].SetValue[j];
           }
 
@@ -512,8 +581,21 @@ void FGScript::Debug(int from)
           if (Events[i].Action[j] == FG_RAMP || Events[i].Action[j] == FG_EXP)
             cout << " with time constant " << Events[i].TC[j] << ")";
         }
-        cout << endl << "    }" << endl << endl;
-
+        cout << endl << "    }" << endl;
+
+        // Print notifications
+        if (Events[i].Notify) {
+          if (Events[i].NotifyProperties.size() > 0) {
+            cout << "  Notifications" << ":" << endl << "    {" << endl;
+            for (unsigned j=0; j<Events[i].NotifyProperties.size();j++) {
+              cout << "      "
+                  << Events[i].NotifyProperties[j]->GetRelativeName("/fdm/jsbsim/")
+                   << endl;
+            }
+            cout << "    }" << endl;
+          }
+        }
+        cout << endl;
       }
     }
   }