4. 环形交叉口(环岛)车辆通行仿真

任务目标

在SUMO中构建一个环形交叉口(环岛)路网,为四个入口设置车辆流量,运行仿真并观察车辆在环岛内的让行行为与通行效率。通过本案例掌握SUMO环岛建模方法、让行规则配置及流量参数调整。

环境依赖

需要SUMO 1.8.0及以上版本(含netedit图形化建网工具),Python 3.6+(用于生成随机流量)。确认命令行中sumo、netedit、python可用。

路网构建(netedit操作)

使用netedit新建路网,按以下步骤操作:

  1. 创建中心环岛:选择Edge模式,沿圆周依次点击生成8条弧段(近似圆形),每条弧段用2个中间节点平滑弯曲;
  2. 创建四条入口道路:从环岛边缘节点向外延伸直路,长度200m,方向为正东、正西、正北、正南;
  3. 设置环岛优先权:选中环岛所有路段,在Edge属性中将Priority设为-1(环内车辆优先);入口道路优先级保持默认-1;
  4. 设置让行规则:在环岛每个入口与环内道路交汇处,使用Connection模式添加Yield连接(入口车辆需让行环内车辆);
  5. 保存为ring_road.net.xml。

若希望快速获得路网文件,可直接使用下方Python脚本调用sumolib生成等价路网(需安装sumolib,随SUMO附带)。

完整实现代码

以下Python脚本生成路网、流量文件并启动仿真,保存为run_roundabout.py:

import os, subprocess, random
import sumolib
from sumolib import net

# 1. 生成路网(若已有ring_road.net.xml则跳过)
if not os.path.exists("ring_road.net.xml"):
    netedit_cmd = ["netedit", "-s", "ring_road.net.xml", "--new"]
    # 此处用netedit交互创建,或使用XML模板(见下方注释)
    # 为简化,直接写入最小环岛路网XML
    with open("ring_road.net.xml", "w") as f:
        f.write('''<?xml version="1.0" encoding="UTF-8"?>
<net version="1.8">
    <location netOffset="0.00,0.00" convBoundary="0.00,0.00,200.00,200.00" origBoundary="0.00,0.00,200.00,200.00"/>
    <edge id="E0" from="0" to="1" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="E1" from="1" to="2" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="E2" from="2" to="3" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="E3" from="3" to="0" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="N0" from="4" to="0" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="N1" from="0" to="5" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="S0" from="6" to="2" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="S1" from="2" to="7" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="W0" from="8" to="1" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="W1" from="1" to="9" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="E4" from="10" to="3" priority="-1" numLanes="1" speed="13.89"/>
    <edge id="E5" from="3" to="11" priority="-1" numLanes="1" speed="13.89"/>
    <junction id="0" x="100" y="100" type="priority"/>
    <junction id="1" x="120" y="100" type="priority"/>
    <junction id="2" x="100" y="120" type="priority"/>
    <junction id="3" x="80" y="100" type="priority"/>
    <junction id="4" x="100" y="50" type="dead_end"/>
    <junction id="5" x="100" y="150" type="dead_end"/>
    <junction id="6" x="50" y="120" type="dead_end"/>
    <junction id="7" x="150" y="120" type="dead_end"/>
    <junction id="8" x="50" y="100" type="dead_end"/>
    <junction id="9" x="150" y="100" type="dead_end"/>
    <junction id="10" x="80" y="150" type="dead_end"/>
    <junction id="11" x="120" y="150" type="dead_end"/>
    <connection from="N0" to="E0" fromLane="0" toLane="0" yield="1"/>
    <connection from="W0" to="E1" fromLane="0" toLane="0" yield="1"/>
    <connection from="S0" to="E2" fromLane="0" toLane="0" yield="1"/>
    <connection from="E4" to="E3" fromLane="0" toLane="0" yield="1"/>
</net>''')
    print("路网已生成:ring_road.net.xml")

# 2. 生成随机流量(每入口120辆/小时)
random.seed(42)
with open("flow.rou.xml", "w") as f:
    f.write('<routes>\n')
    for i in range(120):
        depart = round(random.uniform(0, 3600), 2)
        entry = random.choice(["N0", "W0", "S0", "E4"])
        exit_edge = random.choice(["N1", "W1", "S1", "E5"])
        f.write(f'    <vehicle id="v{i}" depart="{depart}">\n')
        f.write(f'        <route edges="{entry} {exit_edge}"/>\n')
        f.write('    </vehicle>\n')
    f.write('</routes>\n')
print("流量文件已生成:flow.rou.xml")

# 3. 运行仿真(GUI模式便于观察)
sumo_cmd = ["sumo-gui", "-n", "ring_road.net.xml", "-r", "flow.rou.xml", "--start", "--quit-on-end"]
subprocess.run(sumo_cmd)

运行方式

python run_roundabout.py

仿真启动后GUI窗口弹出,可实时观察车辆行为。仿真时长3600秒(1小时),结束后自动关闭。

验证方法与判定标准

  1. 让行规则验证:观察环岛入口处,当环内有车辆接近时,入口车辆应减速或停车等待;环内无车时入口车辆正常汇入。若所有入口车辆均未减速直接冲入,说明让行连接未生效,需检查yield="1"属性。
  2. 通行效率量化:仿真结束后,在SUMO GUI中打开窗口→车辆统计,记录平均旅行时间(预计约30-60秒/辆)。若平均旅行时间超过120秒,说明环岛容量不足或让行规则过于保守,可适当提高环岛限速或增加车道。
  3. 无死锁检查:仿真过程中不应出现车辆长时间(>60秒)完全停止不动的现象。若出现,检查是否有车辆在环岛内逆向行驶或路线冲突。
  4. 流量完成率:仿真结束时,所有120辆车应全部到达出口。若部分车辆未完成,查看消息窗口中的错误日志,通常为路线不连通导致。

常见问题

  • 车辆在入口处永久等待:多为环岛内车辆持续不断导致入口让行无法汇入。可降低入口流量至60辆/小时测试,或增加环岛车道数。
  • 路网无法加载:检查ring_road.net.xml中节点坐标是否合理,所有路段必须连接至有效节点。
  • 路线不连通:确认每条入口道路(如N0)都能通过环岛到达任意出口(如N1、W1等)。本案例中环岛为单向逆时针,需保证连接方向正确。
环岛 逆时针 北入口 120辆/h 南入口 120辆/h 西入口 120辆/h 东入口 120辆/h 让行 让行 让行 让行 入口道路(让行) 环岛主路(优先) 让行标记

上图展示了本案例的环岛路网结构:四条入口道路均设有让行标记,环岛内车辆具有优先通行权。仿真中可通过调整flow.rou.xml中的车辆总数或depart时间分布来测试不同流量下的通行效率。