JSBSim 的函数定义方式功能强大,能够在配置文件中定义代数表达式。函数的语法和 MathML (Mathematical Markup Language, www.w3.org/Math/)相似,但是要更简洁。
函数(function)
函数的定义由操作符(operation)、数值(value)、表格(table)和属性(property)组成。当前 JSBSim 支持的操作符包含:
- 求和:sum
- 求乘:product
- 求商:quotient
- 乘方:pow
- 幂指数:exp
- 绝对值:abs
- 三角函数:sin, cos, tan
- 反三角函数:asin, acos, atan, atan2
- 最小、最大值:min, max
- 变量:avg
- 分数:fraction
- 整除:mod
- 随机数:random
- 微积分:difference, integer
在配置文件中,操作符的使用方法如下:
<sum>
<value>3.14159</value>
<property>velocities/qbar</property>
<product>
<value>0.125</value>
<property>metrics/wingarea</property>
</product>
</sum>
上述代码定义的运算或公式如下:
3.14159 + qbar + (0.125 * wingarea)
一个完整的函数定义应当包含函数元素(即 <function ...>)和其他元素两部分,如下文的气动力定义代码所示。值得注意的是,函数定义中只能有一个非选项型元素,如函数定义代码段中顶端处的代数运算符。也就是说, <function> 元素中不能有多个立即的子运算、属性、表格或者数值。几乎所有的情况下,函数元素的第一个运算符都是求乘(product)或者求和(sum),例如:
<function name="aero/coefficient/Clr">
<description>Roll moment due to yaw rate</description>
<product>
<property>aero/qbar-area</property>
<property>metrics/bw-ft</property>
<property>aero/bi2vel</property>
<property>velocities/r-aero-rad_sec</property>
<table>
<independentVar>aero/alpha-rad</independentVar>
<tableData>
0.000 0.08
0.094 0.19
</tableData>
</table>
</product>
</function>
如上述求和以及气动力定义代码所示,函数定义中最低一级总是数值(value)或者属性(property),在最低级别中的元素是不可以自身包含另外元素的。代码也显示,运算符代码段中是可以包含数值、属性、表格和其他运算符的。在运算中可以只包含一个输入,但是这个输入可以是单个变量或属性,也可以是嵌套的子运算(例如求和),再在自运算内包含其他更多的变量。但需要记住的是,只包含一个输入值的运算只有三角函数(atan2除外)。
译者注:
函数定义中提到的数值(value)、属性(property)、表格(table)和运算符(operation)是函数的四类基本元素,对于有一定编程基础的读者,可能保留英文原文更容易说明(下文将保留英文形式)。下面将四类元素进行列表说明:
- 运算符(operation):即加减乘除这些代数运算;
- 数值(value):特指具有固定大小的数字,可以理解为常数;
- 属性(property):程序中生成的相关变量,即上一章属性管理系统中介绍的属性;
- 表格(table):由数值组成的表格,主要应用于插值运算,因此需要声明独立变量(independentVar)。
在函数定义中,元素的表达可以采用缩写形式,当然也只有数值(value)、属性(property)、表格(table)和运算符(operation)四类元素可以采用缩写。例如,上述气动力定义代码段也可等效的写成如下形式:
<function name="aero/coefficient/Clr">
<description>Roll moment due to yaw rate</description>
<product>
<p>aero/qbar-area</p>
<p>metrics/bw-ft</p>
<p>aero/bi2vel</p>
<p>velocities/r-aero-rad_sec</p>
<t>
<independentVar>aero/alpha-rad</independentVar>
<tableData>
0.000 0.08
0.094 0.19
</tableData>
</t>
</product>
</function>
表格(table)
在四个元素中,表格的定义相对特殊。JSBSim 中的表格可以是一维、二维和三维形式,通常用于气动力的插值运算(译者注:这里的表格应当理解为表格和插值运算的结合体)。一个单向量插值运算定义形式如下:
<table>
<independentVar lookup="row">property_name</independentVar>
<tableData>
key_1 value_1
key_2 value_2
... ...
</tableData>
</table>
这里,用于插值的独立变量是可选的,一方面独立变量本身需要进行声明(property_name),另一方面插值表格的矢量形式也可以声明(lookup="row" 选择按行插值)。上述模板表明,以 property_name 为独立变量并且按照行插值的形式进行运算。
一个二维表格的定义如以下代码段所示:
<table>
<independentVar lookup="row">property_name</independentVar>
<independentVar lookup="column">property_name</independentVar>
<tableData>
{col_1_key} {col_2_key} {...} {col_n_key}
{row_1_key} {value_11} {value_12} {...} {value_1n}
{row_2_key} {value_21} {value_22} {...} {value_2n}
{...} ... ... ... ...
{row_n_key} {value_n1} {value_n2} {...} {value_nn}
</tableData>
</table>
如代码所示,二维表格采用的是网格输入形式,分别按照行和列进行二维插值,用于行和列索引的独立变量也需要声明。
三维表格则是将其拆分为多个二维表格的形式进行代码输入,代码段格式如下:
<table>
<independentVar lookup="row">property_name</independentVar>
<independentVar lookup="column">property_name</independentVar>
<independentVar lookup="table">property_name</independentVar>
<tableData breakpoint="table_1_key">
{col_1_key} {col_2_key} {...} {col_n_key}
{row_1_key} {value_11} {value_12} {...} {value_1n}
{row_2_key} {value_21} {value_22} {...} {value_2n}
{...} ... ... ... ...
{row_n_key} {value_n1} {value_n2} {...} {value_nn}
</tableData>
<tableData breakpoint="table_2_key">
{col_1_key} {col_2_key} {...} {col_n_key}
{row_1_key} {value_11} {value_12} {...} {value_1n}
{row_2_key} {value_21} {value_22} {...} {value_2n}
{...} ... ... ... ...
{row_n_key} {value_n1} {value_n2} {...} {value_nn}
</tableData>
...
<tableData breakpoint="table_n_key">
{col_1_key} {col_2_key} {...} {col_n_key}
{row_1_key} {value_11} {value_12} {...} {value_1n}
{row_2_key} {value_21} {value_22} {...} {value_2n}
{...} ... ... ... ...
{row_n_key} {value_n1} {value_n2} {...} {value_nn}
</tableData>
</table>
注意:JSBSim中表格的插值都采用线性内插算法,并不具备外插功能,即输入的最大值只能返回到表格中的最大索引对应数值。
至此,相信读者已经能够在 XML 配置文件中完成数学公式的输入了,后续将围绕具体物理变量开展飞行参数的学习。
网友评论