编写于:2022.06.23
更新于:2023.04.07
1前言
本人交通工程专业,研一论文实验需要在一条双向4车道高速公路上制造一个事故点,模拟高速公路交通事故,起初想着只能二次开发才行。后来读了知网的一些文献,发现其实用VISSIM的停车场(Parking Lots)模块结合停车路径和停车时间分布即可。然后就一直没有碰VISSIM了。
不得不说VISSIM其实挺好用的,本科只要是交通工程的都学过,当然也有一堆缺点:例如破解版只有4.30,并且每次还需要修改电脑时间才能用,没有中文选项。
虽然5.00和5.20等等之后的版本有中文,但要么是学生版,要么是教学版,com接口用不了,路网长度、仿真时间有限制,作为一个穷学生也买不起正版,毕竟一个版本10万以上。而且PTV公司也比较坑,要花钱升级新版本,我们整个交通系也只有一个正版的8.0好像,每次只能一个人用插U盘。
当然现在已经告别VISSIM了,毕竟有了SUMO,相比于VISSIM的com接口,SUMO真是好用多了traci直接通过python导入随便用,而VISSIM4.3推荐的语言是VB和JS,作为一个只会python的有点难。不过尽管VISSIM好多缺点,但是有一个最好的就是可视化,可以很真实的给相关人员展示。
所以我的建议是两个软件都用,各有千秋。VISSIM可以快速上手,SUMO中的模型还是不太好(目前最新版1.13.0),全英文,教程还有软件汉化等方面资料贼少,需要自己探索。官网:Eclipse SUMO - Simulation of Urban MObility
因此对于VISSIM还有最后一点残念的我,在研二暑假总结一下com接口相关内容,结合网上教程(真的是五花八门,有用的少的可怜),算是给VISSIM画上个句号。
2是否能通过python调用
答案是肯定的!
翻看4.3版本安装目录下doc文件夹下全部自带资料(pdf文档)也没找到一个python有关的,不过最后还是在软件内部找到一个,侧面说明了4.3版本其实可以支持python语言,尽管官方文档没有说,这也坚定了我接下来尝试的信心。
这个代码建议稍微看一看,它是用python2写的而且各种函数还不完整,本人试了一下报错很多,但是可以作为一个例子提供一些思路。
3一些相关的调用命令
下面是一些本人后来研究的一些调用命令。
编辑器:PyCharm 2021.1 (Professional Edition)
解释器:python3.9
VISSIM:4.30
3.1创建路网
通过VISSIM直接创建一个单向3车道的城市道路并且分流一部分车辆驶入高速公路,一部分继续在城市道路行驶。总共有2000辆,车辆构成默认,仿真时间600s。(建议直接手动创建,用代码会有点麻烦)。
对于仿真时间这里一定要重点设置一下,搞不懂的可以去看手册,必须像我这样设置,也就是仿真里面的1s等于现实里的1s。
然后会出现一个**.inp文件**,这里面有vissim仿真运行的所有信息。
下面就通过python调用vissim,具体还需要一些文档就是vissim安装文件夹下的com接口那个文档,虽然用不上但是会给我们python代码提供思路。
其中有一个图也很重要:
3.2仿真参数设置
连接vissim,并进行主要仿真参数的设置。
#0.导入库(具体这个库参考其他资料)
import win32com.client #主要库
import time #不重要
#1.连接VISSIM并创建VISSIM对象
vissim = win32com.client.gencache.EnsureDispatch("Vissim.Vissim.430") #最后数字为版本号
print(vissim)
#2.加载路网(我们在绘制路网的时候通常会导入一张背景图,然后在上面绘制,注意这里仅加载路网不加载背景图)
filename = r"G:\python_VissimCom\01 obtain vehicle information\basehighway.inp" #好像不能用相对路径
vissim.LoadNet(filename)
#3.仿真参数设置
#仿真时长
period = vissim.Simulation.Period #读取仿真时长
print("仿真时长:",period)
period = vissim.Simulation.AttValue('Period') #另一种方式读取
print("仿真时长:",period)
vissim.Simulation.Period =3600 #更改仿真时长为3600s
print("仿真时长:",vissim.Simulation.Period)
vissim.Simulation.SetAttValue('Period', 1200) #另一种方法更改
print("仿真时长:",vissim.Simulation.Period)
#随机种子
randomseed = vissim.Simulation.RandomSeed #读取随机种子
print("随机种子:",randomseed)
vissim.Simulation.SetAttValue('RandomSeed', 35) #更改随机种子
print("仿真时长:",vissim.Simulation.RandomSeed)
<win32com.gen_py.VISSIM_COMServer 4.30 Type Library.IVissim instance at 0x1769233895280>
仿真时长: 600.0
仿真时长: 600.0
仿真时长: 3600.0
仿真时长: 1200.0
随机种子: 42
仿真时长: 35
这里我们设置完成了,需要注意我们原始路网仿真时间设定为600s,然后更改为3600s,再更改为1200s,那么我手动打开.inp文件,里面的仿真时间会不会变成1200s?答案是不会的,所以我们可以在python里面任意操作,都不会影响基础路网信息。
设置好仿真参数就可以开始运行python代码进行仿真。
#仿真形式
# #仿真连续运行到结束
# vissim.Simulation.RunContinuous()
#仿真单步运行
for i in range(1,601): #仿真时长
print(i)
vissim.Simulation.RunSingleStep()#一步一步仿真直到仿真时间结束
#停止仿真
vissim.Simulation.Stop()
还有一些其他的就不额外说明了,可以参考文档,哪些参数可以读写。
3.3车辆信息获取
如果你的基础仿真时间数据按照我之前那样设置了,那么这里循环600次,每次循环就代表实际仿真时间运行1s。对于车辆信息的获取可以一次获取所有车辆的信息如下:
for i in range(1,601): #仿真时长
print("当前仿真时刻:",i)
vissim.Simulation.RunSingleStep() #一步一步仿真直到仿真时间结束
#4.获取车辆信息
#对总车辆的操作
vehicles = vissim.Net.Vehicles #当前仿真时刻整个道路上的车辆集合
vehicles_count = vehicles.Count #当前仿真时刻整个道路上的车辆总数
print("车辆总数:",vehicles_count)
vehicles_id = vehicles.IDs
print("车辆编号:", vehicles_id) #当前仿真时刻整个道路上的车辆编号集合
或者获取指定车辆的信息,如下:
for vehicle in vehicles: #遍历当前仿真时刻道路上所有的车(如果道路上没有车辆则输出为空)
print(vehicle.ID,vehicle.AttValue('SPEED'),vehicle.AttValue('ELAPSEDTIME'),vehicle.AttValue('TOTALDISTANCE'))
通过遍历所有车辆来操作,具体可以获取单个车辆的哪些信息可以参照说明文档。
在编写程序中如果想要获得指定ID的车辆的信息,还可能出现下面的报错
for i in range(1,601): #仿真时长
print("当前仿真时刻:",i)
vissim.Simulation.RunSingleStep() #一步一步仿真直到仿真时间结束
vehicle_id = vehicles.Item(1).AttValue('ID')
print(vehicle_id)
vehicle_id = vehicles(1).AttValue('ID')
print(vehicle_id)
Traceback (most recent call last):
File "G:\python_VissimCom\01 obtain vehicle information\pythonObtainVehicleInformation.py", line 57, in <module>
vehicle_id = vehicles.Item(1).AttValue('ID')
AttributeError: 'NoneType' object has no attribute 'AttValue'
具体原因就是在仿真的时候这辆车并不是第一时间出现在车道上,因此此时车辆各种属性都为空,所以会发生获取不到的错误。所以在编写程序的时候需要进行判断。
for i in range(1,601): #仿真时长
print("当前仿真时刻:",i)
vissim.Simulation.RunSingleStep() #一步一步仿真直到仿真时间结束
#print(vehicles.GetVehicleByNumber(1)) #获取指定ID的车辆的信息
if vehicles.GetVehicleByNumber(1) == None:
vissim.Simulation.RunSingleStep()
else:
vehicle_speed = vehicles.GetVehicleByNumber(1).AttValue('SPEED')
vehicle_elapsedtime = vehicles.GetVehicleByNumber(1).AttValue('ELAPSEDTIME')
vehicle_totaldistance = vehicles.GetVehicleByNumber(1).AttValue('TOTALDISTANCE')
print(vehicle_speed,vehicle_elapsedtime,vehicle_totaldistance)
这样就能获取指定车辆的信息,我获取了速度,在路网中的时间和行驶距离。
4后续
如果继续从事交通仿真并有时间就会更新,之后会尝试其他一些vissim二次开发,会通过不同的项目给展示出来。
不过相信通过上述简单的介绍结合com文档(虽然并不含有python代码)但是已经可以用python进行操作了,不断地试错不断地进步,进一步模拟自动驾驶,交叉口优化等等。
此后的更新将在notion发布:notion_pythonVissimCom
https://mdddhtj.notion.site/python_VissimCom-6a24715bbffe48fe9aa2de40a8ee7529
完整代码和文档参见Gitee:
https://gitee.com/mdddhtj/python_-vissim-com.git