FMI

FMI#

目前正在进行通过利用 libsumo 为 SUMO 构建 FMI v2 支持的工作。

目标#

最初的目标是构建一个原型,该原型能够通过 libsumocpp 加载和运行 SUMO 仿真,同时支持部分选定的 libsumo 函数。 目前,这些函数包括(参见 src/fmi/modelDescription.xml 中的 ScalarVariables):

  • vehicle.getIDCount
  • vehicle.moveToXY
  • vehicle.getParameterWithKey
  • vehicle.getLaneID
  • vehicle.getPosition

Note

libsumo 函数目前是为原型手动添加的。有计划为 FMI 自动生成可用的 libsumo 函数。

架构#

构建功能化仿真单元 (Functional Mockup Unit, FMU) 的当前架构如下(相应的源代码位于 src/fmi)。

uml diagram

FMU 用法#

由于 FMI 标准第 2 版 的限制(例如,输出标量变量不能直接赋予参数),我们实现了一种有状态的方法。 例如,如果我们需要车辆的当前位置,我们会检索 vehicle.getPosition 标量变量的(输出)值。 然而,由于上述 FMI v2 的限制,我们首先需要为 vehicle.getPosition 设置输入参数值,即车辆 ID。 为此,我们在检索输出变量值之前,利用通用的 setGetterParameters 输入标量变量,如下 Python 代码片段所示:

fmu.setString([valueRefs['setGetterParameters']], ["ego"])
resultList = fmu.getString([valueRefs['vehicle.getPosition']])

请注意,setGetterParameters 顾名思义,是一个通用的全能输入标量变量,用于为随后的输出标量变量值的检索设置输入参数。 在有多个输入参数的情况下,例如对于 vehicle.getParameterWithKey,参数值需要用空格分隔符连接成单个字符串。 同样,输出值也以相同的分隔符作为连接字符串返回:

fmu.setString([valueRefs['setGetterParameters']], ["ego meaningOfLife"])
resultList = fmu.getString([valueRefs['vehicle.getParameterWithKey']])
key = resultList[0].decode('UTF-8').split()[0]
value = resultList[0].decode('UTF-8').split()[1]

这种将值作为连接字符串传递的约定源于 FMI v2 的限制,即尚不支持向量和其他复杂数据类型。

使用 Python 连接 SUMO FMU#

FMPy Python 包可用于模拟和验证 FMU,是将 SUMO FMU 与 Python 连接的推荐方式。 在 Linux 上安装 FMPy 的方法如下:

` python -m pip install fmpy

开始使用 FMPy 的一种简单方法是查看位于 tests/complex/fmi 的 SUMO fmi 测试套件的 runner.py(上面的代码片段也可以在这里找到)。