SUMO入门(八) - 从Python引入TraCI接口

SUMO入门(八) - 从Python引入TraCI接口

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找到

1 在脚本中引入TraCI

要使用该库,/tools 目录必须位于python加载路径上。 通常如下:

 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'))

2 第一步

通常,从Python接入SUMO非常容易(以下示例是 tutorial / traci_tls 的修改)

首先,编写命令行以启动 SUMOSUMO-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)

3 Subscriptions 订阅

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()

检索到的值始终是上一个时间步的值,无法检索较旧的值。

3.1 上下文订阅

上下文订阅的工作方式与订阅类似,因为它们会在每个仿真停止自动检索变量列表。 但是,这样做是通过设置引用对象和范围,然后在引用对象的范围内检索给定类型的所有对象的变量。

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()

检索到的值始终是上一个时间步的值,无法检索较旧的值。

3.2 上下文订阅过滤器

对于车辆到车辆的上下文订阅(即,上下文订阅,其参考对象是车辆并且其请求的上下文对象也是车辆),可以请求在服务器侧已经应用的附加过滤器。 一般过程是通过对 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文档。

4 添加StepListener

每次调用 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。

5 从同一个TraCI脚本控制并行仿真

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

6 嵌入式Python

作为一个实验性功能,还可以直接将SUMO与python连接,并在SUMO中执行脚本。 语法完全相同,只是你省去了对init和close的调用,你需要使用选项 –python-script 启动sumo。 此功能被视为已弃用,将由libsumo替换。 但它目前不适用于sumo的GUI版本。

由于该功能尚未经过良好测试,因此建议您需要在构建SUMO时显式启用嵌入式python。 为此,请按照以下说明操作:

6.1 Linux

– 安装python devel包文件
– 使用–with-python选项调用configure
– 像往常一样make && make install

6.2 Windows

– 确保安装了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构建


7 用法示例

运行仿真直到所有车辆到达

  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


你可能感兴趣的:(SUMO,SUMO,TraCI)