本文主要是介绍KY-RTI分布仿真技术:第十章 Python程序设计,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本章讲述了如何基于Python设计聊天程序和时间管理程序,两个程序都是控制台程序,采用了与Java类似的设计风格。聊天程序相当于6.1节的Java聊天程序;时间管理程序相当于6.2节的Java程序。对于不同的程序设计语言而言,基于HLA/RTI设计仿真应用的方法都差不多,其关键在于RTI软件能否支持相应程序设计语言的开发,用户只需要关心一下调用接口即可,通过调用接口可以设计形式多样的程序。与C++、Java等调用接口的一个显著区别在于Python的变量没有类型定义,变量代表的类型可以从上下文了解,也可以参照其他编程语言的示例程序。
10.1 聊天程序
10.1.1需求分析
本项目需要实现一个类似微信群或者QQ群聊天功能的Python程序,每个人发送的消息都能够被群里的其他人看到。
10.1.2项目设计
每条聊天信息应包含2个内容:聊天者昵称、聊天的一句话,这样接收者就会知道是谁在发言。“聊天者昵称”用name表示,“聊天的一句话”用sentence表示,两个都是字符串类型。因为HLA是面向对象的,发送的数据要么采用对象类,要么采用交互类。本项目可采用交互类,将name和sentence封装到一个名叫“chat”的交互类中,如下列伪代码所示。
class chat { //交互类
string name; //参数
string sentence; //参数
}
下面采用KY-OMT创建fed文件,相应的chat.fed文件已经在3.3.3中创建完成,将该文件保存到KY-RTI的bin目录。
本项目对时间没有特别要求,不需要采用HLA时间管理机制。
10.1.3代码设计
该程序由3个源文件组成:GlobalVariables.py、Chat.py、HwFederateAmbassador.py。GlobalVariables.py定义了其他两个文件需要用到的公用变量;Chat.py调用RTI服务访问RTI;HwFederateAmbassador.py接收RTI回调服务。
GlobalVariables.py定义了可由Chat.py、HwFederateAmbassador.py共享使用的全局变量。
表10.1 Python聊天示例:GlobalVariables.py
|
Chat.py代码说明:
1行:Python 文件的UTF-8编码声明。如果没有该语句,则代码内的中文在python2中可能会报错;在python3中,UTF-8为默认的文件编码,该声明不是必需的。
13-27行:创建联邦执行;
29-37行:加入联邦执行;
40-42行:获取交互类及其参数句柄;
45行:公布交互类,只有公布之后才能够向RTI发送交互;
47行:订购交互类,只有订购之后才能够从RTI收到其他人的聊天内容;
50-61行:循环操作,每次输入一句话,并调用sendInteraction服务发送给RTI;当用户输入“exit”时则退出执行;
67-80行:退出联邦执行,不再参加仿真;
82-92行:销毁联邦。如果是最后一个仿真成员执行该操作,则整个仿真结束。
表10.2 Python聊天示例:Chat.py
|
HwFederateAmbassador.py代码说明:
8-9行:由于不处理时间参数,因此如果接收到这种类型的receiveInteraction交互,则直接调用不带时间参数的服务来统一处理;
11-23行:处理接收到的聊天信息,将其简单输出即可。
表10.3 Python聊天示例:HwFederateAmbassador.py
|
10.1.4测试运行
Python程序不需要编译,在运行时需要设置PYTHONPATH环境变量。在Linux操作系统上可按如下方式设置,如果module/python不存在,则作者没有在该版本中提供该功能。
export PYTHONPATH=$PYTHONPATH:${RTI_HOME}/${RTI_BUILD_TYPE}/module/python
测试项目:在Ubuntu1604操作系统上运行2个Python仿真成员,测试KY-RTI通信功能。
测试步骤:
第1步:修改RTI.rid,关闭tick开关。
因为本程序没有使用tick服务,所以需要关闭tick开关。
查看当前目录下是否存在RTI.rid,若没有则在运行程序之后会自动生成该文件。将RTI.rid文件中的“;; UsingTickSwitch On”改为“;; UsingTickSwitch Off”。
第2步:执行RTIManager.sh,启动KY-RTI控制台,如图10.1所示。注意,bin目录中configure.rti的IP地址和端口号,要与仿真程序目录中的RTI.rid一致。
第3步:如图10.2和图10.3所示,开启两个终端,运行2个仿真成员,开始仿真。运行命令:
python Chat.py
测试结果表明:KY-RTI支持基于麒麟操作系统的Python仿真技术,KY-RTI支持中英文传输。
图10.1 KY-RTI控制台
图10.2 Python聊天者1
图10.3 Python聊天者2
10.2 时间管理程序
10.2.1需求分析
本仿真项目的名称为“TimeManagementExample”,名称规定了不是“TimeManagementExample”的程序不属于本项目。对HLA/RTI程序来说,联邦名称为“TimeManagementExample”,不是该名字的仿真成员不属于本项目。
每个仿真成员拥有3架飞机,但其中只有1架飞机会起飞,飞机的x、y坐标为随机数(不考虑合理性),飞机会每隔1秒发布自己的位置信息。
10.2.2项目设计
飞机每隔1秒发布自己的位置信息,意味着该仿真应采用时间管理服务,仿真步长为1。
飞机发送的是自己的x、y二维态势信息,用一个对象类plane来封装,两个属性为xPos和yPos,类型为整型;但不管什么类型,在RTI中都是作为字符串来传送。如下列代码所示。
class plane { //对象类
int xPos; //属性
int yPos; //属性
}
下面采用KY-OMT创建fed文件,相应的tracer.fed文件已经在3.3.2中创建完成,将该文件保存到KY-RTI的bin目录。
10.2.3代码设计
该程序由3个源文件组成:GlobalVariables.py、TimeManagement.py、HwFederateAmbassador.py。GlobalVariables.py定义了其他两个文件需要用到的公用变量;Chat.py调用RTI服务访问RTI;HwFederateAmbassador.py接收RTI回调服务。
GlobalVariables.py定义了可由TimeManagement.py、HwFederateAmbassador.py共享使用的静态变量。
表10.4 Python时间管理示例:GlobalVariables.py
1. #coding:utf-8 2. 3. g_currentTime = 0.0 4. g_lookahead = 1.0 5. g_bConstrained = False 6. g_bRegulation = False 7. g_granted = False 8. 9. g_hxPos = 0 10. g_hyPos = 0 11. 12. #3 planes 13. g_hInstance1 = None 14. g_hInstance2 = None 15. g_hInstance3 = None |
TimeManagement.py代码说明:
1行:Python 文件的UTF-8编码声明。如果没有该语句,则代码内的中文在python2中可能会报错;在python3中,UTF-8为默认的文件编码,该声明不是必需的。
11行:联邦名称定义为“TimeManagementExample”;
15-29行:创建联邦执行;
31-39行:加入联邦执行;
42-44行:获取对象类及其属性句柄;
45行:设置属性集;
48行:公布对象类属性,只有公布之后才能够向RTI发送二维态势信息,即xPos和yPos;
50行:订购交互类属性,只有订购之后才能够从RTI收到二维态势信息;
52-57行:注册3架飞机;
63行:将仿真成员设置为时间管理受限的;
64-71行:等待RTI同意将该仿真成员设置为时间管理受限的;67行采用tick服务接收回调事件,因而RTI.rid中的tick标识应设置为真;若使用71行则不采用tick服务,则RTI.rid中的tick标识应设置为假。一旦tick标识设置为真,则整个仿真都采用tick服务接收回调事件;反之亦然;
73行:将仿真成员设置为时间管控成员;
74-81行:等待RTI同意将该仿真成员设置为时间管控成员;
83行:打开异步消息开关;
88行:仿真周期设置为1秒;这里的逻辑时间1对应物理时间的1秒(假设设置为2,则1个逻辑时间单位对应物理时间的0.5秒,2个逻辑时间单位对应仿真周期1秒);
91-177行:每隔1秒循环推进仿真,直到中断退出仿真;
109行:发送飞机在下一时刻的二维态势信息(如果采用RO消息也可以发送当前时刻的态势,当前或下一步信息依项目要求来抉择);
139行:将仿真请求推进到下一步;
140-147行:等待RTI同意该仿真成员推进到下一步;
179行:该行为注释行,表示仿真成员在结束时不需要调用'resignFederationExecution'和 'destroyFederationExecution'服务,RTI服务器会自动执行这两个服务。当然用户也可以写上这两个服务;
181-194行:退出联邦执行,不再参加仿真;
196-206行:销毁联邦。如果是最后一个仿真成员执行该操作,则整个仿真结束。
表10.5 Python时间管理示例:TimeManagement.py
1. #coding:utf-8 2. 3. from RTIambassador import * 4. from HwFederateAmbassador import * 5. import sys, traceback 6. import GlobalVariables 7. import time 8. import random 9. import pdb #pdb.set_trace() # 设置断点 10. 11. federationName = "TimeManagementExample" 12. federateName = raw_input("Please input your name: ") 13. rti = RTI_RTIambassador() 14. 15. try: 16. rti.createFederationExecution(federationName, "tracer.fed") 17. except RTI.FederationExecutionAlreadyExists: 18. # According to the HLA standard, only the first federate can call createFederationExecution successfully. Don't return. 19. # sys.exit(-1) #MUST not add this line 20. pass 21. except RTI.CouldNotOpenFED: 22. print("Error: Cannot open the fed file!") 23. sys.exit(-1) 24. except RTI.ErrorReadingFED: 25. print("Error: the fed file is not correct!") 26. sys.exit(-1) 27. except: 28. print("cannot create a federation execution") 29. sys.exit(-1) 30. 31. try: 32. federateHandle = rti.joinFederationExecution(federateName, federationName, HwFederateAmbassador()) 33. print("federateHandle: " + str(federateHandle)) 34. except RTI.CouldNotOpenFED: 35. print("FED_HW: CouldNotOpenFED") 36. sys.exit(-1) 37. except: 38. print("Failed to join federation execution") 39. sys.exit(-1) 40. 41. try: 42. hPlaneClass = rti.getObjectClassHandle("plane") 43. GlobalVariables.g_hxPos = rti.getAttributeHandle("xPos", hPlaneClass) #different from p1516 44. GlobalVariables.g_hyPos = rti.getAttributeHandle("yPos", hPlaneClass) #different from p1516 45. theAttributes = [GlobalVariables.g_hxPos, GlobalVariables.g_hyPos] 46. 47. #如果向外发送,则需要公布 48. rti.publishObjectClass(hPlaneClass, theAttributes) 49. #如果需要接收,则必须订购 50. rti.subscribeObjectClassAttributes(hPlaneClass, theAttributes) 51. 52. #register first plane 53. GlobalVariables.g_hInstance1 = rti.registerObjectInstance(hPlaneClass) 54. #register second plane 55. GlobalVariables.g_hInstance2 = rti.registerObjectInstance(hPlaneClass) 56. #register third plane 57. GlobalVariables.g_hInstance3 = rti.registerObjectInstance(hPlaneClass) 58. except: 59. print("FED_HW: Error to call RTI") 60. sys.exit(-1) 61. 62. try: 63. rti.enableTimeConstrained() 64. while not GlobalVariables.g_bConstrained: 65. #use tick 66. # RTI.rid: ';; UsingTickSwitch On' 67. rti.tick(0.001, 0.001) 68. 69. #don't use tick 70. # RTI.rid: ';; UsingTickSwitch Off' 71. #time.sleep(0.001) #1 millisecond 72. 73. rti.enableTimeRegulation(0.0, GlobalVariables.g_lookahead) 74. while not GlobalVariables.g_bRegulation: 75. #use tick 76. # RTI.rid: ';; UsingTickSwitch On' 77. rti.tick(0.001, 0.001) 78. 79. #don't use tick 80. # RTI.rid: ';; UsingTickSwitch Off' 81. #time.sleep(0.001) #1 millisecond 82. 83. rti.enableAsynchronousDelivery() 84. except: 85. print("FED_HW: Error to call RTI") 86. sys.exit(-1) 87. 88. intervalTime = 1 89. tag = "Python" 90. step = 0 91. while True: 92. step = step + 1 93. print("Step: " + str(step)) 94. xPos = random.randint(0, 10000) 95. yPos = random.randint(0, 10000) 96. 97. s1 = RTI.HandleValuePair() 98. s1.aHandle = GlobalVariables.g_hxPos 99. #如果两个仿真成员采用不同语言编程,则应转为字符串再发送 100. s1.aValue = str(xPos) 101. 102. s2 = RTI.HandleValuePair() 103. s2.aHandle = GlobalVariables.g_hyPos 104. #如果两个仿真成员采用不同语言编程,则应转为字符串再发送 105. s2.aValue = str(yPos) 106. 107. theAttributes = [s1, s2] 108. try: 109. rti.updateAttributeValues(GlobalVariables.g_hInstance1, theAttributes, GlobalVariables.g_currentTime + GlobalVariables.g_lookahead, tag) 110. except RTI.ObjectNotKnown: 111. print("Exception: RTI.ObjectNotKnown") 112. sys.exit(-1) 113. except RTI.AttributeNotDefined: 114. print("Exception: RTI.AttributeNotDefined") 115. sys.exit(-1) 116. except RTI.AttributeNotOwned: 117. print("Exception: RTI.AttributeNotOwned") 118. sys.exit(-1) 119. except RTI.InvalidFederationTime: 120. print("Exception: RTI.InvalidFederationTime") 121. sys.exit(-1) 122. except RTI.FederateNotExecutionMember: 123. print("Exception: RTI.FederateNotExecutionMember") 124. sys.exit(-1) 125. except RTI.SaveInProgress: 126. print("Exception: RTI.SaveInProgress") 127. sys.exit(-1) 128. except RTI.RestoreInProgress: 129. print("Exception: RTI.RestoreInProgress") 130. sys.exit(-1) 131. except: 132. print("FED_HW: Error to call RTI") 133. sys.exit(-1) 134. 135. targetTime = GlobalVariables.g_currentTime + intervalTime 136. print("This federate will advance to "+str(targetTime)) 137. 138. try: 139. rti.timeAdvanceRequest(targetTime) 140. while not GlobalVariables.g_granted: 141. #use tick 142. # RTI.rid: ';; UsingTickSwitch On' 143. rti.tick(0.001, 0.001) 144. 145. #don't use tick 146. # RTI.rid: ';; UsingTickSwitch Off' 147. #time.sleep(0.001) #1 millisecond 148. 149. GlobalVariables.g_granted = False 150. print("The federate has advanced to "+str(GlobalVariables.g_currentTime)+"\n") 151. except RTI.InvalidFederationTime: 152. print("Exception: RTI.InvalidFederationTime") 153. sys.exit(-1) 154. except RTI.FederationTimeAlreadyPassed: 155. print("Exception: RTI.FederationTimeAlreadyPassed") 156. sys.exit(-1) 157. except RTI.TimeAdvanceAlreadyInProgress: 158. print("Exception: RTI.TimeAdvanceAlreadyInProgress") 159. sys.exit(-1) 160. except RTI.EnableTimeRegulationPending: 161. print("Exception: RTI.EnableTimeRegulationPending") 162. sys.exit(-1) 163. except RTI.EnableTimeConstrainedPending: 164. print("Exception: RTI.EnableTimeConstrainedPending") 165. sys.exit(-1) 166. except RTI.FederateNotExecutionMember: 167. print("Exception: RTI.FederateNotExecutionMember") 168. sys.exit(-1) 169. except RTI.SaveInProgress: 170. print("Exception: RTI.SaveInProgress") 171. sys.exit(-1) 172. except RTI.RestoreInProgress: 173. print("Exception: RTI.RestoreInProgress") 174. sys.exit(-1) 175. except: 176. print("FED_HW: Error to call RTI") 177. sys.exit(-1) 178. 179. #After the program exits, the RTI will automatically calls 'resignFederationExecution' and 'destroyFederationExecution'. Of course, you can write them for yourself. 180. 181. try: 182. rti.resignFederationExecution( RTI.ResignAction.DELETEOBJECTSANDRELEASEATTRIBUTES ) 183. except RTI.FederateOwnsAttributes: 184. print("FED_HW: FederateOwnsAttributes") 185. sys.exit(-1) 186. except RTI.FederateNotExecutionMember: 187. print("FED_HW: FederateNotExecutionMember") 188. sys.exit(-1) 189. except RTI.InvalidResignAction: 190. print("FED_HW: InvalidResignAction") 191. sys.exit(-1) 192. except: 193. print("FED_HW: ResignFederationExecution") 194. sys.exit(-1) 195. 196. try: 197. rti.destroyFederationExecution( federationName ) 198. except RTI.FederatesCurrentlyJoined: 199. print("FED_HW: FederatesCurrentlyJoined") 200. sys.exit(-1) 201. except RTI.FederationExecutionDoesNotExist: 202. print("FED_HW: FederationExecutionDoesNotExist") 203. sys.exit(-1) 204. except: 205. print("FED_HW: Failed to destroyFederationExecution") 206. sys.exit(-1) |
HwFederateAmbassador.py代码说明:
8-9行:将发现的飞机输出到终端;
11-25行:将收到的飞机态势信息输出到终端;
27-30行:RTI同意将仿真成员设置为时间管控成员;
32-35行:RTI同意将仿真成员设置为时间管理受限的成员;
37-40行:RTI同意仿真成员推进到下一步。
表10.6 Python时间管理示例:HwFederateAmbassador.py
1. #coding:utf-8 2. 3. import sys, traceback 4. from RTIFederateAmbassador import * 5. import GlobalVariables 6. 7. class HwFederateAmbassador(RTIFederateAmbassador): 8. def discoverObjectInstance(self, theObject, theObjectClass, theObjectName): 9. print("discoverObjectInstance: "+str(theObject)+","+str(theObjectClass)+","+theObjectName) 10. 11. def reflectAttributeValuesWithTime(self, theObject, theAttributes, theTime, theTag, theHandle): 12. self.reflectAttributeValues(theObject, theAttributes, theTag) 13. 14. def reflectAttributeValues(self, theObject, theAttributes, theTag): 15. print("reflectAttributeValues: " + str(theObject)) 16. 17. for item in theAttributes: 18. if item.aHandle == GlobalVariables.g_hxPos: 19. print(" <"+str(item.aHandle)+","+item.aValue+">") 20. elif item.aHandle == GlobalVariables.g_hyPos: 21. print(" <"+str(item.aHandle)+","+item.aValue+">") 22. else: 23. print("Receive wrong parameter handle.") 24. 25. print(" tag:" + theTag) 26. 27. def timeRegulationEnabled(self, theFederateTime): 28. GlobalVariables.g_currentTime = theFederateTime 29. GlobalVariables.g_bRegulation = True 30. print("timeRegulationEnabled: " + str(theFederateTime)) 31. 32. def timeConstrainedEnabled(self, theFederateTime): 33. GlobalVariables.g_currentTime = theFederateTime 34. GlobalVariables.g_bConstrained = True 35. print("timeConstrainedEnabled: " + str(theFederateTime)) 36. 37. def timeAdvanceGrant(self, theTime): 38. GlobalVariables.g_currentTime = theTime 39. GlobalVariables.g_granted = True 40. print("timeAdvanceGrant: " + str(theTime)) |
10.2.4测试运行
参照10.1.4设置环境变量PYTHONPATH;因为本程序采用了tick服务,所以在RTI.rid中将tick标识设置为真,之后运行程序进行测试。
测试项目:在Ubuntu1604操作系统上运行2个Python仿真成员,两个仿真成员启动后尽可能快地向前推进;测试KY-RTI的HLA的基本服务功能,特别是时间管理同步功能。
测试步骤:
第1步:修改RTI.rid,打开tick开关。
因为本程序使用tick服务,所以需要打开tick开关。
查看当前目录下是否存在RTI.rid,若没有则在运行程序之后会自动生成该文件。保证RTI.rid文件中的“;; UsingTickSwitch On”设置正确。
第2步:执行RTIManager.sh,启动KY-RTI控制台,如图10.4所示。注意,bin目录中configure.rti的IP地址和端口号,要与仿真程序目录中的RTI.rid一致。
第3步:如图10.5和图10.6所示,开启两个终端,运行2个仿真成员,开始仿真。运行命令:
python TimeManagement.py
测试结果表明:KY-RTI支持基于Ubuntu1604操作系统的Python仿真技术,时间管理同步功能强。
测试说明:
(1)图10.5是仿真成员“Air01”被Ctrl+C中断执行时的界面。此时,它能收到仿真成员“Air02”发送的二维态势信息。
(2)图10.6是仿真成员“Air02”被Ctrl+C中断执行时的界面。此时,只显示它自己的运行信息,不会有其他仿真成员的二维态势信息。
图10.4 KY-RTI控制台
图10.5 使用时间管理服务的HLA仿真成员Air01
图10.6 使用时间管理服务的HLA仿真成员Air02
KY-RTI的Linux、Windows版本和源码请联系作者:walt_lbq@163.com
KY-RTI分布仿真技术:前 言
KY-RTI分布仿真技术:第一章 简介
KY-RTI分布仿真技术:第二章 系统安装
KY-RTI分布仿真技术:第三章 KY-OMT对象模型模板工具
KY-RTI分布仿真技术:第四章 C++程序设计
KY-RTI分布仿真技术:第五章 Qt程序设计
KY-RTI分布仿真技术:第六章 Java程序设计
KY-RTI分布仿真技术:第七章 Visual C++程序设计
KY-RTI分布仿真技术:第八章 Visual C#程序设计
KY-RTI分布仿真技术:第九章 综合演示
KY-RTI分布仿真技术:第十章 Python程序设计
KY-RTI分布仿真技术:附录1 分组聊天(HLA数据分发管理的应用)
KY-RTI分布仿真技术:附录2 大联邦(构建1000个成员的HLA/RTI仿真系统)
KY-RTI分布仿真技术:附录3 国产化(操作系统+CPUs)
这篇关于KY-RTI分布仿真技术:第十章 Python程序设计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!