如何从OSM下载仅含机动车路网的标准.osm格式文件并兼容SUMO?
适配SUMO导入的OSM机动车路网提取方案
核心问题说明
OSMnx直接导出的.osm文件是简化后的网络拓扑结构,丢失了原始OSM文件的多层级标签、元数据与属性规则,因此SUMO解析时无法识别大部分节点与边的属性,导致导入缺失。以下方案直接生成符合原生OSM规范的机动车路网文件,过滤规则与osmnx.graph_from_place(..., network_type='drive')完全对齐。
方案1:Python调用Overpass API直接下载(优先推荐)
直接从OSM官方接口拉取原始结构的机动车路网,无需二次转换,SUMO兼容性最好。
依赖安装
pip install overpy
实现代码
import overpy import xml.etree.cElementTree as ET # 初始化Overpass客户端 api = overpy.Overpass() # 查询规则和OSMnx的drive类型完全对齐:筛选机动车可通行的道路,排除非机动车道、步道、私有道路等 query = """ [out:xml][timeout:25]; // 先查询目标区域边界,这里以Piedmont, CA, USA为例 area["name"="Piedmont"]["admin_level"="9"]["state"="CA"]->.searchArea; ( // 筛选机动车允许通行的道路类型 way["highway"~"motorway|motorway_link|trunk|trunk_link|primary|primary_link|secondary|secondary_link|tertiary|tertiary_link|unclassified|residential|living_street|service"]["access"!~"private|no"]["motor_vehicle"!~"no|private"](area.searchArea); // 拉取道路关联的所有节点 node(w); ); // 输出完整原始OSM结构 out body; >; out skel qt; """ # 执行查询 result = api.query(query) # 生成标准OSM格式文件 osm_root = ET.Element("osm", version="0.6", generator="Overpass API") # 写入节点 for node in result.nodes: node_elem = ET.SubElement(osm_root, "node", id=str(node.id), lat=str(node.lat), lon=str(node.lon)) for k, v in node.tags.items(): ET.SubElement(node_elem, "tag", k=k, v=v) # 写入道路边 for way in result.ways: way_elem = ET.SubElement(osm_root, "way", id=str(way.id)) for node in way.nodes: ET.SubElement(way_elem, "nd", ref=str(node.id)) for k, v in way.tags.items(): ET.SubElement(way_elem, "tag", k=k, v=v) # 保存文件 tree = ET.ElementTree(osm_root) tree.write("piedmont_drive.osm", encoding="utf-8", xml_declaration=True)
如果需要替换查询区域,调整query中area的筛选条件即可,也可以换成bbox范围查询
方案2:本地OSM文件过滤(已有全量OSM文件时使用)
使用pyosmium库对本地全量OSM文件做过滤,保留机动车路网,完全保留原始OSM结构。
依赖安装
pip install osmium
过滤规则和OSMnx的drive规则一致,直接导出的文件即可正常导入SUMO。
SUMO导入验证
使用SUMO官方的netconvert工具转换即可,无节点边丢失问题:
netconvert --osm-files piedmont_drive.osm -o piedmont.net.xml
内容的提问来源于stack exchange,提问作者Matyxus
相关产品推荐
相关产品推荐

