TraCI
TraCI/Interfacing TraCI from Python
TraCI命令分为13个部分,它们对应于各个模块: gui,lane,poi,simulation,trafficlight,vehicletype,edge,inductionloop,junction,multientryexit,polygon,route,person,vehicle
有关函数的详细列表,请参阅 pydoc generated documentation。命令的源代码可以在eclipse/sumo找到
要使用该库,
import os, sys
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_HOME。 或者,您可以直接在行中声明 sumo/tools 的路径
sys.path.append(os.path.join('c:', os.sep, 'whatever', 'path', 'to', 'sumo', 'tools'))
通常,从Python接入SUMO非常容易(以下示例是 tutorial / traci_tls 的修改)
首先,编写命令行以启动 SUMO 或 SUMO-GUI:
(省略在0.28.0版本之前需要的远程端口选项 --remote-port)
sumoBinary = "/path/to/sumo-gui"
sumoCmd = [sumoBinary, "-c", "yourConfiguration.sumocfg"]
然后开始仿真并使用脚本连接到它:
import traci
traci.start(sumoCmd)
step = 0
while step < 1000:
traci.simulationStep()
if traci.inductionloop.getLastStepVehicleNumber("0") > 0:
traci.trafficlight.setRedYellowGreenState("0", "GrGr")
step += 1
traci.close()
连接到仿真后,可以发出各种命令并执行仿真步骤,直到您想要关闭连接。 默认情况下,close命令将一直等到sumo过程真正完成,你可以通过调用来禁用它:
traci.close(False)
Subscriptions 可以被视为用于 检索变量的批处理模式。 您可以在每个时间步之后自动检索感兴趣的值,而不是一遍又一遍地请求相同的变量。 TraCI订阅基于每个模块进行处理。 也就是说,您可以在每个时间步之后向模块询问所有当前订阅的结果。 为了订阅变量,您需要知道它们的变量 id,可以在 traci/constants.py 文件中进行查找。
import traci
import traci.constants as tc
traci.start(["sumo", "-c", "my.sumocfg"])
traci.vehicle.subscribe(vehID, (tc.VAR_ROAD_ID, tc.VAR_LANEPOSITION))
print(traci.vehicle.getSubscriptionResults(vehID))
for step in range(3):
print("step", step)
traci.simulationStep()
print(traci.vehicle.getSubscriptionResults(vehID))
traci.close()
检索到的值始终是上一个时间步的值,无法检索较旧的值。
上下文订阅的工作方式与订阅类似,因为它们会在每个仿真停止自动检索变量列表。 但是,这样做是通过设置引用对象和范围,然后在引用对象的范围内检索给定类型的所有对象的变量。
TraCI上下文订阅是基于每个模块处理的。 也就是说,您可以在每个时间步之后向模块询问所有当前订阅的结果。 为了订阅变量,你需要检索要检索对象的域id,以及可以在 traci/constants.py 文件中查找的变量id。 域ID的格式始终为 CMD_GET_ <DOMAIN> _VARIABLE。 以下代码检索交叉点范围(42m)内的所有车辆速度和等待时间(隐式检索车辆ID)。
import traci
import traci.constants as tc
traci.start(["sumo", "-c", "my.sumocfg"])
traci.junction.subscribeContext(junctionID, tc.CMD_GET_VEHICLE_VARIABLE, 42, [tc.VAR_SPEED, tc.VAR_WAITING_TIME])
print(traci.junction.getContextSubscriptionResults(junctionID))
for step in range(3):
print("step", step)
traci.simulationStep()
print(traci.junction.getContextSubscriptionResults(junctionID))
traci.close()
检索到的值始终是上一个时间步的值,无法检索较旧的值。
对于车辆到车辆的上下文订阅(即,上下文订阅,其参考对象是车辆并且其请求的上下文对象也是车辆),可以请求在服务器侧已经应用的附加过滤器。 一般过程是通过对 addSubscriptionFilter<FILTER_ID>() 的成功调用,在调用 subscribeContext() 之后直接为请求的上下文订阅配备过滤器,例如在下面的代码片段中:
traci.vehicle.subscribeContext("ego", tc.CMD_GET_VEHICLE_VARIABLE, 0.0, [tc.VAR_SPEED])
traci.vehicle.addSubscriptionFilterLanes(lanes, noOpposite=True, downstreamDist=100, upstreamDist=50)
第一行请求具有ID “ego” 的参考车辆附近的车辆速度的上下文订阅。上下文订阅的范围(指通常订阅机制的径向上下文区域)可以设置为等于0.0。
可以使用以下过滤器类型:
Lanes:返回相对于参考车辆指定的车道上的周围车辆
CFManeuver:返回参考车辆车道的领导者和追随者
LCManeuver:返回参考车辆车道和相邻车道的领导者和追随者
Turn:沿着车辆路线返回即将到来的交叉路口的冲突车辆
VType:仅返回指定vType的车辆
VClass:仅返回指定vClasses的车辆
有关详细规范,请参阅 pydoc文档。
每次调用 traci.simulationStep() 时都需要调用一个函数,为了让它自动发生(总是在每次调用simulationStep() 之后)可以添加一个StepListener对象 'listener’(更确切地说是traci.StepListener的子类的一个实例)
class ExampleListener(traci.StepListener):
def step(self, t=0):
# do something at every simulaton step
print("ExampleListener called at time %s ms." % t)
# indicate that the step listener should stay active in the next step
return True
listener = ExampleListener()
traci.addStepListener(listener)
警告:在一个traci客户端控制多个SUMO实例的情况下,不能使用TraCI StepListener。
TraCI python库可用于通过单个脚本同时控制多个仿真。 函数 traci.start() 有一个可选的label参数,允许您使用不同的仿真实例和标签多次调用它。 然后可以使用函数 traci.switch() 切换到任何初始化标签:
traci.start(["sumo", "-c", "sim1.sumocfg"], label="sim1")
traci.start(["sumo", "-c", "sim2.sumocfg"], label="sim2")
traci.switch("sim1")
traci.simulationStep() # run 1 step for sim1
traci.switch("sim2")
traci.simulationStep() # run 1 step for sim2
如果您更喜欢面向对象的方法,也可以使用连接对象与仿真进行通信。 它们具有与静态traci相同的接口调用,但您仍需要手动启动仿真:
traci.start(["sumo", "-c", "sim1.sumocfg"], label="sim1")
traci.start(["sumo", "-c", "sim2.sumocfg"], label="sim2")
conn1 = traci.getConnection("sim1")
conn2 = traci.getConnection("sim2")
conn1.simulationStep() # run 1 step for sim1
conn2.simulationStep() # run 1 step for sim2
作为一个实验性功能,还可以直接将SUMO与python连接,并在SUMO中执行脚本。 语法完全相同,只是你省去了对init和close的调用,你需要使用选项 –python-script 启动sumo。 此功能被视为已弃用,将由libsumo替换。 但它目前不适用于sumo的GUI版本。
由于该功能尚未经过良好测试,因此建议您需要在构建SUMO时显式启用嵌入式python。 为此,请按照以下说明操作:
– 安装python devel包文件
– 使用–with-python选项调用configure
– 像往常一样make && make install
– 确保安装了python并且在你的PATH中
– 调用tools \ build \ pythonPropsMSVC.py来生成或修改build \ msvc10 \ config.props文件
– 像往常一样构建Win32发行版
– 来自PCbuild目录副本
python27_d.dll到Python目录(类似于C:\ Python27)
python27_d.lib,python27_d.pdb,python27_d.exp到libs目录(C:\ Python27 \ libs)
每个* _d.pyd到DLL的目录(C:\ Python27 \ DLLs)
– 通过编辑build \ msvc10 \ Win32.props启用python调试版本
– 现在,您可以为SUMO执行Win32 Debug构建
运行仿真直到所有车辆到达
while traci.simulation.getMinExpectedNumber() > 0:
traci.simulationStep()
动态添加行程(不完整路径)
定义包含起始边和目标边的路线:
traci.route.add("trip", ["startEdge", "endEdge"])
然后添加具有该路线的车辆:
traci.vehicle.add("newVeh", "trip", typeID="reroutingType")
这将导致车辆根据出发时网络中的估计行程时间计算从startEdge到endEdge的新路线。
坐标转换
x, y = traci.vehicle.getPosition(vehID)
lon, lat = traci.simulation.convertGeo(x, y)
x2, y2 = traci.simulation.convertGeo(lon, lat, fromGeo=True)
edgeID, lanePosition, laneIndex = traci.simulation.convertRoad(x3, y3)
edgeID, lanePosition, laneIndex = traci.simulation.convertRoad(lon2, lat2, True)
注意:使用TraCI时,有一些常见的任务没有被traci库覆盖,例如分析道路网络、解析仿真输出。
对于此功能,建议使用 Tools / Sumolib