HLA 监听器





5.00/5 (1投票)
HLA 仿真和 HLA 监听器简介
引言
仿真是一种试图在虚拟环境中模仿真实世界的流程。它是一种经济的过程,无需实验设置或特殊设备即可用于测试不同的场景。
仿真有许多类型;今天我将讨论“高层体系结构(HLA)”,它是一种通用的仿真,将虚拟环境分解为独立的组件;每个组件负责特定的任务并具有与其他组件通信的接口。
HLA借鉴了面向对象编程(OOP)的概念;它由一个应用程序(称为联邦)组成,该应用程序又由几个对象(称为联邦成员)组成。与OOP中一样,每个联邦成员执行一些任务并与其他联邦成员交互。然而,在分布式仿真中,每个联邦成员可能运行在不同的机器上,并通过一个中央枢纽(称为RTI)相互通信,如下图所示。
图1 联邦成员通过RTI通信
一段历史
HLA在90年代中期出现在军事领域;但现在它是一个由IEEE规范和发布的标准化仿真。该标准有三个版本
- HLA 1.3(1998年发布)
- HLA 1516(2000年发布,IEEE首次发布)
- HLA 1516 Evolved(称为HLA1516e和HLA1516-2010,2010年发布);这是最新版本(https://standards.ieee.org/findstds/standard/1516-2010.html)。
HLA组件
RTI
RTI是HLA标准中的关键组件,它创建联邦并提供联邦成员之间相互通信的基础设施。RTI必须通过实现HLA社区提供的Java和/或C++接口中的所有方法(http://standards.ieee.org/downloads/1516/1516.1-2010/IEEE1516-2010_Java_API.zip)来完全符合标准。
不幸的是,没有完全符合标准的开源RTI。但是,您可以获得两个商业RTI(Pitch RTI、MAK RTI)的免费版本,但每个联邦成员的数量限制为2个。
联邦成员
HLA仿真的第二个关键组件是联邦成员。这是一段引用RTI库的代码,用于与其他联邦成员发送/接收消息。因为所有RTI都实现了相同的接口,所以您可以编写引用RTI库的代码,并且只需更改引用的库即可与其他RTI一起工作。
联邦成员不必是全新的代码;可以通过编写一小段在现有软件和RTI之间传输数据的代码,将现有软件用作联邦成员。例如,可以为AutoCAD或Excel等编写插件,以在仿真中利用其功能,如示例部分所示。
FOM
为了发送/接收消息,联邦成员必须就将发送的内容达成一致(例如,消息名称、数据类型等)。这通过一个称为联邦对象模型(FOM)的XML文件完成,该文件可以通过一个名为“simGe”的免费软件生成(http://www.ceng.metu.edu.tr/~otopcu/simge/)。HLA社区为寿司餐厅仿真开发了一个示例FOM(http://standards.ieee.org/downloads/1516/1516.2-2010/RestaurantFOMmodule.xml)。
一个例子:交通仿真
为了阐明HLA仿真概念,让我们想象我们正在尝试开发一个交通系统仿真;该系统将用于调查以下参数的影响
- 天气
- 道路宽度
- 最大速度
- 驾驶员专业知识
一旦所有目标都定义完毕,我们就可以开始定义联邦成员。定义联邦成员没有硬性规定,但直观地说,我们可以说我们将有以下联邦成员
- 道路联邦成员:用于规划道路、安排道路维护等。
- 天气联邦成员:提供天气更新(例如,降水)。
- 交通控制器联邦成员:如交通灯等人员。
- 驾驶员联邦成员:模拟汽车运动。
- 可视化工具:向最终用户直观地显示仿真。
不同的团队可能负责不同的联邦成员。每个团队可以使用不同的编程语言(这是HLA仿真强大的一面)来开发他们的联邦成员。此外,并非所有联邦成员都必须从头开始编写;例如,对于可视化联邦成员,我们可以通过开发插件来可视化RTI的更新,从而调整现有软件(例如,Unity或WPF)。
在开发他们的联邦成员之前,所有团队都必须就联邦FOM达成一致。FOM是一个XML文件,包含两个重要部分:“对象类”和“交互类”;这两个部分指定联邦成员将发布什么。例如,我们可能有一个“HourlyWeather”对象类,其属性如下
<objectClass>
<name>HourlyWeather</name>
<sharing>PublishSubscribe</sharing>
<attribute>
<name>WindSpeed</name>
<dataType>HLAfloat64Time</dataType>
<updateType>Static</updateType>
<ownership>NoTransfer</ownership>
<sharing>PublishSubscribe</sharing>
<transportation>HLAreliable</transportation>
<order>TimeStamp</order>
</attribute>
<attribute>
<name>Temperature</name>
<dataType>HLAfloat64Time</dataType>
<updateType>Static</updateType>
<ownership>NoTransfer</ownership>
<sharing>PublishSubscribe</sharing>
<transportation>HLAreliable</transportation>
<order>TimeStamp</order>
</attribute>
</objectClass>
我们还可以有一个“RoadClosure”交互类,其中包含一个属性“RoadID”
<interactionClass>
<name>RoadClosure</name>
<sharing>PublishSubscribe</sharing>
<transportation>HLAreliable</transportation>
<order>Receive</order>
<parameter>
<name>RoadID</name>
<dataType>HLAunicodeString</dataType>
</parameter>
</interactionClass>
注意:完整的FOM文件可以从顶部的链接下载。
请注意,FOM文件并未说明哪个联邦成员将发布/订阅对象和交互类;它只是指定将发布/订阅什么,每个联邦成员在加入联邦后应告知RTI将发布/订阅什么。因此,在我们的示例中,在加入联邦后,天气联邦成员应通知RIT它将发布“HourlyWeather”,而驾驶员联邦成员将订阅它。因此;每当天气联邦成员发送“HourlyWeather”更新时,它将由RTI转发给驾驶员联邦成员。我应该在这里提到,每个对象/交互类可能有一个以上的发布者/订阅者。
注意:联邦可能拥有多个FOM,RTI将根据某些规则自动将它们合并为一个文件,但这超出了本文的范围。
HLA 监听器
目标
HLA仿真有一个非常陡峭的学习曲线,需要大量努力才能理解其所有概念。因此,我开发了一个名为“HLA Listener”的小应用程序,用于调试和学习HLA概念。
HLA Listener是一个带有GUI的联邦成员,完成后将实现标准中的所有方法。它可用于在深入研究代码之前消化所有HLA概念。我可以安全地说,即使凭借我在编写联邦成员代码方面的经验,我也从这个工具中学到了很多,因为它使我能够通过几次点击回答任何“如果”问题。
接口
HLA Listener是一个Maven开源项目,托管在GitHub上(https://github.com/EMostafaAli/HlaListener)。
要使用此软件,首先安装任何完全符合标准的RTI(我推荐使用Pitch RTI),然后运行HLA Listener并选择库jar文件(图2)。之后,您将看到主窗口,如图3所示。强烈建议运行两个版本的此工具,以查看通信如何通过RTI发生。
图2 第一步选择HLA库
图3 HLA Listener主窗口
代码
注意:此处的所有示例均摘自GitHub存储库。
在运行时加载jar文件
因为所有完全符合标准的RTI都必须实现完全相同的接口,所以我基于此接口构建了我的应用程序,并且在运行时用户必须提供实际的实现,该实现将添加到类路径中,如下所示
private static int AddtoBuildPath(File f) {
logger.entry();
try {
URI u = f.toURI();
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<URLClassLoader> urlClass = URLClassLoader.class;
Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(urlClassLoader, new Object[]{u.toURL()});
} catch (NoSuchMethodException | SecurityException | IllegalArgumentException |
InvocationTargetException | MalformedURLException | IllegalAccessException ex) {
logger.log(Level.FATAL, "Error adding the jar file to the class path", ex);
return 1;
}
logger.exit();
return 0;
}
之后,我们必须使用“getRtiFactory”方法来获取指向实际RTI实现(称为RTI大使)的指针。
URL[] urls = new URL[]{file.toURI().toURL()};
URLClassLoader child = new URLClassLoader(urls, this.getClass().getClassLoader());
Class RtiFactoryFactory = Class.forName("hla.rti1516e.RtiFactoryFactory", true, child);
Method getRtiFactory = RtiFactoryFactory.getMethod("getRtiFactory");
rtiFactory = (RtiFactory) getRtiFactory.invoke(null);
rtiAmb = rtiFactory.getRtiAmbassador();
发送到RTI
一旦我们有了指向RTI大使的指针,我们就可以通过调用相应的方法发送请求;以下代码连接到RTI,创建一个联邦,然后加入联邦
rtiAmb.connect(fedAmb, CallbackModel_choiceBox.getValue());
rtiAmb.createFederationExecution(FederationExecutionName.getText(), foms.toArray(new URL[foms.size()]), LogicalTimeImplementation.getValue());
rtiAmb.joinFederationExecution(FederateType.getText(), FederationExecutionName.getText());
从RTI接收
上面的代码展示了如何向RTI发送请求;为了从RTI接收回调,我们必须扩展“NullFederateAmbassador”抽象类并覆盖其方法。以下代码在连接丢失的情况下向控制台写入消息。
public class ListenerFederateAmb extends NullFederateAmbassador {
//Section 4.4 in standards
@Override
public void connectionLost(String faultDescription) throws FederateInternalError {
System.out.println("Unfortunately, connection to RTI Lost. Try to reconnect");
}
}
到目前为止的进展
到目前为止,我已实现标准中的以下章节
- 第4章:连接到RTI、创建联邦、加入联邦等。
- 第5章:发布/订阅属性和交互
- 第8章:时间管理。
- 其余章节中的零散项目。
接下来是什么?
这是提高对HLA仿真认识的一个初步步骤,希望这将导致开发一个免费的RTI。如果您是HLA仿真新手,请下载代码,构建它,然后自学。如果您熟悉HLA,请随时帮助我实现标准。
结论
我尽力使本文简洁;因此,我没有过多讨论HLA概念(例如,时间管理),也没有彻底审查代码。但是,如果需要,我可以撰写一系列解释HLA概念的文章。我还可以提供使用HLA Listener的分步教程,但我不能确定这是否符合Codeproject的主题。
历史
- 2015年5月24日:初始版本
- 2015年5月25日:扩展文章,添加示例代码,并调整图片大小