``. 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
0.80
0.90
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.