Py学习  »  机器学习算法

自动驾驶算法—利用深度学习进行端到端运动规划

机器人规划与控制研究所 • 2 年前 • 516 次点击  

过去几个月,我对自动驾驶汽车技术非常感兴趣。你可以将机器学习知识应用于开发自动驾驶汽车堆栈的各个部分,这有无数种可能性。

在这篇文章中,我将带您了解为自主机器人开发端到端运动规划器的过程。这个项目深受comma.ai在open pilot中使用的方法的启发。

自动驾驶的不同方法

开发自动驾驶汽车软件的方法有很多种。模型可以采用端到端训练,也可以采用中间到中间方法训练。以下是一些示例:

  • 端到端行为克隆在这种方法中,CNN 是端到端训练的。输入是一系列图像或单个图像,输出直接是转向角。当 Nvidia 大规模训练这种类型的神经网络时,这种方法变得流行起来。相关博客可以在这里找到。我也致力于实现许多类似的模型。repo 的链接可以在这里找到。它包含训练这些模型的分步过程,其中一些是:Nvidia 的模型、Comma AI 的模型、3D CNN、LSTM。这种方法很容易实现,因为模型几乎可以在内部学习所有内容,我们不必实现传统的控制堆栈、定位器、规划器等。但缺点呢?你失去了对模型输出的完全控制,无法解释人类理解的结果(完全黑匣子),难以结合先验知识。


图像输入,控制输出


  • 中间到中间:在这种方法中,网络不是直接输出控制,而是被分解成任意多个部分。例如,训练单独的网络进行物体检测、运动预测、路径规划等。Lyft、Tesla 等都采用了这种方法。下面显示了 Lyft 如何检测其他车辆、将它们放置在周围环境的语义地图上,并预测所有其他事物的运动,其结果将进一步传递给控制器,最终产生转向、油门等输出。


来自 Lyft 的 2020 年运动预测挑战赛


这种方法的缺点是,错误会通过多个步骤不断累积,将所有部分组合在一起会变得困难得多。但另一方面,优点是,这个过程完全可以被人类解释,并且可以轻松推理自动驾驶汽车的决策。除此之外,现在还可以结合先验知识。

  • Comma 的方法: Comma 跳过物体检测、深度估计等,直接输出车辆要遵循的轨迹。然后,该路径由其团队维护的常规控制堆栈跟踪。


理解超级组合模型


超级组合模型制作精良,但重量轻,其输入如下:

  • 2连续的 YUV 格式图像帧

  • 循环细胞 的状态(循环神经网络)

  • 望(稍后讨论)

并预测以下输出:

  • 路径(要遵循的轨迹输出)

  • 左车道

  • 右侧车道

  • 路径和车道的标准偏差(如下所述)

  • 领先车辆信息

  • 未来 n 步的纵向加速度、速度和位移

  • 姿势(如下所述)

  • 还有一些我不太确定的东西

        路径、左车道和右车道是相对于本车辆的“预测轨迹”和自上而下/鸟瞰坐标系中的车道线

超级组合的路径和车道输出

看看模型如何预测右侧道路的曲线。

这里要注意的另一件事是,当看不到车道线时,或者当模型对其预测不太有信心时,车道线也会消失。这个“信心”分数基本上也是由模型预测的,只是“标准偏差”。这些标准偏差是针对每条路径、左车道和右车道以及许多其他输出(包括姿势、领先输出等)预测的。

可以使用贝叶斯神经网络来预测标准差,该网络在计算预测时将不确定性传递到整个网络。

姿态输出是两个输入图像之间预测的平移和旋转。这可能用于执行视觉里程计并根据输出轨迹定位汽车。

数据创建


在考虑训练神经网络之前,我们需要收集数据并将其处理成适合训练的格式。Comma.ai 发布了开源数据集,其中包含大量此类信息,如车道、路径和其他内容。但我想要更多的挑战,所以决定使用 Udacity 的数据集,它只包含:

  • 转向角

  • 速度

  • 陀螺仪读数

  • GPS 读数

  • 来自中心、左侧和右侧安装的摄像机的图像框架。

为了训练自定义模型,我决定只预测未来的路径和速度。

欲望


希望基本上对高级动作进行独热编码,例如“左变道”、“右变道”、“保持在车道内”、“右转”、“左转”等。

Udacity 数据集不包含任何“愿望”。因此需要手动标记 10,000 帧 :(

手动标记 10,000 个帧并不容易。因此,我没有单独标记每个帧,而是为此创建了一个小工具Autolabler


使用这个,我的朋友 Raghav 在 30 分钟内标记了整个数据集。它更像是一个小型视频播放器,您可以根据需要暂停、搜索、快进、减慢输入帧流。它会在播放流时不断动态标记所选标签。有关使用它的完整说明可以在我的repo中找到。


小路

对于轨迹地面实况,我只能使用 udacity 数据集中存在的信息。

首先,我使用了一个简单的自行车模型,通过速度和转向角输入到车辆模型中,随着时间的推移,该模型逐渐变化。

在低速时,使用以质心为参考系的简单自行车模型。

以汽车重心为参考的自行车模型

模型参数


我本可以使用动态模型进行横向控制,但我实际上没有用于收集数据集的车辆参数数据。

现在,可以肯定的是,上述模型非常简单,无法很好地模拟车辆的实际物理特性,因此使用来自陀螺仪和 GPS 的额外数据并将其与卡尔曼滤波器融合在一起绝对有意义。此外,开发算法的另一条规则是,永远不要丢弃任何数据,即使它非常嘈杂。找到整合来自其他数据源的任何信息的方法。这只会改进算法。

幸运的是,GPS 模型是已知的,所以我能够构建卡尔曼滤波器。


不同的跟踪方法的实际应用


观察一段时间后过程模型(红色)如何开始偏离原始轨迹。

我使用了 3 种跟踪方法,并使用卡尔曼滤波器将它们结合在一起。

  • 自行车模型作为流程模式

  • GPS 读数

  • 于 IMU 的里程计

  • 觉里程计

我发现的一个困难是确保所有读数都转换为具有相同参考(汽车)的同一坐标系。例如,对于 GPS 读数,必须将纬度和经度转换为以米为单位的 XY 网格系统。

对于较小的距离,我使用以下公式作为近似值来找到两个纬度经度对之间的距离(以米为单位)。纬度和经度基本上是地球仪上(角度)相对于赤道和本初子午线的测量值。



def latlon_to_xy_grid(lat1, lon1, lat2, lon2):     dx = (lon1-lon2)*40075*math.cos((lat1+lat2)*math.pi/360)/360    dy = (lat1-lat2)*40075/360    return dx, dy

现在,为了收集额外的数据,包括避开障碍物、急转弯和“汽车偏离车道”问题等情况,我使用了 CARLA 模拟器。

紧密的曲线


由于我掌握了用于收集 udacity 数据集的相机的参数,因此我能够在 CARLA 中设计类似的相机模型。从 CARLA 获取真实数据相对容易。

此外,为了避开障碍物,我编写了一个脚本,该脚本可以创建一个场景,将车辆放置在车道边缘,并使用 CARLA 自动驾驶仪生成轨迹以避开障碍物。编写脚本几分钟后,我就有了数千个此类场景。这实际上可能会使模型在现实生活中变得更糟,因为这可能与人类在现实生活中实际做的事情并不接近。



呃,看上去不错?


CARLA 将数据直接保存到磁盘的方式存在一些问题。这导致模拟器速度大幅下降,无法手动控制汽车,也导致数据收集过程变慢。

因此,我必须编写手动缓冲区,以便不断积累数据,直到达到一定大小,然后立即将其转储到磁盘。这极大地提高了数据收集过程的效率。


从数据集中采样的一组轨迹


现在数据收集过程终于完成了。让我们开始模型训练吧!


分析超级组合模型


特征提取器的一部分


对于从帧中提取特征,超级组合使用了大量跳过连接并转换 256 x 128 x 12(两个 YUV 格式的连续帧,带有 3 个额外的 alpha 通道。参见此处)并将它们归结为 1024 维编码。

一旦训练路径规划器,这种编码就会从图像中学习所有信息。


博客文章


“通过在图像上运行视觉模型并尝试使用 GAN 从中重建图像,我们可以深入了解视觉模型的 1024 个输出向量中编码的内容。上图是道路的原始图像,下图是通过几百万张图像和特征向量训练的 GAN 进行的重建。请注意,与规划相关的细节(例如车道和领头车的位置)是如何保留的,而无关的细节(例如汽车的颜色和背景风景)则丢失了。”—— Harald Schäfer

该模型学习将规划所需的所有相关信息编码为压缩形式。此视觉编码随后被分成几个分支,这些分支被独立处理以输出车道、路径等。


分叉成分支


Super Combo 还使用类似 GRU 的层来编码时间信息。网络是有状态的,循环层的状态输出在下一次推理期间被重新输入。

训练模型


为了训练模型,我将以愿望和帧作为输入(RNN 状态仅在推理时间内提供),输出仅仅是未来 50 米/步的路径和速度以及标准差。

贝叶斯神经网络


标准差让我们了解模型对其预测的信心程度。这可以使用一种称为贝叶斯神经网络的特殊网络来实现。

我们不会直接回归车道、路径和速度,而是预测分布。

来源 — https://www.youtube.com/watch?v=z7xV-HYVAZ8


请观看 AI 学生的这段视频,了解对此的精彩解释。

我们可以使用混合密度网络来输出多条路径及其置信度分数,将其转换为混合密度网络。

输出多个高斯分布及其分数、alpha。


我使用批量大小为 16 且包含过去的 16 个时间步骤以及 2 个高斯混合来训练网络。

数据增强


我使用数据增强来使模型对噪声具有鲁棒性。这些包括向图像添加泊松噪声、打乱图像的颜色通道、水平翻转图像、增加/减少图像的对比度、温度等。

数据增强


损失函数


简单点输出(无不确定性 预测):在实际应用中,我们最小化线性函数 μ 的输出的平方误差项 ( μ( x , Θ )− y )²,给定x、其参数Θ和某个数据集 𝔻 中所有 ( x , y ) 对的目标值y。学习函数本质上是在给定数据和参数的情况下“输出”高斯分布 μ( x , Θ ) 的条件均值。它会丢弃与Θ无关的标准差和归一化常数。

我尝试了多种损失函数。对于简单回归输出(如上所述)(简单神经网络,无标准偏差输出),我使用了轨迹之间的 L2 损失和轨迹梯度之间的 L1 损失的加权和。

梯度损失背后的直觉是,我们人类会根据道路上的曲线来估计转动方向盘的“强度”。因此,将其纳入损失函数是有意义的,结果发现它比“仅在轨迹之间使用简单的 L2”表现更好。

MDN 网络:在这种情况下,标准差现在取决于输入,这使我们能够考虑可变的标准差。即使我们只使用单个高斯分布,这一优势也适用。

对于 MDN(也预测标准差),损失计算如下

cat = tfd.Categorical(logits=out_pi)        component_splits = [output_dim] * num_mixes        mus = tf.split(out_mu, num_or_size_splits=component_splits, axis=1)        sigs = tf.split(out_sigma, num_or_size_splits=component_splits, axis=1)        coll = [tfd.MultivariateNormalDiag(loc=loc, scale_diag=scale) for loc, scale in zip(mus, sigs)]mixture = tfd.Mixture(cat=cat, components=coll)        loss = mixture.log_prob(y_true)        


    
loss = tf.negative(loss)        loss = tf.reduce_mean(loss)

我使用了来自这个repo 的实现

(https://github.com/cpmpercussion/keras-mdn-layer)


测试

看看网络如何输出均值(实际路径)和偏差。

最初,模型对预测很有信心,偏差也很低,但随着模型预测未来的轨迹,偏差会增加,这是直观的。



甚至 openpilot 模型也表现出类似的行为。


原始 openpilot 模型中的路径和车道


看看模型在较短距离时如何相当自信,但在较远距离时预测会变得更加嘈杂和不稳定。

我会进行更严格的测试,并很快会发布一个模型运行的视频,既适用于现实生活,也适用于合成数据。现在我们有了轨迹输出,在下一篇文章中,我们可能会讨论如何将轨迹实际转换为控制并控制模拟汽车。但这将需要做很多工作。但让我们尝试一下吧:D

结论

恭喜你读到了最后!这是一篇很长的文章。

因此,这是我训练端到端路径规划器的旅程,这在很大程度上受到了 comma.ai 工作的启发。我想感谢 comma.ai discord 社区解答了我的许多疑问。我不保证这篇文章中的所有内容都是正确的。请随时指出您可能发现的任何错误,并通过下面的评论来帮助纠正它们。

我在这个项目中探索了很多东西。我并没有在这篇文章中深入讨论太多细节,因为我错过了写我在这个项目中遇到的很多挑战。下次,我会尝试将这篇文章并排写出来,这样我就不会忘记添加任何东西。


更多信息请参见原文地址:

https://mankaran32.medium.com/end


    
-to-end-motion-planning-with-deep-learning-comma-ais-approach-5886268515d3



    

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/171527