From 88cb2d13f061a6206c59b216977b44c73b73fe73 Mon Sep 17 00:00:00 2001 From: david <david> Date: Sat, 19 Jan 2002 21:50:31 +0000 Subject: [PATCH] Latest JSBSim changes. --- src/FDM/JSBSim/FGScript.cpp | 828 ++++++++++++++++++------------------ src/FDM/JSBSim/FGScript.h | 398 ++++++++--------- 2 files changed, 613 insertions(+), 613 deletions(-) diff --git a/src/FDM/JSBSim/FGScript.cpp b/src/FDM/JSBSim/FGScript.cpp index 34e7b9f14..19a105039 100644 --- a/src/FDM/JSBSim/FGScript.cpp +++ b/src/FDM/JSBSim/FGScript.cpp @@ -1,414 +1,414 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - 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; - } - } -} - +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + 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; + } + } +} + diff --git a/src/FDM/JSBSim/FGScript.h b/src/FDM/JSBSim/FGScript.h index df39f1eb3..d1ccc88a6 100644 --- a/src/FDM/JSBSim/FGScript.h +++ b/src/FDM/JSBSim/FGScript.h @@ -1,199 +1,199 @@ -/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - 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 - +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + 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 +