图宾根-ML4340-自动驾驶笔记-全-

图宾根 ML4340 自动驾驶笔记(全)

001:课程介绍与组织方式 🚗

在本节课中,我们将要学习自动驾驶汽车课程的基本介绍,并了解这门课独特的“翻转课堂”组织方式。


欢迎来到图宾根大学的自动驾驶汽车课程。我是安德烈亚·盖加,我将担任这门课的讲师。

自动驾驶一直是人类的梦想,正如这张来自20世纪50年代的插图所示。然而,这一目标至今尚未完全实现。在本课程中,我们将探讨自动驾驶技术的现状,以及未来实现自动驾驶所面临的挑战。

我的研究小组也在进行自动驾驶系统的研究。我想快速展示一下我们通过一个端到端训练系统所取得的成果。该系统仅通过观察图像和人类驾驶示范进行学习,之后便能在名为“卡拉”的模拟器中自主驾驶。


上一节我们介绍了课程背景,本节中我们来看看这门课的具体组织方式。

这门课程采用所谓的“翻转课堂”模式进行教学。这意味着什么?

在翻转课堂中,我们会提前提供讲课视频和练习材料。你需要观看视频并完成练习。然后,我们将在实体线下课中重聚,与所有同学一起讨论课程的全部内容。

为了提升学习动力并提供自我评估的手段,同时也为了分析课程的难点与易点,我们提供了可填写的多项选择题测验。参与这些测验可以为你的期末考试赢得加分,并帮助我们根据你的需求调整线下课内容。

同时,我们建议你与同学组建学习小组,共同讨论课程材料和练习。

此外,我们还提供在线练习答疑服务,助教随时准备为你解答与练习相关的任何问题。

与讲课类似,练习部分也提供多项选择题测验,这同样是自我评估和获取期末考试加分的机会。

在整个学习周内,我们通过在线聊天或论坛提供快速反馈。

以下是典型学习周的安排流程:

  • 观看视频:首先观看课程视频。
  • 开始练习:着手完成相关练习。
  • 寻求帮助:与学习小组讨论或在聊天中提问。
  • 完成测验:完成讲课测验和练习测验。
  • 准备问题:带着所有问题参加线下课。

本节课中我们一起学习了自动驾驶课程的概况及其“翻转课堂”的组织模式。我期待在第一次线下课中与大家见面。

002:自动驾驶的挑战与愿景 🚗

在本节课中,我们将探讨为何自动驾驶汽车尚未普及,以及实现完全自动驾驶所面临的核心挑战。我们将从这项技术的潜在益处入手,分析其技术、伦理和现实障碍。

概述

自动驾驶技术被誉为交通领域的革命,但其发展道路远比预想的复杂。本节将系统性地介绍自动驾驶的愿景、当前面临的困难,以及一些关键的伦理困境。

为何需要自动驾驶?🤔

在深入探讨挑战之前,我们首先需要理解发展自动驾驶技术的根本动机。其益处主要体现在以下几个方面。

以下是自动驾驶技术的主要潜在益处:

  1. 降低事故风险:全球交通事故伤亡数字触目惊心。仅2017年,美国有超过32,000人死于交通事故,德国超过3,000人,全球则超过100万人。超速、酒驾和分心驾驶是主要因素,而自动驾驶系统可以有效应对这些问题,未来甚至可能完全消除事故。
  2. 为特殊群体提供出行便利:自动驾驶能为老年人和残障人士提供安全、经济的出行方式。例如,在美国,45%的残障人士仍在工作,他们需要可靠的交通解决方案。
  3. 减少污染,优化交通:大规模部署自动驾驶汽车可以提高车辆使用率,减少所需汽车总量,从而降低制造污染。此外,车辆间可以协同运行,有效缓解交通拥堵。
  4. 推动共享出行,提升资源效率:未来,人们可能无需拥有汽车,而是随时随地呼叫自动驾驶服务。车辆可以在途中以最优方式拼载其他乘客。据统计,普通汽车95%的时间处于闲置状态,这是巨大的资源浪费。自动驾驶可以实现车辆近乎全天候运行,极大提升效率和环保性。

工业界的热情与残酷的现实 🏭

基于计算能力、内存、算法和人工智能的飞速发展,过去十年工业界对自动驾驶抱有极大热情,认为其即将成为现实。

例如,优步在2018年的宣传片中展示了其自动驾驶测试车队,配备了360度摄像头、激光雷达和雷达系统,并有安全员随车监控。视频强调了通过持续测试、数据收集和软件迭代,车辆正变得越来越智能,旨在减少事故、拯救生命。

然而,同样在2018年,优步的一辆自动驾驶测试车在亚利桑那州发生了致命事故,撞死了一名横穿马路的行人。调查显示车辆在碰撞前没有显著减速迹象。这起悲剧凸显了自动驾驶技术面临的严峻挑战和风险。

自动驾驶为何如此困难?🛑

自动驾驶之所以困难,一个关键原因是我们可能低估了人类驾驶员的性能。从统计数据看,人类驾驶员平均每行驶1亿英里才会发生一起致命事故,错误率仅为 0.000001%

在计算机视觉领域,99%的准确率已令人兴奋,但显然远不足以解决自动驾驶问题。99%的准确率意味着每100次判断就有1次错误,这在高速行驶中是不可接受的。

除了极高的可靠性要求,自动驾驶还面临一系列具体挑战:

  1. 全场景适应能力(Level 5):完全自动驾驶车辆必须在任何地点、任何条件下运行,包括雪天、暴雨、夜晚、无标线的非结构化道路(如停车场),并能应对行人不可预测的行为、路面反光造成的感知干扰以及快速变化的动态场景。
  2. 处理罕见与未知事件:收集常规驾驶数据容易,但难以覆盖所有“极端案例”。机器学习模型在像人类一样稳健地泛化到未见过的场景方面,能力仍然有限。
  3. 复杂的路径规划与控制:这不仅仅是保持车道行驶。例如,汇入繁忙的高速公路需要车辆与其他道路使用者进行复杂的“协商”和交互,这对自动驾驶系统是巨大挑战。
  4. 伦理与法律困境:在不可避免的事故中,车辆应如何决策?这引出了著名的“电车难题”伦理思考。

伦理挑战:电车难题与道德机器 🧠

“电车难题”是一个经典的伦理思想实验:一辆失控的电车驶向轨道上的五个人,你可以扳动道岔让电车驶向另一条轨道,但那条轨道上也有一个人。你该如何选择?

麻省理工学院的研究团队将其转化为自动驾驶场景,创建了“道德机器”平台。该平台向公众展示各种道德困境,例如:一辆无法刹车的自动驾驶汽车,是应该撞向违规过马路的三人,还是转向撞向遵守交规的一人?

这些没有标准答案的伦理问题,是自动驾驶技术商业化前必须面对和探讨的社会议题。

总结

本节课我们一起探讨了自动驾驶技术的宏伟愿景与其面临的现实挑战。我们了解到,尽管自动驾驶有望大幅提升道路安全、出行效率和环保水平,但其实现之路布满荆棘。技术层面需要达到远超当前水平的可靠性与泛化能力,同时还需解决复杂的路径规划、以及深刻的伦理与法律问题。理解这些挑战,是我们深入学习后续具体技术方案的基础。

004:自动驾驶方法概述 🚗

在本节课中,我们将学习自动驾驶的不同实现方法。我们将从最直观的端到端学习方法开始,并重点介绍其中的模仿学习。模仿学习是目前最简单、也最有前景的自动驾驶方法之一,但同时也是实际部署最少的方法。让我们一起来探究其原因。


自动驾驶方法概览 🧩

上一节我们介绍了课程目标,本节中我们来看看实现自动驾驶的几种主要范式。

一个自动驾驶系统可以看作一个函数,它接收高维度的传感器输入(例如RGB图像、激光雷达扫描序列等),并输出低维度的控制指令(主要是转向和纵向控制)。我们的目标是找到一个鲁棒可靠的映射函数。

目前有三种主导的自动驾驶范式:

  1. 模块化流水线
  2. 端到端学习(模仿学习属于此类)
  3. 直接感知

让我们逐一了解这些范式的区别。


模块化流水线 🧱

顾名思义,模块化流水线将整个自动驾驶栈分解为独立的组件。这是目前行业领导者(如Waymo、Uber、Tesla)以及早期DARPA挑战赛获胜者采用的主要范式。

以下是该流水线的一个简化示例:

  1. 低级感知:车辆首先需要定位自身,并检测周围的车辆、建筑物、车道线等。

    • 定位:确定车辆在地图中的精确位置。
    • 目标检测:识别并框出周围的物体。
  2. 场景解析:将感知到的所有信息整合成一个统一的、鲁棒的场景表示。这包括将车辆轨迹、消失点、车道标记等信息关联起来,形成一个关于环境的连贯理解。

  3. 路径规划:结合高精地图信息和解析后的场景表示,在全局和局部层面规划行驶路径。

    • 高精地图:包含车道线、交通灯位置等丰富细节的高精度地图。
  4. 车辆控制:执行规划好的路径,通过控制器调整方向盘、油门和刹车,使车辆沿着轨迹行驶。

模块化流水线的优势在于易于并行开发,且因为每个模块都由人类设计,所以系统行为相对可解释。

然而,其劣势也很明显

  • 无法进行端到端联合训练:每个模块都在不同的数据上针对不同的子任务(如检测框的准确性)进行优化,而非直接针对最终的驾驶性能进行优化。
  • 依赖高精地图:当前的定位和规划严重依赖高精地图,而制作和维护这些地图需要大量人力,成本高昂且难以覆盖所有区域。


端到端学习 🔄

与模块化方法相反,端到端学习将“从传感器输入到控制指令”的映射视为一个整体的函数,通常用一个神经网络来表示。

这个神经网络可以通过不同的算法进行训练,其中最重要的两种是:

  • 模仿学习
  • 强化学习(我们将在后续课程中学习)

这种方法历史悠久,例如早在80年代的ALVINN项目,以及现代英伟达的自动驾驶演示,都采用了模仿学习的思路。

端到端学习的优势

  • 直接优化最终目标:模型直接学习驾驶任务,避免了子任务优化与最终目标不一致的问题。
  • 数据标注成本低(特指模仿学习):只需在车上安装摄像头和传感器,记录人类驾驶时的画面和操作,即可自动收集训练数据。

其劣势包括

  • 泛化能力目前通常不如模块化流水线。
  • 缺乏可解释性:神经网络像一个“黑盒”,难以理解其内部决策逻辑。


直接感知 🎯

直接感知是上述两种方法的混合体。它仍然有一个模块化的结构,但保持了端到端训练的可能性。

具体来说,系统首先用一个神经网络从输入图像中预测出一个中间表示(例如语义分割图,或一组关键的“可驾驶性”参数),然后再用另一个神经网络或传统的车辆控制器,根据这个中间表示生成控制指令。

直接感知的优势在于其中间表示既紧凑又可解释。

其挑战在于

  • 如何选择合适的中间表示(这又引入了人为设计)。
  • 如何有效地联合训练感知模块和控制模块。

总结 📝

本节课我们一起学习了自动驾驶的三种主要方法:模块化流水线端到端学习直接感知。模块化流水线结构清晰、可解释性强,但依赖高成本地图且非端到端优化;端到端学习直接针对驾驶任务进行优化,数据收集方便,但可解释性和泛化能力是挑战;直接感知则试图在两者之间取得平衡。在接下来的章节中,我们将深入探讨端到端学习中的核心方法——模仿学习。

005:模仿学习 - 深度学习回顾 🧠

在本节课中,我们将要学习深度学习的基础知识,这对于理解本课程后续讨论的许多算法至关重要。虽然深度学习是本课程的先修内容,但我们认为进行一次快速回顾是很有必要的。本次回顾浓缩了图宾根大学深度学习课程前七讲的核心内容,我们将以较快的速度进行梳理。如果你需要更深入地了解这些材料,建议查阅我们的完整课程。

监督学习概述

上一节我们介绍了课程背景,本节中我们来看看机器学习的核心问题之一:监督学习。在模仿学习等场景中,我们同样会用到监督学习。

监督学习涉及一个参数化模型 F,其参数为 W。该模型接收输入 X 并预测输出 Y。输入可以是一张图像,输出可以是车辆的控制指令。

监督学习包含两个任务:

  1. 学习任务:从包含 (x, y) 对的数据集中估计参数 W
  2. 推理任务:在给定训练好的模型(即参数 W)后,如何进行新的预测。

线性分类器

让我们从最简单的线性分类器——逻辑回归器开始回顾。

其数学公式如下所示。我们首先对输入 X 进行仿射变换(线性变换),即乘以权重 W 并加上偏置 W₀。然后将结果(一个标量)通过一个逻辑函数(Sigmoid 非线性函数)进行处理。Sigmoid 函数的形式如下,它将输入值的范围压缩到区间 (0, 1),这个结果就代表了预测类别的概率。

决策边界位于 Sigmoid 函数参数等于 0 的位置。换句话说,即 Wᵀx + W₀ = 0。如下图所示,当 Wᵀx > -W₀ 时,我们判定为类别 1,否则判定为类别 0。

那么,这个简单的分类器能解决什么问题呢?

以下是第一个问题:逻辑“或”(OR)运算。左侧以表格形式展示,右侧以图形形式展示。我们有一个二维输入,如果两个值中任意一个为 1,则输出为 1(图中绿色点,类别 1);否则输出为 0(仅在坐标 (0,0) 处,图中红色点,类别 0)。

我们可以找到一个分类器,完美地将这两组点分开,如下所示。我们画一条线,清晰地将所有红点与所有绿点分开,其数学形式如顶部所示。

类似地,我们可以定义逻辑“与”(AND)运算符。图中这三个点是红色的,只有当 x₁x₂ 同时为 1 时,输出才是类别 1(绿色),否则是类别 0(红色)。与之前类似,我们可以定义一个线性分类器,用这里的公式表示,将红点与绿点分开。

我们还可以定义“与非”(NAND)运算符,它只是将“与”运算的结果取反。

现在的问题是,“异或”(XOR)运算符如何处理?“异或”运算如下所示:如果 x₁x₂ 中有一个为 1 而另一个为 0,则预测类别 1,否则预测类别 0。在这种情况下,问题变得复杂了。没有单一的决策边界可以正确分类这个数据集,无论是这样还是那样都不行。

那么,我们该怎么办?

特征提升与非线性分类

解决这个问题的一个方案是将特征,即二维特征空间,提升到一个更高维的特征空间。例如,考虑这里的特征空间,我们不仅拥有 x₁x₂,还拥有它们的乘积 x₁ × x₂,如右图所示。现在,我们有了一个三维特征空间。你可以看到,右侧的这个点现在被“提升”到了顶部,因为只有对于 x₁ × x₂,第三个特征值才为 1。

在这种情况下,在这个三维特征空间中,我们实际上可以找到一个线性分类器,一个线性超平面,将这两个类别彼此分开,如图所示。换句话说,非线性特征使得线性分类器能够解决非线性分类问题。我们改变了表示方式,改变了特征空间,因此线性分类器能够解决之前无法解决的问题。

这是另一个例子。左侧的这个数据集无法被线性分离。但是,如果我们使用极坐标(半径 r 和角度 θ)来表示这个数据集,那么我们可以清晰地找到一个线性决策边界来区分这些点。

但是,如何选择这种变换?我们实际上应该如何改变表示?如果想手动完成,这在实践中可能非常困难。然而,在 2000 年代之前,手动设计特征空间是视觉和语音领域的主流方法。而在深度学习或表示学习中,我们希望从数据本身学习这些表示和变换,这当然方便得多。

组合分类器与神经网络雏形

让我们再看一下“异或”问题,你可以在右下角看到。为了正确分类这个数据集,我们可以做的是:这里可以有一个决策边界,代表“或”(OR)运算;这里可以有另一个决策边界,代表“与非”(NAND)运算。然后我们可以将这两个结合起来,得到“异或”运算。

用公式表示,x₁x₂ 的“异或”运算,等于对 x₁x₂ 进行“或”运算的结果,与对它们进行“与非”运算的结果,再进行一次“与”运算。通过简单地组合这三个运算,我们得到了“异或”运算。

这也可以写成一系列逻辑回归器的程序。以下是上一张幻灯片的表达式。我们可以将其写成一个程序,因为其中每个组件都是我们已经了解的内容。例如,前面我们已经看过“与”运算的具体公式,等等。

因此,逻辑回归器的程序如下所示:我们用“或”运算变换 x,得到一个隐藏特征值 h₁。我们用“与非”运算变换 x,得到另一个隐藏特征 h₂。我们将这两个连接成一个向量 h,然后用“与”运算对其进行变换,得到预测结果。

这可以写成右侧的计算图,其中绿色节点是输入,橙色节点是参数,红色节点是中间节点或输出节点。注意,h(x)x 的非线性特征,因为这里的 Sigmoid 非线性函数。我们称 h(x) 为一个隐藏层

多层感知机 (MLP)

这可以推广,其推广形式称为多层感知机,简称 MLP。MLP 是前馈神经网络,不像循环神经网络那样有任何反馈。它们组合了多个非线性函数。例如,f(x) 可以表示为 ŷ(h₃(h₂(h₁(x)))),简单地将这些隐藏特征堆叠起来,直到得到输出。

数据只指定输出层的行为,因此得名“隐藏”。每一层 i 包含多个神经元 j,每个神经元通过仿射变换 aᵀx + b 实现,后接一个非线性激活函数,例如 Sigmoid 函数。更一般地,我们在这里用 g 表示激活函数,因为它可能是不同的激活函数,我们很快会看到一些激活函数。

在 MLP 中,每一层的每个神经元都完全连接到前一层的所有神经元。整个链的长度就是模型的深度,因此称为深度学习。隐藏层越多,我们的模型就越深。

这是一个例子:有一个输入层,然后三个隐藏层,一个输出层。我们说这个网络,因为它有三个隐藏层和一个输出层,所以深度为 4。输入层不计入深度。另一方面,宽度是指每一层有多少个神经元。这里你可以再次看到,神经元被分组到各层,每个神经元都完全连接到前一层的所有神经元。例如,这个神经元连接到这个、这个和这个。

深度与模型复杂度

更深的模型允许更复杂的决策。这里有一个例子,我取自 Andrej Karpathy 的优秀网站,该网站有一个实时演示,你可以在其中对数据进行分类并做许多其他有趣的事情。你可以看到具有两个隐藏层、五个隐藏层和 15 个隐藏神经元的神经网络在相同数据集上的决策边界。


所以,深度和宽度当然都决定了决策可以有多复杂。

MLP 的组成部分

我们来谈谈多层感知机的组成部分。

输出层是神经网络中的最后一层,它计算图中红色部分所示的输出。在输出之后,我们有一个损失函数,它将神经网络的输出与右侧绿色部分所示的一些期望目标值进行比较。

输出层和损失函数的选择取决于任务。例如,如果我们想预测离散值(如图像类别)或连续值(如车辆转向角)。

关于输出层:

  • 对于分类问题,我们通常使用 Sigmoid(二分类)或 Softmax(多分类)非线性函数来获得概率值。
  • 对于回归问题,我们可以直接返回最后一层之后的值,因为它是连续的。所以,我们在最后一个仿射变换之后不应用任何非线性函数。

损失函数也因任务而异:

  • 对于分类问题,从最大似然原理推导出的损失函数是交叉熵损失,或在二分类情况下的二元交叉熵损失
  • 对于回归问题,我们可以使用标准的 L1L2(欧几里得)损失。当然,还有很多其他选择。

每个隐藏层都有一个激活函数。回顾上一张幻灯片,一个隐藏层有一个线性变换加上一个非线性变换 gg 被称为激活函数。激活函数通常以逐元素的方式应用于其输入,所以它实际上是一个只对标量进行操作的函数。

激活函数必须是非线性的,以便通过网络学习整体上的非线性映射。如果没有非线性激活函数,你的整个网络将不会是线性的。

以下是一些激活函数的例子:左上角是已知的 Sigmoid 函数,右边是流行的 ReLU 函数,它计算效率高,并且在梯度方面不会饱和。左下角还有很多其他函数。人们根据问题使用不同的激活函数,选择通常是经验性的,需要尝试不同的激活函数。

卷积神经网络 (CNN)

对于处理图像(如自动驾驶中的情况)特别重要的是卷积神经网络

多层感知机的问题在于它们无法扩展到高维输入。如果你有一张百万像素的图像,那么你将会有非常多的连接和权重,这些权重很难学习并且需要大量内存来存储。

因此,卷积网络将数据表示为三维形式。在这种情况下,输入以图像的宽度和高度表示,第三维是深度,代表特征通道或特征图的数量。卷积网络交错使用离散卷积、非线性激活函数(如 ReLU 或 Sigmoid)以及池化操作,以减小下一层的空间维度。

卷积神经网络的关键思想是:

  1. 利用稀疏交互
  2. 大量使用参数共享
  3. 学习等变表示,这意味着如果我将输入平移,那么卷积层的输出特征也会被平移,这是一个理想的特性,是图像处理中非常有用的归纳偏置。例如,如果我想检测物体,那么我希望无论物体出现在图像中的哪个位置,都能以相同的方式检测到它。

让我们更仔细地看一下这一点,这是全连接层与卷积层的比较。

在左侧,你可以看到全连接层,这里的输入也是一幅图像。在右侧,你可以看到对应的卷积层。你已经可以看到,全连接层有更多的权重,因为每个输入(每个宽度 W、高度 H 和通道数 C_in,再加上偏置)都连接到每个输出元素。因此,我们得到这个乘积与输出宽度 W'、高度 H' 和输出通道数 C_out 的乘积。

相比之下,卷积层的权重要少得多。在这里,对于这个输出,我们只连接位于同一位置的卷积核元素。因此,如果我们假设一个 3x3 的卷积核,那么我们不是连接所有输入,而是只连接 3x3 乘以通道数到这个输出。当然,这里我们也有一个偏置 (+1)。并且我们对所有位置使用相同的权重,我们将这个滤波器应用于输出的所有位置,但使用相同的权重。这就是为什么权重不会被复制。所以,我们在这里的权重数量减少了,这里的 WH 也直接消失了。

但我们为每个输出通道单独进行此操作,所以我们这里仍然有 C_out。这就是所谓的权重共享,它负责减少参数数量,并使这些模型非常高效且具有等变性。

所有这些卷积操作,就像全连接操作一样,后面都跟着一个非线性激活函数,如 ReLU 或 Sigmoid。

这是卷积核在输入上滑动方式的示意图。

卷积的一个问题是,如果我们直接应用卷积,那么我们将无法计算图像边界处的值,因为卷积核会超出图像边界。为了应对这一点,并允许网络在卷积操作本身期间保持规范的图像尺寸(不改变张量的维度),一个简单的想法或解决方案是使用所谓的填充。我们在图像周围添加一个人工边界,用零填充或镜像图像的最后几行和几列。这有不同的变体。然后,如果我们这样做,当然,我们就可以计算并应用这个卷积核,并计算输出张量边界处的这些元素。这就是卷积操作。

池化操作

除了卷积操作,在图像分类以及基于图像输入为自动驾驶做决策的情况下,我们希望将信息缩小到一个单一值,因此我们需要快速减少空间维度。我们通过将池化操作与卷积交错进行来实现这一点。所以,这里我们有一个卷积,然后我们通过对附近的值进行平均或最大池化来简单地降低空间分辨率。

典型的池化操作将输入张量的空间维度减少两倍。通常,在减少空间维度时,特征通道的数量会增加,以保留或增加容量,因为我们正在失去空间分辨率,我们需要增加容量来存储所有相关信息。

下采样也增加了感受野的大小。感受野是原始输入中如果发生改变会影响输出的区域。如果我使用池化操作,将整个图像下采样到一个像素,那么当然,输入像素的任何变化都会改变这唯一的输出。

这是一个池化操作的例子。这是一个简单的池化操作,它计算所有这些值的平均值、均值或最小值,并将其填入这个单元格,然后我们在这里、这里和这里做同样的事情。你可以看到输入的维度是如何被减小的。

通常,卷积网络在最后,在将所有内容展平为空间维度基本为一个像素(即一个向量)之后,包含几个全连接层。然后,我们可以应用几层标准的 MLP 来得出我们的决策。这就是卷积网络的概要。

优化:梯度下降

现在我们来谈谈优化。为了优化神经网络,我们需要应用基于梯度的优化技术,因为神经网络的损失景观当然是非凸的,因为这些模型相对于参数是高度非线性的。

我们从某个特定点开始,然后沿着梯度方向前进,直到达到局部最优解。存在多个局部最小值,但显然,通过梯度下降我们只会找到一个。但好消息是,已知深度网络中有许多局部最小值是好的,所以无论我们陷入哪个局部最小值,大致来说,我们都有很大机会陷入一个好的局部最小值。这就是深度学习效果如此出色的魔力所在。

从数学上讲,我们想要找到最优参数 W,它是损失函数的最小值点。我们想要找到参数 W 的优化值,它是损失函数的极小值点,其中 𝒳 是数据集,W* 是参数。我们想要最小化关于参数 W 的损失函数。

这是一个简单的梯度下降更新循环。当然,为了应用梯度下降,我们需要计算损失函数 L 关于参数 W 的梯度,它出现在梯度更新规则中。我们使用所谓的反向传播算法来计算,该算法使用动态规划来重用计算,以便高效地计算损失函数相对于所有可能数百万个参数的梯度。

它如何工作的概要:首先,通过计算图的前向传播高效地计算值或激活值。这是一个简单的计算图,包含一些输入、参数、隐藏层、输出层和一个损失层。我们简单地遵循计算图来计算所有值。然后,我们通过沿着这些边反向传播梯度来计算导数,并再次使用动态规划来计算所有这些梯度。

然而,我们需要为每个数据点进行一次前向和反向传播。如果我们想计算损失函数的梯度,而损失函数当然是相对于整个数据集的,并且需要在整个数据集上进行损失最小化,那么我们需要为训练集中的每个数据点或数据样本 (xᵢ, yᵢ) 计算损失函数关于参数的梯度。这对应于最大似然估计。

随机梯度下降 (SGD)

那么梯度下降算法是如何工作的呢?首先,我们将权重初始化为某个随机值。我们应该巧妙地做到这一点。有各种技术可以为神经网络正确初始化,例如 Xavier 或 He 初始化。然后我们选择一个学习率 η

然后,对于我们训练集中的所有数据点,我们通过前向传播将训练元素 x 通过网络以计算相应的预测,然后通过反向传播获得梯度。然后我们使用梯度更新规则更新梯度。如果验证误差减小,我们转到步骤 2,否则我们认为已经收敛。

然而,这样做的挑战在于,通常有数百万个参数,所以 W 的维度非常大。而且,通常也有数百万个训练点。因此,计算总和非常慢,变得极其昂贵,有时甚至无法装入内存。

那么,我们能做什么?解决这个问题的方案叫做随机梯度下降

其思想如下:整个训练集上的总损失可以表示为一个期望值。所以,这是 1/N(N 是训练集大小)乘以所有损失函数的总和,这里为了简洁明了,省略了 xy,直接将索引加到 L 上。所以,这当然是损失函数在数据分布上的期望。

这个期望可以用一个更小的子集来近似,其中子集 B 的基数远小于整个训练集的基数(可能是数百万张图像),B 可能只有 64、32 等。这被称为小批量大小。因此,我们通过基于采样的估计来近似这里的期望,我们只需采样子集 B,并计算损失函数的平均值。因此,梯度也可以用这个子集来近似,所以我们也可以计算这个的梯度,它近似于我们实际想要计算的梯度。这就是小批量梯度

随机梯度下降的工作方式如下,与之前非常相似,但现在使用小批量:

  1. 初始化权重。
  2. 选择学习率和小批量大小 B
  3. 在每次迭代中,从整个训练集中随机抽取大小为 B 的小批量。
  4. 对于所有小批量元素,通过前向传播将输入通过网络以计算预测。
  5. 然后通过反向传播获得批量元素梯度。
  6. 然后更新梯度。
  7. 如果验证误差减小,转到步骤 3,否则停止。

现在,这比以前快得多,因为当然,这里我们只对 B 个批量元素进行这个内部循环,而不是对整个训练集进行。

随机梯度下降有很多变体。其中一些使用一些技巧来更好地工作,例如带动量的 SGD、Nesterov 动量、RMSprop 或 Adam。Adam 由于结合了动量和梯度缩放,具有鲁棒性,是迄今为止最常见的选择之一。

学习率调度

如何设置学习率也很重要。固定的学习率通常在训练开始时太慢,在训练后期太快。因此,典型的学习率调度会调整学习率。它们以较高的学习率开始,然后在训练过程中降低学习率。

有不同的方法可以做到这一点。例如,可以使用指数衰减,或者一种非常传统、标准的方法是每隔一定迭代次数(比如每 K 次迭代)将学习率减半或逐步降低,如图所示。所以你可以看到,在这个学习率下,误差不再下降。但当我们改变学习率时,误差率会急剧下降。然后在这里再次发生。所以,适当地调整学习率确实有影响。

正则化

正则化当然很重要,因为我们处理的是一个具有许多参数的高容量模型。众所周知,如果我们的参数太少,模型会欠拟合,容量太低。另一方面,如果参数太多,那么我们会过拟合。我们很好地拟合了绿色的训练点,但没有很好地拟合蓝色的测试点。

这里的出路是正则化。我们取一个原本会自然过拟合的模型(来自第三个区域),但通过应用正则化器,将其带到第二个区域。

同样,有多种方法可以做到这一点。我将快速介绍其中一些。最常见的是早停。早停是一种非常朴素的方法,通过监控验证损失来避免过拟合,并在验证误差再次开始增加时停止训练。开始时,它下降。然后在某个点,训练损失继续下降,但验证损失开始增加。但我们希望找到验证损失最小的点。因此,我们将训练集分成两部分:训练集和验证集,并使用验证集来监控验证误差。这也可以用图来说明。这里是参数空间(本例中只有两个参数),这里是能量函数(损失函数,绿色)。这是训练损失。W* 是根据训练损失得出的理想参数集,但不是根据验证损失。那么,如果我们早停会发生什么?我们遵循这个轨迹,也许从参数 (0,0) 开始,然后遵循这个轨迹,但我们不会一直沿着训练景观走下去,而是在验证误差开始增加时停在这里。

类似地,我们可以使用 L2 正则化。我们可以直接在参数 W 上施加一个 L2 惩罚,通过将参数 W 的欧几里得范数添加到损失函数中。这个惩罚迫使正则化损失的最小值更接近原点,因此也起到了正则化的作用。这是未正则化的训练目标,其中最优点(最优值)是 W。这些是 L2 正则化器的等值面。而正则化的最优点 是 0 和 W 之间的折衷,在这种情况下位于这里。

Dropout 与数据增强

Dropout 是另一种正则化技术,它利用了集成学习的思想,即让许多不同的网络进行预测并平均这些预测。这里的想法非常简单。在训练期间,我们简单地以一定的概率随机将一些神经元设置为 0。基本上,我们随机抽取的每个二元 Dropout 掩码,在每次训练迭代中都会随机变化,因此从同一个神经网络中动态创建了一个新的神经网络。从而避免了神经网络权重的共同适应,并从具有共享参数的单个网络中动态创建集成,使模型在测试时泛化得更好。

在训练神经网络时,同样非常重要(正如你将在本课程相关的编程挑战中看到的那样)的是数据增强。实现更好泛化的最佳方法是使用更多数据进行训练。一切都与数据、数据、数据、数据有关。数据就是一切。

但在实践中,数据集通常是有限的。即使你有一个模拟器,通常也很难创建无限量的数据。现实中更是如此。数据增强的目标是从现有数据中动态创建虚假数据。

并将其添加到训练集中,我们通过稍微扰动数据来实现这一点,例如通过一些仿射变换、添加噪声、稍微改变输入的颜色或丢弃输入的某些区域。

重要的是,新数据也必须保留语义。如果我想预测特定的动物,那么当然,输入图像中的动物应该能被人类识别,它不应该变成不同的动物。例如,如果我有一个字符“6”,把它倒过来就变成了“9”,所以这是我不应该做的增强。但即使是像平移或添加逐像素噪声这样非常简单的操作,通常也能极大地改善泛化能力,这是你应该始终考虑的。

在自动驾驶的情况下,改变摄像机的视角也很有帮助,这在模拟中也很容易做到。有一些好的库可以使用,可以直接从你的数据中提供增强数据。

总结

本节课中我们一起学习了深度学习的基础回顾,涵盖了监督学习、线性与非线性分类、多层感知机、卷积神经网络的核心概念,以及训练神经网络的关键技术:梯度下降、随机梯度下降、学习率调度和各种正则化方法(如早停、L2正则化、Dropout和数据增强)。这些知识是理解后续自动驾驶算法,特别是模仿学习的基础。

006:模仿学习 🚗

在本节课中,我们将要学习模仿学习的核心概念。模仿学习是一种让智能体通过观察专家演示来学习决策策略的方法。我们将从定义问题开始,介绍其基本形式,并探讨两种主要范式:行为克隆和更通用的模仿学习。最后,我们将通过一些实际应用案例来加深理解。


模仿学习的定义与动机

上一节我们介绍了模仿学习的背景,本节中我们来看看其正式定义。

模仿学习的动机在于,为复杂任务(如自动驾驶)手动编写策略通常非常困难。因此,我们采用数据驱动的方法。我们获取专家的演示数据,目标是训练一个策略来模仿专家所做的决策。

以下是模仿学习涉及的核心概念:

  • 状态 (S):智能体观察到的信息。例如,在自动驾驶中,状态可以是车辆摄像头拍摄的图像。状态可以是完全观测或部分观测的。
  • 动作 (A):智能体可以执行的操作。例如,转向角或油门/刹车指令。动作可以是离散的或连续的。
  • 策略 (π):一个由参数 θ 决定的函数,它将状态映射到动作。我们的目标是学习这些参数。
  • 最优动作 (A*):专家演示者在特定状态下提供的动作。
  • 最优策略 (π*):专家的策略,对于任何输入状态 S 都能给出最优动作 A*。
  • 状态动态:模拟器或环境模型。给定当前状态 S_i 和动作 A_i,它决定下一个状态 S_{i+1}。这可以是确定性的或概率性的。
  • 轨迹展开:给定一个起始状态 S_0,按照策略 π 依次执行动作,生成一系列状态和动作对的过程。
  • 损失函数 (L):用于衡量策略输出的动作 A 与专家最优动作 A* 之间的差异。

通用模仿学习与行为克隆

基于以上定义,我们现在可以正式定义模仿学习。我们从最通用的设置开始。

通用模仿学习

通用模仿学习的目标是找到策略参数 θ,以最小化以下期望值:

公式:min_θ E_{s~p(s|π_θ)} [ L( A*, π_θ(s) ) ]

这个公式的含义是:最小化策略 π_θ 在所有可能到达的状态分布 p(s|π_θ) 下,其动作与专家动作之间的期望损失。

关键在于,这里的状态分布 p(s|π_θ) 取决于当前策略 π_θ 本身。这意味着在训练过程中,我们需要根据当前策略进行轨迹展开来采样状态,形成一个循环依赖:策略影响状态分布,而状态分布又用于评估和更新策略。这种方法更接近真实的交互过程,但实现起来更复杂,通常需要能够随时查询专家。

行为克隆

行为克隆是模仿学习的一个简化且更常用的变体。它的目标函数如下:

公式:min_θ E_{(s, a*)~p*(s, a*)} [ L( a*, π_θ(s) ) ]

这里的关键区别在于,期望是在一个固定的、由专家演示生成的数据集分布 p*(s, a*) 上计算的。我们不再根据当前策略采样状态,而是直接使用预先收集好的专家状态-动作对。

因此,行为克隆将模仿学习问题简化为了一个监督学习问题。我们只需拟合一个函数(例如神经网络),使其在固定数据集上,将输入状态映射到输出动作的误差最小化。


行为克隆的挑战与改进方法

行为克隆虽然简单,但存在一个根本性问题:训练与测试的分布不匹配

行为克隆假设训练数据(专家演示的状态)是独立同分布的。然而,当我们部署训练好的策略时,它并不完美,可能会犯错误,导致进入一个专家从未演示过的新状态。由于策略没有学习过如何从这种“错误”状态中恢复,它可能会做出更糟糕的决策,从而进一步偏离专家轨迹,最终导致灾难性失败。这种现象称为分布漂移

改进方法:DAgger

为了克服上述问题,一种流行的方法是 DAgger。它的核心思想是在行为克隆和通用模仿学习之间取得平衡。

以下是DAgger的基本步骤:

  1. 使用初始的专家演示数据集训练一个策略。
  2. 使用当前策略进行轨迹展开,收集新的“在策略”数据(即策略实际遇到的状态)。
  3. 请专家为这些新收集的状态提供正确的动作标签。
  4. 将新标注的数据与原始数据集合并。
  5. 用合并后的数据集重新训练策略。
  6. 重复步骤2-5。

通过迭代地让专家标注策略实际遇到的状态,DAgger逐步构建了一个更能代表策略最终状态分布的数据集,从而缓解了分布不匹配的问题。

针对自动驾驶的增强:关键状态采样与回放缓冲区

在自动驾驶场景中,直接应用DAgger可能效果不佳,因为驾驶数据极度不平衡(例如,直行数据远多于转弯数据)。我们提出了一种增强方法:

  • 关键状态采样:不从所有“在策略”数据中均匀采样,而是根据某些准则(如策略的不确定性、动作的熵等)选择对策略提升最有价值的“关键”状态(如转弯、并线场景)请专家标注。
  • 回放缓冲区:为了避免一次性加入过多困难样本导致训练不稳定,我们使用一个回放缓冲区。它逐步地将关键状态混合到训练数据中,并定期重放旧数据,确保训练的稳定性。

模仿学习的应用实例

现在,让我们看一些模仿学习在实际中的应用。

ALVINN (1989)

这是一个开创性的工作。ALVINN使用一个仅有三层、约3.6万个参数的简单神经网络,将低分辨率道路图像映射到离散的转向指令。它在模拟图像上训练,并成功在真实道路上完成了长达90英里的自动驾驶测试。

NVIDIA PilotNet (2016)

这是ALVINN的现代版本。PilotNet使用更复杂的卷积神经网络架构(受AlexNet启发,约25万个参数),并利用多摄像头数据进行数据增强,以获取更多样化的状态信息。它在一个真实的车辆上进行了演示。

为了理解这个“端到端”网络内部是如何决策的,研究人员采用了可视化反向传播技术。该技术能够高亮显示输入图像中对网络最终决策影响最大的区域。实验表明,被高亮的区域(如车道线)的移动会显著影响网络输出的转向角,而背景区域的移动则影响很小,这证明网络确实学习到了与驾驶决策相关的视觉特征。


总结

本节课中,我们一起学习了模仿学习的核心内容。我们首先定义了状态、动作、策略等基本概念,并区分了通用模仿学习行为克隆这两种范式。我们认识到行为克隆虽然简单,但存在分布不匹配的根本缺陷。为此,我们介绍了DAgger算法及其针对自动驾驶场景的增强版本(关键状态采样与回放缓冲区)。最后,我们通过ALVINNNVIDIA PilotNet这两个里程碑式的实例,看到了模仿学习在自动驾驶领域的成功应用与发展。模仿学习为复杂决策任务的策略获取提供了一条有效的数据驱动途径。

007:条件模仿学习 🚗

在本节课中,我们将要学习条件模仿学习。这是一种用于自动驾驶的高级模仿学习方法,它通过引入额外的导航指令来解决传统模仿学习在交叉路口等场景中面临的决策模糊性问题。

概述

上一节我们介绍了模仿学习的基本概念。本节中我们来看看条件模仿学习。在某些与自动驾驶相关的场景中,单纯的模仿学习是不够的。例如,在交叉路口,智能体可能有多个有效的行动或轨迹可以选择。如果没有额外的输入信息来指示去向,智能体就无法唯一地确定一个特定的行动。条件模仿学习的核心思想非常简单:除了状态之外,我们还向智能体提供一个条件信号,告诉它在下一个交叉路口应该做什么。例如,“在下一个路口直行”、“左转”或“右转”。利用这个额外的条件信号,行动就变得唯一了,模仿学习又可以正常工作了。这在城市驾驶场景中尤其重要,因为其中涉及变道或转弯。

条件模仿学习架构

以下是条件模仿学习的一个示意性概述。我们有一个策略(在相关论文中被称为控制器)。我们让这个控制器或策略同时基于观察(即状态 S)和导航命令 C 进行条件化。导航命令可以是“在下一个路口左转”、“右转”或“直行”。基于这两个输入,控制器可以发出一个行动,该行动通过状态分布改变环境的状态,从而产生一个新的状态,该状态再次输入到控制器中。

这种高级导航命令相对容易获取,因为现代GPS导航系统已经提供了这些信息。它们会告诉我们该做什么。这也是我们作为人类驾驶员在不熟悉的城市中驾驶时所需的输入信号。我们可以使用标准的消费级GPS,它不需要高清地图,传统地图就足够了,只需告诉车辆在下一个路口左转、右转或直行。这完全消除了由环境引入的任务模糊性。

在这个具体案例中,观察 O 是当前图像,行动 A 是转向角和加速度。这种方法首次在2018年ICRA会议上发表的论文《通过条件模仿学习进行端到端驾驶》中实现。

与朴素行为克隆的对比

让我们比较一下朴素的行为克隆和条件模仿学习(后者也是一种行为克隆,但被称为条件模仿学习)。

在左侧是行为克隆。我们有一个训练集,它是由专家演示者提供的 N 帧图像的状态-行动对数据集。目标是最小化一个损失函数,该函数最小化专家行动与策略针对相应状态返回的行动之间的差异。这里的假设是存在一个函数 F,当给定输入状态 S 时,该函数返回一个特定的行动 A。然而,这个假设在实践中常常被违背,例如在交叉路口,对于某个特定状态,可能存在多个有效行动。

相比之下,在条件模仿学习中,训练集通过额外的导航控制命令得到了增强。因此,数据集现在由三元组组成:对于每一帧,我们有专家行动 A、专家状态 S 和来自GPS的相应导航命令 C。目标也发生了变化:现在策略的输入是 SC,而不是左侧的仅 S。这里的假设是存在一个将 SC 映射到 A 的函数。这是一个更好、更合理的假设,因为它在定义状态时更加唯一。

网络架构

原始论文(ICRA 2018)描述了两种网络架构。它们差异不大,但略有不同,因此我想简要解释一下两者。

第一种架构(左侧)包含一个图像编码器、一些通过浅层MLP编码的测量值 M(例如车速)以及导航命令 C。这些信息随后被拼接起来,并由另一个网络来预测行动 A

第二种架构(右侧)是先将图像和测量值拼接,然后由导航命令 C 在三个不同的专用子网络中进行选择,被激活的子网络基于其输入返回行动 A。测量值 M 在这篇论文中仅考虑了车辆的速度,这对于系统是一个有用的输入。如果只提供单张图像,算法将无法知道车辆是静止还是在行驶,因此提供速度信息很重要。

数据增强与因果混淆

该论文还引入了噪声进行数据增强。具体做法是向方向盘注入噪声,然后让专家(人类演示者)驾驶以纠正方向。虽然这很累人,只能收集几分钟的数据,但它有助于缓解行为克隆的一个问题,而条件模仿学习也在一定程度上解决了这个问题。你可以看到噪声是如何被注入的,然后人类如何向相反方向转向以抵消噪声,使车辆回到道路上,最终得到修正后的转向信号。

仿真环境与实验结果

现在,让我们看一些结果。我们将关注Carla仿真器,这是一个比我们在练习中使用的AirSim环境更复杂的仿真环境,它是全3D且具有一定程度的照片级真实感。在2018-2019年的早期工作中,该仿真器包含两个城镇:一个训练镇和一个测试镇。训练镇用于训练智能体,然后智能体被部署在测试镇,以测试其泛化能力。现代版本的Carla仿真器现在包含多达10个城镇,甚至有一个在线排行榜,人们可以提交他们的算法和智能体,类似于你们将提交智能体参与我们课程的排行榜。

Carla仿真器的优点是完全开源,任何人都可以使用,可以在传统消费级GPU上运行,并提供许多资源和环境,以及不同的传感器模态(如激光雷达、RGB相机等)。2019年在该仿真器数据集上的最先进方法称为“CILRS”,它探索了行为克隆在自动驾驶中的局限性(ICCV 2019论文)。其架构与之前的类似,当然也使用导航命令作为输入。但为了克服所谓的“因果混淆”问题,它采取了一些措施。

因果混淆问题是指在自动驾驶的模仿学习中,行动的真实原因常常与错误的原因混淆。例如,当车辆静止且交通灯变绿时,车辆可能不会将交通灯变绿视为启动的原因,因为前一帧静止与下一帧很可能也静止之间的相关性非常高,因此车辆会保持静止。克服这个问题有多种方法,其中之一是除了将速度作为输入外,还尝试让策略预测速度,这可以在一定程度上缓解因果混淆问题。

最新进展:结合注意力与鸟瞰图

我们研究小组的一项较新工作将条件模仿学习的理念更进一步,将其与隐式表示和注意力机制相结合。注意力很重要,因为自动驾驶系统的输入维度非常高(每秒多帧、高分辨率多图像),需要高效地缩小范围,聚焦于当前驾驶情境中重要的部分。这就是我们在这个模型中尝试做的。我们有一个多层感知机,可以用特定位置进行查询,并基于注意力迭代地将高维输入压缩成紧凑的表示 C。你可以看到这些注意力图,它们根据模型在当前迭代中认为对做出下一个决策重要的内容来查询输入。

该模型密集地预测航路点偏移和语义信息,这是在物理鸟瞰图视角下进行学习。我们发现,在鸟瞰图空间(车辆控制实际发生的空间)而非图像空间预测信息也很有用。在这里,我们预测航路点或航路点偏移,从而推导出航路点。在此基础上,我们使用一个更经典的控制器,根据预测的航路点来操控车辆。这是目前进行模仿学习的最先进方法之一。我们实际上不再模仿行动,而是模仿轨迹,然后使用传统的控制器,因为它们在自动驾驶中效果很好,我们无需重新学习。

总结

本节课中我们一起学习了条件模仿学习。模仿学习在自动驾驶中的优势在于易于实现、标注成本低(只需记录驾驶时的图像和行动),并且整个模型可以端到端训练。条件模仿学习可以消除交叉路口的模糊性,并成功通过交叉路口。

然而,模仿学习仍面临一些挑战。行为克隆使用的独立同分布假设在实践中常被违背。从图像到控制的直接映射在基本实现形式中不允许进行长期规划。在标准模型中,也没有真正的记忆机制来记住速度等信息,除非显式地将记忆纳入模型。此外,学习到的映射关系难以解释,因此我们需要良好的可视化技术来更好地理解模型在做什么,或者像最后展示的模型那样,融入注意力等机制,使内省自动构建到模型中。

这就是今天的全部内容。谢谢。

008:直接感知

在本节课中,我们将要学习自动驾驶中的“直接感知”方法。这是一种介于模块化流水线和端到端学习之间的混合方法,旨在结合两者的优点。

概述

直接感知方法的核心思想是,使用一个神经网络将传感器输入(如图像)映射到一个低维的中间表示,这个表示包含了驾驶决策所需的充分统计信息。然后,一个独立的控制器模块根据这个中间表示来生成车辆的控制指令。这种方法将感知与规划、控制解耦,既保持了模型的可解释性,又允许进行端到端的优化。

直接感知的概念

上一节我们介绍了模块化流水线和端到端学习两种方法。本节中,我们来看看它们的混合体——直接感知。

我们目前已经见过两种自动驾驶方法。一种是模块化流水线,它由多个独立模块组成,例如低级感知、场景解析、路径规划和车辆控制。模块化流水线的优势在于其模块化特性,可以由不同的大型团队独立开发,并且由于接口是人工设计的,因此具有可解释性。然而,其缺点是需要大量专家决策,且难以进行端到端学习。

另一种是端到端学习方法,它使用一个单一的整体机器学习模型(如神经网络)直接将传感器输入映射到车辆控制指令。这种方法模型简单,可以进行端到端训练,但通常泛化能力较差、数据需求量大且可解释性低。

直接感知是介于这两种方法之间的一种混合方法。它仍然是模块化的,但比传统的模块化流水线更简洁。它引入了一个中间表示:一个神经网络将传感器输入映射到这个低维的中间表示,然后一个车辆控制器根据这个表示来预测车辆的低级控制指令。这样,我们仍然拥有一个相对简单的系统,但有效地将感知与规划和控制解耦了。这既有利于提高模型的可解释性,也可能因为控制器没有与感知模型联合训练而获得更好的泛化能力。此外,它还允许我们利用经典的控制器(如PID控制器或有限状态机)或学习型控制器。

一个具体模型:学习自动驾驶的直接感知可供性

接下来,我们来看一个实现了这一范式的具体模型。我们将关注2015年的一篇论文《Learning Affordance for Direct Perception in Autonomous Driving》。

该论文的目标是实现一个用于高速公路驾驶的直接感知控制器,并在模拟环境中进行测试。其核心思想是预测一组“可供性”。可供性是一个源自心理学的术语,描述了环境中限制可能行动空间的属性。简单来说,它就是为智能体做出决策所需的、关于观测状态的充分统计信息。

在这篇论文中,作者为在一条三车道高速公路上驾驶设计了13个特定的可供性。第一个可供性是车辆相对于道路的角度,这对于转向至关重要。其余可供性根据车辆所处的两种状态(“车道内”状态和“压线”状态)而有所不同。

以下是两种状态下相关的可供性:

  • 当车辆处于“车道内”状态(位于两条车道线之间)时

    • 到左侧车道线的距离。
    • 到左侧相邻车道左侧车道线的距离。
    • 到右侧车道线的距离。
    • 到右侧相邻车道右侧车道线的距离。
    • 到当前车道前车的距离。
    • 到左侧车道前车的距离。
    • 到右侧车道前车的距离。
  • 当车辆处于“压线”状态(行驶在车道线上)时

    • 到左侧车道线的距离。
    • 到当前所压车道线的距离。
    • 到右侧车道线的距离。
    • 到左侧车道前车的距离。
    • 到右侧车道前车的距离。

系统在TORCS模拟器(一个开源赛车游戏环境)中实现、训练和评估。感知网络采用了简单的AlexNet架构,包含5个卷积层和4个全连接层,输出13个神经元对应13个可供性。训练采用简单的监督学习,使用L2损失函数,真值由模拟器提供。

控制器设计

现在,我们来看看如何利用预测出的可供性来控制车辆。论文中实现了一个简单的手工设计控制器。

控制器逻辑是一个有限状态机。在自动驾驶模式下,控制器读取感知模型输出的可供性指标,并检查左右车道是否可用。其决策逻辑如下:如果正在接近同一车道的前车,且左侧车道存在、可用并允许变道,则变道至左侧;否则,如果右侧车道满足条件,则变道至右侧;如果都无法变道,则减速。

具体控制指令的计算公式如下:

转向控制器
steering_command = θ₁ * relative_angle + (distance_to_center_line / road_width)
其中,relative_angle是车辆相对于道路切线的角度,distance_to_center_line是车辆到目标车道中心线的距离。这是一个线性控制器,旨在减小角度偏差和横向偏移。

速度控制器(最优速度跟车模型)
target_velocity = V_max * [1 - exp( -θ₂ * (distance_to_preceding_car - θ₃) )]
其中,V_max是最大允许速度,distance_to_preceding_car是到前车的距离。当前车很远时,目标速度接近V_max;当前车很近时,车辆会减速以避免碰撞。

这个简单的控制器虽然可能导致驾驶行为不够平滑,但在模拟环境中能够实现基本的跟车、变道等高速公路驾驶功能,展示了直接感知方法的可行性。

模型评估与可视化

该模型在TORCS模拟器中进行了评估。演示视频显示,车辆能够根据预测的可供性做出合理的驾驶决策,例如在接近前车且左侧车道空闲时执行变道。

为了理解感知网络内部的工作机制,作者使用了标准的网络可视化技术。例如,通过可视化第一个全连接层中特定神经元被激活程度最高的平均图像,可以发现网络学会了将相似的驾驶状态(如空旷道路、前方有车、准备变道等)进行聚类。此外,通过可视化卷积层的最大响应区域,可以看到网络能够聚焦于场景中的相关部分,如其他车辆和车道线。这些事后分析有助于提高直接感知模型的可解释性。

总结

本节课中,我们一起学习了自动驾驶中的直接感知方法。我们了解了它作为模块化流水线与端到端学习之间桥梁的定位,其核心是通过学习一个低维的中间表示(可供性)来解耦感知与控制。我们深入分析了一个具体实现模型,包括其定义的13个高速公路驾驶可供性、使用的AlexNet网络架构、以及基于有限状态机和简单公式的手工控制器设计。最后,我们看到了该模型在模拟器中的表现以及通过可视化技术对其内部工作机制的洞察。直接感知方法为实现可解释、可泛化且能进行端到端优化的自动驾驶系统提供了一条有希望的路径。

010:直接感知 - 视觉抽象

在本节课中,我们将探讨如何为自动驾驶系统选择合适的中间视觉表示。我们将分析不同视觉抽象方法的优劣,并研究如何在保证性能的同时,高效地获取训练数据。

概述

我们已经了解到,中间表示对于解耦感知与规划控制非常有用。然而,核心问题在于如何精确地选择这些中间表示。之前我们看到的模型使用了人工设计的低维可供性,但这不可避免地引入了人为设计误差。因此,我们能否使用更通用的中间表示,例如单目深度估计、立体视觉估计或语义分割等标准计算机视觉任务,来提高自动驾驶智能体的鲁棒性?如果使用这些表示,我们如何高效地学习感知模块?为了稳健地学习预测这些表示的模型,我们需要多少标注数据?这正是本单元将要探讨的内容。

视觉抽象的重要性

2019年,Sidel等人发表了一篇文章,探讨了计算机视觉对于机器人行动的重要性。他们分析了多种中间表示,包括语义分割、深度估计、法线预测、光流估计和反照率预测,评估它们对实现稳健驾驶行为的能力。

研究发现,中间表示通常能改善结果和泛化能力,并且在不同模拟环境和任务中都能带来一致的性能提升。特别是在自动驾驶场景中,深度信息和语义分割带来的提升最大:深度信息在越野驾驶中作用显著,因为几何结构至关重要;而语义分割在城市驾驶中非常有用,因为城市场景中的语义类别比越野环境更容易区分。

视觉抽象的特性

那么,一个好的视觉抽象应具备哪些特性?

首先,它必须具有不变性,能够对策略隐藏不相关的变异。如下图所示,对于一个室内场景,如果我们直接比较两张图像的像素空间,它们差异很大。然而,如果使用语义分割作为中间表示,在特征空间中,训练和测试数据的分布会重叠得更多,因为原始图像中不相关的、与度量无关的变异已被抽象掉。从语义分割图来看,这两张图像看起来几乎相同。

其次,一个好的视觉抽象应该是通用的,适用于广泛场景,能够解决我们在模拟器或真实世界自动驾驶中可能遇到的所有任务。它应该是状态的充分统计量。

当然,它还应是数据高效的,不需要太多内存和计算来生成。同时,它必须是标注高效的,即训练用于预测中间表示的感知模块时,所需的标注工作量相对较小。这是我们近期工作中关注的一个方面。

选择语义分割作为抽象

我们选择语义分割作为视觉抽象,因为研究发现它能编码任务相关知识(例如,道路是可行驶的)以及先验知识(例如,相关像素的分组)。此外,它可以使用标准的二维卷积策略网络进行处理,易于部署。

然而,语义分割的缺点是标注耗时。例如,为Cityscapes数据集中的单张图像进行标注,标注员需要90分钟。如果要标注成千上万甚至数百万张图像,成本会非常高昂。因此,拥有一个标注高效的视觉抽象至关重要。

高效标注的视觉抽象研究

我们在2020年IROS上发表的一项名为《Label Efficient Visual Abstractions for Autonomous Driving》的工作中探讨了这个问题。我们提出的问题是:

  • 标注时间与驾驶性能之间如何权衡?
  • 选择特定的语义类别是否能简化策略学习?
  • 用少量图像训练的视觉抽象是否具有竞争力?
  • 像Cityscapes基准测试中那样的细粒度标注是否真的重要?
  • 视觉抽象能否减少训练方差(这是训练端到端驾驶模型时的常见问题)?

模型架构

我们考虑一个标准的视觉抽象模型。输入图像(状态或观测 S)通过一个参数为 ψ 的视觉抽象网络 A 转换为视觉抽象 R。然后,该视觉抽象再通过一个控制策略 π(参数为 θ)转换为控制命令 A,同时策略也考虑高层GPS导航指令 C 和输入速度 v。最终输出是动作 A

用公式表示,动作 A 由这两个函数的复合得到:
A = π(A(S), C, v)

训练数据与流程

训练这两个模型需要标注数据:

  1. 表示数据集 R:包含输入图像和语义真值标签图,用于训练视觉抽象网络 A。这个数据集通常较小,因为标注成本高。
  2. 动作数据集 A:包含输入图像和对应的专家控制命令(如方向盘转角、加速度),用于训练控制策略 π。这个数据集可以很大,因为获取动作标签相对容易。

训练流程如下:

  • 首先,使用较小的语义标注数据集 R 训练视觉抽象网络 A
  • 然后,将此网络应用于所有驾驶过程中采集的输入图像,生成对应的视觉抽象 R,并与车辆传感器测量的真实控制信号结合,形成一个庞大的控制数据集。
  • 最后,使用这个大型控制数据集来训练控制策略 π

这样,我们就用一个小数据集训练了抽象网络,用一个大数据集训练了策略。

使用的模型与损失

我们使用了2019年的先进模型——条件模仿学习模型(CILRS)。其输入是视觉抽象 R(而非原始图像)、导航指令 C 和车辆速度 v。事实证明,单帧图像加上车辆速度足以构成城市驾驶中状态的充分统计量。输出是控制动作 A 和预测的速度 v_pred(后者用作正则化器,以避免因果混淆问题)。

我们优化标准的模仿学习损失,最小化预测动作与真实动作、预测速度与真实速度之间的差异。

实验设计与结果分析

我们设计了不同的视觉抽象进行比较:

  1. 特权分割:使用模拟器提供的语义分割真值作为输入,作为性能上界。
  2. 推断分割(14类):使用在14个类别上训练的最先进语义分割模型预测的分割图。
  3. 推断分割(6类):仅在6个我们认为对自动驾驶最相关的类别(道路、车道线、其他车辆、行人、绿灯、红灯)上训练的分割模型。
  4. 混合表示:对两个“物体”类别(道路、车道线)使用分割模型,对四个“物体”类别(车辆、行人、红灯、绿灯)仅使用边界框检测器。这可以大幅降低标注难度。

我们在CARLA模拟器的“无碰撞”基准上进行评估,设置了不同交通密度的场景。

关键发现

  • 类别数量的影响:从14个类别减少到6个类别,驾驶性能没有显著下降,甚至在部分场景中有所提升。这表明,让策略专注于相关类别,避免被无关信息分散注意力,可能更有益。然而,移除车道线会导致性能急剧下降,证实了车道线信息对驾驶至关重要。
  • 标注粒度的影响:使用混合表示(边界框+分割)的性能与标准分割表示相当,在困难场景中甚至略有提升。同时,其标注时间从每图像约300秒大幅减少到20秒。
  • 数据效率:研究表明,明智地选择视觉表示和类别,比单纯标注更多图像更重要。例如,使用1600张粗标注图像(混合表示,6类)训练的模型,其策略成功率(58%)甚至高于使用6400张细标注图像(14类)的模型(50%),而总标注时间从7500小时锐减到仅50小时。

总结

本节课我们一起学习了视觉抽象在自动驾驶中的关键作用。一个好的视觉抽象应具备不变性、通用性、数据高效和标注高效等特性。通过具体研究,我们发现语义分割是一种有效的抽象方式,但通过精心选择关键语义类别(如道路、车道线、车辆、行人、交通灯)并采用混合表示(结合分割与检测),可以在维持甚至提升驾驶性能的同时,极大降低模型对标注数据量和精细度的需求。这为构建更实用、更高效的自动驾驶感知系统提供了重要指导。核心在于,质量重于数量——智能地设计中间表示比盲目收集更多标注数据更为有效。

011:通过模块化与抽象实现驾驶策略迁移 🚗➡️🌍

在本节课中,我们将要学习如何通过模块化和抽象的方法,将在模拟器中学习的驾驶策略迁移到现实世界的车辆上,以解决策略迁移效果不佳的问题。

概述

我们已经了解了中间表示对于解耦感知与规划控制非常有用,这能让策略学习变得更容易。然而,并非所有硬件都相同。如果你希望将模拟器中学习的驾驶策略迁移到现实世界运行的车辆上,进一步将控制与规划解耦也很有帮助。这正是2018年CoRL会议上发表的论文《Driving Policy Transfer via Modularity and Abstraction》所研究和提出的方法。

核心问题与方法

上一节我们讨论了中间表示的作用,本节中我们来看看一种更进一步的模块化方案。论文考虑的核心问题是:在模拟器中学习的驾驶策略通常无法很好地迁移到现实世界。因此,该论文在“直接感知”理念的基础上,向模块化流程又迈进了一步。

其核心思想是封装驾驶策略。这里的驾驶策略和感知模块仍然是需要学习的神经网络,但通过封装,使得驾驶策略不直接暴露于原始感知输入,也不直接输出底层控制指令。

以下是该方法的整体架构流程:

  1. 输入:一张图像。
  2. 感知模块:生成一个中间表示,在本例中是语义分割图。
  3. 驾驶策略:该策略接收高级GPS导航指令(如“左转”),并基于语义分割图预测一系列路径点。
  4. 控制器:一个PID控制器接收这些路径点,并生成车辆所需的底层控制指令(转向和加速/刹车)。

这种方法的优势在于,当要将策略应用到新车辆时,只需替换控制器部分,而无需重新训练或微调驾驶策略本身。控制器通常参数不多,且我们对车辆的低层控制器(如ESP、自动刹车系统)已有深入理解,因此适配相对容易。

策略解耦的优势

通过这种设计,驾驶策略通过路径点表示,与具体的控制指令解耦;同时,通过语义分割图,也与原始的图像输入解耦。这意味着,对于新的场景或车辆,只需替换感知模块和控制器,而执行实际驾驶任务的策略核心可以保持不变。

所使用的具体表示是:输入为语义分割图,输出为两个路径点。第一个路径点用于转向控制,第二个路径点用于在转弯前刹车。随后,一个PD控制器会尝试基于这些路径点来跟随车道或道路。

实验结果与分析

以下是该论文的核心结果。论文进行了消融研究,比较了模型的不同变体:

  • 图像 -> 控制:直接从输入图像映射到控制指令。
  • 图像 -> 路径点:从图像映射到路径点。
  • 语义分割 -> 控制:从语义分割图直接映射到控制指令。
  • 完整流程:图像 -> 语义分割 -> 路径点 -> 控制指令(即论文提出的方法)。

研究所用的驾驶策略是标准的条件模仿学习策略(分支版本),控制器则是一个用于横向(转向)和纵向(加速/刹车)控制的PID控制器。

研究结果显示,特别是在泛化能力(上图中绿色和金色柱状图,代表训练时未见过的新城镇和新天气条件)方面,采用这种完全封装的、模块化和抽象化的策略性能最佳。这确实证明,封装策略有助于获得更好的泛化性能。

实际演示与应用

该项目还提供了一个精彩的演示视频,展示了其实际效果:

“在这项工作中,我们在模拟器中训练了一个驾驶策略,然后无需任何微调,便将其部署到物理世界的车辆上。车辆基于语义分割图和高层指令(如在下一个路口左转)进行驾驶。因此,我们的驾驶策略不仅能够跟随车道,还能根据高层规划器或操作员的指令进行各种转弯。更重要的是,我们的驾驶策略能够泛化到各种先前未见过的环境。”

该方法通过模块化和抽象来解决迁移问题,结合了深度学习和经典模块化自动驾驶流程的优势。其架构包含三个模块:感知模块驾驶策略底层控制器

研究首先在CARLA模拟器中验证了系统。在CARLA的Town 1、Weather 1环境中训练后,驾驶策略在该设定下表现良好。值得注意的是,分割网络是在Cityscapes数据集上训练的,因此在CARLA中提供的是有噪声的分割图,这是为了迫使驾驶策略学习泛化能力和对噪声的鲁棒性。

随后,在视觉上差异很大的CARLA Town 2、Weather 2环境中进行测试,模型展现了良好的泛化性能。

接着,该系统被部署到真实世界的机器人车辆上,在多样化的城市环境中进行测试:

测试涵盖了不同的环境和天气条件,包括欧洲阴天干燥的路面,以及冬季湿滑积雪的路面。

模型还在不同大陆、环境迥异、阳光明媚的条件下进行了评估。尽管背景纹理、光照条件和道路宽度差异巨大,学习到的驾驶策略依然能够良好泛化。该策略能够完成各种转弯,并成功跑完数条约1公里长的路线。

总结

本节课中,我们一起学习了一种通过模块化抽象来实现驾驶策略迁移的方法。该方法通过引入语义分割作为中间表示,并让驾驶策略输出路径点而非直接的控制指令,有效地解耦了感知、规划与控制。这种设计显著提升了策略从模拟环境到真实世界的泛化能力,并且只需适配少量的控制器参数即可应用于新车辆,为实现更鲁棒、可迁移的自动驾驶系统提供了有力的思路。

012:直接感知 - 在线与离线评估 🚗

在本节课中,我们将讨论自动驾驶智能体的评估方法。具体来说,我们将重点分析在线评估与所谓的离线评估之间的区别,并探讨一篇相关论文的研究结果。


概述

评估自动驾驶系统是开发过程中的关键环节。理想情况下,我们希望进行纯粹的在线评估,即在真实或模拟环境中让车辆实际运行。然而,这种方法成本高昂且存在风险。因此,研究论文中常使用基于预录制数据集的离线评估指标。本节我们将探讨这两种评估方式的差异,并分析离线指标在预测实际驾驶性能方面的有效性。


在线评估与离线评估

上一节我们介绍了直接感知方法,本节我们来看看如何评估基于这些方法构建的驾驶模型。

在理想情况下,我们当然希望进行纯粹的在线评估。这意味着使用真实车辆在真实世界环境或我们希望评估车辆的模拟环境中进行闭环测试。

然而,在现实世界中,这种方法既昂贵又危险。运营成千上万辆汽车仅用于测试成本高昂,而犯错则可能带来危险。

下图底部展示了在线评估的设置:环境生成观察结果,输入给智能体模型;模型做出预测或执行动作;该动作再次影响环境。如此形成一个闭环。基于模型在真实世界中的驾驶表现,我们可以测量其成功率、到达目标的速度、违规次数等指标。

由于在线评估成本高、风险大,研究论文中经常报告离线评估指标。离线评估指标可以基于预录制的验证数据集计算,因此廉价且易于实施。

上图顶部展示了这种设置:我们有一个预录制的数据集。数据集为我们提供观察结果输入模型,同时也包含真实动作标签。我们可以简单地测量模型预测(例如,预测转向角为-10度或+10度)与该特定数据点的真实转向角之间的误差,并将其作为模型的性能衡量标准。

但核心问题是:离线评估对于我们真正关心的在线任务有多大的预测性?


实证研究:方法与指标

为了探究上述问题,我们将分析一篇论文的实证研究。该研究使用在Carla模拟器中训练的、以均方误差(MSE)作为转向角损失的条件模仿学习智能体。这是一个标准的条件模仿学习设置,具体架构不重要,关键是该研究在在线和离线两种场景下评估了多种智能体,以测量其相关性。

以下是研究中考虑的在线评估指标:

  • 成功率:成功完成的路线百分比。
  • 平均完成度:在发生违规等情况前,车辆覆盖的到目标点平均距离比例。
  • 每公里违规数:两次违规之间的平均行驶距离。

需要说明的是,当前的Carla评估指标已经改进(例如,违规分数和驾驶分数),但这项2018年的工作并未考虑这些新指标。不过,预计其结论仍然具有参考价值。

研究中考虑的离线评估指标(即人们常用来替代在线指标的代理指标)如下。注意,该论文仅研究了转向角相关的指标:

  • 均方误差:衡量预测转向角与真实转向角偏差的平方。公式为 MSE = (a - â)²,其中 a 是真实转向角,â 是预测转向角。
  • 绝对误差:使用L1损失衡量绝对偏差。公式为 L1 = |a - â|
  • 速度加权绝对误差:绝对误差乘以速度进行加权,假设高速下的误差危害更大。
  • 累积速度加权绝对误差:上述误差在一定时间间隔内的累积值。
  • 量化分类误差:首先将转向角量化为一系列离散区间,然后测量分类误差。
  • 相对误差:设定阈值后的相对误差。

研究结果与相关性分析

该论文发现,在线评估指标之间通常具有较高的相关性。

例如,下图绘制了45个不同模型(在数据集大小、数据增强技术、网络架构等方面有差异)的成功率与平均完成度关系。每个点代表一个模型,点的半径表示模型停止训练时的迭代次数。可以看出,成功率与平均完成度,以及与每公里违规数都相关性良好。但每公里违规数与平均完成度之间的相关性稍弱。

然而,当比较在线指标与离线指标时,研究发现所有离线指标与在线指标的相关性都不高。

例如,成功率与转向均方误差、绝对误差或速度加权误差的对比图中,相关性分数(标注在图上)普遍较低。分析表明:

  • 绝对误差比均方误差能更好地作为成功率的代理指标。
  • 但相关性仍然不强,且速度加权并未带来显著改善。
  • 累积误差也没有提升相关性。
  • 更鲁棒的量化版本表现最好,但其与在线指标的相关性仍不及在线指标之间的相关性。

案例研究:深入理解差异

为了更好地理解为何在线与离线指标相关性不高,论文中进行了案例研究。

他们观察了两个模型在特定弯道机动中的表现。真实轨迹为蓝色,模型1(红色)使用单摄像头、无数据增强和L2损失训练;模型2(绿色)使用三个摄像头、数据增强和更鲁棒的L1损失训练,是一个更好的模型。

从轨迹图和局部放大图可以看出,两个模型的预测都有噪声,但模型1偶尔会产生非常大的预测误差。尽管从离线指标(如平均转向角偏差)来看,模型1的平均表现并不比模型2差太多,但这些偶发的大误差会导致车辆偏离道路、撞上物体或引发其他违规,最终导致路线任务失败。

这个案例揭示了在线与离线评估不完全兼容的原因:离线指标反映了平均性能,而在线驾驶安全可能取决于最差的偶发性能。偶尔的大错误足以导致任务失败,但它们在平均误差指标中可能被掩盖。

下图进一步说明了这一案例:模型1在每次试验中都发生碰撞,而模型2可以成功驾驶。这凸显了使用离线指标预测在线行为的困难。

因此,离线评估可以提示智能体的性能趋势,但最终仍需在在线环境中评估智能体。正如当前的Carla排行榜所做的那样:参与者提交其智能体,服务器在未公开的城市和天气条件下进行在线评估。由于是模拟器,在线评估是可行的。


总结

本节课我们一起学习了以下内容:

  1. 直接感知方法预测中间表征,低维的功能可供性或经典的计算机视觉表征(如语义分割或深度图)可用作中间表征。
  2. 这些中间表征将感知与规划控制解耦,从而通常能带来更鲁棒的驾驶行为和更好的泛化能力。它们是模仿学习与模块化流水线之间的混合模型。
  3. 直接感知方法更具可解释性,因为其内部表征可以被检视。
  4. 使用相当有限的监督信号,就可以学习到有效的视觉抽象。
  5. 规划本身也可以与控制解耦,以实现更好的策略迁移(例如,迁移到新车辆或从模拟环境迁移到真实世界)。
  6. 离线评估指标不一定能指示在线驾驶性能,因此在解释离线指标时需要谨慎。最终的性能验证离不开在线评估。

本节课到此结束,谢谢观看。

013:强化学习与马尔可夫决策过程 🚗

在本节课中,我们将要学习强化学习,这是一种无需专家演示即可学习机器人策略的流行技术。我们将通过马尔可夫决策过程这一框架来正式定义强化学习问题。

在第二讲和第三讲中,我们看到了如何通过模仿专家行为或预测专家可操作性来学习端到端的自动驾驶模型。本节课我们将讨论另一种技术,即强化学习。

本节课分为四个单元。在第一单元,我们将通过马尔可夫决策过程框架正式定义强化学习问题。在第二单元,我们将学习贝尔曼方程,以及它如何引出强化学习中最基础的算法之一——Q学习。最后,在第三单元,我们将了解基于深度神经网络的Q学习版本,即深度Q学习及其变体。

让我们从马尔可夫决策过程开始。

从监督学习到强化学习 🔄

到目前为止,我们考虑的是监督学习。模仿学习是一个监督学习问题,它需要大量的专家演示,我们基本上是试图模仿专家。这种方法的缺点当然是,首先我们必须能够获得这些专家演示,其次这些损失函数实际上并不是我们理想中想要优化的损失函数。它们是辅助损失函数,只是告诉我们希望接近专家,并且它们具有非常短期的效果。例如,在模仿学习中,我们对动作有逐帧的损失,我们不考虑未来,不预测未来会发生什么,只是通过模仿专家来隐式地做到这一点。同样,在直接感知中,我们看到我们在可操作性指标上设置了逐帧损失函数。

本节课我们将考虑一种不同的方法,我们不再试图模仿专家。相反,我们将尝试通过与环境的探索、利用和交互,基于我们真正关心的损失来学习模型。这些损失函数与我们之前为模仿学习考虑的转向角L1损失等标准损失函数非常不同。这些损失函数更加通用,它是一个更通用的框架。例如,损失函数可以包括我们希望最小化到达目标位置的时间(这是自动驾驶中我们希望做的),或者碰撞次数,或者驾驶时承担的风险,或者我们希望最大化舒适度等。因此,我们可以用强化学习框架中这种通用的损失函数来形式化自动驾驶。

机器学习的三大类别 📊

在机器学习教科书中,学习通常被分为三个不同的类别。

第一类我们已经见过,这是经典的机器学习框架,称为监督学习。我们有一个数据集,包含X、Y数据标签对。目标是学习从x到y的映射。这方面的例子包括图像分类、回归、模仿学习、可操作性学习等。

相比之下,在无监督学习中,我们只提供一个数据集,目标是发现数据背后的结构。例子包括聚类、降维、特征学习等。这种方法也被用于自动驾驶的上下文中,例如,使用简单的重建损失和图像重建损失来学习环境的世界模型,以学习高维状态的良好压缩。

最后,我们有强化学习,这就是我们本节课要讨论的内容。与前两种学习类型不同,智能体与环境交互。环境向智能体提供数值奖励信号,目标是智能体应该学习如何采取行动以最大化环境提供的奖励。这方面的例子包括学习机器人手臂的操纵任务(例如学习抓取物体)或控制任务,正如我们今天将看到的。

强化学习循环图示 🔁

强化学习可以用一个简单的图表来说明。

我们有一个在环境中运行的智能体,智能体可以是在真实世界环境或模拟环境(如Carla)中运行的自动驾驶汽车。智能体在时间T观察环境状态S_T。环境向智能体提供或暴露其状态(或部分状态)。通常,你无法获得环境的完整图像或完整状态,你只能看到环境的一部分。例如,汽车可能只拍照,所以你无法获得环境的3D状态,你只有一个2D投影,可能只是环境某个区域的投影,而不是智能体运行的整个世界。因此,状态通常是不完整的。然后,智能体在时间t将其动作A_T发送给环境。它基于当前状态,尝试为该状态、该观察做出最优动作。汽车观察图像,并根据所见适当转动方向盘。接着,环境向智能体返回两样东西:它返回奖励。奖励告诉智能体该动作有多好。例如,如果自动驾驶汽车到达了目标,它会告诉汽车这很好;如果汽车撞到了行人,它会告诉汽车这不好;如果它闯了红灯,它会告诉汽车这不好,发生了碰撞,这不好。所以环境返回奖励R_T,它评判动作A_T,这是一个简单的数值,可以是正数或负数。智能体希望最大化奖励,希望获得尽可能多的奖励,并最小化负奖励。环境返回的第二样东西是下一个状态。环境根据智能体的动作(当然也包括场景中所有其他智能体的动作,例如在像Carla这样的模拟器中模拟的),转换到下一个状态。例如,如果智能体向前移动,环境将下一个相机位置的图像提供回智能体,这就是观察S_T+1。

因此,强化学习的目标是选择动作以最大化未来的总奖励。环境提供奖励,我们希望获得尽可能多的正奖励。然而,动作可能具有非常长期的后果。例如,在自动驾驶中,我们可能只有在到达目标时才有奖励。这可能发生在驾驶一分钟后、30分钟后或两小时后。在到达那里之前,我们可能没有很多奖励。这使得学习问题变得非常困难,强化学习是一个真正困难的问题。此外,奖励可能是延迟的,而不是即时的。环境可能不会立即给你奖励,尽管你做了一个好的动作。因此,为了获得更多的长期奖励,牺牲即时奖励对智能体来说可能更好。这有一些例子,说明了这个问题有多困难。智能体需要在短期内决定下一个动作,它可能需要决定一个次优的动作,以便在长期获得非常高的奖励。例子包括可能需要数月才能成熟的金融投资,或者考虑一架需要救援人员但燃料不足需要加油的救援直升机。加油需要时间,但它可能会防止几小时后的坠毁。或者一个非常典型的例子是国际象棋游戏,牺牲一个特定的棋子,在短期内让你在棋盘上的棋子更少,但从长远来看可能帮助你赢得游戏。所以这使得问题变得非常困难。

强化学习问题实例 🎮

现在,让我们看一些具体例子,以更好地了解不同的强化学习问题可能是什么样子。

其中一个最简单的例子是所谓的移动小车倒立摆平衡问题。我们有一个可以左右移动的小车,我们可以向该小车施加一个力,使其向左或向右移动。这个问题的目标是平衡移动小车上的杆子,我们希望杆子保持直立。开始时,杆子可能实际上是朝下的,所以我们必须把它抬起来。状态是杆子的角度(这里有一个关节,所以这是角度)、角速度(角度的一阶导数)、小车在x方向的位置以及小车的速度。所以我们有一个四维状态空间,与自动驾驶或其他问题相比,这是一个非常简单的状态空间。而且,在这种情况下,它实际上是完全可观测的,不像我之前提到的自动驾驶,我们只有一张看不到一切的图片,但在这里我们看到了一切,我们只有这四个值。动作是施加水平力使杆子直立,但奖励,正如你在这里看到的,非常稀疏。如果杆子在时间T直立,奖励为1,否则为0。所以如果杆子朝下,系统(智能体)必须与环境互动,才能实际观察到第一个奖励,这使得问题非常困难。这个问题甚至可以变得更难。像这个倒立摆问题,人类可以解决。这很难,你可以自己尝试,把一根杆子放在手上,试着平衡它。这很难,取决于杆子。但你可以做到。但是,添加更多关节和更多杆段会使它变得更加困难。然而,机器人可以解决这个控制任务,我有一个相当巧妙的演示,展示了这样一个倒立三摆。可以看到机器人如何能够摆动它们的杆子竖起来。尽管设置复杂,但令人印象深刻。

另一个例子是机器人运动。这是取自OpenAI Gym中机器人学校环境的一个例子,我们的自动驾驶也发生在这个环境中。这只是OpenAI Gym中的另一个环境。这里的目标是,我们有一个由几块骨头和关节组成的机器人,就像机器人的铰接结构。你可以看到这里有不同的机器人。目标是让机器人向前移动。状态是所有关节的位置和角度,动作是我们可以施加在关节上的扭矩,类似于之前的倒立摆问题,但现在是一个复杂得多的铰接机器人。我们希望机器人学习如何移动。机器人对如何移动一无所知,所以我们希望学习如何移动。如果机器人(智能体)直立并向前移动,奖励为1,否则为0。以下是一些这些机器人使用强化学习学到的行为的例子。它们实际上已经学会了保持直立(不倒下)并同时尽可能快地向前移动的策略。你可以看到有趣的行为出现,其中一些行为实际上与真实生物也学会的行为相似。

另一个例子是Atari游戏。这是来自OpenAI Gym的Atari环境。它提供了一整套Atari游戏,你可以在这里看到。它们直接带有奖励,因为它们有游戏状态,有分数,你可以在游戏中看到你的分数,你可以从那里检索你的分数,你可以用它作为奖励来尝试学习这些游戏。因此,目标是最大化游戏分数,即奖励。状态只是屏幕的原始像素,210乘以160像素。对于其中一些游戏,使用强化学习来学习真的很容易,而那些具有非常复杂行为并需要长期规划的游戏则更难学习。动作是键盘上的标准动作:左、右、上、下。奖励是如果分数在时间T增加或减少。这就是你想要最大化的游戏分数。

你可能都听说过AlphaGo及其后继者。这也是强化学习的一个突出例子,在这种情况下,与经典的规划树搜索技术相结合。围棋是世界上最古老的持续进行的棋盘游戏,它是最简单也是最抽象的之一。在围棋上击败职业选手是人工智能长期以来的挑战。我们在人工智能中尝试过的一切,在尝试围棋游戏时都失败了。棋盘上可能的配置数量比宇宙中的原子数量还要多。AlphaGo找到了一种学习如何下棋的方法。到目前为止,AlphaGo已经击败了我们给它的每一个挑战,但在我们与像李世石这样的世界顶级棋手对弈之前,我们不会知道它的真正实力。这甚至有一部关于AlphaGo的电影。目标很简单,赢得游戏。它是完全可观测的。状态空间很简单,但由于可能出现的许多情况,它极其庞大。所以状态只是所有棋子的位置,动作是下一个棋子的位置。环境的定义超级简单。如果游戏赢了,奖励为1,否则为0,这是非常长期的奖励,极其长期的奖励,这使得它很热门。

另一个例子当然是自动驾驶。你将在第二个编码练习中看到这一点,我们将尝试开发一个在OpenAI Car Racing环境中驾驶良好的智能体,并尝试仅通过强化学习通过尽可能多的灰色瓷砖。这是一个智能体在这里驾驶的例子。在这种情况下,目标是车道跟随,状态也是图像,96乘以96像素,动作是加速和转向。如果我们继续到下一帧,奖励是负的。所以每一帧,我们得到一个负奖励。而我们每通过一个灰色瓷砖,就会得到一个正奖励。换句话说,我们希望尽可能在尽可能短的时间内通过尽可能多的灰色瓷砖。

马尔可夫决策过程形式化 📐

再次回到我们之前见过的强化学习循环,我们如何用数学形式化RL问题?

我们使用所谓的马尔可夫决策过程来实现。马尔可夫决策过程,简称MDP,定义了一个元组 (S, A, R, P, γ)。这个元组的五个组成部分是什么?

  • S 是所有可能状态的集合。例如,在围棋游戏中,是所有可能棋子在棋盘上组合的集合。
  • A 是所有可能动作的集合。
  • R 是给定状态-动作对的当前奖励的分布。因为环境可能具有随机性,我们在这里考虑最一般的情况。我们有一个分布。它可以是确定性的,给定一个状态和动作,它可以只是一个映射到R的函数,但它也可以是一个分布。其中可能存在不确定性,这通常是情况,例如,当我们有游戏或由于测量噪声导致的不确定观察时,事物是不确定的。所以我们考虑给定状态-动作对的奖励分布。
  • P 是这个元组的第四个元素,是给定状态-动作对的下一个状态的分布。所以是 P(S_{t+1} | S_t, A_t)。这是环境如何转换到下一个状态。
  • γ 是所谓的折扣因子,它决定了未来奖励的价值。它降低了未来奖励的价值,因为智能体只能向前看有限的步数。通常,考虑一百万年后的奖励与一分钟后的奖励价值相同是没有意义的。这就是这个折扣因子的作用。我们将在下一单元更详细地讨论这个问题。

几乎所有的强化学习问题都可以形式化为马尔可夫决策过程。这就是为什么它们提供了这个强大的数学框架,我们将在其中进行操作。

它们被称为马尔可夫决策过程,是因为它们遵循马尔可夫性质。马尔可夫性质指出,当前状态完全表征了世界的状态。这意味着,当且仅当 P(S_{t+1} | S_t) = P(S_{t+1} | S_1, ..., S_t) 时,状态S是马尔可夫的。换句话说,当前状态仅依赖于前一个状态。如果前一个状态已知,那么前一个状态之前的所有状态都不再重要。这就是马尔可夫性质。你可能已经通过隐马尔可夫模型或卡尔曼滤波器等熟悉这个了。

以下是一些与此等价的陈述:例如,给定现在,未来独立于过去;或者状态捕获了历史中所有相关信息;一旦状态已知,历史就可以被丢弃;状态S_t是未来的充分统计量,我们不需要知道以前的状态。

MDP中的强化学习循环 🔄

现在让我们回到强化学习循环,我们已经在右边看到过,现在让我们在引入的马尔可夫决策过程的背景下看看这个循环。

我们从时间 t=0 开始。在时间 t=0,第一步。在第一步,环境从状态分布 P(S_0) 中采样初始状态。所以我们得到第一个状态。然后,对于 t=0 直到我们完成(直到模拟结束,有时也称为一次“rollout”,即策略在环境中与环境交互的展开)。所以对于 t=0 直到完成,智能体选择一个动作 A_t。然后环境采样奖励 R_t(给定状态和动作)以及下一个状态。智能体接收奖励和下一个状态,并选择下一个动作,依此类推。

策略:动作选择机制 🎯

我们实际上如何选择一个动作呢?我们已经知道选择动作的机制,它被称为策略。我们在模仿学习的背景下见过策略,我们将在这里再次在强化学习的背景下看看策略。

策略 π 是一个从状态空间到动作空间的函数,它指定在每个状态下要采取什么动作。给定任何状态,这个函数告诉我们应该采取什么动作,而策略正是我们想要学习的东西。它通常是一个由某些参数参数化的神经网络,或者如果状态和动作空间是离散的,它可能是一个查找表。因此,策略完全定义了一个智能体的行为。策略可以是确定性的,我们有一个从S到A的直接映射函数;也可以是随机的,它模拟不确定性,给我们返回一个分布。我们将其表示为 π(a|s),即分布 P(A_t = a | S_t = s)。

作为一个小备注,MDP策略仅依赖于当前状态(正如你在这里看到的),而不依赖于整个历史。然而,当前状态当然可以包含过去的观察结果。这只是我们如何定义状态的问题。我们可以将状态定义为一个帧缓冲区,例如,我们作为智能体观察到的最后10帧图像的缓冲区。在这个形式化中,这完全没问题。这只是我们如何定义状态的问题。

如何学习策略?🤔

我们已经看到了一种方法,称为模仿学习。我们使用监督学习直接从专家演示中学习策略。

然而,在强化学习中,我们假设没有给出专家演示。相反,我们通过试错来学习策略。智能体自己发现哪些动作能最大化预期的未来奖励,这是我们想要最大化的量。智能体与环境交互并获得奖励,智能体发现好的动作,并根据通过这个试错游戏给予智能体的奖励来改进其策略π。

探索与利用的权衡 ⚖️

那么我们如何发现好的动作呢?我们需要探索状态-动作空间。这也使得RL在现实世界中通常不安全且难以执行。有一个完整的研究分支关于如何使RL安全,但当然,如果我们在模拟器中,比如在Carla中模拟自动驾驶,那就容易得多,因为我们不会构成任何安全风险,我们也可以模拟和探索不安全的场景。

因为我们需要探索状态-动作空间,我们一无所知,我们没有专家可以模仿。我们在这里结合了两个任务,这是强化学习的两个基本任务。

第一个任务称为探索。探索的目标是在状态S中尝试一个新动作A,然后我们观察奖励R_t。我们不知道那个动作是好是坏,但我们不在乎,我们只是想看看会发生什么。这就是为什么它被称为探索。探索发现了更多关于环境的信息,但牺牲了在该“回合”中给出的总奖励。因为我们正在尝试一个动作,在大多数情况下,这个动作实际上不会是一个好动作。然而,通过体验新的状态,我们可能在某个时候找到一个真正好的动作,因此我们可以从中学习,并尝试在未来更频繁地执行该动作。所以探索在开始时特别有用,当我们对环境一无所知时,我们需要探索,我们真的没有其他选择。我们需要探索才能找到有用的动作。游戏玩法中的一个例子是走一步新颖的实验性棋步。我们不知道会发生什么,我们尝试一下,看看这会导致什么。

RL中的另一个基本任务称为利用。在利用中,我们使用一个先前发现的好动作,一个我们知道是好动作的动作。当然,通过使用一个我们知道对特定状态有益的动作,通过利用这些信息,我们正在最大化奖励,因为我们知道这是一个好动作。但同时,我们牺牲了未探索的区域。如果我们只利用,如果我们发现了一些好动作,但我们没有考虑状态空间的大部分区域,在那里也许可以获得更高的奖励。我们陷入了一个循环,我们只是在探索我们已经知道的区域,从某种意义上说,我们只得到这个小奖励。所以游戏玩法中的例子是走你认为最好的一步。

在实践中,这两者之间存在权衡,你需要在探索和利用之间进行权衡。同时进行探索和利用很重要。开始时,你想从探索开始。随着你的智能体变得更好,你想更多地转向利用,因为你已经在更好的状态下运行了。

ε-贪心探索算法 🎲

但是如何平衡探索和利用呢?有一个所谓的ε-贪心算法正是这样做的。

ε-贪心探索算法以非零概率尝试所有可能的动作。具体来说,以概率 ε,它随机选择一个动作,完全随机。这就是探索。以概率 1-ε,我们选择最佳动作。这就是利用。贪心动作被定义为迄今为止发现的最佳动作。所以最佳动作在某种意义上就是贪心动作,你查看一个状态的所有可能动作,查看你当前的策略,并最大化它以进行利用。以 1-ε 的概率,你进行利用移动;以 ε 的概率,你进行探索移动。

如前所述,在开始时,当你对环境一无所知时,你必须探索。因此,ε 的调度是这样的:开始时选择一个较大的 ε,然后逐渐退火,随着时间的推移逐渐减小它,这样当你的策略变得越来越好时,你就从探索转向利用。你希望更多地利用状态空间中那些能给你高奖励的区域,因为如果你在这些高价值区域探索,而不是随机地到处探索,你可能会发现一些更好的奖励。


本节课中我们一起学习了强化学习的基本概念,特别是通过马尔可夫决策过程框架来形式化问题。我们了解了强化学习循环、策略的作用,以及在学习过程中至关重要的探索与利用之间的权衡。下一节我们将深入探讨贝尔曼方程和Q学习算法。

014:强化学习 - 贝尔曼最优性与Q学习 🚗🤖

在本节课中,我们将学习第一个,也是最基础、最常用的强化学习算法——Q学习。我们将从理解价值函数开始,探讨如何评估未来奖励,并引出贝尔曼最优性原理,最终学习Q学习算法。

价值函数

为了通过强化学习进行学习,我们需要知道一个状态的好坏。状态的好坏只能通过从该状态开始,遵循特定策略行动后所能获得的未来奖励来评估。

状态价值函数 V

状态价值函数 V 是针对一个固定策略 π 定义的。函数 V^π 在状态 s_t 的值,表示从状态 s_t 开始,遵循策略 π 所能获得的期望累积折扣奖励

其数学定义如下:

V^π(s_t) = E[ Σ_{k=0}^{∞} γ^k * r_{t+k} | s_t, π ]

其中:

  • E 表示期望值,用于汇总策略、状态转移和奖励中可能存在的随机性。
  • γ 是折扣因子,取值范围在 0 到 1 之间(通常接近1)。它决定了未来奖励在当前时刻的价值,γ^k 使得更近期的奖励比远期奖励权重更高。例如,若 γ=0.5,则下一步奖励的权重仅为当前奖励的一半。

动作价值函数 Q

动作价值函数 Q 用于评估在特定状态下采取某个动作的好坏。函数 Q^π 在状态 s_t 和动作 a_t 的值,表示在状态 s_t 采取动作 a_t,然后遵循策略 π 所能获得的期望累积折扣奖励。

其数学定义如下:

Q^π(s_t, a_t) = E[ Σ_{k=0}^{∞} γ^k * r_{t+k} | s_t, a_t, π ]

V^π 的主要区别在于,Q^π 额外条件于初始采取的动作 a_t,而不是对动作取平均。

最优价值函数

上一节我们介绍了在给定策略下的价值函数。本节中,我们来看看理论上最优的价值函数是什么样的。

最优状态价值函数 V* 是所有可能策略 π 中,能得到的最大 V^π 值。它代表了在最优策略下,从某个状态开始能获得的最大累积折扣奖励。

V*(s) = max_π V^π(s)

类似地,最优动作价值函数 Q* 是所有可能策略 π 中,能得到的最大 Q^π 值。

Q*(s, a) = max_π Q^π(s, a)

Q* 具有一个关键性质:如果我们知道了 Q,那么最优策略 π 也就随之确定了。我们只需要在每个状态 s 下,选择能使 Q*(s, a) 最大化的动作 a 即可。

π(s) = argmax_a Q(s, a)

然而,对于大多数有趣的问题,直接枚举所有策略来寻找 Q* 是计算上不可行的。它更多是一个理论概念。

一个简单示例:网格世界 🌐

为了直观理解最优策略,让我们看一个简单的“网格世界”例子。智能体在离散网格中移动,目标是到达标记为星号的终止状态,且每走一步都会获得一个负的奖励(惩罚),因此智能体需要尽快到达终点。

一个随机策略会为每个状态下的四个动作(上、下、左、右)分配相等的概率。而最优策略则如下所示:在靠近终点的格子,策略会指向直接到达终点的方向;在更远的格子,策略会指向通往终点的最短路径方向。

这个例子中,最优策略可以通过观察轻松得出。但对于复杂问题(如围棋或自动驾驶),我们无法通过“肉眼”观察得到最优策略。

贝尔曼最优性方程

既然直接搜索所有策略不可行,我们如何求解最优策略呢?这就是贝尔曼最优性方程发挥作用的地方。

贝尔曼最优性方程以理查德·E·贝尔曼命名,是动态规划和最优控制理论的核心。它将 Q* 函数表达为一个递归形式。

对于最优动作价值函数 Q*,贝尔曼最优性方程如下:

Q(s_t, a_t) = E[ r_t + γ * max_{a} Q(s_{t+1}, a) | s_t, a_t ]

这个方程非常强大,它将一个需要计算未来所有时间步奖励的长期问题(原始定义),转化为一个只向前看一步的递归问题。方程包含两部分:

  1. 当前奖励 r_t:在状态 s_t 执行动作 a_t 后立即获得的奖励。
  2. 未来价值:折扣因子 γ 乘以在下一个状态 s_{t+1} 所有可能动作中,最大的 Q* 值。

这个方程是非线性的(因为包含 max 算子),通常没有闭式解。但幸运的是,我们可以使用迭代方法来求解它,其中最著名的就是 Q 学习算法。

Q学习算法

上一节我们介绍了求解 Q* 的理论框架——贝尔曼最优性方程。本节中,我们来看看如何通过 Q 学习这个迭代算法来实际求解它。

Q 学习通过迭代更新来逼近 Q* 函数。其核心更新规则如下:

Q_{i+1}(s_t, a_t) ← (1 - α) * Q_i(s_t, a_t) + α * [ r_t + γ * max_a Q_i(s_{t+1}, a) ]

其中:

  • α 是学习率,控制着新信息覆盖旧估计的速度。
  • γ 是折扣因子。
  • max_a Q_i(s_{t+1}, a) 是基于当前估计 Q_i,对下一状态最优未来价值的估计。

这个规则可以重写为更常见的形式,突出其“时序差分”的本质:

Q_{i+1}(s_t, a_t) ← Q_i(s_t, a_t) + α * [ r_t + γ * max_a Q_i(s_{t+1}, a) - Q_i(s_t, a_t) ]

方括号内的项称为时序差分误差,它代表了当前估计与“目标值”(即时奖励加上对未来价值的估计)之间的差异。算法通过向目标值方向调整当前估计来学习。

以下是 Q 学习的基本步骤:

  1. 初始化 Q 表(例如,全零或随机值)。
  2. 重复以下过程:
    • 观察当前状态 s_t
    • 根据 ε-贪心策略选择一个动作 a_t(以概率 ε 进行探索,随机选动作;以概率 1-ε 进行利用,选择当前 Q 值最高的动作)。
    • 执行动作 a_t,观察奖励 r_t 和下一个状态 s_{t+1}
    • 使用上述更新规则更新 Q(s_t, a_t)
  3. 在足够多的迭代后,Q 函数会收敛到 Q*(在适当条件下已被证明)。

需要注意的是,Q 学习是一种离策略算法,因为用于更新 Q 值的策略(贪婪策略,即 max_a Q_i)与智能体实际执行动作的策略(ε-贪心策略)是不同的。

从表格到函数逼近

Q 学习算法简单有效,但其经典形式依赖于用表格来表示 Q(s, a)。这对于状态和动作空间是离散且较小的问题很有效。

然而,表格法存在严重的可扩展性问题。对于状态或动作空间非常大甚至是连续的问题(例如围棋有超过宇宙原子数量的可能状态,自动驾驶的摄像头输入是连续的像素图像),我们无法创建和维护一个巨大的表格。

解决方案是使用函数逼近器(如神经网络)来代表 Q 函数。我们可以构建一个神经网络,以状态 s 和动作 a 作为输入,输出对应的 Q 值估计。例如,在自动驾驶中,可以使用卷积神经网络处理图像输入。这种方法被称为深度 Q 网络,我们将在后续单元中详细探讨。

总结

本节课中,我们一起学习了强化学习的核心算法——Q学习。我们从定义状态价值函数 V 和动作价值函数 Q 开始,理解了它们如何评估未来奖励。接着,我们探讨了最优价值函数 Q* 的概念,并认识到它直接隐含了最优策略。然后,我们通过贝尔曼最优性方程,建立了递归求解 Q* 的理论基础。最后,我们详细介绍了 Q 学习算法,它通过迭代更新时序差分误差来逼近最优动作价值函数,并讨论了使用函数逼近器(如神经网络)来解决高维状态/动作空间的可扩展性问题。

015:深度Q学习 🚗🤖

在本节课中,我们将要学习如何将深度神经网络与经典的Q学习算法相结合,以处理高维状态空间,例如图像输入。我们将探讨深度Q学习(Deep Q-Learning)的核心思想、面临的挑战以及关键的改进技术。

概述

在上一单元中,我们介绍了Q学习。我们看到Q学习是一种强化学习算法,能够处理简单、离散且低维的状态空间。然而,它无法处理高维状态空间,例如围棋游戏,因为可能的状态数量太多,无法用表格枚举。这正是深度Q学习发挥作用的地方。

从Q表到深度Q网络

在深度Q学习中,我们通过使用深度神经网络作为函数逼近器来估计Q值,从而缓解了Q表容量有限的问题。这在数学上可以表示为:

Q*(s, a) ≈ Q(s, a; θ)

其中,Q(s, a; θ) 是一个参数为 θ 的神经网络,它以状态 s 和动作 a 作为输入,输出对应的Q值。

这种方法有两种变体:

  1. 第一种变体如之前所述,神经网络以状态和动作为输入,输出单个Q值。
  2. 第二种更实用的变体是,神经网络仅以状态为输入,并输出一个向量,其中每个元素对应一个可能动作的Q值。例如,如果有10个动作,网络就输出一个10维向量。

第二种架构的优势在于,要找到最优动作,我们只需一次前向传播并选择输出值最大的动作,而无需为每个可能的动作单独计算Q值。

训练深度Q网络

训练Q网络包括前向传播和反向传播。

  • 前向传播:计算损失函数,即Q值的均方误差。损失函数基于贝尔曼最优方程,目标是使当前Q值预测接近“目标值”(即时奖励加上对未来奖励的估计)。
    损失 L(θ) = E[ (目标 - 预测)² ]
    目标 = r + γ * max_a‘ Q(s‘, a‘; θ)
    预测 = Q(s, a; θ)

  • 反向传播:计算损失函数相对于网络参数 θ 的梯度,并使用随机梯度下降等优化方法更新参数。

然而,直接这样训练会导致优化过程非常不稳定,难以收敛。接下来,我们将看看如何解决这个问题。

稳定训练的关键技术

有两项关键技术对于稳定深度Q学习的训练至关重要,它们在一篇2015年发表于《自然》杂志的论文中被提出。

经验回放 🧠

为了加速训练,我们使用小批量样本。问题在于,智能体在环境中连续移动产生的样本之间具有强相关性,从这些连续样本中学习效率很低。

经验回放通过存储智能体在每个时间步的经验(即状态、动作、奖励、新状态元组)到一个“回放缓冲区”或“回放记忆” D 中来应对这个问题。在训练时,我们从缓冲区中均匀地随机采样一批经验。

这种方法打破了样本间的相关性,提高了数据效率,因为每个样本可以被多次使用(“回放”)。实践中,通常使用一个固定大小的循环缓冲区。

固定Q目标 🎯

第二个问题是“非平稳目标”。由于我们通过梯度下降不断更新Q网络参数 θ,用于计算目标值的Q函数本身也在变化,这就像是在追逐一个移动的目标,容易导致振荡甚至发散。

解决方案是使用“固定Q目标”。我们引入一个“目标网络” Q‘,其结构与主Q网络相同,但拥有另一套参数 θ‘。我们用这个目标网络来计算目标值。关键之处在于,目标网络的参数 θ‘ 并不会每一步都更新,而是每隔 C 步才用主网络的参数 θ 来更新一次(例如直接复制)。这样有效地减慢了目标值的变化速度,稳定了训练。

损失函数因此变为:
L(θ) = E[ (目标‘ - 预测)² ]
目标‘ = r + γ * max_a‘ Q‘(s‘, a‘; θ‘)
预测 = Q(s, a; θ)

深度Q学习算法

结合了经验回放和固定Q目标的深度Q学习算法步骤如下:

  1. 根据ε-贪婪策略选择并执行动作 a_t
  2. 将经验 (s_t, a_t, r_t, s_{t+1}) 存储到回放缓冲区 D 中。
  3. D 中随机采样一个小批量的经验。
  4. 使用目标网络的参数 θ‘ 计算Q目标值。
  5. 计算当前Q网络预测值与目标值之间的均方误差损失。
  6. 对损失执行随机梯度下降,更新主Q网络的参数 θ
  7. 每隔C步,将主网络参数 θ 复制给目标网络参数 θ‘

深度Q网络实战:玩转Atari游戏

上述算法在Atari游戏(如打砖块)上取得了突破性表现。网络输入是经过处理的84x84像素灰度图像堆叠,经过几个卷积层和全连接层后,输出每个游戏动作的Q值。

一个有趣的现象是,智能体通过强化学习自发地发现了一种高效策略:将球打到砖墙后方,让球在顶部持续弹跳,从而快速获得高分。这展示了算法超越人类直觉策略的能力。

深度Q学习的局限与改进

尽管强大,深度Q学习仍有其局限:

  1. 训练时间漫长:稀疏奖励和深度网络需要大量更新。
  2. 均匀采样效率低:回放缓冲区中的所有经验被同等对待,但有些经验可能更重要。
  3. 探索策略简单:依赖ε-贪婪策略。
  4. 需要完全可观测状态
  5. 动作空间受限:只能处理离散、低维动作。

针对这些局限,研究者提出了多种改进算法。

深度确定性策略梯度(DDPG)🎭

DDPG算法旨在解决连续或高维动作空间的问题。在原始DQN中,处理连续动作需要在每一步优化Q函数,这很困难。

DDPG的解决方案是同时使用两个网络:

  • 演员网络 (Actor):一个参数为 θ^μ 的确定性策略网络 μ(s),它直接将状态映射到具体的动作。
  • 评论家网络 (Critic):一个参数为 θ^Q 的Q值网络 Q(s, a),评估在状态 s 下采取动作 a 的好坏。

训练过程

  • 评论家更新:类似于DQN,通过最小化时序差分误差来更新,但目标动作由目标演员网络 μ‘ 提供。
  • 演员更新:使用策略梯度定理。演员网络的参数沿着提升Q值的方向更新,即最大化 Q(s, μ(s))。梯度公式为:
    ∇_θ^μ J ≈ E[ ∇_a Q(s, a|θ^Q) |_{a=μ(s)} · ∇_θ^μ μ(s|θ^μ) ]

DDPG同样使用经验回放和软更新的目标网络来稳定训练。探索通过向演员网络输出的动作添加噪声来实现。

一个令人印象深刻的演示是,一家初创公司使用DDPG配合优先经验回放,仅用几十个训练回合就让一辆真实汽车在简单乡村道路上学会了自动驾驶。奖励信号是安全驾驶员未介入干预的行驶距离。

其他改进方向

以下是其他一些重要的改进思路:

  • 异步强化学习:多个智能体在并行环境中独立探索,共同更新一个共享的全局模型,稳定训练并加速。
  • Bootstrapped DQN:使用多个Q头(网络分支)来近似Q值的分布,通过随机选择一个头来引导探索,最终集成以得到更鲁棒的策略。
  • 双Q学习:解耦动作选择和动作评估所使用的Q函数,使用两个不同的网络(在线网络和目标网络)来分别完成这两个任务,以减少Q值的高估。
  • 循环DQN:在网络中加入循环层(如LSTM),以处理部分可观测的状态,让网络能够记忆历史信息。

奖励函数设计的重要性 ⚠️

最后,我们必须强调设计合适的奖励函数至关重要。强化学习虽然不需要专家示范,但需要精心设计奖励来引导智能体学习期望的行为。一个设计不当的奖励函数可能导致智能体学会“钻空子”,找到一些意想不到但能获得高奖励却不符合初衷的策略。例如,在一个赛车游戏中,智能体可能发现不断绕圈收集道具比真正完成一圈比赛能获得更高的累计奖励。

总结

本节课中,我们一起学习了:

  • 强化学习通过与环境的交互进行学习,目标是最大化期望累积奖励。
  • Q学习通过迭代更新来求解最优动作价值函数,但受限于表格表示法。
  • 深度Q学习通过用深度神经网络近似Q函数,解决了高维状态空间的问题。
  • 为了稳定训练,经验回放固定Q目标是两项核心技术。
  • 深度确定性策略梯度通过引入独立的演员-评论家架构,将算法扩展到了连续动作空间。
  • 我们还简要了解了其他改进技术,如优先经验回放、双Q学习等,并认识到精心设计奖励函数是强化学习成功应用的关键。

强化学习是一个广阔且快速发展的领域,为自动驾驶等复杂决策问题提供了强大的工具。

016:车辆动力学导论 🚗

在本节课中,我们将要学习车辆动力学的基础知识。我们已经了解到,通过直接从图像映射到车辆控制指令来控制车辆是可行的。但在实践中,通常更优的方法是使用一个独立的控制器来控制车辆。如果我们能很好地理解系统,就能更好地设计这样的控制器。因此,我们需要理解车辆的运动学和动力学,这正是本讲的内容。它涉及大量几何学知识,同时也涉及物理学和机械工程。

本讲分为四个单元。首先,我们将介绍并探讨为何需要更好地理解车辆动力学,并引入一些基本的几何和物理概念。在第二单元,我们将研究最基本的车辆模型,即运动学自行车模型。该模型不涉及力的作用,只考虑纯运动学,是一个纯几何模型,也是最简单的模型。接着,我们将研究轮胎,以及轮胎如何改变车辆行为,特别是在较高速度下,仅考虑运动学模型是不够的,我们必须同时建模动力学,包括力、摩擦和滑移。这将引导我们进入第四单元要介绍的动力学自行车模型

现在,让我们从导论部分开始。在开始之前,我要特别感谢吕贝克大学Schilpar教授的“车辆动力学与控制”课程,本讲部分内容基于此,这是一门非常出色的课程。如果你想更深入地理解本讲中的概念,我推荐你观看这门课程,链接已在页脚处提供。

理解车辆动力学的重要性

如前所述,为了控制车辆,我们需要了解车辆动力学。事实上,今天的汽车内部已经集成了许多复杂的控制器。例如,电子稳定程序 独立控制汽车的四个车轮,这些系统正是基于我们对车辆动力学的理解而构建的。

当你驾驶时,许多力作用在你的车辆上。你可能在日常驾驶中感受到其中一些力,比如在转弯时身体会向一侧倾斜。当你转动方向盘时,你的车不只是向一侧移动,它实际上会围绕一个垂直轴旋转。在某些条件下,车辆可能旋转过度或不足,例如当你急转弯避让障碍物、过弯太快或遇到湿滑路面时。这就是为什么梅赛德斯-奔驰发明了电子稳定程序。ESP的传感器网络持续监测车辆执行驾驶员指令的情况。ESP将你的转向输入与每个车轮的速度和车辆的旋转速度进行比较。在几毫秒内,ESP就能感知车辆是否偏离了你的预期路线。当你快速转向避让障碍物时,车辆倾向于继续直线前进。此时,ESP会对内侧后轮进行制动,产生一个旋转力,帮助车辆转向你指示的方向。当你恢复时,车辆尾部可能发生侧滑,ESP会对前外侧车轮进行制动,帮助车辆旋转回正确路线。必要时,ESP还可以降低发动机功率以帮助更快地恢复控制。当物理定律与人的本能相遇时,ESP帮助你保持在正确的路线上并保持控制。

因此,理解车辆动力学的一个很好的动机是,我们希望获得对车辆的控制权。控制实际上是下一讲的主要主题,但本讲首先侧重于更精确地理解车辆的行为。

基本概念:运动学与动力学

现在,让我们介绍一些非常基础和核心的概念,我们将按顺序构建这些概念,以理解车辆运动学和动力学。

首先定义的两个术语是运动学动力学

  • 运动学 源自希腊语,意为“运动”或“移动”。它描述点和物体的运动,特别考虑位置、速度、加速度以及更高阶的导数。运动学运动的例子包括天体运动、粒子系统、机械臂或人体骨骼的运动。在右侧,你可以看到一个图示,展示了位置、速度和加速度之间的关系。众所周知,它们通过各自的时间导数相关联:速度是位置的时间导数,加速度是速度的时间导数。如果我们沿着速度方向前进一小步(速度乘以时间),我们就到达了轨迹上的下一个位置。
  • 动力学 则描述运动的原因,即运动的根本原因。例如,力和力矩的影响。它包含了像牛顿第二定律这样的物理定律:F = m × a,即力等于物体的质量乘以它的加速度。这些都是非常基础的物理定律。

这两个概念在本讲中都扮演着基础角色。我们将首先推导不考虑力的运动学自行车模型,然后推导一个更现实的、考虑力和动力学的模型,即动力学自行车模型

完整约束与非完整约束

我们需要引入的另一个概念是构型空间上的约束,称为完整约束

  • 完整约束 是对构型的约束。例如,考虑一个在三维空间(X, Y, Z)中自由移动的粒子。我们可以通过将该粒子的Z坐标设置为0来约束它,使其只能在X-Y平面内移动。如果我们这样做,这个粒子就只能移动在由X和Y向量张成的平面内,因为我们只能修改X和Y的位置,而将Z位置固定为0。我们可以将此条件表达为粒子构型的函数等于0。在这个简单情况下,该函数就是Z。当然,可能存在更复杂的完整约束系统,例如机械臂,我们通过固定机械臂的手部(末端执行器)和基座来约束它,使得机械臂可以移动,但手部和基座保持固定。这种形式的约束(F(x, y, z) = 0)被称为完整约束。它们约束了构型空间。在这个例子中,我们将其约束在X-Y平面上。然而,系统可以在该约束空间内自由移动,这意味着可控自由度等于总自由度。在这个例子中,可控自由度是2,我们可以控制该粒子,在X和Y方向上施加力,并将其移动到X-Y平面上的任何位置。

另一方面,所谓的非完整约束是对速度的约束。例如,假设一个车辆,我们用一个非常简单的模型来参数化它。在这种情况下,该车辆被参数化(这是一个二维车辆的俯视图),参数包括车辆在二维坐标系中的X、Y位置(我们将车辆原点设在后轴中心),以及车辆的朝向角 ψ(Psi),即车辆前进方向与坐标系X轴之间的夹角。因此,我们有一个三维构型空间:x, y 和车辆朝向 ψ。给定这样一个模型,二维车辆速度可以描述为:x方向的速度(即x的一阶时间导数)等于速度大小乘以cos(ψ);y方向的速度等于速度大小乘以sin(ψ)。如果我们解第二个方程求速度v,并将其代入第一个表达式,最终只得到一个表达式:ẋ sin(ψ) - ẏ cos(ψ) = 0。这是一个对速度的约束,因为它包含了x和y的时间导数(即速度)。这里需要注意的重要一点是,这个约束是一个非完整约束,因为它不能表达为构型空间函数F(x, y, ψ) = 0的形式,这与之前的完整约束例子不同。这就是非完整约束与完整约束的区别:完整约束是对构型空间的约束,而非完整约束是对速度的约束。

这意味着这辆车实际上不能像上一张幻灯片中提到的粒子(那是一个完整约束的例子)那样自由地向任何方向移动。对于这个非完整约束,我们限制了车辆可以移动的方向。例如,它不能立即侧向滑动。我们只能向前移动并旋转车辆,但不能立即侧向移动。我们无法在这里进行侧方停车。因此,我们约束了速度空间,但没有约束构型空间。在这种情况下,可控自由度小于总自由度。我们可以控制两个自由度:速度(一维的速度大小,不是速度向量)和航向。我们可以控制这两个量来驾驶车辆,但我们不能直接控制构型。然而,尽管不能直接控制构型,我们最终仍然可以到达构型空间中的任何可能点。这在右侧进行了说明:我们约束了速度空间,但没有约束构型空间。因此,通过特定的停车操作,我们可以从这个位置到达那个位置(通过前进、后退等操作),但我们不能直接从A点直线移动到B点,因为这种运动被这个速度上的非完整约束所禁止。

总结完整系统与非完整系统:

  • 一个完整系统约束构型空间,这意味着我们可以在该约束空间内自由地向任何方向移动,并且可控自由度等于总自由度。这种约束可以用构型函数等于0来描述。一个例子是约束在X-Y平面上的三维粒子。
  • 相比之下,一个非完整系统约束速度空间。它不能自由地向任何方向移动,并且可控自由度小于总自由度。例如,在汽车中,我们只能控制两个自由度,但总自由度是三个。因此,这些约束不能以上述形式描述。一个例子就是具有这种速度约束的汽车。

需要注意的是,一个机器人可以同时受到完整约束和非完整约束的约束,汽车就是一个很好的例子。因为汽车是三维空间中的一个刚体(我们接下来会解释刚体的含义),它是一个作为一个整体在三维空间中移动的物体。因此,它实际上有六个自由度:三维空间中的位置和绕三个规范方向轴的朝向。但是,由于汽车通常在平坦的地面上行驶,从俯视图角度考虑它们就足够了。因此,我们可以使用三个完整约束将汽车保持在地面上:我们将Z坐标约束为0,并且还将车辆的侧倾角和俯仰角约束为0,同时不约束车辆的偏航角或航向角。这样我们就剩下了航向角和X、Y位置。然后,我们可以添加一个额外的非完整约束来防止侧向滑动,并确保我们建立的车辆模型像真实车辆一样运动,并受到与真实车辆相同的约束。

坐标系

理解了存在的系统类型后,现在让我们讨论坐标系,因为我们需要这些坐标系来定义后续的车辆运动。

在坐标系方面,我们考虑三种不同的坐标系:

  1. 惯性坐标系:这是世界坐标系,固定在地球上。其垂直的Z轴指向重力向量g的反方向,X和Y是水平面,这意味着Z轴垂直于X-Y平面。这是一个右手正交坐标系。
  2. 车辆坐标系:附着在车辆上,固定在车辆的一个参考点上(例如后轴中心)。X_V指向车辆前方,Y_V指向车辆侧方,Z_V指向车辆顶部(根据ISO 8855标准定义)。
  3. 水平坐标系:其原点与车辆坐标系的参考点相同。但X轴和Y轴是车辆坐标系X_V轴和Y_V轴在水平面上的投影。水平面由惯性坐标系的X和Y向量张成。因此,我们有效地移除了X-Y平面之外的任何可能旋转,使该坐标系位于X-Y平面内。

点的运动学

让我们继续讨论运动学。首先考虑一个点的运动学。我们已经提到,运动学涉及位置、速度和加速度等。

让我们看一个单点在三维空间中的运动学。在三维空间中,我们有由X, Y, Z指定的惯性坐标系,以及该三维点P的位置,由向量 r_P 指定。我们可以通过在任何时间t指定该向量 r_P 来指定该三维点的轨迹,这是一个三维向量 [x(t), y(t), z(t)]^T。显然,该点的速度是这个向量的一阶时间导数,加速度是这个位置向量 r_P 的二阶时间导数。

刚体的运动学

我们看了一个点的运动学,现在让我们看看刚体的运动学。

  • 刚体 指的是由无限多个无限小的质点组成的集合,这些质点刚性连接。这意味着它们的相对位置随时间保持不变。例如,刚体上任意两点C和P之间的相对距离保持不变。我可以旋转和平移这个刚体,但这些点之间的相对距离保持不变。
  • 刚体的运动可以简洁地描述为:一个任意参考点(我们称之为C)的运动,加上所有其他点P相对于C的相对运动。因此,我们可以指定点C及其运动,以及所有其他点相对于该点的运动,来描述刚体的运动。
  • 同样,C是固定在刚体上的参考点,P是刚体上的任意点。C的位置是 r_C,点P相对于C的位置是 r_C/P。该刚体的角速度由向量 ω 表示。角速度向量描述了刚体如何旋转,其长度 |ω| 指定了旋转的角速度大小,向量 ω 的方向是旋转轴。因此,刚体绕该轴 ω 旋转。
  • 由于点P相对于C存在这种相对关系,我们当然可以将P的位置描述为 r_C 加上 r_C/P,这表示为 r_P。类似地,我们也可以描述速度:刚体上任意点的速度是参考点C的速度加上一个旋转分量。因此,当我们描述刚体运动时,总有一个线性分量和一个旋转分量。旋转分量就是角速度向量 ω 与从C到P的相对向量的叉积。
  • 由于刚性,P上的点只能相对于C旋转。因此,刚体有六个自由度:三个用于位置,三个用于朝向。
  • 在每个时间实例t,存在一个特定的参考点O,称为瞬时旋转中心,该点的速度为零。刚体的每个点P都围绕该参考点O进行纯旋转,这意味着任何点的速度(由平移部分和旋转分量组成)仅包含旋转分量。

我们考虑的第一个例子是一个转动的轮子。在第一个例子中,这个轮子完全离地,这意味着它不接触地面,可以自由移动。轮轴在X或Y方向上不移动,它是固定的。它围绕瞬时旋转中心O旋转。角速度向量 ω 在这种情况下指向X-Y平面。现在,该转动轮子上任何点的速度(这里不再是三维,而是二维)可以描述为角速度(现在这不是向量,而是标量)乘以半径。因此,我们越靠近外侧,速度越大,运动越快。如果我们非常靠近旋转中心,速度向量接近于零;如果我们在旋转中心,速度向量为零。并且它随半径线性增加,如表达式所示:v_P = ω × r

让我们考虑第二个例子,一个滚动的轮子。在这种情况下,轮子在地面上无滑移地滚动。地面固定在X-Y平面,所以地面不能移动,因此轮子必须移动。角速度向量 ω 再次指向X-Y平面。在这种情况下,点P的速度是角速度 ω 乘以半径 r 的两倍。瞬时旋转中心(即存在纯旋转且没有平移速度的点)是轮子与地面的接触点。当然,这仅在特定时间实例t成立。如果我们稍微向前移动一点,进入未来,那个点也会移动。具体来说,在这种情况下,随着轮子向右移动,该点将沿着轮子和地面移动。因为所有这些点都围绕轮子与地面的接触点旋转,而不是围绕轮子的中心旋转,所以这些向量会发生变化,速度是 2ωr

本节课中我们一起学习了车辆动力学的基础导论,包括运动学与动力学的区别、完整与非完整约束的概念、三种重要的坐标系(惯性系、车辆系、水平系),以及点和刚体的基本运动学原理。这些概念是理解后续更复杂车辆模型(如运动学和动力学自行车模型)的基石。

017:车辆动力学 - 运动学自行车模型 🚗

在本节课中,我们将要学习运动学自行车模型。这是最重要且最简单的车辆模型之一。它基于许多简化假设,其中核心假设是车轮没有滑移。这意味着车轮始终沿着其朝向的方向运动,不会在地面上发生侧滑。因此,该模型主要适用于低速场景(如泊车)或已知无滑移效应的场景。在高速情况下,该模型的可靠性会降低。

刚性体与旋转中心

上一节我们介绍了车辆被视为刚性体的概念。本节中,我们来看看如何描述其运动。刚性体意味着车身上所有点的相对位置保持不变。我们可以将车辆的运动视为围绕一个旋转中心的转动。

当车辆围绕旋转中心转动时,车身上所有点都沿着各自的圆形轨迹运动,且速度方向始终与轨迹相切。这意味着,任何点的速度向量都垂直于连接该点与旋转中心的直线。这一关系可以用以下公式表达:

[
\vec{v} \perp \vec{r}
]

其中,(\vec{v}) 是点的速度向量,(\vec{r}) 是从旋转中心指向该点的向量。

模型的核心假设

以下是运动学自行车模型做出的几个关键简化假设:

  1. 双轮近似:将实际车辆的四轮系统简化为一个由前后两个“虚拟”车轮组成的自行车模型。这在许多建模场景中已足够。
  2. 平面运动:只考虑车辆在XY平面内的运动,忽略车辆的侧倾和俯仰,只保留描述车辆朝向的横摆角 (\psi)
  3. 无车轮滑移:假设车轮的滚动方向始终与其自身的朝向一致。这是该模型称为“运动学”模型的原因,它忽略了轮胎的动力学滑移效应。

模型参数详解

现在,让我们详细定义模型中的各个参数。参考下图,我们可以识别出以下关键量:

  • (\psi)横摆角。车辆纵轴线(连接前后轮中心的黑线)与全局坐标系X轴之间的夹角,代表车辆的“朝向”。
  • (\delta_f, \delta_r)前轮转向角后轮转向角。分别表示前轮和后轮相对于车辆纵轴线的偏转角度。
  • (v):车辆质心速度的大小。
  • (\beta)车辆侧偏角。这是车辆质心速度向量的方向与车辆纵轴线(朝向 (\psi))之间的夹角。请注意:虽然模型假设车轮无滑移,但车辆整体是可以有侧偏角的。
  • 航向角:车辆质心速度向量的方向,等于 (\psi + \beta)。
  • (L)轴距。前后轮中心之间的距离,(L = l_r + l_f),其中 (l_r) 和 (l_f) 分别是质心到后轴和前轴的距离。
  • (R)转弯半径。从旋转中心到车辆质心的距离。

运动方程推导

基于上述模型,我们的目标是推导出描述车辆如何移动和转动的运动方程。我们想知道车辆位置 ((x, y)) 和横摆角 (\psi) 随时间的变化率,即它们的导数 (\dot{x}, \dot{y}, \dot{\psi})。

首先,位置的变化率(即速度)很容易从几何关系得出:

[
\dot{x} = v \cdot \cos(\psi + \beta)
]
[
\dot{y} = v \cdot \sin(\psi + \beta)
]

接下来,推导横摆角变化率 (\dot{\psi})(即横摆角速度)更为复杂。为了简化,我们考虑一个更常见的情况:仅前轮转向(即 (\delta_r = 0))。大多数民用车辆都属于这种情况。

仅前轮转向的简化推导

在仅前轮转向的设定下,我们可以利用简单的三角几何来推导 (\dot{\psi})。观察下图中的几何关系:

以下是推导步骤:

  1. 在红色三角形中,根据正切定义有:(\tan(\delta) = \frac{L}{R'}),其中 (R') 是旋转中心到后轮的距离。由此可得 (1/R' = \tan(\delta) / L)。
  2. 同样在红色三角形中,有 (\tan(\beta) = l_r / R')。将第一步的 (1/R') 代入,得到 (\tan(\beta) = l_r \cdot \tan(\delta) / L)。
  3. 考虑质心处的转弯半径 (R),有 (\cos(\beta) = R' / R),因此 (1/R = \cos(\beta) / R')。
  4. 质心处的角速度 (\dot{\psi}) 等于线速度除以转弯半径:(\dot{\psi} = v / R)。
  5. 将第3步的 (1/R) 代入第4步,再将第1步的 (1/R') 代入,最终得到:

[
\dot{\psi} = \frac{v}{L} \cos(\beta) \tan(\delta)
]

这就是仅前轮转向时,车辆横摆角速度的表达式。

小角度近似

当车辆近似直行或转向角很小时(即 (\delta) 和 (\beta) 很小),我们可以对模型进行进一步简化:

  • (\cos(\beta) \approx 1)
  • (\tan(\delta) \approx \delta) (因为 (\tan) 函数在原点附近近似线性)

此时,运动方程简化为:

[
\dot{x} = v \cdot \cos(\psi)
]
[
\dot{y} = v \cdot \sin(\psi)
]
[
\dot{\psi} = \frac{v}{L} \delta
]

这个简化形式非常直观,广泛应用于路径规划和控制的初步分析中。

离散时间模型

为了在计算机中模拟车辆运动,我们需要离散时间版本的运动方程。假设时间步长为 (\Delta t),则车辆状态更新公式为:

[
x_{t+1} = x_t + v \cdot \cos(\psi_t) \cdot \Delta t
]
[
y_{t+1} = y_t + v \cdot \sin(\psi_t) \cdot \Delta t
]
[
\psi_{t+1} = \psi_t + \frac{v}{L} \delta \cdot \Delta t
]

阿克曼转向几何

最后,我们需要讨论一个重要的实践问题:阿克曼转向几何。在真实的四轮车辆中,如果直接将自行车模型的前轮转角 (\delta) 同时应用于左右两个前轮,会导致轮胎滑移。

为了避免滑移,在转弯时,内外侧前轮的转向角应该不同。连接旋转中心与左右前轮中心的直线并不重合,因此为了满足“速度方向垂直于旋转半径”的无滑移条件,左右轮的朝向(即转向角 (\delta_L) 和 (\delta_R))必须不同。

满足运动学自行车模型约束的左右轮转向角关系,就称为阿克曼转向几何。当转向角较小时,可以近似计算为:

[
\delta_L \approx \frac{L}{R} + \frac{B}{2R}
]
[
\delta_R \approx \frac{L}{R} - \frac{B}{2R}
]

其中,(B) 是后轮轮距(左右后轮之间的距离)。

在实际车辆中,通常通过一个梯形转向机构来实现近似阿克曼几何。该机构在转向时,能自动让内侧车轮比外侧车轮转过更大的角度,从而减少轮胎磨损并满足运动学约束。

总结

本节课中我们一起学习了运动学自行车模型。我们首先了解了其核心假设:将四轮车辆简化为两轮、仅考虑平面运动、并假设车轮无滑移。然后,我们详细定义了模型的各个状态量和参数,包括横摆角、转向角、侧偏角和轴距等。

接着,我们推导了描述车辆运动的微分方程,并特别针对常见的仅前轮转向情况,利用三角几何得到了横摆角速度的表达式。在小角度条件下,该模型可以进一步简化。我们还给出了用于计算机仿真的离散时间更新公式。

最后,我们探讨了模型在实际应用中的一个关键点——阿克曼转向几何,解释了为什么真实车辆的左右前轮转向角不同,以及如何通过机构设计来实现它。

运动学自行车模型因其形式简单、计算高效,成为自动驾驶领域进行轨迹规划、控制和状态估计的基础模型之一,尤其在低速场景下非常有效。

018:轮胎模型 🚗

在本节课中,我们将要学习轮胎模型。理解轮胎对于理解施加在车辆车轮上的力与车轮发生的滑移之间的关系至关重要。

概述

上一节我们介绍了车辆动力学的基础,本节中我们来看看轮胎模型。为了理解施加在车轮上的力与车轮滑移之间的关系,我们必须理解轮胎。

通过观看这段视频,可以清楚地看到这辆车没有遵循运动学自行车模型。因此,运动学自行车模型是不够的。在这种情况下,运动学自行车模型的哪个假设被违反了?

显然,车轮发生了滑移。每个车轮都存在一个滑移角。因为我们假设运动学自行车模型没有滑移,所以该模型在这里被严重违反。当然,这是一个极端情况,但在现实中,车轮总是存在轻微的滑动。它们永远不会完美地遵循运动学自行车模型。这当然取决于地形和地面类型,例如是冰面、草地还是沥青路面。但总是存在一些滑移,因此我们需要超越目前所学的运动学自行车模型。

为了超越并理解什么是滑移以及滑移与力之间的关系,我们需要更好地理解轮胎。

轮胎基础

这是一个轮胎的例子。它由橡胶制成,内部充满加压空气。基于气压和车辆重量,轮胎与地面在一个称为接触斑块的区域接触,该区域定义了车轮与地面之间的接触。

现在,我们可以对车轮的轴施加一些力,这意味着车轮开始向前移动。但由于车轮与地面之间没有完美的接触,总是存在轻微的滑动,车轮的旋转速度不会完全等同于车辆向前移动的速度。这两者之间的差异被称为滑移。

我们将使用轮胎模型来描述施加在轮胎上的横向力和纵向力。存在许多不同复杂程度的轮胎模型,甚至深入到分子级别。但我们将在这里使用一个非常简单的定性描述,称为胎面块模型,它很好地说明了基本现象和力曲线的定性行为。

胎面块模型

我们试图回答的问题是:轮胎为什么会滑移?它们究竟如何滑移?这与施加在轮胎上的力有何关系?

我们将考虑胎面块模型。它之所以被称为胎面块模型,是因为我们在宏观层面上将轮胎视为由许多小胎面块组成。你可以看到,这里的每一个小块基本上都是一块附着在轮胎上的橡胶。图中只显示了轮胎的底部。在这个例子中,你可以看到五个这样的胎面块。从图中已经可以看出,这些胎面块看起来并不相同,只有这里的这个胎面块处于其标准位置和标准形状,而其他这些则是它的变形版本。

它们为什么会变形?一旦车辆被外部驱动,一旦我们施加一个力,即对车轮施加一个周向力,这个胎面块就开始变形和滑移。

我们对车轮施加一个力。想象一下,从一个速度为零的车辆车轮开始施加力。这意味着,为了推动车辆前进(因为车辆有质量),我们需要施加一个相对于地面的力。这个力必须通过这些胎面块传递。

现在发生的情况是,一旦一个胎面块进入接触斑块(即轮胎与地面接触的区域),这个力就会通过使胎面块变形而逐渐建立起来。胎面块向后移动得越多,力就越大。这由下图所示。沿着这个接触区域移动得越多,胎面块变形就越大。然后,一旦胎面块离开接触区域,它就会弹回其原始位置。基本上,在离开接触区域后,它又恢复成这样。

这已经是产生滑移的原因。你可以看到,这些胎面块为了传递力以对地面施加力而发生变形。因此,在这个区域,车轮的速度与如果它与地面完美接触时的速度不同,因为这个力是通过这些变形的胎面块传递的。所以,基本上你通过这个现象产生了滑移。轮胎胎面块接触地面时,它们变形并滑移。当失去接触时,就会发生滑移,因为它们变形然后滑移。因此,车轮的速度和地面的速度不相同。

静摩擦与滑动摩擦

这被称为静摩擦。之所以称为静摩擦,是因为胎面块在变形时始终与地面保持接触,它们没有在地面上滑动。然而,当车轮的驱动力增加并超过最大静摩擦力时,就会进入滑动摩擦区域。这个最大摩擦力取决于轮胎材料和地面材料的分子特性,例如是沥青还是冰面等。

一旦超过这个最大静摩擦力,我们就进入了滑动摩擦区域,这些胎面块开始更早地滑移。它们不是在最后弹回原始位置时才滑移,而是可能在这里就已经开始失去与地面的接触,因为力太强了。这就是我们所说的滑动摩擦。

这意味着,在下图的第一部分,胎面块仍然与地面接触,因此行为与此处相同。但在这一点,它们开始滑动。由于滑动摩擦力小于静摩擦力,这会导致传递的驱动力下降,这基本上是我们想要避免的。

例如,如果你在红灯起步时对车轮施加过大的力,你将无法快速移动,因为你立即进入了滑动摩擦区域。同样的情况也发生在高速时突然猛烈刹车,你也会进入滑动摩擦区域。因此,在这种情况下,如果胎面块从一开始就滑动,只能施加滑动摩擦力。滑动摩擦力低于静摩擦力,这是你想要避免的。这也是现代制动系统,如防抱死制动系统(ABS)所做的事情。一旦它们检测到滑移过大,就会开始释放车轮的制动,以便仍然能够操控车辆。我们稍后会讨论为什么否则无法操控车辆。

但总的来说,我们也要避免滑动摩擦,因为它低于静摩擦。如果没有ABS,我们就无法如此有力地刹车,无法像有该系统那样快速停下来。

滑移与力的关系曲线

这是另一条曲线,它绘制了相对于滑移率S可以施加在车辆上的力。其中滑移率是车轮表面速度与车辆速度之间的差异,它是一个相对数值。这意味着,如果车轮与地面完美接触且没有滑移,滑移率S将为0,因为此时车轮表面速度与车辆速度相同。例如,当你以恒定速度行驶,没有加速或减速,并且没有力施加在车辆上时,就会发生这种情况。比如在低速行驶时,没有其他力作用在车辆上,并且你没有对车轴施加任何力。

现在,我们可以在这张图中看到,曲线看起来是这样的。我们还可以看到,力F在开始时随着滑移率S线性增长。这是胎面块变形但仍与地面接触的区域。但在某一点,当我们达到静摩擦极限,滑移率变得太大时,这会导致F减小。我们处于滑动摩擦部分。滑动摩擦再次小于静摩擦,因此我们总是希望避免这种情况,例如通过像ABS这样的系统。

低摩擦路面的变化

现在,对于湿滑的低摩擦路面,这条F(S)曲线会如何变化?给你一点时间思考这个问题。你认为它会如何变化?

曲线的起点不会改变。因为胎面块的弹性没有改变,我们观察的是相同的轮胎、相同的橡胶材料,胎面块的变形方式相同。然而,由于静摩擦力减小,可以施加的最大力会降低,因为可能地面不像沥青那样,而是冰面。因此,我们无法再施加相同的最大力。所以,胎面块由于摩擦力的减小而更早开始滑动。这由这里的曲线说明。因此,定性地看,两条曲线看起来相似。在开始时,两者都是线性的,但对于低摩擦曲线,可以施加的最大力更小,因此我们也更早开始滑动。

横向力分析

以上是针对纵向力和纵向滑移的分析,但我们可以对横向力进行同样的分析,实际上这里的图表看起来非常相似。在这种情况下,我们看的是力,我们称之为Fy,即横向力,指向车辆侧面。力相对于滑移率的图表看起来相似,开始时有一个线性部分,然后当我们达到最大力时,就进入滑动摩擦区域,我们也希望避免横向滑动。

因此,横向力Fy与纵向力类似,但现在胎面块是横向移动。对于小的滑移率S和小的车轮滑移角α,横向力由以下表达式给出:

Fy = C * α

其中C是一个称为侧偏刚度的常数,α是该车轮的滑移角,即车轮的前进方向与该车轮实际移动速度方向之间的夹角。我们这里不推导这个公式,暂时接受这个事实。因此,近似地,我们有Fy = C * α,这从图中看也是合理的。如果α为0,那么你实际上遵循运动学自行车模型,该车轮没有滑移角,车轮速度方向与车轮朝向相同。但如果α很大,那么我们有一个大的滑移角,车轮的速度具有很大的横向分量,因此我们正在横向滑动。

力圆现象

另一个值得讨论的有趣现象是所谓的力圆。力圆告诉我们,可以施加在车轮上的横向力和纵向力并不是独立的,因为它们不能超过一个最大摩擦力Fmax。所以我们有这个圆,所有我们可以施加在该车轮上的力都位于这个圆内。我们无法施加更强的力。这意味着更大的纵向力意味着更小的横向力,或者说最大加速度只能用于直线行驶。

例如,考虑你想从50公里/小时的速度完全停下来,你猛踩刹车,导致你在纵向方向上开始滑动。这意味着你现在无法再转向了。车辆变得完全无法操控,无法转向。这当然是不好的。因此,你应该做的是,如果你想避开一个障碍物,并且仅仅因为速度太快而无法通过刹车来避开障碍物,你不应该刹车那么猛,而应该转向绕过那个障碍物。在防御性驾驶课程中学到的是,开始时猛踩刹车,但随后松开刹车以便转向绕过物体,避免与物体接触。当然,这也是防抱死制动系统背后的动机。它只是避免你进入曲线的滑动阶段,因此即使完全踩下刹车,你仍然能够操控你的车辆。

这不仅允许我们对施加在车轮上的力做出陈述,而且可以对整个车辆可以施加的加速度做出类似的陈述,因为车辆有四个车轮,如果这对所有四个车轮都适用,那么车辆加速度也有类似的行为。这就是我刚才提到的,如果你想完全停下来,你就不能再进行横向加速,所以你总是需要在这两者之间权衡。同样,如果你遇到强烈的侧风,但你已经超过了纵向的X方向加速度,那么与没有加速时相比,你会受到侧风更强烈的影响。

总结

本节课中我们一起学习了轮胎模型。我们了解到,由于轮胎胎面块的变形和滑移,车辆在现实中总会存在滑移,这超越了运动学自行车模型的假设。我们通过胎面块模型定性地理解了静摩擦与滑动摩擦的区别,以及力与滑移率之间的关系曲线。我们还学习了横向力的近似公式 Fy = C * α,并认识了力圆的概念,它揭示了纵向力与横向力之间的制约关系,这对于理解车辆操控极限和防抱死制动系统(ABS)等安全系统的工作原理至关重要。

019:车辆动力学 - 动态自行车模型 🚗

在本节课中,我们将学习如何定义动态自行车模型。我们将从最基本的模型形式入手,该模型考虑了轮胎的横向滑移。

概述

上一节我们介绍了考虑轮胎滑移的必要性。本节中,我们将基于刚体动力学原理,推导出最简单的动态自行车模型方程。我们将从单个质点的运动开始,逐步扩展到刚体的平动与转动,最终将这些原理应用于车辆模型。

刚体动力学基础

在定义车辆模型之前,让我们先回顾一下质点和刚体的动力学。

质点的平动

首先,考虑三维空间中的一个质量为 M 的质点 P。设向量 r 表示该质点的位置,v 表示其速度,a 表示其加速度。

该质点的线性动量 p 定义为:

p(t) = M * v(t)

根据牛顿第二定律,线性动量的时间导数等于作用在该质点上的净力:

d(p)/dt = M * a(t) = Σ F

其中,Σ F 是所有作用在质点 P 上的力的矢量和。

刚体的平动与转动

现在,考虑一个质量为 M 的刚体 B。设其质心 C 的位置为 r,速度为 v_c,加速度为 a_c

刚体的线性动量定义为:

P_B(t) = M * v_c(t)

刚体的质心运动就像一个质量为 M 的质点,因此有:

M * a_c = Σ F

其中,Σ F 是所有作用在刚体上的力的矢量和。

然而,刚体不仅有平动,还有转动。其转动运动与刚体的几何形状和质量分布有关。

ρ 为刚体的质量密度函数。刚体的总质量为:

M = ∫_B ρ dV

我们定义刚体的惯性张量 I 为一个矩阵,其元素由以下公式定义:

I = [ ∫ (y²+z²)ρ dV,  -∫ xyρ dV,      -∫ xzρ dV;
      -∫ xyρ dV,       ∫ (x²+z²)ρ dV, -∫ yzρ dV;
      -∫ xzρ dV,       -∫ yzρ dV,      ∫ (x²+y²)ρ dV ]

考虑刚体的转动。设角速度向量为 ω。刚体绕该向量旋转,旋转速率等于该向量的模长。

刚体关于质心 C角动量 L_c 定义为:

L_c = I * ω

根据角动量原理,角动量的时间导数等于作用在刚体上的净力矩:

d(L_c)/dt = I * (dω/dt) = Σ M_c

其中,Σ M_c 是所有力关于质心 C 的力矩之和。力矩等于力乘以力臂。

简化情况

在某些情况下,问题可以得到简化。如果我们选择的体坐标系与刚体的主轴系(对称轴)对齐,则惯性张量 I 是对角矩阵。

对于我们关心的车辆运动,通常假设车辆在 XY 平面内运动(俯视图)。此时,绕 X 轴和 Y 轴的角速度及力矩均为零。因此,角动量退化为一个标量:

L_c = I_zz * ω_z(t)

角动量原理也简化为标量方程:

I_zz * (dω_z/dt) = Σ M_z

动态自行车模型定义

有了这些动力学基础,现在让我们回到车辆模型,定义考虑力和轮胎滑移的动态自行车模型。

我们考虑一个具有前轮转向角 δ 的自行车模型,后轮与车辆方向对齐。对于这个最简单的动态自行车模型,我们做出以下关键假设:

  1. 车辆运动被限制在 XY 平面(俯视图)。
  2. 车辆被视为一个刚体。
  3. 仅考虑由线性轮胎模型产生的横向轮胎力,忽略纵向力。
  4. 假设转向角 δ 很小,因此有:sin(δ) ≈ δ, tan(δ) ≈ δ, cos(δ) ≈ 1
  5. 假设纵向速度 V_x 恒定。

在这些假设下,我们来推导模拟车辆运动所需的方程。

横向动力学方程(平动)

首先考虑横向(侧向)动力学。根据牛顿第二定律,在横向(Y方向)上有:

M * a_y = Σ F_y

作用在车辆上的横向力来自两个轮胎。因此:

M * a_y = F_r + F_f

其中,F_r 是后轮横向力,F_f 是前轮横向力。由于 δ 很小,前轮力在车辆Y方向的分量近似为 F_f 本身。

车辆质心的横向加速度 a_y 由两部分组成:横向速度 V_y 的变化率,以及由于车辆旋转(角速度 ω)产生的向心加速度 ω * V_x。因此:

a_y = d(V_y)/dt + ω * V_x

结合以上两式,得到第一个基本方程:

M * [ d(V_y)/dt + ω * V_x ] = F_r + F_f

横摆动力学方程(转动)

接下来考虑转动(横摆)动力学。根据简化后的角动量原理:

I_zz * (dω/dt) = Σ M_z

作用在车辆上的力矩由轮胎力乘以相应的力臂产生:

  • 后轮力 F_r 产生的力矩为 -l_r * F_r(负号表示其方向与正转向相反)。
  • 前轮力 F_f 产生的力矩为 +l_f * F_f(正号表示其方向与正转向相同)。

因此,得到第二个基本方程:

I_zz * (dω/dt) = -l_r * F_r + l_f * F_f

轮胎力模型

现在,我们需要定义轮胎力 F_rF_f。根据上一节的内容,在轮胎特性曲线的线性区域,横向力与轮胎侧偏角 α 成正比。

对于后轮(无转向角):

F_r = -C_α_r * α_r

其中,C_α_r 是后轮侧偏刚度,负号表示力方向与图示定义的侧偏角方向相反。对于小侧偏角,有 α_r ≈ tan(α_r) = V_{r,y} / V_{r,x}

对于前轮(有转向角 δ):

F_f = -C_α_f * α_f

其中,C_α_f 是前轮侧偏刚度。α_f ≈ tan(α_f) = V_{f,η} / V_{f,ξ},这里 ηξ 是以前轮平面定义的坐标系。

轮胎处的速度

我们需要计算轮胎接地点的速度,以确定侧偏角。

后轮速度(与车辆方向一致):

  • 纵向速度:V_{r,x} = V_x
  • 横向速度:V_{r,y} = V_y - ω * l_r (减去因旋转产生的速度分量)

前轮速度(在车辆坐标系XY下):

  • 纵向速度:V_{f,x} = V_x
  • 横向速度:V_{f,y} = V_y + ω * l_f (加上因旋转产生的速度分量)

为了得到前轮平面(ξ-η坐标系)下的速度,需要进行旋转变换,旋转角为前轮转向角 δ。利用小角度假设 cos(δ)≈1, sin(δ)≈δ,并假设纵向速度远大于某些横向速度分量,可以得到简化后的表达式:

V_{f,ξ} ≈ V_x
V_{f,η} ≈ V_y + ω * l_f + V_x * δ

闭合方程与状态空间形式

将轮胎速度表达式代入轮胎力公式,再将得到的 F_rF_f 代入之前推导的横向与横摆动力学方程,经过整理,我们可以得到一个闭合的系统方程。

这个系统可以写成简洁的状态空间表示形式。定义状态向量为:

x = [ V_y,  ψ,  ω ]^T

其中,V_y 是车辆横向速度,ψ 是车辆横摆角(航向角),ω 是横摆角速度。

系统的状态方程可以写为:

d(x)/dt = A * x + B * u

其中,输入 u 就是前轮转向角 δ。矩阵 AB 中的元素由车辆质量 M、转动惯量 I_zz、轴距 l_f, l_r 以及轮胎侧偏刚度 C_α_f, C_α_r 等参数决定。

通过这个状态空间模型,我们可以模拟车辆在给定转向角输入序列下的动态响应,即计算出 V_yψω 如何随时间变化。如果需要全局位置,可以额外添加方程,但会使模型变为非线性。

总结

本节课中,我们一起学习了动态自行车模型的推导。我们了解到:

  1. 车辆可以被建模为一个受完整和非完整约束的刚体。
  2. 自行车模型用两个车轮来近似四轮车辆。
  3. 运动学自行车模型假设无轮胎滑移,仅适用于低速场景。
  4. 要准确建模轮胎行为,必须考虑滑移,正如赛车漂移例子所示。
  5. 滑动摩擦力小于静摩擦力,因此我们应确保轮胎工作在静摩擦(即力-滑移率曲线的线性区域)。
  6. 摩擦力圆概念表明,轮胎的纵向力和横向力是相互耦合、此消彼长的。
  7. 动态自行车模型通过引入基于侧偏角的线性轮胎力模型,在一定程度上考虑了轮胎滑移的影响,从而能够描述车辆在更宽泛工况下的动力学特性。

通过本讲推导的状态空间方程,我们获得了对车辆横向及横摆动态进行仿真和分析的基础工具。

020:车辆控制简介 🚗

在本节课中,我们将要学习车辆控制的基本概念。车辆控制是自动驾驶汽车和现代驾驶辅助系统的核心模块,它负责将规划好的路径或指令转化为车辆的实际操控命令,如方向盘转角和油门/刹车控制。


控制问题与动机

首先,我们介绍控制问题并阐述为什么需要控制系统。

自动驾驶汽车需要车辆控制模块,现代驾驶辅助系统同样需要。例如,上一讲提到的电子稳定程序(ESP)通过独立控制每个车轮来提升车辆操控性,降低高动态场景下的事故风险。因此,精密的控制器已广泛应用于当今的汽车中。

以下是使用此类控制系统的驾驶辅助系统发展简史:

  • 1926年:伺服制动系统。
  • 1951年:伺服转向系统。
  • 1958年:定速巡航系统,用于将车速控制到设定值。
  • 1978年:防抱死制动系统(ABS)。
  • 1986年:牵引力控制系统(ASR)。
  • 1995年:电子稳定程序(ESP)。
  • 2000年代:自适应巡航控制(ACC),使用传感器探测前车距离并自动调整车速。
  • 2002年:紧急制动辅助、车道保持辅助、自动泊车等。

所有这些系统都需要对车辆的精确了解和有效控制。


开环与闭环控制

控制系统主要分为两种类型。第一种称为开环控制器。

开环控制器之所以得名,是因为它不具备我们接下来要讲的闭环控制器那样的反馈“回路”。下图展示了一个开环控制器的结构。

我们使用统一的变量来描述这个过程。控制器的输入(图中橙色部分)是参考变量或设定点 R(t)(t 是时间索引)。例如,在定速巡航系统中,这可以是我们想要达到的目标速度。

控制器随后输出一些校正变量,作为被控过程(图中绿色部分)的输入。控制器的设计目标是计算这些校正变量,使得被控变量 y 能尽快达到参考值 R

然而,过程还会受到干扰 z(t) 的影响,这些是环境效应,我们可能无法完全预测。正如下一点所述,开环控制在实际中难以实施。

开环控制要求对过程及其所有影响因素有精确了解。由于没有关于被控变量的反馈,控制器无法得知其当前状态,也无法处理未知干扰,因此容易导致系统漂移。现实中几乎总存在未知干扰,所以我们需要所谓的闭环控制器。

下图展示了闭环控制器的结构。

唯一的变化是,现在我们有一个传感器来测量过程,并将测量值反馈给控制器。具体来说,参考变量 R(t) 与测量值相减,其结果我们称为误差 e(t)

控制器现在的任务比之前简单得多:它只需要将这个误差减小到0。我们希望测量值变得与参考变量相同。由于有这个明确的反馈回路,控制器可以输出校正变量给过程,使得误差 e(t) 随时间减小。这被称为闭环控制,因为图中存在一个闭合的反馈回路。


经典控制实例:离心调速器

控制器历史悠久,离心调速器可能是最著名也是最早的控制系统实例之一,它可用于控制蒸汽机等设备。以下视频片段解释了其工作原理。

离心调速器是一种通过调节工作流体的输入来控制机器运行速度的装置。由詹姆斯·瓦特于1788年发明,成为驱动工业革命的许多机器的基本组件。最常见的是安装在蒸汽机上。动力通过皮带和飞轮连接从发动机输出轴传递给调速器,随着发动机运行,调速器开始旋转。调速器操作节流阀,当其旋转速度越快,作用于飞球的离心力使它们克服重力向外和向上移动,带动杠杆臂。随着杠杆臂弯曲,它们拉下一个垂直轴,使其进入节流阀并减小蒸汽通过的间隙。如果调速器旋转得足够快,轴将完全切断蒸汽进气口。调速器的使用在工业革命期间及之后对于大型发动机和机械的运行至关重要。如果发动机运行过于剧烈,则有震散的风险。此外,在大型工厂中,许多相同的机器(如纺织厂的动力织机)配置为由单一发动机驱动,必须始终保持恒定、平稳和稳定的速度,否则生产的产品会不规则。博物馆中可以找到许多离心调速器的例子,设计用于安装在蒸汽机和水轮机上,尽管大小和复杂程度不同,但每一个都是其机器同样关键的组成部分。

这是一个非常直观的控制器示例。


本讲将涉及的控制器类型

本课程中我们将考虑闭环控制,因为这是对车辆唯一有意义的控制方式。车辆需要在纵向(速度)和横向(方向)上都被控制。

我们将探讨三种不同类型的控制器:

上一节我们介绍了控制的基本概念,本节中我们来看看具体的控制器类型。以下是本讲将详细讲解的三种控制器:

  • 黑盒控制器:这是最通用的闭环控制器形式,它不需要关于过程的任何知识。过程对控制器来说就像一个黑盒,控制器唯一的目标就是最小化前面提到的误差 e(t)
  • 几何控制器:与黑盒控制器相反,几何控制器(特指为车辆设计的)利用关于车辆的知识。它们利用车辆与路径之间的几何关系,从而形成用于路径跟踪的紧凑控制器。在这个背景下,我们将再次回顾我们熟悉的自行车模型。
  • 最优控制器:最优控制器也利用系统模型,但可能方式更明确。它们通过最小化未来时间步长的目标函数来进行控制,具有更长的“前瞻”潜力。它们优化起来更困难,但在非常动态的驾驶场景中能带来更好的结果。

总结

本节课中我们一起学习了车辆控制的基础。我们首先明确了控制问题的必要性,并回顾了驾驶辅助系统中的控制应用。接着,我们区分了开环控制和闭环控制,理解了反馈机制对于应对现实世界干扰的重要性。通过离心调速器的例子,我们看到了一个经典的控制系统实现。最后,我们概述了本课程将要深入探讨的三种控制器类型:黑盒控制器、几何控制器和最优控制器,为后续的学习奠定了基础。

021:车辆控制 - 黑盒控制 🚗

在本节课中,我们将要学习第一类控制器——黑盒控制器。我们将了解其基本概念、工作原理,并通过具体例子理解其在自动驾驶车辆控制中的应用。

概述

黑盒控制器之所以得名,是因为它们不依赖于对被控过程内部机理的了解。因此,它们具有通用性,可以潜在地应用于任何过程。本节我们将从最简单的黑盒控制器开始,逐步深入到工业中最常用的PID控制器。

黑盒控制器简介

上一节我们介绍了控制系统的整体框架,本节中我们来看看黑盒控制器的具体形式。

黑盒控制器不假设了解被控过程的内部知识,因此具有通用性,可以潜在地应用于任何过程。

开关控制器

最简单的黑盒控制器形式称为开关控制器。

开关控制器也称为滞环控制器,常用于家用恒温器等场景。它之所以被称为开关控制器,是因为它在两种状态之间 abrupt 切换。

该控制器的数学公式很简单。我们需要定义从误差 E 到校正变量 U 的映射。

开关控制器的工作原理如下:

以下是其最简单的形式:

  • 如果误差高于阈值 τ,则 U 定义为 U1(控制器的一个参数)。
  • 否则,U 定义为 U2(控制器的另一个参数)。

因此,这个最简单的控制器有3个参数:U1U2τ。以恒温器为例,如果温度低于某个阈值,它会输出校正变量 U1(例如打开加热);否则输出 U2(例如关闭加热)。

然而,这种简单的控制器对于控制汽车来说效果不佳,会导致非常颠簸和不舒适的行为。我们需要更好的方案。

PID控制器

更好的方案是PID控制器,它同样属于黑盒控制器。

PID控制器是工业应用中最常见的控制器,因其简单性和广泛的应用范围,在约95%需要控制器的场合中被使用。

PID控制器同样不需要了解被控过程的内部知识。与开关控制器不同,它包含三个部分:

  1. 比例环节:输出一个与误差成比例的校正值。公式为 Kp * E(t),其中 Kp 是比例增益参数。
  2. 积分环节:对所有先前时间步的误差进行积分。公式为 Ki * ∫E(t) dt,其中 Ki 是积分增益参数。
  3. 微分环节:计算误差随时间的变化率(导数)。公式为 Kd * dE(t)/dt,其中 Kd 是微分增益参数。

PID控制器的数学公式如下:

U(t) = Kp * E(t) + Ki * ∫E(t) dt + Kd * dE(t)/dt

控制器输出 U 是这三个部分乘以各自参数后的总和,作为校正变量传递给被控过程。

为什么需要三个环节?

这三个环节各有不同的作用:

  • 比例环节 是最重要的,它确保我们实际在控制过程,使误差按增益 Kp 成比例地减小。
  • 单独使用比例环节 在实践中往往效果不佳,通常会导致超调和振荡。因为当误差减小到零时,控制器没有意识到已经达到目标,会继续向反方向调整,从而产生符号相反的误差。
  • 微分环节 的加入可以缓解这个问题。它引入了阻尼行为,从而避免超调或振荡。仅有比例和微分环节的控制称为PD控制。
  • 积分环节 能够通过累积过去的误差测量值来校正稳态误差。包含全部三个环节的才是完整的PID控制器。

控制器行为示例

为了更直观地理解,让我们看一个比例控制器和比例微分控制器的例子。

首先,理解用于生成这些图的系统。被控变量是位置 y(t) = x(t)。校正变量 u(t) 是加速度,而加速度是位置的二阶时间导数。因此,这是一个简单的双重积分器系统:输入 u(加速度),经过两次积分后输出 y(位置)。

假设我们想让一辆初始位置为0的汽车向前移动1米。参考信号(蓝色)在20个时间步后从0阶跃到1。

纯比例控制

我们实现了一个比例控制,比例增益 Kp = 0.05,微分增益 Kd = 0

仿真结果(红色虚线)并不理想。车辆开始加速,但由于是纯比例控制,它没有意识到误差已减小到0,因此继续运动并超调。由于系统的质量和惯性,减速和加速一样慢,车辆需要一直运动到2米处才能完全停止。然后它开始反向加速,再次超调,最终停止在起始点0。结果是围绕目标值持续大幅振荡。

如果将比例增益增加到 Kp = 0.5,振荡会变得更快,但仍然存在振荡行为,永远无法达到并维持参考值的稳态。

这说明了单独使用比例控制器的问题。

比例微分控制

现在,我们加入微分环节,构成PD控制器(Kp = 0.05, Kd = 0.1)。

振荡行为得到了阻尼。因为微分环节让我们知道正在接近目标值,所以超调量减少。每次摆动都超调更少,直到在目标值附近达到稳定。

如果将微分增益增加到 Kd = 0.5,阻尼效应更强。在这个简单系统中,甚至可以完全避免超调,快速达到参考值并保持稳定。

这个例子说明了在比例控制器中加入微分环节的重要性。对于像双重积分器这样的系统(在自适应巡航控制等场景中很常见),这非常关键。

参数整定:齐格勒-尼科尔斯方法

那么,如何最优地选择这些增益参数呢?

由于PID控制器常用于控制黑盒过程,我们需要启发式方法。最常用的是齐格勒-尼科尔斯方法。

该启发式算法很简单:

  1. 首先,将积分和微分增益设为0。
  2. 仅使用比例控制器,从0开始增加比例增益 Kp,直到系统出现持续振荡。此时的增益称为最终增益 Ku
  3. 测量在 Ku 下的振荡周期 Tu
  4. 根据以下通过计算机仿真经验推导出的公式设置参数:
    • Kp = 0.6 * Ku
    • Ki = 2 * Kp / Tu
    • Kd = Kp * Tu / 8

这些启发式值提供了一个良好的起点。但在实践中,通常需要根据具体问题进行手动微调,以使控制器达到最佳性能。

在车辆控制中的具体应用

现在,让我们看看PID控制器在车辆控制中的一些具体应用示例。

纵向车辆控制(速度控制)

纵向控制指控制车辆的速度。变量定义如下:

  • 参考变量 R(t):目标速度 v(t)
  • 校正变量 U(t):油门和刹车踏板设置(影响加速度)。
  • 被控变量 Y(t):当前速度。
  • 误差 E(t):目标速度与当前速度之差(有符号误差)。

参考速度可以基于与前车的距离来设置,例如使用公式:v(t) = v_max * (1 - exp(-距离/时间常数)),从而实现简单的自适应巡航控制。

横向车辆控制(路径跟踪)

横向控制的一种形式是定义横向误差,即车辆重心与应跟随路径上最近点之间的距离。

变量定义如下:

  • 参考变量 R(t):0(我们希望横向误差为0)。
  • 校正变量 U(t):转向角 δ
  • 被控变量 Y(t):横向误差。
  • 误差 E(t)0 - Y(t) = 负的横向误差。

PID控制演示视频摘要

一个演示视频生动地展示了不同控制器的效果:

  1. 开关控制:转向角只有固定左转或右转两个状态。控制效果颠簸,乘客不舒适。
  2. 比例控制:转向角与横向误差成比例(转向角 = Kp * 横向误差)。性能随增益 Kp 增加而改善,但增益过高且起始误差大时,系统可能失控。即使使用最佳增益,车辆到达中心线时可能仍是歪斜的,导致反复超调。
  3. 比例微分控制:加入微分项,考虑横向误差的变化率(+ Kd * d(横向误差)/dt)。比例增益增加“拉回”力,微分增益增加“抵抗”快速运动的阻力。微分增益太低(欠阻尼)仍会振荡;太高(过阻尼)纠正偏移很慢;适当的值(临界阻尼)能让车辆快速接近目标轨迹且横向误差率接近0。
  4. 比例积分微分控制:加入积分项,累积横向误差总和(+ Ki * ∫横向误差 dt),用于纠正如侧风或车辆机械缺陷导致的稳态误差。需要同时调整三个增益。增益太大会不稳定;太小则响应过慢;合适则能快速纠正偏差。

实践案例:基于航点的PID控制

最后,介绍一个实践中使用的PD控制器案例,该案例也用于我们的研究小组在Carla模拟器中的智能体上。

在一篇2019年的论文《Learning by Cheating》中,实现了一种基于航点的PID控制器。感知栈(如神经网络)输出未来一系列时间点的航点 W1...Wk

基于这些航点,可以定义两个控制器:

  1. 纵向PID控制器(速度控制)

    • 通过计算相邻航点之间的L2距离,除以时间间隔,再取平均,来估计期望速度。
    • 将此期望速度设置为纵向PID控制器的参考速度。如果航点预测得近,车辆应走慢;预测得远,则应走快。
  2. 横向PID控制器(转向控制)

    • 将一条圆弧拟合到远处的航点。
    • 在该圆弧上选择一个特定前瞻距离的点 P 作为转向目标点。
    • 通过计算车辆航向与指向目标点 P 的方向之间的角度差来设置转向角。

这种方法允许根据高级驾驶策略输出的航点进行平滑的车辆控制。

总结

本节课中我们一起学习了黑盒控制器。我们从最简单的开关控制器入手,了解了其原理和局限性。然后,我们深入探讨了工业中广泛应用的PID控制器,详细解释了其比例、积分、微分三个环节的作用和数学表达。通过系统响应示例,我们直观地看到了纯比例控制的振荡问题以及加入微分环节的阻尼效果。我们还介绍了使用齐格勒-尼科尔斯方法进行参数整定的启发式步骤。最后,我们探讨了PID控制器在车辆纵向速度控制和横向路径跟踪中的具体应用,并通过一个基于航点的实际控制案例结束了本课。理解这些基础的黑盒控制原理,是构建更复杂自动驾驶控制系统的重要基石。

022:车辆控制 - 几何控制

在本节课中,我们将要学习几何控制器。这是一种利用车辆模型知识的控制器,与之前介绍的不依赖模型的黑箱控制器不同。我们将重点探讨两种具体的几何控制方法:纯追踪控制器和斯坦利控制器。

上一节我们介绍了不依赖任何过程知识的通用控制器。本节中,我们来看看如何利用已知的车辆动力学模型来构建性能更好的控制器。

🎯 纯追踪控制器

纯追踪控制器的目标是跟踪路径上的一个目标点,该点位于车辆前方一个特定的预瞄距离 D 处。控制器的目的是通过调整前轮转向角 δ,使车辆后轴中心沿着一条圆弧轨迹接近该目标点,从而最小化横向跟踪误差 e

以下是控制器工作原理的几何关系推导图示:

图中,α 是车辆当前航向与指向目标点的视线之间的夹角。L 是车辆的轴距。R 是期望圆弧轨迹的半径。

我们的目标是建立转向角 δ 与夹角 α 之间的关系。根据运动学自行车模型和几何关系,可以推导出以下公式:

首先,根据正弦定理和三角恒等式,可得到轨迹曲率 κα 的关系:
κ = 1 / R = 2 sin(α) / D

接着,根据运动学自行车模型,转向角 δ 满足:
tan(δ) = L / R

将曲率公式代入,得到纯追踪控制律:
δ = arctan(2L sin(α) / D)

当转向角较小时,可近似为:
δ ≈ 2L sin(α) / D

在实际应用中,预瞄距离 D 通常与车速 v 相关,例如设为 D = K * v,以确保在高速时不会进行过于激进的转向。

现在,我们来看看这个控制律如何与横向误差 e 关联。根据几何关系,有 sin(α) = e / D。将其代入上述控制律,可得:
δ = arctan(2L e / D²) ≈ (2L / D²) * e

这表明,纯追踪控制器本质上是一个针对横向误差 e 的比例控制器,其比例系数与轴距 L 和预瞄距离 D 有关。

🏆 斯坦利控制器

斯坦利控制器是纯追踪思想的一个改进,由斯坦福大学车队在DARPA挑战赛中成功使用。与纯追踪控制器不同,斯坦利控制器以车辆前轴为参考点,选择路径上距离前轴最近的点作为目标点,并且没有预瞄距离。

其控制律结合了横向误差校正和航向误差校正,公式如下:
δ = arctan(k * e / v) + ψ

其中:

  • e 是前轴中心到路径的横向误差。
  • v 是车辆当前速度。
  • ψ 是车辆当前航向与路径在目标点处切线方向的夹角(航向误差)。
  • k 是一个可调增益参数。

该控制律的第一项 arctan(k * e / v) 用于修正横向误差。误差越大或车速越低,转向指令越强。第二项 ψ 直接修正航向误差,使车辆方向与路径对齐。

斯坦利控制器具有良好的理论特性,例如可以证明其横向误差能够指数收敛到零,并且具有全局稳定性。当然,它仍是一个相对简单的模型,未考虑轮胎力、执行器动态和观测噪声等因素。实践中常通过添加阻尼项或融合路径曲率信息对其进行改进。

以下是斯坦利控制器在不同初始误差下工作的两个示例图示:

最后,值得一提的是,斯坦利控制器在真实的DARPA Grand Challenge中得到了验证,能够引导自动驾驶车辆在复杂地形(如狭窄的山路)上稳定循迹行驶。

📝 总结

本节课中我们一起学习了两种基于几何模型的车辆路径跟踪控制器。

  1. 纯追踪控制器:通过跟踪前方一个预瞄点,使车辆沿圆弧运动,其控制律近似为一个横向误差的比例控制器。
  2. 斯坦利控制器:以前轴为参考,综合校正横向误差和航向误差,被证明具有全局稳定性,在低速场景下表现优异。

这两种控制器都充分利用了车辆的运动学模型知识,比通用的黑箱控制器更高效、更具可解释性,是自动驾驶控制领域的基础方法。

023:最优控制 🚗

在本节课中,我们将学习最优控制与模型预测控制。这两种控制器利用车辆动力学模型,能够预测未来状态并进行全局优化,从而处理高速驾驶等需要前瞻性的复杂场景。

控制器面临的共同问题

上一节我们介绍了几何控制器,本节中我们来看看所有控制器面临的一个共同局限。

目前所见的所有控制器都存在一个问题:它们无法展望很远的未来。然而,由于我们希望车辆能以高速行驶,并且车辆本身具有质量,因此常常需要,特别是在高速情况下,提前展望未来,并预判即将到来的路口、其他车辆或弯道。现有的控制器难以处理此类情况。因此,在最后一个单元,我们将简要介绍更高级的最优控制器和模型预测控制器。

最优控制基础:线性二次型调节器

最优控制器和模型预测控制器都利用了底层的动力学模型。与之前看到的几何控制方法相比,这些控制器对模型的利用更为深入。

让我们以动态自行车模型为例进行回顾。

以下是上一讲中见过的动态自行车模型方程,其状态 X 包含横向速度、横摆角和横摆角速度。这是一个简单的微分方程,其中状态的一阶时间导数被表达为状态的线性系统加上一个向量乘以输入(本例中为前轮转向角 δ)。

因此,我们得到了一个非常简单的线性微分方程。这意味着我们可以将其写成以下线性系统形式:

ẋ = A x + B δ

其中:

  • 是状态 x 的时间导数。
  • A 是系统矩阵。
  • x 是状态向量(包含横向速度、横摆角和横摆角速度)。
  • B 是输入向量。
  • δ 是标量输入(转向角)。

给定这样一个方程,线性二次型调节器是最常见的最优控制器形式之一。

给定这个具有边界条件(初始条件 x(0) = x_init)的连续线性时不变系统,以及一个二次型成本泛函 J,其定义为:

J = 1/2 ∫₀^∞ [ x(t)ᵀ Q x(t) + δ(t)ᵀ R δ(t) ] dt

其中 Q 是一个对角权重矩阵,用于为未来的特定状态分配成本;R 用于对控制输入(如转向角)施加成本。这个模型具有很强的表达能力,我们可以通过它定义未来的成本。

有趣的是,在这种特定的简单形式下,如果我们能以这种简单形式表述系统,那么最小化成本 J 并满足约束的反馈控制 δ 由以下表达式给出:

δ = -K x

其中 K = R⁻¹ Bᵀ P,而 P 是黎卡提方程的解。这里不深入细节。重要的是,我们得到了一个封闭形式的解。

但这个封闭形式解的存在,是因为我们以特定方式(二次型成本泛函和连续时间线性系统)进行了公式化。这些是相当强的假设,并不总是符合现实。我们通常希望在建模上更加灵活,这便引出了模型预测控制。

模型预测控制:灵活性与计算权衡

虽然之前看到的最优LQR控制器有封闭形式的解,但模型预测控制推广了这一思想,同时放弃了封闭形式解,需要在执行控制器时进行实时优化。这使得计算成本更高,但同时也获得了建模的灵活性。

模型预测控制将LQR推广到非线性成本函数和动力学系统。这非常有用,例如,我们可以考虑从直道进入弯道的情况、非线性特性,并且可以从简单的动态自行车模型局部坐标定义,转换到我们几乎总是感兴趣的车辆全局坐标定义。正如在动态自行车模型讲座最后讨论的,这会使系统变为非线性,因此仅适用于线性系统的LQR不再适用,但模型预测控制可以处理。

这是表达能力最强的控制器,随着计算成本越来越低,以及许多待控制系统能够承载大量计算,它现在被广泛使用。

它非常灵活。例如,它允许使用滚动时域。我们不需要一直建模到无限远的未来,而是可以为未来一个固定的时间窗口建模,并且可以为不同的时间步分配不同的权重。我们可以说,减少近期未来的误差比展望更远的未来更重要,因为更远的未来我们的感知测量也可能更不确定。此外,我们可以纳入任意约束,任何可以优化的东西都可以纳入。

然而,如前所述,它计算成本更高。现在我们需要在控制器每次迭代执行时进行非线性优化。控制器通常需要以很高的频率执行(例如每秒1000次)来控制一个系统,这意味着你需要每秒解决1000次非线性优化问题。但这仍然是可行的。

形式上,模型预测控制可以用以下方程表述:目标是相对于未来 T 个时间步的输入转向角序列 δ₁, ..., δ_T,最小化一个成本函数的总和。在每个时间步,我们可能有一个不同的成本函数,它取决于车辆未来的状态。车辆从某个初始条件开始,我们有一个动态模型(如动态自行车模型),允许我们通过迭代执行来模拟车辆未来 T 个时间步的状态。

你可以将其想象成一个大的计算图,一个展开的计算图。你将这个优化问题展开到未来,然后优化这些参数 δ。我们也可以容纳任意约束。

因此,我们将动态模型展开 T 次,然后应用非线性优化来寻找参数,类似于在深度学习中展开循环神经网络并优化神经网络参数的方式。

实例对比:为何模型预测控制至关重要

最后,让我们看一个具体例子,说明为什么模型预测控制很重要,特别是在考虑高速驾驶时。

顶部是一个经典PID或路径跟踪控制器的示例。假设车辆沿着一条道路行驶,这里有一个右转弯,实际上是一个相当急的右转。我们想要跟踪道路中心线上、车辆前方一定距离处的这个点。假设最初车辆以50公里/小时行驶。因为我们跟踪那个点,并且道路上没有限制,我们可能会加速。现在我们以60公里/小时行驶。由于仍在直行,并且只局部观察环境,我们进一步加速到70公里/小时。一切似乎都还好,我们不知道这里有一个右转弯。但是,一旦我们加速到70公里/小时,我们会突然发现,路径上的目标点向右移动了,但我们速度太快,无法及时刹车。我们继续减速,试图跟踪那个点,但已无法做到。因此,我们虽然减速,但仍会撞到道路的另一侧。

相比之下,模型预测控制器将模型展开 T 个时间步(根据我们设定的长度)。只要我们有地图或能观测到未来的环境,它就知道未来的整个轨迹。因此,我们早在这一点就知道未来必须减速,这意味着我们现在就可以开始减速。我们遵循这条轨迹,在每个时间步,模型预测控制都会重新计算未来 T 个时间步。在这里,我们计算了这些时间步;现在在这里,我们计算这些时间步以及一个未在此显示的未来时间步。因为我们在计算未来,我们在滚动执行我们的车辆模型。理论上,我们可以假设未来的轨迹。因此,我们早已知道在这一点需要减速,以便实际完成这里的右转。所以我们减速到30公里/小时,再到20公里/小时,然后完成右转。这就是在考虑高速驾驶和需要长远展望的情况下,路径跟踪与模型预测控制的区别。

总结

本节课中我们一起学习了最优控制与模型预测控制。

我们了解到,开环控制器无法处理未知扰动,因此在实践中需要带有传感器反馈的闭环控制器。

我们也看到,黑盒控制器不需要关于过程的知识,其中最流行的是PID控制器。

我们学习了几何控制器利用几何关系进行路径跟踪。

而最优控制器则使用车辆模型并优化全局成本函数。

其中,模型预测控制是最灵活和强大的方法,但它需要在每个时间步解决一个优化问题。

024:里程计、SLAM与定位 - 视觉里程计

在本节课中,我们将要学习自动驾驶汽车中一个核心的模块:自我运动估计与定位。我们将重点探讨视觉里程计,这是一种通过图像序列来估计车辆自身相对运动的技术。

我们已经完成了本课程的一半。在接下来的六节课中,我们将更深入地研究经典的模块化流水线,特别是构成该流水线的各个独立模块。例如,低级感知与场景解析,这将是接下来几节课的内容。以及路径规划与决策制定,这将是第12讲的内容。当然,还有车辆控制,我们已经在之前的两节课中讨论过了。

在本节课中,我们将专注于自我运动估计和定位。自动驾驶汽车在动态环境中运行,因此必须了解其自我运动(即自身的运动)以及其他交通参与者的运动。本课的重点是估计自身的运动,即所谓的自我运动。

我们将考虑三种不同类型的运动估计。第一种称为视觉里程计。视觉里程计是指从图像中估计相对自我运动。例如,在时间T,你可以看到左边的车辆;在时间T+1,你可以看到右边的车辆。从时间T到时间T+1,车辆经历了一个具有旋转 R 和平移 t 的刚体变换。这是一个六自由度的刚体变换。我们想要估计的是这个刚体变换的六个参数,它们将当前姿态与前一时刻的姿态联系起来。这就是为什么它被称为相对自我运动估计,因为我们不是将车辆定位到全局参考系(如地图)中,而是将其定位到前一时刻的姿态。

我们将要研究的另一类是SLAM,即同步定位与建图。其目标是构建地图并同时在该地图中定位。我们将看到这两个任务必须联合处理。例如,地图可能由一些地标组成。我们希望联合估计这些地标的位置和车辆的姿态。这样,之后我们既在地图中完成了定位,也生成了一个可以在以后再次行驶到同一区域时用于定位的地图。

第三类是定位问题,即给定一个地图(例如,由地图公司提供的高清地图,或通过SLAM算法预先行驶并建图自动计算出的地图),我们希望找到车辆的全局姿态,即车辆相对于该给定地图的位置。这些地图可能非常大,可达数百或数千公里,因此这个定位问题也可能相当复杂。

所有这些任务在实践中都很有用。例如,估计相对于前一帧的自我运动对于在更长的时间范围内整合轨迹、衡量我们的动力学模型预测效果以及控制车辆都很重要。当然,我们需要知道我们是如何行驶的。相对于地图的定位也很重要,因为我们可能向地图中添加有用信息,例如交通灯的位置,这可能反过来促进交通灯的检测。或者我们可能在其中加入其他信息,如车道标记,以帮助我们保持车道或了解车道数量,所有这些元信息都可能很有用。

因此,在实践中,所有这些对于自动驾驶都是必需的。以下是今天的路线图:在第一单元,我们将介绍视觉里程计;在第二单元,介绍SLAM;最后是定位。让我们从视觉里程计开始。

什么是里程计?

这是之前的图片。现在我们将更一般地看待里程计,它不一定是视觉的,不一定需要从图像传感器估计,也可以使用其他传感器。问题是,我们希望通过可用的传感器来估计自我位置随时间的变化,并且通常有多个传感器,我们希望将它们结合起来。

里程计(Odometry)一词源于希腊语,odos 意为路线,metron 意为测量,因此我们想要测量车辆所经过的路线。在上面的例子中,汽车在两帧之间经历了刚体运动。

里程计产生的是相对运动估计,而不是相对于地图的全局位置。因此,它容易受到随时间累积的误差影响。它只在局部精确。如果你获取这些相对运动估计并将它们随时间累积,就会产生漂移。我们稍后将在SLAM中看到这种漂移情况以及如何使用闭环技术来解决。但如果你只考虑里程计问题,你总是会有漂移,因为你是通过相对测量随时间积分位置,所以误差会随着时间的推移越来越大。对于估计非常长时间范围内的全局位置来说,这不是一个好技术。但它擅长估计局部的相对运动,而这通常是自动驾驶中重要的,因为我们想知道我们是如何在局部移动的。

里程计信息可以通过多种传感器获得。以下是两个非视觉的例子。第一个是轮式里程计。轮式里程计系统使用车轮编码器来测量车轮旋转。你可以在这里看到这样一个编码器。我选择这张图片是因为它非常直观。当然,在现代自动驾驶车辆中,这些传感器被集成在车辆内部。一个非常不精确的版本今天在我们所有人的汽车中都有,如果你进入你的汽车,你会看到自购买以来行驶的公里数,等等。这是同样的原理,只是自动驾驶车辆使用的这类传感器应该更精确。

另一种里程计传感器称为惯性测量单元(IMU)。你可以在这里右边看到一个非常昂贵的,常用于自动驾驶车辆。但你的智能手机中也有这样的IMU,例如,用于确定你是竖屏还是横屏拍照,这些加速度传感器被使用,或者当你拿起智能手机时,屏幕会亮起等等。惯性测量单元通过内置在这些模块中的加速度计以及通过滤波跟踪和更新此信息的复杂算法来测量物体的力。加速度计当然只估计加速度,通常是线性加速度和角加速度。为了从加速度获得姿态,我们需要积分两次,这意味着噪声也被积分了两次。因此,我们不能仅使用IMU数据来获得精确的姿态估计。这就是为什么IMU经常与其他类型的传感器结合使用,例如视觉传感器或GPS传感器。

最后,我们有使用相机图像的视觉里程计算法,这是我们今天重点关注的。多个系统经常被组合起来以相互补充,例如,如果你驶入隧道,图像变暗,很难匹配特征,因此在这短暂的时间内,另一个传感器接管是很重要的,这就是为什么你通常会融合这些信息,例如,VIO(视觉惯性里程计)意味着我们将视觉里程计与惯性测量单元结合起来,在实践中,惯性测量单元经常与GPS或轮式里程计等结合使用,以使其更鲁棒。

视觉里程计简介

以下是视觉里程计的一个例子。视觉里程计关注的是从图像中跟踪相机的姿态(相机的位置和方向)相对于环境。如果你能跟踪相机姿态并且相机已校准,你就知道相机相对于车辆坐标系的相对姿态,因此通过知道相机运动,你也知道车辆运动。

视觉里程计通常考虑有限的近期帧集以实现实时性能。在大多数情况下,里程计只考虑将当前帧相对于前一帧进行配准,估计两幅图像之间的相对运动。这也导致了随时间累积的误差。

另一个需要注意的点是,视觉里程计虽然主要关注运动估计(相对运动估计),但它们通常也必须构建一个局部稀疏地图。这是一个副产品,不是这些技术的重点。但这是一个副产品,意味着它们被用来估计运动。我们将看到,与SLAM算法或密集建图算法相比,它们通常不那么精确,也不那么密集,但它们是估计姿态所必需的。

这里有一个例子,在背景中你可以看到场景的3D重建,这不是视觉里程计算法产生的稀疏局部地图。它是一个通过立体重建获得的更密集的地图,用于说明场景的样子。但视觉里程计算法的实际输出是这条红色轨迹。你可以看到这些小三角形,它们是相机姿态。每个三角形对应一帧。你可以看到车辆是如何沿着这条路行驶,然后驶过这座桥的。所有这些都是仅通过图像测量确定的。整个运动都是通过图像测量确定的。然后,通过知道每一帧中每个独立相机的姿态,我们当然可以将从立体视觉获得的所有局部重建组合成一个非常好的全局重建,正如你在这里看到的。因此,我们也可以使用里程计信息来局部地映射环境。

以下是视觉里程计在实践中如何工作的一个例子。作为对比,红色的是非常精确的GPS惯性测量单元的轨迹,正如你在上一张幻灯片中看到的,蓝色的是算法的估计。你可以看到算法如何将相对运动估计累积成地图上的全局位置(相对于第一个姿态估计)。你可以看到它仅根据图像测量,就相当可靠地跟踪了这个停车操作。

这是另一个例子,首先,我将展示使用的输入序列,然后是估计的轨迹,该轨迹是通过视觉里程计计算的相对运动累积而成的,再加上通过一些简单的立体匹配算法计算的更密集的地图。所以这里没有涉及任何GPS或激光雷达。这只是一个被整合到这个局部环境中的图像序列。

视觉里程计方法详述

现在让我们更详细地看看这些方法。我们将看两种方法。第一种方法称为间接视觉里程计。它之所以被称为间接,是因为我们这里有一个间接步骤,即特征检测、提取和匹配步骤。

输入序列中的输入图像通过特征检测器,该检测器检测图像中的显著点,并尝试在相应的帧(通常是相邻帧)之间匹配这些显著点,以获得所谓的图像对应点。然后,我们有一个算法,最小化这些对应点重投影回图像的重投影误差,同时返回一些稀疏地图。通过这个,我们得到运动,即相对运动估计。这被称为间接视觉里程计方法,因为它经过了特征匹配步骤。有时它也被称为基于特征的视觉里程计方法。

相比之下,直接方法省略了这个中间步骤,直接从输入图像序列到相对相机参数和地图。它们不是最小化稀疏特征对应点的重投影误差,而是最小化光度误差,它们通过估计每个像素的深度作为地图,然后计算扭曲图像之间的光度一致性,尝试将一幅图像扭曲到另一幅,以对齐运动或图像序列中的两幅连续图像,从而找到最优运动。

这两种方法都有优点和缺点,我们将在本单元稍后讨论。让我们首先从经典的间接视觉里程计方法开始。

间接视觉里程计:特征匹配

如前所述,第一步是对于每幅图像,我们需要找到图像中独特的、显著的点,这些点可以与前一帧中找到的点相匹配。我们通过寻找图像中的显著点来做到这一点,例如斑点。这里有一个简单的5x5滤波器,我们可以在图像上滑动以找到斑点。这是一个棋盘格滤波器,我们可以用它来找到角点。然后,我们可以获取像素强度或梯度,并将它们组合成特征向量来描述这些角点和斑点。然后,通过将这些向量的特征值与在前一帧中提取的特征向量进行匹配,我们可以得到对应点,如这些小箭头所示。所以,这些点的起点是前一帧中的位置,点的终点是当前帧中的位置。这是针对自我车辆移动的场景。这是针对自我车辆静止但其他物体移动的场景。

这些特征应该对透视和光照变化具有不变性,并且有很多选择,有些比其他的更快,例如SIFT、SURF、BRISK、ORB、FAST,或者像这篇论文中这样非常简单的特征通常对于自动驾驶来说就足够了。我们通常不需要像通用计算机视觉中那样具有不变性,因为我们比较的两帧是在非常接近的时间内拍摄的。这意味着没有发生太大变化。当然,我们希望在一定程度上对透视和光照变化具有不变性,但我们不必,例如,对180度旋转(将图片倒置)具有不变性,这在驾驶中通常不会在两帧之间发生。因此,我们可以使用一些更简单的特征,这些特征在实时中效果很好。

然后,我们通过特征向量的相似性在两幅图像之间匹配这些特征。因此,我们可能在第一帧中构建一个KD树,在这个特征描述符所在的特征空间中。然后我们将当前帧与之匹配,这在实践中对于至少像这里这样的简单描述符来说效率相当高。所以在这个案例中,是非常简单的5x5核用于寻找特征,加上所谓的非极大值抑制以仅保留最显著的特征,然后使用这种特征描述符在非常特定的稀疏位置处的梯度,并将它们堆叠成一个向量,然后在前一帧中找到最接近的匹配。你会得到类似这样的结果。

这些是十多年前的结果,即使在那个时候,在单个CPU核心上,你也可以获得每秒超过20帧的速度。正如你所看到的,这里有很多图像特征被匹配,这对于估计视觉里程计来说已经足够了,视觉里程计实际上只包含六个参数,即刚体变换的六个参数,因此我们可以非常快速地获得大量测量值。这是基于特征方法的第一步。

从特征到运动估计

现在,下一步是我们如何从提取的这些特征对应点中实际得到相对运动估计。为了理解这一点,我们首先需要看看图像形成过程。我取了计算机视觉第2讲和第3讲的一些幻灯片,并为这节课相当紧凑地浓缩了它们,以便快速回顾或快速介绍图像形成的工作原理,因为我们需要知道这一点才能理解这些视觉里程计算法是如何工作的。

好的,那么让我们从图像形成开始。简而言之,我们首先需要讨论基本元素,这些通常是点。例如,2D点可以用所谓的非齐次坐标表示,只需堆叠两个坐标。这是一个简单的2D向量,描述2D点,例如图像中的像素。类似地,我们可以用3D向量描述3D点。这很清楚。

但我们也可以使用所谓的齐次坐标来描述它们。使用齐次坐标,我们总是将维度增加一,因此一个2D点(一个像素)变成一个3D向量,一个3D点变成一个4D向量。我们这样做是因为我们喜欢这些点,它们来自一个称为射影空间 P^2 的空间。原因是,我们认为所有仅相差一个比例因子的齐次向量是等价的。它们定义了一个等价类。这意味着齐次向量仅定义到比例因子。

那么,为什么我们要人为地从二维增加到三维呢?嗯,这使我们以后的生活更容易。然后我们可以定义,例如,本质上非线性的图像投影过程为一个线性函数,一个线性映射。因此,我们可以使用简单的线性代数来定义我们需要定义的许多映射。我们也可以更容易地用这个定义推导出极线几何。

所以这是一个点的齐次坐标,我们可以用齐次坐标描述同一个点,但我们如何在这两种表示之间进行转换呢?哦,注意,在本课程中,我们总是像在计算机视觉课程中那样,在符号上方加一个波浪号来表示这些是齐次坐标。

一个非齐次向量 x 被转换为齐次向量 (这里缺少一个波浪号),如下所示:x̃ = [x, y, 1]^T。所以我们只需添加一个维度,并在那里放入元素1。这也被称为增广向量,如果一个齐次向量的最后一个元素是1,我们称之为增广向量。这是从非齐次向量到齐次向量的简单转换。

要向相反方向转换,我们只需除以最后一个元素 。假设我们有一个任意的齐次向量,其中 不等于1。我们可以将这个向量除以 1/w̃,使得最后一个元素变为1。这样我们就得到了所谓的增广向量,我们可以通过只看前两个元素来读取非齐次部分,即 x̃/w̃ỹ/w̃,这对应于 x

这就是我们如何在齐次和非齐次向量之间转换的方法,只需在末尾添加一个1,或除以最后一个元素。

这是这种关系的图形说明,你可以看到三维空间中的齐次向量。然后增广向量是我们连接原点和该点的直线与位于 w̃ = 1 的平面相交处的向量。你已经可以从这个说明中看出,这某种程度上类似于透视投影。我们已经有一些看起来非常类似于3D点如何投影到2D图像平面的东西。

那么透视投影究竟是如何工作的呢?让我们看看这张图片。一个3D点 X_c 透视投影到像素坐标(我们称之为屏幕坐标 x_s)在2D图像平面上。首先,我们必须注意光线总是直线,所以我们有一条通过相机中心和3D点的射线,该射线与图像平面相交于点 x_s。现在的目标当然是估计那个蓝色点 x_s 相对于相机坐标系的位置。

惯例是让主光轴(即 z 轴)与图像平面垂直对齐。所以主光轴是垂直穿过图像平面的轴。因此,我们这样对齐这个坐标系,使得 z 轴与该轴对齐。这是一个惯例。为了清晰起见,这里没有显示 y 坐标,所以我们从侧面看图像平面。这是我们在这里进行测量的地方。为简单起见,当然,在 y 方向上,它的工作方式完全相同。

现在的问题是,我们如何从3D坐标和相机坐标系推导出2D像素的位置?为此,我们只需看这里的相似三角形。我们有一个大三角形,然后是一个小三角形。因此,我们可以看到 x_s(这里的距离,2D像素的 x 分量)除以焦距(相机中心与图像平面之间的距离)等于3D点在相机坐标中的 x 坐标除以3D点的 z 坐标(3D点在相机坐标中的距离)。换句话说,在透视投影中,相机坐标中的3D点通过除以它们的 z 分量并乘以焦距映射到图像平面,如果我们把焦距移到另一边,我们看到我们需要取 X 坐标除以 Z 坐标再乘以焦距。我们必须这样做。我们可以对3D点的 x 坐标和 y 坐标都这样做,以获得该像素在图像平面上的 x 位置和 y 位置。

这里要注意的一点是,拥有齐次坐标的优雅之处在于,如果我们用齐次坐标来写这个,这个非线性方程(它是非线性的,因为我们除以了一个 z)突然变成了一个线性表达式。这在右边有说明。我们取一个增广向量 [X, Y, Z, 1]^T,乘以这个矩阵,这给了我们齐次向量(一个三维向量)。你可以看到,如果我们这样做,例如在第一行,我们得到 f * x,在最后一行,我们得到 1 * z。所以作为齐次向量的最后一个元素,我们有 z,作为第一个元素,我们有 f * x。因此,如果我们将这个向量转换为非齐次形式并除以最后一个元素,我们恰好得到这个表达式。一个小备注:焦距的单位通常选择为像素,因为我们将以米为单位的3D点转换为像素,所以这里我们有以米为单位的东西,输出应该是像素为单位的东西,这就是为什么 f 的单位通常选择为像素。

所以我们看到透视投影可以非常简单地写成这样。正如这里推导的,但如果我们使用齐次坐标,我们可以有一个更简单的线性形式,因为那些隐式地为我们做了除以 z 的操作。

到目前为止,我们假设的是图像坐标系的原点位于主光轴与图像平面相交的点。但通常我们使用正的像素坐标工作,其中图像坐标系位于图像的角落,因此通常添加一个主点偏移 c_xc_y,以便将图像坐标系移动到图像平面的角落。

当我们看透视投影模型时,这看起来如何?嗯,我们只需将 c_xc_y(这个所谓的主点)添加到方程中。我们在这里添加的另一件事是所谓的 s 参数,它决定了图像的倾斜度,但通常这个项是0。然而,现在我们已经定义了完整的针孔透视投影模型,我们也可以用齐次形式(右边的线性形式)来写这个。现在红色的元素。这个所谓的3x4投影矩阵的3x3子矩阵。投影矩阵的这个红色部分称为校准矩阵 K。校准矩阵 K 的参数称为相机内参。与外参相对,外参指的是相机姿态,例如相对于世界坐标系。这些是内参。

你可以看到,与之前相比,我们现在有独立的 f_xf_y,我们有这个 s 参数,并且我们有主点。在这种情况下,f_xf_y 是独立的,这允许不同的像素纵横比。s 的出现是因为传感器可能没有垂直于光轴安装,所以我们在投影中得到一个小 s。但通常不需要,因为现在的制造工艺非常精确,所以在实践中,我们经常设 f_x = f_y,只有一个焦距,并且 s 为0。但我们必须对主点建模,因为我们真的想要正的坐标,而不是负的像素坐标。

好的,这就是内参的样子。当我们在相机坐标中有一个3D点时,这就是图像形成过程,但我们也可以链接这些变换。例如,一个3D点可能不是用相机坐标表示的,而是用世界坐标表示的(这里是橙色)。但我们可能知道相机相对于世界坐标的姿态,所以我们仍然可以将世界坐标中的那个点投影到图像平面。

这是如何工作的?让 K 再次成为校准矩阵(内参)。让 Rt 成为世界坐标系和相机坐标系之间的刚体变换。这是相机姿态,或者这些参数被称为外参。我们可以简单地链接这两个变换,将世界坐标中的一个点投影到图像坐标。这在底部有说明。再次,因为在齐次坐标中更简单。

因此,屏幕上的齐次坐标点,正如我们所见,是投影矩阵(包括校准矩阵和零向量)乘以相机坐标中的增广向量(这是相机坐标中的3D点)。而相机坐标中的3D点本身只是世界坐标中增广向量的一个线性投影,一个通过 Rt 的刚体变换。我们可以取世界坐标中的那个向量,通过乘以 R 并加上 t 将其转换为相机坐标。因此,我们可以将其写为这里的简单线性表达式。然后我们可以简单地链接这些变换,得到一个单一的投影矩阵,所以如果我们愿意,我们可以预先将这两个相乘,得到一个单一的矩阵,该矩阵接受世界坐标中的3D点并将其投影到屏幕上。当然,它将是齐次的,因此为了推导出实际的非齐次像素坐标,我们需要再次除以最后一个元素。

好的,这就是图像形成的简要介绍。现在让我们看看所谓的极线几何,它构成了最简单的视觉里程计算法的基础,该算法试图估计给定两幅图像之间相机所经历的相对运动。再次,我们将假设相机已经预先校准,这对于大多数视觉里程计系统来说是成立的。所以相机内参是已知的。

现在的目标是恢复相机姿态,我们也可以从中恢复3D结构,从图像对应点。描述这一点的所需关系由双视极线几何描述。如果你想了解更多关于这方面的内容,而不是我们在这里可以涵盖的,我建议你看看我们的计算机视觉课程。

极线几何在右边有说明。让 Rt 再次表示捕获的这两幅图像之间的相对姿态。所以我们想估计 Rt。一个3D点在这个设置中被投影到图像1中的像素 x_1 和图像2中的像素 x_2,只需将连接3D点和相机原点的线与图像平面相交。

3D点和两个相机中心张成所谓的极平面(这里是橙色)。像素 x_1 在图像 x_2 中的对应点必须位于所谓的极线 l_2 上。这是通过将极平面与图像平面相交形成的线。这里就是这条线。类似地,在相反的方向上,对于这个点,对应点必须位于这条线 l_1 上。此外,所有极线都通过相应的极点。第一幅图像中有一个极点,第二幅图像中有一个极点。如果图像被校正,如果相机面向同一方向,那么这些极点在无穷远处,但在这种特定情况下,它们甚至在图像域内。所有的极线都必须通过那个极点。这基本上就是连接相机中心的线与图像平面相交的地方。

为了说明这一点,我做了一个小动画,你可以看到如果我移动3D点会发生什么。如果我移动3D点,那么极平面会改变。3D点在图像中的投影以及极线也会改变,但你可以看到极点 e_1e_2 对于这两种情况保持不变。

好的,这描述了双视极线几何。现在极线几何的一个基本性质是所谓的极线约束,我们不会在这里推导它,它在计算机视觉课程中有推导,但我只是把它给你。极线约束由这个公式给出,我们取第二台相机图像平面上的一个齐次点,乘以所谓的本质矩阵 E(这是一个3x3矩阵,它是一个齐次矩阵,因为我们只能估计到比例因子,并且因为这是一个齐次方程,比例因子无关紧要),然后乘以另一幅图像中的对应点(相同的点,另一幅图像中的对应像素)。所以在这里,如果我们取那个点,那么对应点就是这里的这个点。这三个的乘积必须等于0。这是描述极线几何的极线约束。

这个约束必须对所有对应点 x_1x_2 成立。对于所有,如果你想,对于沿着对应极线的所有点,这个约束都会说它们是0。我们还不知道这些点具体在哪里,我们不知道3D点,但如果它们是潜在的对应点,它们必须是0。

现在,本质矩阵 E 进一步分解为一个平移部分(这里的符号表示将平移向量转换为一个反对称的3x3矩阵,代表平移向量)和一个3x3旋转矩阵 R。这意味着我们可以首先从n个图像对应点确定本质矩阵 E,然后将 E 分解为 Rt,这就是我们寻求的里程计信息。

从对应点恢复运动

让我们做第一步,我们可以从n个图像对应点恢复本质矩阵 E,这些对应点形成了 E 九个元素中的n个齐次方程。所以,如果我们看这个方程,我们可以把它写成一个线性系统的一行。因此,我们得到一个线性系统,其中有很多这样的约束,取决于我们有多少图像对应点。但是,因为这个方程只定义到比例因子,我们需要约束比例因子,我们可以通过使用奇异值分解(SVD)来做到这一点。由于 E 是一个齐次矩阵,我们使用奇异值分解来约束比例因子,我们不会在本课中再次练习它,我参考早期的计算机视觉课程,看看这具体是如何工作的,我只是告诉你,你可以使用SVD来获得解。

注意,这里的一些项是两个图像测量的乘积,例如,这里有 y_1y_2。因此,与那些只有一次测量的项相比,它们不对称地放大了测量噪声。因此,使用SVD来获得 E 解的所谓的归一化八点算法,首先对观测值进行白化处理,使其具有零均值和单位方差,然后再计算,并在最后相应地反变换由SVD恢复的矩阵。所以我们归一化和反归一化以应对这种不对称性。但这只是一个细节。

这里的主要关键点是,我们使用SVD从一组线性方程中恢复 E,这些方程是我们从这个极线约束推导出来的,给定我们事先确定的对应点。正如我们所见。

现在,从 E,我们可以恢复平移向量 t 的方向 (我在这里用这个帽子表示我们只能恢复方向)。仅从单目图像序列中,存在固有的尺度模糊性,我们只能恢复方向。所以,如果我们看这里的本质矩阵,我们在左边乘以方向向量 ,我们看这个三重积,我们可以证明这必须是0,因为我们有一个三重积,其中两个向量在这里指向同一个方向。因此,E 是奇异的,我们在这里再次得到 作为与奇异值零相关的左奇异向量。在实践中,由于测量噪声,奇异值不会恰好是0。因此,我们可以选择最小的那个。另外两个奇异值大致相等。所以通常一个比其他的小得多,我们可以选择那个。

旋转矩阵 R 也可以计算,但它更复杂一些。因此,如果你想知道如何做到这一点,我会参考Cliky的教科书。再次注意,本质矩阵有5个自由度,3个用于旋转,2个用于平移。换句话说,这意味着仅使用单目视觉里程计无法确定全局尺度。如果我们只给出一个单目图像序列,我们无法确定绝对尺度。这根本不可能。这是不可观测的。这就是为什么在这里我们也必须将尺度限制为一个固定的假设值,以获得解。

现在,我们可以通过非线性优化进一步改进我们刚刚推导出的 Rt 的代数估计。

π 表示3D点 X_i 投影到2D图像平面,同时考虑外参 Rt 以及我没有在这里明确写出的内参。让 x_{1,i}x_{2,i} 表示第一帧和第二帧中的2D特征对应点。所以 X_i 是一个3D点,x_{1,i}x_{2,i} 是图像中的2D像素对应点。

现在,我们可以做的是最小化所谓的重投影误差,我们可以将所有对应点的3D点投影到两幅图像中,并针对运动以及可选地针对3D位置进行优化。这在这里有说明。所以我们想找到 Rt 的最优值,如果我们还想优化并有时间预算这样做,我们也可以优化3D点 X,通过解决这样一个非常小的光束法平差问题,我们在这个表达式中相对于 Rt 和可选的 X 进行最小化。

这个表达式是什么?嗯,它是所有对应点的和,我们试图最小化重投影误差,即第一幅图像中测量的对应点与预测的对应点之间的差异,以及第二幅图像中测量的对应点与预测的对应点之间的差异。你可以看到,对于这里的预测,我们使用相同的函数,只是在第一种情况下,在第一台相机中,我们使用外参集(单位矩阵和零平移向量)投影3D点,因为这个点被假设在第一台相机的坐标系中,所以我们不需要应用任何外参变换。但对于第二台相机,我们首先使用将点从第一坐标系变换到第二坐标系的外参变换3D点,然后我们应用内参(相机校准矩阵)将其投影到图像平面。这就是这里的区别。

我们特别针对 Rt 优化这个表达式。但我们也可以针对 X 进行优化,这会增加我们进行此优化所需的时间,但会改善结果。

与之前的代数解相比,优化重投影误差通常会产生更好的结果,但我们需要初始化参数,所以我们需要首先有代数解。原因是这更符合我们拍照时的实际噪声统计,因为在这里,例如,我们使用了L2范数,这对应于假设这些像素坐标对应点在图像平面上服从高斯噪声,这对于所有不是异常值但正确的点来说是一个相对较好的假设。而代数解有一个非常不同的噪声假设,不那么现实。

三角测量可用于初始化 X。因此,给定来自代数解的 Rt,我们可以反向投影光线并找到3D点,以便为此优化初始化 X。当然,我们可以通过不在此优化中包含 X 来获得加速,但如果代数解有误差,那么我们也无法修复它们。

必须考虑异常值。如果有一个错误的对应点,它当然会严重影响结果,因为它也像内点一样以平方范数被积分。因此,必须移除它们以免影响估计,有各种技术。你可以在这里使用鲁棒的损失函数,这些函数不是平方的,通常使用的是所谓的RANSAC(随机抽样一致性),你使用所需的最小对应点集(例如,在八点算法的情况下是四个对应点)进行第一次估计。然后你这样做很多很多次,并检查所有其他点是否遵循你估计的模型,然后你选择获得最多投票(大多数点同意)的那个,然后你包括所有内点并进行最终的优化步骤。

再次,对于非线性优化,平移向量的长度无法确定。所以平移向量的长度是未知的,但这种模糊性可以解决,例如,如果你有立体图像并且你知道校准,你知道基线,那么你也可以恢复这个信息,或者如果你使用VIO(视觉惯性里程计),正如我们在开头看到的,我们可以将轮式里程计与这种视觉里程计结合起来以解决尺度模糊性。

现在,这看起来如何?我试着在这里说明。我们可以使用现成的非线性最小二乘求解器(如Levenberg-Marquardt)来优化这个表达式。在这个特定情况下,我尝试只优化 Rt。你可以看到,在这种情况下,我选择的图像测量值都稍微位于投影的右侧。因此,为了最小化这些红色的重投影误差,我必须做的是将相机稍微向左移动,以减少这些误差。现在这只是优化 Rt,如果我们也能优化3D点,那么这些重投影误差也可以减少。

再次,如果有立体相机可用,我们可以针对所有四幅图像进行优化,这样我们可以得到更鲁棒的估计,并且我们也可以估计全局尺度,即平移向量的长度或场景的尺度,这两者是等价的。此外,立体测量允许瞬时三角测量。所以在这里,如果你在第一帧中有立体图像,你可以在左右相机之间找到对应点。通过这个,你知道点的深度,所以你可以直接从单帧三角测量3D点,然后通过这些三角测量的3D点将第二对立体图像相对于第一对进行配准。所以它使事情更简单,但需要两个相机。

直接视觉里程计

现在,这是间接视觉里程计,我们优化特征的重投影误差。对于直接视觉里程计,我们跳过那一步。我们避免手工制作的关键点检测、描述和匹配,而是直接基于图像中的所有像素将两幅图像彼此对齐。

这样做的好处是,我们也可以使用那些描述性不强的像素进行这个过程,因此我们可能有更多的信息。当然,为了做到这一点,我们需要深度,深度可以来自像RGB-D相机这样的传感器,这当然不适用于自动驾驶,因为它不能在户外工作,但它可以来自激光雷达,或者立体传感器,或者来自多视图立体视觉。

这个想法非常简单,在这里有说明。如果我们知道,这里是橙色的一台相机和红色的一台相机。如果我们知道每像素深度,所以这里是图像强度 I_1 和每像素深度 D_1(这是深度图),那么我们可以从任意视点模拟一幅图像,并且我们可以优化那个视点,使得模拟图像的像素与我们实际观察到的像素一致。所以我们优化 Rt,只要模拟图像尚未与实际观察到的第二幅图像完全一致。

你可以看到这里第一幅图像平面上的点 x_1 对应于这条虚线,落到这个3D点 X 上。如果我们知道深度,那么当然,我们从那个2D像素坐标知道那个3D点。因此,我们可以将那个点投影到另一幅图像中。所以我们可以扭曲这里的强度,或者实际上做的是将强度从这里扭曲回这幅图像,以最小化相对于外参(姿态)的光度误差,即这台相机相对于那台相机所经历的姿态。换句话说,理想情况下,图像 I_2 扭曲到第一台相机图像平面等于第一幅图像平面。

在数学上,这可以紧凑地描述如下。在底部,我们针对 RtD_1 优化这个表达式,通过找到这个表达式的最小值,我们在图像域的所有像素上求和,并比较第一幅图像在该像素 x 处的强度(或RGB值或图像梯度)与第二幅图像在3D点投影到第二幅图像平面处的强度。因此,在这种情况下,这个投影函数必须不仅知道第一幅图像点 x(所以这个 x 实际上是图像平面上的一个点),还要知道相机的刚体变换外参和该点的深度,以使这个变换发生。然后,一旦我们完成了这个变换,我们就可以查询第二幅图像中该像素的强度,并将其扭曲到第一幅图像中,然后我们可以尝试最小化两者之间的差异,再次相对于 Rt 和第一幅图像的深度图。

现在,这是一个关于这是如何工作的例子。你可以在这里看到的是一种称为直接稀疏里程计的方法。它于2018年问世,是最流行的方法之一。它也是一个经过大量优化的方法,因此可以实时运行。与使用图像中的所有像素(其中一些像素可能饱和且信息量很少)相比,它只使用图像的非饱和区域部分。这就是为什么这张地图看起来仍然有些稀疏。但这足以获得鲁棒的里程计估计。

当然,这些直接方法也可以与基于特征的间接方法结合使用。

让我们看看这些结果。所以你可以在这里看到相机是如何移动的。它正在重建这个大厅。相机移动得越远,重建变得越亮。虽然看起来这些是点特征,但实际上它们不是点特征,而是用于光度对齐过程的特征。只是不需要整个图像来获得鲁棒的估计。实际上,包含信息量不大的像素甚至可能有害,因为你整合了噪声。你可以看到该方法能够跟踪相机多长时间。

他们在这个特定视频中演示的是,最终的姿态实际上非常接近初始姿态。你可以看到这些自行车现在被重建了两次,因为这个里程计算法不知道这是同一个位置。但这是故意这样做的,以证明即使经过几分钟的录制,我们也可以得到相当接近的结果。所以这种方法的漂移(误差累积)对于视觉里程计方法来说是相当低的。

间接与直接方法比较

一些关于间接方法与直接方法比较的说明。

直接方法通常能带来更准确的结果,因为它们利用了整个图像,然而,满足实时性要求需要高效的实现。此外,它们受到局部极小值的影响,需要适当的初始化。

基于特征的方法通常更快,但一般来说,准确性较低。这是因为通常只能找到少数可靠的特征对应点。然而,它们对初始化更鲁棒,更不容易陷入局部极小值。因此,这两种技术经常结合使用,例如,基于特征的方法可用于初始化姿态,然后使用直接方法进行微调。

在本节课中,我们一起学习了视觉里程计的基本概念,包括间接(基于特征)和直接(基于光度)两种主要方法。我们了解了如何从图像对应点中恢复相机的相对运动,以及这些方法各自的优缺点。视觉里程计是自动驾驶汽车理解自身运动、进行定位和建图的基础模块之一。

025:同步定位与建图 (SLAM)

在本节课中,我们将要学习同步定位与建图,简称SLAM。我们将了解SLAM如何通过联合优化相机位姿和地图来构建全局一致的地图,并介绍其核心概念——回环检测。

从里程计到SLAM

上一节我们主要讨论了相邻两帧图像间的运动估计优化。这种方法并未特别关注构建全局一致且精确的地图,地图只是作为估计相对运动的副产品而得到。

在本节中,我们将考虑在更大窗口上进行优化,即优化迄今为止记录的所有帧。我们将同时优化相机位姿和地图。在间接SLAM中,地图可以是三维特征点的位置。

SLAM的核心挑战

SLAM是一个“鸡生蛋,蛋生鸡”的问题。精确的定位需要精确的地图,反之亦然。因此,联合优化相机位姿和地图是必要的。

SLAM的另一个关键特性,除了在大窗口上进行优化外,是能够通过所谓的回环检测来纠正累积误差。这使得生成的地图更具全局一致性,并可用于定位目的。

特征点法SLAM与光束法平差

与视觉里程计类似,SLAM也存在间接(基于特征点)和直接法。同时,SLAM方法也有多种形式,例如基于滤波的方法(如EKF-SLAM)和基于光束法平差的方法。

在本节中,我们将重点介绍通过光束法平差实现的特征点法SLAM。课程末尾会提供其他SLAM算法的参考资料。

以下是特征点法SLAM的目标:

  • 目标:优化重投影误差,即图像中观测到的特征点与根据相机参数和三维点云投影到图像平面上的点之间的距离。

下图展示了室内场景(右)和KITTI自动驾驶数据集(左)的示例。在左图中,绿色线条是恢复的轨迹,黑色点是构成地图的三维地标(特征点)。

光束法平差形式化定义

这个过程在计算机视觉中被称为光束法平差。让我们正式定义它。

  • π 表示所有 N 个相机的集合。此符号也指代相机的内参和外参。
  • X_W 表示世界坐标系中的三维点集。
  • x 表示在所有相机图像中对应的图像屏幕观测值。

当然,并非每个三维点都在每个相机图像中被观测到,但为了求解SLAM问题,我们必须至少在多个图像中观测到部分三维点。

光束法平差最小化所有观测的重投影误差:

min_{π, X_W} Σ_{i=1}^{N} Σ_{p=1}^{P} w_{ip} * || x_{ip} - π_i(X_{Wp}) ||^2

这个公式与之前视觉里程计中优化两视图的公式非常相似,区别在于现在我们要优化 N 个相机视图和 P 个地标(特征点)。我们最小化观测值 x_{ip} 与对应投影 π_i(X_{Wp}) 之间的差异。

  • w_{ip} 是一个指示符,表示点 p 是否在图像 i 中被观测到。
  • π_i(X_{Wp}) 是根据相机模型将三维地标投影到二维图像平面的函数。它包含将点从世界坐标系变换到相机坐标系的外参变换,以及进一步变换到像素坐标系的内参变换。

下图再次说明了这个过程。与之前类似,但现在三维地标(地标)是在某个世界坐标系中表示的。我们同时估计所有相机的位姿。为了图示简洁,这里只展示了两个相机和三个地标。

在光束法平差中,我们联合优化相机参数和三维地标。

优化的稀疏性与计算优势

需要指出的是,优化过程并不像初看起来那么困难。用于更新非线性优化器的海森矩阵虽然很大,但通常非常稀疏。原因是地标之间或位姿之间没有直接的约束关系。

我们可以重新排列海森矩阵,使其呈现稀疏结构。例如,矩阵的左上角块对应位姿维度,右下角块对应地标维度。虽然位姿与许多地标相连,但位姿之间不相连,地标之间也不相连,从而形成了稀疏矩阵。这种稀疏性在使用稀疏优化器时能带来巨大的计算优势。

回环检测

最后,我们来讨论回环检测。回环检测旨在纠正随时间累积的误差漂移,正如之前在视觉里程计中讨论的那样。

其原理是:当我们在环境中移动并再次访问同一个地方时,可以尝试将当前帧的特征点不仅与前一帧匹配,还可以与很久以前的帧进行匹配。如果我们发现当前帧的特征点与过去某帧的特征点非常相似,就检测到了一个回环。

检测到回环后,我们可以将这些额外的对应关系作为新的约束条件添加到优化过程中。优化后,地图中原本因漂移而错位的两部分会被“拉”到一起,变得全局一致。当然,这只有在实际多次访问同一地点时才有效。回环检测是SLAM的一个核心方面。

其他SLAM方法概览

最后两张幻灯片(来自补充材料)展示了各种间接和直接SLAM方法的示例。这些方法在类型上有所不同:有些是在线算法,有些使用光束法平差;有些使用单目相机,有些使用双目或RGB-D相机等。这里不详细展开这些表格,仅作为参考资料提供。

总结

本节课中,我们一起学习了同步定位与建图。我们了解到SLAM通过联合优化所有历史帧的相机位姿和三维地图,解决了定位与建图相互依赖的问题。核心方法光束法平差通过最小化重投影误差来实现这一目标。此外,回环检测通过识别重访地点并添加额外约束,有效纠正了累积误差,从而得到全局一致的地图,为自动驾驶等应用提供了可靠的定位基础。

026:定位技术

在本节课中,我们将要学习自动驾驶汽车如何确定自身在环境中的精确位置,即定位技术。定位是路径规划、车辆控制和利用先验地图信息(如交通标志)的基础。我们将探讨多种定位方法,包括卫星定位、视觉定位以及基于地图的定位。

卫星定位 🛰️

上一节我们介绍了里程计和SLAM,本节中我们来看看如何利用外部基础设施进行全局定位。卫星定位是我们最熟悉的定位方式之一。

全球定位系统(GPS)由美国于1978年首次部署,最初由24颗卫星组成。如今,多个国家拥有自己的卫星系统,例如俄罗斯的格洛纳斯(GLONASS)、欧洲的伽利略(Galileo)和中国的北斗(BeiDou)。现代GPS接收器可以同时利用所有这些系统的信号,可见卫星越多,定位精度和可用性就越高。

卫星定位的原理称为三边测量法。其目标是已知卫星位置,通过测量到多颗卫星的距离,利用球体几何关系来确定接收设备(车辆)的位置。

距离通过测量信号发送与接收之间的时间延迟来计算,公式为:
距离 = 光速 × 时间延迟

由于光速极快,微小的计时误差都会导致巨大的位置误差。卫星搭载原子钟以保证时间精度。理论上,三颗卫星即可确定一个三维位置点,但实践中需要第四颗卫星进行时间同步校正,因此至少需要四颗可见卫星。

为了提高精度,可以使用差分GPS。该方法利用位置精确已知的地面基站接收GPS信号,通过对比来校正大气效应等因素引起的误差,可将精度提升至厘米级。

然而,卫星定位存在若干问题:

  • 可用性:在隧道或高楼林立的城市街道中,卫星信号可能被遮挡。
  • 精度:原始GPS精度在米级,差分GPS可达厘米级,但后者依赖基站且易受环境限制。
  • 信息不全:仅提供位置,不提供朝向(旋转),无法获得完整的6自由度位姿。
  • 频率低:更新频率最高为5-10 Hz,对于需要高速控制(如500-1000 Hz)的车辆来说太低。
  • 多路径效应:在城市峡谷中,信号可能经建筑物反射后到达接收器,导致测量误差,使定位结果跳跃。

因此,仅依赖GPS无法满足自动驾驶高精度、高可靠性的定位需求。

视觉定位 👁️

鉴于卫星定位的局限性,我们需要其他技术,视觉定位是其中重要的一类。其核心思想是预先构建一个包含已知位置及其关联特征的地图或数据库。

地图可以是一系列带有特征向量的路标集合,特征可以从图像或激光扫描中提取。建图应在与定位时相似的传感器配置和环境条件下进行,以最小化域偏移。在定位时,系统从当前输入(如图像)中提取特征,并在数据库中检索匹配项,从而确定位置。

视觉定位面临的主要挑战包括:

  1. 地图规模庞大,需要实时高效检索。
  2. 场景外观和几何结构会剧烈变化,例如昼夜、季节、天气变化都会导致同一地点看起来完全不同。

拓扑-度量定位

我们首先看一种图像级别的定位技术:拓扑-度量定位。该方法仅将当前位置定位到地图中某个图像帧的ID上,而不恢复精确的6自由度位姿。

该方法由CMU团队在2012年提出。他们将地图构建为一个有向图,每个节点代表一帧图像。系统为整个图像计算一个全局特征描述符(例如64维),然后在图数据库中寻找最相似的图像节点。

定位过程采用贝叶斯滤波框架。该框架通过运动模型预测位置概率分布,再利用观测(当前图像特征)进行更新,迭代地估计车辆最可能位于哪个图像节点附近。这本质上是一种已知初始位置后的跟踪。

基于学习的定位

我们也可以使用神经网络直接回归相机位姿。例如,PoseNet(ICCV 2015)使用一个23层的深度卷积网络(基于GoogLeNet),输入RGB图像,直接输出相机的3D位置和3D旋转(用四元数表示)。

这种方法的优点是对特征匹配错误和异常值相对鲁棒。但通常难以达到很高的精度,位姿预测结果与真实值之间存在一定偏差。

基于特征的定位

接下来我们看看基于特征的定位,这与之前讨论的SLAM方法非常相似。其目标是先在环境中构建一个稀疏特征点地图(例如使用SLAM技术),每个3D点都关联一个特征描述符(如SIFT或深度学习描述符)。

定位时,从当前查询图像中提取特征,然后在庞大的地图特征数据库中进行高效检索匹配(常用KD树或倒排索引等近似搜索算法)。由于地图规模巨大,匹配会产生大量错误对应关系(异常值)。

关键步骤是几何验证。我们使用RANSAC算法来处理高比例的异常值:

  1. 随机选取最小数量的特征对应(对于6自由度位姿,最小集是3个2D-3D对应)。
  2. 用这组最小集计算一个位姿假设。
  3. 检查地图中其他特征点在该位姿假设下,投影到图像上的位置与实测2D点的吻合程度,统计“内点”数量。
  4. 重复上述过程多次,选择内点数量最多的位姿假设作为最佳估计。
  5. 最后,仅使用所有内点进行优化,得到精确位姿。

这种方法即使在高异常值率(如超过80%)的情况下也能鲁棒地工作。

基于地图的定位 🗺️

最后,我们简要介绍基于地图的定位。其思想是在一个简单的路线图(如从OpenStreetMap下载的道路网络)上定义一个位置概率分布,然后利用视觉里程计测量的运动信息来更新这个分布。

系统开始时位置概率均匀分布。当车辆检测到转弯等特定动作时,那些在道路图上不可能发生该动作的位置概率会降低,而可能发生的位置概率会升高。随着时间的推移,概率分布逐渐收敛,车辆就能在没有初始位置先验的情况下实现全局定位。这种方法不提供精确的6自由度位姿,但能确定车辆在道路网络中的大致位置。

总结

本节课中我们一起学习了自动驾驶中的多种定位技术:

  • 卫星定位(如GPS)依赖外部基础设施,易受遮挡和多路径效应影响,精度和频率有限,常需与其他传感器融合。
  • 视觉定位利用视觉特征进行定位,包括:
    • 拓扑-度量定位:实现图像级别的粗略定位。
    • 基于学习的定位:用神经网络直接回归位姿,鲁棒但精度一般。
    • 基于特征的定位:通过匹配稀疏特征点并利用RANSAC进行几何验证,能在庞大特征地图中实现精确、鲁棒的6自由度定位。
  • 基于地图的定位:利用先验道路网络和运动信息进行概率滤波,实现高效的全局定位。

我们还回顾了视觉里程计与SLAM的区别与联系:里程计估计相对运动,SLAM同时建图与定位,而定位技术则利用这些生成的地图或其它先验信息来确定全局位姿。间接法(基于特征)通常更快、收敛性更好;直接法(基于像素强度)通常更精确但计算量更大;二者可以结合使用。对于自动驾驶而言,实时性至关重要,因为定位信息必须立即提供给后续的决策与控制模块。

027:道路与车道检测简介 🛣️

在本节课中,我们将要学习自动驾驶中的一个核心感知任务:道路与车道检测。我们将探讨其重要性、不同的输出表示方法以及在实际驾驶场景中面临的挑战。

上一讲我们学习了如何构建地图并利用地图进行定位,以规划车辆的路径。然而,车辆通过自身传感器感知到的局部环境信息同样至关重要。今天,我们将讨论如何利用这些局部信息来规划车辆的局部路径。

本讲内容分为五个单元:

  1. 首先,我们将介绍并阐述道路与车道检测问题。
  2. 其次,我们将讨论道路分割,即语义分割。
  3. 第三,我们将探讨车道线检测。
  4. 第四,我们将学习车道检测,即如何将检测到的车道线汇总成可用于车辆控制的连贯车道估计。
  5. 最后,我们将看到一个在简单场景下进行车道跟踪的算法示例,了解如何随时间整合车道检测的估计结果。

现在,让我们开始学习。

现有系统与应用 🚗

道路与车道检测算法已广泛应用于当今的许多汽车中。先进的商用系统包括:

  • 车道偏离预警:当车辆偏离当前车道时警告驾驶员。
  • 车道保持辅助:通过轻微的转向干预辅助驾驶员,使车辆保持在车道内,但驾驶员可以轻松覆盖系统的指令。
  • 车道保持与车道偏离防护:能够自主地将车辆保持在当前车道内的系统,例如在交通拥堵时自动转向。

以下是一个展示奔驰主动车道保持辅助系统的视频描述摘要:
该系统通过摄像头识别道路标线,并利用雷达传感器监控车辆周围的交通状况。当系统判断车辆可能无意中偏离车道时,会通过ESP系统对单侧车轮进行制动干预,确保车辆不压过实线。同时,仪表盘会显示警告。如果车辆越过虚线,方向盘会振动以提示驾驶员反向转向。该系统还能在相邻车道被占用且存在碰撞风险时做出反应。系统在车速超过60公里/小时后激活。

道路与车道检测的表示方法 📊

道路与车道检测的目标是在没有详细全局地图的情况下,通过感知车辆附近的可行驶区域进行导航。有多种线索可用于此目的:

  • 几何线索:例如,某区域相对于路面是否凸起。
  • 语义信息:例如,道路通常具有特定的灰色调或纹理。
  • 人造线索:例如,为辅助驾驶员而设置的车道标线。

我们可用的输入主要是图像,这也是我们今天讨论的重点。此外,激光雷达和雷达可用于感知几何线索。

有多种可能的输出表示形式,以下是几种主要类型:

1. 道路分割
这是一种语义线索。目标是将图像中的每个像素分类为道路或非道路像素。下图展示了一个理想情况下的道路分割结果,所有道路像素被高亮为红色。
道路分割是纯粹的语义线索,它告诉我们车辆可以在哪里行驶,可以通过深度神经网络等语义分割算法实现。它不考虑可达性,也不包含车道信息。

2. 行驶走廊
行驶走廊预测估计车辆前方应行驶的通道,同样是一个逐像素的估计(像素掩码)。它可能考虑障碍物。可能存在多个可行的行驶走廊,具体选择哪一个取决于高层规划。

3. 车道线
车道线用于辅助驾驶员,因此也可用于驾驶辅助系统或自动驾驶汽车。道路通常通过车道线划分为多个车道。车道线检测的目标是首先检测出车道线(有时也包括路缘石),然后为这些被检测出的像素拟合一个参数化模型(如样条曲线)。这种方法在高速公路上效果良好,但在城市中由于车道线经常不可见、不完整或被遮挡,效果会变差。

4. 车道
车道检测的目标是识别车道。车道检测算法将两条车道线(例如,我们所在车道的左、右车道线)分组为一个单一的车道。这样我们就知道这两条参数化曲线共同构成了一个车道。通过这种方式,我们可以获得车道宽度、中心线等信息,这些可用于导航。同样,与导航相关的车道取决于高层规划。

5. 自由空间估计
自由空间估计的目标是估计图像中可以无碰撞到达的位置。这是一个纯粹的几何线索。它询问哪些地方可以直接到达,通常基于来自激光雷达或立体视觉的几何信息进行计算。基本形式的自由空间估计通常基于简单的深度图输入,然后通过算法沿射线检测第一个不符合道路几何模型(例如一个平面)的点。

从图像域到鸟瞰图 🌍

以上所有表示形式都位于2D图像域中。然而,车辆是在3D物理世界中行驶的,在自动驾驶中,这可以合理地近似为鸟瞰图。在2D图像域中估计的量(如距离)对我们的控制任务并不直接有用。因此,我们应该将这些表示映射到3D空间或鸟瞰图中。
这种映射是可能的。例如,给定对道路表面的估计(如拟合一个平面),我们可以利用该平面将图像中的观测(如车道线)扭曲到鸟瞰图中。这个过程会引入不确定性,并且使场景看起来截然不同,这本身就说明了执行这种映射并非易事。

实际挑战与复杂性 ⚠️

在深入第一个单元之前,我们需要理解这个问题在实际中有多复杂。作为人类驾驶员,我们每天都在解决这个问题,看似不难,但对机器而言却充满挑战。以下是一些从实际驾驶数据集中选取的示例,说明了各种挑战:

  • 语义模糊:在居民区道路,可行驶区域(道路)与人行道之间的界限可能不明确。基于几何的自由空间估计可能将人行道也判为可行驶,但这取决于高度阈值,且阈值设置很脆弱。车道边界检测在此也会失败。
  • 光照与阴影:在高速场景,阴影区域会使道路颜色变暗,但分割算法可以处理。自由空间估计则需判断路肩草地是否可穿越(几何上可能,但语义上不可)。
  • 施工与新旧标线:施工区域可能出现新旧标线并存(如黄线与残留白线),难以判断哪条有效。此外,还存在自行车道、人行横道等无关标线,以及因眩光导致的检测困难。
  • 标线缺失与标志依赖:在没有车道线的乡村道路,导航需依赖交通标志(如指示方向的蓝色路牌)。自由空间估计可能将路缘较低的车道入口误判为可行驶。
  • 停车场与无结构环境:停车场导航无法仅靠车道线,环境非结构化。路缘高度不定,低路缘难以稳健检测。
  • 铁路轨道混淆:在交叉口,缺失车道线时,铁轨在特定光照下易与车道线混淆,需要整体推理或先验地图信息来消除歧义。
  • 施工区与遮挡:施工区标志改变道路布局,可用车道可能被部分阻挡,需要处理遮挡问题。
  • 隐含车道与狭窄汇流:在没有标线的道路上,可能存在隐含的两车道,但在某点会基于细微线索汇流成一车道,需要结合规划与反应控制来应对对向交通。
  • 标线语义多样与严重遮挡:标线可能有不同语义(如表示禁停区)。允许的行驶方向不易推断。其他交通参与者、停放的车辆或建筑物可能造成严重遮挡。

这些例子说明了为何今天讨论的算法无法在所有场景下工作,以及为何在实践中需要针对不同情况使用多种算法的组合。

方法概述与比较 📋

以下是五种不同表示方法的优缺点概述:

  • 道路分割(语义分割)

    • 优点:适用于非结构化环境;不依赖于几何估计。
    • 缺点:存在语义模糊性(如人行道);不直接输出路径信息(仅为像素掩码)。
  • 行驶走廊估计

    • 优点:与控制更直接相关;可包含障碍物信息。
    • 缺点:仍仅为像素掩码;依赖于高层规划;可能模糊且难以估计。
  • 车道线检测

    • 优点:若标线清晰则相对容易检测;可使用紧凑的参数化模型表示。
    • 缺点:标线经常缺失或损坏;仅在高度结构化的环境(如高速公路)中可靠。
  • 车道检测

    • 优点:直接产生可用于控制的路径或中心线;可使用紧凑的参数化模型表示。
    • 缺点:经常模糊且难以估计;同样仅在结构化环境中可靠。
  • 自由空间估计

    • 优点:适用于非结构化环境(如越野);不依赖语义,因此具有鲁棒性。
    • 缺点:依赖于输入几何信息的质量;不直接输出路径信息。

本节课中,我们一起学习了道路与车道检测的基本概念、多种输出表示形式及其优缺点,并了解了在实际复杂驾驶场景中面临的挑战。在接下来的单元中,我们将深入探讨具体的算法和技术。

028:道路与车道检测 - 道路分割 🛣️

在本节课中,我们将要学习如何使用深度卷积神经网络进行图像分割,特别是针对自动驾驶场景中的道路像素分割。

概述

道路分割的目标是识别图像中所有属于道路的像素。现代方法的核心是使用深度卷积神经网络进行语义分割,即为输入图像中的每一个像素预测一个语义类别标签。

语义分割网络架构

上一节我们介绍了道路分割的基本概念,本节中我们来看看实现这一目标的核心技术——编码器-解码器网络。

语义分割任务为每个像素分配一个类别标签(例如:天空、树木、建筑物、人行道、道路)。这本质上是一个逐像素的分类问题。我们之前了解的卷积神经网络(CNN)通常用于图像分类,它会通过卷积层和池化层逐步缩小特征图的空间分辨率,最终输出一个单一的分类结果。

语义分割算法在此基础上增加了一个解码器部分,形成了编码器-解码器结构。

  • 编码器:与标准CNN类似,通过卷积和池化操作压缩空间信息。
  • 解码器:通过上采样操作逐步恢复特征图的空间分辨率,直至达到原始输入图像的大小。

这种结构因其形状常被称为 U-Net 或沙漏网络。其一个关键特性是跳跃连接,它允许编码器中间层在相应分辨率下的特征信息直接传递到解码器的对应层,这有助于在恢复分辨率时保留更多的细节。

以下是该网络工作流程的简化描述:

  1. 输入RGB图像。
  2. 编码器进行特征提取和下采样。
  3. 解码器进行上采样和特征融合。
  4. 输出与输入同分辨率的语义分割图。

网络训练方法

了解了网络结构后,我们来看看如何训练这样的网络。

训练分割网络参数的标准方法是经验风险最小化。我们需要一个有标注的数据集,其中包含图像及其对应的逐像素标签。

训练时,我们为每个像素定义一个分类损失函数。最常用的是交叉熵损失。对于训练集中的每一张图像,网络会为每个像素预测一个类别概率分布,损失函数则衡量这个预测分布与真实标签分布之间的差异。通过反向传播和优化算法(如随机梯度下降)最小化总损失,模型就能学习预测正确的语义类别。

分割效果演进与优化

早期的基础分割模型效果有限。例如,在最初的SegNet论文结果中,虽然能大致区分道路、车辆等区域,但边界模糊,精度不高。

为了提升效果,后续研究引入了后处理优化。一个典型的方法是将卷积神经网络的输出与条件随机场 相结合。CRF可以建模像素间在空间(甚至时间)上的关联性,通过定义一元势能和二元势能,使分割结果在空间和时间上更平滑、更一致。

  • 一元势能:基于CNN对每个像素的独立分类置信度。
  • 二元势能:鼓励在空间或时间上接近的像素拥有相同的标签。

这种结合了深度学习和概率图模型的方法,在2016年的Cityscapes等数据集上取得了显著更清晰、更准确的分割结果。

三维语义建图与应用

语义分割不仅可用于二维图像,还能扩展到三维空间。

一种方法是同时进行两项工作:将输入图像通过语义分割网络,同时使用SLAM技术计算局部三维地图。然后将二维图像的语义信息融合到三维地图中,从而构建出语义化的三维地图。这种表示能更丰富地描述环境,对于自动驾驶的路径规划和理解至关重要。

面向自动驾驶的特定分割

最后,我们可以针对自动驾驶的具体需求定制语义类别。

例如,道路分割不仅可以区分“道路”与“非道路”,还可以进一步细分道路内部结构。可以训练一个模型来区分自我车道相邻车道以及对向车道。这样的细粒度分割能为车道保持、变道等决策提供更精确的信息。从示例中可以看出,算法能够较好地区分这些不同的车道区域。

总结

本节课中我们一起学习了道路分割技术。我们从基础的语义分割概念出发,深入了解了编码器-解码器网络(如U-Net)的架构及其训练方式。我们还看到了通过结合条件随机场进行后处理如何提升分割效果,以及如何将二维语义信息融合到三维地图中。最后,我们探讨了为自动驾驶定制细分车道类别的具体应用。这些技术是自动驾驶汽车理解道路环境的基础。

029:车道线检测 🛣️

在本节课中,我们将要学习如何检测车道线。我们将首先介绍一个非常简单的算法,然后探讨一种基于深度学习的解决方案。

概述

车道线检测是自动驾驶系统中的一项基础任务。它旨在从车辆前方的图像中识别出车道标记,为路径规划和车辆控制提供关键信息。本节将介绍两种主要方法:基于传统图像处理的方法和基于深度学习的方法。

简单梯度检测算法

上一节我们介绍了车道线检测的重要性,本节中我们来看看一个非常基础的检测算法。

观察道路图像,我们可以发现车道线通常是明亮的,并且与深色的路面背景形成鲜明对比。这意味着我们可以计算图像的梯度,并将车道线的轮廓识别为强烈的梯度响应。

例如,我们可以使用水平卷积核 [-1, 0, +1] 对图像进行水平滤波。然后观察梯度图像(这里展示的是梯度绝对值图像),我们会得到类似下图的结果。

除了使用这种简单的梯度滤波器,也可以使用可转向滤波器或特定模板。如果你知道车道线的宽度和道路的几何形状,就可以利用这些信息,当然也可以学习特征。

现在,让我们保持简单,继续分析这个简单的梯度图像。我们可以沿着图像的每一行(图中用红线标出)寻找大的梯度值。我们已经知道梯度的符号。可以看到,如果存在一条车道线,这里总会有两个相邻的峰值:车道线左侧有一个强梯度,右侧也有一个强梯度。

我们可以利用这个信息来筛选出车道线。例如,如果有深度图可用,我们可以过滤掉不在地平面上的点。我们可以在车辆前方的深度图中拟合一个平面,并假设这就是路面,从而去除来自树木等背景的噪声。我们还可以移除孤立的点(如图中这个点),因为在其紧邻区域内没有相反的梯度,所以它不可能是车道线,只是一个异常值。

以下是这个简单流程的结果,对于这张简单的图像,效果可能出奇地好。我们可以看到,检测到的车道线左边界用绿色标出,右边界用红色标出,同时还有一些残留的异常值。

我们可以进一步使用一些启发式方法(如检测非直线标记)或使用随机抽样一致性进行鲁棒拟合来剔除误检。

从这张图中还需要注意一个重要问题:并非所有车道线都被检测到。特别是最左边这条,由于透视畸变,观察角度非常倾斜,我们未能识别出来。可以看到,这里的梯度非常微弱,很难将白色与灰色的路面区分开来,因此它低于此处用于检测车道线的阈值。

如果你采用这种基于阈值的方法,那么根据你如何调整阈值,你需要在检测所有想要的车道线(但会得到很多误检)和不检测所有车道线之间进行权衡。

逆透视映射到鸟瞰图

正如前面提到的,我们真正感兴趣的不是图像域中的车道线,而是鸟瞰视图中的车道线。那么,如何将我们在图像域中检测到的车道线映射到鸟瞰图中呢?

请记住,我们在这里检测到的本质上是像素。将它们映射到鸟瞰图的过程称为逆透视映射,如下图所示。

逆透视映射将图像平面上的每个像素(此处矩形表示图像平面)映射到相应的地平面点。例如,图像平面上的像素 (u, v) 将被投影到地平面上的点 (X, Y)。其中 (u, v) 在图像坐标系中表示,而地平面上的点则在道路坐标系中表示。

只有当每个像素的深度已知时,逆透视映射才可能实现,因为这样我们可以将其反投影到3D空间;或者,如果我们有一个地面模型(例如一个平面)。这个平面可以从深度信息中估计出来。

图中其他组成部分包括:刚体变换 RT(道路坐标系和相机坐标系之间的变换),通常道路坐标系直接放置在相机坐标系下方,因此它是唯一定义的;以及校准矩阵或内参 K,它将相机坐标系中的点映射到图像平面。

换句话说,我们定义了完整的变换链。现在,我们可以取道路坐标系中的一个点,将其映射到相机坐标系,然后再映射到图像坐标系。

那么,我们如何获得地平面呢?换句话说,我们如何得到外参,即刚体变换 RT?它将道路坐标系变换到相机坐标系。

一个非常简单的解决方案是:我们直接假设一个预先确定的固定平面。因为我们知道相机在车辆上的位置是固定的,相对于车辆总是固定的,所以相对于地面也大致固定(如果我们不是在过于崎岖的地形中行驶)。

当然,这不是一个很好的模型,因为车辆会俯仰(加速或刹车时)。如果你假设一个固定平面,那么当车辆这样运动时,这个假设就不成立了。因此,在实践中更好的是估计路面平面。你可以通过立体视觉或激光雷达测量来估计路面平面。如果我拥有立体视觉或激光雷达,我就有一个3D点云,我可以(例如,使用语义分割算法或直接假设正前方区域属于路面)对这些3D点拟合一个平面,从而定义我的地平面。这是通常的做法。当然,这需要更复杂一些的处理,例如随时间跟踪这个平面估计,并对异常值具有鲁棒性。

现在,这就是你通过将平面拟合到3D点云来获得 RT 的方法。3D点云是在相机坐标系中指定的,所以如果你将平面拟合到该点云,你就得到了这个刚体变换。

假设这已经完成,我们已经知道了 RT。那么,图像中的一个像素可以按如下方式映射到地平面。

在左侧,我们看到的是针孔相机模型的标准方程(来自我们几节课前的图像形成讲座)。我们取道路坐标中的一个3D点 (X, Y, Z)(这里只显示了两个轴,但还有第三个轴,不过不相关,我们有一个Z坐标)。所以我们有一个道路坐标中的点 (X, Y, Z),我们看这个末尾带1的增广向量。然后,我们将其与外参 [R|t] 相乘,再与内参 K 相乘,就得到了齐次表示下的像素坐标 λ * [u, v, 1]^T。我们需要除以最后一个元素才能得到非齐次表示。

因为我们假设路面是平坦的,所以我们假设这里的点位于 (X, Y)Z = 0。换句话说,Z = 0。这意味着这里的方程简化了:Z 消失了,旋转矩阵 R 的第三列 R_z 也消失了。R_x 是第一列,R_y 是第二列。这基本上就是张成坐标系的基。但 Z 不再相关,因为我们假设 Z = 0

这就是剩下的方程。现在你可以看到,左边是一个齐次3D向量,右边也是一个齐次3D向量,我们有一个3x3矩阵 K 和一个3x3矩阵 [R|t]。因为这是定义良好的3x3矩阵,我们可以求逆。所以,我们可以将 K 移到另一边得到 K^{-1},将 [R|t] 移到另一边得到 [R|t]^{-1},然后得到最终的方程。这基本上是一个由 [R|t]^{-1}K^{-1} 相乘定义的单应性变换

如果我们用这个单应性矩阵乘以齐次向量 [u, v, 1]^T,然后除以最后一个元素,我们就得到了道路坐标系中点的非齐次版本,可以直接读出 XY。所以,这基本上只是与一个3x3矩阵相乘,非常简单。

这里有一个例子,来自一篇非常古老的论文(Bertozzi & Broggi, 1998)。你可以看到它的样子。你还可以看到,远处的点会严重畸变,因此这些区域有很大的不确定性,而在近距离,测量更精确。如果这里有一辆车,它也会严重畸变,因为它不满足平面假设。但在这个特定场景中,是一条空路,所以你可以看到这条空路如何很好地变换到鸟瞰视角。

这里我们有一些车辆在场的例子。你可以看到,这辆车在鸟瞰图中严重畸变。但现在我们有了鸟瞰图表示。如果我们检测到了车道线,我们就可以在鸟瞰图中找到它们。这样,我们就得到了我们想要的、对车辆控制有用的格式。

从像素到参数化曲线

我们已经完成了这种转换,但我们仍然只有像素。从图像到鸟瞰图的转换仍然给我们一幅图像,只是一组像素。其中一些是白色的(属于车道线),一些是黑色的(不属于车道线)。但这只是一组像素,因此对于控制来说还不是非常有用。

相反,我们需要的是一组参数化曲线,可以用来控制车辆,定义我们想要跟踪的路径(例如使用纯追踪控制器)。那么,如何从像素到曲线呢?

车道线检测本身并不足够,因为它只返回图像或道路平面空间(即鸟瞰空间)中的一组像素。为了对导航有用,我们需要将其转换为更具语义意义的参数化模型。通常使用低维参数化模型,如直线、多项式或样条曲线。

需要说明的是,这是一个多模型拟合问题。我们基本上每个车道线对应一个模型。但图像中通常有多个车道线,所以我们需要为每个车道线估计一个模型。我们不能假设只有一个模型,还必须确定有多少个车道线。这被称为多模型拟合问题。当然,还必须处理异常值,模型必须对噪声具有鲁棒性。

这里有一个此类算法的例子,也是一个相当古老的算法,但在当时被广泛使用。在这种情况下,车道线已被检测并转换到鸟瞰图,正如我们刚才讨论的。然后,通过随机采样连续线段上的点,使用RANSAC程序将参数化样条曲线拟合到这些车道线上,并评估该样条曲线与已识别的车道线像素的重合程度。

在顶部,你可以看到这样一个通过一些控制点确定的样条曲线,然后将其拟合到车道线上。这里有一个评分函数(我们不会深入细节),它告诉我们样条曲线对观测值(即我们检测到的像素)的拟合程度。然后进行一些后处理,去除一些异常值并使结果更平滑、更连贯。

以下是一些结果,你可以看到这个非常简单的算法如何工作。它效果不是特别好,但在一定程度上有效。所以你可以尝试基于此来操控你的车辆,但你可以看到它在十字路口会失败,而且很难可靠地检测到道路最左边或最右边的车道线。因此,如果这是我的车道保持系统的输入,我可能不会依赖这辆车,我可能会手握方向盘。但如前所述,城市内驾驶是困难的,即使是最先进的系统,在城市内也常常遇到麻烦,因此它们通常只在高速公路上可靠地开启。

基于深度学习的车道线检测

现在,这是一个非常简单的算法。我们能用深度学习做得更好吗?如何用深度学习检测多条车道线?

我们可以说,我们知道语义分割算法,所以我们可以采用这样的算法,将输入图像映射到车道线或直接映射到车道。但这样做的问题是,我们需要检测多个车道线(通常,比如你所在车道的左侧车道线和右侧车道线),并且需要区分它们。仅仅将它们检测为“车道线”是不够的,因为如果你想拟合一个参数化模型,你需要知道哪个是哪个。因此,用于分割(语义分割或道路分割)的标准交叉熵损失在这里是不够的。

那么解决方案是什么?一种解决方案是实例分割。这种方法在通用的实例分割算法中已经使用过,但在这里被适应于车道识别问题。其核心思想不是直接预测类别标签,而是预测每个像素的特征,然后在特征空间中对这些特征进行聚类。

以下是它的工作原理:

  1. 输入图像:我们有一个共享编码器,产生特征嵌入。
  2. 两个解码器
    • 第一个解码器产生每个像素的特征嵌入(图中用彩色图表示,但实际上是每个像素可能64维的特征)。
    • 第二个解码器是一个分割分支,执行二值车道线分割(这可以使用标准语义分割和交叉熵损失来完成)。
  3. 掩码与聚类:我们用二值车道线分割掩码来过滤像素嵌入,只考虑属于前景(即车道线上)的像素。
  4. 训练目标:我们训练模型,使得不同车道线(如左车道线和右车道线)在这个嵌入空间中相距很远。这样,当我们在特征空间应用聚类算法时(图中可视化为二维空间,但通常是更高维),属于不同车道线的像素会形成不同的簇。
  5. 输出:一旦我们完成了聚类,我们就知道了各个实例。注意,这不依赖于车道线的数量,模型是灵活的,我们不需要预先知道有多少条车道线,因为模型会通过聚类机制来确定。

那么,这是如何学习的呢?二值车道线分割是通过标准交叉熵学习的,但特征嵌入部分不是。它是通过一个聚类损失函数学习的,该损失函数包含两个部分:

  • 第一部分:属于同一车道的像素的特征应该被拉近。
  • 第二部分:属于不同车道的像素的特征应该被推远。

我们假设有可用的真实实例分割标签,但我们并不试图直接预测实例标签(因为我们不知道有多少个实例,标签本身没有意义),而是使用这个真实标签来定义上述损失函数。

这是你得到的结果。对于这些例子,车道线被检测得相当好。因为我们使用了更复杂的、基于深度神经网络的方法,所以对于那些在图像边界更远处、或者实际上没有任何标记的车道,我们也能相当鲁棒地得到这些车道线。算法只是学习到那里应该有标记,如果偶尔出现一个车道标记,就足以让算法识别出整个车道边界。

在这项工作中,这个实例分割结果也被用作拟合过程的输入,然后为每条车道拟合一个样条曲线。但现在这是一个非常简单的过程,因为我们已经有了分割结果,我们只需要取所有这些像素并拟合参数化模型。你可以在底行看到这个结果。

总结

本节课中我们一起学习了车道线检测的两种主要方法。我们首先介绍了一个基于图像梯度的简单算法,它通过寻找梯度峰值来定位车道线边界,但受限于阈值选择和透视畸变。接着,我们探讨了如何通过逆透视映射将图像中的车道线转换到鸟瞰视图,这需要已知或估计路面平面。最后,我们介绍了一种基于深度学习的先进方法,它通过预测像素特征嵌入并进行聚类来实现实例级别的车道线分割,从而能够更鲁棒地处理多条车道线和复杂场景。从像素到最终用于车辆控制的参数化曲线,是车道线检测流程的最终目标。

030:车道检测 🛣️

概述

在本节课中,我们将学习如何将检测到的车道线标记聚合为一个完整的车道模型,以便车辆能够跟随车道中心线行驶。我们将介绍一个简单的线性道路模型,并讲解如何通过观测到的车道线标记来估计车辆在车道内的位置、航向角以及车道宽度等关键参数。


在上一节中,我们学习了如何检测车道线标记,以及如何将它们从图像空间映射到鸟瞰图空间中的道路平面上。然而,仅仅检测单个的道路或车道线标记并不足以引导车辆行驶。我们需要将这些标记聚合为一个完整的车道模型,例如,以便车辆能够跟随车道中心线行驶。这正是本节“车道检测”要讨论的内容。

为了便于说明,本节我们将考虑一个非常简单的模型,即线性道路模型。当然,这种模型并非适用于所有场景,但它适用于例如在高速公路上直线行驶的情况。

上图展示了直线车道的模型。这是一个几何模型,模拟了高速公路场景,其中本车道由左右两侧的车道线标记界定。现在的问题是,我们能否为整个车道区域拟合一个单一的模型?

我们首先定义需要建模的参数。第一个未知参数是车道宽度 B。根据道路情况,我们可能对车道宽度有一些先验知识,但通常车道宽度是可变的,因此我们在估计时也需要为车道宽度估计一个单一的值。B 是一个正实数。

下一个参数是车辆相对于车道中心线的横向偏移 d_lat。图中绿色坐标系是道路坐标系,蓝色坐标系是车辆坐标系。d_lat 就是这两个坐标系在水平方向(即横向)上的位移。类似地,我们还有纵向位置 d_long,即图中所示的纵向距离。d_latd_long 共同描述了车辆坐标系相对于道路坐标系的位置。

此外,在这个简单的鸟瞰图模型中,我们还需要考虑车辆的横摆角 ψ,类似于我们讨论过的自行车模型中的角度。ψ 的取值范围在 之间。在图中,ψ 相对较小。

因此,我们想要估计的完整状态可以用四个变量来描述:

  • 车道宽度 B
  • 车辆相对于道路坐标系的纵向位置 d_long
  • 车辆相对于道路坐标系的横向位置 d_lat
  • 车辆的横摆角 ψ

我们的目标是通过观测车道线标记的测量值来估计这些参数(车道宽度和车辆位姿)。我们该如何实现呢?

首先,让我们看看两个坐标系之间的变换关系。我们有绿色的道路坐标系和蓝色的车辆坐标系。根据之前的定义,我们可以将一个在车辆坐标系中的点(例如车道标记上的点 (x_vehicle, y_vehicle))通过一个简单的 2D 刚体变换转换到道路坐标系中。这个变换包含一个基于车辆横摆角 ψ 的旋转矩阵,以及车辆相对于道路坐标系的纵向和横向位移 (d_long, d_lat)

用公式表示,从车辆坐标系到道路坐标系的变换为:

[x_road]   [cosψ  -sinψ] [x_vehicle]   [d_long]
[y_road] = [sinψ   cosψ] [y_vehicle] + [d_lat ]

类似地,我们也可以进行反向变换,从道路坐标系映射到车辆坐标系:

[x_vehicle]   [cosψ   sinψ] ( [x_road]   [d_long] )
[y_vehicle] = [-sinψ  cosψ] ( [y_road] - [d_lat ] )

在道路坐标系中,车道线标记的描述非常简单。车道线是图中所示的红色垂直线。在道路坐标系中,任何红色点(车道标记点)的 x 坐标就是沿 X 方向的路径长度 L,而 y 坐标则是 +B/2(右侧车道线)或 -B/2(左侧车道线)。

因此,我们可以将道路坐标系中的车道标记点 (L, ±B/2) 代入上面的反向变换方程,从而将其映射到车辆坐标系中。经过数学上的重新排列,并假设横摆角 ψ 接近于 0,我们可以得到一个非常简单的表达式:

y_vehicle ≈ -ψ * x_vehicle ± B/2 - d_lat

这个表达式建立了车辆坐标系中 yx 之间的关系,并且包含了我们想要估计的参数:横摆角 ψ、车道宽度 B 和横向位置 d_lat。这意味着我们现在可以利用观测到的 (x, y) 点来估计这些参数。

这引出了一个简单的回归问题,如果我们有足够的观测点,可以独立地在每一帧解决。假设我们在左侧车道线上有 N_L 个点 (x_i^L, y_i^L),在右侧车道线上有 N_R 个点 (x_j^R, y_j^R),我们通过解决以下最小化问题来估计参数:

(B*, d_lat*, ψ*) = argmin_{B, d_lat, ψ} [ Σ_i (y_i^L - (-ψ * x_i^L - B/2 - d_lat))^2 + Σ_j (y_j^R - (-ψ * x_j^R + B/2 - d_lat))^2 ]

我们最小化的是平方误差项的和。每个误差项衡量的是在车辆坐标系中,测量到的车道线标记点的 y 坐标与我们模型预测值之间的平方距离。我们的模型就是上面的近似公式,输入 x 坐标和参数 ψ, B, d_lat,输出预测的 y 坐标。

可以看到,误差项内部的所有参数 ψ, B, d_lat 都是线性出现的。这意味着这是一个线性最小二乘问题,存在闭合形式的解。解可以通过求解一个简单的线性方程组得到。

值得注意的是,在这个简单的模型中,纵向位置参数 d_long 是不可观测的。在进行上述公式变换和消除 L 的过程中,d_long 也被消去了。直观上理解,我们不知道车道标记相对于某个全局参考系的绝对纵向位置,只知道那里有一条车道线,因此 d_long 无法仅从单帧图像中确定。在右侧的示例图中,我们简单地将 d_long 设为 0,然后估计 d_latBψ

总结

本节课我们一起学习了如何从检测到的车道线标记构建完整的车道模型。首先,我们需要在相机图像中检测车道线标记,并使用逆透视映射将它们的位置转换到车辆坐标系中。然后,我们介绍了一个简单的线性车道模型,并展示了如何利用鸟瞰视图中的测量值,通过求解一个线性最小二乘问题,来估计车辆在车道内的横向位置 d_lat、车道宽度 B 以及车辆的横摆角 ψ。这个方法为自动驾驶车辆理解自身在车道内的位姿提供了一个基础而有效的解决方案。

031:车道追踪 🛣️

在本节课中,我们将学习如何利用多帧图像信息,通过状态估计方法来持续、稳定地追踪车道参数。我们将从单帧车道估计的局限性出发,引入车道追踪的概念,并详细介绍其数学模型和实现方法。

概述

上一节我们介绍了如何从单帧图像中检测车道线并估计车道参数。然而,单帧估计存在两个主要问题:一是忽略了历史帧中可能包含的宝贵信息,导致鲁棒性不足;二是无法估计车辆沿车道的纵向位置。本节我们将探讨车道追踪,其核心思想是将车道参数估计问题扩展到多个连续的时间帧上,通过整合历史观测数据、车辆运动模型以及其他传感器信息,来获得更优、更稳定的估计结果。

状态向量与运动模型

为了进行车道追踪,我们首先需要定义随时间变化的状态向量。我们沿用上一节的状态向量,但将其视为一个随时间演变的序列。状态向量包含以下参数:

  • 车道宽度 (B)
  • 车辆的纵向位置 (s)
  • 车辆的横向位置 (t_lat)
  • 车辆的航向角 (ψ)

接下来,我们需要定义状态转移方程,它描述了状态如何从一个时刻(t)演化到下一个时刻(t+1)。这本质上是一个运动模型。

假设车辆在相邻两帧间的相对运动由平移向量 m 和相对航向变化 φ 描述。那么,状态转移方程可以写作:

s_{t+1} = s_t + m_x * cos(ψ_t) - m_y * sin(ψ_t)
t_lat_{t+1} = t_lat_t + m_x * sin(ψ_t) + m_y * cos(ψ_t)
ψ_{t+1} = ψ_t + φ
B_{t+1} = B_t (假设车道宽度不变)

为了简化模型并得到线性方程(便于后续使用经典滤波器),我们假设航向角变化很小(这在高速公路等场景下是合理的)。利用小角度近似(cos(ψ) ≈ 1, sin(ψ) ≈ ψ),上述方程可以简化为线性形式:

x_{t+1} = A * x_t + b

其中,x_t 是 t 时刻的状态向量,A 是状态转移矩阵,b 是输入向量。这个线性方程清晰地描述了状态如何随时间线性演变。

观测模型

仅有运动模型还不够,我们还需要将实际的传感器观测(如检测到的车道线点)与状态关联起来。这就是观测模型

与单帧估计类似,我们假设在车辆坐标系(鸟瞰视图)中观测到了一系列左右车道线的点。对于任意一个观测到的横向位置 x,根据当前状态估计,我们可以预测其对应的纵向位置 y

预测公式如下(与上一节相同):

  • 对于左车道线点:y_L = p - t_lat - ψ * x_L + B/2
  • 对于右车道线点:y_R = p - t_lat - ψ * x_R - B/2

其中,p 是一个与纵向位置相关的参数。这个关系可以简洁地写成一个线性方程:

y = C * x

这里,y 是观测到的纵向位置向量,C 是观测矩阵。该方程表明,对纵向位置 y 的预测可以通过观测矩阵 C 与状态向量 x 的乘积得到。

线性系统与卡尔曼滤波

现在,我们得到了一个完整的线性状态空间表示:

  1. 线性状态转移方程x_{t+1} = A * x_t + b
  2. 线性观测方程y_t = C * x_t

这是一个线性动态系统。如果我们进一步假设过程噪声和观测噪声都是高斯噪声,那么就可以使用卡尔曼滤波器来最优地、以闭合形式求解这个状态估计问题。卡尔曼滤波器正是为这类线性高斯系统设计的。

以下是卡尔曼滤波器在车道追踪中的工作流程简述:

  1. 预测步骤:利用运动模型(如来自视觉里程计的信息),将上一时刻的状态向前推演,得到当前时刻状态的先验估计。这个预测可能包含误差累积。
  2. 更新(创新)步骤:获取当前帧的实际车道线观测数据。将预测的状态与当前的观测值进行比较,通过卡尔曼增益计算出一个修正量,对先验状态进行校正,得到后验状态估计。这一步有效地融合了运动预测和当前观测,从而得到更准确的状态。

通过这种“预测-校正”的循环,我们可以持续、稳健地追踪车道参数,即使在某些帧检测不完整或有噪声时也能保持良好的估计。

更复杂的道路模型

直线车道模型虽然简单,但不足以描述所有驾驶场景。因此,我们需要引入更复杂的模型。

圆形车道模型:用曲率(κ = 1/半径)来描述弯道。当曲率为0时,即退化为直线模型。然而,直接从直线进入圆形弯道会导致曲率(进而加速度)发生突变,产生不舒适的“急动”。在实际道路设计中,通常会使用回旋曲线(Clothoid)模型

回旋曲线模型:其核心特征是曲率随路径长度线性变化。这使得车辆可以从直线平滑地过渡到固定曲率的弯道,避免了加速度的突变。在数学上,这会导致状态方程变为非线性(例如,横向位置 y 成为路径长度的三次多项式)。对于这类非线性系统,需要使用更高级的状态估计器,如扩展卡尔曼滤波(EKF)无迹卡尔曼滤波(UKF)粒子滤波

一篇开创性的论文《Recursive 3-D Road and Relative Ego-State Recognition》就成功地将回旋曲线模型与扩展卡尔曼滤波结合,用于3D道路和车辆状态的估计,为自动驾驶的状态估计奠定了基础。

总结

本节课我们一起学习了车道追踪技术。我们从单帧估计的局限性出发,引入了基于多帧信息的状态估计框架。我们定义了包含车道宽度、车辆位置和航向的状态向量,并建立了线性的状态转移方程和观测方程,从而构成了一个可以用卡尔曼滤波器求解的线性高斯系统。最后,我们探讨了更符合实际道路设计的圆形和回旋曲线模型,并指出这些非线性模型需要更高级的滤波技术。

车道检测与追踪是高级驾驶辅助系统(ADAS)和自动驾驶的关键技术,它使得车辆能够在无需全局地图的情况下实现相对于道路的局部定位。然而,我们尚未讨论另一个重要部分——可行驶空间估计,这将在下一讲结合三维重建技术进行探讨。

032:三维重建与运动估计 - 立体匹配

在本节课中,我们将要学习自动驾驶汽车的一项基础任务:三维重建。具体来说,我们将深入探讨立体匹配技术,它利用两个同时拍摄的图像来生成视差图深度图,从而感知环境的三维结构。

概述:为什么需要三维感知?

自动驾驶汽车需要精确了解周围环境的几何结构,以确保安全导航。例如,当车辆需要绕过前方停放的车辆时,必须非常清楚其精确位置和形状,才能在不发生碰撞的情况下安全通过。

为了实现三维感知,自动驾驶汽车通常融合多种传感器:

  • 主动传感器:如激光雷达(LiDAR)和雷达(Radar),它们主动发射波(光波/无线电波)并测量反射时间来计算距离。
  • 被动传感器:如摄像头,它们不发射任何信号,仅被动接收环境光。

立体相机属于被动传感器,它由两个刚性连接的摄像头组成,通过比较两个视角图像的差异来推算深度。其优点是成本低、分辨率高,但需要额外的计算来处理图像以获取深度信息。

立体匹配的基本原理

立体匹配的核心思想是:同一场景点在两个相机图像中的水平位置存在差异,这个差异称为“视差”。距离相机近的物体,其视差大;距离远的物体,其视差小。

以下是立体匹配的标准处理流程:

  1. 相机标定:确定两个相机的内部参数(如焦距、畸变)和外部参数(相对位置和姿态)。
  2. 图像校正:根据标定结果,对图像进行重投影,使得两个相机的图像平面对齐,对应的极线变为水平线。这极大地简化了后续的匹配搜索。
  3. 立体匹配:在校正后的图像上,为左图(或右图)的每个像素,在右图(或左图)的同一水平行上搜索最相似的图像块,从而计算其视差值。
  4. 后处理:通常包括左右一致性检查,以剔除误匹配的异常值。
  5. 深度计算:通过三角测量原理,将视差图转换为度量深度图。转换公式为:
    深度 Z = (焦距 f * 基线 B) / 视差 d
  6. 三维重建(可选):可以融合多个深度图或结合相机运动估计,构建更完整的三维场景模型。

上一节我们介绍了立体匹配的整体流程,本节中我们来看看其中几个关键步骤的细节。

极线几何与图像校正

在已知两个相机相对姿态(通过标定获得)的情况下,极线几何约束告诉我们:左图像中的一个点,其在右图像中的对应点必然位于一条特定的直线上,这条线称为极线。这使我们的搜索范围从整幅图像(二维)缩小到一条线(一维)。

为了进一步简化,我们希望这些极线是水平的。图像校正过程通过图像重投影(单应性变换)来实现这一点,使得两个虚拟相机的图像平面共面且行对齐。这样,匹配搜索就只需要在左右图像的同一水平行上进行。

块匹配算法

图像校正后,最简单的立体匹配方法是块匹配。其核心思想是:对于左图中的一个像素,在右图的同一行上滑动一个固定大小的窗口,计算窗口间的相似度,相似度最高的位置即视为匹配点,其水平偏移量即为视差。

以下是几种常见的相似度度量方法:

  • 平方差之和:计算两个图像块向量之间各像素强度差的平方和。公式为:SSD = Σ (I_left(x, y) - I_right(x-d, y))^2
  • 零均值归一化互相关:先对图像块进行零均值化和归一化,再计算互相关值,对光照变化更鲁棒。公式为:ZNCC = Σ [(I_left - μ_left)/σ_left * (I_right - μ_right)/σ_right]

然而,块匹配算法存在局限性:

  • 前景滑动问题:当匹配窗口横跨深度不连续的区域(如物体边缘)时,窗口内包含不同深度的像素,导致匹配错误,产生“边缘膨胀”效应。
  • 窗口大小权衡:小窗口对细节敏感但噪声大,大窗口结果平滑但会模糊边缘细节。

视差后处理与深度计算

由于噪声和遮挡,初始视差图通常包含错误。一种有效的后处理方法是左右一致性检查:分别计算以左图为参考和以右图为参考的视差图,并检查它们是否相互一致。不一致的像素通常被视为遮挡区域或误匹配,可以被剔除。

得到可靠的视差图 d 后,即可通过三角测量公式计算每个像素的深度 Z
Z = f * B / d
其中,f 是相机焦距,B 是两个相机光心之间的距离(基线)。值得注意的是,深度误差随距离的平方增长,这意味着立体视觉在远距离处的深度估计精度会下降。

进阶方法简介

除了基础的块匹配,还有更先进的方法:

  • 基于能量最小化的方法:将立体匹配建模为一个能量最小化问题,能量函数包含数据项(匹配代价)和平滑项(相邻像素视差应相似的约束)。通过如图割置信传播等算法求解,能得到更全局一致的结果。
  • 基于深度学习的方法:使用卷积神经网络直接从图像对回归视差图。例如,DispNet 等端到端网络通过在大规模合成数据上预训练,再在真实数据上微调,能够学习复杂的匹配关系和上下文信息,获得非常清晰、准确的视差图。

总结

本节课中我们一起学习了立体匹配技术,这是自动驾驶汽车利用双目视觉进行三维环境感知的核心。我们从需求出发,介绍了立体匹配的完整流程:包括相机标定、图像校正、匹配算法、后处理以及深度计算。我们探讨了基础的块匹配算法及其局限性,并简要了解了更先进的基于全局优化和深度学习的方法。立体匹配生成的深度图,为后续的自由空间估计、障碍物检测等导航任务提供了重要的几何信息基础。

033:从深度图到自由空间与Stixel估计 🚗

概述

在本节课中,我们将学习如何将立体视觉或激光雷达生成的深度图,转换为对自动驾驶任务(如导航和碰撞避免)更直接有用的鸟瞰图自由空间估计。上一节我们介绍了如何从图像估计视差图和度量深度图,本节中我们来看看如何进一步处理这些深度信息。

从深度图到鸟瞰图自由空间估计

输入是一系列深度图(每帧一个),可能来自立体视觉重建或激光雷达直接测量。输出是鸟瞰视角下的自由空间估计,为局部路径规划或碰撞避免提供关键信息。

本单元简要讨论的论文(Badino et al.)所采用的方法是:

  1. 首先,通过视觉里程计对齐多帧视差图,进行时间上的融合,以获得更鲁棒、噪声更少的视差估计。
  2. 然后,将这些深度测量值转换为鸟瞰图占据概率图。
  3. 最后,基于此鸟瞰图占据概率,通过能量最小化来优化自由空间分割。

占据栅格表示的选择

以下是论文中考虑的三种不同计算需求的占据栅格表示方法:

  • 笛卡尔占据栅格:在横向(x方向)和深度方向(z方向)使用等大小的栅格单元。这是最直观的鸟瞰图表示。
  • 列-视差表示:基于图像列和视差维度进行离散化,导致栅格单元大小不等,且所有单元都朝向相机坐标原点。
  • 极坐标表示:栅格单元同样遵循透视投影,但在鸟瞰图的深度维度上是等大小的。

以下是这些鸟瞰图占据概率图可能呈现的示例。可以看到,在每种表示中,行人(由绿色箭头标出)都显示为一个黄色的斑点。

从深度图推导占据概率

我们将重点介绍极坐标表示,但该方法同样适用于其他表示。

(x_i, z_i) 表示图像域中的x坐标和深度值(深度 z = fB/d,其中d为视差)。我们使用一个核估计器来累积附近深度观测的证据,从而估计占据图中位置 (x, z) 的占据概率。

具体公式为:
P_occ(x, z) = (1/N) * Σ_i exp(-((x - x_i)^2 / σ_x^2) - ((z - z_i)^2 / σ_z^2))

其中,N 是观测总数。这个公式意味着,如果有大量观测值接近我们正在计算占据概率的特定 (x, z) 坐标,则指数项的值将接近1,总和会很大。反之,如果没有接近的观测值,总和就会很小。这本质上是一个累积附近深度观测证据的核估计器。

基于此概率,论文为每个图像列 j(假设有M列,例如VGA图像的640列)定义了一个数据项 D_j(z),简单地取占据概率的倒数:D_j(z) = 1 / P_occ(x_j, z)。在后续优化中,我们希望数据项的值较小(即占据概率较大)。

自由空间分割的优化

现在,我们可以将分割自由空间(绿色区域)和非自由空间/被遮挡区域(红色区域)表述为一个优化问题。我们希望找到一条边界,使其穿过基于视差图计算出的高占据概率区域(如上图所示),同时这条边界本身应该尽可能平滑,以克服噪声的影响。

为此,我们求解一个能量最小化问题,其能量函数类似于之前立体匹配中见过的形式:
E({z_j}) = Σ_j D_j(z_j) + λ * Σ_j |z_j - z_{j-1}|

该能量函数包含:

  1. 一元数据项 D_j(z_j):鼓励边界经过低数据成本(即高占据概率)的区域。
  2. 平滑项 λ * Σ_j |z_j - z_{j-1}|:例如使用截断L1惩罚,鼓励相邻图像列的边界深度 z_j 变化平缓。

由于这是一个一维图模型(本质上是一条链),我们可以使用动态规划高效地找到最优解。输出就是自由空间的估计,其边界穿过了高概率区域,同时被强制保持平滑。

算法结果与分析

现在让我们看看该算法在一些具体输入数据上的结果。

可以看到,算法能正确识别车辆为非自由空间区域。但例如在人行道这里,由于人行道在深度坐标上与道路非常接近,自由空间算法无法确定,因此将人行道也包含在了自由空间区域内,尽管中间有路缘石。这说明仅使用立体视觉来区分自由空间和道路是困难的。

同时需要注意,障碍物的高度是未知的,我们实际上只估计了自由空间(地面区域),这可以用于导航和碰撞避免。

扩展:Stixel世界模型

该模型有一个重要的扩展,称为 Stixel世界。在同一作者的另一篇论文中,他们估计多个这样的“Stixel”。Stixel是垂直方向拉长的“小棍”像素,因此得名。

这是一种更紧凑的环境表示,因为不需要表示每个单独的像素,只需将这些Stixel作为变量。他们将此表述为一个分割问题,试图基于视差和语义分割输入,将图像分割成多个Stixel。这些Stixel不仅在下部分割自由空间和非自由空间,也在顶部正确地将物体与背景分割开。因此,他们实际上为每个图像列估计了多个Stixel。

下图是该算法早期版本的一个输出示例,可以看到为汽车和背景中的树木生成的Stixel,以及它如何将障碍物检测与自由空间估计结合起来。

总结

本节课中,我们一起学习了如何将深度图转换为鸟瞰图自由空间估计。我们首先探讨了不同的占据栅格表示方法,然后介绍了通过核密度估计从深度图生成占据概率图的过程。接着,我们将自由空间分割问题形式化为一个包含数据项和平滑项的能量最小化问题,并利用动态规划求解。最后,我们了解了该方法的实际效果及其重要扩展——Stixel世界模型,它能以更紧凑的方式同时表示自由空间和垂直障碍物。这些技术为自动驾驶车辆的实时环境理解提供了基础。

034:光流与运动估计

在本节课中,我们将从三维重建转向运动估计,并首先探讨二维图像域中的运动估计,即光流。

概述

光流是由观察者与场景之间的相对运动引起的物体、表面和边缘在视觉场景中的表观运动。了解过去或当前的运动有助于我们预测未来。例如,通过了解或外推车辆过去的运动,我们可以预测其一秒后的位置。然而,光流预测是在图像空间中进行的,而非我们真正感兴趣的三维空间。对于三维运动估计(我们称之为场景流),我们需要更多的观测数据,因此我们首先从经典的光流问题入手,然后在第四单元转向场景流。

光流简介

在上图中,你可以看到两个由小箭头表示的光流场示例。对于场景图像中的某些点,我们展示了它们在图像域中运动的方向和大小。左侧示例中,观察者正朝着这个扩张点移动。右侧示例中,观察者是静止的,而交叉车流正从左向右移动,如这些绿色小箭头所示。

这些箭头仅显示了某些位置的光流。在实践中,我们希望像立体视觉一样,估计一个密集的光流场,但这很难可视化。稍后,我们将看到用颜色编码的可视化方法。这里仅稀疏地显示了这些箭头,但实际上我们拥有的是密集的光流场。

光流与立体视觉的对比

上一节我们介绍了光流的基本概念,本节我们来比较光流与立体视觉。在立体视觉中,我们处理的是同一时刻的两张图像。而在光流中,我们处理的是两个不同时间步的两张图像。通常,我们只有一个摄像头捕捉视频序列,我们考虑该序列中的两帧,并希望估计相邻两帧之间图像域中的运动。

这意味着,在立体视觉中,我们只考虑相机运动;而在光流中,我们同时考虑相机和物体的运动。因此,立体视觉是一个一维估计问题,而光流是一个二维估计问题。与立体视觉不同,我们无法在此利用极线几何约束。物体可能任意移动,我们没有可以利用的约束,因此这是一个更难的问题。

这两种情况都有生物学上的例子。例如,猴子的眼睛像人类一样朝向前方,因此它们有较大的重叠视野区域,可以用来进行立体视觉。相比之下,松鼠的眼睛朝向两侧,它们的重叠视野非常小,因此比猴子更少使用立体视觉。但它们拥有几乎360度的环绕视野,可以利用光流来探测周围几乎所有的运动。

运动场与光流场

在考虑光流时,我们必须区分光流场和运动场。那么这两者是什么呢?

  • 运动场:代表了物理世界中实际三维运动在图像平面上的投影。例如,考虑一个三维点从A移动到B,它在图像平面上的投影点p从A‘移动到B’。这就是所谓的运动场。它可能是相机运动、物体运动或两者共同作用的结果。这是我们真正感兴趣的内容。
  • 光流场:这是我们能够测量的内容,因为它描述了图像中表观运动的二维速度场。例如,它是看起来相似的像素的位移。

然而,光流场和运动场不一定相同。为什么?你能想到它们不同的情况吗?

让我们做一个小实验来更好地理解这一点。

实验一:旋转的朗伯球体
考虑一个朗伯球体在三维空间中绕其垂直轴旋转。那么二维运动场看起来是什么样的?运动场是物体物理运动在图像平面上的投影,这意味着球体顶部会有从左向右的小箭头,靠近赤道时箭头变大(因为速度变大),然后底部箭头再次变小。那么二维光流场看起来是什么样的?球体是朗伯体且无纹理,光源不变,这意味着图像看起来总是一样的。因此,光流场处处为零。这里我们有一个场景,其中运动场明显不同于光流场。

实验二:静止的镜面球体与移动光源
考虑另一个情况:一个静止的球体,但它不是朗伯体而是镜面体,并且有一个移动的光源围绕它旋转,改变了镜面高光的位置。二维运动场看起来是什么样的?球体是静止的,所以显然为零。那么二维光流场呢?它并非处处为零,因为这个镜面高光在球体表面移动,在图像中产生了一些表观运动。因此,我们会有一个由这个在球体表面移动的高光产生的速度矢量。

这说明了运动场和光流场之间的区别。当然,在实践中,我们总是对运动场感兴趣,但我们只能测量光流场。然而,场景在自然界中通常具有丰富的纹理,因此在大多数感兴趣的情况下,两者变得相当一致。

光流场的意义与孔径问题

光流场告诉我们关于世界三维结构、观察区域内物体运动以及观察者自身运动的一些信息(可能具有模糊性)。例如,在上面的案例中,我们只有观察者的运动,并且我们观察到一个三维平面结构。我们可以看到纯平移运动、纯旋转运动以及平移和旋转组合产生的这些流场。

与立体视觉相比,我们无法利用极线几何约束,因此需要处理一个更难的二维估计问题。对于参考图像中的每一个点,我们需要估计一个完整的二维运动矢量。这也通过著名的“孔径问题”得以说明。

我们通过一个小孔观察一个几何元素(例如一条线),并思考这一个测量是否足以描述这条线的移动方向。这是一个很好的思维实验。我们有一个小孔,观察后面的几何结构。现在移动这条线,问你它向哪个方向移动?大多数人可能会说这条线看起来是沿对角线方向移动。但这实际上是一种错觉,因为我们并不知道这条线是如何移动的。现在移开遮挡物,显示这条线实际上是水平从左向右移动的,而不是对角线方向。

这说明了仅凭单次观测来估计运动的问题,这是不充分的。这种现象也被用于吸引注意力,例如著名的理发店旋转柱错觉。你可能在美国的理发店见过这种柱子,它有一个彩色的旋转柱,但它产生的运动实际上是垂直方向的平移。

如何计算光流:Horn-Schunck算法

到目前为止,我们介绍了光流的背景。现在,让我们看看如何实际确定光流。我们已经知道这是一个二维估计问题,每个像素的单一观测信息是不够的,因为我们至少需要两个信息。我们能做什么呢?

我们将要看的算法是最具开创性的一个,即著名的Horn-Schunck光流算法,发表于1981年,距今已有40多年。

考虑图像I是连续变量X、Y和T的函数。考虑U(x,y)和V(x,y)为连续的光流场。因此,我们首先对所有内容进行连续建模,然后再进行离散化。U和V是连续流场,它们是x和y的函数。

Horn-Schunck算法或公式旨在最小化以下能量泛函。它是一个泛函,因为该能量不依赖于变量,而是依赖于待优化的函数。

能量泛函公式
E = ∫∫ [(I(x+u, y+v, t+1) - I(x, y, t))^2 + λ (||∇u||^2 + ||∇v||^2)] dx dy

换句话说,第一项是对亮度变化的二次惩罚,第二项是对流场变化的二次惩罚。第一项是数据项,第二项是空间正则化项。你可以看到,每个像素需要两个观测值这个不适定问题,正是通过这个通常需要设置较大λ值的强正则化项来解决的。这是我们添加的额外约束。

数据项非常简单。它只是一个对亮度变化的二次惩罚,表示:在考虑了U方向(基本上是x方向)和V方向的光流位移后,下一时刻在位置(x+u, y+v)的强度,减去当前时刻在位置(x, y)的强度。如果光流估计正确,我们期望这个差值非常小。换句话说,我们希望亮度在跟随正确光流时保持不变。我们希望将图像相互扭曲,使它们看起来最相似。当然,这也与我们之前讨论的直接视觉里程计方法相关。但在这种情况下,我们不是估计结构和运动并假设静态场景,而是真正地估计每个像素的光流。

这是一个能量泛函,包含数据项和平滑度正则化项,并且目前是连续形式。直接最小化这个能量是一个难题,因为该能量是高度非凸的,并且有许多局部最优解。为什么它是非凸的并且有许多局部最优解?它看起来是二次的,似乎是一个简单的问题。这种非凸性和局部最优解从何而来?它并非来自正则化项,而是来自数据项。因为我们有一个二次项,但我们估计的变量U和V(这些流场函数)是作为参数出现在图像算子内部的。当然,图像通常是非常复杂的。如果你绘制一个以图像强度为第三维度的三维图,它会有很多山峰和山谷。如果U和V流作为参数出现,这意味着它通过了这个高度非凸的图像算子,这就是非凸性的来源。它不是来自平方运算,二次函数本身是凸的。

那么解决方案是什么?解决方案是线性化亮度恒定假设。当我们不知道该怎么办时,线性化总是一个办法。当我第一次在卡尔斯鲁厄上光流课时,光流领域的先驱之一Hans-Hellmut Nagel告诉我,每当科学家和工程师不知道下一步该怎么做时,就假设一切都是高斯和线性的,事情就会变得简单。当然,这是一个非常强的假设,但在这种情况下是一个有用的假设。因此,我们线性化亮度恒定假设来解决这个问题。我们将看到为了使这有效我们需要做什么。

线性化与离散化

我们如何线性化?让我们考虑一阶多元泰勒级数。我们可以将一个函数用一阶近似表示,去掉所有高阶项。因此,我们在坐标(a, b)附近线性化该函数。我们计算f在(a, b)处的值,然后加上关于x的导数乘以(x-a),再加上关于y的导数乘以(y-b)。

如果我们将这个泰勒级数公式应用于我们想要线性化的表达式,我们得到底部的这个表达式。这只是公式的直接应用。现在我们可以将这个表达式代回之前的函数中。这样就得到了线性化方程。如果我将这个代入,你可以看到I(x, y, t)项(这里带负号,那里带正号)会抵消掉。剩下的只是右边的这个项。这就是这个项。你可以直接看到它是线性化的,因为现在U和V作为线性项出现在这个二次项内部。

接下来我们要做的是在空间上离散化这个方程。这是上一页的线性化方程,它导致了以下离散化的目标函数。我们不再使用能量泛函,而是得到一个关于离散化光流场U和V的能量函数。U和V基本上是光流在U方向和V方向的图像,每个像素有一个值。因此,积分被替换为求和,并且函数U(x, y)被简单地替换为对这个U流图的索引U[x, y],V类似。

现在,这个目标函数在流图U和V上是二次的,因此具有唯一的最优解。所以,它只是一个非常高维的“抛物线”。我们可以对U和V求导,并将梯度设为零来求解。这导致了一个非常大但幸运的是稀疏的线性系统。因此,我们可以使用标准技术(如高斯-赛德尔或逐次超松弛法)来求解。

然而,现在的问题是,我们做了线性化假设,因此这实际上只适用于小运动,因为线性化只在小范围内成立。目前,光流领域采用的使其也能处理大运动的解决方案是迭代线性化:线性化,计算光流的估计,然后扭曲图像,再重新线性化并计算光流的另一个估计。通过迭代进行,你可以在一定程度上克服线性化的问题。

另一个技巧是采用由粗到精的估计策略:将图像下采样到图像金字塔中。我们从低分辨率开始,可能是原始分辨率的1/16。因为在较低图像分辨率下,光流会更小,我们在那里估计光流。然后我们使用这个光流在下一个分辨率级别上预扭曲图像,以便需要求解的光流场不再那么大。这些技巧在一定程度上有效,但像这种由粗到精的估计通常会过早丢失精细结构,而这些结构在后续阶段无法恢复。因此,它也有其问题。

结果与可视化

让我们看一些结果。如前所述,我们处理的是一个密集的二维矢量场,用箭头很难可视化。因此,我们使用这个漂亮的颜色图进行可视化。它通过颜色编码光流的U和V方向。你可以看到,这个方向的光流将被编码为红色,而这个方向的光流将被编码为蓝色。光流的大小被编码为颜色的饱和度或强度,其中零光流是白色,光流越强,颜色越浓。

这是一个结果。这里有一个著名的Middlebury场景,是最早的光流基准测试之一。你可以看到这些场景纹理非常丰富,运动非常小,因此与自动驾驶场景相比非常容易。这是由Horn-Schunck算法估计的光流场。你可以看到,总体上光流看起来是合理的,但在边界处存在问题。

使用Horn-Schunck计算光流的一个问题正是它使用的二次惩罚项,因此有许多后续工作。例如,Black和Anandan的工作,以及Sun等人那篇描述所有小技巧和不同惩罚项如何有益于光流估计的精彩论文。通过不使用二次惩罚假设并使用其他一些技巧,他们得到了这里显示的更好得多的结果。

这是KITTI数据集图像对应的示例,你可以看到它效果不是那么好。在自动驾驶中,光流是一个难题,因为运动矢量通常相当大,并且场景中有许多部分纹理很少。因此,这确实是一个难题。与这些在实验室环境中捕捉的场景不同,这是一个困难得多的问题,而且比立体视觉更难,因为我们必须估计二维流。

目前,KITTI排行榜上的最先进技术是基于深度学习的光流。虽然早期的深度学习方法还无法与经典技术相媲美,但现在它们已经以相当大的优势超越了经典技术。这里是最早使用深度神经网络进行光流估计的例子之一,其架构基本上与U-Net架构相同:有一个带卷积层和步长卷积的编码器,以及一个带上卷积和跳跃连接的解码器。他们还使用多尺度损失来更好地通过网络传播梯度,并通过课程学习在大量合成数据上训练,然后在真实数据上微调。

Flownet的一个更近的版本叫做Flownet2,它基本上是结合了多个带扭曲的Flownet。因此,它再次使用了光流文献中的经典思想(在这种情况下是扭曲和堆叠),这些思想在深度学习时代也有帮助。

这是该算法对同一张KITTI图片的结果。你可以看到,虽然它仍然不完美,但比经典技术噪声少得多。当然,以视频形式展示光流结果很难可视化,但你可以看到一些估计的结构,例如这里的这辆车。

总结

在本节课中,我们一起学习了光流的基本概念。我们从光流的定义和与立体视觉的对比开始,明确了光流是图像域中的表观运动。我们深入探讨了运动场与光流场的区别,并通过思想实验理解了它们并非总是一致。接着,我们分析了光流估计的核心挑战——二维估计问题和孔径问题。为了解决这些问题,我们详细介绍了经典的Horn-Schunck算法,其核心是通过亮度恒定假设构建数据项,并引入平滑正则项来约束解空间。为了求解这个非凸问题,我们学习了如何通过泰勒展开进行线性化,以及如何离散化并最终求解线性系统。我们还了解了处理大运动的实用技巧,如迭代线性化和由粗到精的金字塔策略。最后,我们观看了光流的可视化结果,并看到基于深度学习的方法如何在该领域取得显著进展,尤其是在处理如自动驾驶这样的复杂真实场景时。光流是理解场景动态和实现运动预测的基础,尽管挑战重重,但持续的研究正在不断推动其性能边界。

036:目标检测 - 引言 🚗

在本节课中,我们将学习目标检测。目标检测是自动驾驶系统中的一项核心技术,它负责在图像或点云中定位并识别出感兴趣的物体,如车辆、行人和骑行者。

上一讲我们探讨了如何重建场景的三维结构并估计运动,这些过程与场景中存在何种物体无关。本节中,我们将聚焦于目标检测,即在二维或三维空间中定位物体并识别其类别。

本讲内容分为五个单元。第一单元介绍目标检测问题及其面临的挑战。第二单元关注性能评估,这对于选择适合特定任务的检测器至关重要。第三和第四单元将分别介绍经典的以及更先进的基于深度学习的目标检测算法,它们主要在二维图像域工作。最后,第五单元将探讨如何从图像和激光雷达扫描中进行三维目标检测。

目标检测问题定义 📸

目标检测是计算机视觉中的一个识别问题。我们可以将识别问题大致分为四类:

  • 图像分类:为整张图像分配一个类别标签(例如,“这是一张街景图”)。这对自动驾驶来说还不够具体。
  • 语义分割:为图像中的每个像素分配一个语义标签(例如,哪些像素属于道路区域)。我们在之前的课程中已经接触过。
  • 目标检测:定位(通常用边界框表示)并分类图像中的所有物体,如下图所示。
  • 实例分割:为图像中每个物体的像素同时分配语义标签和实例标签,这结合了语义分割和目标检测。

本节课我们专注于目标检测问题,它对自动驾驶至关重要。我们也会简要了解如何将目标检测器扩展为实例分割算法。

目标检测的重要性 🎯

为了说明目标检测的重要性,我们来看两个例子。

第一个例子来自Mobileye公司,他们为高级驾驶辅助系统生产智能摄像头。他们的系统持续扫描车辆前方区域,检测路径上的所有类型车辆(包括摩托车),计算相对速度,并在可能发生碰撞时发出警告。

第二个例子来自前谷歌自动驾驶项目负责人Chris Urmson的TED演讲。他展示了自动驾驶汽车如何通过目标检测来理解世界:车辆首先通过地图和传感器数据对齐来确定自身位置,然后实时感知周围环境。视频中,紫色方框代表其他车辆,红色物体代表骑行者,远处的锥桶也被识别出来。车辆不仅要检测物体,还要预测它们的行为(例如,一辆皮卡因为前方道路封闭而准备变道),并据此规划自身的轨迹。从简单的公路场景到复杂的城市街道(包含行人、交通灯、施工区、警车、校车等),目标检测的难度急剧增加。系统还需要理解手势(如骑行者举手示意)和特殊规则(如避让警车)。通过车辆间共享数据,系统可以学习物体的典型外观和运动模式,从而更好地预测未来行为。

这些例子充分说明了目标检测对于自动驾驶问题的重要性。

问题形式化与挑战 ⚙️

现在,让我们更正式地审视这个问题。目标检测的输入通常是一张RGB图像或激光雷达扫描。我们需要推断的输出是一组带有类别标签和置信度分数的二维或三维边界框。

例如,在图像中,我们可能检测到一个“人”,并用一个边界框标出,同时给出94%的置信度。几乎所有目标检测器都会提供置信度,因为基准测试和下游应用需要根据检测置信度来做决策或评估算法性能。

本质上,我们试图在图像中以边界框的粒度找出“什么物体在哪里”。在三维场景中,则是在激光雷达点云中检测三维边界框。

这个任务面临几个固有挑战:

  1. 边界框数量巨大:即使将坐标离散化为整数像素位置,可能的边界框数量依然极其庞大。
  2. 物体数量未知:我们甚至不知道需要预测多少个物体实体,这增加了问题的难度。

除此之外,识别问题本身还面临诸多挑战:

以下是目标检测面临的主要挑战:

  • 类别繁多:在通用场景中,物体类别可能多达数万种。幸运的是,在自动驾驶场景中,频繁出现的类别较少,主要是行人、骑行者、摩托车手和车辆。
  • 类内差异:同一类别的物体(例如不同的椅子)在像素级别上可能看起来截然不同。
  • 视角变化:同一个物体(例如推土机)从不同角度观看,其图像差异巨大。
  • 光照变化:光源位置改变会导致像素强度发生剧烈变化,尽管场景内容本身未变。
  • 背景干扰:当物体与背景相似或不够突出时,识别会变得困难。
  • 形变:物体(尤其是动物和人)会发生形变,导致外观不同。
  • 遮挡:物体可能被部分或完全遮挡(例如,一排停放的汽车)。
  • 上下文依赖与误导:上下文信息对识别有帮助(例如,在办公桌环境中更容易识别键盘),但过度依赖上下文可能导致误判(例如,将相似的色块在不同背景下识别为不同物体)。我们需要在利用上下文和防止被其误导之间取得平衡。

总结 📝

本节课我们一起学习了目标检测的引言部分。我们明确了目标检测在自动驾驶中的核心作用,即定位并识别二维或三维空间中的物体。我们形式化地定义了该任务的输入(图像/点云)和输出(带标签和置信度的边界框集合),并深入探讨了该任务面临的一系列主要挑战,包括海量可能的检测框、未知的物体数量、类内差异、视角与光照变化、背景干扰、形变、遮挡以及复杂的上下文依赖关系。理解这些挑战是设计和评估有效目标检测算法的第一步。在接下来的单元中,我们将学习如何评估检测器的性能,并探索解决这些挑战的各类算法。

037:目标检测性能评估 🚗

在本节课中,我们将学习如何评估目标检测算法的性能。我们将从最简单的单目标场景开始,逐步深入到更复杂的多目标场景,并介绍业界最常用的评估指标——平均精度。

单目标检测评估 🛑

上一节我们介绍了目标检测的基本概念,本节中我们来看看如何量化一个检测结果的好坏。首先考虑场景中只有一个目标的情况。

例如,图中有一个停车标志。绿色的边界框是真实标注框,这是由人工标注员标注的。红色的边界框是目标检测算法预测的边界框

那么,如何为这个检测结果关联一个“匹配度”分数呢?我们可以考虑使用所谓的交并比,它衡量的是两个边界框重叠区域的面积与它们并集面积的比值。

公式IOU = Area(Intersection) / Area(Union)

从定义可以直接看出,IOU可能获得的最高分是1,这发生在预测框和真实框完全重合的情况下。最低值是0,表示两个框完全不相交。

我们可以为IOU设定一个特定的阈值,并以此判断检测是否成功。例如,在2D目标检测评估中,通常使用IOU阈值 = 0.5。如果检测框与真实框的IOU大于等于0.5,则视为正确检测;反之,则视为不正确。

多目标检测评估 🔢

单目标的评估相对简单,但如何公平地衡量多目标场景下的检测性能呢?这并不容易,因为检测数量取决于检测器的置信度阈值,而这是检测器特定的。

目标检测器会输出一组边界框,每个框都带有语义类别标签和一个置信度分数。根据我们选择的置信度阈值,我们可以控制被算作有效检测的边界框数量。因此,检测数量依赖于这个阈值,我们应该考虑一整个阈值范围,因为没有单一阈值是最优的。

这正是用于评估多目标检测算法结果的平均精度指标所做的事情。

平均精度计算步骤 📊

以下是计算平均精度的主要步骤:

  1. 运行检测器并变化阈值:我们在一个阈值范围内运行检测器,从高阈值(不返回任何检测框)到低阈值(返回大量检测框)。

  2. 将检测框分配给真实框:对于每个阈值下的检测结果,我们将检测框分配给最接近的真实边界框,通常每个真实物体最多只与一个检测框关联。这个过程通常使用二分图匹配技术,如匈牙利算法。

  3. 统计结果数量:我们计算以下数量:

    • 真正例:正确检测到的物体数量(即IOU ≥ 0.5)。
    • 假负例:未被检测到的物体数量(即IOU < 0.5或没有检测框与之匹配)。
    • 假正例:错误的检测数量,即那些未被分配给任何真实物体的剩余检测框(可能是冗余检测或检测到了不存在的物体)。
  4. 计算精确率与召回率:基于上述统计,我们计算两个关键指标:

    • 精确率:衡量检测结果的准确性。
      公式Precision = TP / (TP + FP)
    • 召回率:衡量检测器找出所有真实物体的能力。
      公式Recall = TP / (TP + FN)

高精确率意味着检测算法找到的物体大多是正确的。高召回率意味着大多数真实存在的物体都被找到了,但它不考虑是否有误检。在实践中,我们希望两者都高,但存在权衡:如果检测器返回太多框,召回率会高,但会产生误检,导致精确率低;如果只返回最确信的框,精确率高,但会漏掉一些物体,导致召回率低。

绘制PR曲线与计算AP 📈

精确率和召回率可以针对我们变化的每一个检测阈值进行计算。

当我们变化检测阈值时,可以在“精确率-召回率”空间中得到一系列点,并连成一条曲线(PR曲线)。通常,随着阈值降低,我们会从高精确率、低召回率的点移动到低精确率、高召回率的点。

由于这条曲线通常是锯齿状的,我们会通过取每个召回率水平右侧的最大精确率值来平滑它,得到一条单调递减的曲线。

为了计算一个统一的指标——平均精度,我们简单地计算这条平滑后的PR曲线下的面积平均值。可以将其视为对曲线进行积分并取平均。

核心概念AP = ∫ Precision(Recall) dRecall 的近似计算(通常对0到1之间的11个等间隔召回率点采样求平均)。

这个AP值独立于特定的检测阈值选择,因为它考虑了整个阈值范围。因此,平均精度是当前评估目标检测器性能最常用和最重要的指标。

总结 🎯

本节课中我们一起学习了目标检测的性能评估方法。我们从单目标的交并比评估入手,理解了其原理和阈值判断。随后,我们深入探讨了多目标评估的复杂性,并详细介绍了平均精度的计算流程:通过变化置信度阈值、匹配检测框与真实框、统计真正例/假正例/假负例,计算并绘制精确率-召回率曲线,最终通过计算曲线下面积得到AP值。AP是一个综合性的指标,能够全面、公平地衡量目标检测器在不同操作点上的性能。

038:滑动窗口目标检测

在本节课中,我们将学习目标检测的基本过程。我们将从最简单、最基础的目标检测器形式——经典的滑动窗口目标检测方法开始,为后续学习基于深度学习的方法打下基础。

概述

目标检测的任务是在图像中定位并识别出感兴趣的物体。滑动窗口检测法是一种经典且直观的解决方案。本节我们将详细拆解其工作原理、核心步骤以及早期广泛使用的特征描述子。

滑动窗口检测的工作原理

上一节我们介绍了目标检测的基本概念,本节中我们来看看滑动窗口检测法是如何具体运作的。

滑动窗口目标检测的工作流程如下:

  1. 我们在图像上以固定步长滑动一个固定大小的窗口(图中以绿色框示意)。
  2. 对于每个窗口或图像裁剪区域,我们提取其特征。
  3. 然后,我们使用一个基于这些提取特征的二分类模型(例如,物体 vs. 背景,或行人 vs. 其他任何东西)对每个窗口进行分类。用于此问题的分类模型可以是支持向量机、随机森林、基于提升的技术或深度神经网络。

为了检测不同大小或距离的物体(由于透视相机的影响,近处的行人看起来比远处的大),我们还必须搜索不同宽高比和尺度的检测框。这变成了一个相当详尽的搜索问题。为了在可行的时间内完成此任务,我们必须以一定的步长进行搜索。

至此,我们有效地将目标检测问题转化为了一个分类问题,而我们知道如何使用机器学习分类技术来解决它。

最后一步是应用非极大值抑制或聚类,以为每个物体只保留一个预测。问题是,当我们滑动窗口遍历所有可能的位置时,在红色目标物体附近的一些窗口也会获得较高的分类得分(例如,来自支持向量机的输出),因为它们接近行人,预测“几乎正确”。但我们当然不希望保留所有这些检测结果,我们只想为场景中的每个物体保留最好的一个。这就是非极大值抑制的作用:它是一种聚类启发式方法,会查看边界框的重叠情况,如果重叠度很高,则只保留置信度最高的那个边界框。因此,它最终只保留目标检测算法对每个物体的一个预测。

特征空间的选择

接下来我们必须回答的问题是:应该在哪个特征空间上,让支持向量机对这些小图像块进行分类?

最简单的做法当然是使用RGB像素空间,但正如我们在介绍单元中已经看到的,这既不具备视角不变性,也不具备光照不变性,因此不是一个好的选择。

一个更好的选择是使用方向梯度直方图,简称HOG。在超过十年的目标检测研究中,它一直是事实上的标准,由Dalal和Triggs的论文《Histograms of Oriented Gradients for Human Detection》推广普及。

其核心思想是用代表梯度角度的直方图(以梯度幅值为权重)来描述图像块

让我们用一个来自MNIST数据集的简单数字“8”的例子来说明。

  1. 首先,我们计算这个裁剪图像在x和y方向上的空间导数,然后计算梯度幅值和梯度角度。
  2. 梯度幅值如上图所示。梯度角度则如下图所示,我们将梯度角度量化为八个不同的方向(这是一种相当粗略的方向分箱)。例如,在数字“8”的左侧,有朝左的梯度(红色),右侧则有朝右的梯度(蓝色)。
  3. 下一步,我们将图像细分为多个单元格。单元格是图像中具有一定像素宽度和高度的子区域,例如本例中的8x8或6x6像素。
  4. 之后,对于每个单元格,我们计算一个直方图,累加每个角度方向上的梯度幅值权重。例如,对于某个单元格,我们从朝向橙黄色方向的像素获得贡献,但不会从绿色像素(该均匀区域的梯度幅值为0)获得证据。观察另一个单元格,我们可以看到来自橙黄色像素和蓝色像素的贡献。
  5. 我们对所有定义的单元格重复此过程。

与直接使用RGB像素空间相比,HOG的优势在于:

  • 对微小形变具有鲁棒性:图像可以轻微平移、缩放、旋转或施加一点透视变换,梯度不会发生太大改变,因为它们是整个区域的汇总统计量,且梯度角度已被量化为非常粗略的离散分箱表示。
  • 对亮度变化具有不变性:由于直方图仅基于梯度计算,而不依赖于原始强度信息,因此它独立于绝对亮度。例如,改变相机的增益或快门速度,HOG特征基本保持不变。

正是这两个方面促成了方向梯度直方图的成功:它们捕获了相关的边缘方向信息,同时对平移、缩放、旋转有一定灵活性,并且对亮度变化具有不变性。

基于部件的模型扩展

基于方向梯度直方图思想的一个扩展是Felzenszwalb和Girshick等人于2010年提出的基于部件的模型。其思想是基于物体的部件来建模,然后对部件配置的分布进行建模。这个想法实际上可以追溯到20世纪70年代,并已得到应用。在这里,它与图模型和HOG特征结合使用,用HOG特征描述每个部件。

使用基于部件的模型允许实现更多的 invariance,因为我们可以通过简单地调整不同部件之间的关系,并在图模型分布的配置空间中对这种关系进行建模,从而允许物体发生一些非刚性形变。

然而,这些模型会导致推理速度变慢,因为我们需要在推理时解决图模型中的推断问题。同时人们也发现,与简单地针对我们可能感知到的物体的每个不同视角分别训练一个多视角HOG模型相比,基于部件的模型并没有带来巨大的性能提升。

性能展示

尽管如此,对于像汽车这样相对容易检测的物体,这些基于简单方向梯度直方图特征和非深度学习的图模型推理算法,已经能够实现令人印象深刻的性能。以下是在KITTI数据集上的一些结果。可以看到,检测虽然不够超级精确,但能够检测出相当多的物体。

总结

本节课中,我们一起学习了经典的滑动窗口目标检测方法。我们了解了其将检测转化为分类问题的核心流程,深入探讨了方向梯度直方图这一关键特征描述子的计算方式及其具备平移、亮度不变性的优点,并简要介绍了基于部件的模型扩展及其利弊。这些方法为后续深度学习目标检测算法的发展奠定了重要基础。

039:基于区域的卷积神经网络 (R-CNN) 🚗

在本节课中,我们将要学习基于深度学习的物体检测方法,特别是被称为“两阶段”或“基于区域”的卷积神经网络。这些方法是目前最强大的深度学习技术之一,也是物体检测领域的事实标准。

概述

上一节我们介绍了经典的物体检测方法。本节中,我们将转向基于深度学习的方法,并重点探讨基于区域的卷积神经网络。这些方法通过将检测任务分解为两个阶段,极大地提升了检测的精度和效率。

从经典方法到深度学习

正如我们在上一单元所见,经典方法并未在物体识别领域带来重大突破。它们仅在特定非安全关键任务(如相机人脸检测)中取得了巨大成功,至少在应用层面如此。

为什么经典方法难以突破?第一个也是最困难的问题是,计算机视觉特征非常难以手工设计。我们人类并不知道一个好的特征应该是什么样子,一个好的表示应该如何构成尚不明确。此外,滑动窗口方法在实践中通常很慢,因为它们必须在所有可能的边界框构成的巨大空间中进行搜索。在复杂的基于部件的图模型中进行推理,不仅没有改善情况,反而使这些方法变得更慢。上一单元视频中展示的结果,每帧大约需要一分钟的计算时间,原因是计算通常无法被高效简化,而且有时需要图模型中的复杂推理。

幸运的是,深度学习改变了这一切。现在,识别任务也成为了一个成功的故事。

以下是一张概述进展的幻灯片。我们可以将输入图像的RGB像素直接通过一个分类器。我们有一个可训练的模块,并直接将图像作为表示。但正如我们所见,这效果并不好。一个更好的解决方案是计算梯度,并将这些梯度通过一个分类器。这里我们有一些手工设计的特征(黄色部分)和一个训练好的组件(绿色部分)。更好的方法是获取梯度并形成直方图,然后将这种手工设计的表示通过一个学习到的分类器,或者在这些直方图之上进行一些操作,例如K-means或稀疏编码。一个曾被广泛使用的流行表示叫做“fisher向量”。但所有这些方法都存在一个问题:这些中间表示、中间处理层都是手工设计的,没有考虑最优性。

因此,深度学习的区别在于,我们现在尝试学习所有这些特征。现在所有这些方框(这里用绿色方框表示)都是可训练的。我们学习所有这些低级特征(这是我们深度神经网络的早期层)、中级特征和高级特征(后期层),甚至分类器本身,所有这些都是一个端到端训练的大型神经网络。这确实带来了性能的 dramatic 提升。

在2005年至2010年左右,物体检测技术的性能曾停滞不前。在我们上一单元看到的那个 formidable 基于部件的模型上,特定基准测试的平均精度仅为5。而使用第一个基于深度学习的模型,如使用非常简单的骨干网络(如AlexNet)的Fast R-CNN,我们已经将平均精度提高了三倍。在基于深度神经网络的检测方法发展的两年半内,我们又获得了三倍的提升。在非常短的时间内取得了巨大的进步。

本单元的内容基于Ross Girshick的幻灯片,他是接下来我将描述的基于区域的深度神经网络物体检测系列算法的主要贡献者之一。因此,我想在此感谢Ross的幻灯片。

基于深度神经网络的物体检测原理

那么,我们如何使用深度神经网络检测物体呢?

一个朴素的想法是使用一个分类深度神经网络对图像中所有可能的框进行分类。但正如我们所见,这是不可行的,因为框的数量太多了。即使空间被离散化,我们也无法做到。

一个更好的想法是首先检测一组可能包含物体的候选边界框。并非所有候选框都是正确的,但其中一些是。我们实际上是在量化空间。当然,我们应该选择这组候选边界框(例如2000个)是过完备的,我们应该包含更多的框,但应确保这组框包含所有真实标注框。

这是第一阶段。它是一个两阶段检测器,因为它还有第二阶段:我们获取所有这些候选框(比如2000个),现在使用一个深度神经网络将它们分类为一组标签(不同的物体或背景类别),并同时细化这些框的位置。因为我们在之前已经减少了候选边界框的数量,现在我们需要有机会和能力来细化位置,以使检测器的输出边界框更加精确。这就是两个阶段。因此,这种方法被称为基于提议或两阶段的物体检测器。

请注意,我们现在将原始的物体检测问题拆分成了两个代理任务:检测一组较小的候选边界框的任务(或边界框空间的量化任务),以及分类和细化这组候选边界框的任务。

这里再次进行了说明。通过用有限的一组边界框进行近似,我们可能会得到这里所示的量化误差。我们有一张恐龙的图片,我们有一个量化后的框,这个框还可以,但并不完美。因此,相对于真实框,我们存在这个量化误差。我们现在想在第二阶段做的是,通过回归位置偏移量来细化框的位置,以预测从绿色提议框到最终预测(虚线绿色框)的增量,从而恢复因量化而损失的定位精度。当然,我们也会使用非极大值抑制来移除冗余的预测。就像我们在基于滑动窗口的技术中所做的那样,因为这里可能有多个提议框回归到同一个物体,所以我们希望只保留最自信的那个,每个真实标注只保留一个预测。

R-CNN:首个深度学习方法

现在,让我们深入了解第一个用于物体检测的深度学习方法,它被称为R-CNN,在论文《用于精确物体检测和语义分割的丰富特征层次结构》中描述。

R-CNN代表基于区域的卷积神经网络,因为其思想非常简单:我们计算这些提议区域,然后对每个区域应用一个卷积神经网络分类器。

我们首先使用一个现成的区域检测器/提议算法。在当时,有一些算法可用,如选择性搜索或边缘框。这些是非常简单的通用算法,不考虑物体的类别(无论是马、骑手、自行车手还是任何东西),但它们是为检测通用物体而训练的。它们做得还可以,但通常生成的预测非常不精确。因此,我们需要采样更多的框,我们需要对置信度应用一个较低的阈值,以便获得大量稍后可以分类的框。

我们运行这些经典技术之一来获得一组框。然后,我们将原始图像裁剪并变形为固定大小的表示,并将这个固定大小的表示前向传播通过一个卷积神经网络(一个标准的卷积神经网络)以获得特征表示。然后,我们有两个输出头:一个用于对该区域进行分类(例如,将其分类为“骑马者”),另一个用于回归边界框的偏移量,以细化它们,使其比原始那些相当粗糙、嘈杂且不精确的提议更好地拟合真实标注。

这里你还可以看到,这个黄色区域表示仅需要每图像计算的组件。我们只计算一次,只为该图像计算一次框。但这个绿色区域表示需要每区域计算的组件。每个区域,我们都需要裁剪和变形;每个区域,我们都需要运行一个卷积网络。这里你已经可以看出为什么这很慢了,因为我们需要为选择性搜索算法提出的每个提议(例如2000个)运行一个完整的卷积网络。

通用框架与R-CNN的局限性

我们现在可以将这个表示、这个框架概括为更通用的形式,我们将看到,理解原始R-CNN算法之上的创新是有用的。

我们看看这两个区域:每图像计算和每区域计算。在这个通用框架中,我们首先将输入图像转换为特征化表示。然后,我们有一个从该图像计算物体区域提议的机制。我们称之为R(I)。所以我们有特征F(I),这是特征图。这里我们有从该图像计算的区域R(I)。然后,我们有一个函数,它接收特征和区域,并计算每个提议区域的特征化表示。然后,我们对每个提议特征应用额外的处理,并有多个头来做出特定于任务的预测。

现在,如果我们看R-CNN,这个基于深度学习的两阶段物体检测的第一个最简单版本,在这个框架中,它看起来是这样的。这里的特征映射只是恒等函数,所以它将图像复制为特征表示。对于这个从图像计算区域的函数,我们简单地使用一个现成的经典、传统的非深度学习算法,如选择性搜索。然后,这个组合函数只是一个裁剪和变形操作。接着,这个每区域计算是一个完整的卷积网络。然后我们有两个头:一个用于分类,一个用于边界框细化(回归任务)。

R-CNN有什么问题?第一个问题是我们有较重的每区域计算。我们需要进行2000次完整的网络评估,对于每个提议,我们需要运行一个完整的AlexNet或ResNet架构来进行预测。所以它相当慢。此外,我们没有利用计算或特征共享,因为我们真的是独立进行的,我们独立地将2000个输入通过这个网络进行推理。另一个缺点是,我们有一个缓慢的区域提议方法,增加了运行时间。所以这些确实是经典技术,不使用深度学习,它们在CPU上运行,相当慢。因此,如果我们以帧率、实时物体检测为目标,这并不理想。然后,我们有通用的区域提议技术或这些经典技术,它们的召回率相当有限。尽管选择了低阈值,它们仍然无法预测所有真实标注物体的框。

Fast R-CNN:更快的两阶段检测器

这个两阶段物体检测家族的下一个版本叫做Fast R-CNN。它的不同之处在于,它拥有更轻量级的每区域计算。它实际上是R-CNN的一个端到端可训练版本。

这里进行了说明。在第一步中,我们现在做的不同之处在于,我们不只是将图像复制为特征表示,而是运行全卷积网络骨干来从该图像生成特征。但我们只对每张图像做一次。所以这里我们共享计算。我们将这个输入图像映射到一个较低分辨率的空间特征图。在第二步中,我们应用感兴趣区域池化,它将每个区域转换为一个固定维度的表示。然后,因为我们已经在这个每图像部分做了很多处理,我们只需要一个轻量级的多层感知机来处理每个这些区域特征图。然后我们像以前一样有一个分类头和一个框回归头。

与之前的主要区别在于,现在很多计算已经从绿色的纯区域部分转移到了黄色的每图像部分。这使得处理速度更快。这就是为什么它被称为Fast R-CNN。

让我们更详细地看看这些单独的模块。首先是这个FCN块。这是一个我们用作骨干的标准卷积网络,可以是AlexNet、VGG、ResNet、Inception、DenseNet等。实际上,识别骨干越强,特征就越好,这确实是所有这些论文的结论:无论你在顶部做什么,你的骨干越强,你的物体检测结果就越强。从这些骨干中移除的一个东西是最终的全局池化层,它将空间维度减少到1,因为在原始架构中,我们感兴趣的是每图像分类问题,但现在我们想创建一个具有空间范围的特征图。所以我们创建一个输出,其空间维度与输入空间维度成比例。例如,如果我们有一个大小为宽度×高度的输入图像,那么输出特征图可能有512个通道,并且我们可能有一个宽度为W/16、高度为H/16的特征图。所以我们在每个维度上减少了16倍,但仍然保留了一些空间分辨率。

Fast R-CNN的第二个创新是这个RoI池化操作。现在的想法当然是,基于提议机制检测到的这些区域,从这个特征图中提取特征。这是早期工作SPP-Net的关键创新之一。

想法相当简单。我们有一个来自这个提议检测器的提议区域,我们也有特征图(在背景中用蓝色表示)。当然,这个提议区域可能无法与这个低分辨率特征图的空间网格完美对齐。所以我们做的是,将RoI对齐到最接近的、网格对齐的特征子图。换句话说,我们将任意大小的提议转换为这个固定维度的表示,然后我们在这里应用最大池化。我们计算特征值作为输入单元的最大值,以获得固定大小的表示。在这种情况下,从这个4×3的区域得到一个2×2的特征图。

这就是RoI池化中所做的一切。我们将提议区域对齐到特征图的网格,然后我们池化到一个固定的2×2空间分辨率,然后将其作为输入馈送到这个轻量级MLP。所以现在的优势当然是,我们不再有任何繁重的每区域计算,我们不再需要2000次完整的网络评估,而是将这个负担卸载到了骨干网络,我们只需要每个区域进行这个轻量级MLP评估。所以我们实际上利用了特征共享和计算共享。

但我们仍然有这个缓慢的区域提议方法增加了运行时间,并且我们仍然有一个内置在这个模型中的、召回率低的通用区域提议技术。

Faster R-CNN:引入区域提议网络

这个两阶段检测器家族的下一个变体叫做Faster R-CNN。请注意,这一切都发生在非常短的时间内。你也可以意识到所有这些扩展都相当简单。我记得当Ross在一次会议上做这个演讲时,在会议上,他已经展示了下一个版本、论文的下一个创新,而不是会议上实际发表的内容。是的,所以今天的研究进展很快。

那么Faster R-CNN有什么不同?它的不同之处在于,它不使用这种通用的区域提议机制(经典方法),而是使用学习到的提议。它通过一个与整个图像网络共享计算的网络来计算提议。所以,我们不是使用这个箭头,而是使用从骨干特征的特征图出发的箭头。它直接回归深度提议,并联合端到端地训练整个模型。

这个区域提议网络是什么样的?就是这部分。在Faster R-CNN中的实现方式是一个简单的3×3卷积核,在这个卷积特征图上滑动扫描。这是这里的特征图,这是骨干的输出。它扫描特征图,寻找有趣的通用物体,并定义一个锚框。预测是相对于这个框的,而不是3×3的滑动窗口。选择这个锚框比3×3滑动窗口大的原因是,当然,存储在这个3×3滑动窗口中的特征具有更大的感受野。所以它们看到更多。仅仅看这个小的红色区域,我们仍然有来自这个区域的信息,因为我们有一个卷积骨干,它扩展了感受野,这在卷积网络中很常见。

因此,我们基于这些特征预测一个相对于这个锚框的边界框。对于这个区域提议网络,我们再次有一个物体分类器(不是物体类别分类器,只是一个“物体性”分类器),我们只想分类:是否有东西(无论其类别)?或者它是背景?然后我们有一个框回归器,预测相对于锚框的偏移量。例如,在这种情况下,“物体性”分类器可能会产生高分,因为我们位于这个恐龙的中心。而框回归器预测锚框的偏移量,以更精确地拟合这个物体。这是另一个例子,其中“物体性”分数会较低,因为我们没有位于物体的中心。

在实践中,Faster R-CNN的实现使用多个锚框以适应物体的多种宽高比。这里我们可以看到三个不同的锚框:一个是正方形的,两个是矩形的,作为偏移预测的基础。所以在这个过程中,我们基本上有K个分类问题和K个框回归问题。每个区域有K个“物体性”分类器和K个框回归器。

另一个被证明非常有影响力的创新是特征金字塔网络。Faster R-CNN基本上已经消除了缓慢的区域提议方法增加运行时间以及这些召回率低的通用技术的问题。所以它不受召回率的限制,并且运行时间也 dramatically 增加了。所以我们真的有了一个现在以每秒10帧左右运行的方法。但在这个基础上,一个额外的技巧提高了性能,那就是特征金字塔网络的想法。

这里的想法是,通过使其多尺度化,可以改进这里的整个图像特征表示。这意味着什么?特征金字塔网络的目标是改进尺度等变性。记住,检测器需要在很宽的尺度范围内对物体进行分类和定位。例如,这只猫可能出现在相机附近,也可能出现在很远的地方。所以我们希望无论其大小如何都能检测到这只猫。特征金字塔网络提高了这种能力。

那么,为了检测不同尺度、不同大小的物体,我们能做什么?最简单的想法,我们已经在上一单元讨论过,就是使用图像金字塔来下采样图像到不同分辨率,然后在这些不同分辨率上运行完全相同的物体检测算法。所以我们计算特征,然后进行预测。但这当然很慢,因为对于每个图像金字塔层级、每个分辨率,我们都需要运行整个Faster R-CNN算法。所以这不理想。

第二种策略是简单地使用多尺度特征,就像在Fast或Faster R-CNN中那样,把所有事情都交给特征。现在这当然快得多,因为我们只需要运行一个网络,并在这个骨干的最终层以Ca分辨率获取这些特征,并用它们进行预测。但这并不最优,因为我们无法同等地检测所有尺度的物体。

我们可以使用的第三种策略是网络内部金字塔,我们使用内部金字塔,并在每个单独的特征尺度上应用或进行预测。现在这也很快,但仍然不是最优的。原因在于,第一个金字塔层级,直到那里只发生了相对较少的处理,所以我们只有高分辨率和弱特征,而在较低层级(处理了更多卷积层的地方)只有强特征。所以对于较小的物体,我们只能用很少的层来检测它们,而对于大的物体,我们将用很多层来检测,所以我们可以更好地检测那些。因此,我们在低分辨率有强特征,在高分辨率有弱特征。

现在改进这个的想法是一个简单的单元,基本上,它被称为特征金字塔网络。我们有一个自上而下地丰富高分辨率特征的过程,这仍然很快,但没那么次优。所以这个想法真的只是一个单元,我们有一个编码器和跳跃连接,然后我们有一个解码器。在这种情况下,我们在高分辨率和低分辨率都有强特征,因为在高低分辨率,我们都接收来自网络所有尺度、所有特征尺度的信息。然后我们可以用这些来进行预测。

检测结果与扩展应用

这样的物体检测器的结果是什么样的?这里有一个应用于KITTI序列之一的例子,你可以看到,嗯,它有点闪烁,因为没有时间连续性,但你可以看到,汽车大多数时候被正确检测到,但也有一些其他物体在这种情况下被错误地分类为汽车。

我们在这个视频中已经看到的一个好处是,我们可以很容易地将这个框架推广到其他输出模式。很容易向这个框架添加更多的输出头。例如,2017年的Mask R-CNN,它为每个检测实例预测一个分割掩码。DensePose预测物体坐标,在这种情况下,是人体上的相对坐标。如果你有一个标注了这些的数据集,你也可以预测它。Mesh R-CNN为每个物体预测三角网格。

让我展示给你看。这在当时是一个惊人的结果,DensePose的结果,其中并行、实时地预测这些物体坐标,然后可以转换为人体的姿态估计。这里进行了说明。所以你可以看到许多物体在并行移动,以及这个方法在这里的预测。

我们社区的另一件好事是,几乎所有这些最先进的方法都是免费可用的。你可以下载它们,并且有好的软件框架可用。例如,Facebook Research发布了Detectron和Detectron 2,它们实现了所有这些技术以及不同的输出模式,正如你在这里看到的。所以我鼓励你,如果你好奇的话,可以自己尝试一下。

训练挑战与单阶段检测器

最后,我想强调的一个问题是在训练物体检测算法时出现的前景-背景不平衡。问题是正样本框和负样本框的数量严重不平衡。事实上,图像中通常只有少数物体,但我们可以从背景中采样到更多的负样本框,这些框不包含感兴趣的物体。

因此,在量化之前,当我们考虑连续的边界框坐标时,存在无限的不平衡。但即使在量化之后,在选择了离散框的子集之后,我们仍然只有0.01%到0.1%的前景框。换句话说,我们有99.9%的背景框。从如此不平衡的数据中学习分类器非常困难,因为分类器(如果你曾经训练过这样的分类器,你会意识到)将简单地忽略少数类,因为通过将所有东西预测为背景,它将获得接近100%的准确率。

那么,如何改进这个问题?一个解决方案是使用一个关注困难样本的损失函数,这里一个突出的例子是所谓的焦点损失。它带来了物体检测性能的显著提升,你可以在这里看到蓝色的交叉熵损失曲线,它仍然对分类良好的样本分配了显著的惩罚。然后是这个修改版本,它是这个损失函数的一个非常简单的修改。它进一步压低了这条曲线。例如,对于伽马值等于5,我们有这条绿色曲线,这样分类良好的样本受到的惩罚更少,而更多地关注分类较差的样本。

另一个我们已经广泛看到的解决方案是级联的想法。所以,基于提议的检测器的想法,我们首先选择一组提议,然后在第二阶段,分类器看到更平衡的数据,当然也有帮助。这可以与焦点损失的想法结合起来。最后,我们可以执行更极端的量化形式,这就是单阶段检测器所做的。它们通过构造简单地减少了不平衡。我也想简要强调一下这类检测器,因为它们真的很快。它们比例如Faster R-CNN检测器快得多,而Faster R-CNN已经比2000年代的经典模型快得多了。

单阶段检测器的想法是在一次前向传递中预测物体框。这类单阶段检测器的例子有YOLO和SSD。这里的想法真的是,给定输入图像,在一个非常粗糙的分辨率(在这种情况下只有7×7)预测类别概率,并从这里的每个单元格回归边界框,加上一个置信度得分,直接导致最终的检测。通过这种极端的量化,我们可以在一个阶段完成整个处理,而且速度极快。但一般来说,由于输出空间的 dramatic 子采样,性能较差。并且大的量化误差在实践中难以纠正,这通常导致比我们之前看到的两阶段检测器更低的AP指标。

最新趋势:DETR等替代范式

最后,最近出现了物体检测的替代范式的趋势。一个突出的例子叫做DETR,它使用一个Transformer编码器和一个Transformer解码器。所以这是一种非常不同的使用深度神经网络的方式。它受到语言模型的启发,这些模型现在使用很多Transformer,其中输入图像通过一个骨干网络,然后被标记化。Transformer为这些标记生成一组特征。然后这些特征被输入到一个解码器,然后我们不仅联合学习这些特征,还学习一组物体查询,这些查询随后被解码为单独的预测。

总结

本节课中,我们一起学习了基于区域的卷积神经网络在物体检测中的应用。我们从最初的R-CNN开始,了解了其通过独立处理每个候选区域进行检测的基本思想,但计算成本高昂。接着,我们探讨了Fast R-CNN如何通过引入感兴趣区域池化和共享卷积特征计算,大幅提升了效率。然后,我们学习了Faster R-CNN的核心创新——区域提议网络,它将提议生成也集成到深度学习框架中,实现了端到端的训练和更快的速度。我们还介绍了特征金字塔网络如何通过多尺度特征融合来提升对不同大小物体的检测能力。最后,我们简要讨论了训练中的前景-背景不平衡问题及其解决方案(如焦点损失),并概述了更快的单阶段检测器(如YOLO、SSD)以及最新的基于Transformer的检测范式(如DETR)。这一系列发展展示了深度学习如何推动物体检测技术不断向前,在精度和速度上取得显著突破。

040:3D目标检测 🚗

在本节课中,我们将要学习3D目标检测。我们之前讨论了2D目标检测技术,但现实世界是三维的。因此,对于自动驾驶汽车来说,在三维空间中感知环境并检测物体至关重要。这引出了我们将在本单元讨论的3D目标检测。

概述

3D目标检测的目标是为场景中每一个感兴趣的物体预测一个三维边界框。例如,右侧的橙色3D框是预测结果,而绿色框表示该特定物体的真实标注。

3D目标检测算法的性能评估方式与2D情况类似,通过定义一个3D交并比(IoU)度量,并基于该3D IoU计算平均精度。这里的交集计算不再是针对2D情况下的2D框面积,而是针对这两个立方体的3D体积(图中黄色高亮部分)。

2D与3D检测的参数化对比

首先,我们来看看2D和3D目标检测的不同参数化方式。

在2D情况下,目标是找到一个2D框,可以用图像域中的X、Y位置以及框的宽度和高度来参数化。

在3D情况下,位置是一个三维坐标(X, Y, Z)。3D框有宽度、高度和长度参数。此外,还有三个旋转参数:翻滚角(Roll)、俯仰角(Pitch)和偏航角(Yaw)。因此,在一般的3D目标检测中,我们需要估计九个参数。

然而,在考虑自动驾驶时,一个常见的假设是物体(车辆)在道路平面上行驶。因此,我们可以假设翻滚角和俯仰角为零,从而移除这两个参数,只估计偏航角。这样就将估计问题简化为一个七维的估计问题。

尽管如此,3D检测仍然困难得多,参数更多,问题也更复杂,出错的几率也更高。此外,难度还取决于输入数据。例如,仅从2D图像(即投影到图像域)回归3D框,比从激光雷达(LiDAR)3D点云进行检测要困难得多。

单目图像3D检测的挑战

这一点在此处也有说明。图像中的一个2D框(例如这里的红色框)对应于三维空间中的一个视锥体。物体可以位于该视锥体内的任何位置。一般来说,图像中可见的物体可以位于相机视锥体内的任何地方。这意味着不同尺度和距离的物体可能看起来完全相同。

例如,观察这只兔子。如果一只兔子距离很近,它看起来很小。如果我现在增大兔子的尺寸并将其放在更远的地方,它会投影到完全相同的像素值、完全相同的图像上,因此这里存在尺度模糊性。

幸运的是,在自动驾驶的情况下,我们可以通过机器学习来学习解决这个问题。因为汽车通常有典型的尺寸(例如长度在4到6米之间)。通过了解物理世界中汽车的典型尺寸,我们仍然可以通过观察汽车2D投影的大小来获取关于其距离的线索。

尽管如此,难度仍然取决于输入模态。迄今为止最困难的任务是从单目图像回归3D框,因为这需要非常好的物体尺寸先验知识,尤其是在远距离时,仅从单目RGB图像预测3D框的位置非常困难。

如果我们有两张图像(立体相机),这当然有助于在3D空间中定位框。但根据三维重建课程的内容,误差会随距离呈二次方增长。因此,它仍然不如我们拥有来自雷达或激光雷达扫描仪的3D点云那样精确。

不同传感器模态的优劣

与图像传感器相比,激光雷达传感器虽然稀疏,但在远距离也能提供良好的3D精度,因此定位变得容易得多。然而,由于其稀疏性,它们的分辨率较低,因此检测像行人这样的小物体可能更困难。我们稍后会看到这一点。

这就是为什么一些方法也尝试结合两种模态,因为它们提供了互补的线索和信息。它们试图结合图像和激光雷达数据。

现在,让我们逐一查看这些类别中的例子。我们将从基于图像的3D目标检测类别开始,这是最困难的。

基于图像的3D目标检测方法

为了从单个图像预测度量3D边界框。

我想展示的第一个方法名为《Monocular 3D Object Detection for Autonomous Driving》(CVPR 2016)。这里的想法是在地平面采样候选3D框,并移除所有非道路区域的3D框。

该方法参考输入图像的语义分割结果,并假设相机处于一定高度和倾斜角(可能已预先校准)。因此,我们有一个可以假设的虚拟地平面。然后,我们将这个语义分割投影到该地平面上(如图所示)。我们忽略道路区域,并采样典型尺寸的3D汽车框。因此,我们构建了一个具有典型3D汽车尺寸的3D汽车模型,并在这些灰色区域采样这些汽车。

现在,我们在3D空间中有了位于合理3D位置且具有合理3D尺寸的汽车采样,但这只是大量的3D框提议。为了提取特征,我们将它们投影到图像平面。在这项早期工作中,使用了一种基于特征的评分机制,这些特征包括语义类别信息、语义实例信息、轮廓、形状和上下文。

这些是简单的特征,考虑了形状和上下文信息,以及关于车辆典型位置的非常通用的先验。如果你有一个大数据集,当然可以生成像这里鸟瞰图和图像中车辆通常出现位置的热力图。基于这些特征,他们对这些假设进行重新排序。然后,对于排名靠前的假设,他们使用快速的R-CNN在2D图像域进行最终评分和细化,以保留最有可能的3D提议。

这基本上是一种首先在3D空间采样,并通过该采样过程自动将汽车的位置和尺寸约束在合理范围内,但随后在2D图像空间进行分类和检测的技术。

更先进的单目3D检测技术

一个更近期的技术名为《Geometric-based Distance Decomposition for Monocular 3D Object Detection》(ICCV 2021)。这里的想法是改进单目3D目标检测中最困难的部分——定位。主要问题是回归深度真的非常困难。

因此,他们观察到物体距离、物体的实际3D高度以及2D边界框在图像域中的高度之间存在关系。他们所做的是同时回归物理高度(H)和图像高度(h),以及它们的不确定性。然后以最优方式融合这些信息,以产生更好的深度估计。

他们表明,除了这里经典的基于区域的提议机制(如适应3D空间的Faster R-CNN)外,他们可以通过这种方式显著提升性能。

以下是该技术的一些结果。请记住,所有这些都是仅从单目RGB图像(即左侧看到的图像)计算出来的。我认为这相当令人印象深刻。

从深度图生成伪点云

另一个想法是使用单目图像或立体图像对,首先使用立体匹配算法(如果是单目图像则使用单目深度网络,如MonoDepth)预测深度图。然后将该深度图反投影成3D点云,作者称之为伪激光雷达点云。因为这样你就可以将标准的基于点的激光雷达3D检测算法直接应用于这个伪激光雷达点云。

这篇名为《Pseudo-LiDAR from Visual Depth》的论文声称,这种方法的性能可以与基于激光雷达的检测器竞争。这篇论文在社区引起了很大轰动,因为人们普遍认为从单目图像进行3D检测比基于激光雷达的检测困难得多,因此这对许多人来说确实令人惊讶。

但最近,围绕这个话题有了一些讨论,因为这种方法实际上并没有融入太多先验知识,这里没有魔法发生。那么,为什么通过深度图的方法会比直接从图像回归3D框效果好得多呢?最近发现,其中一些改进实际上是通过评估中的一些技巧获得的,并不对应于实际的性能提升。如果你对这个讨论感兴趣,我很乐意推荐你阅读Simon等人发表在ISV 2021上的这篇论文。

但这是另一个例子,说明如何利用单目或立体图像首先计算3D点云,然后在该3D点云上应用3D目标检测算法。

基于激光雷达的3D目标检测

这直接将我们带到了基于激光雷达的3D目标检测,其输入是这种伪激光雷达点云或来自激光雷达扫描的真实激光雷达点云。

然而,与从图像学习相比,使用点云学习带来了一些独特的挑战,我们知道如何使用2D卷积来处理图像域。

第一个挑战是学习模型必须适应任意大小的点云。如果我下采样点云,如果我移除每隔一个点,我仍然希望得到相似的结果、相似的答案。当然,不同的激光雷达点云具有不同数量的点。首先,我的算法必须能够处理这一点。例如,多层感知机(MLP)就不行,它假设一个固定维度的输入向量。所以这不是一个可行的模型。

第二个挑战是学习模型需要对所有n!种排列保持不变性,如图所示。如果我们有这个点云,它基本上是一个集合。如果我们有这个集合作为输入,那么它代表与这个相同的集合,它不依赖于每个点在我的模型输入空间的输入表示中具有哪个索引。因此,我们构建的模型需要以完全相同的方式处理这两者。

例如,最大池化(max)算子是一个对排列不变的函数,平均或加法算子也是不变的。但当然,仅此还不够,它不是一个神经网络,我们不能仅凭此学习任何参数。

最后,学习模型还应该对点云的旋转保持不变性,因为无论我如何定向它,物体总是相同的,所以我们也应该考虑到这一点。

PointNet:点云深度学习的奠基工作

这正是从一篇名为《PointNet》的论文开始的一切,它尝试将深度神经网络应用于点云,完成三个任务:分类、部件分割和语义分割。在分类中,目标是预测整个点云的类别标签;在语义分割中,我们想预测点云中每个点的语义类别标签。这并不直接是3D检测问题,但它是许多基于激光雷达点云的3D检测模型的基础,这就是为什么首先理解它很重要。

那么,PointNet是如何工作的?这是PointNet的架构。PointNet对每个点应用一个多层感知机(这些是这里的小方框)。它们共享参数,但独立应用于每个点。因此,它们获取单个三维点并将其投影到64维特征空间,并且对每个点独立进行此操作。但该模型的参数是共享的。

在这里,在算法的第二阶段,它们获取该点的65维特征向量,并再次将其转换为1024维特征向量,同样是独立于每个点。之后,PointNet应用一个最大池化操作,这就是排列不变性发挥作用的地方,以获得相同维度(1024)的全局特征向量。然后是一个最终的全局MLP来进行分类,或者获取这些全局特征(这是针对分类任务)。但如果你想进行语义分割,你可以获取这些全局特征,并将它们与一些每点的局部特征连接起来,然后通过更多的PointNet层来预测每个点的输出分数。

此外,这里还有输入变换和特征变换块。在这些块内部,再次使用了被称为T-Net的小型PointNet。这些T-Net就像是这里整个蓝色块的复制品,但更小更浅。它们预测一个变换,在这个例子中是一个3x3变换,在另一个例子中是一个64x64变换,因此它们预测一个仿射变换,该变换再次独立应用于每个点。这有助于学习这些几何不变性,例如旋转不变性。

这是一个有趣的模型,值得稍作思考。为什么它实际上有效?尽管我们在这里独立地对每个点进行一些处理步骤,同时共享网络的特征,将这些点连续投影到更高维的特征空间,然后应用这个最大池化操作来产生全局特征,再通过MLP投影到类别标签,但端到端训练这个模型效果相当好。

PointNet的一个缺点是它不捕获局部结构,并且依赖于全局坐标。这里的每个点都是全局点坐标。

PointNet++:引入层次化结构

来自同一团队的一个后续创新是PointNet++,它递归地应用PointNet,如图所示,对点集进行嵌套分区。例如,这个点有一个由虚线指示的感受野,而这个点有一个由虚线指示的感受野。因此,它连续聚合来自嵌套分区的更强特征,并学习具有不断增加上下文尺度的特征。你可以将其视为一个多尺度的PointNet。与PointNet类似,它有一个用于语义分割的解码器或用于分类的MLP。

现在,这是关于物体或点云分类和语义分割的。我们如何将其用于3D检测呢?

PointRCNN:点云上的Faster R-CNN

我想在这个背景下展示的一个方法叫做PointRCNN(《3D Object Proposal Generation and Detection from Point Cloud》)。我称之为点云上的Faster R-CNN,因为它基本上做的与Faster R-CNN完全相同,但是针对点云。它有一个蓝色的提议阶段,生成一组3D框提议,理想情况下是过完备的。然后它有一个3D框细化阶段,预测3D框偏移量以及置信度,以产生最终的3D检测。

现在让我们分别来看这两个阶段。这是第一阶段,顶部部分。我们这里有什么?首先,这里有一个主干网络,即点云编码器和点云解码器,它使用标准的PointNet++来学习有区分度的逐点特征。所以这只是一个给我们提供每点特征的PointNet++。

然后我们有一个3D框提议回归模块,类似于Faster R-CNN及其两阶段中的第一阶段,但用于点云。还有另一个模块预测前景与背景。他们使用的是回归和分类加回归损失的组合。通过分类加回归,我的意思是,例如,对于鸟瞰图中的空间坐标,他们为每个点定义一个局部坐标系,然后离散化该局部坐标空间。首先对物体的位置进行分类(判断它应该在哪个区间内),然后进行额外的回归(确定在该区间内的确切位置)。这是一个常见的技巧,当直接回归效果不好时(因为我们必须处理多模态分布等),可以使用这个技巧。他们就是这么做的,他们称之为基于区间的损失。

好的,所以他们进行这个3D框提议回归,然后将前100个最自信的提议传递给下一个框细化阶段,如图所示。你可以看到它以点坐标、语义特征、前景掩码和提议的3D感兴趣区域作为输入。

然后,在第一阶段,它基于3D框提议汇集所有3D点特征,简单地聚合任何这些3D提议框(如这里的橙色框)内的所有特征。这产生了一组语义特征和局部空间点。

在第二阶段,这些局部空间点坐标被转换成一个相对于该橙色框的局部3D框相对坐标表示,使它们处于规范坐标系中,然后与语义特征合并,并作为输入馈送到点云编码器,该编码器随后通过预测残差(类似于Faster R-CNN的第二阶段)进行3D框细化,并且再次使用回归和分类加回归损失的组合。这给出了最终的3D框作为输出。

以下是该方法的一些结果,你可以看到它能够很好地检测3D物体。当然,它仅使用点云作为输入。这里是在KITTI数据集上评估的,图像是可用的,因此我们也可以将3D框投影到图像中,但图像并未用作模型的输入。

从这个底部的表格中可以看到一个有趣的观察结果,其中显示了不同IoU阈值下的平均精度数值。这个PointRCNN方法通常优于多模态方法。这里有一些结合RGB和激光雷达的方法,而这种方法比那些先前的方法更好。除了行人,因为行人很小。所以对于行人,有时很难在激光雷达点云中检测到它们,因为落在这些物体上的点太少了。因此,如果你有图像信息,那可能会有所帮助。

但总的来说,激光雷达是迄今为止最重要的输入模态。除了非常小的物体,添加图像信息几乎没有什么增益,至少在你拥有昂贵的HDL-64线激光雷达的情况下。

体素化与鸟瞰图表示

除了我刚才展示的PointNet模型之外,另一种方法是将点编码为体素表示,然后使用3D卷积。这是在论文《VoxelNet: End-to-End Learning for Point Cloud Based 3D Object Detection》中采用的方法,该论文在CVPR 2018上也受到了相当多的关注,因为它是苹果团队为数不多的论文之一。苹果公司通常不以发表大量成果而闻名,但这是他们发表的一篇论文,显然出自他们的自动驾驶项目。

他们所做的基本上是首先将输入空间划分为一组体素,然后将落入这些体素的点转换为这些体素的特征,然后在该体素空间上应用3D卷积。然后他们有一个基本上基于这些特征的单阶段检测器。他们在这里说这是一个区域提议网络,但实际上区域提议网络直接提议3D框输出,所以它不是一个两阶段检测器,而是一个单阶段检测器。当然,这需要大量的内存和计算,因为你必须在一个大的3D体积中工作。

另一个想法是使用2D鸟瞰图表示,这更加内存和计算高效,例如在名为《PIXOR》和《HDNet》的工作中采用。这个想法是表示激光雷达信息,可能还包括可以用作辅助信息以帮助目标检测的道路图,正如HDNet所示。因此,地图可以提供强大的先验,可以提升3D检测性能。

对于激光雷达,实现这一点的方法是将Z维度视为特征通道,将Z坐标离散化为不同的区间,并将这些用作特征通道。因为这样你就可以使用高效的2D卷积,而不是应用3D卷积。是的,例如在HDNet中就是这样做的,利用高清地图进行3D目标检测。但也有研究表明,如果你用地图(例如高清地图)来补充这个激光雷达点云,并且你已在该地图中定位了自己,那么这个地图先验可以帮助你移除3D检测器中不合理的或无效的3D检测,从而获得更好的性能。

多模态融合的3D目标检测

现在,在本单元的最后部分,我想展示一些在多模态融合或多模态3D目标检测领域的工作。

第一个工作名为《Frustum PointNets for 3D Object Detection from RGB-D Data》(CVPR 2018)。这里的想法是首先在RGB图像中生成2D物体提议。

他们所做的是获取激光雷达扫描,将激光雷达点投影到图像域(如顶部所示,颜色编码表示深度)。然后,你可以将这个激光雷达图像投影与RGB图像结合,并使用标准的2D CNN(如Faster R-CNN)来获得2D物体提议。

然后,他们计算对应于提议2D边界框的物体视锥体(如图所示),并考虑位于该视锥体内的所有3D点,从这些点预测一个3D边界框。

因此,它在第一个物体提议检测步骤中进行了一些融合。当然,它也使用RGB颜色为点云着色。但这实际上是一个两阶段机制,第一阶段在图像域生成提议,然后在3D域使用PointNet验证这些提议。

这里有更多细节。3D框预测问题分为三个阶段。在第一阶段(此处红色高亮),该方法将RGB点云分割为物体和背景,基本上试图提取物体并移除杂波(如图所示,这是输入,这是输出)。然后在第二阶段,平移点云,使点云的质心与3D框中心对齐,因为如果你在这个规范空间中学习,那么学习3D检测当然更容易。所以我们尝试端到端地联合学习这种对齐。然后在最后的第三步,进行3D边界框回归,我们回归X, Y, Z, 宽度、高度、长度以及偏航角,以产生最终的3D边界框。

另一个多模态融合的例子是《MV3D: Multi-View 3D Object Detection Network for Autonomous Driving》。同样,这是一个基于流行的两阶段目标检测框架的工作,我们在最后有一个3D提议网络和一个基于区域的融合网络。

在第一步中,该方法从激光雷达鸟瞰图生成3D提议。因此,我们在这个提议生成步骤中生成一组3D提议。然后将它们投影到激光雷达鸟瞰图、激光雷达前视图(这基本上是一个对应于RGB图像的图像,但域对应于RGB图像。我们在这里看到的是投影到该图像域的激光雷达点,这被称为激光雷达前视图)。我们还将这个3D提议投影到RGB图像中。

当然,这三种不同的输入模态中的每一种都有一个卷积网络来提取特征。然后我们可以应用RoI池化(就像在Faster R-CNN中一样)来提取这些投影区域中的特征。然后我们使用这个融合机制融合来自所有模态的RoI池化特征。该机制在分支之间进行拆分、在每个分支上进行一些计算,然后对这些模态进行平均池化之间进行迭代。所以我们有这个特定的融合机制,最后我们有一个输出头,用于重新分类和框残差回归。所以,这又是一个经典的提议加细化的两阶段流程。

这里我们可以看到一些结果,同样从这个表格中我们可以看到,如果我们将单目图像线索添加到激光雷达线索中,我们会有所收获,但并不像我们希望的那么显著。例如,在交并比阈值为0.5(这是一个标准阈值)时,我们在这里可能获得0.8个百分点,在这里获得1.5个百分点。所以我们确实有所收获,但激光雷达是迄今为止3D目标检测最重要的线索,正如这篇论文也发现的那样。

以下是一些结果。不幸的是,质量不是很好。但我想你明白了要点。

总结

本节课到此结束。让我总结一下。

在本节课中,我们看到,对于自动驾驶来说,定位和识别物体至关重要。然而,如果我们考虑连续值,那么可能的框有很多,甚至有无穷多个。而且,物体的数量是未知的,这使得这个问题变得困难。此外,我们还必须处理外观和视角变化、光照变化、杂波、遮挡以及所有其他挑战。

我们还看到,检测性能通常使用我们称之为平均精度的指标来衡量。经典的滑动窗口检测方法使用手工制作的特征,这些特征不是最优的。

我们已经看到,深度学习在短短几年内将识别性能提升了10倍。两阶段检测方法,如Faster R-CNN和Mask R-CNN,或其3D变体,如今占据主导地位。

我们还看到,特征金字塔网络有助于检测各种尺度的特征。

最后,在本单元中,我们讨论了3D检测方法要么依赖于RGB图像,要么依赖于激光雷达点云,或者两者兼用。但激光雷达信息对于精确的3D定位至关重要。

041:目标跟踪 - 引言 🚗

在本节课中,我们将要学习目标跟踪。目标跟踪是自动驾驶系统中的关键环节,它负责将不同时刻检测到的物体关联起来,并估计其状态,从而理解物体的运动轨迹和意图。

在上一单元中,我们学习了多种用于目标检测的算法,包括在二维图像空间和三维空间中的检测。然而,仅仅在每一帧中独立地检测物体,并不足以理解物体正在做什么以及它们将去向何方。因此,我们还需要将这些检测结果在时间上进行关联,这就是目标跟踪的任务:估计物体随时间变化的状态,并将新帧中的新观测结果与已有的物体轨迹关联起来。

本节课的结构分为四个单元。在第一单元中,我们将更精确地介绍跟踪问题,并了解其基本要素。在第二单元中,我们将讨论滤波,这本质上是给定物体随时间变化的多个观测值进行状态估计。我们可以获得比检测器给出的位置更精确的物体状态估计。我们将利用观测模型和运动模型来找到更精确的状态,这被称为滤波。在此背景下,我们将特别讨论所谓的贝叶斯滤波器,这是一个非常通用的框架。在第三单元中,我们将转向关联问题:如何将当前帧中的检测结果与之前帧中已有的物体轨迹关联起来?最后,我们将简要概述将目标跟踪更全面地整合到场景理解过程中的技术,例如利用高清地图来辅助和支持目标检测与跟踪,或者联合估计物体轨迹和场景布局。

现在,让我们从第一单元开始。

什么是跟踪?🎯

跟踪的目标是:给定有噪声的物体检测结果(例如,以2D或3D边界框表示),对于序列的每一帧,我们希望将属于同一物理物体的检测结果关联起来。此外,我们希望剔除那些误报的检测结果。物体检测器会犯错,会产生误报。我们当然不希望将这些误报整合到我们的物体轨迹中。因此,我们需要一种机制来剔除它们。同样,我们需要有启动和删除物体轨迹的可能性。当我们观察图像或视频序列时,可能会有物体因为从其他物体后面或图像边界进入场景而出现,也可能会有物体因为不再可见而消失。因此,我们需要一种机制来启动和删除物体轨迹。正如已经提到的,我们还需要估计物体状态。物体检测只是一个有噪声的观测,而我们感兴趣的是真实的物体状态。那么,我们如何通过考虑观测模型或运动模型,并利用例如贝叶斯滤波器将这种先验知识整合到估计过程中,从而更精确地估计物体状态呢?

下图展示了两个目标跟踪结果的示例视频。左侧是一个带有静态摄像头的行人场景,你可以看到物体周围被平滑跟踪的边界框。你还可以看到,在某些情况下,一个物体出现在观测区域,轨迹启动;然后一些行人移出该区域,物体轨迹被删除。这些视频来自最早和最流行的评估目标跟踪器的基准测试之一,称为PETS。右侧是另一个非常不同的应用示例:在蜂巢中跟踪蜜蜂。

跟踪的要素 🧩

跟踪包含两个或三个要素,这取决于你是否将检测视为跟踪的一部分。在这里,我们将采用“基于检测的跟踪”范式,即检测是跟踪问题的一个组成部分。因此,我们有三个问题:检测、关联和滤波。

检测问题我们已经在上一讲中讨论过。这里要回答的问题是:每一帧中候选物体的位置在哪里?与之前不同的是,我们现在考虑的不是单张图像,而是传感器记录的连续视频或3D点云序列。因此,我们在该序列的每一帧上运行物体检测器。如果是视频,就在视频的每一帧上运行物体检测器。存在不同类型的跟踪算法,例如,有些算法在第一帧中手动选择一个物体周围的框作为任务,然后跟踪器的任务是在视频序列中尽可能长时间地跟踪该物体。这不是我们在这里考虑的范式。我们在这里考虑的是在每一帧运行物体检测器,然后必须估计状态并将这些检测结果在时间上关联起来的设置。这可以说是自动驾驶场景中最主要、最重要的目标跟踪或多目标跟踪范式,被称为“基于检测的跟踪”。

我们必须解决的第二个问题,即跟踪的第二个要素,是关联问题。这里我们要问的问题是:哪个检测结果对应哪个物体?例如,这里我们将一个物体预测到未来一帧,红色表示预测结果,我们有两个观测值。现在我们需要弄清楚这些观测值中哪一个是同一个物体,以便将该检测结果与该物体轨迹关联起来,并继续估计该物体的状态。

最后,我们还有滤波问题。问题是:什么是最可能的物体状态?例如,物体的位置或大小,这取决于状态的定义或用户感兴趣的内容。通常,我们感兴趣的是位置,可能还有边界框的大小。请记住,检测结果是有噪声的,检测器是有噪声的。因此,我们在这里试图通过利用我们对同一物体有多个观测值这一事实来最小化这种噪声。与上一讲只考虑单帧物体检测不同,那时每个物体只有一个观测值;但现在我们处理的是跟踪问题,我们在多帧中观测物体,我们可以利用这一点来改进对物体状态(例如物体位置)的估计。我们通过整合一些先验知识、一些假设、一些归纳偏置来实现这一点,例如利用概率观测模型和运动模型。例如,我们可以假设该物体以恒定速度运动。我们可以使用将要学习的贝叶斯滤波器来整合这一点。

以下是一个示例。X轴是时间,Y轴是物体位置(我们称之为状态),这里是一个一维示例。红色曲线是物体随时间移动的真实状态,但我们不知道这个,这是我们想要估计的。我们唯一有的是这里用这些小轴表示的有噪声测量值。如果我们只是对这些测量值进行插值,我们会得到这条虚线所示的锯齿状有噪声曲线。现在我们可以做的是,整合关于物体运动的假设,例如恒定速度。这样,我们可以过滤掉噪声,在这种情况下得到绿色的状态估计。它并不完美,也不完全是真实状态,但比单独的有噪声测量值要好。这就是滤波背后的核心思想。

在线跟踪与离线跟踪 ⏱️

跟踪有两种不同类型。第一种称为在线跟踪,第二种称为离线跟踪。

它们的区别是什么?在线跟踪中,我们根据当前和过去的观测值来估计当前状态。这里我用绿色表示当前观测值或当前状态,用红色表示过去的状态或观测值。我们基于过去的观测值和当前的观测值来估计当前状态,这就是“在线”的含义,因为我们可以为当前帧执行此操作,我们不需要知道未来就能处理当前帧。相反,离线跟踪器根据所有观测值来估计所有状态,因此我们需要知道整个序列,需要知道所有帧的所有观测值。这也是为什么有些人称之为批处理模式跟踪,我们需要知道整个批次,序列就是批次。当然,使用这种离线跟踪算法,通常实时性要求也低于在线跟踪。在线跟踪中,你希望实时知道结果,因为你想实时做出决策;但在离线跟踪中,你可以离线运行并提供离线结果,因为没有实时性要求。因此,离线跟踪器因为可以“看到”未来,并且没有时间限制,通常可以提供更好的结果。当然,在自动驾驶中,这是不可能的,所以在本节课中,我们将主要关注在线跟踪。

延伸学习资源 📚

如果你对目标跟踪更感兴趣,我想提两个很好的资源,我在制作这些幻灯片时也部分使用了它们,因此也在此致谢。第一个是来自亚琛工业大学的Bastian Leibe教授的课程“计算机视觉2”,你可以在这里找到公开的幻灯片链接。第二个是来自慕尼黑工业大学的Laura Leal-Taixé教授的课程“计算机视觉:检测、分割和跟踪”,她在线提供了幻灯片和视频讲座。如果你对这个主题感兴趣,我强烈推荐你查看这些资源。

本节课中,我们一起学习了目标跟踪的基本概念、核心要素(检测、关联、滤波)以及在线与离线跟踪的区别。我们了解到,跟踪对于理解动态场景至关重要,它通过整合多帧信息来提供更稳定、更准确的物体状态估计,是自动驾驶感知系统的关键组成部分。

042:目标跟踪 - 滤波

在本节课中,我们将要学习目标跟踪中的核心问题——滤波或状态估计。我们将从理解状态与观测的区别开始,逐步推导出递归贝叶斯估计(贝叶斯滤波)的通用框架,并了解其最著名的特例——卡尔曼滤波。我们将学习如何通过预测和校正两个步骤,利用带噪声的观测来估计我们感兴趣的、可能无法直接观测的系统状态。

状态与观测

在开始滤波问题之前,我们首先需要更好地理解状态与观测之间的区别。

隐藏状态是我们感兴趣的参数,例如,物体在2D或3D空间中的位置或速度,或者人体关节的角度等。

观测则相反,它是我们能够直接观察到的东西,也就是测量值。

现在,隐藏状态和观测不一定相同。首先,观测通常是真实状态的一个带噪声版本,因为我们的传感器存在噪声。我们无法精确估计位置,物体检测器的结果是带噪声的,我们必须接受这一点。

此外,并非状态的所有方面都能被直接观测到。状态可能只能被部分观测。例如,我们可能对跟踪球的速度感兴趣,但我们只能观测到球的位置

这就是为什么我们想要随时间跟踪的隐藏状态,在大多数情况下,与观测并不相同。当然,这也是我们需要滤波和状态估计的原因。

单目标跟踪问题建模

现在,让我们假设我们只有一个想要跟踪的单个目标。这也是我们在整个单元中都会做的假设。

感兴趣的运动物体由一个底层状态 X 来表征。这里的 x(粗体)表示一个向量,即状态向量。状态 X 会产生测量值或观测值,我们称之为 Y。因此,对于每个状态,我们都有一个对应的测量向量 y

在每个时间 t,状态从 x_{t-1} 变为 x_t。同时,我们在该时间接收到一个新的观测,称为 y_t。换句话说,我们只是使用时间索引 t 来索引时间维度。

现在,给定一个观测序列 Y(我们在这里用大写字母 Y 来总结),我们的目标是恢复状态序列 X(用大写字母 X 总结)。所以,Y 是所有时间实例(所有帧)的观测集合,而 X 是所有帧的状态集合。

在下方,你可以看到这个过程的图模型,我们将在几页幻灯片后详细讨论。但你已经可以看到,这对应着我们想要解决的问题:我们有一个隐藏的状态序列(用未填充的圆圈表示,这些是我们想要估计且未知的变量)。例如,时间 t 的状态通过某个运动模型依赖于时间 t-1 的状态。而我们观察到的测量值(这个用灰色高亮的节点)则依赖于对应时间实例的状态。因此,时间 t 的测量依赖于时间 t 的状态,时间 t-1 的测量依赖于时间 t-1 的状态,而时间 t 的状态又依赖于时间 t-1 的状态,如此在时间上前后延续。

现在,这反映在我们已经见过的简单例子中。在这种情况下,测量值将对应虚线(我们称之为 Y),而估计状态将对应绿线。

概率论回顾

在跟踪中,我们处理的是不确定性,即状态和检测中的不确定性。因此,我们通常追求的是概率估计,而不是点估计。我们想要随时间跟踪分布,例如,物体位置随时间的分布。

这就是为什么我们现在要做一个简短的概率论回顾,以便快速重温概率知识,并为我们将在本单元中考虑的、严重依赖贝叶斯公式的所谓贝叶斯滤波通用框架做准备。

以下是回顾内容。

在概率论中,我们考虑随机变量。例如,从标签集中取值的离散随机变量。在这种情况下,x 取值为 c 的概率记为 P(x = c)

我们还有连续随机变量。在跟踪中,最常考虑的是连续状态空间(并非总是如此,也存在这些滤波器的离散版本,但在本单元中我们主要考虑连续变量,所以这与我们相关)。x 在其定义域的一个子集 A 中取值的概率记为 P(x ∈ A)

随机变量上的分布我们写作 P(x),两个随机变量的联合分布我们记为 P(x, y),这基本上是 P(x = c, y = d) 等的简写。

概率论有两个基本性质或公理:第一个称为求和规则或边缘化规则,第二个称为乘积规则。

边缘化/求和规则告诉我们,P(x) 等于对 y 的所有状态求和后的联合分布 P(x, y)。或者等价地,对于连续情况,P(x) 等于 P(x, y)y 的积分。

乘积规则简单地告诉我们,联合分布 P(x, y) 等于条件分布 P(x|y) 乘以 P(y)

基于乘积规则 P(x, y) = P(x|y)P(y),我们有以下关系。首先,我们有 P(x, y) = P(x|y)P(y)。当然,我们也可以颠倒这个概率分布中两个随机变量的顺序,这不会改变任何东西。但这意味着我们也可以用 P(y|x)(给定 xy 的条件分布)乘以 P(x) 来表示这个乘积。注意,这里我们有 x|y,而这里有 y|x

如果我们现在求解中间这个表达式,即解出 P(x|y),换句话说,如果我们把 P(y) 放到等式另一边的分母上,我们就得到了著名的贝叶斯规则:后验概率 P(x|y) 等于似然 P(y|x) 乘以先验 P(x),再除以 P(y)

类似地,我们可以考虑三个随机变量的联合分布 P(x, y, c)。我们可以再次交换 xy,得到这个方程。然后我们可以通过将这个项放到分母上来求解 P(x, y|c) 的表达式,得到这个表达式。

现在,如果我们看这个表达式,我们可以看到,这里我们可以通过乘积规则将这两项替换为 P(x|c)P(c),而这里,P(y|c)P(c),我们只是对这两项应用了乘积规则。然后我们看到 P(c) 被约掉了。因此,我们得到:P(y|x, c)P(x|c) / P(y|c)

我们为什么要这样做?因为我们现在看到,贝叶斯规则在以另一个随机变量 c 为条件时也适用。这个公式中唯一的变化是,我们在表达式左右两边的所有项中都添加了一个相同的额外条件。因此,我们在任何变量上条件化,贝叶斯规则仍然适用。

我们这样做当然是有原因的,因为我们需要这个规则来推导贝叶斯滤波器。所以请记住这一点。

贝叶斯滤波器

现在让我们转向贝叶斯滤波器,它也被称为递归贝叶斯估计。

在递归贝叶斯估计中,我们假设只有一个想要跟踪的单个目标。此外,假设每帧恰好有一个带噪声的观测可用,因此我们没有关联问题。我们想要进行概率状态推断,即我们想要估计分布。

递归贝叶斯估计或贝叶斯滤波方法是一种概率方法,用于随时间递归地估计未知的概率密度函数,使用传入的测量值(例如来自物体检测器的检测到的物体位置)和一个系统过程模型(例如恒定速度运动模型)。

它涉及两个交替的步骤。第一步是预测步骤,我们基于先前的状态预测物体在下一帧中应该在哪里。例如,如果先前的状态包括位置和速度,基于此,我们可以预测下一个状态中的位置。第二步是校正步骤,我们基于当前观测来修正预测。预测还不知道任何关于当前观测的信息,因此我们将当前观测整合回预测中。你可以将其视为在运动模型的预测和实际观测之间建立一个加权和。

作为一个小备注,一个好的运动模型不仅对于做出易于校正的良好预测是必要的,而且显然对于关联也很重要。因为如果我们有很多检测,并且我们的预测非常准确,那么就很容易在下一帧中找到与每个预测对应的正确检测。

因此,虽然我们在这里首先推导通用滤波器(或贝叶斯滤波器,卡尔曼滤波器是一个特例),但当然,一旦我们解决了关联问题,我们就可以将这个贝叶斯滤波器应用于所有已关联的物体。这并不意味着这个滤波器只适用于单个物体,但在不考虑关联且只考虑单个物体时,问题更容易分析。

在正式定义贝叶斯滤波器之前,让我们先看看我们在这里所做的假设。思考我们为所考察的某些模型所做的假设总是很重要的。

我们所做的一般假设是:相机不会瞬间跳跃到新的视点,它具有某种平滑性;物体不会在场景中消失并在不同位置重新出现;相机和场景之间的姿态变化是渐进的。这意味着事情是平滑发生的,物体平滑移动。这就是为什么我们可以利用模型,例如运动模型。

我们所采用的运动和观测模型也有某些假设。例如,贝叶斯滤波器假设状态遵循一个马尔可夫过程。我们实际上是在建模一个隐马尔可夫模型卡尔曼滤波器是最简单的连续贝叶斯滤波器之一,具有封闭形式的解,它进一步假设了线性和高斯的运动与观测模型。这看起来相当严格,确实,对于许多应用来说,它太严格了。因此,人们开发了更高级的模型,例如扩展卡尔曼滤波器、无迹卡尔曼滤波器或粒子滤波器,它们的限制更少。

贝叶斯滤波器的形式化定义

现在让我们开始正式定义贝叶斯滤波器。

x_t 表示系统在时间 t 的真实隐藏状态。x_t 是一个维度为 m 的实数向量。

进一步令 y_t 表示在时间 tx_t 的某个带噪声的测量。

贝叶斯滤波器假设状态序列是一个未被观测到的马尔可夫过程,而观测值是对应的测量值。

在这里,你可以再次看到来自前一页幻灯片的所谓图模型,其中状态依赖于前一时刻的状态,而观测依赖于对应时刻的状态。但状态不直接依赖于更早时间步的状态,观测也不依赖于更早时间步的状态或观测。这就是所谓的马尔可夫性质。这就是为什么它被称为隐马尔可夫模型。我们这里有一个隐藏层,即我们想要估计的未知状态,并且我们遵守刚才提到的马尔可夫性质。

这意味着这个模型的概率公式化非常简单。整个序列中所有状态和所有观测的联合分布可以简单地分解为:序列开始时的状态先验分布,乘以从时间 t-1 到时间 t 的运动模型的乘积(乘积遍历所有时间步),再乘以每个时间步的观测模型的乘积。

这是一个有向图模型(贝叶斯网络),这是该贝叶斯网络对应的分解。

现在的目标是执行推断,换句话说,在这个隐马尔可夫模型中从 y 估计 x。我们如何做到这一点?

对于这个递归状态估计问题,我们利用贝叶斯规则。更准确地说,我们利用的正是我们刚刚推导出的条件化形式的规则。

让我们考虑后验概率。后验概率是给定从时间1到时间 t 的所有观测时,状态 x_t 的概率。这就是我们想要估计的,可以说是推断问题的解。因为这个分布告诉我们,给定所有先前观测和当前时间的观测,时间 t 的状态概率是多少。

现在,我们可以使用这个条件化形式的贝叶斯规则来重新表述它,如下所示。在这里,我们以 y_{1:t-1} 为条件。这个符号表示我取所有的 y,即从1到 t-1 的所有观测的集合(类似于MATLAB的记法)。所以这是条件变量,在之前的简单例子中是红色的。

然后我们在这里应用了贝叶斯规则,即 P(y_t|x_t) 乘以 P(x_t) 除以 P(y_t),对吧?所以这只是之前公式的形式。

现在,我们在这里观察到,在分母中,我们有一个常数,因为 x 没有出现,我们没有任何随机变量,这些只是观测值,所以我们可以将这个常数吸收到这里的比例符号中。这意味着后验概率正比于观测分布乘以预测分布。这是第一项,这是第二项。

你看到的是,这一项与这里这一项略有不同。为什么会这样?嗯,那是因为我们利用了我们已经假设的马尔可夫性质。我们知道,变量 y_t 在以 x_t 为条件时,换句话说,这个变量在给定 x_t 的条件下,独立于所有其他先前的变量。这意味着这个分布等于 P(y_t|x_t),而这简单地就是观测模型。然后在这里,我们右边有预测分布,它估计了给定所有先前测量时 x_t 的分布。

右边的这个预测分布可以进一步分解,如下所示。我将其标为红色以便更好地说明。这是我们想要分解的那个。

我们将按如下方式分解它。我们首先将这个预测分布视为边缘分布(看,我们在这里进行边缘化,因为我们有一个随机变量 x_{t-1} 的积分,我们在条件符号之前将其插入到左边)。根据求和规则,这里的这两个表达式是相似或相同的。

所以我们没有改变任何东西。我们只是边缘化了 x_{t-1} 以得到预测分布。

现在我们可以再次应用乘积规则。因此,我们应用乘积规则将这个分布分解为 P(x_t | x_{t-1}, y_{1:t-1}) 乘以 P(x_{t-1} | y_{1:t-1})

现在,我们再次可以利用马尔可夫性质。我们知道 x_t 给定 x_{t-1}y_{1:t-1} 等于 x_t 给定 x_{t-1}。因为如果我知道 x_{t-1},并且我想估计这里的这个预测分布,那么我不需要知道这里的先前变量。在这个有向图中,所以这又是我们利用的马尔可夫性质。

因此,这里的这个表达式简化为这里的这个,正如我们现在看到的,它简单地就是运动模型。它告诉我们给定先前状态时,当前状态是如何分布的。这就是我们所说的运动模型。我们还看到,在右边这里出现了先前的后验分布。这与我们开始时的表达式完全相同,只是索引 t 被替换为索引 t-1。所以它是前一时刻的后验。

现在你可以看到我们如何得到这个两步过程,我们在预测和校正之间交替。我们得到了一个递归状态估计算法。预测步骤是我们刚刚得到的第二个公式,我们推导了预测分布。校正步骤则是这里的第一个方程,我们从观测和预测中得到时间 t 的后验。

因此,我们在每一帧、每一个新观测到来时交替进行这两个步骤。我们首先对状态进行预测,然后整合该观测以获得后验,然后在下一帧重新开始。所以滤波器是在线运行的,我们每帧进行一次更新。

卡尔曼滤波器

现在,贝叶斯滤波器有一些特例,其中最著名的是著名的卡尔曼滤波器

如果运动模型和观测模型都是线性正态分布的,我们就得到卡尔曼滤波器。在这种情况下,我们跟踪的是一个高斯分布,所以我们跟踪的是参数,即均值向量和协方差矩阵。

卡尔曼滤波器的解以封闭形式给出,因为乘积和边缘分布都是高斯的。所以我们假设运动模型和观测模型都是高斯的。并且因为在这些方程中,我们只进行边缘化和计算乘积,所以我们得到的结果也是一个高斯分布。这也意味着最大似然解简单地对应于一个最小二乘拟合。

我在这里省略了公式,因为它们有点技术性,但我们得到了一个封闭形式的解,这是关键信息。所以形式非常简单。但是,当然,它做出了很强的假设,它假设运动模型和观测模型是线性且高斯的。

卡尔曼滤波器在最小二乘意义下是最优滤波器。但也有非线性扩展,如前所述,例如扩展卡尔曼滤波器(EKF)或无迹卡尔曼滤波器(UKF)。而卡尔曼滤波器无法处理的多模态问题(因为我们跟踪的是单峰高斯分布),可以通过诸如粒子滤波器之类的扩展来处理,后者计算状态后验的基于采样的近似。

因此,如果你期望有一个高度多模态的分布需要跟踪,那么卡尔曼滤波器当然不行。你需要像粒子滤波器这样更高级的方法。最近,基于学习的运动模型,例如神经网络,也已被探索,因此你可以联合学习它们。

回到卡尔曼滤波器,跟踪一个高斯分布,状态表示为一个高斯分布。这里有一个简单的例子:我们从这个分布开始。假设这是物体位置 x 的分布。我们做的第一件事是应用一个确定性漂移,这基本上对应于预测。我们还有一个随机扩散,因为预测会变得对状态更加不确定。所以你会看到方差增加了。

但随后我们也整合了新的测量值,正如你所看到的,现在方差再次减小,分布更接近观测值。所以,可以说是对预测和观测的效果进行了平均。

模型示例

运动和观测模型的例子,例如,在恒定速度的情况下:一个简单的设置,其中状态向量是位置和速度。所以我们有 x_t = [位置_t, 速度_t]^T

然后我们可以将运动方程写为:x_t = A * x_{t-1} + ε_m,其中 ε_m ~ N(0, Σ_m)。这实际上意味着 位置_t = 位置_{t-1} + Δt * 速度_{t-1} + 噪声。所以这是确定性部分加上这个随机部分。

类似地,我们有一个观测模型,在右边给出,在这种情况下,我们简单地从状态向量中选取位置分量,这就是我们的 y_t,同样被一些高斯噪声破坏。

类似地,我们可以定义一个具有恒定加速度的1D示例,其中现在状态向量包括位置、速度和加速度。状态转移通过这个3x3的状态转移矩阵发生。同样,我们对于运动的状态转移和这里的观测都有高斯噪声。

所以这是两个可以通过卡尔曼滤波器最优求解的情况,因为我们有一个线性模型用于运动模型和观测模型,并且两者都是高斯的。

然而,在现实世界中,有许多情况不适用,这些情况是非线性的,需要非线性模型。例如,这里你可以看到一个具有非线性动力学的例子:行人不是线性行走,而是上下弹跳,还有这个弹跳的球。如果你使用,例如,一个恒定加速度模型,那么在这个点,我们会预测下一帧中球的位置在这里。但实际上,它弹了回来。所以预测会离真实位置太远,无法在校正步骤中产生有意义的校正,并且会严重违反线性模型。

结果与应用

现在让我们看一些结果。在这里,我们可以看到跟踪一只狗的结果。在背景中,白色方块对应检测结果,你可以看到它在跳动,因为它是有噪声的。平滑的版本是红色框,这是这里卡尔曼滤波器的输出。所以这再次说明,滤波器正在滤除噪声,这也是其名称的由来。

这里是另一个例子,其中跟踪器跟随这里的观测(观测为红色),而跟踪结果(估计值)为白色。你可以看到它是如何能够平滑掉一些噪声的,但跟踪中也引入了一些滞后或延迟。

卡尔曼滤波器已在许多应用中使用,其中最著名的之一是登月任务。这里有一个有趣的引述我想展示给你。在这篇出版物中,工程师们寻求卡尔曼滤波器的指导。卡尔曼滤波器被用于20世纪60年代的Ranger、Mariner和Apollo任务中,特别是引导阿波罗11号登月舱降落到月球的机载计算机就有一个卡尔曼滤波器。

根据航空航天工程师William Lear的说法,在阿波罗11号预定发射前大约九个月,NASA联系了他,因为他们基于地球的跟踪程序无法工作。Lear编写了一个21状态的卡尔曼滤波器程序,该程序被用于多普勒雷达系统。Lear回忆说,该程序的最终检查是在阿姆斯特朗、奥尔德林和柯林斯起飞前一天完成的。所以我想,不只是我们在截止日期前工作。

我希望阿姆斯特朗、奥尔德林和柯林斯不知道这件事。

总结与延伸阅读

好了,让我们以一些进一步阅读的指引来结束本单元。如果你对卡尔曼滤波器的技术细节更感兴趣,维基百科当然是一个很好的资源。但也有这本由Forsyth和Ponce所著的《Computer Vision: A Modern Approach》一书,其第17章对跟踪和卡尔曼滤波器有很好的介绍。

在本节课中,我们一起学习了目标跟踪中的滤波问题。我们从区分状态与观测开始,理解了为何需要概率估计。随后,我们深入探讨了递归贝叶斯估计(贝叶斯滤波)的通用框架,它通过交替进行预测和校正两个步骤,在线地估计状态的后验分布。作为该框架在线性高斯假设下的特例,我们介绍了著名的卡尔曼滤波器,它提供了一种高效且最优(在最小二乘意义下)的跟踪方法。我们还了解了其局限性以及更高级的非线性扩展(如EKF、UKF和粒子滤波器)。最后,我们通过实例看到了滤波器的实际效果,并了解了其重要的历史应用。

043:目标跟踪 - 关联问题

在本节课中,我们将要学习多目标跟踪中的核心挑战:关联问题。我们将探讨如何将新帧中的检测结果与先前帧中已有的目标轨迹正确匹配,并介绍解决此问题的多种方法。


关联问题概述

到目前为止,我们考虑的是单个目标以及每帧只有一个检测的情况。我们无需进行关联,因为我们假设该检测就是对应那个目标的。但在自动驾驶中,我们通常需要同时跟踪多个目标,并且每一帧都有许多检测结果。因此,问题就出现了:我们如何将新帧中的这些检测结果与先前帧中已有的目标轨迹关联起来?

多目标跟踪算法通常可以概括为以下步骤:

  1. 使用运动模型,将先前帧中的目标预测到当前帧。
  2. 同时,在当前图像中检测目标。
  3. 将检测结果与目标轨迹进行关联,并在必要时初始化和删除轨迹。
  4. 使用观测结果(例如,通过卡尔曼滤波器)来修正预测。

上一节我们介绍了跟踪的基本流程,本节中我们来看看其中的关键步骤——关联。


关联度量方法

对于第二步,即关联步骤,我们需要一个度量标准来判断两个连续帧中的观测结果是否属于同一个目标。以下是几种可能的度量方法:

  • 边界框重叠度:通过运动模型预测边界框,并测量其与检测框的重叠程度。
  • 颜色直方图比较:比较图像块的颜色直方图。
  • 归一化互相关:在图像块之间执行归一化互相关计算。
  • 光流一致性:估计光流并测量其一致性。
  • 边界框相对位置和大小:比较边界框的相对位置和大小,假设目标在帧间不会剧烈收缩或增长。
  • 目标朝向比较:例如,要求像 Fast R-CNN 这样的目标检测器也输出被检测车辆的朝向。

以上是一些非常简单的关联度量方法。然而,我们可以做得更好。


使用深度学习进行关联

我们可以使用深度学习,特别是度量学习来改进关联。其核心思想是使用卷积网络来学习图像块 I 的目标表示 f_θ(I)。这里,f_θ 是具有参数 θ 的神经网络,它以图像块作为输入,并为该图像块计算一个特征向量。

一个好的表示会将同一目标的图像映射到相似的特征,而将不同目标的图像映射到不同的特征。例如,我们有一个显示目标的图像块,称之为锚点 A。我们有一个正样本 P(来自不同帧的同一目标)和一个负样本 N(不同目标)。我们希望学习一个排序,使得同一目标(AP)的特征向量之间的距离,小于不同目标(AN)的特征向量之间的距离。

我们可以使用所谓的三元组损失来实现这一点。其公式如下:

L = max(0, d(A, P) - d(A, N) + m)

其中 d(·, ·) 表示距离(如欧氏距离),m 是一个确保损失专注于困难样本的边界项。这个损失函数有效地尝试让正样本比负样本更接近锚点至少一个边界 m 的距离。

训练这种三元组损失时,可以使用诸如难负样本挖掘等技术,即不是随机采样图像块,而是采样那些可能难以区分但仍不同的样本(例如,相似但不同的白色汽车)。最近,Laura Leal-Taixé 团队发表的论文《The Group Loss for Deep Metric Learning》也解决了三元组损失的高效学习问题。


关联中的歧义与挑战

即使找到了好的关联度量或学习了好的特征表示,仍然存在歧义和困难。以下是可能遇到的一些情况:

  • 预测无测量支持:预测存在,但没有对应的观测。问题是目标消失了、被遮挡了,还是检测失败了?
  • 出现意外测量:预测存在,但没有一个检测结果与之接近。这些是新出现的可见目标还是误检?我们应该初始化新的目标轨迹吗?
  • 多个测量匹配一个预测:一个预测轨迹,有多个检测结果都与之接近。哪个测量是正确的?其他的又该如何处理?
  • 一个测量匹配多个预测:一个检测结果同时与多个预测轨迹都匹配良好。这个测量应该分配给哪个目标?

最近邻关联及其局限性

解决这个问题最简单的方法是最近邻关联。在最近邻关联中,我们首先将测量限制在预测周围的某个“门控区域”内。我们认为距离很远的检测不太可能对应于该轨迹。然后,我们从检测集合 Y_t 中关联一个与预测 x_t 最接近的检测。

数学上可以表述为寻找使 ||y_t - x_t||_2 最小的 y_t。如果我们有一个像卡尔曼滤波器中的高斯预测模型,我们可以考虑在该预测模型下最可能的检测,即最大化似然的那个。这对应于马氏距离,它考虑了预测的不确定性(协方差矩阵),可以用于定义门控区域。

然而,简单的最近邻方法存在严重问题。考虑一个两个目标(蓝色和红色)移动的例子。在某些情况下,仅根据位置相似性选择最近邻会导致错误的关联,甚至可能将一个检测同时分配给两个轨迹。在实践中,情况可能更加严重和困难。这表明简单的最近邻方法通常不是一个好主意。


二分图匹配

为了超越最近邻方法,我们可以使用二分图匹配。我们有效地利用图论工具来帮助我们。

给定一个二分图(节点分为两个集合,边只连接不同集合的节点),一个匹配是边的一个子集,使得每个顶点恰好属于其中一条边。帧到帧的跟踪可以表述为二分图匹配问题。它通过定义,在相似度矩阵的每一行和每一列中至多选择一个匹配,同时最大化总得分。

例如,我们有三个目标轨迹(行)和下一帧的三个检测(列),以及它们的相似度得分。我们希望将每个轨迹只关联到一个检测,反之亦然。解决方案是选择一组匹配(每行每列一个),使得这些匹配对应的相似度得分之和最大。

现在的问题是,如何解决这个二分图匹配问题?


解决二分图匹配问题

首先正式定义问题:给定一个 M x N 的关联得分矩阵 S,确定一个二元的 M x N 矩阵 C,以最大化总得分 ∑∑ S_{ij} * C_{ij}。约束条件是:在二元矩阵 C 的每一行和每一列中,恰好有一个元素为 1,其余为 0,且 C_{ij} ∈ {0, 1}。这是一个整数线性规划问题,但幸运的是,在这个特定情况下,存在多项式时间算法。

可能的分配数量是 N!,对于大量检测,穷举搜索变得不可行。

最简单的算法是贪心算法

  1. 从一个未标记的矩阵开始。
  2. 对于 i = 1n,标记不在已有标记行或列中的最大值。
  3. 关联该匹配,并划掉对应的行和列。

贪心匹配易于实现、运行快速,并能找到较好的解,但它通常不能产生最优解。

为了找到最优解,可以使用图论中的算法,例如具有二次复杂度的匈牙利算法,或者后来提出的具有立方时间复杂度的算法。这些算法可以快速交付解决方案,因此被频繁用于帧到帧的跟踪二分图匹配。


处理轨迹起始与终止

在实际中,轨迹和观测的数量通常不同,轨迹可能结束,也可能有新的轨迹开始。我们可以使用一个简单的技巧:引入额外的“吸收节点”来吸收这些匹配,并设置一个阈值。这样,如果一个轨迹与吸收节点关联,就意味着该轨迹终止;如果一个检测与吸收节点关联,就意味着可能开始一个新的轨迹。我们可以通过扩展矩阵,使用相同的算法(如匈牙利算法)来解决这个问题。


多帧关联与网络流方法

以上都是关于帧到帧匹配的。二分图匹配只能将当前帧的检测与上一帧的目标轨迹(或检测)进行匹配,但这对于更长的序列不一定是最优的。错误的关联在后续帧中无法撤销。

因此,我们需要考虑多帧情况。目标是在序列的所有帧中解决所有关联问题。一个开创性的想法是将问题转化为最小代价流网络问题

其思想是:每个检测在图(网络)中创建两个节点,并用一条边连接它们,该边携带与检测置信度成比例的负成本。然后,将这些检测与下一帧的检测连接起来(链接边携带正成本,以分离不同的目标)。此外,将检测的第一个节点连接到图的源点 S,第二个节点连接到汇点 T

目标是尝试从源点 S 到汇点 T 推送“流”,使得沿边的总成本最小。由于观测携带负成本,流被鼓励通过高置信度的观测。链接边携带正成本以分离不相似的目标。通过这种表述,我们可以处理多帧序列,并自动确定轨迹何时开始和结束。

该问题的最优解可以通过称为“连续最短路径算法”的多项式时间算法找到。然而,这种方法只能建模相邻时间步之间的成对关系,无法直接建模跨越多个帧的遮挡,并且只能使用非常简单的运动模型。


先进的基于图的模型

更先进的模型尝试联合训练检测和跟踪。例如,有工作通过线性程序(解决最小代价流问题)进行反向传播,将整个流程视为神经网络中的一层,从而实现端到端的训练。

另一个更近期的、取得了先进成果的想法更简单:既然我们有一个基于图的问题,而图神经网络近年来取得了巨大进展,那么自然可以尝试直接用图神经网络来解决这个问题。这种方法将输入用卷积神经网络编码为特征,然后在该图上进行神经消息传递,并将问题表述为一个简单的边分类问题(属于同一轨迹的边被分类为正)。这种方法非常直接,易于用现代框架实现和端到端训练。


多目标跟踪的评估

最后,我们来讨论如何评估多目标跟踪。评估的第一步是使用类似于评估目标检测器时所用的二分图匹配技术,将预测轨迹与真实轨迹关联起来。

最突出和最古老的跟踪评估指标是多目标跟踪准确度。其计算公式为:

MOTA = 1 - (∑_t (FN_t + FP_t + IDSW_t)) / ∑_t GT_t

其中,FN_t 是漏检数,FP_t 是误检数,IDSW_t 是ID切换次数(即一个真实轨迹被不同跟踪ID关联的次数),GT_t 是真实目标数。这是一个简单的度量,但也有许多缺陷。

一个更近期的、避免了一些问题的度量称为 HOTA,它也被集成在先进的评估框架中。

先进的算法在基准测试上进行评估,例如自动驾驶领域的 KITTI 基准测试就包含目标跟踪任务,参与者可以在排行榜上提交结果并查看排名。


总结

在本节课中,我们一起学习了多目标跟踪中的关联问题。我们从简单的关联度量(如边界框重叠)和最近邻方法开始,认识到其局限性。然后,我们引入了更强大的二分图匹配方法,将其形式化为一个优化问题,并介绍了贪心算法和匈牙利算法等解决方案。为了处理轨迹的起始与终止,我们探讨了引入吸收节点的技巧。接着,我们超越了帧到帧匹配,介绍了基于最小代价流网络的多帧全局关联方法及其变体。最后,我们简要了解了使用深度学习(如三元组损失和图神经网络)进行端到端关联的先进方法,并讨论了多目标跟踪的评估指标(如 MOTA 和 HOTA)和基准测试。掌握这些关联技术对于构建鲁棒的多目标跟踪系统至关重要。

044:整体场景理解与追踪 🚗

在本节课中,我们将学习如何将物体追踪技术融入到自动驾驶感知系统的更广泛任务中,即整体场景理解。我们将探讨融合多种信息源(如传感器数据、地图和场景线索)如何能带来更鲁棒和准确的场景理解。


在上一节中,我们讨论了物体追踪的基础技术。本节中,我们来看看如何将追踪置于更宏观的“整体场景理解”框架下。

为了理解交通场景,仅仅检测车道线是不够的。在高速公路等简单场景中,车道保持或许只需车道检测。然而,面对复杂的十字路口,仅从车道检测器的视角出发几乎无法理解全局。

因此,需要融合各种线索来获得完整、整体的理解,例如车辆的位置与动向、车道与道路、建筑物、天空、消失点等。只有综合考虑所有这些因素,才能获得对场景的整体理解。融合多种线索能带来更鲁棒的估计。

多线索融合示例

首先,我们通过一个简单的双传感器融合例子来理解基本原理。假设我们通过两个传感器(例如相机和激光雷达)获得对同一物体的检测。

X 为未知的物体真实位置。
C1C2 分别为相机和激光雷达的带噪声测量值。

根据贝叶斯定律,在给定两个测量值的条件下,物体位置的后验概率分布可计算为:

P(X | C1, C2) ∝ P(C1 | X) * P(C2 | X) * P(X)

如果我们假设两个测量值相互独立(这通常是一种简化),并且假设先验分布 P(X) 是均匀的(即无信息先验),那么公式可简化为:

P(X | C1, C2) ∝ P(C1 | X) * P(C2 | X)

这是一种融合来自不同传感器或同一传感器不同检测器信息的简单方法,也是我们尝试融合场景各方面信息的基础。

整体场景理解项目

接下来,我们介绍一个旨在实现整体场景理解的研究项目:“基于移动平台的3D交通场景理解”。

该项目的目标是从短时立体视频序列(不使用地图或激光雷达)中推断出:

  • 场景的拓扑结构与几何形状。
  • 语义信息,如当前的交通状况、交通模式。
  • 交通灯状态(通过观察物体的运动间接推断)。
  • 并生成一个融合了多种线索的城市场景概率生成模型。

这种方法的优势在于可以利用大量先验知识。例如,我们知道十字路口通常具有特定的几何形状,因此物体更可能遵循某些轨迹。我们还可以利用交通规则(如靠右行驶)等信息。

该项目通过一个复杂的概率图模型来实现上述目标。该贝叶斯网络融合了场景光流、占据栅格、语义标签、消失点等观测数据,并将追踪片段(Tracklets)作为一个隐马尔可夫模型嵌入其中,试图在联合推断出的场景情境下预测每个车辆的个体状态。

以下是该模型的一个输出结果示例:

上图展示了输入的单目图像序列(顶部)以及模型推断出的交通状况(底部)。可以看到模型如何评估物体沿特定方向移动的可能性,并将其与整体交通状况联系起来。这是一个具有挑战性的问题,因为仅从单目图像测量距离非常困难,但通过将车辆运动置于特定的交通情境中,可以有效地缩小不确定性。这体现了整体建模的优势。

利用高精地图辅助追踪

另一种将额外信息整合到追踪问题中的方法是使用高精地图。例如,CVPR 2020的论文《Perception and Prediction with Tracking in the Loop》就采用了这种方法。

其核心思想是结合高精地图和激光雷达数据,来支持物体检测器和追踪器,并执行联合的感知、追踪和运动预测(即轨迹估计)。一旦追踪到物体并建立了良好的运动模型,预测物体未来的运动就会变得容易得多,这对于后续的行为建模和规划阶段至关重要。

Argoverse数据集

最后,我们介绍Argoverse数据集,这是一个用于3D追踪和运动预测的最新数据集,其特点是包含了丰富的高精地图信息。

该数据集为自动驾驶研究公开提供了包含激光雷达点云、RGB图像以及精确定位信息的序列数据。如今,它常被用于评估追踪和运动预测技术的性能。

相关链接:Argoverse官方网站(包含排行榜等更多信息)。


总结 📝

本节课中,我们一起学习了如何将物体追踪融入整体场景理解。

我们回顾并总结了以下核心要点:

  • 物体追踪需要检测、关联和滤波三个步骤。
  • 精确的观测模型运动模型知识可以改进追踪效果。
  • 离线追踪需要未来观测值,而自动驾驶的关注点自然是在线追踪
  • 滤波是根据观测序列估计状态的任务,贝叶斯滤波包含预测更新两个步骤。
  • 卡尔曼滤波是贝叶斯滤波在高斯线性假设下的一个特例,具有闭式解。
  • 帧间关联可以通过二分图匹配解决。
  • 多帧追踪可以表述为最小代价流问题。
  • 多目标追踪精度(MOTA)常被用来评估性能。
  • 物体轨迹和场景布局进行联合估计,有助于提高系统的鲁棒性和性能。

045:决策与规划 - 引言 🚗

在本节课中,我们将要学习自动驾驶流程中的最后一个关键环节:决策与规划。这是整个课程的最后一次讲座,我们将探讨如何让车辆从当前位置安全、高效地抵达目的地。

概述

决策与规划阶段的目标是,在考虑静态基础设施和周围动态物体的前提下,找到并跟随一条从车辆当前位置到目的地的路径。其输入是感知系统提供的车辆与环境状态,输出则是传递给车辆控制器的参考轨迹。

然而,驾驶场景和行为非常复杂,难以将其建模为单一的优化问题。因此,我们通常将这个复杂任务分解为一系列更简单的子问题。

课程结构

本次讲座分为四个单元:

  1. 首先,我们将介绍决策与规划阶段及其在自动驾驶流程中的位置。
  2. 接着,我们将探讨三个规划问题中的第一个:路径规划。这是最高层级的规划问题,类似于GPS导航系统在城市中寻找从A点到B点的路线。
  3. 然后,在第三单元,我们将学习行为规划。我们将了解如何将自动驾驶车辆可能遇到的不同情况,分解为典型的基于图结构的表示。
  4. 最后,我们将研究运动规划。其目标是规划出实际的车辆轨迹,以供控制器执行。

上一节我们介绍了课程的整体结构,本节中我们来看看决策与规划在自动驾驶流程中的具体位置。

决策与规划在流程中的位置

下图是我们之前见过的简化版自动驾驶流程示意图,它抽象地展示了不同模块:低级感知、语义理解、路径规划和车辆控制。

在第5和第6讲中,我们讨论了车辆控制部分。在第5到11讲中,我们讨论了低级感知和语义理解部分。现在,我们将要讨论从感知到控制的连接环节,即这里的决策与路径规划阶段。

问题定义与分解动机

决策与规划阶段的目标是找到并跟随一条从车辆当前位置到目的地的路径,同时考虑静态基础设施和周围的动态物体。输入是感知系统提供的车辆与环境状态,输出是传递给车辆控制器的参考轨迹。

然而,驾驶场景和行为可能非常复杂,因此很难将整个决策与规划问题建模为单一的优化问题。我们通常的做法是将这个复杂任务分解为一系列更简单的子问题。

以下是几个需要将问题分解的驾驶场景示例:

  • 速度跟踪:车辆试图以设定的目标速度(例如30英里/小时)在车道内行驶。
  • 减速停车:车辆需要减速,以便在到达交叉路口时停下。
  • 等待红灯:交通灯为红色时,车辆需要保持停止状态,并观察交通灯以确定何时可以再次启动。
  • 启动通行:交通灯变绿后,车辆开始行驶。
  • 让行观察:在没有交通灯但有让行标志的交叉口,车辆需要观察周围的车辆和其他交通参与者,并为来车让行。
  • 紧急制动:车辆前方出现障碍物或发生紧急情况时,车辆需要尽快完全停止。

这仅仅是车辆可能遇到的众多情况中的一小部分。因此,我们的思路不是将整个决策与规划模块建模为一个单一问题,而是将其分解为如下图所示的层级结构,其中每个问题都针对其范围和抽象层级进行了定制。

在这个层级结构中,左侧意味着更高的抽象层级。例如,在路径规划阶段,我们希望找到从车辆当前位置到目的地的大致路线。而在较低层级,例如运动规划阶段,我们试图以更精细的分辨率规划车辆的轨迹或路径,以执行特定的机动动作。这个参考轨迹随后被输入到本地反馈控制器中。我们将要阐述的每一个优化问题,都有其独特的约束和目标函数。

规划层级详解

让我们更详细地看看这个层级结构。我们从最抽象、最高层级的左侧开始。

  1. 路径规划:首先,用户指定的目的地被传递给路径规划器。给定一个高清道路地图,它会生成一条穿过道路网络的路线,类似于您车辆中的GPS导航系统,但精度更高,因为它拥有高清地图,所以也知道车道级别的信息。路径规划器会生成一些车辆应遵循的路径点。
  2. 行为层:这些路径点被传递给行为层。行为层根据环境进行推理,并生成一个运动指令。为了做到这一点,它需要观察环境,访问感知系统的信息,例如场景中的车辆、障碍物或标志信息。行为层通常使用有限状态机来实现。
  3. 运动规划:运动指令进入运动规划器,运动规划器求解出一个可行的运动,以完成来自行为层的运动指令。
  4. 本地反馈控制:最终产生的参考轨迹被输入到本地反馈控制器中。控制器调整执行变量(如转向、油门和刹车),以纠正执行参考路径时的误差。它获取车辆状态的估计值以执行本地反馈控制。

各阶段核心概念

现在,让我们更深入地了解这些模块中的每一个。

  • 路径规划:在此阶段,道路网络通常被表示为一个有向图。该图包含节点和带有方向箭头的有向边,边指示车辆允许行驶的路径。这通常是一个加权有向图,其中边的权重对应于路段长度或行驶时间,可以被路径搜索算法考虑在内。这个问题被转化为一个最小成本图网络问题,可以使用图论中的标准搜索算法来解决,例如 DijkstraA* 算法

  • 行为层:行为层根据当前的车辆或环境状态选择驾驶行为。例如,在停车线处停车,观察其他交通参与者,然后通过交叉路口。行为层通常使用有限状态机建模,其状态转换由感知信息驱动。它也可以使用概率模型建模,例如我们早期课程中见过的马尔可夫决策过程

  • 运动规划:运动规划阶段接收运动指令并产生一条参考轨迹。其目标是基于运动指令,找到一条可行、舒适、安全且快速的车辆路径或轨迹。精确解的计算在大多数情况下是计算上难以处理的,因此通常使用数值近似方法。我们将简要讨论的典型方法包括变分法图搜索法增量树搜索法

  • 本地反馈控制:本地反馈控制器接收来自运动规划阶段的路径或轨迹并执行它,同时纠正由于车辆模型不准确而产生的误差,正如我们在车辆控制讲座中看到的那样。控制阶段的重点当然是鲁棒性、稳定性和舒适性。如今,我们的大多数车辆已经配备了复杂的低级控制器。

因此,今天讲座的内容是前三个模块,因为最后一个模块我们已经在第5和第6讲中讨论过了。

算法概览

需要说明的是,自动驾驶文献中使用了许多规划算法。如下图所示,数量众多。当然,我们今天只会有时间关注其中最经典的几种。

那么,接下来我们将要做什么呢?

总结

本节课中,我们一起学习了自动驾驶决策与规划模块的引言部分。我们了解了该模块在整体流程中的位置,明确了其目标是生成安全可行的行驶轨迹。由于问题的复杂性,我们将其分解为路径规划行为规划运动规划三个层级,并简要介绍了每个层级的核心任务和常用方法(如图搜索、有限状态机等)。这为我们后续深入探讨每个具体的规划问题打下了基础。

自动驾驶汽车课程:12.3:行为规划 🚗

在本节课中,我们将要学习自动驾驶决策与规划中的行为规划阶段。我们将了解行为规划的作用、常用模型,并重点探讨确定性有限状态机的工作原理及其在自动驾驶中的应用。


给定一条规划好的路线后,车辆需要跟随该路线行驶。这个过程进一步分为两个子任务:行为规划和运动规划。

本节我们将深入探讨行为规划阶段。为了跟随规划路线,车辆必须执行各种驾驶操作,正如我们在课程开始时所见。

以下是几种常见的驾驶操作示例:

  • 速度跟踪
  • 跟车行驶
  • 停车
  • 并道

为所有操作联合设计一个运动或路径规划器是困难的。因此,行为规划阶段将行为离散化为更简单的原子操作,每个操作都可以由专用的运动规划器单独处理。

行为层必须考虑交通规则、静态和动态障碍物。行为规划器的输入包括我们之前见过的高级路线规划(例如,使用A*算法规划的结果)以及感知系统的输出。行为规划阶段的输出则是运动规划器的约束条件,例如行驶走廊、车辆附近的物体、速度限制、目标位置等。

行为规划常用的模型,在离散或确定性情况下是有限状态机及其变体;在概率性情况下是马尔可夫决策过程或部分可观测马尔可夫决策过程。在本节中,我们将重点讨论确定性的有限状态机。

一个有限状态机在数学上由一个五元组定义,如下所示:
FSM = (Σ, S, s0, F, δ)
其中:

  • Σ 是输入字母表(例如,本例中的 {α, β, γ})。
  • S 是非空的状态集合(例如,本例中的 {s0, s1})。
  • s0 ∈ S 是初始状态。
  • F ⊆ S 是可能为空的最终状态集合。
  • δ: S × Σ → S 是状态转移函数,它根据当前状态和输入字符映射到下一个状态。

例如,如果处于状态 s0 并接收到输入 γ,则保持在状态 s0;如果处于状态 s0 并接收到输入 α,则转移到状态 s1

这是一个简单的非自动驾驶例子:想象一个孩子的状态。大多数时候他们处于“开心”状态。随着时间的推移(尤其是在晚上),他们可能变得疲倦并转入“不开心”状态。那么如何从“不开心”状态回到“开心”状态呢?通常,“糖果”这个输入可以触发状态转移。

现在,让我们看一个自动驾驶的例子。这是一个简单的车辆行为有限状态机,包含三个状态:

  1. 绿色 - 跟踪速度状态:车辆正常行驶。
  2. 黄色 - 减速至停止状态:车辆正在减速。
  3. 红色 - 停止状态:车辆已停止。

我们从“跟踪速度”状态开始。只要车辆位置未接近交叉路口或停止线,就保持此状态。一旦感知系统检测到正在接近停止线,就转移到“减速至停止”状态。只要速度不为零,就保持减速状态。当速度降至零且已达到目标位置(停止线)时,则转移到“停止”状态。在此状态下,车辆必须至少停止三秒钟。如果停止时间少于三秒,则保持停止状态。只有当停止时间达到或超过三秒且确认可以安全通行时,才转移回“跟踪速度”状态。

当然,这是一个非常简化的示例。在实践中,有限状态机要复杂得多。例如,在一个四向交叉路口场景中,状态可能包括“接近停车标志”、“在停车标志处等待”和“通过交叉路口”。

这是一个来自斯坦福大学Junior车队在DARPA挑战赛中使用的真实高级有限状态机示例。可以看到,它有“定位车辆”、“行驶”、“通过交叉路口”、“停车”、“在停车场导航”等状态,以及它们之间的转移关系。

现在的问题是,如何将这些简单的有限状态机扩展到更复杂的操作,特别是如何处理多种不同场景(例如交叉路口场景和高速公路驾驶场景),因为其中的状态和转移可能差异很大。如果扩展单个有限状态机,会导致规则数量爆炸式增长。

更好的方法是使用所谓的分层(或分级)有限状态机,如下图所示。我们拥有元状态(例如“交叉路口场景”状态和“车道行驶场景”状态),可以在这些元状态之间转移。同时,在每个元状态内部,又包含一系列子状态(图中的黄、红、绿状态),可以在这些子状态内部进行转移。

这种方法的优点是结构更简单、更高效,也更容易理解。但缺点是一些规则可能会重复,因为在交叉路口和直道上都可能需要减速和停车等操作。

这是一个来自卡内基梅隆大学Boss车队在DARPA挑战赛中使用的分层有限状态机实例。图中顶层的“行驶”状态本身又包含“车道行驶”、“变道”、“转弯”等子状态。


总结

本节课中我们一起学习了行为规划的核心概念。有限状态机是将复杂驾驶行为分解为简单原子操作的一种优雅方法。它们具有可解释性,易于设计。然而,在处理复杂场景时,需要避免规则爆炸,否则会降低可解释性,增加理解难度和代码出错的风险。此外,有限状态机无法处理噪声或不确定性,若要处理这些问题,则需要转向如马尔可夫决策过程之类的概率模型。最后,许多已部署的有限状态机(例如在DARPA城市挑战赛中)大量依赖专家设计的超参数,而更理想的方式是通过强化学习等方法来自动学习这些参数。

048:运动规划 🚗

在本节课中,我们将学习自动驾驶规划层级中最精细的阶段——运动规划。运动规划接收行为层的指令,并生成可供控制器执行的局部路径。

概述

上一节我们介绍了行为规划,本节我们将深入探讨运动规划。运动规划的目标是基于行为层的输出,从车辆的当前构型到局部目标点,计算出一条安全、舒适且可行的轨迹。我们通常只进行非常局部的规划,例如规划车辆前方几米处的车道中心点、下一个停车线或停车位。

运动规划器以车辆周围的静态和动态障碍物作为输入,并尝试生成无碰撞的轨迹。

输出表示

运动规划器有两种基本的输出表示形式。

第一种输出表示称为路径,我们用 σ(L) 表示。它将一个从0到1的标量(即归一化的路径长度L)映射到构型空间 X。换句话说,路径表示不指定速度,只指定车辆应遵循的路径。

第二种输出表示称为轨迹,我们用 π(t) 表示。它将从0到规划时域 T 的时间t映射到构型空间 X。与路径不同,轨迹输出表示明确考虑了时间,它要求控制器在任意指定时间t,使车辆接近该函数预测的对应构型。而对于路径,控制器自身必须提供逻辑来确定正确的速度。

其中,T 称为规划时域,X 是车辆的构型空间,在简单情况下包括车辆的位置和航向角。

规划方法

解决运动规划问题主要有三种主流方法:变分法、图搜索法和增量搜索法。我们将逐一简要了解。

变分法

变分法,正如你在数学中所知,旨在最小化一个泛函。这里我们试图最小化依赖于轨迹π的泛函 J,其最小值在所有可能的轨迹π中寻找,因此被称为泛函(即函数的函数)。

我们最小化从0到时域T的积分:min J(π) = ∫₀ᵀ F(π(t)) dt。其中,F 整合了软约束(如关于空间位置的约束)以及额外的硬约束(如车辆的最小转弯半径、起始位置和终点位置)。起始位置是车辆在时间0的构型,目标位置是车辆在时间T的构型。

这个问题通常使用标准的数值优化技术求解。但在几乎所有情况下,这都是一个困难、非线性且非凸的优化问题,因此会收敛到局部最小值。为了避免这种情况,有时会从不同的初始值开始求解,并使用其他技术来克服此问题。

下图展示了一个没有任何额外约束的简单变分函数优化问题。你可以看到被优化的函数、不同的迭代过程,以及通过泛函F整合的软约束(如空间位置约束)。随着时间的推移,函数朝着这个“山谷”的最小值移动,从起始位置到达目标位置,最终的迭代结果是图中的红色轨迹。

这是一个车辆规划的具体示例视频截图,展示了此类算法能够规划出非常精确和敏捷的轨迹。

图搜索法

变分法的一种替代方案是使用我们之前讨论过的图搜索方法,例如Dijkstra或A*算法。但为了使用它们,我们首先必须将构型空间 X 离散化为一个由顶点和边组成的图。文献中有多种构建此类图的算法。

以下是一个简单的示例。左图是一个停车操作的示例,构型空间基于网格结构进行了离散化。右图是高速公路上的不同车道,车道变换操作基于构型空间的离散化进行建模。每一条灰色和黑色的轨迹都是车辆可以采取的轨迹。通过这种离散化,我们现在可以将其表述为一个图搜索问题。

这是另一个十字路口的示例,展示了不同车道和通过十字路口的可能性如何被离散化。例如,这辆车可以直行或右转,如果右转,它还可以选择进入这条车道或那条车道。

增量搜索法

最后,还有增量搜索技术。其思想是增量式地构建越来越精细的构型空间 X 离散化。只要有足够的计算时间,这些方法能保证找到可行路径,但计算时间可能无界。此类算法的一个突出例子是快速探索随机树算法。

如下图所示,开始时,它随机探索空间并找到一条通往目标的粗略路径。然后,它对空间进行更密集的采样,以细化并优化该路径。

这是使用A算法进行规划场景的另一个示例。这实际上是Stanley车辆的一个例子,他们使用了所谓的混合A算法,这是A*的一个变体,能保证路径的运动学可行性。规划会随着车辆探索环境而持续重新进行。

实际应用结果显示,车辆从这里开始,面对真实的障碍物(这些是停放车辆的激光扫描数据),目标位置在那边。虽然曲线不是非常平滑,但通过这个对A*算法微小但重要的修改,它仍然能够找到一条连续且可行驶的曲线到达停车位置。

A算法还有其他一些修改,这里无法详述。下图展示了一个机器人在模拟中尝试导航停车场的典型过程。你可以看到搜索中扩展的树。每次遇到阻碍,它都会进行一次新的A搜索。可以看到地图随着机器人移动而被获取。在机器人的状态等价表示中,它不仅考虑了X、Y和航向,还允许机器人前进和后退,而倒车是与前进不同的状态。现在你可以看到它如何倒车、找到新路径,并最终通过一个实际开口到达目标位置。

这个迷宫被设计得很困难以测试算法。好处是这些算法几乎实时运行,构建整个搜索树只需不到十分之一秒。机器人能够非常高效地导航这个停车场。这实际上是我在DARPA城市挑战赛中见过的最快的运动规划算法之一,甚至是我一生中在机器人领域见过的最快算法之一。

同样的算法被应用到一个实际的停车示例中,使用我们的机器人Junior。它希望从这里到达那里。你可以看到它精确地倒车进入这里的停车位,然后沿着这里的线向前移动。我们的状态空间是四维的,包括X、Y、航向方向以及车辆是前进还是倒退。改变方向有成本,因此它不会太频繁地改变方向。你可以看到它导航到一个安全位置。需要指出的是,规划器生成的轨迹随后会使用二次平滑器进行平滑,以消除扭结,从而使车辆行驶得更平稳。但完成所有工作、找到最佳路径的核心算法是经过修改的混合A*算法。

在最后一段视频中,我们看到车辆在左侧有很多交通锥的停车场中导航。右侧可以看到内部地图和路径规划器。它试图将自己停在左侧的指定位置。

总结

本节课我们一起学习了运动规划。我们看到驾驶场景和行为可能非常复杂,因此将问题分解为更简单问题的层次结构(如路线规划、行为规划和运动规划)是一个好主意。每个问题都针对其范围和抽象级别进行了定制。

道路网络可以表示为加权有向图,并且我们已经看到Dijkstra算法可以在这样的图中找到最短路径。然而,A*算法效率更高,它利用规划启发式来提高效率。我们还看到行为规划可以使用有限状态机实现,而对于运动规划,变分法和图搜索法经常被使用。

各种规划算法已被用于自动驾驶演示中。目前对于哪种算法效果最佳尚无共识,这真的取决于具体问题。因此,每个问题可能需要不同的算法,关于什么是自动驾驶的最佳算法,仍有待研究。

你已经完成了整个自动驾驶课程的学习。感谢你一直以来的参与,希望你和我一样享受这个过程,并从这门课中学到了一些东西,也希望你在实现我们的小型自动驾驶智能体时获得了一些乐趣。最后,祝你考试顺利,希望在未来讲座或研讨会中再次见到你。

posted @ 2026-03-26 13:18  布客飞龙V  阅读(0)  评论(0)    收藏  举报