
如果你最近在找交通仿真软件大概率会撞见SUMO这个名字。它的全称是Simulation of Urban MObility由德国宇航中心DLR主导开发、目前挂在Eclipse基金会下的开源微观交通仿真工具。网上关于SUMO的教程不少但很多要么是官方文档的生硬翻译要么直接甩一堆XML让你自己猜。新手装完软件之后面对黑乎乎的终端窗口往往不知道下一步该干什么。这篇教程就是来补这个断层的从下载安装、配置环境变量开始到用netedit画出一个能跑的十字路口路网再手写车辆文件、灌入车流、跑通第一次仿真、看懂输出数据整个过程不需要你有交通工程专业背景只要能操作电脑、愿意跟着敲几行命令就行。而且我会尽量把每一步背后的原因也讲清楚免得你机械照抄之后换个场景就抓瞎。1. SUMO的价值和适用场景先把它看明白再用1.1 SUMO的出身和技术特点SUMO从2001年前后开始研发持续迭代了二十多年学术圈里用它发论文、做实验的历史相当长。“微观”这两个字是理解SUMO的关键它不是把交通流当成水管里的水用宏观公式估算流量和密度而是对每一辆车都建立独立模型。每辆车在仿真中都有自己的长度、最大加速度、期望速度、跟驰行为参数仿真器会按固定时间步比如0.1秒逐次更新每辆车的位置、速度和车道。这种逐车计算的方式决定了SUMO的优势不在“宏观路网容量计算”上而在那些需要观察个体车辆行为的场景里。比如信号灯配时优化你要统计的是某一相位下排队长度怎么变化再比如自动驾驶测试你需要精确知道后车和前车之间的距离、相对速度。这些用SUMO来做就很顺手。和VISSIM、Aimsun这类商业软件比SUMO最核心的差异化优势有两条。第一完全免费开源学生、研究人员、创业公司都能零成本上手不用担心license到期或者节点数限制。第二从底层就是为自动化批量实验设计的所有场景用XML描述所有交互可以通过Python脚本控制跑一千组参数对照实验这件事在SUMO里是基本操作在商业软件里往往要折腾半天。1.2 SUMO适合干什么、不适合干什么我把SUMO最常见的应用场景列一下方便你对号入座信号灯配时优化通过配置文件或TraCI接口动态修改红绿灯方案对比不同配时下的延误、排队和停车次数。自动驾驶与网联车仿真TraCI可以在每个仿真步读取或写入车辆位置、速度、转向灯等状态适合做V2V/V2I策略验证。公交与多模式交通支持公交线路、站点、行人、自行车等对象能评估公交优先策略。大规模路网测试用netconvert把OpenStreetMap数据转成SUMO路网在城市尺度上跑交通组织方案。强化学习训练环境把SUMO当成一个可交互的仿真环境让智能体通过TraCI控制信号灯或车辆策略。但它也有明显的边界。SUMO的二维可视化比较朴素别指望它做出电影级别的三维效果车辆动力学模型属于“行为规则”层面不是车辆动力学仿真软件不适合研究ABS、悬挂这类底盘控制问题另外把真实城市路网标定到和实测流量误差很小的程度需要做大量校准工作接入地图只是第一步不是终点。1.3 学习SUMO需要哪些基础作为入门教程我默认你具备以下条件会用命令行至少能执行cd、python、sumo这种命令能看懂XML的基础结构会一点Python会明显提高效率但第一篇教程里用到的代码很短临时查也能搞定。你不需要系统学过交通工程SUMO里涉及的“车头时距”“跟驰模型”“排队长度”这些概念遇到的时候我会顺带解释。还有一个心态上的建议SUMO的学习曲线是“阶梯式”的安装完软件只是看到了台阶真正让你觉得值回票价的是第一次用自己的路网跑出车流、第一次从输出文件里拿到统计数据。所以这篇教程的目标不是让你成为仿真专家而是帮你快速站上第一级台阶。2. 十分钟装好SUMO版本、路径、环境变量一次说清2.1 下载渠道和版本怎么选SUMO的官方下载地址是官网页面里提供了Windows、Linux、macOS三个平台的安装包。Windows用户直接下载64位安装包即可如果你更习惯绿色软件的方式也可以下载ZIP压缩包解压后配置环境变量就能用。版本选择上我的建议是选最新的稳定Release版本不要碰每晚构建的Nightly版。稳定版功能未必最新但文档、教程、报错信息都对得上遇到问题搜一下就有人回答。以1.20、1.21之后的版本为例netedit界面和命令行工具的参数基本稳定你在这套教程里学到的操作在后续版本上仍然适用。2.2 安装路径和环境变量配置这里我要重点强调一个新手最容易忽略的细节安装路径千万不要带空格和中文。SUMO的很多工具链在解析路径时碰到空格会出现莫名其妙的问题比如明明文件存在却说找不到。推荐装到D:\SUMO或C:\sumo这种纯英文无空格目录下。安装完成后环境变量配置是绕不开的一步。不配置环境变量你只能在bin目录里运行程序配置好之后可以在任何终端窗口直接输入sumo-gui、netedit这些命令。步骤很简单右键“此电脑” → 属性 → 高级系统设置 → 环境变量。在“系统变量”里新建一个变量变量名填SUMO_HOME变量值填你的SUMO安装根目录比如D:\SUMO。找到Path变量点击编辑新增一条%SUMO_HOME%\bin。一路点确定保存。如果你下载的是ZIP压缩包解压后同样按上面步骤配置。注意配置完环境变量后已经打开的终端窗口不会生效必须新开一个CMD或PowerShell窗口再测试。这个问题我当年踩过一度以为安装包坏了其实是终端没有刷新。2.3 bin和tools目录下都有什么装好后建议先看一下SUMO目录结构心里有个数。核心执行文件都在bin目录里sumo.exe命令行仿真器没有界面跑批处理实验用。sumo-gui.exe带图形界面的仿真器能看到车辆移动和路网状态。netedit.exe网络编辑器用来手工绘制或修改路网。netconvert.exe格式转换工具能把OpenStreetMap、MATSim等格式转成SUMO路网。duarouter.exe路径计算工具根据出发地和目的地生成具体路线。polyconvert.exe把建筑物、绿地等多边形数据转换到仿真场景中。另外还有一个tools目录里面全是Python脚本对新手最实用的两个工具是randomTrips.py随机生成车流和osmWebWizard.py一键截取真实地图区域并自动生成路网。这俩脚本依赖Python环境所以你要确认电脑上装了Python 3.6以上版本并且在命令行能执行python命令。2.4 验证安装第一次运行sumo --version环境变量配置好、新开终端窗口之后执行下面三条命令验证sumo --version sumo-gui --version netedit --version正常会输出类似SUMO Version 1.21.0的信息。如果提示“不是内部或外部命令”优先检查两件事一是Path变量里的%SUMO_HOME%\bin是否写对二是安装目录下bin文件夹是否真实存在。如果执行python --version失败那就先去装Python再把Python目录加入环境变量。这一步验证虽然简单但我建议每个人都做一下。后续所有命令都依赖环境变量早发现问题比在跑仿真时才发现路径不对要好得多。3. 绕不开的三张文件.net.xml、.rou.xml、.sumocfg3.1 路网文件.net.xml点、边、连接的关系SUMO仿真的本质就是把“路网”和“交通需求”叠加起来按时间推进。一张路网文件后缀一般是.net.xml描述的是一张“有向图”道路被拆成一条条有方向的边edge边的端点叫节点node。车辆只会在边上跑到节点处根据连接关系选择继续走哪条边。为什么强调“有方向”因为在SUMO里一条双向两车道道路不会是“一条路”而是方向相反的两条边。比如从A点到B点的路实际是A→B这条边和B→A这条边叠加在一起。如果一个交汇点有多个方向的边汇入就形成一个交叉口车辆在这里能不能左转、能不能直行由“连接”connection定义。这也是新手画完路网后最容易忽略的东西——边画了但节点处没生成连接车走到那里就报错“no connection”。手写.net.xml不是不可以但完全不推荐。一个真实路网的XML里包含了每条车道的几何坐标、每个交叉口的转向连接、限速、车道宽度等大量信息手工维护会疯掉。正确方式是用netedit画或者用netconvert从OpenStreetMap转换。但我仍然建议你至少读一遍生成的XML理解节点和边的结构因为后面排错时你要看得懂报错里提到的edge id。3.2 需求文件.rou.xml车辆、车流和路线路网解决的是“车能在哪里跑”需求文件解决的是“什么车、什么时候、从哪条路到哪条路”。需求文件后缀一般是.rou.xml里面有三类核心元素vType车辆类型定义加速度、最大速度、车长、颜色等参数。route行车路线用一串连续的边id表示。vehicle或flow单辆车或车流指定出发时间、使用的路线和车辆类型。给你一段最简示例?xml version1.0 encodingUTF-8? routes vType idcar accel2.6 decel4.5 sigma0.5 length5.0 maxSpeed16.67 color1,0,0/ route idW2E edgesE0 E1/ vehicle idv1 typecar routeW2E depart0/ vehicle idv2 typecar routeW2E depart10/ /routes注意route里的edges属性车辆会严格按照这条边序列行驶。如果中间某条边不存在或两条边之间没有连接仿真器就会报错。这一行是新手出错的重灾区排查时先看路由的边是否都存在于网络文件中。3.3 配置文件.sumocfg把网络和需求组装起来有了路网和需求还差一个“总指挥”——仿真配置文件.sumocfg。它的作用是把路网文件、需求文件、仿真时间范围、输出文件都串起来。示例?xml version1.0 encodingUTF-8? configuration input net-file valuemynet.net.xml/ route-files valuemyroutes.rou.xml/ /input time begin value0/ end value300/ step-length value0.1/ /time /configuration写好后启动仿真只需要一行命令sumo-gui -c myconfig.sumocfg-c指定配置文件。如果不写配置文件用sumo -n mynet.net.xml -r myroutes.rou.xml -b 0 -e 300这种简写方式也能跑参数多了之后配置文件更清晰。前缀.sumocfg本质是XML用文本编辑器就能改。我第一次跑通仿真时没建配置文件直接命令行塞参数后来场景越来越复杂才发现配置文件更重要。4. 不用一行代码画出可用路网Netedit实操4.1 启动Netedit与界面布局在终端输入netedit或者在SUMO安装目录里双击netedit.exe就会打开网络编辑器。第一次打开可能是一个空白画布如果不是可以通过菜单File → New Network新建。netedit的界面分几个区域左侧是绘图工具栏右侧是属性面板中间是画布。绘图工具栏里最常用的几个模式是边缘模式Edge、连接模式Connection、交通灯模式Traffic Lights、移动模式Move。你可以在绘图过程中随时按快捷键切换Esc退出当前操作。新手最关心的两个默认参数是车道数和限速。在边缘模式下右侧的面板会显示当前待绘制边的属性比如numLanes2、speed13.89。13.89这个数字对应50km/h单位是米/秒这是SUMO的默认限速。如果在中国城市道路场景里想设为60km/h就填16.67。我建议一开始就用默认值先跑通后面再调。4.2 画一个十字路口路网接下来我们画一个最简单的十字路口四个方向各有入口和出口。我习惯的做法是先规划好五个节点的位置再连边西节点 N0坐标0, 200东节点 N1坐标400, 200北节点 N2坐标200, 0南节点 N3坐标200, 400中心交叉节点 N4坐标200, 200具体操作进入边缘模式后在画布上点击一下创建一个起始节点移动鼠标到目标位置再点击就完成了一条边的绘制。关键点是绘完N0→N4后把鼠标移到N4→N1再画一条这就是东西方向的主干。对垂直方向也做同样操作得到N2→N4和N4→N3。这样画出来的网络每个方向只有一条入边和一条出边车辆可以直行通过交叉口但缺少左转和右转的连接。没关系默认情况下节点N4处会根据进入边和离开边的组合自动生成合法连接。如果你看到车流在交叉口无法转向可以单独补。要想让路网更像真实道路可以在画每条边时把右侧的“双向”选项打开。这样画一次N0→N4系统会自动生成N4→N0的反向边避免来回画两遍。这个功能不同版本位置略有不同但通常都在边缘模式属性区名字叫“Two-way”或“双向”。4.3 检查并修正连接关系画完路网后千万别急着保存就跑。先切换到连接模式看交叉口节点处有没有代表转向连接的弧线。如果某些转向缺失点击对应车道的起点和终点手动创建连接。这一步在简单十字路口可能体会不到重要性等以后路网复杂了信号灯配时、转向限制都会依赖连接关系。保存路网时选择File → Save Network As命名比如mynet.net.xml。我建议文件名也用纯英文路径不要出现空格。保存后可以顺便用文本编辑器打开看一眼你会发现里面的信息比我们刚刚画的内容多得多——系统已经自动生成了交叉口内部的连接车道和几何坐标。4.4 想偷懒时的替代方案用OSM数据一键生成如果你现在不想从零画路网另一个非常推荐的方式是使用tools目录下的osmWebWizard.py。在命令行执行python %SUMO_HOME%\tools\osmWebWizard.py然后浏览器会打开一个地图界面你框选一块区域点击生成SUMO会自动下载OpenStreetMap数据、转换路网、添加交通需求并直接打开SUMO GUI开始仿真。整个过程不需要你手工画一条边。我第一次用这个工具时有些惊讶它连信号灯和公交车都自动配好了。但要注意自动生成的路网质量取决于OSM数据质量有些小区内部道路可能被识别成普通道路限速和车道数也不一定准确。所以我会把它定位成“快速体验完整流程”的利器甚至可以直接用这个工具生成的场景做后续实验但如果你要做严肃的科研或工程应用还是得学会手动创建一个干净的最小路网这样你能完全掌控每条边的属性。5. 给路网灌入车辆手写Routes与脚本生成5.1 手写一份最简单的.rou.xml手工写需求文件虽然原始但这是理解SUMO需求建模逻辑的最快途径。假设我们的十字路口网络用了4.2节里的边ID比如E0表示N0→N4E1表示N4→N1E2表示N2→N4E3表示N4→N3那么西向东的车流走E0 E1北向南的车流走E2 E3。新建文本文件命名为myroutes.rou.xml写下?xml version1.0 encodingUTF-8? routes vType idcar accel2.6 decel4.5 sigma0.5 length5.0 maxSpeed16.67 color1,0,0/ route idW2E edgesE0 E1/ route idN2S edgesE2 E3/ vehicle idv1 typecar routeW2E depart0/ vehicle idv2 typecar routeN2S depart10/ vehicle idv3 typecar routeW2E depart20/ vehicle idv4 typecar routeN2S depart30/ /routesdepart是出发时间秒上面这4辆车会在0秒、10秒、20秒、30秒依次进入路网。color1,0,0是RGB颜色三个数分别对应红、绿、蓝范围0到1这里红色表示小汽车。跑这个文件前记得把myroutes.rou.xml和上一节保存的mynet.net.xml放到同一个文件夹下再写一个简单的.sumocfg指向它们。如果你不修改任何配置就可以直接跑说明这件事没这么复杂。5.2 用randomTrips.py快速生成车辆流手写车辆适合单点调试但要生成几百上千辆车手工写就太笨了。SUMO自带的randomTrips.py就是干这个的。常用命令如下python %SUMO_HOME%\tools\randomTrips.py -n mynet.net.xml -r random_routes.rou.xml -e 300 -p 2参数含义-n指定路网文件-r指定输出路线文件-e 300表示仿真结束时间设为300秒-p 2表示每2秒生成一辆车。这个脚本会在合法起终点之间随机选路自动生成车辆和路线。如果不指定起终点默认在文件里随机挑。对于十字路口这种对称路网随机车流很快就能跑起来。如果你需要车流从特定入口到特定出口可以用--from和--to参数限定或者手工改生成的XML。实际测试时我发现路网如果存在未连接的边randomTrips会报类似“No connection between edge”的警告这其实是件好事它帮你提前暴露路网连通性问题。5.3 GUI仿真运行、视角与常用设置一切准备就绪后在终端执行sumo-gui -c myconfig.sumocfg --start--start参数让仿真启动后立刻开始运行不用每次手动点播放。启动后你会看到一辆辆小车在路网上移动。GUI下部有播放/暂停按钮和速度调节滑块把滑块往右拉可以加速跑完300秒场景。几个我常用的操作鼠标滚轮缩放视角按住中键拖动平移画面左侧车辆面板可以查询每一辆车的实时位置和速度右键点击车辆可选择追踪视角让镜头跟着这辆车走。在“Visualization Settings”里可以调整车辆颜色、是否显示车道编号。第一次看到车流在十字路口转向的时候那种“原来这就是微观仿真”的感觉还挺有成就感的。如果只想跑批处理、不需要看动画就用命令行版sumo -c myconfig.sumocfg没有GUI的情况下仿真速度会快很多特别适合后面做参数批量扫描时使用。5.4 从命令行批量跑仿真的小技巧批量跑仿真时我习惯把多个.sumocfg放在不同子目录里每个子目录对应一组参数然后写个小循环脚本统一执行。简单示例for /L %i in (1,1,10) do ( mkdir case_%i copy base.net.xml case_%i\base.net.xml )当然了更正规的批量实验可以用Python脚本通过subprocess调用sumo -c再把输出结果读回来分析。这些内容后续教程会展开这里先留个印象SUMO的组件化设计让“批量跑实验”这件事很容易自动化。6. 跑通仿真后如何从输出里拿数据6.1 仿真输出文件有哪些类型仿真的意义不只是看动画而是拿到可量化的数据。SUMO支持多种输出类型常用四种输出文件内容典型用途tripinfo.xml每辆车的完整行程信息统计行程时间、延误、停车次数fcd.xml每辆车每个时间步的位置、速度轨迹级分析summary.xml整个路网随时间变化的汇总数据观察总体流量和密度vehroute.xml车辆实际行驶的路线检查路径选择这些输出需要在.sumocfg的output区域显式声明例如output tripinfo-output valuetripinfo.xml/ fcd-output valuefcd.xml/ summary-output valuesummary.xml/ /output6.2 用Python简化tripinfo统计拿到tripinfo.xml后直接看XML会很痛苦用Python批量解析才高效。我一般在放tripinfo.xml的目录下写一个stat.pyimport xml.etree.ElementTree as ET import statistics tree ET.parse(tripinfo.xml) trips tree.getroot().findall(tripinfo) durations [] losses [] for t in trips: durations.append(float(t.get(duration))) losses.append(float(t.get(timeLoss))) print(完成车辆数:, len(durations)) print(平均行程时间: {:.2f} s.format(statistics.mean(durations))) print(平均时间损失: {:.2f} s.format(statistics.mean(losses))) print(总时间损失: {:.2f} s.format(sum(losses)))tripinfo的duration是车辆从出发到到达的总时间timeLoss是因为拥堵、信号灯等导致的额外延误。这两个指标在做信号灯配时对比时特别常用配时方案改进后平均timeLoss通常会下降。如果要对多个文件做对比只需改一下读取路径或者用glob匹配目录下所有tripinfo.xml一次统计全部结果。这个脚本是后续所有实验的基础值得好好留底。6.3 数据怎么看以旅行时间和延误为例数据不是跑出来就完事关键是会解读。比如跑了300秒仿真得到平均行程时间20秒、平均时间损失5秒能说明什么如果这个路网本身只有200米长车辆按50km/h通过只需14秒左右那多出来的6秒就说明车辆在交叉口或路段上遇到了红灯或跟驰减速。时间损失数值越大说明路网运行效率越低。我做信号灯配时实验时习惯同时看两个指标平均时间损失和排队长度。有时候平均延误变化不大但排队长度明显变短说明方案优化的是空间分布而非时间平均。SUMO的数据维度很细能提取出来的指标远不止行程时间和延误关键是搞清楚你关心什么问题再决定看什么字段。7. 新手期常见的报错和处理经验7.1 新手最常遇到的错误汇总结合我自己和带新人时的经验以下错误最典型报错信息常见原因解决办法Could not open network file路径不对或文件名有错检查config里value的路径尽量用相对路径Error: No connection between edge ...路网节点处没有生成连接到netedit连接模式检查交叉口Vehicle v1 has no routeroute元素里的边ID在网络中不存在核对route的edges是否都存在于net.xmlCould not open requested file ...文件编码或路径含中文/空格路径换成纯英文文件用UTF-8编码提示找不到python命令Python未安装或未加入环境变量安装Python并配置PATH这些报错信息在终端里看起来吓人但本质都是配置问题和数据本身无关。我的排查顺序永远是先确认文件存在再确认文件路径最后确认ID是否匹配。7.2 几个能明显提升效率的实操习惯过了安装和第一次跑通之后有几个习惯能帮你少走很多弯路。第一把%SUMO_HOME%\tools加入PYTHONPATH环境变量这样在Python里可以import traci和import sumolib后续做TraCI二次开发时才不会一上来就报模块找不到。第二所有仿真文件命名统一比如网络用xxx.net.xml、路由用xxx.rou.xml、配置用xxx.sumocfg中间不要混入tripinfo.xml这类输出文件名避免覆盖。第三每次大改路网之前先备份一份能跑的版本。别问我为什么强调这条当你改了20个参数后突然跑不出来时就知道备份有多重要了。还有一个小技巧是GUI仿真时在配置里加上--quit-on-end仿真结束自动退出进程省得每次都手动关窗口。批量跑几百组实验时这个参数能节省大量操作时间。根据我个人的体会SUMO最大的门槛不在安装而在于“第一次亲手把路网和车流组装起来”的过程。只要跨过这个坎后面无论是导入真实地图、做信号灯优化还是用TraCI做二次开发都会顺理成章。这套教程先到这里下一篇我会继续写如何用netedit给十字路口加上信号灯相位以及如何用duarouter实现真正意义上的路径规划。到时候见。