SUMO ( Simulation of Urban Mobility) 是免费、开源的交通系统仿真软件,可以实现交通流的微观控制,即具体到道路上每一辆车的运行路线都可以单独规划。可模拟复杂环境中的交通流。
sumo中一个路网文件,分为路网net文件和交通需求(路径)route文件。net文件由node文件和edge文件组成。其中node表示节点,如一个交叉口。

- 节点文件 node file (.nod.xml)
- 连边文件 edge file (.edg.xml)
- 类型文件 edge type file (.type.xml)
- 基于上述三个文件创建路网文件 net file (.net.xml)
- 路由文件 route file (.rou.xml)
上述文件本质上都是 xml 文件,不过为了方便区分其作用,额外增加了一个后缀名。
假设我们要创建如下图所示的小型道路网络:

图中黑色节点对应交通路口,连边对应道路。每个路口所在位置坐标已给出。
node file
1 | <nodes> |
edge file
1 | <edges> |
type file
1 | <types> |
基于以上三个文件,可以通过命令 netconvert 创建 net 文件,命令如下:
1 | netconvert --node-files my_nodes.nod.xml --edge-files my_edge.edg.xml -t my_type.type.xml -o my_net.net.xml |
route file
1 | <routes> |
运行程序时需要送入一些参数,可以通过命令行形式送入,如果参数太多、太长,为了方便起见,可以将参数统一放到 xml config 文件中,在运行时,可以调用这个 config 文件。
定义 my_config_file.sumocfg
1 | <configuration> |
如果一个参数既出现在了 config 文件中,又在 command line 中,则采用 command line 的设置。
一切准备就绪,下边运行程序
1 | sumo-gui my_config_file.sumocfg |
然后将工具栏中的 Delay 设置为 100 ms,否则仿真开始之后瞬间结束。

在手动构造路网 net.xml 文件时,我们也可以用 SUMO 自带的 NETEDIT 程序,通过 NETEDIT GUI 编辑路网,可能效率更高一些
上述手动设置路网的方式只适用于比较简单的情况,如果要构造与现实世界比较接近的大型路网,我们可以用下边的从外部导入 OSM (Open Street Map)路网的方法。通过搜索城市、街道找到目标道路网,然后 export 即可。

转化成 SUMO 路网文件
1 | netconvert --osm-files map.osm -o sjtu.net.xml |
以上就得到了 .net.xml 文件,这里不是通过基于 node, edge, type 文件的整合,而是直接从 osm 地图转化过来。下边就是如何得到 route 文件。
对于这种大型的路网,手动创建 route 文件也很麻烦,这里我们用 SUMO 自带的 randomTrips.py 程序创建随机的 route 文件。
1 | python <path_to_randomTrips.py> -n sjtu.net.xml -r sjtu.rou.xml -e 50 -l # -e 表示 end time |
最后汇总sjtu.sumocfg
1 | <configuration> |
运行仿真,局部放大:

上边导入 osm 地图的方法还是比较麻烦,它主要包括 4 步:
- 从 osm 网站获取 osm 地图
- 用 netconvert 将 osm 地图转化成 SUMO 的 .net.xml 格式地图
- 用 randomTrip.py 生成随机 route 文件
- 开启仿真
实际上,SUMO 自带了一个 osmWebWizard.py 程序,整合了上述较为独立的步骤,在同一个操作界面,“一站式” 完成上述步骤。
用 osmWebWizard.py 运行仿真也是 SUMO tutorial 中的第一个项目。
1 | python osmWebWizard.py |
没有问题的话,应该会在浏览器中打开如下页面。这里初始地图位置是 Berlin。

首先是选定要仿真的地图环境。可以缩放、移动视图,通过右侧的 Select Area 可以选定一个区域。最好不要选择太大范围,否则仿真很占资源,甚至导致死机。
以上就设定好了地图和 route,点击右上方的 Generate Scenario, 就可以进入仿真界面了。
安装
安装XQuartz ,启动sumo-gui和netedit需要
1 | brew install --cask xquartz |
Traci接口
Traci接口是用来和sumo模拟器通信的, 因为不可能总是在sumo-gui里点图形化界面, 肯定得通过python, java之类的语言来和sumo通信, 靠的就是traci接口。
1 | import os |
相关接口说明:
traci.trafficlight.setPhase 设置红绿灯的状态(tlsID, index) 第一个为交通灯ID,第二个为灯的状态,2为绿灯
getNextSwitch(string) 获取到下个信号灯相位的时间
getPhaseDuration(string) 获取该信号灯相位已经持续的时间
setPhaseDuration(string, double) 设置当前信号灯持续的时间
getMinExpectedNumber 系统仿真中车辆数。如果车辆数为0,说明所有车辆已经离开路网。仿真可以停止了
getLastStepMeanSpeed(string) -> double 可以获取车辆平均行驶速度
getLastStepVehicleIDs(string) -> list(string) 获取通过感应线圈的车辆ID
traci.inductionloop.getLastStepVehicleNumber(string) -> integer 最近一次仿真步里,指定线圈上通过车辆的数量,判断某个方向是否有车通过
traci.edge.getLastStepVehicleNumber(string) -> integer 某个路段通过车辆的数量
traci下面的vehicle类 访问车辆动作的函数:
changeTarget(string, string) -> None重新规划目的地道路
getAccel(string) -> double 获取车辆加速度
getPosition(string) -> (double, double) 获取车辆位置
isStopped(string) -> bool 检测车辆是否停止
setAccel(string, double) -> None设置车辆加速度
setMaxSpeed(string, double) -> None 设置车辆最大速度
setStop(string, string, double, integer, double, integer, double, double) -> None 设置停车时间
行人动作函数:
traci.edge.getLastStepPersonIDs(edge) 获取该edge上行人的ID
traci.person.getWaitingTime(ped) 获取指定行人的等待时间(s)
订阅subscriptions:订阅可以被看作是一个用于检索变量的批处理模式。代替重复请求相同的变量,在每个时间步长中,你可以自动检索感兴趣的值。
1 | import traci |
检索的值总是从最后一个时间步骤的,它是不可能检索旧的值。
动力学模型
SUMO 中车辆动力学模型包括两方面
longitudinal model: 纵向动力学模型,描述车辆加速和减速
lateral model:横向动力学模型,描述车辆换道
纵向动力学模型方面,SUMO 主要用于研究车辆的外部行为、多车交互和交通流,对于单个车辆建模精度要求不高,可以近似看作质点。采用比较简单的 car-following model (跟车模型) 来描述车辆速度和位置变化规律。跟车模型分为两种情况:有前车和无前车。
无前车的情形,车辆保持为最大速度,这里最大速度要至少考虑三方面的因素。三个最大速度中的最小值:
- 该类型车辆本身能够达到的最大物理速度
- 前一时刻速度经过最大加速之后在当前时刻所能达到的最大速度
- 当前行驶道路规定的最大速度
有前车的情形,要计算安全的行驶速度,保证任何情况下(尤其是前车急刹车时)车辆不会相撞。不同的跟车模型主要区别就在于如何计算安全行驶速度。目前 SUMO 中采用的为改进的 Krauss model.
横向动力学模型方面,SUMO采用lane changing model变道模型,简单地说就是以决策树的方式设定诸多换道条件,只要满足某些条件,就进行相应的换道操作。默认的 lane changing model 是瞬间换道,即在一个 simulation step 中完成换道,直观地看就是车辆在两个车道之间瞬移。更加精细的模型包括SublaneModel和Simple Continous lane-change model。
Krauss model
了解一下原始的 Krauss model 的建模思想。

泰勒展开近似替代后,得到估算值:

1 | double MSCFModel_KraussOrig1::vsafe(double gap, double predSpeed, double /* predMaxDecel */) const { |
这一速度还不是最终车辆采用的跟车速度。与无前车情况类似,我们也要保证跟车速度不能超过允许的最大速度,因此要取安全速度和允许最大速度中的较小值.
改进模型与原始的 Krauss 模型的出发点是相同的:在保证不碰撞的前提下,车速尽量的快。但在计算安全速度方面,与原始 Krauss 完全不同.
没有采用泰勒展开方式近似表达刹车距离函数,而是直接数值计算。 基本思想是找到一个安全跟车速度使得后车在此速度下刹车距离 (包括反应距离) 正好等于前车的刹车距离加上原本两车间距。

lane changing model
道路车辆微观驾驶动力学是由以下几种模型的相互作用决定的:
- 跟驰模型:根据前车的行为决定自身的速度。
- 交叉口通行模型:从通行权规则、间隙接受、避免路口堵塞等方面确定车辆在不同类型交叉口的行为。
- 换道模型:决定在多车道道路的车道选择和换道时的速度调整。
相比于其他的微观换道模型,该模型明确区分了四种不同的换道动机:
- Strategic change 战略变道:每当车辆必须换道以便于能够驶向其行驶路径的下一条道路。
- Cooperative change 协同变道:帮助另一辆车辆换道到他们所在的车道
- Tactical change 战术变道:车辆试图避免跟随缓慢前车的动作,平衡从换车道中获得的预期速度收益和换车道的努力
- Obligatory change 义务变道:清除超车车道的强迫行为可以被定义为义务行为
汽车变道规划的四个子步骤:
- 计算优选后继车道;
- 在保持当前车道的假设下,计算安全速度,并整合来自先前模拟步骤的车道变换相关速度请求;
- 车道变换模型计算变更请求(左,右,停留);
- 执行换道操作或计算下一个模拟步骤的速度请求(包括提前计划多个步骤)。是否请求速度变化取决于变道请求的紧急程度;
评估子线路的标准:
- bestLanes(不需要换道)
- occupation(沿着最优道路的车辆密度)
- bestLaneOffset(车道偏移量)
评估换道行为的紧急程度:
探究vechicle 与blocking vehicle的关系,并根据两者之间的关系来相应地改变行为:
每当由于阻挡车辆而不能执行期望的车道变换时,车辆可以调整其速度以允许车道变换在后续步骤中成功。 此外,车辆可能对阻挡车辆的速度产生影响(实际上,这通常作为对观察自我车辆的转向信号的反应而发生)。
避免死锁:两车由于一些原因,同时到达道路的终点,此时两车都希望可以实现换道,这种情况便发生了死锁(deadlock)。
为了避免这种情况,对车进行分类(更靠近道路终点的称为
blocking leader,另一个称为the blocking follower)。后者要预先进行减速,以为前车留出足够的距离进行变道操作。尽管采取这种操作,死锁仍然可能无法避免,因为会存在多车道的情况。因此,采用的方法是预留出20~40m范围进行变道。