JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
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 166 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 PutMessage (const Message &msg)
 Places a Message structure on the Message queue. More...
 
void PutMessage (const std::string &text)
 Creates a message with the given text and places it on the queue. More...
 
void PutMessage (const std::string &text, bool bVal)
 Creates a message with the given text and boolean value and places it on the queue. More...
 
void PutMessage (const std::string &text, int iVal)
 Creates a message with the given text and integer value and places it on the queue. More...
 
void PutMessage (const std::string &text, double dVal)
 Creates a message with the given text and double value and places it on the queue. More...
 
int SomeMessages (void) const
 Reads the message on the queue (but does not delete it). More...
 
void ProcessMessage (void)
 Reads the message on the queue and removes it from the queue. More...
 
MessageProcessNextMessage (void)
 Reads the next message on the queue and removes it from the queue. More...
 
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 double PitotTotalPressure (double mach, double p)
 Compute the total pressure in front of the Pitot tube. More...
 
static double MachFromImpactPressure (double qc, double p)
 Compute the Mach number from the differential pressure (qc) and the static pressure. More...
 
static double VcalibratedFromMach (double mach, double p)
 Calculate the calibrated airspeed from the Mach number. More...
 
static double MachFromVcalibrated (double vcas, double p)
 Calculate the Mach number from the calibrated airspeed.Based on the formulas in the US Air Force Aircraft Performance Flight Testing Manual (AFFTC-TIH-99-01). 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 double GaussianRandomNumber (void)
 
- 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 Message localMsg
 
static std::queue< MessageMessages
 
static unsigned int messageId = 0
 
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 ktstofps = 1.68781
 
static constexpr double fpstokts = 1.0 / ktstofps
 
static constexpr double inchtoft = 1.0/12.0
 
static constexpr double fttom = 0.3048
 
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__
 
static int gaussian_random_number_phase = 0
 

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  FGInitialCondition *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, 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  FGTemplateFunc* f = FDMExec->GetTemplateFunc(function_str);
286  if (f)
287  newEvent->NotifyProperties.push_back(new FGFunctionValue(notifyPropertyName, PropertyManager, f));
288  else {
289  cerr << notify_property_element->ReadFrom()
290  << fgred << highint << " No function by the name "
291  << function_str << " has been defined. This property will "
292  << "not be logged. You should check your configuration file."
293  << reset << endl;
294  }
295  }
296  else
297  newEvent->NotifyProperties.push_back(new FGPropertyValue(notifyPropertyName, PropertyManager));
298 
299  string caption_attribute = notify_property_element->GetAttributeValue("caption");
300  if (caption_attribute.empty()) {
301  newEvent->DisplayString.push_back(notifyPropertyName);
302  } else {
303  newEvent->DisplayString.push_back(caption_attribute);
304  }
305 
306  notify_property_element = notify_element->FindNextElement("property");
307  }
308  }
309 
310  // Read set definitions (these define the actions to be taken when the event
311  // is triggered).
312  set_element = event_element->FindElement("set");
313  while (set_element) {
314  prop_name = set_element->GetAttributeValue("name");
315  if (PropertyManager->HasNode(prop_name)) {
316  newEvent->SetParam.push_back( PropertyManager->GetNode(prop_name) );
317  } else {
318  newEvent->SetParam.push_back( 0L );
319  }
320  newEvent->SetParamName.push_back( prop_name );
321 
322  // Todo - should probably do some safety checking here to make sure one or
323  // the other of value or function is specified.
324  if (!set_element->GetAttributeValue("value").empty()) {
325  value = set_element->GetAttributeValueAsNumber("value");
326  newEvent->Functions.push_back(nullptr);
327  } else if (set_element->FindElement("function")) {
328  value = 0.0;
329  newEvent->Functions.push_back(new FGFunction(FDMExec, set_element->FindElement("function")));
330  }
331  newEvent->SetValue.push_back(value);
332  newEvent->OriginalValue.push_back(0.0);
333  newEvent->newValue.push_back(0.0);
334  newEvent->ValueSpan.push_back(0.0);
335  string tempCompare = set_element->GetAttributeValue("type");
336  if (to_lower(tempCompare).find("delta") != string::npos) newEvent->Type.push_back(FG_DELTA);
337  else if (to_lower(tempCompare).find("bool") != string::npos) newEvent->Type.push_back(FG_BOOL);
338  else if (to_lower(tempCompare).find("value") != string::npos) newEvent->Type.push_back(FG_VALUE);
339  else newEvent->Type.push_back(FG_VALUE); // DEFAULT
340  tempCompare = set_element->GetAttributeValue("action");
341  if (to_lower(tempCompare).find("ramp") != string::npos) newEvent->Action.push_back(FG_RAMP);
342  else if (to_lower(tempCompare).find("step") != string::npos) newEvent->Action.push_back(FG_STEP);
343  else if (to_lower(tempCompare).find("exp") != string::npos) newEvent->Action.push_back(FG_EXP);
344  else newEvent->Action.push_back(FG_STEP); // DEFAULT
345 
346  if (!set_element->GetAttributeValue("tc").empty())
347  newEvent->TC.push_back(set_element->GetAttributeValueAsNumber("tc"));
348  else
349  newEvent->TC.push_back(1.0); // DEFAULT
350 
351  newEvent->Transiting.push_back(false);
352 
353  set_element = event_element->FindNextElement("set");
354  }
355  Events.push_back(*newEvent);
356  delete newEvent;
357 
358  event_element = run_element->FindNextElement("event");
359  }
360 
361  Debug(4);
362 
363  return true;
364 }
+ Here is the call graph for this function:
+ Here is the caller 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 379 of file FGScript.cpp.

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

The documentation for this class was generated from the following files:
JSBSim::FGInput::Load
bool Load(Element *el) override
Load the input directives and adds a new input instance to the Input Manager list.
Definition: FGInput.cpp:76
JSBSim::FGFDMExec::GetOutput
FGOutput * GetOutput(void)
Returns the FGOutput pointer.
Definition: FGFDMExec.h:383
JSBSim::FGFDMExec::GetIC
FGInitialCondition * GetIC(void)
Returns a pointer to the FGInitialCondition object.
Definition: FGFDMExec.h:387
JSBSim::FGFDMExec::GetSimTime
double GetSimTime(void) const
Returns the cumulative simulation time in seconds.
Definition: FGFDMExec.h:542
JSBSim::FGOutput::Load
bool Load(Element *el, const SGPath &dir=SGPath())
Load the output directives and adds a new output instance to the Output Manager list.
Definition: FGOutput.cpp:238
JSBSim::FGFDMExec::GetInput
FGInput * GetInput(void)
Returns the FGInput pointer.
Definition: FGFDMExec.h:381
JSBSim::FGFDMExec::Setsim_time
double Setsim_time(double cur_time)
Sets the current sim time.
Definition: FGFDMExec.cpp:213
JSBSim::FGJSBBase::fgred
static char fgred[6]
red text
Definition: FGJSBBase.h:139
JSBSim::FGFDMExec::GetPropagate
FGPropagate * GetPropagate(void)
Returns the FGPropagate pointer.
Definition: FGFDMExec.h:377
JSBSim::FGJSBBase::reset
static char reset[5]
resets text properties
Definition: FGJSBBase.h:129
JSBSim::FGFDMExec::GetDeltaT
double GetDeltaT(void) const
Returns the simulation delta T.
Definition: FGFDMExec.h:545
JSBSim::FGPropagate::GetAltitudeASLmeters
double GetAltitudeASLmeters(void) const
Returns the current altitude above sea level.
Definition: FGPropagate.h:335
JSBSim::FGJSBBase::underon
static char underon[5]
underlines text
Definition: FGJSBBase.h:131
JSBSim::FGJSBBase::normint
static char normint[6]
normal intensity text
Definition: FGJSBBase.h:127
JSBSim::FGFDMExec::Setdt
void Setdt(double delta_t)
Sets the integration time step for the simulation executive.
Definition: FGFDMExec.h:564
JSBSim::FGJSBBase::highint
static char highint[5]
highlights text
Definition: FGJSBBase.h:123
JSBSim::FGFDMExec::LoadModel
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:671
JSBSim::FGJSBBase::underoff
static char underoff[6]
underline off
Definition: FGJSBBase.h:133