LCOV - code coverage report
Current view: top level - input_output - FGScript.cpp (source / functions) Hit Total Coverage
Test: JSBSim-Coverage-Statistics Lines: 213 264 80.7 %
Date: 2010-08-24 Functions: 8 10 80.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 130 200 65.0 %

           Branch data     Line data    Source code
       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 (jon@jsbsim.org) -------------
       9                 :            : 
      10                 :            :  This program is free software; you can redistribute it and/or modify it under
      11                 :            :  the terms of the GNU Lesser 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 Lesser General Public License for more
      18                 :            :  details.
      19                 :            : 
      20                 :            :  You should have received a copy of the GNU Lesser 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 Lesser 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                 :            : #include "FGScript.h"
      45                 :            : #include "input_output/FGXMLElement.h"
      46                 :            : #include "input_output/FGXMLParse.h"
      47                 :            : #include "initialization/FGTrim.h"
      48                 :            : 
      49                 :            : #include <iostream>
      50                 :            : #include <cstdlib>
      51                 :            : #include <iomanip>
      52                 :            : 
      53                 :            : using namespace std;
      54                 :            : 
      55                 :            : namespace JSBSim {
      56                 :            : 
      57                 :            : static const char *IdSrc = "$Id: FGScript.cpp,v 1.41 2010/07/08 11:36:28 jberndt Exp $";
      58                 :            : static const char *IdHdr = ID_FGSCRIPT;
      59                 :            : 
      60                 :            : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      61                 :            : GLOBAL DECLARATIONS
      62                 :            : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
      63                 :            : 
      64                 :            : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      65                 :            : CLASS IMPLEMENTATION
      66                 :            : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
      67                 :            : 
      68                 :            : // Constructor
      69                 :            : 
      70                 :          1 : FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
      71                 :            : {
      72                 :          1 :   PropertyManager=FDMExec->GetPropertyManager();
      73                 :            : 
      74                 :          1 :   Debug(0);
      75                 :          1 : }
      76                 :            : 
      77                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      78                 :            : 
      79                 :          1 : FGScript::~FGScript()
      80                 :            : {
      81                 :            :   unsigned int i;
      82                 :            : 
      83 [ +  - ][ +  + ]:          8 :   for (i=0; i<local_properties.size(); i++) delete local_properties[i];
         [ #  # ][ #  # ]
      84                 :          1 :   local_properties.clear();
      85                 :            : 
      86 [ +  - ][ +  + ]:         10 :   for (i=0; i<Events.size(); i++) delete Events[i].Condition;
         [ #  # ][ #  # ]
      87                 :          1 :   Events.clear();
      88                 :            : 
      89                 :          1 :   Debug(1);
      90                 :          2 : }
      91                 :            : 
      92                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      93                 :            : 
      94                 :          1 : bool FGScript::LoadScript(string script, double deltaT)
      95                 :            : {
      96                 :          1 :   string aircraft="", initialize="", comparison = "", prop_name="";
      97                 :          1 :   string notifyPropertyName="";
      98                 :          1 :   Element *element=0, *run_element=0, *event_element=0;
      99                 :          1 :   Element *condition_element=0, *set_element=0, *delay_element=0;
     100                 :          1 :   Element *notify_element = 0L, *notify_property_element = 0L;
     101                 :          1 :   Element *property_element = 0L;
     102                 :          1 :   Element *output_element = 0L;
     103                 :          1 :   Element *input_element = 0L;
     104                 :          1 :   bool result = false;
     105                 :          1 :   double dt = 0.0, value = 0.0;
     106                 :            :   struct event *newEvent;
     107                 :            :   FGCondition *newCondition;
     108                 :            : 
     109                 :          2 :   document = LoadXMLDocument(script);
     110                 :            : 
     111         [ -  + ]:          1 :   if (!document) {
     112                 :          0 :     cerr << "File: " << script << " could not be loaded." << endl;
     113                 :          0 :     return false;
     114                 :            :   }
     115                 :            : 
     116                 :            :   // Set up input and output files if specified
     117                 :            :   
     118                 :          1 :   output_element = document->FindElement("output");
     119                 :          1 :   input_element = document->FindElement("input");
     120                 :            : 
     121         [ -  + ]:          2 :   if (document->GetName() != string("runscript")) {
     122                 :          0 :     cerr << "File: " << script << " is not a script file" << endl;
     123                 :          0 :     return false;
     124                 :            :   }
     125                 :            : 
     126                 :          2 :   ScriptName = document->GetAttributeValue("name");
     127                 :            : 
     128                 :            :  // First, find "run" element and set delta T
     129                 :            : 
     130                 :          1 :   run_element = document->FindElement("run");
     131                 :            : 
     132         [ -  + ]:          1 :   if (!run_element) {
     133                 :          0 :     cerr << "No \"run\" element found in script." << endl;
     134                 :          0 :     return false;
     135                 :            :   }
     136                 :            : 
     137                 :            :   // Set sim timing
     138                 :            : 
     139                 :          1 :   StartTime = run_element->GetAttributeValueAsNumber("start");
     140                 :          1 :   FDMExec->Setsim_time(StartTime);
     141                 :          1 :   EndTime   = run_element->GetAttributeValueAsNumber("end");
     142                 :            : 
     143         [ +  - ]:          1 :   if (deltaT == 0.0)
     144                 :          1 :     dt = run_element->GetAttributeValueAsNumber("dt");
     145                 :            :   else {
     146                 :          0 :     dt = deltaT;
     147                 :            :     cout << endl << "Overriding simulation step size from the command line. New step size is: "
     148                 :          0 :          << deltaT << " seconds (" << 1/deltaT << " Hz)" << endl << endl;
     149                 :            :   }
     150                 :            : 
     151                 :          1 :   FDMExec->Setdt(dt);
     152                 :            :   
     153                 :            :   // read aircraft and initialization files
     154                 :            : 
     155                 :          1 :   element = document->FindElement("use");
     156         [ +  - ]:          1 :   if (element) {
     157                 :          2 :     aircraft = element->GetAttributeValue("aircraft");
     158         [ +  - ]:          1 :     if (!aircraft.empty()) {
     159                 :          1 :       result = FDMExec->LoadModel(aircraft);
     160         [ -  + ]:          1 :       if (!result) return false;
     161                 :            :     } else {
     162                 :          0 :       cerr << "Aircraft must be specified in use element." << endl;
     163                 :          0 :       return false;
     164                 :            :     }
     165                 :            : 
     166                 :          2 :     initialize = element->GetAttributeValue("initialize");
     167         [ -  + ]:          1 :     if (initialize.empty()) {
     168                 :          0 :       cerr << "Initialization file must be specified in use element." << endl;
     169                 :          0 :       return false;
     170                 :            :     }
     171                 :            : 
     172                 :            :   } else {
     173                 :          0 :     cerr << "No \"use\" directives in the script file." << endl;
     174                 :          0 :     return false;
     175                 :            :   }
     176                 :            : 
     177                 :            :   // Now, read input spec if given.
     178         [ -  + ]:          1 :   if (input_element > 0) {
     179                 :          0 :     FDMExec->GetInput()->Load(input_element);
     180                 :            :   }
     181                 :            : 
     182                 :            :   // Now, read output spec if given.
     183         [ -  + ]:          1 :   if (output_element > 0) {
     184                 :          0 :     string output_file = output_element->GetAttributeValue("file");
     185         [ #  # ]:          0 :     if (output_file.empty()) {
     186                 :          0 :       cerr << "No logging directives file was specified." << endl;
     187                 :            :     } else {
     188         [ #  # ]:          0 :       if (!FDMExec->SetOutputDirectives(output_file)) return false;
     189                 :          0 :     }
     190                 :            :   }
     191                 :            : 
     192                 :            :   // Read local property/value declarations
     193                 :          1 :   property_element = run_element->FindElement("property");
     194         [ +  + ]:          8 :   while (property_element) {
     195                 :            : 
     196                 :          7 :     double value=0.0;
     197                 :          7 :     string title="";
     198                 :            : 
     199                 :         14 :     title = property_element->GetDataLine();
     200         [ +  + ]:          7 :     if ( ! property_element->GetAttributeValue("value").empty())
     201                 :          6 :       value = property_element->GetAttributeValueAsNumber("value");
     202                 :            : 
     203                 :          7 :     LocalProps *localProp = new LocalProps(value);
     204                 :          7 :     localProp->title = title;
     205                 :          7 :     local_properties.push_back(localProp);
     206         [ +  + ]:          7 :     if (PropertyManager->HasNode(title)) {
     207                 :          6 :       PropertyManager->GetNode(title)->setDoubleValue(value);
     208                 :            :     } else {
     209                 :          1 :       PropertyManager->Tie(localProp->title, localProp->value);
     210                 :            :     }
     211                 :          7 :     property_element = run_element->FindNextElement("property");
     212                 :            :   }
     213                 :            : 
     214                 :            :   // Read "events" from script
     215                 :            : 
     216                 :          1 :   event_element = run_element->FindElement("event");
     217         [ +  + ]:         10 :   while (event_element) { // event processing
     218                 :            : 
     219                 :            :     // Create the event structure
     220                 :          9 :     newEvent = new struct event();
     221                 :            : 
     222                 :            :     // Retrieve the event name if given
     223                 :         18 :     newEvent->Name = event_element->GetAttributeValue("name");
     224                 :            : 
     225                 :            :     // Is this event persistent? That is, does it execute every time the
     226                 :            :     // condition triggers to true, or does it execute as a one-shot event, only?
     227         [ +  + ]:         18 :     if (event_element->GetAttributeValue("persistent") == string("true")) {
     228                 :          1 :       newEvent->Persistent = true;
     229                 :            :     }
     230                 :            : 
     231                 :            :     // Does this event execute continuously when triggered to true?
     232         [ +  + ]:         18 :     if (event_element->GetAttributeValue("continuous") == string("true")) {
     233                 :          1 :       newEvent->Continuous = true;
     234                 :            :     }
     235                 :            : 
     236                 :            :     // Process the conditions
     237                 :          9 :     condition_element = event_element->FindElement("condition");
     238         [ +  - ]:          9 :     if (condition_element != 0) {
     239                 :            :       try {
     240                 :          9 :         newCondition = new FGCondition(condition_element, PropertyManager);
     241                 :          0 :       } catch(string str) {
     242                 :          0 :         cout << endl << fgred << str << reset << endl << endl;
     243                 :          0 :         return false;
     244                 :            :       }
     245                 :          9 :       newEvent->Condition = newCondition;
     246                 :            :     } else {
     247                 :          0 :       cerr << "No condition specified in script event " << newEvent->Name << endl;
     248                 :          0 :       return false;
     249                 :            :     }
     250                 :            : 
     251                 :            :     // Is there a delay between the time this event is triggered, and when the event
     252                 :            :     // actions are executed?
     253                 :            : 
     254                 :          9 :     delay_element = event_element->FindElement("delay");
     255         [ -  + ]:          9 :     if (delay_element) newEvent->Delay = event_element->FindElementValueAsNumber("delay");
     256                 :          9 :     else newEvent->Delay = 0.0;
     257                 :            : 
     258                 :            :     // Notify about when this event is triggered?
     259         [ +  - ]:          9 :     if ((notify_element = event_element->FindElement("notify")) != 0) {
     260                 :          9 :       newEvent->Notify = true;
     261                 :          9 :       notify_property_element = notify_element->FindElement("property");
     262         [ +  + ]:         29 :       while (notify_property_element) {
     263                 :         40 :         notifyPropertyName = notify_property_element->GetDataLine();
     264         [ +  - ]:         20 :         if (PropertyManager->GetNode(notifyPropertyName)) {
     265                 :         20 :           newEvent->NotifyProperties.push_back( PropertyManager->GetNode(notifyPropertyName) );
     266                 :            :         } else {
     267                 :            :           cout << endl << fgred << "  Could not find the property named "
     268                 :            :                << notifyPropertyName << " in script" << endl << "  \""
     269                 :            :                << ScriptName << "\". This unknown property will not be "
     270                 :          0 :                << "echoed for notification." << reset << endl;
     271                 :            :         }
     272                 :         20 :         notify_property_element = notify_element->FindNextElement("property");
     273                 :            :       }
     274                 :            :     }
     275                 :            : 
     276                 :            :     // Read set definitions (these define the actions to be taken when the event is triggered).
     277                 :          9 :     set_element = event_element->FindElement("set");
     278         [ +  + ]:         33 :     while (set_element) {
     279                 :         48 :       prop_name = set_element->GetAttributeValue("name");
     280                 :         24 :       newEvent->SetParam.push_back( PropertyManager->GetNode(prop_name) );
     281                 :            :       //Todo - should probably do some safety checking here to make sure one or the other
     282                 :            :       //of value or function is specified.
     283         [ +  + ]:         24 :       if (!set_element->GetAttributeValue("value").empty()) {
     284                 :         22 :         value = set_element->GetAttributeValueAsNumber("value");
     285                 :         22 :         newEvent->Functions.push_back((FGFunction*)0L);
     286         [ +  - ]:          2 :       } else if (set_element->FindElement("function")) {
     287                 :          2 :         value = 0.0;
     288                 :          4 :         newEvent->Functions.push_back(new FGFunction(PropertyManager, set_element->FindElement("function")));
     289                 :            :       }
     290                 :         24 :       newEvent->SetValue.push_back(value);
     291                 :         24 :       newEvent->OriginalValue.push_back(0.0);
     292                 :         24 :       newEvent->newValue.push_back(0.0);
     293                 :         24 :       newEvent->ValueSpan.push_back(0.0);
     294                 :         24 :       string tempCompare = set_element->GetAttributeValue("type");
     295         [ +  + ]:         24 :       if      (to_lower(tempCompare).find("delta") != string::npos) newEvent->Type.push_back(FG_DELTA);
     296         [ -  + ]:         23 :       else if (to_lower(tempCompare).find("bool") != string::npos)  newEvent->Type.push_back(FG_BOOL);
     297         [ -  + ]:         23 :       else if (to_lower(tempCompare).find("value") != string::npos) newEvent->Type.push_back(FG_VALUE);
     298                 :         23 :       else                                newEvent->Type.push_back(FG_VALUE); // DEFAULT
     299                 :         48 :       tempCompare = set_element->GetAttributeValue("action");
     300         [ -  + ]:         24 :       if      (to_lower(tempCompare).find("ramp") != string::npos) newEvent->Action.push_back(FG_RAMP);
     301         [ -  + ]:         24 :       else if (to_lower(tempCompare).find("step") != string::npos) newEvent->Action.push_back(FG_STEP);
     302         [ +  + ]:         24 :       else if (to_lower(tempCompare).find("exp") != string::npos) newEvent->Action.push_back(FG_EXP);
     303                 :         20 :       else                               newEvent->Action.push_back(FG_STEP); // DEFAULT
     304                 :            : 
     305         [ +  + ]:         24 :       if (!set_element->GetAttributeValue("tc").empty())
     306                 :          4 :         newEvent->TC.push_back(set_element->GetAttributeValueAsNumber("tc"));
     307                 :            :       else
     308                 :         20 :         newEvent->TC.push_back(1.0); // DEFAULT
     309                 :            : 
     310                 :         24 :       newEvent->Transiting.push_back(false);
     311                 :            : 
     312                 :         24 :       set_element = event_element->FindNextElement("set");
     313                 :            :     }
     314                 :          9 :     Events.push_back(*newEvent);
     315         [ +  - ]:          9 :     delete newEvent;
     316                 :            : 
     317                 :          9 :     event_element = run_element->FindNextElement("event");
     318                 :            :   }
     319                 :            : 
     320                 :          1 :   Debug(4);
     321                 :            : 
     322                 :          2 :   FGInitialCondition *IC=FDMExec->GetIC();
     323         [ -  + ]:          1 :   if ( ! IC->Load( initialize )) {
     324                 :          0 :     cerr << "Initialization unsuccessful" << endl;
     325                 :          0 :     exit(-1);
     326                 :            :   }
     327                 :            : 
     328                 :          1 :   return true;
     329                 :            : }
     330                 :            : 
     331                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     332                 :            : 
     333                 :      54004 : bool FGScript::RunScript(void)
     334                 :            : {
     335                 :            :   unsigned i, j;
     336                 :      54004 :   unsigned event_ctr = 0;
     337                 :            : 
     338                 :     108008 :   double currentTime = FDMExec->GetSimTime();
     339                 :      54004 :   double newSetValue = 0;
     340                 :            : 
     341         [ +  + ]:      54004 :   if (currentTime > EndTime) return false; //Script done!
     342                 :            : 
     343                 :            :   // Iterate over all events.
     344         [ +  + ]:     540030 :   for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) {
     345                 :            :     // Determine whether the set of conditional tests for this condition equate
     346                 :            :     // to true and should cause the event to execute. If the conditions evaluate 
     347                 :            :     // to true, then the event is triggered. If the event is not persistent,
     348                 :            :     // then this trigger will remain set true. If the event is persistent,
     349                 :            :     // the trigger will reset to false when the condition evaluates to false.
     350         [ +  + ]:     486027 :     if (Events[ev_ctr].Condition->Evaluate()) {
     351         [ +  + ]:     280142 :       if (!Events[ev_ctr].Triggered) {
     352                 :            : 
     353                 :            :         // The conditions are true, do the setting of the desired Event parameters
     354         [ +  + ]:        112 :         for (i=0; i<Events[ev_ctr].SetValue.size(); i++) {
     355                 :         61 :           Events[ev_ctr].OriginalValue[i] = Events[ev_ctr].SetParam[i]->getDoubleValue();
     356         [ -  + ]:         61 :           if (Events[ev_ctr].Functions[i] != 0) { // Parameter should be set to a function value
     357                 :          0 :             Events[ev_ctr].SetValue[i] = Events[ev_ctr].Functions[i]->GetValue();
     358                 :            :           }
     359      [ +  +  - ]:         61 :           switch (Events[ev_ctr].Type[i]) {
     360                 :            :           case FG_VALUE:
     361                 :            :           case FG_BOOL:
     362                 :         80 :             Events[ev_ctr].newValue[i] = Events[ev_ctr].SetValue[i];
     363                 :         16 :             break;
     364                 :            :           case FG_DELTA:
     365                 :        315 :             Events[ev_ctr].newValue[i] = Events[ev_ctr].OriginalValue[i] + Events[ev_ctr].SetValue[i];
     366                 :         45 :             break;
     367                 :            :           default:
     368                 :          0 :             cerr << "Invalid Type specified" << endl;
     369                 :            :             break;
     370                 :            :           }
     371                 :        183 :           Events[ev_ctr].StartTime = currentTime + Events[ev_ctr].Delay;
     372                 :        427 :           Events[ev_ctr].ValueSpan[i] = Events[ev_ctr].newValue[i] - Events[ev_ctr].OriginalValue[i];
     373                 :         61 :           Events[ev_ctr].Transiting[i] = true;
     374                 :            :         }
     375                 :            :       }
     376                 :     280142 :       Events[ev_ctr].Triggered = true;
     377                 :            : 
     378         [ +  + ]:     205885 :     } else if (Events[ev_ctr].Persistent) { // If the event is persistent, reset the trigger.
     379                 :            : 
     380                 :     107916 :       Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events
     381                 :      53958 :       Events[ev_ctr].Notified = false;  // Also reset the notification flag
     382                 :            :     }
     383                 :            : 
     384 [ +  - ][ +  + ]:     486027 :     if ((currentTime >= Events[ev_ctr].StartTime) && Events[ev_ctr].Triggered) {
                 [ +  + ]
     385                 :            : 
     386         [ +  + ]:    1087654 :       for (i=0; i<Events[ev_ctr].SetValue.size(); i++) {
     387         [ +  + ]:     803976 :         if (Events[ev_ctr].Transiting[i]) {
     388                 :     639555 :           Events[ev_ctr].TimeSpan = currentTime - Events[ev_ctr].StartTime;
     389   [ -  +  +  - ]:     213185 :           switch (Events[ev_ctr].Action[i]) {
     390                 :            :           case FG_RAMP:
     391         [ #  # ]:          0 :             if (Events[ev_ctr].TimeSpan <= Events[ev_ctr].TC[i]) {
     392                 :          0 :               newSetValue = Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i];
     393                 :            :             } else {
     394                 :          0 :               newSetValue = Events[ev_ctr].newValue[i];
     395         [ #  # ]:          0 :               if (Events[ev_ctr].Continuous != true) Events[ev_ctr].Transiting[i] = false;
     396                 :            :             }
     397                 :            :             break;
     398                 :            :           case FG_STEP:
     399                 :        171 :             newSetValue = Events[ev_ctr].newValue[i];
     400                 :            : 
     401                 :            :             // If this is not a continuous event, reset the transiting flag.
     402                 :            :             // Otherwise, it is known that the event is a continuous event.
     403                 :            :             // Furthermore, if the event is to be determined by a function,
     404                 :            :             // then the function will be continuously calculated.
     405         [ +  - ]:         57 :             if (Events[ev_ctr].Continuous != true)
     406                 :         57 :               Events[ev_ctr].Transiting[i] = false;
     407         [ #  # ]:          0 :             else if (Events[ev_ctr].Functions[i] != 0)
     408                 :          0 :               newSetValue = Events[ev_ctr].Functions[i]->GetValue();
     409                 :            : 
     410                 :            :             break;
     411                 :            :           case FG_EXP:
     412                 :     213128 :             newSetValue = (1 - exp( -Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] )) * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i];
     413                 :     213128 :             break;
     414                 :            :           default:
     415                 :          0 :             cerr << "Invalid Action specified" << endl;
     416                 :            :             break;
     417                 :            :           }
     418                 :     213185 :           Events[ev_ctr].SetParam[i]->setDoubleValue(newSetValue);
     419                 :            :         }
     420                 :            :       }
     421                 :            : 
     422                 :            :       // Print notification values after setting them
     423 [ +  - ][ +  + ]:     283678 :       if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) {
                 [ +  + ]
     424                 :            :         cout << endl << "  Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
     425                 :        102 :              << " executed at time: " << currentTime << endl;
     426         [ +  + ]:        951 :         for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) {
     427                 :            :           cout << "    " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
     428                 :       1800 :                << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
     429                 :            :         }
     430                 :            :         cout << endl;
     431                 :         51 :         Events[ev_ctr].Notified = true;
     432                 :            :       }
     433                 :            : 
     434                 :            :     }
     435                 :            : 
     436                 :     486027 :     event_ctr++;
     437                 :            :   }
     438                 :      54004 :   return true;
     439                 :            : }
     440                 :            : 
     441                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     442                 :            : //    The bitmasked value choices are as follows:
     443                 :            : //    unset: In this case (the default) JSBSim would only print
     444                 :            : //       out the normally expected messages, essentially echoing
     445                 :            : //       the config files as they are read. If the environment
     446                 :            : //       variable is not set, debug_lvl is set to 1 internally
     447                 :            : //    0: This requests JSBSim not to output any messages
     448                 :            : //       whatsoever.
     449                 :            : //    1: This value explicity requests the normal JSBSim
     450                 :            : //       startup messages
     451                 :            : //    2: This value asks for a message to be printed out when
     452                 :            : //       a class is instantiated
     453                 :            : //    4: When this value is set, a message is displayed when a
     454                 :            : //       FGModel object executes its Run() method
     455                 :            : //    8: When this value is set, various runtime state variables
     456                 :            : //       are printed out periodically
     457                 :            : //    16: When set various parameters are sanity checked and
     458                 :            : //       a message is printed out when they go out of bounds
     459                 :            : 
     460                 :          3 : void FGScript::Debug(int from)
     461                 :            : {
     462         [ +  - ]:          3 :   if (debug_lvl <= 0) return;
     463                 :            : 
     464         [ +  - ]:          3 :   if (debug_lvl & 1) { // Standard console startup message output
     465         [ +  + ]:          3 :     if (from == 0) { // Constructor
     466         [ +  - ]:          2 :     } else if (from == 3) {
     467         [ +  + ]:          2 :     } else if (from == 4)  { // print out script data
     468                 :            :       cout << endl;
     469                 :          1 :       cout << "Script: \"" << ScriptName << "\"" << endl;
     470                 :            :       cout << "  begins at " << StartTime << " seconds and runs to " << EndTime
     471                 :            :         << " seconds with dt = " << setprecision(6) << FDMExec->GetDeltaT() << " (" <<
     472                 :          5 :         ceil(1.0/FDMExec->GetDeltaT()) << " Hz)" << endl;
     473                 :            :       cout << endl;
     474                 :            : 
     475         [ +  + ]:          8 :       for (unsigned int i=0; i<local_properties.size(); i++) {
     476                 :            :         cout << "Local property: " << local_properties[i]->title 
     477                 :            :              << " = " << PropertyManager->GetNode(local_properties[i]->title)->getDoubleValue()
     478                 :          7 :              << endl;
     479                 :            :       }
     480                 :            :       
     481         [ +  - ]:          1 :       if (local_properties.size() > 0) cout << endl;
     482                 :            : 
     483         [ +  + ]:         10 :       for (unsigned i=0; i<Events.size(); i++) {
     484                 :          9 :         cout << "Event " << i;
     485         [ +  - ]:          9 :         if (!Events[i].Name.empty()) cout << " (" << Events[i].Name << ")";
     486                 :          9 :         cout << ":" << endl;
     487                 :            : 
     488         [ +  + ]:          9 :         if (Events[i].Persistent)
     489                 :          1 :           cout << "  " << "Always executes";
     490                 :            :         else
     491                 :          8 :           cout << "  " << "Executes once";
     492                 :            : 
     493                 :          9 :         Events[i].Condition->PrintCondition();
     494                 :            : 
     495                 :          9 :         cout << endl << "  Actions taken";
     496         [ -  + ]:          9 :         if (Events[i].Delay > 0.0)
     497                 :          0 :           cout << " (after a delay of " << Events[i].Delay << " secs)";
     498                 :         18 :         cout << ":" << endl << "    {";
     499         [ +  + ]:         33 :         for (unsigned j=0; j<Events[i].SetValue.size(); j++) {
     500 [ +  + ][ +  + ]:         24 :           if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) {
                 [ +  + ]
     501         [ -  + ]:          2 :             if (Events[i].SetParam[j] == 0) {
     502                 :            :               cerr << fgred << highint << endl
     503                 :            :                    << "  An attempt has been made to access a non-existent property" << endl
     504                 :            :                    << "  in this event. Please check the property names used, spelling, etc."
     505                 :          0 :                    << reset << endl;
     506                 :          0 :               exit(-1);
     507                 :            :             }
     508                 :            :             cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
     509                 :          4 :                  << " to function value";
     510                 :            :           } else {
     511         [ -  + ]:         22 :             if (Events[i].SetParam[j] == 0) {
     512                 :            :               cerr << fgred << highint << endl
     513                 :            :                    << "  An attempt has been made to access a non-existent property" << endl
     514                 :            :                    << "  in this event. Please check the property names used, spelling, etc."
     515                 :          0 :                    << reset << endl;
     516                 :          0 :               exit(-1);
     517                 :            :             }
     518                 :            :             cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
     519                 :         66 :                  << " to " << Events[i].SetValue[j];
     520                 :            :           }
     521                 :            : 
     522      [ +  +  - ]:         24 :           switch (Events[i].Type[j]) {
     523                 :            :           case FG_VALUE:
     524                 :            :           case FG_BOOL:
     525                 :         23 :             cout << " (constant";
     526                 :         23 :             break;
     527                 :            :           case FG_DELTA:
     528                 :          1 :             cout << " (delta";
     529                 :          1 :             break;
     530                 :            :           default:
     531                 :          0 :             cout << " (unspecified type";
     532                 :            :           }
     533                 :            : 
     534   [ -  +  +  - ]:         24 :           switch (Events[i].Action[j]) {
     535                 :            :           case FG_RAMP:
     536                 :          0 :             cout << " via ramp";
     537                 :          0 :             break;
     538                 :            :           case FG_STEP:
     539                 :         20 :             cout << " via step)";
     540                 :         20 :             break;
     541                 :            :           case FG_EXP:
     542                 :          4 :             cout << " via exponential approach";
     543                 :          4 :             break;
     544                 :            :           default:
     545                 :          0 :             cout << " via unspecified action)";
     546                 :            :           }
     547                 :            : 
     548 [ +  - ][ +  + ]:         24 :           if (Events[i].Action[j] == FG_RAMP || Events[i].Action[j] == FG_EXP)
                 [ +  + ]
     549                 :          8 :             cout << " with time constant " << Events[i].TC[j] << ")";
     550                 :            :         }
     551                 :          9 :         cout << endl << "    }" << endl;
     552                 :            : 
     553                 :            :         // Print notifications
     554         [ +  - ]:          9 :         if (Events[i].Notify) {
     555         [ +  + ]:          9 :           if (Events[i].NotifyProperties.size() > 0) {
     556                 :          2 :             cout << "  Notifications" << ":" << endl << "    {" << endl;
     557         [ +  + ]:         21 :             for (unsigned j=0; j<Events[i].NotifyProperties.size();j++) {
     558                 :            :               cout << "      "
     559                 :            :                    << Events[i].NotifyProperties[j]->GetRelativeName("/fdm/jsbsim/")
     560                 :         40 :                    << endl;
     561                 :            :             }
     562                 :          1 :             cout << "    }" << endl;
     563                 :            :           }
     564                 :            :         }
     565                 :            :         cout << endl;
     566                 :            :       }
     567                 :            :     }
     568                 :            :   }
     569         [ -  + ]:          3 :   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
     570         [ #  # ]:          0 :     if (from == 0) cout << "Instantiated: FGScript" << endl;
     571         [ #  # ]:          0 :     if (from == 1) cout << "Destroyed:    FGScript" << endl;
     572                 :            :   }
     573                 :          3 :   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
     574                 :            :   }
     575                 :          3 :   if (debug_lvl & 8 ) { // Runtime state variables
     576                 :            :   }
     577                 :          3 :   if (debug_lvl & 16) { // Sanity checking
     578                 :            :   }
     579         [ -  + ]:          3 :   if (debug_lvl & 64) {
     580         [ #  # ]:          0 :     if (from == 0) { // Constructor
     581                 :          0 :       cout << IdSrc << endl;
     582                 :          0 :       cout << IdHdr << endl;
     583                 :            :     }
     584                 :            :   }
     585                 :            : }
     586 [ +  + ][ +  - ]:         12 : }

Generated by: LCOV version 1.9