Sumolib

sumolib 是一组用于处理 sumo 网络、仿真输出和其他仿真产物的 Python 模块。有关可用函数的详细列表,请参阅 pydoc 生成的文档。您可以在此处浏览代码

在脚本中导入 sumolib#

要使用该库,<SUMO_HOME>/tools 目录必须位于 Python 加载路径上。通常使用如下代码段实现:

import os
import sys
if 'SUMO_HOME' in os.environ:
    sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))

加载网络文件#

# 导入库
import sumolib
# 解析网络
net = sumolib.net.readNet('myNet.net.xml')

可以向 readNet 函数提供以下命名参数(例如 readNet('myNet.net.xml', withInternal=True)):

  • withPrograms (bool): 导入所有交通信号灯程序(默认为 False)
  • withLatestPrograms (bool): 仅导入每个交通信号灯的最后一个程序。这是 sumo 中默认激活的程序。(默认为 False)
  • withConnections (bool): 导入所有连接(默认为 True)
  • withFoes (bool): 导入路权信息(默认为 True)
  • withInternal (bool): 导入内部边和车道(默认为 False)
  • withPedestrianConnections (bool): 导入人行道、人行横道之间的连接(默认为 False)

使用示例#

导入网络并检索节点和边#

# 导入库
import sumolib
# 解析网络
net = sumolib.net.readNet('myNet.net.xml')

# 根据 ID 检索节点的坐标
print(net.getNode('myNodeID').getCoord())

# 检索边的后继节点 ID
nextNodeID = net.getEdge('myEdgeID').getToNode().getID()

计算 plain xml 边文件中的平均边速度#

speedSum = 0.0
edgeCount = 0
for edge in sumolib.xml.parse('myNet.edg.xml', ['edge']):
    speedSum += float(edge.speed)
    edgeCount += 1
avgSpeed = speedSum / edgeCount

Note

这只是一个处理示例。要计算网络中的平均行驶速度,请处理 edgeDatatripinfossummary-output

计算选定边的长度#

net.loadSelection('selection.txt')
cumulLength = 0.
for edge in net.getEdges():
    if edge.isSelected():
        cumulLength += edge.getLength()

使用 Statistics 模块计算中位数速度#

edgeStats = sumolib.miscutils.Statistics("edge speeds")
for edge in sumolib.xml.parse('myNet.edg.xml', ['edge']):
    edgeStats.add(float(edge.speed))
avgSpeed = edgeStats.median()

Note

属性 speed 在用户生成的 .edg.xml 文件中是可选的,但如果该文件是由 netconvertnetedit 写入的,则将始终包含该属性。

基于地理坐标定位附近的边#

这需要安装 pyproj 模块。 对于较大的网络,强烈建议同时安装 rtree

net = sumolib.net.readNet('myNet.net.xml')
radius = 0.1
x, y = net.convertLonLat2XY(lon, lat)
edges = net.getNeighboringEdges(x, y, radius)
# 挑选最近的边
if len(edges) > 0:
    distancesAndEdges = sorted([(dist, edge) for edge, dist in edges], key=lambda x:x[0])
    dist, closestEdge = distancesAndEdges[0]

解析路线文件中的所有边#

for route in sumolib.xml.parse_fast("myRoutes.rou.xml", 'route', ['edges']):
    edge_ids = route.edges.split()
    # 对边 ID 向量执行某些操作

解析路线文件中的车辆及其路线边#

for vehicle in sumolib.xml.parse("myRoutes.rou.xml", "vehicle"):
    route = vehicle.route[0] # 访问名为 'route' 的第一个(也是唯一一个)子元素
    edges = route.edges.split()

包含自动数据转换(包括出发时间格式为 "HH:MM:SS"):

from sumolib.miscutils import parseTime
for vehicle in sumolib.xml.parse("myRoutes.rou.xml", "vehicle", attr_conversions={
            'depart' : parseTime,
            'edges' : (lambda x : x.split())}):
    edges = vehicle.route[0].edges
    if vehicle.depart > 42:
       ...

解析边数据 (meanData) 文件中的所有边#

for interval in sumolib.xml.parse("edgedata.xml", "interval"):
    for edge in interval.edge:
        # 对边属性执行某些操作,例如 edge.entered

坐标转换#

net = sumolib.net.readNet('myNet.net.xml')

# 网络坐标(网络左下角位于 x=0, y=0)
x, y = net.convertLonLat2XY(lon, lat)
lon, lat = net.convertXY2LonLat(x, y)

# 原始 UTM 坐标
x, y = net.convertLonLat2XY(lon, lat, True)
lon, lat = net.convertXY2LonLat(x, y, True)

# 车道/偏移量坐标
# 从车道位置转换为网络坐标
x,y = sumolib.geomhelper.positionAtShapeOffset(net.getLane(laneID).getShape(), lanePos)
# 从网络坐标转换为车道位置
lane, d = net.getNeighboringLanes(x, y, radius)[0] (参见上面的基于地理坐标定位附近的边)
lanePos, dist = sumolib.geomhelper.polygonOffsetAndDistanceToPoint((x,y), lane.getShape())

另请参阅 TraCI/Interfacing_TraCI_from_Python#coordinate_transformations

操作和写入 xml#

with open("patched.nod.xml", 'w') as outf:
    # 设置 attrs 是可选的,它会生成更清晰的补丁文件
    attrs = {'node': ['id', 'x', 'y']}  # 其他属性对于打补丁不是必需的
    # parse 总是返回一个生成器,但只有一个根元素
    nodes = list(sumolib.xml.parse('plain.nod.xml', 'nodes', attrs))[0]
    for node in nodes.node:
        node.addChild("param", { "key": "origPos", "value" : "%s %s" % (node.x, node.y) } )
        node.x = float(node.x) + random.randint(-20, 20)
        node.y = float(node.y) + random.randint(-20, 20)
    outf.write(nodes.toXML())

更多示例#

<SUMO_HOME>/tests/tools/sumolib 测试子文件夹中的 runner.py 文件提供了 sumolib 使用的其他示例。