TraCI 是交通控制接口(Traffic Control Interface)的简称,通过该接口与模拟器进行通信,可以实现对 SUMO 仿真中的实时交通信息获取和控制仿真对象的形为,与外界进行实时性的交互,极大提高了仿真性能。例如,在一个发生交通堵塞的场景中,可以通过 TraCI 接口获取当前车辆的位置和行驶路线信息,可以在线为车辆重新规划路线,调整既定信号灯相位配时等方法缓解交通拥堵。
使用 TraCI 首先要为其配置环境变量,SUMO 中的许多工具要求将环境变量 SUMO_HOME 设置为 SUMO 安装的基本目录,包含文件夹bin和tools的目录。使用命令行运行程序,必须配置 Path 变量和SUMO_HOME 变量。
打开环境变量页面,点击 “新建” ,输入变量名 SUMO_HOME ,变量值为 SUMO 的安装路径。
如果已经有 Path 变量,双击变量值为其添加新的值即可,如果没有,需要新建该变量并为其添加值,变量值为 bin 文件夹的路径。
至此,环境变量配置完毕。
TraCI 接口目前支持包括 Python, Java, C++,.NET 等多种主流语言,其中 python 语言的功能最为完善,实现相对简单。
在使用 TraCI 前需要将其安装到 Python 的加载路径上,TraCI 位于 SUMO 安装目录下 tools->traci 文件夹中,打开可以看到 TraCI 的一系列功能函数,我们需要将 tools 目录加载到 Python 中。
打开 Python 安装目录,E:\python\Lib\site-packages,新建文本文档 traci.txt,在其中输入 tools 目录的位置:E:\SUMO\tools ,最后将文件后缀改为 .pth 即可。
可以在命令行中检查 TraCI 是否安装成功
TraCI 命令可以调用一系列库函数,实现仿真数据信息的获取和仿真对象的状态修改,极大程度方便了交通场景的构建,是二次开发不可或缺的重要工具。下面简单介绍各 API 的功能:
该类接口的主要功能是获取仿真对象的状态信息值,可以作为仿真输出,可以在输出数据基础上进行研究,对仿真进行改进,以达到理想的效果。下面介绍几个常用的 API :
举例说明:为信号灯设置三个不同的相位,分别是 28s 、3s 和 14s ,在 0 ~ 28s 也就是第一个相位的时间内,getNextSwitch()的值恒定为 28 ,在第二个相位的时间内,getNextSwitch()的值恒定为 31(28+3) ,第三个相位 getNextSwitch()值恒定为 45(28+3+14)。这样,假设获取到了第 3s 仿真数据,信号灯剩余时间就是 28 - 3 = 25s 。
该类接口的主要功能是控制仿真对象的状态,例如要测试自定义的车辆在不同路况条件下的性能表现,如果需要分析某一变量对车辆的影响,需要修改该变量的值,如信号灯持续时间、周围车辆密度、道路限速限行等,这时候就可以通过该接口来修改某一变量的值,得到前后的对比实验数据,方便下一步分析改进。下面简单介绍几个常用接口功能:
车辆状态 | 功能描述 | python 实现 |
---|---|---|
停车 | 使车辆停在给定的边沿,给定的位置和车道上。车辆将在给定的时间内停止。 | setStop |
变更车道 | 强制将车道更改为具有给定索引的车道;如果成功,将在给定的时间量(以秒为单位)内选择车道。 | changeLane |
更改目的地 | 给定新的目的地道路,重建行车路线 | changeTarget |
速度 | 将车辆的速度设定为给定值,车速要符合当前的速度模型 | setSpeed |
设置路线 | 为车辆设置行驶路线,车辆将沿给定的路线列表依次驶过 | setRoute |
TraCI 使用基于 TCP 的客户端/服务器体系结构来提供对 SUMO 的访问,SUMO 作为客户端,由于 TraCI 接口支持多种语言,服务器可以是由某种语言编写的脚本,通过该脚本控制仿真运行。下面的例子以 Python 脚本为例,探讨仿真运行过程和原理:
场景描述:在一个十字路口,东西方向有持续车流,南北方向间歇有车辆通过。使用 TraCI 控制信号灯在南北方向没有车辆时保持东西方向绿灯,当检测到南北方向的车辆,控制信号灯切换相位到南北方向绿灯而东西方向红灯。该例程可以在 …\doc\tutorial\traci_tls 中找到,下面代码已经简化和部分功能修改,在控制信号灯的同时打印出检测器检测到车辆信息。
代码如下,功能参考注释:
# 首先需要从 SUMO_HOME/tools 中导入一些实验用到的 python 模块
import os
import sys
import optparse
import random
import time
import traci
from sumolib import checkBinary
# 其次检查 SUMO_HOME 是否在系统环境变量中,这是进行下一步仿真的必要条件
if 'SUMO_HOME' in os.environ:
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
sys.path.append(tools)
else:
sys.exit("please declare environment variable 'SUMO_HOME'")
# 是否打开 sumo-gui 进行可视化演示
if_show_gui = True
if not if_show_gui:
sumoBinary = checkBinary('sumo')
else:
sumoBinary = checkBinary('sumo-gui')
# 指定 *.sumocfg 文件的位置
sumocfgfile = "E:\\SUMO\\doc\\tutorial\\traci_tls\\data\\cross.sumocfg"
# 接下来是 *.rou 文件的定义函数
def generate_routefile():
random.seed(42) # 设定种子值,下面使用 random() 生成的随机数是确定的,确保每次生成的 *.rou 文件相同
N = 3600 # 总仿真步数
pWE = 1. / 10
pEW = 1. / 11
pNS = 1. / 30
# 打开文件,“w” 代表将进行写入操作
with open("data/cross.rou.xml", "w") as routes:
print("""
""" , file=routes)
vehNr = 0 # 初始时刻车辆数为 0
for i in range(N):
if random.uniform(0, 1) < pWE:
print(' ' % (
vehNr, i), file=routes)
vehNr += 1
if random.uniform(0, 1) < pEW:
print(' ' % (
vehNr, i), file=routes)
vehNr += 1
if random.uniform(0, 1) < pNS:
print(' ' % (
vehNr, i), file=routes)
vehNr += 1
print("", file=routes)
# 定义主函数,traci 的核心控制逻辑
def run():
step = 0
traci.trafficlight.setPhase("0", 2) # 设置 ID 为 “0” 的信号灯初始相位是 2,该相位下东西方向绿灯
while traci.simulation.getMinExpectedNumber() > 0: # 获取预计仍要离开网络的车辆的最小数量
time.sleep(0.05) # 设置时延为 50ms
traci.simulationStep()
if traci.inductionloop.getVehicleData("0"): # 若 ID 为 “0” 的检测器检测到车辆通过,则打印出车辆的信息
print(traci.inductionloop.getVehicleData("0"))
if traci.trafficlight.getPhase("0") == 2:
if traci.inductionloop.getLastStepVehicleNumber("0") > 0: # 检测到有南北方向的车辆
traci.trafficlight.setPhase("0", 3) # 切换到 3 相位,南北方向绿灯,东西方向红灯
else:
traci.trafficlight.setPhase("0", 2)
step += 1
traci.close()
generate_routefile()
traci.start([sumoBinary, "-c", sumocfgfile]) # 启动 sumo-gui ,加载 *.sumocfg 文件
run()
运行脚本,仿真效果如下:
该场景简单模拟了拥有高通行优先级的车辆在 TraCI 控制信号灯路口的优先通行权,在真实环境中,这些车辆可以是执行紧急任务的救护车、消防车、警车等,通过实时控制信号灯,节省时间的同时保证通行安全。
注:本文仅涉及 TraCI 的几个常见使用,更多功能详见官方描述文档。