5

OpenDrive解析小结

 2 years ago
source link: https://cniter.github.io/posts/b7d79231.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

OpenDrive解析小结 - Shaun's Space

  接触并使用高精地图和 OpenDRIVE 已有一年的时间,简要写写 Shaun 对 OpenDRIVE 的一些认知。

OpenDRIVE 目前最新的版本的 1.6,下面主要结合 1.4,1.5 和1.6 版本一起看。

  在 OpenDRIVE 中主要有两种坐标系统,一种是常见的 X/Y/Z 空间坐标系统,另一种是 S/T/H 坐标系统。其中 X/Y/Z 坐标系统常与地理信息的各种坐标系统一起使用,S/T/H 坐标系统是针对 OpenDRIVE 中道路参考线设定的一种局部坐标系统,在 OpenDRIVE 中称前者为 “inertial co-ordinates”,后者为 “track co-ordinates”(1.6 中直接为 Reference Line System)。除此之外,还有个局部坐标系 U/V/Z,该坐标系统系统是相对于 S/T/H 坐标系统平移旋转而来的。

对于旋转,以逆时针为正,heading 是指绕 z/h 轴旋转,pitch 是指绕 y/t 轴旋转,roll 是指绕 x/s 轴旋转。

对于曲率,逆时针延申的曲线曲率为正,顺时针延申的曲线曲率为负。

在 OpenDRIVE 中对于道路和车道的描述,有以下几个重要的概念:

  • Reference Line。用来指示一条道路的骨架,是 S/T/H 坐标系统的依据,道路中各车道线需要参考这条线。
  • Lanes。用来描述各车道以及各车道所属 Lane Section。
  • Lane Offset。其意义在 OpenDRIVE 标准看起来很清除,但实际用起来非常模糊,offset 到底是只能偏移一个车道,或半个车道或多个车道,所属哪个 Lane Section,其意义不明,故下文解析篇将直接忽略该属性。
  • Lane Section。可以简单理解为子道路,一个 lane section 中包含多条车道,一条道路包含多个 lane section。一个 lane section 中车道数是一个常数,所以对于存在 m 变 n 车道的一条道路,至少要划分为两个 lane section。
  • Superelevation、Crossfall 和 Shape。用来表示路面倾斜程度。Superelevation 是整个路面侧向太高,即路面倾斜程度,Crossfall 在 1.6 中已被废弃,原因为 1.6 完善了 Shape,可以完全取代 CrossFall,甚至能做的更好,Shape 主要用来描述路面两侧车道的倾斜程度,通过三次曲线和线性插值可以精确到车道各点倾斜程度。
  • Road Linkage。道路之间的连接关系,通过前继(predecessor)和后继(successor)建立道路之间连接关系,若一条路存在多个前继或后继,则其对应前继或后继应该为 Junction ,即目前的标准中暂不支持道路多前后继,1.5 中只支持车道多前后继,道路多前后继依然不支持。
  • Junction。交汇处,通俗意义上的路口,主要包含 incomingRoad 和 connectingRoad。
  • Junction Group。可以简单理解为交通环岛。
  • Neighbors。相邻关系,和 Road Linkage 类似,一个是前后连接关系,一个侧面相邻关系。
  • Surface。车道或道路表面材质,有 OpenCRG 则优先使用,没有则由应用程序自定义字符串。
  • ....... 等等。还有一些冷门的元素暂时没用到,就不介绍了。

下面就是真正的解析内容了。

  一些简单的就不介绍了,就介绍解析时需要注意的一些重点元素。

Road Geometry

  geometry 信息可以说是 OpenDRIVE 中最重要的信息,没有之一。OpenDRIVE 中最重要的元素为 Road,而 Road 中最重要的是 Reference Line,而 geometry 正是用来描述 Reference Line 几何线条形状的信息。

  首先 geometry 标签中共有 5 个属性,分别为 s (该段 geometry 沿参考线起始位置),x(该段 geometry 在 inertial system 下起始横坐标),y(该段 geometry 在 inertial system 下起始纵坐标),hdg(该段 geometry 在 inertial system 下起始弧度),length(该段 geometry 长度)。其次,geometry 共有 5 种线型,分别为 straight lines(直线),spirals(螺线),arcs(圆弧线),cubic polynomials(三次曲线),parametric cubic polynomials(参数化三次曲线),这 5 种线型分别由 geometry 下 5 种标签控制。解析 geometry 的要点在于:先不用管 geometry 标签中的属性,直接解析对应线型标签,需要满足两点:1、起始点坐标一定为 (0, 0);2、起始点斜率,即导数也一定为 0。依据这两点正确解析完线型之后,再根据 hdg 旋转线型,根据 (x, y) 将线型平移到正确位置。 下面就具体看看这 5 种线型:

  1. line,直线。没有任何属性,直接根据 geometry 中 (x, y) 和 hdg 就可得到直线方程。
  2. spiral,螺线。有两个属性 curvStart(起始曲率),curvEnd(结束曲率)。螺线解析的代码已经由 OpenDRIVE 官方直接给出了,里面涉及到的数值计算方法就不详解了,直接看官方提供 API 的输入输出,输入有两个:s(从原点开始,螺线延展的长度),cDot(螺线的曲率关于 s 的一阶导数);输出有 3 个:x(横坐标),y(纵坐标),t(该点的切线弧度)。解析螺线最大的问题应该就是如何得到这两个输入参数,由螺线的性质可以得到,螺线的曲率一定随着螺线的长度均匀变化的,换句话说,对于一条已知螺线,cDot 一定是常数。则 cDot=(curvEnd−curvStart)/lengthcDot=(curvEnd−curvStart)/length,其中 length 为 geometry 中的长度属性,下一步需要求出 s,由于已知螺线在原点处的曲率一定为 0,则 (curv - 0) / (s - 0) = cDot,即 s = curv / cDot。由此可得到螺线的各点坐标和切向方向,但由于解析线型需要满足上面说的两点,所以需要将螺线坐标以起始点进行平移和旋转,以满足起始点为原点,起始点切线弧度为 0,最后再将完成平移和旋转后的点根据 geometry 的属性进行旋转和平移以得到真正的坐标点。
  3. arc,圆弧线。只有一个属性 curvature(曲率),可根据曲率直接得到圆的半径,在根据曲率的正负可得到该曲线是以顺时针延申还是逆时针延申,再根据解析线型需要满足的两点和 geometry 的属性可得到真正的 inertial system 中的点。
  4. poly3,三次曲线,在 1.6 中已被废弃。精度要求低一点可直接插值计算,要求高一点则需要利用 length ,数值计算和二分法直接求出最大的 u,然后插值。
  5. paramPoly3,参数化三次曲线。最有名的两个参数化三次曲线就是 Bezier 曲线和 Hermite 曲线,为满足解析线型需要满足的两点,一定有 au=0,av=0,bv=0au=0,av=0,bv=0,需要注意的是一般参数化曲线的参数取值范围为 [0,1][0,1],即该标签最后一个属性 pRange="normalized",若碰到特殊情况 pRange="arcLength",则需要将 au,bu,…au,bu,… 等属性转化为参数取值范围为 [0,1][0,1] 时对应的属性。

最重要的元素 Geometry 的解析就是这样了,下面谈谈 Shaun 对基于三次曲线的一些元素的理解。


  比较重要的基于三次曲线的元素主要有 elevation(控制路面的高度),superelevation(道路侧面抬高弧度),crossfall(路面两侧弧度,已被废弃),shape(路面两侧形状,特殊,下文详细介绍),laneOffset(车道偏移量),border 和 width(特殊,下文详细介绍),这些元素所使用的三次曲线一般都基于道路参考线(特殊除外),即该三次曲线的横坐标一般为 s,纵坐标即三次曲线的值则为各元素的信息,这些三次曲线一般是分段描述的,即道路参考线上两个关键点的 s 之间必会生成对应的一段三次曲线,每一段三次曲线的横坐标取值范围都为 [0,poly3Length][0,poly3Length],其中 ploy3Length 为该段三次曲线的长度。这些三次曲线段全部合起来则构成沿道路参考线的一条三次曲线,根据 s 计算三次曲线的取值得到对应的信息。

LaneOffset

  laneOffset 用来指示的是所有车道沿参考线法线方向的偏移量,所有车道包括中心车道(centerLane),由于中心车道没有宽度,所以也可以叫道路中心线,这和道路参考线是两个概念,若 laneOffset 都为 0,则道路中心线和道路参考线重合。

Shape

  路面两侧车道的高度,该元素虽然也是使用三次曲线进行描述的,但是该三次曲线的横坐标为 S/T/H 坐标中的 t,不是 s,不同的 t 得到不同的高度,该元素下可能存在多段三次曲线,这些三次曲线段是独立的,只是描述其属性 s 所在位置横截面的 shape,而没有完全指定 s 的横截面的 shape,则由两临近 s 的 三次曲线计算相同的 t 对应的高度然后线型插值得到(1.6 标准中插值的公式 Shaun 觉得有问题)。

border 和 width

  之所以把这个两个元素放在一起写,是因为这两个元素描述的本质上是一个东西,都是车道边界所在的位置。同时,Shaun 还是想吐槽一下,作为一个既定的标准,完全不应该把这两个元素同时放出来,只需要放出一个即可,既然为标准就应该做到完全统一,至于具体用哪个是应用程序的事,但是出来的东西必须得唯一。border 是指车道边界到道路中心线在道路参考线法线上的投影,有正负之分,一般左边车道为正,右边车道为负,而 width 是指车道的宽度,这两者完全可以相互转换。虽然描述这两者的三次曲线是基于道路参考线 s 的,但是这个 s 是相对于 laneSection 标签中 s 属性的,即其真正沿道路参考线的 s' 应该为 s' = s + laneSection.s。


  至于Junction 的解析好像没什么需要注意的,就不写了,至于 1.5 中的 Virtual Junction,引入新的道路前后继描述方式,也新加了一个 virtual connection,解析时到也没有需要注意的,唯一需要注意是在应用程序中该如何利用这些信息。


  对于 Signal 和 Object,Shaun 觉得标准中强制规定 s > 0 同样是一件非常不合理的事情,既然能超出道路长度,只准正向超出,不能反向超出,这有点不讲道理。 Signal 和 Object 同样需要注意在应用程序中的用法,至于解析方面,需要注意的应该就是 Object 中 outline 下面的 cornerRoad 和 cornerLocal。

cornerRoad 和 cornerLocal

  这两个元素描述的本质上也是一个东西,都是面域对象多边形边界上的轮廓点,虽然 1.5 中引入了复杂多边形的概念,即有内轮廓和外轮廓,但 cornerRoad 和 cornerLocal 还是一样的解析。cornerRoad 是直接相对于道路参考线的坐标,即将 X/Y/Z 坐标直接转换为 S/T/H 坐标得到的,所以直接解析转换就可得到该点的真正坐标。而 cornerLocal 的解析则相对要麻烦些,首先根据 object 标签中 s 和 t 属性计算得到 Object 的位置,以道路参考线上 s 所在的位置建立 S/T/H 坐标系统,将该坐标系统平移到 Object 所在位置,即该 S/T/H 系统以Object 的位置为原点,将 cornerLocal 上 u,v,z 属性带入该坐标系统计算出真正的坐标。由于 Object 中的 roll,pitch,hdg 属性,所以还需要对坐标以 Object 的位置为中心进行相应旋转才能得到真正 X/Y/Z 坐标系统中坐标。


好了,以上就是 Shaun 觉得在解析 OpenDRIVE 时需要注意的一些地方了。

  整个地图行业本来就存在很强的壁垒,国内更是如此,而高精地图作为专为自动驾驶服务的地图,国内估计更是少有人接触过。

  OpenDRIVE 虽作为一种高精地图标准,但离那种被广泛认可关注的标准还有很长一段距离,虽然它发展了十几年,但奈何整个行业才算是起步阶段,所以之前其一直发展的十分缓慢,之前用 OpenDRIVE 较多的应该是交通仿真领域,这个领域同样存在很强的壁垒,要在这种领域得到整个行业的认可是一件非常困难的事,因为其本来就存在一套自己的格式,而想要应用别人的标准,就势必需要逐渐抛弃自己的格式,这对企业来说需要下很大的决心。

  就 Shaun 目前所知,行业内虽然有许多企业使用 OpenDRIVE 标准,但基本都是自己魔改后的标准,原因在于 OpenDRIVE 标准还没做到真正成为标准的地步,虽然其一些基本元素具备,但很有很多元素是完全缺失或不完善的,更重要的是,其可视化程序竟然不开源,在整个计算机领域内,还从没见过一种标准没有其开源实现的东西,没有相应的源码,只靠文字来理解难免会产生歧义,各大厂商自然就会选择实现自己的 OpenDRIVE,很难统一。历史上一些经典的论文和算法,都有其相应的开源实现,没有开源实现的论文和算法基本都淹没在了历史长河之中。所以没有开源实现,在计算机领域内很难真正推广开,就很难成为真正的标准。综上,OpenDRIVE 的发展任重而道远啊!希望现在在 ASAM 手中能发展的更快更完善些吧。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK