面向自动驾驶的高精度地图框架解析和实战
目前行业并没有通用的标准(OpenDrive并不是为自动驾驶设计的),Autoware自动驾驶系统的矢量地图和地图引擎计划使用Lanelet2,本文我们就来了解并且上手一下Lanelet2高精度地图框架。
本文来源:hdmap
前面聊了一些如何制作较大规模的点云地图以及如何使用点云地图进行定位的方法,点云图是高精度地图的一部分,主要用于配准定位和作为高精度地图构建环节中的几何图层(能够反应路面几何结构和大量有效信息),产品形态的高精度地图通常为包含大量交通要素语义和坐标信息的矢量地图,如何定义、构造这种面向自动驾驶业务的矢量地图,目前行业并没有通用的标准(OpenDrive并不是为自动驾驶设计的),Autoware自动驾驶系统的矢量地图和地图引擎计划使用Lanelet2,本文我们就来了解并且上手一下Lanelet2高精度地图框架。
Lanelet2是什么?
准确地说,Lanelet2是一套面向自动驾驶(highly automated driving ,HAD)的地图框架,使用C++实现,下图描述了自动驾驶模块对于HAD map(为HAD服务的地图我们把它简称为HAD map)的使用情况:
HAD map很重要,一些图商也号称能够提供面向自动驾驶的高精度地图,但是真正开源的地图架构非常少,Lanelet2前身是Liblanelet,该框架作为map format驱动了 Bertha-Benz项目(奔驰的一个HAD原型车) ,Liblanelet提供了用于routing、动作规划乃至目标行为预测的C++接口,但是Liblanelet这个库存在一些短板,并不能支持上图中所示HAD系统中的许多功能,Lanelet2就是Liblanelet库的改进版。
地图格式(map format)目前来说是比较混乱的,开源领域用的最多的当属OSM的地图格式,OSM全称Open Street Map,是一个开源的、众包电子地图框架。
Lanelet2的设计理念
由上图可知HAD系统对于HD map的利用情况可以分为以下三个方面:
使用路网(road network)信息进行全局路线规划(routing)、行为决策以及目标预测;需要结合车道和其他图层的信息的AD模块:诸如路径规划(path planning)、场景理解等;需要直接访问图层元素的AD模块:主要是定位模块,将地图的某些图层(比如点云图)用于配准定位routing和path planning的区别:routing是指在导航中获取的从起点到终点的路线,是全局的规划,而path planning是指根据当前的全局规划选择接下来的100米的路径,包括走哪条车道、是否变道等,是局部的规划,两者相交(路径规划需要满足routing的要求)但不相同。
我们就从这三个方面理解Lanelet2的设计理念。
路网(Road network)
路网即地图中道路的拓扑关系,在传统的电子地图中,路网是地图的骨架,道路元素多是通过在路网基础上添加offset来表述的。HAD系统中,使用路网语义的主要目的之一就是产生routing,即起点到终点的全局路线,区别于粗粒度的电子导航routing,AD系统中的routing不仅需要知道车的路线(road级别),还需要知道车道(lane)级别的信息,比如说可以走哪些车道、车道是不是公交专用道、车道能否变道、能否借道等等。
行为决策也和路网信息高度相关,目前的HAD系统里,行为决策的实现依然是基于交通规则的,对规则列表的适配需要结合routing信息。目标的预测也类似,道路交通中的目标预测一个重要的先验就是目标在多数情况下会在自己的车道上行驶或者遵循交通规则变道,针对不同的道路参与者,交通规则也不一定相同,所以,一个合格的自动驾驶地图,应当包含所有交通参与者的道路规则,比如说非机动车道以及行人可能出现的区域和运动的方向等。
车道和环境要素信息
车道的几何信息对于AD系统的规划尤其是动作规划尤为关键,HAD规划系统产生的轨迹并不一定严格遵循车道中心线,在安全和 车道道宽 允许的情况下动作规划模块通常倾向于产生平滑且舒适度高的轨迹,这就意味着我们不仅需要知道车道中心线的位置,车道的边缘坐标对于HAD系统也是非常有意义的。
物理元素
基于配准的定位需要直接访问某些地图中的某些物理元素,这些物理元素的类别和具体的定位方法相关。包括landmark(路标)、护栏、道路边缘等信息,HAD map理论上应该包含这些物理元素以支持基于地图的配准定位。
高度精度地图的另一大挑战就是保持地图的“新鲜度”,即始终处于最新的状态,显然地图包含的要素越多,需要更新的概率就越大,现代电子地图通常只包含已经预处理过的结构化数据,不包含基础的物理元素,那么一旦环境发生变化,就很难追踪环境变化对地图的影响。
lanelet2论文中的一个例子:假定我们拆除了一条道上的限速牌,那么相应的这块限速牌后的road section(路段)的限速也就应该被解除,但是实际上可能在路的另一侧还有一个限速牌,如果我们只是把速度作为道路的属性而不标注速度属性的信息源的话,就难以确定速度的来源是什么,也就是交通规则的来源。所以HAD map不仅要生产必要的交通要素,还应该包含交通要素的来源。
设计理念总结
lanelet2称上述可以被观测到的要素为地图的 物理层(physical layer) ,诸如路标、红绿灯、交通标志、防撞栏等等,其他的所有地图元素,比如车道(lane),是这些物理元素的一种抽象表示。同样地,交通规则是规则源(例如交通信号灯)与其所应用的车道之间的关联。根据这些物理元素我们可以追踪这些关联信息,我们称这些元素为地图的 关联层(relational layer)。
然而,并非地图的所有元素都可以与物理层相关联,因为道路交通中往往会包含隐含的规则,比如说在路口内,车道线和车道边缘并没有画出来,但是它们是存在的,HAD map必须包含这些隐含的元素以保证路网拓扑的连通性,这些元素都是我们的行为“常识”引入的,不和实际的可观测元素关联。
站在地图可验证性的角度来看, Lanelet2作者认为应当尽可能避免这种“常识”元素和规则,一方面是因为缺乏物理元素关联,给地图验证带来困难,另一方面,“常识”有时候也是会发生变化的。
可拓展性也是HAD map必须具备的特性,随着无人车算法的发展,必然对于地图的需求也会发生变化,另外地图得适配各个国家的交通规则,这些都对地图的可扩展性提出了要求。总的来说,为了设计面向自动驾驶的地图,lanelet2认为需要遵循一下原则:
可以通过将地图上的所有信息与可观察元素(物理元素)相关联来进行验证;涵盖所有潜在的可通行区域,包括道路以外的;地图上各个车道与区域之间的交互必须是可识别且可理解的,通过地图要能够知道哪些车道间可以进行变道;地图应当包含对其他类型交通参与者(比如说行人、非机动车)的交通规则和信息;应当将地图的信息源和其对道路交通的影响进一步分离,以保证元素变更的可追踪性;可扩展性和模块化;可以轻松修改,以实现地图的更新;
结合以上基本原则,我们来看一下Lanelet2对于地图元素的划分和定义,以及结合osm的Lanelet2地图格式。
Lanelet2架构
由上述的设计理念可知,Lanelet2地图可以划分为:
物理层(physical layer):主要包含一些能具体观测到的元素关联层(relational layer):物理层的元素被进一步关联到车道、区域和交通规则等信息拓扑层(topological layer)
Lanelet2默认的格式为XML形式的OSM地图格式,可以使用OSM地图编辑器进行编辑和可视化。Lanelet2假定地图中的所有元素均能投射到平面,不过元素的高度信息也会被保存,以避免将立交桥处理成十字路口的情况。当加载地图的时候,为了方便地图的使用,会采用通用莫卡托投射(UTM,Universal Transverse Mercator)将地图投射到笛卡尔坐标系。
Lanelet基础元素
Lanelet2地图主要包含6类基元(18年论文中为5类,后扩展为6类),分别是:
Points:点Linestrings: 由点前后连接构成的折线序列Polygons:多边形Lanelets:车道的原子单元,或者说对车道的最小划分Areas:区域,类似与lanelet,但是它一般用于描述建筑、停车区等独立区域Regulatory elements:控制元素,能产生交通规则的元素,如信号灯、限速牌等
前三类为物理层,其余为关联层,每一个元素都有自己唯一的ID,我们逐一分析基元的含义。
Points
Points是地图的最基础元素,单个的Points也能表示一些含义,比如说一个柱子,但是更多情况下,点是作为Linestrings的一部分出现的。一个Point会包含三维位置信息,Points也是Lanelet2中唯一真实包含位置信息的基础元素,其他基元直接或间接地由点组成。下面是一个Points的例子:
<node id="1001" visible="true" version="1" lat="35.61834168094" lon="139.78068648494"><tag k="ele" v="-2.5" /><tag k="local_x" v="89576.40395318175" /><tag k="local_y" v="42302.65455295006" /><tag k="mgrs_code" v="54SUE895423" /><tag k="subtype" v="" /><tag k="type" v="" /></node>12345678
Lanelet2中的Points会被直接映射为OSM中的Node,其中的ele的tag主要描述点的海拔高度(WGS84坐标系下)。
Linestrings
如下图所示,Linestrings是对一组有序的点进行线性插值构成的线串,用于描述地图中元素的轮廓,包括道路标线、路缘、外墙、栅栏等,它也能描述一些虚拟的线,比如说车道线等,Linestrings不能包含重复的点,且不能相交,Linestrings必须包含type属性以确定其用途。
Polygon
Polygons也就是多边形的意思,和Linestrings类似,也是一组折线,区别在于Polygons的第一个点和最后一个点是连接的,从而能够闭环形成一个图形。多边形通常用作自定义元素(例如感兴趣的区域)。
Lanelet
Lanelet定义了地图中车道的原子段,原子段即最小分割,指在这一段lane上交通规则是不变的。下图是lanelet的定义,可见一个lanelet包含左右两条lanestrings分别表示车道的左右边缘,构成了lanelet的可行驶区域(drivable area)。lanelet通常还会包含Regulatory elements指定该lanelet上的交通规则,连续的两端lanelet共享左右linestrings的端点,Lanelet边缘的类型将被用于判断能否变道。车道中心线是非必须元素,可以指定也可以不指定,不指定的话在加载osm是Lanelet2库会自动生产中心线。
下面是一个lanelet的例子,我们必须能够直接从lanelet元素中获得车道的限速,可以通过两种方法指定lanelet的限速:第一是通过关联一个type为SpeedLimit的控制元素来指定限速,第二则是如下例所示设定location的tag来指定限速(如果是在德国市区,那么限速就是50kph)。
<relation id='45064' visible='true' version='1'><member type='way' ref='43822' role='left' /><member type='way' ref='43564' role='right' /><tag k='location' v='urban' /><tag k='one_way' v='yes' /><tag k='region' v='de' /><tag k='subtype' v='road' /><tag k='type' v='lanelet' /></relation>123456789
lanelet元素对应于OSM格式中的relation,下图是该lanelet(id为45064)在JOSM中的可视化效果(图中粉色线):
Area
Area类似于Lanelet,是指由多个linestrings构成的一片区域, 通常用来描述停车位、绿化带、建筑物等,Area也可以关联控制元素以添加交通规则。下图使用Area描述了两个停车区:
具体到osm format中,采用type为multipolygon的relation描述Area,停车区的例子如下:
<relation id='45420' visible='true' version='1'><member type='way' ref='44024' role='outer' /><member type='way' ref='44402' role='outer' /><member type='way' ref='44768' role='outer' /><tag k='location' v='urban' /><tag k='region' v='de' /><tag k='subtype' v='parking' /><tag k='type' v='multipolygon' /></relation>123456789
该Area元素对应于下图中粉红色框内的停车区:
Regulatory elements(控制元素)
控制元素定义了地图中的交通规则,诸如限速、优先规则、信号灯等,控制元素需要被lanelet或者area引用才能发挥作用。下图描述的是信号灯的控制元素,该控制元素包含停止线以及红路灯:
Lanelet2项目各个模块
Lanelet2论文的另外一个工作就是基于以上设计理念和基本要素开源了一套C++编写的地图框架,lanelet2项目依靠catkin编译,所以每个模块都是以ros package的形式进行管理,各个模块内容如下:
lanelet2:基础模块,没有具体实现lanelet2_core:实现了基元、地理计算等核心库lanelet2_io:lanelet地图的IO库lanelet2_traffic_rules:提供地图交通规则的支持lanelet2_projection:提供WGS84坐标系到指定坐标系下的投影的实现lanelet2_routing:提供基于lanelet地图的routing功能lanelet2_maps:lanelet2官方提供的示例地图lanelet2_python:lanelet2的python接口lanelet2_validation:验证Lanelet2地图lanelet2_examples:教程和示例
可以通过lanelet2_examples下面的代码进一步学习lanelet2项目的API的使用。具体使用方法本文不再赘述,下面我们主要关注lanelet2在自动驾驶系统Autoware中的应用。
注意:建议看到这里的同学先完成lanelet2_examples下的代码阅读和理解,再开始下面的阅读。
Autoware对lanelet2的扩展
Autoware最新的Map模块已经舍弃了先前的基于csv的map format,转而使用基于lanelet2的OSM格式地图,Autoware的map模块在AD系统中的结构和数据流如下图所示:
lanelet2地图在系统中被称为vector map,主要描述道路交通的语义信息,目前来说vector map主要被用于planning和perception两个模块,其作用主要为:
Perception:使用vector map预测目标的轨迹(基于车道的)用于红绿灯检测Planning:计算当前位置到目标终点的routing路线在lane follow场景下(注意,最新的Autoware也采用了类似Apollo的规划模块设计,基于场景进行了划分)计算沿车道的轨迹交通规则的读取
为了方便自动驾驶系统各个模块调用HAD Map,Autoware对lanelet2进行了一些扩展,扩展内容包括必须属性和非必须属性,表现为OSM中的Tag,下面详细讨论:
额外的必须属性
海拔信息(ele)
point的海拔信息在lanelet2中是非必须的,但是对于Autoware来说,在执行信号灯检测模块时依赖该信息,所以Autoware要求OSM中所有的point(node)都应该包含名为ele的海拔信息及具体的数值,如下所示:
<node id='1' visible='true' version='1' lat='49.00501435943' lon='8.41687458512'><tag k='ele' v='3.0'/></node>123
SpeedLimit属性
在lanelet2中,lanelet(osm对应于ralation)的speedlimit是非必须tag,因为lanelet2有三种设定speedlimit的方式(前面已经讨论),为了避免混淆,Autoware将其作为必须tag,如下:
<relation id="34408" visible="true" version="1"><member type="way" ref="34406" role="left" /><member type="way" ref="34407" role="right" /><tag k="speed_limit" v="30m/h" /><tag k="subtype" v="road" /><tag k="type" v="lanelet" /></relation>1234567
信号灯
默认的lanelet2允许使用linestring和Polygon来描述信号灯,Autoware为了避免混淆仅允许使用linestring描述信号灯,如下图所示,仅用一条linestring描述一个红绿灯,linestring的起点为左下,终点为右下角,通过定义height指定信号灯的高度,如下实例所示:
<way id='13' visible='true' version='1'><nd ref='6' /><nd ref='5' /><tag k='type' v='traffic_light' /><tag k='subtype' v='red_yellow_green' /><tag k='height' v='0.5'/> <!-- this tag is mandatory for Autoware!! --></way>1234567
道路方向
路口内的lanelet需要包含turn_direction属性以支持左右转向灯的功能,示例如下:
<relation id='1' visible='true' version='1'><member type='way' ref='2' role='left' /><member type='way' ref='3' role='right' /><member type='relation' ref='4' role='regulatory_element' /><tag k='location' v='urban' /><tag k='one_way' v='yes' /><tag k='subtype' v='road' /><tag k='type' v='lanelet' /><tag k='turn_direction' v='left' /> <!-- this tag is mandatory for lanelets at intersections!! --></relation>12345678910使用Lanelet2地图完成仿真环境中的routing
lanelet2地图中包含大量交通元素,自动驾驶系统中各个模块会根据其自身的业务需求来使用地图中的对应元素,本文的实践部分我们将采用lanelet2地图完成一个起点到终点的routing,并且将routing的结果显示于Rviz中,实践部分为C++编写的ROS项目。
代码克隆与环境准备
读者可以直接在你的ROS workspace下克隆我的这个仓库:
cd your_ros_workspace/src/git clone https://github.com/AbangLZU/ad_with_lanelet2.git12
根据仓库中README.md的提示(Manual installation一节),安装lanelet2项目所需的依赖,在此不赘述。
安装好lanelet2相关依赖后,使用catkin build编译:
cd your_ros_workspacecatkin build12
你可能没有安装catkin build工具,可以使用sudo apt-get install python-catkin-tools 命令安装。
本项目的仓库包含了一份Autoware官方开源的高精度地图样例(lanelet2格式),我们使用该地图完成实践,地图文件位于项目的:
map/map_loader/data/lanelet2_map.osm1路径下。Lanelet2地图的可视化和编辑
因为采用了OSM的地图格式定义,Lanelet2地图可以很方便地使用OSM的工具链进行查看和编辑,下面我们使用JOSM工具对项目内的lanelet2_map.osm地图进行可视化和编辑。JOSM是一个Java实现的对OSM进行编辑的工具,因其为Java程序,所以可以跨平台使用,官网下载最新版本的JOSM,本文采用的是jar包的形式运行,jar下载链接:https://josm.openstreetmap.de/josm-tested.jar
配置系统的Java环境,参照教程:https://josm.openstreetmap.de/wiki/Download#Java 检查你的系统是否正确安装Java,你也可以在命令行通过java --version检查系统中安装的Java,我的环境如下:
openjdk 14.0.1 2020-04-14OpenJDK Runtime Environment (build 14.0.1+7)OpenJDK 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)123
下载好josm-tested.jar包后,在同目录下使用以下命令运行JOSM:
java -jar josm-tested.jar1
在JOSM中添加lanelet2的地图样式和预设组合标签,在JOSM中选择预设组合->preset preferences->地图样式->+:
分别将项目中lanelet2_maps/josm/目录下的lanelets.mapcss和lines.mapcss添加为地图样式,在添加预设组合标签下,添加lanelet2_maps/josm/目录下的laneletpresets.xml文件:
在JOSM中,选择文件->打开,选择项目中map/map_loader/data/目录下的lanelet2_map.osm文件,得到如下地图:
你可在JOSM中查看和编辑地图中的各个元素。
在ROS中使用lanelet2地图完成routing
在你的ros workspace中,运行本项目:
cd your_ros_workspacesource devel/setup.bashroslaunch src/ad_with_lanelet2/run_map_simulator.launch123
如图,map被加载与Rviz中:
run_map_simulator.launch内容如下,一共会启动4个ros node:
planning仿真节点:来自Autoware的简单planning仿真map loader:加载Autoware扩展版lanelet2地图,发送用于可视化的Rviz marker,以ros msg的形式发送mapmission planning模块:来自Autoware的任务规划模块,在本例中主要使用了Routing路线生成Rviz:启动Rviz并使用预先设置的配置参数
<launch><include file="$(find simple_planning_simulator)/launch/simple_planning_simulator.launch"/><include file="$(find map_loader)/launch/lanelet2_map_loader.launch"/><include file="$(find mission_planner)/launch/mission_planning.launch" /><!--- Run Rviz--><node pkg="rviz" type="rviz" name="rviz" args="-d $(find map_loader)/loader.rviz" /></launch>1234567
点击Rviz中的2D Pose Estimate在图中设置当前位置,设置完成后如下图所示:
仿真节点根据这个init pose发一个base_link 到world坐标系的tf,接着使用Rviz中的2D Nav Goal设置routing的终点,具体见如下动图:
如图中所示,mission planner会根据设置的目标位姿动态生成routing路线(图中深色路线):
注:该样例地图为Tier 4公司(Autoware的主要维护者)开源的地图,在日本,所以是靠左行驶,routing的时候需要按照靠左行驶的规则设定起终点。
构建自己的Lanelet2高精度地图
总的来说,Lanelet2是一套完全开源的、较为完整的、专为自动驾驶设计的高精度地图架构和方案,并且构建在OSM的基础上,拥有较为丰富的开源工具支持。你可能已经迫不及待的在自己的自动驾驶项目中应用该高精度地图框架,那么如何构建你自己的lanelet2高精度地图呢?实际上,完整的高精度地图建图是一套复杂的产品化流程,存在较高的技术壁垒和法规风险,在中国,要构建公共道路高精度地图需要获得国家自然资源部的相关测绘资质,否则会被认定为非法测绘行为,所以在中国,需要分以下几种情况讨论:
如果你是获得资质的传统图商/自动驾驶公司:支持Lanelet2格式的高精度地图是发展的趋势,其开源性保证了该产品在市场上的通用性,Autoware对lanelet2的支持会让国内对lanelet2格式的地图需求增加;如果你是无资质的自动驾驶公司/高校研究者:选择有资质的高精度地图公司的lanelet2产品将是最高效、省钱的解决方案;
目前国内能够完美支持lanelet2(Autoware扩展版)且具备相关测绘资质的高精度地图公司主要为高深智图(Deepmap),其官方网址见参考链接。
参考
lanelet2论文:https://www.mrt.kit.edu/z/publ/download/2018/Poggenhans2018Lanelet2.pdflanelet2原项目地址:https://github.com/fzi-forschungszentrum-informatik/Lanelet2本文项目仓库:https://github.com/AbangLZU/ad_with_lanelet2Autoware: https://www.autoware.ai/JOSM:https://josm.openstreetmap.de/高深智图:https://www.deepmap.ai/
作者:AdamShan
奔驰高级自动驾驶扫地僧,谷歌认证机器学习专家,兰州大学无人驾驶团队创始人,主攻深度学习,无人驾驶汽车方向,著有《无人驾驶原理与实践》一书。
页:
[1]