从GIS到交通仿真:shp转osm再导入SUMO的完整技术链路
发布时间:2026/10/14 3:34:57 锦皓数字建站

1. 从GIS数据到交通仿真这条链路到底在解决什么问题做过交通仿真的人都有一个共识路网建模是整个项目里最脏最累的活。你拿到手的往往是一份规划部门给的shp文件里面线要素密密麻麻属性表字段命名随心所欲拓扑关系一塌糊涂。而仿真工具需要的是一张干净、连通、带车道信息和限速的路网。这中间的鸿沟就是我今天要聊的核心内容。把shp文件转化为osm文件再导入SUMO本质上是在做一件事把GIS领域的通用矢量数据翻译成交通仿真领域能理解的路网语言。shp是ESRI那套体系下的产物强在几何表达和属性存储osm是OpenStreetMap的通用格式强在路网语义和拓扑结构SUMO则是微观交通仿真器它需要的是带车道数、限速、连接关系的精确路网。三者之间的转换不是简单的格式另存为而是一次语义层面的重构。这套流程适合谁如果你是交通工程专业的学生正在做课程设计或毕业论文需要把某个区域的路网导入仿真软件跑流量如果你是规划院的工程师手头有现成的GIS数据想快速搭建仿真场景做方案比选甚至你是做自动驾驶仿真的开发者需要构建测试场景的路网底图——这条链路都值得你花时间吃透。我前后用这套流程做过好几个项目踩过的坑包括但不限于坐标系不匹配导致路网偏移几百米、属性字段丢失导致所有道路限速变成默认值、交叉口拓扑断裂导致车辆开到路口就消失。下面我把整个流程拆开揉碎从原理到实操从工具选型到避坑经验一次性讲清楚。2. 整体技术路线设计与工具选型2.1 为什么是shp到osm再到SUMO而不是直接转换很多人第一反应是有没有工具能把shp直接转成SUMO的net.xml答案是理论上可以但实践中几乎没人这么干。原因在于SUMO的net.xml格式极其复杂它描述的是车道级别的连接关系包括每条车道的形状、每个交叉口的转向规则、信号灯相位等等。而shp文件通常只记录道路中心线没有车道级别的信息。直接从shp生成net.xml等于让工具去猜车道数和连接关系结果往往惨不忍睹。osm在这里扮演了一个中间语义层的角色。它有一套成熟的路网标签体系highway标签定义道路等级lanes标签定义车道数maxspeed标签定义限速oneway标签定义单行道。当你把shp转成osm时你实际上是在做一次语义映射——把shp属性表里的字段映射到osm的标准标签上。这个过程可以人工干预、可以批量处理、可以逐条校验。而SUMO对osm的支持非常成熟内置的netconvert工具能直接读取osm文件并生成路网它会根据osm标签自动推断车道连接、交叉口转向等细节。所以这条链路的核心逻辑是shp提供几何和原始属性osm提供标准化的路网语义SUMO负责最终的仿真路网生成。每一步都有明确的输入输出和可干预的环节出了问题也容易定位。2.2 工具链选型与各自角色整个流程涉及的工具不多但每个都有讲究工具角色选型理由QGISshp数据预处理与格式转换开源免费支持shp到osm的导出插件生态丰富JOSMosm文件精修专业osm编辑器支持批量编辑标签和拓扑检查SUMO netconvertosm转net.xmlSUMO官方工具对osm标签解析最完整SUMO netedit路网可视化检查与微调图形化编辑适合排查连接问题Python脚本批量属性处理当shp属性表字段复杂时用脚本做映射最高效QGIS在这里的角色是数据清洗和初步转换。它可以直接把shp图层导出为osm格式但导出的osm标签映射是QGIS默认的不一定符合你的需求。所以更常见的做法是在QGIS里先把shp的属性表整理好字段名尽量向osm标准标签靠拢然后再导出。JOSM的作用是精修。QGIS导出的osm文件在拓扑上往往有问题道路在交叉口处没有共享节点、单行道方向标反了、道路等级标签缺失。JOSM可以让你像编辑地图一样逐条检查和修正这些问题。它的验证工具能自动检测未连接的节点、重复的路径等问题效率比在QGIS里手动改高得多。netconvert是最终转换引擎。它的参数非常多但常用的就那么几个。关键是理解它如何根据osm标签推断车道数和连接关系。比如它默认会把highwayprimary的道路设为双向两车道如果你在osm里标了lanes4它就会生成四车道。如果没标它就按默认值来。所以osm标签的完整性直接决定了最终路网的质量。2.3 坐标系与投影的坑提前说清楚这是最容易翻车的地方。shp文件通常带有投影坐标系比如某个地方坐标系或UTM分区。而osm文件使用的是WGS84地理坐标系经纬度。如果你在QGIS里直接导出QGIS会自动做坐标转换但转换参数如果不对路网就会偏移。我的做法是在QGIS里先确认shp的坐标系然后用“另存为”功能导出时明确指定目标坐标系为EPSG:4326WGS84。导出后在JOSM里加载osm文件再加载一个底图比如卫星影像做视觉校验。如果路网和底图对不上说明坐标转换有问题需要回到QGIS检查原始坐标系定义是否正确。注意有些shp文件的坐标系定义是错的或者根本没有.prj文件。这种情况下你需要根据数据来源判断大致区域手动指定一个合理的坐标系再做转换。宁可多花十分钟确认也不要等到SUMO里发现路网跑到海里去了再回头查。3. shp数据预处理与属性映射的核心细节3.1 shp属性表的整理与标准化拿到一份shp文件第一件事不是急着转换而是打开属性表看看里面有什么。典型的道路shp会有这些字段道路名称、道路等级、车道数、限速、单行道标志、路面宽度等。但字段名可能是中文的、拼音的、或者缩写比如“DLDJ”代表道路等级“CD”代表车道数。你需要把这些字段映射到osm的标准标签上。osm的路网标签体系里最核心的几个是highway道路等级取值包括motorway、trunk、primary、secondary、tertiary、residential、service等。这个标签决定了SUMO里道路的默认限速和优先级。lanes车道数正整数。注意这是单向车道数不是双向总数。maxspeed限速单位是km/h。可以写数字也可以写“50”这样的形式。oneway单行道取值为yes或no。如果道路是单行道还需要注意方向。name道路名称主要用于标识不影响仿真。在QGIS里你可以用字段计算器批量生成这些标签字段。比如新建一个字段叫“highway”根据“DLDJ”字段的值做映射如果DLDJ是“快速路”则highway赋值为“motorway”如果是“主干路”赋值为“primary”以此类推。这个映射关系需要你根据当地的道路分类标准来定没有统一答案。我一般会先在Excel里整理一张映射表然后在QGIS里用“按表达式计算”或者Python脚本批量赋值。这样比手动一条条改快得多而且不容易出错。3.2 几何处理打断、简化与拓扑修复shp文件里的道路几何往往是连续的折线一条路从起点到终点可能穿过多个交叉口但它在属性表里只是一条记录。这种数据在转osm时会有问题osm要求道路在交叉口处必须打断共享一个节点。如果一条路穿过交叉口但没有节点SUMO就无法识别这里有一个路口车辆会直接开过去不会产生转向行为。所以预处理阶段必须做几何打断。在QGIS里可以用“线相交”工具或者“分割线”工具把所有道路在交叉口处打断。具体操作是先提取所有道路的交叉点然后用这些点去分割道路线。打断之后每条路段都是两个节点之间的一段拓扑关系就清晰了。另一个问题是几何简化。shp文件的折线可能非常密集每隔几米就有一个节点。osm文件虽然也能容纳这么多节点但SUMO在生成路网时会对节点做处理过多的节点会导致路网文件巨大仿真速度变慢。我通常会用QGIS的“简化几何”工具设置一个合适的容差值比如1米把不必要的节点去掉。容差太大会导致道路形状失真太小则起不到简化效果需要根据路网精度要求来调。还有一个容易被忽略的问题是重复道路。有些shp文件里同一条路可能因为数据采集原因存在两条重叠的线或者一条主路和一条辅路完全重合。这种情况在转osm后会导致SUMO生成重复路段车辆会在两条路上跳来跳去。处理方法是在QGIS里用“删除重复几何”工具或者手动检查并删除多余的线。3.3 道路等级与车道数的映射逻辑道路等级和车道数的映射直接决定了SUMO里车辆的行驶行为。SUMO会根据highway标签给道路分配一个默认限速和优先级但如果你在osm里明确写了maxspeed和lanes它会优先使用你写的值。这里有一个经验性的映射表供参考shp道路等级osm highway标签默认限速(km/h)典型车道数快速路motorway120双向6-8车道主干路primary60双向4-6车道次干路secondary40双向2-4车道支路residential30双向2车道小区内部道路service20单向1车道这个表不是绝对的你需要根据实际数据调整。关键是lanes标签一定要写对。如果你不写lanesSUMO会按默认值来通常是双向两车道。但实际道路可能是双向四车道这样仿真出来的通行能力就差了一倍。还有一个细节oneway标签的方向。shp文件里如果有一条单行道它的几何方向可能和实际行驶方向一致也可能相反。在转osm时你需要确保onewayyes的道路其几何节点顺序是从起点到终点的。如果反了SUMO里车辆会逆行。检查方法是在JOSM里看箭头方向或者在SUMO netedit里看车道方向。4. 从shp到osm的实操过程与关键步骤4.1 QGIS导出osm的完整操作假设你已经在QGIS里整理好了属性表字段名已经映射为highway、lanes、maxspeed、oneway等。接下来是导出操作在QGIS图层面板中右键点击道路图层选择“导出”-“另存为”。在格式下拉框中选择“OpenStreetMap XML”如果找不到需要安装“OSM Export”插件。指定输出文件路径和名称后缀为.osm。在“坐标系”选项中选择EPSG:4326WGS84。在“字段映射”部分QGIS会尝试自动映射字段。你需要手动确认highway字段是否映射到了osm的highway标签lanes是否映射到了lanes标签以此类推。点击确定等待导出完成。导出完成后用文本编辑器打开osm文件看一眼。它应该是一个XML结构包含 和 元素。 是节点有经纬度坐标 是路径引用了多个节点ID并带有 标签。检查一下 里是否有你需要的标签比如 。如果发现标签丢失或映射错误回到QGIS检查字段映射设置。有时候QGIS会把字段名直接作为标签名比如字段叫“highway”它就生成 这是对的。但如果字段叫“道路等级”它就会生成 SUMO不认识这个标签。所以字段名一定要用英文标准标签名。4.2 JOSM精修拓扑检查与标签补全QGIS导出的osm文件拓扑上通常有以下几类问题未连接的节点两条路在交叉口处应该有共享节点但QGIS导出时可能生成了两个独立的节点坐标相同但没有合并。JOSM的验证工具会提示“未连接的节点”或“重复节点”。道路方向错误单行道的方向可能反了。标签缺失某些道路没有highway标签或者lanes标签为空。道路重叠两条路完全重合。在JOSM里修复这些问题的流程是打开JOSM加载osm文件。按ShiftV打开验证面板点击“验证”按钮。JOSM会列出所有问题。对于“未连接的节点”双击问题条目JOSM会定位到问题位置。你可以手动把两个节点合并选中两个节点按M键或者用“合并节点”工具批量处理。对于“道路方向错误”选中道路按R键反转方向。或者在属性面板里检查oneway标签确保方向正确。对于“标签缺失”选中道路在属性面板里添加缺失的标签。可以多选道路批量添加。对于“道路重叠”选中其中一条按Delete删除。JOSM还有一个很实用的功能下载底图。你可以通过“影像”菜单加载卫星影像或地图底图然后目视检查路网是否和底图对齐。如果发现整体偏移说明坐标转换有问题需要回到QGIS重新导出。实操心得JOSM的验证工具虽然强大但有时候会报一些“假阳性”问题。比如两条路在端点处连接但JOSM认为它们没有共享节点。这种情况下你需要手动检查节点坐标是否完全一致。如果一致但不共享用“合并节点”工具处理。如果不一致说明几何有微小偏差需要调整节点位置。4.3 osm转SUMO路网netconvert参数详解osm文件准备好之后就可以用SUMO的netconvert工具生成路网了。基本命令是netconvert --osm-files input.osm --output-file output.net.xml但这只是最基础的转换生成的路网往往需要调整。以下是我常用的参数组合netconvert --osm-files input.osm \ --output-file output.net.xml \ --geometry.remove \ --ramps.guess \ --junctions.join \ --tls.guess-signals \ --tls.discard-simple \ --no-turnarounds \ --offset.disable-normalization \ --lefthand false逐个解释这些参数的作用--geometry.remove移除不必要的几何节点简化路网。这个参数会合并一些短路段减少节点数量。--ramps.guess自动推断匝道连接。如果你的路网里有高速公路匝道这个参数能帮助生成合理的连接。--junctions.join合并距离很近的交叉口。有些交叉口在osm里被拆成了多个节点这个参数能把它们合并成一个。--tls.guess-signals自动推断信号灯位置。SUMO会根据交叉口的道路数量和流量猜测哪些路口需要信号灯。--tls.discard-simple丢弃简单的信号灯。有些路口只有两条路相交SUMO认为不需要信号灯这个参数会把这些信号灯去掉。--no-turnarounds禁止掉头。除非你的路网确实需要掉头否则建议禁止因为掉头会占用大量仿真资源。--offset.disable-normalization禁用坐标归一化。这个参数确保路网的坐标和原始osm一致方便后续和GIS数据对齐。--lefthand false右侧通行。国内是右侧通行所以设为false。如果是左侧通行的地区设为true。转换完成后用SUMO的netedit打开output.net.xml检查路网是否合理。重点看几个地方交叉口是否有连接线、车道数是否正确、限速是否合理、单行道方向是否对。如果发现问题可以在netedit里手动调整也可以回到osm文件修改后重新转换。4.4 路网校验与仿真测试路网生成后不要急着跑仿真。先做几项校验第一连通性检查。在netedit里用“检查连通性”工具看看有没有孤立的路段或无法到达的区域。如果发现某条路和主路网不连通说明osm里缺少连接节点需要回去补。第二车道连接检查。在交叉口处检查每条进口道是否有对应的出口道连接。如果某个方向没有连接车辆到这个路口就无法转向。netedit里可以用“连接编辑器”查看和修改。第三限速和车道数检查。随机选几条路看看属性面板里的限速和车道数是否和预期一致。如果发现所有路都是默认值说明osm标签没有正确传递。第四跑一个简单的仿真测试。在SUMO里加载路网用randomTrips.py生成一些随机出行需求跑几分钟看看车辆是否能正常行驶。如果车辆在某个路口消失或卡住说明那里有连接问题。注意netconvert生成的信号灯是默认配时通常需要根据实际方案调整。如果你的项目涉及信号控制需要在netedit里手动修改信号灯相位和配时或者用额外的工具生成信号配时文件。5. 常见问题与排查技巧实录5.1 路网偏移与坐标问题现象导入SUMO后路网整体偏移和底图对不上。原因坐标转换参数错误或者shp文件坐标系定义不准确。排查步骤在QGIS里确认shp的原始坐标系。查看图层属性看坐标系定义是什么。如果坐标系定义是“未知”或明显错误需要根据数据来源判断正确坐标系。比如数据来自某个城市可以查该城市常用的地方坐标系。在QGIS里用“重新投影”工具把shp投影到EPSG:4326。导出osm后在JOSM里加载底图目视检查对齐情况。如果仍有微小偏移可能是原始数据采集精度问题可以在JOSM里手动微调或者在SUMO里用offset参数调整。避坑技巧在项目开始前先拿一个已知坐标的点做测试。比如在shp里找一个明显地标如交叉口中心记下它的坐标转换后在JOSM里看这个点是否落在底图的对应位置。这样可以快速判断坐标转换是否正确。5.2 属性丢失与标签映射错误现象SUMO路网里所有道路的限速都是默认值车道数都是1。原因osm文件里缺少maxspeed和lanes标签或者标签名不对。排查步骤用文本编辑器打开osm文件搜索tag kmaxspeed和tag klanes。如果没有说明QGIS导出时字段映射没做对。回到QGIS检查字段映射设置。确保shp里的限速字段映射到了osm的maxspeed标签车道数字段映射到了lanes标签。如果字段名不是标准标签名可以在QGIS里用字段计算器新建标准命名的字段把原字段的值复制过去。重新导出osm再次检查。避坑技巧在QGIS里整理属性表时直接把字段名改成osm标准标签名。比如把“限速”改成“maxspeed”把“车道数”改成“lanes”。这样导出时QGIS会自动映射不需要额外配置。5.3 交叉口拓扑断裂现象车辆行驶到交叉口后消失或者无法转向。原因osm文件里交叉口处的道路没有共享节点SUMO认为这些路没有连接。排查步骤在JOSM里打开osm文件按ShiftV验证。查看是否有“未连接的节点”问题。定位到问题位置检查两条路的端点节点是否坐标一致。如果一致但不共享用“合并节点”工具合并。如果不一致说明几何有偏差。可以用“对齐节点”工具或者手动调整节点位置。合并后重新导出osm用netconvert重新生成路网。在netedit里检查交叉口连接确保每个方向都有连接线。避坑技巧在QGIS里做几何打断时确保打断点准确落在交叉口中心。如果打断点偏移会导致节点不重合。可以用“捕捉”功能让打断点自动吸附到交叉口。5.4 单行道方向错误现象单行道上的车辆逆行或者双向道路被误判为单行道。原因osm里oneway标签设置错误或者道路几何方向与行驶方向相反。排查步骤在JOSM里选中单行道查看属性面板里的oneway标签。如果是yes检查道路上的箭头方向是否与预期一致。如果方向反了按R键反转道路方向。如果双向道路被误判为单行道检查oneway标签是否误设为yes。如果是改为no或删除该标签。重新导出osm重新生成路网。避坑技巧在QGIS里整理属性时单行道字段的值要明确。可以用“是/否”或“1/0”表示然后在导出时映射为yes/no。不要留空留空可能导致SUMO按默认值处理。5.5 路网文件过大导致仿真缓慢现象SUMO加载路网很慢仿真运行时卡顿。原因osm文件里节点过多或者netconvert生成了大量不必要的连接。排查步骤在QGIS里用“简化几何”工具减少道路折线的节点数。容差设为1-2米既能保持形状又减少节点。在netconvert里加--geometry.remove参数让工具自动简化。检查是否有重复道路删除多余的。如果路网范围很大考虑只保留仿真需要的区域裁剪掉无关部分。避坑技巧在项目初期就确定仿真范围不要一次性导入整个城市的路网。按需裁剪既能加快仿真速度也便于管理。6. 进阶技巧批量处理与自动化脚本6.1 用Python批量处理shp属性当shp文件字段复杂、需要批量映射时用Python脚本比在QGIS里手动操作高效得多。以下是一个示例脚本用geopandas读取shp整理属性后导出为osm兼容的格式import geopandas as gpd import pandas as pd # 读取shp文件 gdf gpd.read_file(roads.shp) # 查看字段 print(gdf.columns) print(gdf.head()) # 道路等级映射 level_map { 快速路: motorway, 主干路: primary, 次干路: secondary, 支路: residential } # 新建highway字段 gdf[highway] gdf[道路等级].map(level_map) # 新建lanes字段 gdf[lanes] gdf[车道数].apply(lambda x: str(int(x)) if pd.notna(x) else 2) # 新建maxspeed字段 gdf[maxspeed] gdf[限速].apply(lambda x: str(int(x)) if pd.notna(x) else 40) # 新建oneway字段 gdf[oneway] gdf[单行道].apply(lambda x: yes if x 1 else no) # 投影到WGS84 gdf gdf.to_crs(epsg4326) # 导出为GeoJSON后续可转osm gdf.to_file(roads_processed.geojson, driverGeoJSON)这个脚本的核心是字段映射和坐标系转换。映射关系可以根据实际数据调整。导出为GeoJSON后可以用QGIS打开再导出为osm或者用其他工具转换。6.2 netconvert批处理与参数模板如果你需要频繁转换不同区域的路网可以把netconvert命令写成一个批处理脚本#!/bin/bash # 批量转换osm到net.xml for osm_file in ./osm_data/*.osm; do filename$(basename $osm_file .osm) netconvert --osm-files $osm_file \ --output-file ./net_data/${filename}.net.xml \ --geometry.remove \ --ramps.guess \ --junctions.join \ --tls.guess-signals \ --tls.discard-simple \ --no-turnarounds \ --offset.disable-normalization \ --lefthand false echo Converted: $filename done这个脚本会遍历osm_data目录下的所有osm文件逐个转换并输出到net_data目录。参数模板可以根据项目需求调整。6.3 用netedit做最终微调netconvert生成的路网虽然大体可用但总有一些细节需要手动调整。netedit是SUMO自带的图形化路网编辑器功能非常强大。我常用的操作包括修改车道连接在交叉口处用连接编辑器调整每个进口道到出口道的连接关系。比如某个方向禁止左转可以在这里取消连接。调整信号灯配时选中信号灯路口在属性面板里修改相位和配时。添加或删除路段如果发现osm里遗漏了某条路可以在netedit里手动添加。修改限速和车道数选中路段在属性面板里直接修改。netedit的界面可能一开始不太习惯但用多了会发现它比反复修改osm文件再重新转换高效得多。特别是对于局部调整直接在netedit里改完保存即可不需要重新跑netconvert。7. 一些零散但重要的经验关于数据来源不同来源的shp文件质量差异很大。规划院的数据通常属性完整但几何精度一般测绘部门的数据几何精确但属性可能缺失。拿到数据后先做质量评估决定是否需要补充属性或修正几何。关于osm标签的完整性SUMO对osm标签的解析是有优先级的。如果你写了maxspeed它就用你写的值如果没写它按highway标签的默认值如果连highway都没写它就按最保守的默认值通常是30km/h。所以宁可多写标签不要留空。关于仿真精度路网精度和仿真精度是两回事。路网再精确如果交通需求数据不准仿真结果也没有意义。所以不要过度追求路网的完美够用就行。把更多精力放在交通需求建模和参数校准上。关于版本兼容SUMO的版本更新比较频繁不同版本的netconvert参数可能略有差异。建议固定使用一个稳定版本不要频繁升级。如果升级先在小项目上测试确认没问题再迁移。关于文件管理整个流程涉及多个中间文件原始shp、预处理后的shp、导出的osm、精修后的osm、生成的net.xml。建议按项目建目录每个阶段的文件分开存放命名清晰。这样出问题时容易回溯也方便团队协作。关于性能优化如果路网规模很大比如整个城市netconvert转换可能耗时较长。可以先用小范围数据测试参数确认无误后再跑全量。另外netconvert支持多线程可以用--threads参数指定线程数加快转换速度。关于可视化检查SUMO的sumo-gui可以加载路网并可视化。在跑仿真前先用sumo-gui打开net.xml看看路网显示是否正常。如果发现路段显示异常比如车道数不对、连接线缺失及时回到netedit修正。关于文档记录整个转换流程涉及的参数和映射关系很多建议写一个简单的文档记录每一步的操作和参数。这样下次做类似项目时可以直接参考也方便交接给其他人。这套流程我用了好几年从最初的手忙脚乱到现在的流程化操作中间踩过的坑不计其数。核心体会就是预处理阶段多花时间后面就少受罪。shp属性整理得越干净osm标签映射得越准确SUMO路网的质量就越高后续仿真调试的时间就越短。反过来如果预处理偷懒后面在netedit里一个个修连接、改限速那才是真正的噩梦。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。