1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 Header: FGScript.h 3 Author: Jon Berndt 4 Date started: 12/21/2001 5 6 ------------- Copyright (C) 2001 Jon S. Berndt (jon@jsbsim.org) ------------- 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU Lesser General Public License as published by the Free Software 10 Foundation; either version 2 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 16 details. 17 18 You should have received a copy of the GNU Lesser General Public License along with 19 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 20 Place - Suite 330, Boston, MA 02111-1307, USA. 21 22 Further information about the GNU Lesser General Public License can also be found on 23 the world wide web at http://www.gnu.org. 24 25 HISTORY 26 -------------------------------------------------------------------------------- 27 12/21/01 JSB Created 28 29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 SENTRY 31 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 32 33 #ifndef FGSCRIPT_HEADER_H 34 #define FGSCRIPT_HEADER_H 35 36 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37 INCLUDES 38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 39 40 #include <vector> 41 #include <map> 42 43 #include "FGJSBBase.h" 44 #include "FGPropertyReader.h" 45 #include "input_output/FGPropertyManager.h" 46 #include "simgear/misc/sg_path.hxx" 47 48 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 49 FORWARD DECLARATIONS 50 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 51 52 namespace JSBSim { 53 54 class FGFDMExec; 55 class FGCondition; 56 class FGFunction; 57 class FGPropertyValue; 58 59 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 60 CLASS DOCUMENTATION 61 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 62 63 /** Encapsulates the JSBSim scripting capability. 64 <h4>Scripting support provided via FGScript.</h4> 65 66 <p>There is support for scripting provided in the FGScript 67 class. Commands are specified using the <em>Scripting 68 Directives for JSBSim</em>. The script file is in XML 69 format. A test condition (or conditions) can be set up in an event in a 70 script and when the condition evaluates to true, the specified 71 action[s] is/are taken. An event can be <em>persistent</em>, 72 meaning that at every time the test condition first evaluates to true 73 (toggling from false to true) then the specified <em>set</em> actions take 74 place. An event can also be defined to execute or evaluate continuously 75 while the condition is true. When the set of tests evaluates to true for a given 76 condition, an item may be set to another value. This value may 77 be a value, or a delta value, and the change from the 78 current value to the new value can be either via a step action, 79 a ramp, or an exponential approach. The speed of a ramp or exponential 80 approach is specified via the time constant. Here is an example 81 illustrating the format of the script file: 82 83 @code 84 <?xml version="1.0"?> 85 <runscript name="C172-01A takeoff run"> 86 <!-- 87 This run is for testing the C172 altitude hold autopilot 88 --> 89 90 <use aircraft="c172x"/> 91 <use initialize="reset00"/> 92 <run start="0.0" end="3000" dt="0.0083333"> 93 94 <event name="engine start"> 95 <notify/> 96 <condition> 97 sim-time-sec >= 0.25 98 </condition> 99 <set name="fcs/throttle-cmd-norm" value="1.0" action="FG_RAMP" tc ="0.5"/> 100 <set name="fcs/mixture-cmd-norm" value="0.87" action="FG_RAMP" tc ="0.5"/> 101 <set name="propulsion/magneto_cmd" value="3"/> 102 <set name="propulsion/starter_cmd" value="1"/> 103 </event> 104 105 <event name="set heading hold"> 106 <!-- Set Heading when reach 5 ft --> 107 <notify/> 108 <condition> 109 position/h-agl-ft >= 5 110 </condition> 111 <set name="ap/heading_setpoint" value="200"/> 112 <set name="ap/attitude_hold" value="0"/> 113 <set name="ap/heading_hold" value="1"/> 114 </event> 115 116 <event name="set autopilot"> 117 <!-- Set Autopilot for 20 ft --> 118 <notify/> 119 <condition> 120 aero/qbar-psf >= 4 121 </condition> 122 <set name="ap/altitude_setpoint" value="100.0" action="FG_EXP" tc ="2.0"/> 123 <set name="ap/altitude_hold" value="1"/> 124 <set name="fcs/flap-cmd-norm" value=".33"/> 125 </event> 126 127 <event name="set autopilot 2" persistent="true"> 128 <!-- Set Autopilot for 6000 ft --> 129 <notify/> 130 <condition> 131 aero/qbar-psf > 5 132 </condition> 133 <set name="ap/altitude_setpoint" value="6000.0"/> 134 </event> 135 136 <event name="Time Notify"> 137 <notify/> 138 <condition> sim-time-sec >= 500 </condition> 139 </event> 140 141 <event name="Time Notify"> 142 <notify/> 143 <condition> sim-time-sec >= 1000 </condition> 144 </event> 145 146 </run> 147 148 </runscript> 149 @endcode 150 151 The first line must always be present - it identifies the file 152 as an XML format file. The second line 153 identifies this file as a script file, and gives a descriptive 154 name to the script file. Comments are next, delineated by the 155 <!-- and --> symbols. The aircraft and initialization files 156 to be used are specified in the "use" lines. Next, 157 comes the "run" section, where the conditions are 158 described in "event" clauses.</p> 159 @author Jon S. Berndt 160 */ 161 162 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 163 CLASS DECLARATION 164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 165 166 class FGScript : public FGJSBBase 167 { 168 public: 169 /// Default constructor 170 FGScript(FGFDMExec* exec); 171 172 /// Default destructor 173 ~FGScript(); 174 175 /** Loads a script to drive JSBSim (usually in standalone mode). 176 The language is the Script Directives for JSBSim. If a simulation step 177 size has been supplied on the command line, it will override the script 178 specified simulation step size. 179 @param script the filename (including path name, if any) for the script. 180 @param default_dT the default simulation step size if no value is specified 181 in the script 182 @param initfile An optional initialization file name passed in, empty by 183 default. If a file name is passed in, it will override the 184 one present in the script. 185 @return true if successful */ 186 bool LoadScript(const SGPath& script, double default_dT, 187 const SGPath& initfile); 188 189 /** This function is called each pass through the executive Run() method IF 190 scripting is enabled. 191 @return false if script should exit (i.e. if time limits are violated */ 192 bool RunScript(void); 193 194 void ResetEvents(void); 195 196 private: 197 enum eAction { 198 FG_RAMP = 1, 199 FG_STEP = 2, 200 FG_EXP = 3 201 }; 202 203 enum eType { 204 FG_VALUE = 1, 205 FG_DELTA = 2, 206 FG_BOOL = 3 207 }; 208 209 struct event { 210 FGCondition *Condition; 211 bool Persistent; 212 bool Continuous; 213 bool Triggered; 214 bool Notify; 215 bool NotifyKML; 216 bool Notified; 217 double Delay; 218 double StartTime; 219 double TimeSpan; 220 std::string Name; 221 std::string Description; 222 std::vector <FGPropertyNode_ptr> SetParam; 223 std::vector <std::string> SetParamName; 224 std::vector <FGPropertyValue*> NotifyProperties; 225 std::vector <std::string> DisplayString; 226 std::vector <eAction> Action; 227 std::vector <eType> Type; 228 std::vector <double> SetValue; 229 std::vector <double> TC; 230 std::vector <double> newValue; 231 std::vector <double> OriginalValue; 232 std::vector <double> ValueSpan; 233 std::vector <bool> Transiting; 234 std::vector <FGFunction*> Functions; 235 eventevent236 event() { 237 Triggered = false; 238 Persistent = false; 239 Continuous = false; 240 Delay = 0.0; 241 Notify = Notified = NotifyKML = false; 242 Name = ""; 243 StartTime = 0.0; 244 TimeSpan = 0.0; 245 } 246 resetevent247 void reset(void) { 248 Triggered = false; 249 Notified = false; 250 StartTime = 0.0; 251 } 252 }; 253 254 std::string ScriptName; 255 double StartTime; 256 double EndTime; 257 std::vector <struct event> Events; 258 259 FGPropertyReader LocalProperties; 260 261 FGFDMExec* FDMExec; 262 FGPropertyManager* PropertyManager; 263 void Debug(int from); 264 }; 265 } 266 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 267 #endif 268