JSBSim Flight Dynamics Model  1.2.0 (05 Nov 2023)
An Open Source Flight Dynamics and Control Software Library in C++
FGScript Class Reference

Detailed Description

Encapsulates the JSBSim scripting capability.

Scripting support provided via FGScript.

There is support for scripting provided in the FGScript class. Commands are specified using the Scripting Directives for JSBSim. The script file is in XML format. A test condition (or conditions) can be set up in an event in a script and when the condition evaluates to true, the specified action[s] is/are taken. An event can be persistent, meaning that at every time the test condition first evaluates to true (toggling from false to true) then the specified set actions take place. An event can also be defined to execute or evaluate continuously while the condition is true. When the set of tests evaluates to true for a given condition, an item may be set to another value. This value may be a value, or a delta value, and the change from the current value to the new value can be either via a step action, a ramp, or an exponential approach. The speed of a ramp or exponential approach is specified via the time constant. Here is an example illustrating the format of the script file:

<?xml version="1.0"?>
<runscript name="C172-01A takeoff run">
<!--
This run is for testing the C172 altitude hold autopilot
-->
<use aircraft="c172x"/>
<use initialize="reset00"/>
<run start="0.0" end="3000" dt="0.0083333">
<event name="engine start">
<notify/>
<condition>
sim-time-sec >= 0.25
</condition>
<set name="fcs/throttle-cmd-norm" value="1.0" action="FG_RAMP" tc ="0.5"/>
<set name="fcs/mixture-cmd-norm" value="0.87" action="FG_RAMP" tc ="0.5"/>
<set name="propulsion/magneto_cmd" value="3"/>
<set name="propulsion/starter_cmd" value="1"/>
</event>
<event name="set heading hold">
<!-- Set Heading when reach 5 ft -->
<notify/>
<condition>
position/h-agl-ft >= 5
</condition>
<set name="ap/heading_setpoint" value="200"/>
<set name="ap/attitude_hold" value="0"/>
<set name="ap/heading_hold" value="1"/>
</event>
<event name="set autopilot">
<!-- Set Autopilot for 20 ft -->
<notify/>
<condition>
aero/qbar-psf >= 4
</condition>
<set name="ap/altitude_setpoint" value="100.0" action="FG_EXP" tc ="2.0"/>
<set name="ap/altitude_hold" value="1"/>
<set name="fcs/flap-cmd-norm" value=".33"/>
</event>
<event name="set autopilot 2" persistent="true">
<!-- Set Autopilot for 6000 ft -->
<notify/>
<condition>
aero/qbar-psf > 5
</condition>
<set name="ap/altitude_setpoint" value="6000.0"/>
</event>
<event name="Time Notify">
<notify/>
<condition> sim-time-sec >= 500 </condition>
</event>
<event name="Time Notify">
<notify/>
<condition> sim-time-sec >= 1000 </condition>
</event>
</run>
</runscript>

The first line must always be present - it identifies the file as an XML format file. 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 "event" clauses.

Author
Jon S. Berndt

Definition at line 167 of file FGScript.h.

#include <FGScript.h>

+ Inheritance diagram for FGScript:
+ Collaboration diagram for FGScript:

Public Member Functions

 FGScript (FGFDMExec *exec)
 Default constructor.
 
 ~FGScript ()
 Default destructor.
 
bool LoadScript (const SGPath &script, double default_dT, const SGPath &initfile)
 Loads a script to drive JSBSim (usually in standalone mode). More...
 
void ResetEvents (void)
 
bool RunScript (void)
 This function is called each pass through the executive Run() method IF scripting is enabled. More...
 
- Public Member Functions inherited from FGJSBBase
 FGJSBBase ()
 Constructor for FGJSBBase.
 
virtual ~FGJSBBase ()
 Destructor for FGJSBBase.
 
void disableHighLighting (void)
 Disables highlighting in the console output.
 

Additional Inherited Members

- Public Types inherited from FGJSBBase
enum  { eL = 1 , eM , eN }
 Moments L, M, N.
 
enum  { eP = 1 , eQ , eR }
 Rates P, Q, R.
 
enum  { eU = 1 , eV , eW }
 Velocities U, V, W.
 
enum  { eX = 1 , eY , eZ }
 Positions X, Y, Z.
 
enum  { ePhi = 1 , eTht , ePsi }
 Euler angles Phi, Theta, Psi.
 
enum  { eDrag = 1 , eSide , eLift }
 Stability axis forces, Drag, Side force, Lift.
 
enum  { eRoll = 1 , ePitch , eYaw }
 Local frame orientation Roll, Pitch, Yaw.
 
enum  { eNorth = 1 , eEast , eDown }
 Local frame position North, East, Down.
 
enum  { eLat = 1 , eLong , eRad }
 Locations Radius, Latitude, Longitude.
 
enum  {
  inNone = 0 , inDegrees , inRadians , inMeters ,
  inFeet
}
 Conversion specifiers.
 
- Static Public Member Functions inherited from FGJSBBase
static const std::string & GetVersion (void)
 Returns the version number of JSBSim. More...
 
static constexpr double KelvinToFahrenheit (double kelvin)
 Converts from degrees Kelvin to degrees Fahrenheit. More...
 
static constexpr double CelsiusToRankine (double celsius)
 Converts from degrees Celsius to degrees Rankine. More...
 
static constexpr double RankineToCelsius (double rankine)
 Converts from degrees Rankine to degrees Celsius. More...
 
static constexpr double KelvinToRankine (double kelvin)
 Converts from degrees Kelvin to degrees Rankine. More...
 
static constexpr double RankineToKelvin (double rankine)
 Converts from degrees Rankine to degrees Kelvin. More...
 
static constexpr double FahrenheitToCelsius (double fahrenheit)
 Converts from degrees Fahrenheit to degrees Celsius. More...
 
static constexpr double CelsiusToFahrenheit (double celsius)
 Converts from degrees Celsius to degrees Fahrenheit. More...
 
static constexpr double CelsiusToKelvin (double celsius)
 Converts from degrees Celsius to degrees Kelvin. More...
 
static constexpr double KelvinToCelsius (double kelvin)
 Converts from degrees Kelvin to degrees Celsius. More...
 
static constexpr double FeetToMeters (double measure)
 Converts from feet to meters. More...
 
static bool EqualToRoundoff (double a, double b)
 Finite precision comparison. More...
 
static bool EqualToRoundoff (float a, float b)
 Finite precision comparison. More...
 
static bool EqualToRoundoff (float a, double b)
 Finite precision comparison. More...
 
static bool EqualToRoundoff (double a, float b)
 Finite precision comparison. More...
 
static constexpr double Constrain (double min, double value, double max)
 Constrain a value between a minimum and a maximum value.
 
static constexpr double sign (double num)
 
- Static Public Attributes inherited from FGJSBBase
static char highint [5] = {27, '[', '1', 'm', '\0' }
 highlights text
 
static char halfint [5] = {27, '[', '2', 'm', '\0' }
 low intensity text
 
static char normint [6] = {27, '[', '2', '2', 'm', '\0' }
 normal intensity text
 
static char reset [5] = {27, '[', '0', 'm', '\0' }
 resets text properties
 
static char underon [5] = {27, '[', '4', 'm', '\0' }
 underlines text
 
static char underoff [6] = {27, '[', '2', '4', 'm', '\0' }
 underline off
 
static char fgblue [6] = {27, '[', '3', '4', 'm', '\0' }
 blue text
 
static char fgcyan [6] = {27, '[', '3', '6', 'm', '\0' }
 cyan text
 
static char fgred [6] = {27, '[', '3', '1', 'm', '\0' }
 red text
 
static char fggreen [6] = {27, '[', '3', '2', 'm', '\0' }
 green text
 
static char fgdef [6] = {27, '[', '3', '9', 'm', '\0' }
 default text
 
static short debug_lvl = 1
 
- Static Protected Member Functions inherited from FGJSBBase
static std::string CreateIndexedPropertyName (const std::string &Property, int index)
 
- Static Protected Attributes inherited from FGJSBBase
static constexpr double radtodeg = 180. / M_PI
 
static constexpr double degtorad = M_PI / 180.
 
static constexpr double hptoftlbssec = 550.0
 
static constexpr double psftoinhg = 0.014138
 
static constexpr double psftopa = 47.88
 
static constexpr double fttom = 0.3048
 
static constexpr double ktstofps = 1852./(3600*fttom)
 
static constexpr double fpstokts = 1.0 / ktstofps
 
static constexpr double inchtoft = 1.0/12.0
 
static constexpr double m3toft3 = 1.0/(fttom*fttom*fttom)
 
static constexpr double in3tom3 = inchtoft*inchtoft*inchtoft/m3toft3
 
static constexpr double inhgtopa = 3386.38
 
static constexpr double slugtolb = 32.174049
 Note that definition of lbtoslug by the inverse of slugtolb and not to a different constant you can also get from some tables will make lbtoslug*slugtolb == 1 up to the magnitude of roundoff. More...
 
static constexpr double lbtoslug = 1.0/slugtolb
 
static constexpr double kgtolb = 2.20462
 
static constexpr double kgtoslug = 0.06852168
 
static const std::string needed_cfg_version = "2.0"
 
static const std::string JSBSim_version = JSBSIM_VERSION " " __DATE__ " " __TIME__
 

Member Function Documentation

◆ LoadScript()

bool LoadScript ( const SGPath &  script,
double  default_dT,
const SGPath &  initfile 
)

Loads a script to drive JSBSim (usually in standalone mode).

The language is the Script Directives for JSBSim. If a simulation step size has been supplied on the command line, it will override the script specified simulation step size.

Parameters
scriptthe filename (including path name, if any) for the script.
default_dTthe default simulation step size if no value is specified in the script
initfileAn optional initialization file name passed in, empty by default. If a file name is passed in, it will override the one present in the script.
Returns
true if successful

Definition at line 91 of file FGScript.cpp.

93 {
94  SGPath initialize;
95  string aircraft="", prop_name="";
96  string notifyPropertyName="";
97  Element *element=0, *run_element=0, *event_element=0;
98  Element *set_element=0;
99  Element *notify_element = 0L, *notify_property_element = 0L;
100  double dt = 0.0, value = 0.0;
101  FGCondition *newCondition;
102 
103  FGXMLFileRead XMLFileRead;
104  Element* document = XMLFileRead.LoadXMLDocument(script);
105 
106  if (!document) {
107  cerr << "File: " << script << " could not be loaded." << endl;
108  return false;
109  }
110 
111  if (document->GetName() != string("runscript")) {
112  cerr << "File: " << script << " is not a script file" << endl;
113  return false;
114  }
115 
116  ScriptName = document->GetAttributeValue("name");
117 
118  // First, find "run" element and set delta T
119 
120  run_element = document->FindElement("run");
121 
122  if (!run_element) {
123  cerr << "No \"run\" element found in script." << endl;
124  return false;
125  }
126 
127  // Set sim timing
128 
129  if (run_element->HasAttribute("start"))
130  StartTime = run_element->GetAttributeValueAsNumber("start");
131  else
132  StartTime = 0.0;
133  FDMExec->Setsim_time(StartTime);
134  if (run_element->HasAttribute("end")) {
135  EndTime = run_element->GetAttributeValueAsNumber("end");
136  } else {
137  cerr << "An end time (duration) for the script must be specified in the script <run> element." << endl;
138  return false;
139  }
140 
141  if (default_dT == 0.0)
142  dt = run_element->GetAttributeValueAsNumber("dt");
143  else {
144  dt = default_dT;
145  cout << endl << "Overriding simulation step size from the command line. New step size is: "
146  << default_dT << " seconds (" << 1/default_dT << " Hz)" << endl << endl;
147  }
148 
149  FDMExec->Setdt(dt);
150 
151  // Make sure that the desired time is reached and executed.
152  EndTime += 0.99*FDMExec->GetDeltaT();
153 
154  // read aircraft and initialization files
155 
156  element = document->FindElement("use");
157  if (element) {
158  aircraft = element->GetAttributeValue("aircraft");
159  if (!aircraft.empty()) {
160  if (!FDMExec->LoadModel(aircraft))
161  return false;
162  } else {
163  cerr << "Aircraft must be specified in use element." << endl;
164  return false;
165  }
166 
167  initialize = SGPath::fromLocal8Bit(element->GetAttributeValue("initialize").c_str());
168  if (initfile.isNull()) {
169  if (initialize.isNull()) {
170  cerr << "Initialization file must be specified in use element." << endl;
171  return false;
172  }
173  } else {
174  cout << endl << "The initialization file specified in the script file ("
175  << initialize << ") has been overridden with a specified file ("
176  << initfile << ")." << endl;
177  initialize = initfile;
178  }
179 
180  } else {
181  cerr << "No \"use\" directives in the script file." << endl;
182  return false;
183  }
184 
185  auto IC = FDMExec->GetIC();
186  if ( ! IC->Load( initialize )) {
187  cerr << "Initialization unsuccessful" << endl;
188  return false;
189  }
190 
191  // Now, read input spec if given.
192  element = document->FindElement("input");
193  while (element) {
194  if (!FDMExec->GetInput()->Load(element))
195  return false;
196 
197  element = document->FindNextElement("input");
198  }
199 
200  // Now, read output spec if given.
201  element = document->FindElement("output");
202  SGPath scriptDir = SGPath(script.dir());
203  if (scriptDir.isNull())
204  scriptDir = SGPath(".");
205 
206  while (element) {
207  if (!FDMExec->GetOutput()->Load(element, scriptDir))
208  return false;
209 
210  element = document->FindNextElement("output");
211  }
212 
213  // Read local property/value declarations
214  int saved_debug_lvl = debug_lvl;
215  debug_lvl = 0; // Disable messages
216  LocalProperties.Load(run_element, PropertyManager.get(), true);
217  debug_lvl = saved_debug_lvl;
218 
219  // Read "events" from script
220 
221  event_element = run_element->FindElement("event");
222  while (event_element) { // event processing
223 
224  // Create the event structure
225  struct event *newEvent = new struct event();
226 
227  // Retrieve the event name if given
228  newEvent->Name = event_element->GetAttributeValue("name");
229 
230  // Is this event persistent? That is, does it execute every time the
231  // condition triggers to true, or does it execute as a one-shot event, only?
232  if (event_element->GetAttributeValue("persistent") == string("true")) {
233  newEvent->Persistent = true;
234  }
235 
236  // Does this event execute continuously when triggered to true?
237  if (event_element->GetAttributeValue("continuous") == string("true")) {
238  newEvent->Continuous = true;
239  }
240 
241  // Process the conditions
242  Element* condition_element = event_element->FindElement("condition");
243  if (condition_element != 0) {
244  try {
245  newCondition = new FGCondition(condition_element, PropertyManager);
246  } catch(string& str) {
247  cout << endl << fgred << str << reset << endl << endl;
248  delete newEvent;
249  return false;
250  }
251  newEvent->Condition = newCondition;
252  } else {
253  cerr << "No condition specified in script event " << newEvent->Name
254  << endl;
255  delete newEvent;
256  return false;
257  }
258 
259  // Is there a delay between the time this event is triggered, and when the
260  // event actions are executed?
261 
262  Element* delay_element = event_element->FindElement("delay");
263  if (delay_element)
264  newEvent->Delay = event_element->FindElementValueAsNumber("delay");
265  else
266  newEvent->Delay = 0.0;
267 
268  // Notify about when this event is triggered?
269  if ((notify_element = event_element->FindElement("notify")) != 0) {
270  if (notify_element->HasAttribute("format")) {
271  if (notify_element->GetAttributeValue("format") == "kml") newEvent->NotifyKML = true;
272  }
273  newEvent->Notify = true;
274  // Check here for new <description> tag that gets echoed
275  string notify_description = notify_element->FindElementValue("description");
276  if (!notify_description.empty()) {
277  newEvent->Description = notify_description;
278  }
279  notify_property_element = notify_element->FindElement("property");
280  while (notify_property_element) {
281  notifyPropertyName = notify_property_element->GetDataLine();
282 
283  if (notify_property_element->HasAttribute("apply")) {
284  string function_str = notify_property_element->GetAttributeValue("apply");
285  auto f = FDMExec->GetTemplateFunc(function_str);
286  if (f)
287  newEvent->NotifyProperties.push_back(new FGFunctionValue(notifyPropertyName, PropertyManager, f,
288  notify_property_element));
289  else {
290  cerr << notify_property_element->ReadFrom()
291  << fgred << highint << " No function by the name "
292  << function_str << " has been defined. This property will "
293  << "not be logged. You should check your configuration file."
294  << reset << endl;
295  }
296  }
297  else
298  newEvent->NotifyProperties.push_back(new FGPropertyValue(notifyPropertyName, PropertyManager,
299  notify_property_element));
300 
301  string caption_attribute = notify_property_element->GetAttributeValue("caption");
302  if (caption_attribute.empty()) {
303  newEvent->DisplayString.push_back(notifyPropertyName);
304  } else {
305  newEvent->DisplayString.push_back(caption_attribute);
306  }
307 
308  notify_property_element = notify_element->FindNextElement("property");
309  }
310  }
311 
312  // Read set definitions (these define the actions to be taken when the event
313  // is triggered).
314  set_element = event_element->FindElement("set");
315  while (set_element) {
316  prop_name = set_element->GetAttributeValue("name");
317  if (PropertyManager->HasNode(prop_name)) {
318  newEvent->SetParam.push_back( PropertyManager->GetNode(prop_name) );
319  } else {
320  newEvent->SetParam.push_back( 0L );
321  }
322  newEvent->SetParamName.push_back( prop_name );
323 
324  // Todo - should probably do some safety checking here to make sure one or
325  // the other of value or function is specified.
326  if (!set_element->GetAttributeValue("value").empty()) {
327  value = set_element->GetAttributeValueAsNumber("value");
328  newEvent->Functions.push_back(nullptr);
329  } else if (set_element->FindElement("function")) {
330  value = 0.0;
331  newEvent->Functions.push_back(new FGFunction(FDMExec, set_element->FindElement("function")));
332  }
333  newEvent->SetValue.push_back(value);
334  newEvent->OriginalValue.push_back(0.0);
335  newEvent->newValue.push_back(0.0);
336  newEvent->ValueSpan.push_back(0.0);
337  string tempCompare = set_element->GetAttributeValue("type");
338  if (to_lower(tempCompare).find("delta") != string::npos) newEvent->Type.push_back(FG_DELTA);
339  else if (to_lower(tempCompare).find("bool") != string::npos) newEvent->Type.push_back(FG_BOOL);
340  else if (to_lower(tempCompare).find("value") != string::npos) newEvent->Type.push_back(FG_VALUE);
341  else newEvent->Type.push_back(FG_VALUE); // DEFAULT
342  tempCompare = set_element->GetAttributeValue("action");
343  if (to_lower(tempCompare).find("ramp") != string::npos) newEvent->Action.push_back(FG_RAMP);
344  else if (to_lower(tempCompare).find("step") != string::npos) newEvent->Action.push_back(FG_STEP);
345  else if (to_lower(tempCompare).find("exp") != string::npos) newEvent->Action.push_back(FG_EXP);
346  else newEvent->Action.push_back(FG_STEP); // DEFAULT
347 
348  if (!set_element->GetAttributeValue("tc").empty())
349  newEvent->TC.push_back(set_element->GetAttributeValueAsNumber("tc"));
350  else
351  newEvent->TC.push_back(1.0); // DEFAULT
352 
353  newEvent->Transiting.push_back(false);
354 
355  set_element = event_element->FindNextElement("set");
356  }
357  Events.push_back(*newEvent);
358  delete newEvent;
359 
360  event_element = run_element->FindNextElement("event");
361  }
362 
363  Debug(4);
364 
365  return true;
366 }
std::shared_ptr< FGInitialCondition > GetIC(void) const
Returns a pointer to the FGInitialCondition object.
Definition: FGFDMExec.h:389
std::shared_ptr< FGOutput > GetOutput(void) const
Returns the FGOutput pointer.
Definition: FGFDMExec.cpp:383
double GetDeltaT(void) const
Returns the simulation delta T.
Definition: FGFDMExec.h:547
double Setsim_time(double cur_time)
Sets the current sim time.
Definition: FGFDMExec.cpp:194
bool LoadModel(const SGPath &AircraftPath, const SGPath &EnginePath, const SGPath &SystemsPath, const std::string &model, bool addModelToPath=true)
Loads an aircraft model.
Definition: FGFDMExec.cpp:821
void Setdt(double delta_t)
Sets the integration time step for the simulation executive.
Definition: FGFDMExec.h:566
std::shared_ptr< FGInput > GetInput(void) const
Returns the FGInput pointer.
Definition: FGFDMExec.cpp:292
static char fgred[6]
red text
Definition: FGJSBBase.h:167
static char reset[5]
resets text properties
Definition: FGJSBBase.h:157
static char highint[5]
highlights text
Definition: FGJSBBase.h:151
+ Here is the call graph for this function:

◆ RunScript()

bool RunScript ( void  )

This function is called each pass through the executive Run() method IF scripting is enabled.

Returns
false if script should exit (i.e. if time limits are violated

Definition at line 381 of file FGScript.cpp.

382 {
383  unsigned i, j;
384  unsigned event_ctr = 0;
385 
386  double currentTime = FDMExec->GetSimTime();
387  double newSetValue = 0;
388 
389  if (currentTime > EndTime) return false;
390 
391  // Iterate over all events.
392  for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) {
393 
394  struct event &thisEvent = Events[ev_ctr];
395 
396  // Determine whether the set of conditional tests for this condition equate
397  // to true and should cause the event to execute. If the conditions evaluate
398  // to true, then the event is triggered. If the event is not persistent,
399  // then this trigger will remain set true. If the event is persistent, the
400  // trigger will reset to false when the condition evaluates to false.
401  if (thisEvent.Condition->Evaluate()) {
402  if (!thisEvent.Triggered) {
403 
404  // The conditions are true, do the setting of the desired Event
405  // parameters
406  for (i=0; i<thisEvent.SetValue.size(); i++) {
407  if (thisEvent.SetParam[i] == 0L) { // Late bind property if necessary
408  if (PropertyManager->HasNode(thisEvent.SetParamName[i])) {
409  thisEvent.SetParam[i] = PropertyManager->GetNode(thisEvent.SetParamName[i]);
410  } else {
411  throw("No property, \""+thisEvent.SetParamName[i]+"\" is defined.");
412  }
413  }
414  thisEvent.OriginalValue[i] = thisEvent.SetParam[i]->getDoubleValue();
415  if (thisEvent.Functions[i] != 0) { // Parameter should be set to a function value
416  try {
417  thisEvent.SetValue[i] = thisEvent.Functions[i]->GetValue();
418  } catch (string& msg) {
419  std::cerr << std::endl << "A problem occurred in the execution of the script. " << msg << endl;
420  throw;
421  }
422  }
423  switch (thisEvent.Type[i]) {
424  case FG_VALUE:
425  case FG_BOOL:
426  thisEvent.newValue[i] = thisEvent.SetValue[i];
427  break;
428  case FG_DELTA:
429  thisEvent.newValue[i] = thisEvent.OriginalValue[i] + thisEvent.SetValue[i];
430  break;
431  default:
432  cerr << "Invalid Type specified" << endl;
433  break;
434  }
435  thisEvent.StartTime = currentTime + thisEvent.Delay;
436  thisEvent.ValueSpan[i] = thisEvent.newValue[i] - thisEvent.OriginalValue[i];
437  thisEvent.Transiting[i] = true;
438  }
439  }
440  thisEvent.Triggered = true;
441 
442  } else if (thisEvent.Persistent) { // If the event is persistent, reset the trigger.
443  thisEvent.Triggered = false; // Reset the trigger for persistent events
444  thisEvent.Notified = false; // Also reset the notification flag
445  } else if (thisEvent.Continuous) { // If the event is continuous, reset the trigger.
446  thisEvent.Triggered = false; // Reset the trigger for persistent events
447  thisEvent.Notified = false; // Also reset the notification flag
448  }
449 
450  if ((currentTime >= thisEvent.StartTime) && thisEvent.Triggered) {
451 
452  for (i=0; i<thisEvent.SetValue.size(); i++) {
453  if (thisEvent.Transiting[i]) {
454  thisEvent.TimeSpan = currentTime - thisEvent.StartTime;
455  switch (thisEvent.Action[i]) {
456  case FG_RAMP:
457  if (thisEvent.TimeSpan <= thisEvent.TC[i]) {
458  newSetValue = thisEvent.TimeSpan/thisEvent.TC[i] * thisEvent.ValueSpan[i] + thisEvent.OriginalValue[i];
459  } else {
460  newSetValue = thisEvent.newValue[i];
461  if (thisEvent.Continuous != true) thisEvent.Transiting[i] = false;
462  }
463  break;
464  case FG_STEP:
465  newSetValue = thisEvent.newValue[i];
466 
467  // If this is not a continuous event, reset the transiting flag.
468  // Otherwise, it is known that the event is a continuous event.
469  // Furthermore, if the event is to be determined by a function,
470  // then the function will be continuously calculated.
471  if (thisEvent.Continuous != true)
472  thisEvent.Transiting[i] = false;
473  else if (thisEvent.Functions[i] != 0)
474  newSetValue = thisEvent.Functions[i]->GetValue();
475 
476  break;
477  case FG_EXP:
478  newSetValue = (1 - exp( -thisEvent.TimeSpan/thisEvent.TC[i] )) * thisEvent.ValueSpan[i] + thisEvent.OriginalValue[i];
479  break;
480  default:
481  cerr << "Invalid Action specified" << endl;
482  break;
483  }
484  thisEvent.SetParam[i]->setDoubleValue(newSetValue);
485  }
486  }
487 
488  // Print notification values after setting them
489  if (thisEvent.Notify && !thisEvent.Notified) {
490  if (thisEvent.NotifyKML) {
491  cout << endl << "<Placemark>" << endl;
492  cout << " <name> " << currentTime << " seconds" << " </name>"
493  << endl;
494  cout << " <description>" << endl;
495  cout << " <![CDATA[" << endl;
496  cout << " <b>" << thisEvent.Name << " (Event " << event_ctr << ")"
497  << " executed at time: " << currentTime << "</b><br/>" << endl;
498  } else {
499  cout << endl << underon
500  << highint << thisEvent.Name << normint << underoff
501  << " (Event " << event_ctr << ")"
502  << " executed at time: " << highint << currentTime << normint
503  << endl;
504  }
505  if (!thisEvent.Description.empty()) {
506  cout << " " << thisEvent.Description << endl;
507  }
508  for (j=0; j<thisEvent.NotifyProperties.size();j++) {
509  cout << " " << thisEvent.DisplayString[j] << " = "
510  << thisEvent.NotifyProperties[j]->getDoubleValue();
511  if (thisEvent.NotifyKML) cout << " <br/>";
512  cout << endl;
513  }
514  if (thisEvent.NotifyKML) {
515  cout << " ]]>" << endl;
516  cout << " </description>" << endl;
517  cout << " <Point>" << endl;
518  cout << " <altitudeMode> absolute </altitudeMode>" << endl;
519  cout << " <extrude> 1 </extrude>" << endl;
520  cout << " <coordinates>"
521  << FDMExec->GetPropagate()->GetLongitudeDeg() << ","
522  << FDMExec->GetPropagate()->GetGeodLatitudeDeg() << ","
523  << FDMExec->GetPropagate()->GetAltitudeASLmeters()
524  << "</coordinates>" << endl;
525  cout << " </Point>" << endl;
526  cout << "</Placemark>" << endl;
527  }
528  cout << endl;
529  thisEvent.Notified = true;
530  }
531 
532  }
533 
534  event_ctr++;
535  }
536  return true;
537 }
std::shared_ptr< FGPropagate > GetPropagate(void) const
Returns the FGPropagate pointer.
Definition: FGFDMExec.cpp:278
double GetSimTime(void) const
Returns the cumulative simulation time in seconds.
Definition: FGFDMExec.h:544
static char normint[6]
normal intensity text
Definition: FGJSBBase.h:155
static char underon[5]
underlines text
Definition: FGJSBBase.h:159
static char underoff[6]
underline off
Definition: FGJSBBase.h:161
+ Here is the call graph for this function:

The documentation for this class was generated from the following files: