Unite 2019|基于Unity的自动驾驶模拟(下)
在基于Unity的自动驾驶模拟(上)中,百度美国研发中心的荣国栋博士介绍百度的自动驾驶平台阿波罗,以及为什么使用Unity开发阿波罗的仿真。
本文将重点分享如何在Unity中重构自动驾驶的虚拟世界。
演讲内容
现在来讲一下我们如何在Unity中重构虚拟世界。
我们使用了Unity推荐的摄影制图法工作流程,就是通过拍摄真实世界的图像,然后通过图像重构真实世界。
我们先通过高精度的数码相机拍摄大量的图像,然后使用的是Reality Capture,从图像重构出三维模型。
三维模型是很复杂的,所以我们使用Maya或Instant Mesh来对模型进行简化,然后使用xNormal、Substance Designer等软件将这些模型的纹理贴到模型上。我们使用Unity或Substance Painter来对模型进行进一步的清理,最终在Unity中使用。
下面是一个简单的例子。我们先拍摄一个树干的模型,保证不同的图片之间有足够的重叠,这样软件可以找到相同的特征点,将图片进行对齐,生成点云。点云进一步三角化,生成网格,同时生成模型。
但这样生成的网格是非常复杂的,很可能是几十万到上百万三角片,我们没法直接拿来使用。所以我们要重构它的拓扑结构,把它大大简化。但同时我们通过Normal Map方式保留尽可能多的细节。
例如,下图的树干是一个复杂的模型,简化过的模型,我们可以看到只有很少的三角面片,但是通过Normal Map的情况,我们还是保留了足够多的细节。
通过这种方式建立的三维场景,然后再结合Unity高精度的渲染,这样渲染出的场景是跟真实相机拍摄的相差无几。
我们可以看到下图实际是百度美国研发中心门前的一条路,左侧是我们渲染的场景,右边则是用真实相机拍摄的,效果非常逼真。
通过摄影制图法,我们可以高精度地重构现实中的三维世界。但是这个还不够,因为我们不可能重构所有的内容,我们还需要参考一些文档来建一些现实中的路况标志物和红绿灯这类东西。
因为我们拍照片的时候,有可能是白天、晴天,但是我们还需要模拟阴天、夜晚的情况,所以我们还需要采集各种光照条件。我们还需要用HDR高动态图形渲染方式来达到更逼真的渲染效果。
下面是一个例子,例如我们要创建一个很简单的Stop Sign,就是停的标志。我们就去查阅相关规定的文档,了解它应该要多大,应该有多少度的角度,根据这些要求来建模。
当然现实生活中,它不仅仅是一个Stop Sign,有可能还有红绿灯,还有车道线,还有各种各样的文档。我们从车管局,建筑部门等所有公开的地方查阅。
我们的美术查阅了大量的文档,根据这些文档重构现实生活中的各种场景。
这些场景渲染出来之后,我们可以看到下图的效果是比较逼真的。但是总是有一些假的感觉,像是计算机生成的图像,而不是照片上的图像。所以我们需要使用高动态范围的Tone Mapping,这样我们可以保留更大的光谱动态范围。
下图是HDR渲染的效果。大家可以比较一下二幅图的效果,上面的图看起来比较CG,像计算机生成的图像,下面的图看起来更像是用真实相机拍摄的图像。
Unity提供了一个HDRP高清晰渲染管线,但是我们目前还没有能够使用它,原因是因为我们使用了Asset Store资源商店中一些不兼容HDRP的第三方软件,当这些软件跟HDRP兼容时,我们也会进行更新为HDRP。
我们主要使用的第三方软件是:
Enviro,它可以帮我们动态地模拟各种天气,雨雪、雾等天气,还有不同的时间,白天黑夜的转换。
Gaia和CTS,它们可以帮我们动态高效地建立更多的地形。
EasyRoads3D,它可以帮我们在地形上动态地加载各种建筑物、植物等环境元素。
Unity也发布了SimViz,它是专为自动驾驶而使用的工具包,我们重用了SimViz中的场景来进行一些单元测试,这可以让我们很快地在一天之内做一些小的单元测试。
下图左侧是一个十字路口,右侧是一个三车道的直路,这些场景都是来自SimViz工具包。
当然提到场景,自动驾驶毕竟跟游戏不一样,游戏三维场景可能就是前面提到的内容,但自动驾驶还有一项更重要:路网的构造。
EasyRoads3D的初衷就是为游戏的路网而开发。它创建的路网还不够复杂,因为我们需要从路网导出高精地图,给我们的自动驾驶软件来使用。
我们不仅需要知道每一条路,而且需要知道每条路里的各个车道线和这些车道线的连接关系、红绿灯、各种交通标志的位置,所以我们需要更加高效的路网创建软件。
我们可能第一个想法是:在现实中,市政施工人员是用什么软件来设计的。
下图中的软件是建设真正道路的人使用的三维软件。
但是我们衡量之后发现,这些软件并不是为游戏或三维渲染引擎而设计的,所以它们有大量功能是我们用不到的。当然还有一些公司使用Houdini来制作。
我们目前使用的是RoadRunner,它由VectorZero来开发的。这个软件的功能非常强大,它可以很轻易地编辑各种复杂的路网。
RoadRunner有一个很重要的功能是:它可以导出OpenDRIVE的地图格式,OpenDRIVE是现在比较通用的高精地图格式。我们可以使用脚本把OpenDRIVE地图格式转化成百度阿波罗的高精地图格式。
下面是我们使用RoadRunner设计的复杂路口的示意图。我们可以看到,这种路口如果用普通三维软件做会耗费大量的时间。
我们不仅需要每个路有不同车道,还需要这些车道的连接关系。哪个车道能转向哪个车道,哪个车道不能转向哪个车道,这些连接关系RoadRunner都可以帮我们生成,这对自动驾驶模拟是非常重要的。
还有下图这样复杂的转盘路和多层的立交桥,RoadRunner都可以支持。
即使有上述这些所有的工具帮忙,生成这些三维环境的时候还有一个问题:工作量和数据量。
我们生成一平方公里的区域可能还是可以的,但是我们不可能生成一个几百平方公里,甚至几千平方公里的大城市。所以我们从真实世界开始,但是对真实世界做了简化,因为很多时候不需要生成整个真实世界的路网。
例如,一条高速公路可能有10公里都是很简单的路况,但是到了一些上下闸道,到了一些路口,这些路口是比较复杂的。那么我们只需要把复杂的路口挑选出来,中间简单的路网我们可以大大缩短,用很短的路把这些复杂路口联系起来。
下图是一个实际的例子,下图显示在硅谷山景城,我们自动驾驶汽车实际行驶的路线,这个路线全长是20英里。
我们挑出了一些比较有代表性的路口,并对这些路口进行建模,然后用较短的路把这些路口连起来。
最后我们把它简化为4英里的路,这个4英里的路就可以模拟刚才20英里路几乎所有的信息。
下图是在硅谷圣马刁县市中心的一块区域,我们的自动驾驶车在这里进行测试。
我们把这个区域分割成:市中心的区域、住宅区、还有一些过渡区,然后对每个区域建立一个简化模型。
这些模型跟真实的区域并不完全一致,但是它包含了真实区域所有有代表性的路口,停车场之类的结构,类似我们建立的简化住宅区。
下图我们建的简化市中心区域,我们将这些区域连接起来,就可以组成小型的圣马刁的模型。
这是我们提到的第一个挑战:如何重构三维的场景。第二个挑战就是如何模拟不同传感器所输出的数据。
我们现在所模拟的是相机传感器,我们想使用Unity很自然地渲染三维场景,得到图片,但其实不仅仅是这么简单。
真实的相机并不会像Unity渲染出的图片那样完美,真实的相机会有变形,会有畸变。真实相机捕捉高精度光的范围要大大高于渲染出来的场景。真实相机还有不同的Tone Mapping曲线,在低光照的情况下,真实相机会有很多的噪点,这些内容都需要我们进行进一步模拟。
下面是我们模拟的一辆车,车上有10个摄像机,它在三车道直路上行驶的情况。
这辆车有三个前向摄像机,左前、右前、左后、右后,四个侧面摄像机,一个后向摄像机,还有二个鱼眼摄像机。我们可以同时模拟十个摄像机看到不同的位置。
使用Unity直接渲染出来的图像是没有畸变的,但是摄像机是有畸变的。所以我们要加上摄像机的畸变模拟。
摄像机的畸变包括:径向畸变和切向畸变。由于切向畸变一般很小,我们只模拟了径向畸变。
径向畸变包括桶形畸变和枕形畸变,我们有二种畸变的模拟方式:
后向方式:我们对输出图像的每一个像素,可以用反向畸变的公式去进行计算,得到它在没有畸变的图像的位置,然后从那里读取它的RGB。
因为Unity渲染出来的是没有畸变的图像,所以我们可以从对应位置读取RGB,这样可以得到畸变图像中每个像素的颜色值。
前向方式:我们可以把没有畸变的图像用一个稀疏网格来代表,例如:20x20的网格。然后把每个网格的顶点使用畸变公式,计算它畸变后的位置。最后对网格进行变形,把原始没有畸变的图像作为纹理贴在网格上。
实际应用中,我们使用的是一个Shader程序来实现后向畸变方式。
需要注意:桶形畸变会把图像缩小一点。如果我们要输出1920x1080的图片,我们实际渲染时要渲染大一点的纹理,这样桶形畸变缩小后,它会变成1920x1080的分辨率。
下图是桶形畸变不同参数的效果示意图。我们可以调整畸变的不同参数,模拟不同相机的畸变效果。
因为我们重建了三维场景,所以我们拥有所有的真值。我们可以将感知模块识别出来的感知结果读取过来,跟我们的真值进行比较,进行一个实时评估。
例如:对于障碍物,一般返回的是包围盒。我们可以将这个包围盒跟我们真值的包围盒做一个求交,看看二者有多大的公共部分,当然这个公共部分越大越好。
对于车道线,我们可以对车道线进行水平采样,看这些采样点附近有没有真实的车道线。如果在足够近的距离有真实车道线,我们就认为它是一个对的检测结果,否则就是一个错的检测结果。
所以我们可以实时对感知结果进行评估。
我们还可以将感知结果进行实时的可视化。但可视化有一点比较难处理,当我们把图像发给感知模块,感知模块进行感知计算之后再返回我们,这时已经过了一段时间了。
如果这个结果直接显示在屏幕上,它跟屏幕上的车、人、障碍物是对不上的,所以我们需要用一个Cache队列存储一定时间的障碍物的信息。当我们拿到感知模块结果之后,通过时间戳找到对应的一帧,拿到对应那一帧的真值,然后把我们的真值和感知结果跟当前时间做一个变换。
例如,车前进了一段距离,我们就把这个真值和感知结果都往前推一段距离,这样显示的图像和我们真实的车是可以完全对起来的。
下面视频显示了我们实时对感知模块结果进行评估,这些曲线图显示它评估的结果,还有这些框图和下面的车道线,下面曲线显示的是障碍物和车道线真值检测结果的可视化。
左边是我们白天的测试,右边是夜间环境测试。比较有意思的是,我们发现夜间环境的测试结果会更好,原因可能是因为夜间环境有路灯,车子可以看得更加清楚,而白天时候,车会跟周围环境融合得更加好一些。
下一步计划
目前我们实现了感知模块的相机传感器的仿真,对感知模块的感知结果进行实时评估和可视化。下一步我们为感知模块输出大量有标注的数据,帮助感知模块去训练感知算法,提高它的感知结果。
我们还会增加对更多传感器的支持,现在大量自动驾驶厂商都使用了Lidar激光雷达,还有Radar雷达和超声波,这些我们都会支持,支持更多的传感器。
我们目前还是Open loop开环式,车都是通过脚本来控制。我们将来也会提供闭环式,通过自动驾驶软件的反馈来控制我们的主车运动。
我们现在交通流的模拟还是比较简单地用脚本来模拟交通流,我们跟百度研究院合作,采用数据驱动方式来模拟更加真实的交通流。
最后我们还会提供更加用户友好的工具,让用户更容易地定制传感器的位置、各种场景、车流运动、白天黑夜、天气等各种因素。
我们目前的感知软件是在百度供阿波罗内部使用的,将来希望把它作为云服务开放给第三方的开发者来使用。
我们也会把带有标注的数据作为大型数据集开放出来,我们还希望让用户可以定制自己的数据集,用我们的感知系统给用户生成可定制的带标注数据。
总之,自动驾驶的仿真还是我们刚刚开始的工作,结合Unity强大的游戏引擎,我们可以很快做出一些原型工作。
例如,我们现在用相机、传感器对感知模块进行仿真,接下来我们还会有更多工作可以做,有更多的挑战可以由Unity开发者,就像在座各位一样,帮助我们实现更多的功能。
如果你对我们的这些感知工作有更多问题的话,可以到阿波罗网站了解更多关于游戏引擎开发自动驾驶仿真的工作,谢谢大家。
小结
我们感谢百度美国研发中心的荣国栋博士带来的精彩分享。更多Unite大会精彩内容分享,尽在Unity Connect平台(Connect.unity.com)。
下载Unity Connect APP,请点击此处。 观看部分Unity官方视频,请关注B站帐户:Unity官方。
推荐阅读
官方活动
8月2-4日,Unity将参展ChinaJoy 2019,展位及周边活动精彩纷呈,线上线下同步开启。了解Unity at ChinaJoy精彩活动内容,请点击此处。
展位地点:上海新国际博览中心 W4馆B601号
开展时间:8月2-4日 (星期五-星期天)
8月21日前加入Unity Connect,创建个人频道,成为与Unity社区同行的伙伴-Unity Buddy,享受专属福利。
了解如何成为Unity Buddy,请点击此处。
Unity Connect评论区支持你认可的Buddy,获得免费门票。
喜欢本文,请点“在看”