在自动驾驶汽车开发中利用机器人数据-卡尔·奎因,Zoox
Zoox的工程师们正在制造自动驾驶汽车,以解决世界上的交通问题。他们的车辆是机器人,可以捕获并生成大量数据。他们收集数据、摄取数据、对数据进行编目,并将其提供给公司的其他部门用于许多用途,例如性能分析、事件分类、机器学习和数据挖掘。在这个视频中,Zoox描述了机器人数据与典型的服务器日志数据的不同之处,以及他们如何管理它,将其转化为有利于Zoox开发和运营团队的平台。
视频记录
好吧,我要开始了。今天的演讲是关于在自动驾驶汽车开发中利用机器人数据。
我在一家名为Zoox的初创公司工作。我们正在制造自动驾驶汽车,今天我要讲一下我们如何利用收集到的数据来改进我们的开发过程,并为我们的工作提供信息。
所以,自动驾驶汽车就是机器人,Zoox正在建造,我不知道你们是否知道我们的使命,但是,Zoox,我们的使命是为世界提供机动性,为密集的城市环境,我们的目标是建立一个完整的堆栈,一个完整的解决方案。所以,我们正在制造车辆,我们正在开发人工智能软件,它将驱动车辆,我们将拥有我们所建立的车队,我们将像出租车服务一样运营车队,机器人出租车,等等。
这给了我们一些优势,一些很大的优势,我们认为这是很重要的,与其他一些公司相比,这些公司实际上只是把机器人技术加到现有的汽车上,因为这些汽车是由人类驾驶的,如果你把机器人扔进去,试图驾驶它,有很多事情都不太好。
我们认为,如果你从头开始造一辆车,那么我们就能做得更好。所以,在我们的开发过程中,我们同时致力于两个分支,或者说开发工作的两个主要方面。
其中之一是,我们正在建造飞行器,我们有一些原型。事实上,今天早上视频里的一些车是我们的车在阿拉米达赛道上开的。它们看起来像沙丘车。所以,这些是我们的原型车的实际物理设计。但是,我们所做的大部分工作,最难的部分是开发用于实际驾驶的人工智能软件。
我们用的是所谓的三级车辆。所以,我不知道你们是否熟悉DOT的自动驾驶级别,但一,二,三是人类在驾驶汽车时参与的级别。
所以,第三级是一辆基本上是自动驾驶的汽车,但人类在做后备。所以,这就是我们这里的,这也是大多数其他自动驾驶汽车公司在他们的驾驶模型和训练模型中使用的。所以,有一个训练有素的司机坐在驾驶座上,还有一个软件操作员。在我们的情况下,我们总是有第二个软件操作员坐在乘客座位上做笔记并注意某些事情。
然后,在某个时候,当我们的5级车辆完成,我们的软件完成,然后我们会把它们放在一起,在不久的将来在公共道路上行驶。
所以,机器人就像青蛙或其他动物一样。如果你这样想的话,它们有传感器或感官,还有摄像头,激光雷达,雷达,飞行时间,声纳。一些制造自动驾驶汽车的自动驾驶汽车公司把一切都押在了摄像头上,理论上,人类可以看到,我们可以驾驶,所以,因此,如果一辆汽车能看到,它就应该能够驾驶。
但是,我们大脑的计算能力与我们的gpu堆栈相比有很大的不同。因此,为了规避这些限制,引入多种模式的激光雷达,雷达,飞行时间,声纳,其他近距离传感器,我们可以得到很多交叉参考信息,以及很多关于环境的可靠输入,这些通常只使用摄像头是无法获得的。
然后,计算。所以,机器人有计算能力,我们使用CPU和GPU。很多工作,特别是视觉和感知处理可以在GPU上完成。这对于机器学习和类似的处理来说更有效。
然后,每当决定要做什么时,这些信号就会返回去控制马达,执行器,速度控制,以及各种各样的硬件。
所以,现在的每辆车上面都有公交车,对吧?CAN总线,LIN总线,在你的汽车上有很多不同类型的普通互连,它们在传感器和小执行器,控制器之间发送信号,用于汽车的所有不同部分。所以,我们的车,我们的车辆,是相似的。
所以,我们有很多标准的汽车公交车,我们在低水平上处理物理控制的事情。但是,我们也有一些更高级别的总线,因为你不会在CAN总线上运行激光雷达数据流和摄像头数据流。因此,我们也有以太网总线和其他类型的路由和交换,更像是一个完整的计算机。就像塞在那辆车里的一个小数据中心。
所以,它把所有的信息都输入到中央计算机,或者我们称之为PCU,它是汽车的大脑。在主脑中有专门的过程。这是一个有趣的建筑。当我加入的时候,我发现它很吸引人,因为在这台多核多处理器的机器上,有一个高速的消息总线在运行。
但是,消息总线允许不同的进程或组件、软件组件发布和订阅。所以,pub/sub,但是速度非常快,消息在总线上传递,它们有预定的接收者,他们可以读回这些消息。
它们各自完成自己的部分处理图像,进行检测,进行分类,实时建立世界的3D模型,并在车辆移动时维护该模型。定位,各种决策,规划机器人的行为。
所以,我们有很多数据,我们应该怎么做呢?让我们来捕捉一下。现在,在传统的服务器环境中,你通常会做日志收集,所以你会让你的服务器写,可能只是标准输出,它只是转储,你试图写过滤脚本或模式匹配,试图提取有趣的日志,并将它们路由到日志堆栈中。
也许你的服务器更好,你的系统更好,他们在写JSON,这很好,因为它更容易解析,你知道你有什么,但通常,它有点模糊,你试图从原始文本流中提取精华,逐行提取。
但是,我们所拥有的有点不同,因为在我们的系统中通过总线传递的实际上是不同类型的结构化消息。它们中的大多数是协议缓冲区。我不知道你们是否熟悉Google protobufs。
其中一些是来自我们使用的旧的基于ROS的开源平台的ROS消息。而且,我们还使用DDS消息,这是OMG DDS的标准。因此,这些不同类型的系统使用不同的消息,这取决于它们来自哪里以及它们被用于什么。
所以,在很多情况下,这些已经非常紧凑和简洁的信息,已经是自包含和可解析的,我们可以把它们以某种格式写入磁盘,我们已经知道如何处理它们了。我们不需要解析它们。我们只是在录音。所以,在这一点上,我们的录音更像是飞机上的飞行记录器。
所以,我们必须控制何时录制。我们并不想在汽车行驶时一直记录。所以,我们有,作为软件操作员工作流程的一部分,进入那里执行任务和做驱动器的团队,他们将控制在开始录制时要为驱动器启动哪些软件组件的设置。
然后,在录音过程中,操作员会做笔记,可能会发出信号,表明出了什么问题,并写下一些关于它的记录。因此,所有这些信息都可以打包到消息中,并记录和保存。所以,他们也在控制录音。所以,当我们开始录音的时候,当我们结束录音的时候,这很重要。
让我在这里展示一个场景。所以,这是操作员在驾驶时看到的,没有驾驶员,只有软件操作员,你可以看到他们在打开不同的东西。所以,他们打开激光雷达,关闭激光雷达,规划信息。所以,所有这些都是可视化的,让他们看到车辆,规划者,人工智能组件中的所有组件实际上在做什么,在想什么。
所以,它是信息本身的可视化。操作员可以打开或关闭它们,因为他们不必总是看到所有的东西。他们通常不需要看到激光雷达,但他们主要是想看看车辆计划做什么,但我们记录了一切。所有通过总线的数据都会被记录不管他们用UI做了什么。
这些看起来真的很有趣。我不知道。
你可以看到,小旗子上有像c或[听不清00:09:54]这样的字母。那么,这些是场景中的其他代理我们给它们贴上其他汽车或行人的标签?它也显示了它们被感知的方式。所以视觉,激光雷达,雷达。通常我们会用两三个人来接他们。
但是,你可以看到,在我们看到只有一种模态的情况下,这是一个很好的情况,这是一件好事,我们有不止一种模态,我们正在寻找的东西。如果我们只是依靠相机,有很多东西我们无法捕捉到,而我们可以用其他方式看到。
那么,我们在收集什么呢?所以,所有的消息都在总线上传递。我们不会完全收集每条信息,因为其中一些信息非常大,但我们确实捕获了大部分信息。主要的是,当我们捕捉到有趣的决定和低带宽的感知信息时。所以,定位,3D模型预测规划,所有这些都是非常重要的信息。
它们不是特别大。我们捕捉到了所有这些。传感器输入。我们确实在空间和时间上减少了一些。对于相机数据,我们捕获静态图像,但我们也捕获视频流。但是,我们将其压缩为H265,因为它太大了,无法从16个摄像机录制原始视频。这是大量的数据。
但是,执行器控制,其他元数据,比如地图和路线。车辆去哪儿了?它用的是什么地图?操作员做了什么?什么模式,他们在哪里?他们有什么开关?所有这些我们都可以收集。
因此,我们有大量的数据在流动。我们正在从大巴上收集样本。理论上,你可以尝试通过LTE将其传输到后端。如果我们有那样的带宽,那就太酷了。但实际上,我们不这么做,所以我们把它写在本地磁盘上,我们会开车到处收集所有的数据,所以在运行中,当任务完成时,我们会把它带回我们的基站,并以某种方式上传。
那么,我们要怎么做呢?我们应该用什么格式来记录呢?在飞行器上,我们写入磁盘。我们最初使用,因为我们开始使用一些叫做ROS的开源框架,机器人操作系统。我们使用了一种称为包文件的本地格式,这是一种索引数据库文件,您可以向其写入消息,这非常方便。很多工具都能很好地处理它,但它倾向于把所有东西都写进一个文件,然后它就在里面了,索引是在事后建立的。
所以,当我们在写,写,写的时候,如果我们决定我们想要能够完成我们的使命和驾驶。在开了那么多车之后,你得到了将近1tb的数据。这些文件太大了,一旦我们试图将它们移植回后端,就会变得非常笨拙和不可用。
复制和处理这么大的文件确实是个问题。所以,我们改变了记录的方式,利用了信息的一些基本特性。消息都有类型。因此,protobufs具有类型,并且我们知道每条消息的信息类型。他们也发表了一些主题。
所以,就像一个典型的消息总线一样,有一个主题,它是消息流的标签。这些主题命名得很好,然后它们会有时间戳。所以,我们有一个非常精确的时钟。我们可以计时,我们知道消息什么时候被发布,什么时候被写入磁盘。我们可以用时间戳来组织它。
所以,我们发明了我们自己的模式,我们称之为CHUM。所以,它代表分块信息。这是个有趣的名字。有些人真的很讨厌它,但它很有趣,而且很流行。这个想法,我认为它就像一个条带录音机,如果你见过那些老式的学校,所有的笔都在摆动,在纸上写字。这是一样的。
因此,每个主题都写在自己的文件中,每分钟结束时我们关闭文件,刷新它,然后在下一个目录中启动下一个文件。在叶节点上有一个目录树,里面都是文件,目录都是基于时间的。然后,这些文件是这一分钟窗口的主题。
所以,你有一分钟的时间来写主题,然后,窗口关闭了。你先写,然后再写下一个。所以,一个话题在一分钟内的交集给了你一个大块。它运行得很好,因为我们可以连续写入,理论上,你可以在写入新数据的同时写入和上传一小时前的数据。我们在实践中并没有这样做,但是理论上,我们可以这样做因为这是连续的书写。
所以,我们确实发明了这个。所以,这是我们自己专有的东西,但是我们把它建立在开源的底层库之上,因为我们不想从头再来。所以,我们把它建立在sst之上,SS表,排序字符串表,这是一个低级的存储平台,谷歌的DB数据库建立在上面。
而且,它工作得很好,因为sst使用这种数据库作为仅追加模式写入系统。所以,你要写到最后,你要写到最后。然后,这些不可变的写入序列就会被封装在内存数据库中。
我们用同样的方法,把记录写成两个字段。以纳秒为单位的时间戳。这张唱片是什么时候写的?然后,消息本身是负载的其余部分,带有一些元数据来描述,这个消息是什么类型的?还有什么额外的小数据需要配合吗?消息的元数据可能来自总线,但不在消息中,但它是关于消息的。
比如出版时间和写作时间,还有一些其他的事情。而且,我们总是可以在需要的时候添加更多额外的数据,这些数据是在实际消息的带外的。
然后,我们需要把数据输入到系统中,输入到我们的系统中,所以数据在车上,我们想把它放到云端。在我们的例子中,云是AWS和on-prem,我们自己的数据中心,所以它是一个混合体,我们只是根据性能、成本和延迟对需要数据的系统有意义来移动东西。
最初,S3是一个非常棒的存储系统,我们喜欢它。所以,那是我们举办活动的主要场所。所以,我们喜欢做的是把驾驶过程中产生的跑步记录,上传到云端,对它们进行编目,并提取出一些元数据,了解发生了什么,跑步是什么时候,谁在跑步,骑的是什么车?然后建立这个小数据库,这个边带到CHUM存储本身。
但是,在收集这么多数据的过程中存在一些挑战。通常都很尖。我们的队伍白天开车到处转。有些日子真的很忙,我们经常开车。他们都倾向于在相同的时间回到基站,他们想要转身离开,所以,你会看到这些大的峰值,每个人都出现了。
我们想要获取数据,然后继续前进。其他日子就没那么忙了,这是一年前的事了。我们现在开车的次数比一年前多得多,但即便如此,还是有一个很大的高峰。因此,需要将数据从飞行器上取下来,并尽快将飞行器取出来。
所以,我们尝试了一些不同的东西。这些车辆的运行,基本上就像一个小型的计算服务器机架,里面有一堆固态硬盘,所以它们只是我们可以插入的常规状态的驱动器。这是我们的存储空间。它真的很好用。带宽写入,一个大的RAID ssd阵列真的很好。这是一个很简单的问题。
这也是一件有趣的事情。也许我们可以接上以太网,上传所有东西,理论上说,应该没问题。但是,在实践中,如果你有一堆车辆在等待,试图通过10g以太网上传1tb的数据,这开始需要一段时间,因为你永远不会得到100%的效率,而且上游会有一些东西减慢所有的速度。
所以,10g以太网最终成为了我们的备用方案。如果驱动器出了问题,或者他们不需要马上使用车辆,我们有时会使用10g。
但是,使用固态硬盘本身是很棒的。我们在基站设置了一些信息亭,它们只是非常简单的Linux盒子,驱动器托架,自动安装驱动器,查看上面的内容,上传它们,清理它们。所以,基本上是安全进入云端。所以,它只是一个愚蠢的机器,将数据发送到云端。它工作得很好,但也有一些地方可能会出错。
我想最有可能出问题的是那些驱动器进出那些驱动器托架的物理连接。他们真的不是为这个而生的。它们开始磨损,别针弯曲,它们不能一直固定。所以,人们给他插上电源,然后走开,什么也不会发生。或者,它们会被卸下来。它们可能没有被干净地卸载,它们被拖走了,然后,它们的一些引导信息被破坏了,它们看起来还好,但它们不起作用。
有很多事情正在发生。有很多操作符和runbook之类的东西需要发生人们知道,“好,我做了这个,我做了这个。”我们如何解决这些问题?另一个也一样,网络可能会瘫痪,现在我们就被卡住了,或者我们被同时上传的太多内容所阻塞,每个人都在等待。
这种情况通常发生在所有知道情况的人都在度假的时候,而我是负责的人,我负责传呼机,然后,“哦。这是怎么呢我必须弄清楚。”
所以,当然,这很好。所以,这种情况偶尔会发生。所以,我们试着寻找其他的解,对吧?你如何减轻一直插入这些SATA驱动器的问题?我们目前的解决方案运行得很好,USB 3.1驱动器。它们非常好,我们可以把所有需要的东西写到一个驱动器上而不是八个驱动器。它们很坚固,连接器不会像SATA引脚那样快磨损。
所以,这对我们上传光盘的可靠性来说真的是一个很大的福音,而不需要很多人为干预,对吧?事情就会顺利进行。如果需要的话,我们还有网络。
所以,一旦我们上传数据,我们的后台系统就会扫描CHUM并查看那里有什么,查看元数据,然后,将其分类并将其分解为运行,我们称之为运行。所以,每一个记录序列,当操作员进入并打开它时,我们记录数据,我们称之为运行。所以,从开始到结束,这是一个运行。它是有目的的。它有一个驱动程序,所以所有关于它的元数据。
因此,我们对所有这些进行编目,对于每一个,我们都可以提取一堆元数据。所以,我们看看所有与…相关的东西,让我试试我的小指针。哦。是的。好吧。看那个。
运行的元数据,它告诉你关于运行的一切,时间和运行的模式,车辆,运行的目的,以及它目前在工作流程中的位置。我们画一个小图来表示它在哪里,在哪里发生。这里离这里有五个街区。那是我们主要开车的地方。百老汇外,从那里往北走。
我们也会扫描,这个仍然运行得很好,会有意外发生。因此,一些消息将包含关于发生的事情的元数据信息,操作员做了一些笔记,只是随意的笔记,他们注意到一些应该让别人看的东西。
或者,像驾驶员不得不脱离方向盘这样的问题,因为车辆可能离边缘太远了,或者它不知道自己是否会对正在发生的事情做出正确的反应。
因此,这些被提取出来并编目,我们实际上把它们,我们称之为分流事件,它们被放入JIRA,这是对JIRA的滥用。我们对它进行了多次修改,但它确实运行得很好,因为它最终与开发人员的工作流程和软件的发布配合得很好,我们可以说,“好吧,哪些问题得到了解决?”并且,他们可以将这些问题组合在一起,并创建元问题,然后代表如何重现错误。
所以,我们有了所有这些数据,它们都被编目了,准备好了。我们要拿它怎么办?所以,我用几种不同的方式来思考数据,我重新思考如何称呼这些数据,但我认为我认为最有效的是,我们用两种方式处理数据。一种是面向消息的,我们只使用组件编写的数据,这些组件甚至可能是离线运行的相同组件。
如果我们想重现一个问题,我们实际上可以运行大部分的部分软件堆栈。也许我们在运行规划程序,我们给它输入来自实际驾驶的感知信息,规划程序认为它在开车,它在做决定。
因此,我们可以使用它进行回归测试,或者开发人员可以使用它在他们的机器上调试问题。所以,实际上很难在机器人中实时调试问题。但是,如果你可以完美地复制它,因为你有进入它的确切数据,你可以离线做,复制它,修复它,写一个回归测试,永远不会再破坏它。
然后,我们看数据的另一种方式是分析。我想也许用分析的方式来称呼它是一个好方法,在数据存在的事实之后提出问题,但没有真正组织起来回答你的问题。我们不会写一个记录来回答你的问题,因为你后来想到了这个问题。
所以,更像是传统的数据分析,要求商业信息或其他指标和测量,性能方面的事情可能会在以后出现,你会汇总大量的数据。我会更详细地讲一下这些。
因此,对于消息数据,这是我们的大部分流量。基本上,我们将其保存在数据中心,仍然以相同的CHUM形式保存。我们可能会将其转移到热访问数据的不同存储中,并使其位于同一位置,更接近我们拥有的大型计算集群。
因此,我们实际上有大型的超级计算机集群,许多机架的Linux盒子塞满了gpu。所以,他们在做各种各样的事情,比如机器学习,运行我们正在运行的所有测试,以及所有其他需要数据的事情。
因此,我们可以做的一些事情就是通过查看总线上的一些简单的元消息,我们可以查看消息之间的时间,我们可以生成报告,以便团队可以查看组件运行的速度有多快?他们能跟上分配给他们的节拍和节奏吗?他们是否在规定的时间内完成了产出?的性能。什么样的CPU?
所以,一旦你能把这些联系起来,我想这将是下一张幻灯片,关于性能的更多细节。但是,是的,所以你可以通过一些简单的工具直接查看很多信息,我们的核心团队开发了这些工具,这些工具可以快速查看整个飞行器上使用的一些原始信息。
但是,我们也可以交叉引用消息中一些相同的定时信息与CPU的行为,标准CPU分析和转储,这样我们就可以将CPU使用率,火焰图与定时和延迟,以及发生的事情联系起来,因为很多核心都在运行,它们都在做不同的事情,它们都在发送消息。除非你有非常好的工具来深入挖掘和关联,否则调试起来真的很棘手。这可能是发送的消息的因果关系,以及触发的事情,可能是另一个组件的CPU峰值。
当然,我们会使用收集到的数据。尤其是激光雷达的所有数据。可能雷达和视觉也被用来收集大量的记录,并构建定位信息。因此,利用GPS和其他系统结合我们在激光雷达中看到的,并在一个漫长的过程中平均,我们可以创建非常非常精确的数字地图,它告诉我们在我们驾驶的整个城市区域内,事物之间的精确位置在一厘米或两厘米内。
而且,回放。所以,我们也可以把那些我们录制的信息回放,并以不同的方式有效地呈现它们。我马上会播放这段视频,但你可以在左边看到的是摄像机捕捉到的,然后,在那里有了覆盖层,覆盖层的所有信息,比如盒子在那个空间里的位置,传感器在不同的代理上采集到的模式。这些都被记录下来了。
右边的3D图像的所有信息,所有的代理人,他们是什么,他们的计划是什么。这些也被记录下来,然后,覆盖在我们运行的地图上。
所以,这只是我们发布的一小段视频蒙太奇中的一段,展示了车辆的工作情况,我们可以根据团队需要构建的内容来布局这些视频。这是我们做的。主要是我们用来炫耀的。所以,观看很有趣。你可以看到,粉色代表行人,蓝色代表车辆,橙色代表自行车或摩托车。
在右边你可以看到计划器。所以,它在顶部显示了指示车辆打算做什么的信号。如果它绕着两辆车转,底部是一样的,但这是俯视图。红门表示它知道它会停在那里。然后,绿线是来自每个智能体的预测向量,所以我们知道预测,我们认为行人或其他司机会去哪里。好吧。
我之前提到的一件事是,当发生什么事情时,脱离接触,一般来说,操作员会做笔记,脱离接触会被记录在信息中。我们将收集这些信息,然后将其保存在JIRA中。然后,团队可以看一下JIRA的门票。
QA可能会首先查看这些内容,或者工程师可能会立即查看这些内容,并决定何时查看这些内容。所以,他们有他们需要知道的一切。他们需要的所有元数据都出去获取CHUM并重现发生的问题,他们可以查看这些数据。
我们可以对它进行分类,我们可以对它进行标记,我们可以回放,看看在不同的视图中发生了什么,我们可以生成不同的外观。我们有办法布置窗口,在那里我们可以观察发生了什么,查看消息的度量和时间,以及同时发生的各种诊断信息。
我们可以保存它们,剪掉它们,把它们变成我们反复运行的测试,一遍又一遍地验证东西。我们也可以进行日志测试,也就是基于真实数据的测试,部分自动化和手动制作的测试更加综合,我们可以用同样的方式重现这个问题,但随后,添加一些额外的模糊测试,这样你就可以创建。比如,如果行人走得快一点,或慢一点,或向右走得多一点,会怎么样?因此,我们可以展开,乘出,特定测试可以测试的情况。
是的,我想我已经提到了很多,开发人员调试,让所有的数据都可用来让人们在桌面上调试或者通过在作业队列中写入作业来运行它们。当然是机器学习训练,以及用于识别事物的标签。
然后,最后一点。我会稍微讲一下,分析学。在很长一段时间里,我们只是运行脚本,从CHUM中提取数据,然后直接用Python查看它。我们可以用这种方式进行分析,它对特殊查询非常有效。如果一个工程师想要查看大量数据,并在很长一段时间内从许多主题中提取出一些信息线索,他们可以使用一些很好的Python分析工具,我们可以直接访问CHUM数据,但我们想要更多,更正式一点,让我们利用一些数据分析工具。
因此,我们现在主动ETL了一堆我们发现有趣的CHUM数据,并将其放入列式存储中。我们现在用的是红移。可能是未来任何可行的方法。但是,考虑到我们有这组对很多不同工作都非常有用的数据,我们可以定期将其放入柱状存储中,根据摄取的规律节奏,然后使用它来生成各种不同类型的报告。
这些是故意模糊的,但它的想法是,它可以告诉我们我们在旧金山某条路线上做得有多好。假设我们正在驾驶一条具有挑战性的路线,我们想说,“我们这周在这条路线上做得怎么样?”随着时间的推移,我们是否会变得更好?”或者,在某些情况下,乱穿马路的人或自行车喜欢跑停车标志。我们到哪里去找?
然后我们就可以追踪并从原始数据中收集信息,使其可用,并将其可视化,并在地图上跟踪,创建热点图。
我们也可以用它来生成我们每年都要做的车管所报告。基本上就是这样。谢谢你!
