Math ==== Functions --------- The function specification in JSBSim is a powerful and versatile resource that allows algebraic functions to be defined in a JSBSim configuration file. The function syntax is similar in concept to MathML (Mathematical Markup Language, https://www.w3.org/Math/), but it is simpler and more terse. A function definition consists of an operation, a value, a table, or a property (which evaluates to a value). The currently supported operations are: - ``sum`` (takes n arguments) - ``difference`` (takes n arguments) - ``product`` (takes n arguments) - ``quotient`` (takes 2 arguments) - ``pow`` (takes 2 arguments) - ``exp`` (takes 2 arguments) - ``abs`` (takes n arguments) - ``sin`` (takes 1 arguments) - ``cos`` (takes 1 arguments) - ``tan`` (takes 1 arguments) - ``asin`` (takes 1 arguments) - ``acos`` (takes 1 arguments) - ``atan`` (takes 1 arguments) - ``atan2`` (takes 2 arguments) - ``min`` (takes n arguments) - ``max`` (takes n arguments) - ``avg`` (takes n arguments) - ``fraction`` (takes 1 argument) - ``mod`` (takes 2 arguments) - ``lt`` (less than, takes 2 args) - ``le`` (less equal, takes 2 args) - ``gt`` (greater than, takes 2 args) - ``ge`` (greater than, takes 2 args) - ``eq`` (equal, takes 2 args) - ``nq`` (not equal, takes 2 args) - ``and`` (takes n args) - ``or`` (takes n args) - ``not`` (takes 1 args) - ``if-then`` (takes 2-3 args) - ``switch`` (takes 2 or more args) - ``random`` (Gaussian random number, takes no arguments) - ``integer`` (takes one argument) An operation is defined in the configuration file as in the following example: .. code-block:: xml 3.14159 velocities/qbar 0.125 metrics/wingarea In the example above, the ``sum`` element contains three other items. What gets evaluated is written algebraically as: .. math:: 3.14159 + \mathtt{qbar} + \big( 0.125 \cdot \mathtt{wingarea} \big) A full function definition, such as is used in the aerodynamics section of a configuration file, includes the function element and other elements. It should be noted that there can be only one non-optional (non-documentation) element, that is, one operation element, in the top-level function definition. The ```` element cannot have more than one immediate child operation, ``property``, ``table``, or ``value`` element. Almost always, the first operation within the function element will be a product or sum. For example: .. code-block:: xml Roll moment due to yaw rate aero/qbar-area metrics/bw-ft velocities/r-aero-rad_sec aero/bi2vel aero/alpha-rad 0.000 0.08 0.094 0.19 ... ...
The "lowest level" in a function definition is always a value or a property, which cannot itself contain another element. As shown, operations can contain values, properties, tables, or other operations. Some operations take only a single argument. That argument, however, can be an operation (such as ``sum``) which can contain other items. The point to keep in mind is any such contained operation evaluates to a single value, which is just what the trigonometric functions require (except ``atan2``, which takes two arguments). Finally, within a function definition, there are some shorthand aliases that can be used for brevity in place of the standard element tags. Properties, values, and tables are normally referred to with the tags ````, ````, and ````. Within a function definition only, those elements can be referred to with the tags ``

``, ````, and ````. Thus, the previous example could be written to look like this: .. code-block:: xml Roll moment due to yaw rate

aero/qbar-area

metrics/bw-ft

aero/bi2vel

velocities/r-aero-rad_sec

aero/alpha-rad 0.000 0.08 0.094 0.19 ... ... An example of tabular functions used in aerodynamic modeling is given by ground-effect factors affecting lift and drag. To see how the ground effect can be modelled in JSBSim one can look at the Cessna 172 Skyhawk model. This is implemented in the file ``/aircraft/c172p/c172p.xml``. In the ```` block of this XML file two non-dimensional factors are modeled, :math:`K_{C_D,\mathrm{ge}}` and :math:`K_{C_L,\mathrm{ge}}`, which are functions of the non-dimensional height above the ground and are to be thought of as multipliers of lift and drag, respectively. These factors are defined as follows: .. code-block:: xml Change in drag due to ground effect 1.0
aero/h_b-mac-ft 0.0000 0.4800 0.1000 0.5150 0.1500 0.6290 0.2000 0.7090 0.3000 0.8150 0.4000 0.8820 0.5000 0.9280 0.6000 0.9620 0.7000 0.9880 0.8000 1.0000 0.9000 1.0000 1.0000 1.0000 1.1000 1.0000
Change in lift due to ground effect 1.0 aero/h_b-mac-ft 0.0000 1.2030 0.1000 1.1270 0.1500 1.0900 0.2000 1.0730 0.3000 1.0460 0.4000 1.0550 0.5000 1.0190 0.6000 1.0130 0.7000 1.0080 0.8000 1.0060 0.9000 1.0030 1.0000 1.0020 1.1000 1.0000
The tabular functions ``aero/function/kCDge`` and ``aero/function/kCLge``, representing the factors :math:`K_{C_D,\mathrm{ge}}` and :math:`K_{C_L,\mathrm{ge}}`, are plotted in the JSBSim reference manual against non-dimensional ground altitude :math:`h/(b/2)`. Tables ------ One, two, or three dimensional lookup tables can be defined in JSBSim for use in aerodynamics and function definitions. For a single "vector" lookup table, the format is as follows: .. code-block:: xml property_name_1 key_1 value_1 key_2 value_2 ... ... key_n value_n
The ``lookup="row"`` attribute in the ```` element is optional in this case; it is assumed that the ``independentVar`` is a row variable. A real example is as shown here: .. code-block:: xml aero/alpha-rad -1.57 1.500 -0.26 0.033 0.00 0.025 0.26 0.033 1.57 1.500
The first column in the data table represents the lookup index (or breakpoints, or keys). In this case, the lookup index is ``aero/alpha-rad`` (angle of attack in radians). If ``aero/alpha-rad`` is :math:`0.26` radians, the value returned from the lookup table would be :math:`0.033`. The definition for a 2D table is as follows: .. code-block:: xml property_name_1 property_name_2 {col_1_key col_2_key ... col_n_key } {row_1_key} {col_1_data col_2_data ... col_n_data} {row_2_key} {... ... ... ... } { ... } {... ... ... ... } {row_n_key} {... ... ... ... }
The data is in a gridded format. A real example is shown below. Alpha in radians is the row lookup (alpha breakpoints are arranged in the first column) and flap position in degrees is split up in columns for deflections of 0, 10, 20, and 30 degrees: .. code-block:: xml aero/alpha-rad fcs/flap-pos-deg 0.0 10.0 20.0 30.0 -0.0523599 8.96747e-05 0.00231942 0.0059252 0.00835082 -0.0349066 0.000313268 0.00567451 0.0108461 0.0140545 -0.0174533 0.00201318 0.0105059 0.0172432 0.0212346 0.0 0.0051894 0.0168137 0.0251167 0.0298909 0.0174533 0.00993967 0.0247521 0.0346492 0.0402205 0.0349066 0.0162201 0.0342207 0.0457119 0.0520802 0.0523599 0.0240308 0.0452195 0.0583047 0.0654701 0.0698132 0.0333717 0.0577485 0.0724278 0.0803902 0.0872664 0.0442427 0.0718077 0.088081 0.0968405
The definition for a 3D table in a coefficient would be (for example): .. code-block:: xml property_name_1 property_name_2 property_name_3 {col_1_key col_2_key ... col_n_key } {row_1_key} {col_1_data col_2_data ... col_n_data} {row_2_key} {... ... ... ... } { ... } {... ... ... ... } {row_n_key} {... ... ... ... } {col_1_key col_2_key ... col_n_key } {row_1_key} {col_1_data col_2_data ... col_n_data} {row_2_key} {... ... ... ... } { ... } {... ... ... ... } {row_n_key} {... ... ... ... } ... {col_1_key col_2_key ... col_n_key } {row_1_key} {col_1_data col_2_data ... col_n_data} {row_2_key} {... ... ... ... } { ... } {... ... ... ... } {row_n_key} {... ... ... ... }
Note the ``breakpoint`` attribute in the ``tableData`` element above. Here is an example: .. code-block:: xml fcs/row-value fcs/column-value fcs/table-value -1.0 1.0 0.0 1.0000 2.0000 1.0 3.0000 4.0000 0.0 10.0 2.0 1.0000 2.0000 3.0 3.0000 4.0000 0.0 10.0 20.0 2.0 1.0000 2.0000 3.0000 3.0 4.0000 5.0000 6.0000 10.0 7.0000 8.0000 9.0000
Note that table values are interpolated linearly, and no extrapolation is done at the table limits. The highest value a table will return is the highest value that is defined. Interpolate 1D ~~~~~~~~~~~~~~ Some lookup tables in simulation, particularly for aerodynamic data, can be four, five, six, or even more dimensional. ``Interpolate1d`` returns the result from a 1-dimensional interpolation of the supplied values, with the value of the first immediate child element representing the lookup value into the table, and the following pairs of values representing the independent and dependent values. The first provided child element is expected to be a property. The interpolation does not extrapolate, but holds the highest value if the provided lookup value goes outside of the provided range. The format is as follows: .. code-block:: xml {property, value, table, function} {property, value, table, function} {property, value, table, function} ... Example: If mach is 0.4, the interpolation will return 0.375. If mach is 1.5, the interpolation will return 0.60. .. code-block:: xml

velocities/mach

0.00 0.25 0.80 0.50 0.90 0.60
The above example is very simplistic. A more involved example would use a function in any argument (except the first). That means that the breakpoint vector can be variable, but more importantly the values in the lookup vector (second column) could be function table elements of 1, 2, or 3 dimensions. The arguments could even be nested ``interpolate1d`` elements. For example: .. code-block:: xml

velocities/mach

0.00 ... table definition ...
0.80 ... table definition ...
0.90 ... table definition ...
Carrying this further: .. code-block:: xml

aero/qbar-psf

0

velocities/mach

0.00 ... table 1 definition ...
0.80 ... table 2 definition ...
0.90 ... table 3 definition ...
65

velocities/mach

0.00 ... table 1 definition ...
0.80 ... table 2 definition ...
0.90 ... table 3 definition ...
90

velocities/mach

0.00 ... table 1 definition ...
0.80 ... table 2 definition ...
0.90 ... table 3 definition ...
The above effectively gives a five-dimensional lookup table. It would be large in practice, but the format is valid. For very large aerodynamic databases there may be times when some coefficients do not need to be calculated. For instance, ground-effect aerodynamic coefficients only need to be calculated close to the ground. The ``ifthen`` element can bypass expensive computations. If the value of the first immediate child element is 1, then the value of the second immediate child element is returned, otherwise the value of the third child element is returned. .. code-block:: xml {property, value, table, or other function element} {property, value, table, or other function element} {property, value, table, or other function element} Example: if flight-mode is greater than 2, then a value of 0.00 is returned, otherwise the value of the property ``control/pitch-lag`` is returned. .. code-block:: xml

executive/flight-mode

2
0.00

control/pitch-lag

In this case, a 5-dimensional lookup can be wrapped to return zero unless a condition is true: .. code-block:: xml

position/altitudeMSL

90

aero/qbar-psf

0

velocities/mach

0.00 ... table 1 definition ...
0.80 ... table 2 definition ...
0.90 ... table 3 definition ...
65

velocities/mach

0.00 ... table 1 definition ...
0.80 ... table 2 definition ...
0.90 ... table 3 definition ...
90

velocities/mach

0.00 ... table 1 definition ...
0.80 ... table 2 definition ...
0.90 ... table 3 definition ...
0
The above example is intentionally schematic, but demonstrates the valid format and the performance-oriented use of conditional evaluation.